Răsfoiți Sursa

Merge branch 'master' into feat/web-bi-client

charlie 2 ani în urmă
părinte
comite
b07992aaae

+ 121 - 16
libs/yarn.lock

@@ -17,6 +17,14 @@
   dependencies:
     "@babel/highlight" "^7.18.6"
 
+"@babel/code-frame@^7.22.13":
+  version "7.22.13"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+  integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
+  dependencies:
+    "@babel/highlight" "^7.22.13"
+    chalk "^2.4.2"
+
 "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1":
   version "7.20.1"
   resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
@@ -43,7 +51,7 @@
     json5 "^2.2.1"
     semver "^6.3.0"
 
-"@babel/generator@^7.20.1", "@babel/generator@^7.20.2":
+"@babel/generator@^7.20.2":
   version "7.20.4"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8"
   integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==
@@ -52,6 +60,16 @@
     "@jridgewell/gen-mapping" "^0.3.2"
     jsesc "^2.5.1"
 
+"@babel/generator@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+  integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+  dependencies:
+    "@babel/types" "^7.23.0"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
 "@babel/helper-annotate-as-pure@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
@@ -115,6 +133,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
   integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
 
+"@babel/helper-environment-visitor@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+  integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
 "@babel/helper-explode-assignable-expression@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
@@ -130,6 +153,14 @@
     "@babel/template" "^7.18.10"
     "@babel/types" "^7.19.0"
 
+"@babel/helper-function-name@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+  integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
+  dependencies:
+    "@babel/template" "^7.22.15"
+    "@babel/types" "^7.23.0"
+
 "@babel/helper-hoist-variables@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
@@ -137,6 +168,13 @@
   dependencies:
     "@babel/types" "^7.18.6"
 
+"@babel/helper-hoist-variables@^7.22.5":
+  version "7.22.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
+  integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-member-expression-to-functions@^7.18.9":
   version "7.18.9"
   resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
@@ -219,16 +257,33 @@
   dependencies:
     "@babel/types" "^7.18.6"
 
+"@babel/helper-split-export-declaration@^7.22.6":
+  version "7.22.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
+  integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-string-parser@^7.19.4":
   version "7.19.4"
   resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
   integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
 
+"@babel/helper-string-parser@^7.22.5":
+  version "7.22.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
+  integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+
 "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
   version "7.19.1"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
   integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
 
+"@babel/helper-validator-identifier@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+  integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
 "@babel/helper-validator-option@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
@@ -262,11 +317,25 @@
     chalk "^2.0.0"
     js-tokens "^4.0.0"
 
-"@babel/parser@^7.18.10", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2":
+"@babel/highlight@^7.22.13":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
+  integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.22.20"
+    chalk "^2.4.2"
+    js-tokens "^4.0.0"
+
+"@babel/parser@^7.18.10", "@babel/parser@^7.20.2":
   version "7.20.3"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2"
   integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==
 
+"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+  integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
 "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
@@ -875,19 +944,28 @@
     "@babel/parser" "^7.18.10"
     "@babel/types" "^7.18.10"
 
-"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1":
-  version "7.20.1"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8"
-  integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==
+"@babel/template@^7.22.15":
+  version "7.22.15"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+  integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
   dependencies:
-    "@babel/code-frame" "^7.18.6"
-    "@babel/generator" "^7.20.1"
-    "@babel/helper-environment-visitor" "^7.18.9"
-    "@babel/helper-function-name" "^7.19.0"
-    "@babel/helper-hoist-variables" "^7.18.6"
-    "@babel/helper-split-export-declaration" "^7.18.6"
-    "@babel/parser" "^7.20.1"
-    "@babel/types" "^7.20.0"
+    "@babel/code-frame" "^7.22.13"
+    "@babel/parser" "^7.22.15"
+    "@babel/types" "^7.22.15"
+
+"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1":
+  version "7.23.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+  integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
+  dependencies:
+    "@babel/code-frame" "^7.22.13"
+    "@babel/generator" "^7.23.0"
+    "@babel/helper-environment-visitor" "^7.22.20"
+    "@babel/helper-function-name" "^7.23.0"
+    "@babel/helper-hoist-variables" "^7.22.5"
+    "@babel/helper-split-export-declaration" "^7.22.6"
+    "@babel/parser" "^7.23.0"
+    "@babel/types" "^7.23.0"
     debug "^4.1.0"
     globals "^11.1.0"
 
@@ -900,6 +978,15 @@
     "@babel/helper-validator-identifier" "^7.19.1"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+  integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+  dependencies:
+    "@babel/helper-string-parser" "^7.22.5"
+    "@babel/helper-validator-identifier" "^7.22.20"
+    to-fast-properties "^2.0.0"
+
 "@discoveryjs/json-ext@^0.5.0":
   version "0.5.3"
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d"
@@ -927,6 +1014,11 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
   integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
 
+"@jridgewell/resolve-uri@^3.1.0":
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+  integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
 "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
@@ -945,6 +1037,11 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
   integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
 
+"@jridgewell/sourcemap-codec@^1.4.14":
+  version "1.4.15"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
 "@jridgewell/trace-mapping@^0.3.14":
   version "0.3.17"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
@@ -953,6 +1050,14 @@
     "@jridgewell/resolve-uri" "3.1.0"
     "@jridgewell/sourcemap-codec" "1.4.14"
 
+"@jridgewell/trace-mapping@^0.3.17":
+  version "0.3.20"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
+  integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
+  dependencies:
+    "@jridgewell/resolve-uri" "^3.1.0"
+    "@jridgewell/sourcemap-codec" "^1.4.14"
+
 "@jridgewell/trace-mapping@^0.3.9":
   version "0.3.14"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
@@ -1365,7 +1470,7 @@ caniuse-lite@^1.0.30001400:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795"
   integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==
 
-chalk@^2.0.0:
+chalk@^2.0.0, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -1483,7 +1588,7 @@ [email protected], debug@^4.1.0, debug@^4.1.1:
   dependencies:
     ms "2.1.2"
 
-deepmerge@^4.3.1:
[email protected]:
   version "4.3.1"
   resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
   integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==

+ 1 - 1
package.json

@@ -110,7 +110,7 @@
         "d3-force": "3.0.0",
         "diff": "5.0.0",
         "dompurify": "2.4.0",
-        "electron": "24.6.3",
+        "electron": "26.4.2",
         "electron-dl": "3.3.0",
         "fs": "0.0.1-security",
         "fs-extra": "9.1.0",

+ 1 - 0
resources/js/glide/glide.core.min.css

@@ -0,0 +1 @@
+.glide{position:relative;width:100%;box-sizing:border-box}.glide *{box-sizing:inherit}.glide__track{overflow:hidden}.glide__slides{position:relative;width:100%;list-style:none;backface-visibility:hidden;transform-style:preserve-3d;touch-action:pan-Y;overflow:hidden;margin:0;padding:0;white-space:nowrap;display:flex;flex-wrap:nowrap;will-change:transform}.glide__slides--dragging{user-select:none}.glide__slide{width:100%;height:100%;flex-shrink:0;white-space:normal;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}.glide__slide a{user-select:none;-webkit-user-drag:none;-moz-user-select:none;-ms-user-select:none}.glide__arrows{-webkit-touch-callout:none;user-select:none}.glide__bullets{-webkit-touch-callout:none;user-select:none}.glide--rtl{direction:rtl}

Fișier diff suprimat deoarece este prea mare
+ 5 - 0
resources/js/glide/glide.min.js


+ 1 - 0
resources/js/glide/glide.theme.min.css

@@ -0,0 +1 @@
+.glide__arrow{position:absolute;display:block;top:50%;z-index:2;color:#fff;text-transform:uppercase;padding:9px 12px;background-color:transparent;border:2px solid rgba(255,255,255,.5);border-radius:4px;box-shadow:0 .25em .5em 0 rgba(0,0,0,.1);text-shadow:0 .25em .5em rgba(0,0,0,.1);opacity:1;cursor:pointer;transition:opacity 150ms ease,border 300ms ease-in-out;transform:translateY(-50%);line-height:1}.glide__arrow:focus{outline:none}.glide__arrow:hover{border-color:#fff}.glide__arrow--left{left:2em}.glide__arrow--right{right:2em}.glide__arrow--disabled{opacity:.33}.glide__bullets{position:absolute;z-index:2;bottom:2em;left:50%;display:inline-flex;list-style:none;transform:translateX(-50%)}.glide__bullet{background-color:rgba(255,255,255,.5);width:9px;height:9px;padding:0;border-radius:50%;border:2px solid transparent;transition:all 300ms ease-in-out;cursor:pointer;line-height:0;box-shadow:0 .25em .5em 0 rgba(0,0,0,.1);margin:0 .25em}.glide__bullet:focus{outline:none}.glide__bullet:hover,.glide__bullet:focus{border:2px solid #fff;background-color:rgba(255,255,255,.5)}.glide__bullet--active{background-color:#fff}.glide--swipeable{cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}.glide--dragging{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}

+ 4 - 3
resources/package.json

@@ -13,7 +13,7 @@
     "electron:make": "electron-forge make",
     "electron:make-macos-arm64": "electron-forge make --platform=darwin --arch=arm64",
     "electron:publish:github": "electron-forge publish",
-    "rebuild:all": "electron-rebuild -v 24.6.3 -f",
+    "rebuild:all": "electron-rebuild -v 26.4.2 -f",
     "postinstall": "install-app-deps"
   },
   "config": {
@@ -53,12 +53,13 @@
     "@electron-forge/maker-squirrel": "^6.0.4",
     "@electron-forge/maker-zip": "^6.0.4",
     "@electron/rebuild": "3.2.10",
-    "electron": "24.6.3",
+    "electron": "26.4.2",
     "electron-builder": "^22.11.7",
     "electron-forge-maker-appimage": "https://github.com/logseq/electron-forge-maker-appimage.git"
   },
   "resolutions": {
-    "**/electron": "24.6.3",
+    "**/electron": "26.4.2",
+    "**/node-abi": "3.51.0",
     "**/node-gyp": "9.0.0"
   }
 }

+ 9 - 3
src/electron/electron/url.cljs

@@ -104,7 +104,13 @@
       (= "new-window" url-host)
       (local-url-handler win parsed-url true)
 
+      (= "handbook" url-host)
+      (send-to-renderer :handbook
+                        {:key  (some-> (.-pathname parsed-url) (string/replace-first #"^[\/]+" ""))
+                         :args (some-> (.-searchParams parsed-url) (js/Object.fromEntries))})
+
       :else
-      (send-to-renderer "notification" {:type "error"
-                                        :payload (str "Failed to open link. Cannot match `" url-host
-                                                      "` to any target.")}))))
+      (send-to-renderer :notification
+                        {:type    "error"
+                         :payload (str "Failed to open link. Cannot match `" url-host
+                                       "` to any target.")}))))

+ 7 - 1
src/main/electron/listener.cljs

@@ -195,7 +195,13 @@
 
   (safe-api-call "syncAPIServerState"
                  (fn [^js data]
-                   (state/set-state! :electron/server (bean/->clj data)))))
+                   (state/set-state! :electron/server (bean/->clj data))))
+
+
+  (safe-api-call "handbook"
+                 (fn [^js data]
+                   (when-let [k (and data (.-key data))]
+                     (state/open-handbook-pane! k)))))
 
 (defn listen!
   []

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

@@ -1338,7 +1338,7 @@
                   url)]
         (if (and (coll? src)
                  (= (first src) "youtube-player"))
-          (youtube/youtube-video (last src))
+          (youtube/youtube-video (last src) nil)
           (when src
             (let [width (min (- (util/get-width) 96) 560)
                   height (int (* width (/ (if (string/includes? src "player.bilibili.com")
@@ -1475,7 +1475,7 @@
                                 :else
                                 (nth (util/safe-re-find text-util/youtube-regex url) 5))]
           (when-not (string/blank? youtube-id)
-            (youtube/youtube-video youtube-id))))
+            (youtube/youtube-video youtube-id nil))))
 
       (= name "youtube-timestamp")
       (when-let [timestamp (first arguments)]

+ 68 - 10
src/main/frontend/components/container.cljs

@@ -1,6 +1,7 @@
 (ns frontend.components.container
   (:require [cljs-drag-n-drop.core :as dnd]
             [clojure.string :as string]
+            [frontend.version :refer [version]]
             [frontend.components.find-in-page :as find-in-page]
             [frontend.components.header :as header]
             [frontend.components.journal :as journal]
@@ -11,6 +12,7 @@
             [frontend.components.select :as select]
             [frontend.components.theme :as theme]
             [frontend.components.widgets :as widgets]
+            [frontend.components.handbooks :as handbooks]
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
             [frontend.db :as db]
@@ -35,6 +37,7 @@
             [frontend.util :as util]
             [frontend.util.cursor :as cursor]
             [frontend.components.window-controls :as window-controls]
+            [medley.core :as medley]
             [goog.dom :as gdom]
             [goog.object :as gobj]
             [logseq.common.path :as path]
@@ -696,15 +699,71 @@
                {:on-click state/toggle-document-mode!}
                "D"])))
 
+(def help-menu-items
+  [{:title "Handbook" :icon "book-2" :on-click #(handbooks/toggle-handbooks)}
+   {:title "Keyboard shortcuts" :icon "command" :on-click #(state/sidebar-add-block! (state/get-current-repo) "shortcut-settings" :shortcut-settings)}
+   {:title "Documentation" :icon "help" :href "https://docs.logseq.com/"}
+   :hr
+   {:title "Report bug" :icon "bug" :on-click #(rfe/push-state :bug-report)}
+   {:title "Request feature" :icon "git-pull-request" :href "https://discuss.logseq.com/c/feature-requests/"}
+   {:title "Submit feedback" :icon "messages" :href "https://discuss.logseq.com/c/feedback/13"}
+   :hr
+   {:title "Ask the community" :icon "brand-discord" :href "https://discord.com/invite/KpN4eHY"}
+   {:title "Support forum" :icon "message" :href "https://discuss.logseq.com/"}
+   :hr
+   {:title "Release notes" :icon "asterisk" :href "https://docs.logseq.com/#/page/changelog"}])
+
+(rum/defc help-menu-popup
+  []
+
+  (rum/use-effect!
+    (fn []
+      (state/set-state! :ui/handbooks-open? false))
+    [])
+
+  (rum/use-effect!
+    (fn []
+      (let [h #(state/set-state! :ui/help-open? false)]
+        (.addEventListener js/document.body "click" h)
+        #(.removeEventListener js/document.body "click" h)))
+    [])
+
+  [:div.cp__sidebar-help-menu-popup
+   [:div.list-wrap
+    (for [[idx {:keys [title icon href on-click] :as item}] (medley/indexed help-menu-items)]
+      (case item
+        :hr
+        [:hr.my-2 {:key idx}]
+
+        ;; default
+        [:a.it.flex.items-center.px-4.py-1.select-none
+         {:key      title
+          :on-click (fn []
+                      (cond
+                        (fn? on-click) (on-click)
+                        (string? href) (util/open-url href))
+                      (state/set-state! :ui/help-open? false))}
+         [:span.flex.items-center.pr-2.opacity-40 (ui/icon icon {:size 20})]
+         [:strong.font-normal title]]))]
+   [:div.ft.pl-11.pb-3
+    [:span.opacity.text-xs.opacity-30 "Logseq " version]]])
+
 (rum/defc help-button < rum/reactive
   []
-  (when-not (state/sub :ui/sidebar-open?)
-    [:div.cp__sidebar-help-btn
-     [:div.inner
-      {:title    (t :help-shortcut-title)
-       :on-click (fn []
-                   (state/sidebar-add-block! (state/get-current-repo) "help" :help))}
-      "?"]]))
+  (let [help-open?      (state/sub :ui/help-open?)
+        handbooks-open? (state/sub :ui/handbooks-open?)]
+    [:<>
+     [:div.cp__sidebar-help-btn
+      [:div.inner
+       {:title    (t :help-shortcut-title)
+        :on-click #(state/toggle! :ui/help-open?)}
+       "?"]]
+
+     (when help-open?
+       (help-menu-popup))
+
+     (when handbooks-open?
+       (handbooks/handbooks-popup))]))
 
 (rum/defcs ^:large-vars/cleanup-todo sidebar <
   (mixins/modal :modal/show?)
@@ -828,7 +887,6 @@
                                     :nfs-granted? granted?
                                     :db-restoring? db-restoring?})
       [:a#download.hidden]
-      (when
-       (and (not config/mobile?)
-            (not config/publishing?))
+      (when (and (not config/mobile?)
+                 (not config/publishing?))
         (help-button))])))

+ 34 - 11
src/main/frontend/components/container.css

@@ -487,14 +487,6 @@
   }
 }
 
-html[data-theme='dark'] {
-  #left-sidebar {
-    > .shade-mask {
-      background-color: rgba(0, 0, 0, .15);
-    }
-  }
-}
-
 .settings-modal {
   @apply -m-8 rounded-lg;
   /* box-shadow: inset 0 0 0 1px var(--ls-border-color); */
@@ -527,13 +519,36 @@ html[data-theme='dark'] {
     @apply fixed bottom-4 right-4 sm:right-8;
 
     > .inner {
-      @apply font-bold
-      rounded-full h-8 w-8 flex items-center justify-center font-bold
-      select-none cursor-help;
+      @apply rounded-full h-8 w-8 flex items-center justify-center
+      font-bold select-none cursor-help;
 
       background-color: var(--ls-secondary-background-color);
     }
   }
+
+  &-menu-popup {
+    @apply fixed bottom-14 right-8 z-10 border
+    rounded-lg min-w-[260px] shadow;
+
+    background-color: var(--ls-secondary-background-color);
+    border-color: var(--ls-border-color);
+
+    > .list-wrap {
+      @apply flex flex-col pt-3;
+
+      .it {
+        color: var(--ls-primary-text-color);
+
+        &:active, &:hover {
+          background-color: var(--ls-tertiary-background-color);
+        }
+      }
+    }
+  }
+
+  &-handbook-btn {
+    @apply bottom-16;
+  }
 }
 
 .cp__right-sidebar {
@@ -754,3 +769,11 @@ a.ui__modal-close, a.close {
 a.ui__modal-close:hover, a.close:hover {
   opacity: 1;
 }
+
+html[data-theme='dark'] {
+  #left-sidebar {
+    > .shade-mask {
+      background-color: rgba(0, 0, 0, .15);
+    }
+  }
+}

+ 40 - 0
src/main/frontend/components/handbooks.cljs

@@ -0,0 +1,40 @@
+(ns frontend.components.handbooks
+  (:require [rum.core :as rum]
+            [frontend.state :as state]
+            [frontend.modules.layout.core :as layout]
+            ;[shadow.lazy :as lazy]
+            [frontend.extensions.handbooks.core :as handbooks]))
+
+#_:clj-kondo/ignore
+;(def lazy-handbooks (lazy/loadable frontend.extensions.handbooks.core/content))
+;
+;(rum/defc loadable-handbooks
+;  []
+;  (let [[content set-content] (rum/use-state nil)]
+;
+;    (rum/use-effect!
+;     (fn []
+;       (lazy/load lazy-handbooks #(set-content %))) [])
+;
+;    [:div.cp__handbooks-content
+;     content]))
+
+(rum/defc handbooks-popup
+  []
+  (let [popup-ref (rum/use-ref nil)]
+    (rum/use-effect!
+     (fn []
+       (when-let [^js popup-el (rum/deref popup-ref)]
+         (comp
+          (layout/setup-draggable-container! popup-el nil))))
+     [])
+
+    [:div.cp__handbooks-popup
+     {:data-identity "logseq-handbooks"
+      :ref popup-ref}
+     [:div.cp__handbooks-content-wrap
+      (handbooks/content)]]))
+
+(defn toggle-handbooks
+  []
+  (state/toggle! :ui/handbooks-open?))

+ 1 - 0
src/main/frontend/components/onboarding/index.css

@@ -506,6 +506,7 @@ body[data-page=import] {
 
   &.cp__sidebar-help-btn {
     background-color: rgba(0, 0, 0, .4);
+    z-index: 9;
 
     > .inner {
       opacity: 1;

+ 658 - 0
src/main/frontend/extensions/handbooks/core.cljs

@@ -0,0 +1,658 @@
+(ns frontend.extensions.handbooks.core
+  (:require [clojure.string :as string]
+            [rum.core :as rum]
+            [cljs.core.async :as async :refer [<! >!]]
+            [frontend.ui :as ui]
+            [frontend.state :as state]
+            [frontend.search :as search]
+            [frontend.config :as config]
+            [frontend.handler.notification :as notification]
+            [frontend.extensions.lightbox :as lightbox]
+            [frontend.modules.shortcut.config :as shortcut-config]
+            [frontend.rum :as r]
+            [cljs-bean.core :as bean]
+            [promesa.core :as p]
+            [camel-snake-kebab.core :as csk]
+            [medley.core :as medley]
+            [frontend.util :as util]
+            [frontend.storage :as storage]
+            [frontend.extensions.video.youtube :as youtube]
+            [frontend.context.i18n :refer [t]]
+            [clojure.edn :as edn]))
+
+(defonce *config (atom {}))
+
+(defn get-handbooks-endpoint
+  [resource]
+  (str
+    (if (storage/get :handbooks-dev-watch?)
+      "http://localhost:1337"
+      "https://handbooks.pages.dev")
+    resource))
+
+(defn resolve-asset-url
+  [path]
+  (if (string/starts-with? path "http")
+    path (str (get-handbooks-endpoint "/")
+              (-> path (string/replace-first "./" "")
+                  (string/replace-first #"^/+" "")))))
+
+(defn inflate-content-assets-urls
+  [content]
+  (if-let [matches (and (not (string/blank? content))
+                        (re-seq #"src=\"([^\"]+)\"" content))]
+    (reduce
+      (fn [content matched]
+        (if-let [matched (second matched)]
+          (string/replace content matched (resolve-asset-url matched)) content))
+      content matches)
+    content))
+
+(defn parse-key-from-href
+  [href base]
+  (when (and (string? href)
+             (not (string/blank? href)))
+    (when-let [href (some-> href (string/trim) (string/replace #".edn$" ""))]
+      (some-> (if (string/starts-with? href "@")
+                (string/replace href #"^[@\/]+" "")
+                (util/node-path.join base href))
+              (string/lower-case)
+              (csk/->snake_case_string)))))
+
+(defn parse-parent-key
+  [s]
+  (if (and (string? s) (string/includes? s "/"))
+    (subs s 0 (string/last-index-of s "/"))
+    s))
+
+(defn bind-parent-key
+  [{:keys [key] :as node}]
+  (cond-> node
+          (and (string? key)
+               (string/includes? key "/"))
+          (assoc :parent (parse-parent-key key))))
+
+(defn load-glide-assets!
+  []
+  (p/let [_ (util/css-load$ (str util/JS_ROOT "/glide/glide.core.min.css"))
+          _ (util/css-load$ (str util/JS_ROOT "/glide/glide.theme.min.css"))
+          _ (when-not (aget js/window "Glide")
+              (util/js-load$ (str util/JS_ROOT "/glide/glide.min.js")))]))
+
+(rum/defc topic-card
+  [{:keys [key title description cover] :as _topic} nav-fn! opts]
+  [:button.w-full.topic-card.flex.text-left
+   (merge
+     {:key      key
+      :on-click nav-fn!} opts)
+   (when cover
+     [:div.l.flex.items-center
+      [:img {:src (resolve-asset-url cover)}]])
+   [:div.r.flex.flex-col
+    [:strong title]
+    [:span description]]])
+
+(rum/defc pane-category-topics
+  [handbook-nodes pane-state nav!]
+
+  [:div.pane.pane-category-topics
+   [:div.topics-list
+    (let [category-key (:key (second pane-state))]
+      (when-let [category (get handbook-nodes category-key)]
+        (for [topic (:children category)]
+          (rum/with-key
+            (topic-card topic #(nav! [:topic-detail topic (:title category)] pane-state) nil)
+            (:key topic)))))]])
+
+(rum/defc media-render
+  [src]
+  (let [src (util/trim-safe src)
+        extname (some-> src (util/full-path-extname) (subs 1))
+        youtube-id (and (string/includes? src "youtube.com/watch?v=")
+                        (subs src (+ 2 (string/last-index-of src "v="))))]
+    (cond
+      (and extname (contains? config/video-formats (keyword extname)))
+      [:video {:src src :controls true}]
+
+      (string? youtube-id)
+      (youtube/youtube-video youtube-id {:width "100%" :height 235})
+
+      :else [:img {:src src}])))
+
+(rum/defc chapter-select
+  [topic children on-select]
+  (let [[open?, set-open?] (rum/use-state false)]
+    (rum/use-effect!
+      (fn []
+        (when-let [^js el (js/document.querySelector "[data-identity=logseq-handbooks]")]
+          (let [h #(when-not (some->> (.-target %)
+                                      (.contains (js/document.querySelector ".chapters-select")))
+                     (set-open? false))]
+            (.addEventListener el "click" h)
+            #(.removeEventListener el "click" h))))
+      [])
+
+    [:div.chapters-select.w-full
+     [:a.select-trigger
+      {:on-click #(set-open? (not open?))
+       :tabIndex "0"}
+      [:small "Current chapter"]
+      [:strong (:title topic)]
+      (if open?
+        (ui/icon "chevron-down")
+        (ui/icon "chevron-left"))
+
+      (when open?
+        [:ul
+         (for [c children]
+           (when (and (seq c) (not= (:key c) (:key topic)))
+             [:li {:key (:key c)}
+              [:a.flex {:tabIndex "0" :on-click #(on-select (:key c))}
+               (or (:title c) (:key c))]]))])]]))
+
+(rum/defc ^:large-vars/cleanup-todo pane-topic-detail
+  [handbook-nodes pane-state nav!]
+
+  (let [[deps-pending?, set-deps-pending?] (rum/use-state false)
+        *id-ref (rum/use-ref (str "glide--" (js/Date.now)))]
+
+    ;; load deps assets
+    (rum/use-effect!
+      (fn []
+        (set-deps-pending? true)
+        (-> (load-glide-assets!)
+            (p/then (fn [] (js/setTimeout
+                             #(when (js/document.getElementById (rum/deref *id-ref))
+                                (doto (js/window.Glide. (str "#" (rum/deref *id-ref))) (.mount))) 50)))
+            (p/finally #(set-deps-pending? false))))
+      [])
+
+    (rum/use-effect!
+      (fn []
+        (js/setTimeout #(some-> (js/document.querySelector ".cp__handbooks-content")
+                                (.scrollTo 0 0))))
+      [pane-state])
+
+    (when-let [topic-key (:key (second pane-state))]
+      (when-let [topic (get handbook-nodes topic-key)]
+        (let [chapters (:children topic)
+              has-chapters? (seq chapters)
+              topic (if has-chapters? (first chapters) topic)
+              parent (get handbook-nodes (:parent (bind-parent-key topic)))
+              chapters (or chapters (:children parent))
+              parent-key (:key parent)
+              parent-category? (not (string/includes? parent-key "/"))
+              show-chapters? (and (not parent-category?) (seq chapters))
+
+              chapters-len (count chapters)
+              chapter-current-idx (when-not (zero? chapters-len)
+                                    (util/find-index #(= (:key %) (:key topic)) chapters))]
+
+          (when-not deps-pending?
+            [:div.pane.pane-topic-detail
+             (when-not show-chapters?
+               [:h1.text-2xl.pb-3.font-semibold (:title topic)])
+
+             ;; chapters list
+             (when show-chapters?
+               [:div.chapters-wrap.py-2
+                (chapter-select
+                  topic chapters
+                  (fn [k]
+                    (when-let [chapter (get handbook-nodes k)]
+                      (nav! [:topic-detail chapter (:title parent)] pane-state))))])
+
+             ;; demos gallery
+             (when-let [demos (:demos topic)]
+               (let [demos (cond-> demos
+                                   (string? demos) (list))]
+                 (if (> (count demos) 1)
+                   [:div.flex.demos.glide
+                    {:id (rum/deref *id-ref)}
+
+                    [:div.glide__track {:data-glide-el "track"}
+                     [:div.glide__slides
+                      (for [demo demos]
+                        [:div.item.glide__slide
+                         (media-render (resolve-asset-url demo))])]]
+
+                    [:div.glide__bullets {:data-glide-el "controls[nav]"}
+                     (map-indexed
+                       (fn [idx _]
+                         [:button.glide__bullet {:data-glide-dir (str "=" idx)}
+                          (inc idx)])
+                       demos)]]
+
+                   [:div.flex.demos.pt-1
+                    (media-render (resolve-asset-url (first demos)))])))
+
+             [:div.content-wrap
+              (when-let [content (:content topic)]
+                [:<>
+                 [:div.content.markdown-body
+                  {:dangerouslySetInnerHTML {:__html (inflate-content-assets-urls content)}
+                   :on-click                (fn [^js e]
+                                              (when-let [target (.-target e)]
+                                                (if-let [^js img (.closest target "img")]
+                                                  (lightbox/preview-images! [{:src (.-src img)
+                                                                              :w   (.-naturalWidth img)
+                                                                              :h   (.-naturalHeight img)}])
+                                                  (when-let [link (some-> (.closest target "a") (.getAttribute "href"))]
+                                                    (when-let [to-k (and (not (string/starts-with? link "http"))
+                                                                         (parse-key-from-href link parent-key))]
+                                                      (if-let [to (get handbook-nodes to-k)]
+                                                        (nav! [:topic-detail to (:title parent)] pane-state)
+                                                        (js/console.error "ERROR: handbook link resource not found: " to-k link))
+                                                      (util/stop e))))))}]
+
+                 (when-let [idx (and (> chapters-len 1) chapter-current-idx)]
+                   (let [prev (when-not (zero? idx) (dec idx))
+                         next (when-not (= idx (dec chapters-len)) (inc idx))]
+
+                     [:div.controls.flex.justify-between.pt-4
+                      [:div (when prev (ui/button [:span.flex.items-center (ui/icon "arrow-left") "Prev chapter"]
+                                                  :small? true :on-click #(nav! [:topic-detail (nth chapters prev) (:title parent)] pane-state)))]
+                      [:div (when next (ui/button [:span.flex.items-center "Next chapter" (ui/icon "arrow-right")]
+                                                  :small? true :on-click #(nav! [:topic-detail (nth chapters next) (:title parent)] pane-state)))]]))])]]))))))
+
+(rum/defc pane-dashboard
+  [handbooks-nodes pane-state nav-to-pane!]
+  (when-let [root (get handbooks-nodes "__root")]
+    [:div.pane.dashboard-pane
+     (when-let [popular-topics (:popular-topics root)]
+       [:<>
+        [:h2 (t :handbook/popular-topics)]
+        [:div.topics-list
+         (for [topic-key popular-topics]
+           (when-let [topic (and (string? topic-key)
+                                 (->> (util/safe-lower-case topic-key)
+                                      (csk/->snake_case_string)
+                                      (get handbooks-nodes)))]
+             (topic-card topic #(nav-to-pane! [:topic-detail topic (t :handbook/title)] [:dashboard]) nil)))]])
+
+     [:h2 (t :handbook/help-categories)]
+     [:div.categories-list
+      (let [categories (:children root)
+            categories (conj (vec categories)
+                             {:key      :ls-shortcuts
+                              :title    [:span "Keyboard shortcuts"]
+                              :children [:span (->> (vals @shortcut-config/*config)
+                                                    (map count)
+                                                    (apply +))
+                                         " shortcuts"]
+                              :color    "#2563EB"
+                              :icon     "command"})]
+        (for [{:keys [key title children color icon] :as category} categories
+              :let [total (if counted? (count children) 0)]]
+          [:button.category-card.text-left
+           {:key      key
+            :style    {:border-left-color (or (ui/->block-background-color color) "var(--ls-secondary-background-color)")}
+            :data-total total
+            :on-click #(if (= key :ls-shortcuts)
+                         (do (state/toggle! :ui/handbooks-open?)
+                             (state/open-right-sidebar!)
+                             (state/sidebar-add-block! (state/get-current-repo) "shortcut-settings" :shortcut-settings))
+                         (nav-to-pane! [:topics category title] pane-state))}
+           [:div.icon-wrap
+            (ui/icon (or icon "chart-bubble") {:size 20})]
+           [:div.text-wrap
+            [:strong title]
+            (cond
+              (vector? children)
+              children
+
+              :else
+              [:span (str total " " (util/safe-lower-case (t :handbook/topics)))])]]))]]))
+
+(rum/defc pane-settings
+  [dev-watch? set-dev-watch?]
+  [:div.pane.pane-settings
+   [:div.item
+    [:p.flex.items-center.space-x-3.mb-0
+     [:strong "Writing mode (preview in time)"]
+     (ui/toggle dev-watch? #(set-dev-watch? (not dev-watch?)) true)]
+    [:small.opacity-30 (str "Resources from " (get-handbooks-endpoint "/"))]]])
+
+(rum/defc search-bar
+  [pane-state nav! handbooks-nodes search-state set-search-state!]
+  (let [*input-ref (rum/use-ref nil)
+        [q, set-q!] (rum/use-state "")
+        [results, set-results!] (rum/use-state nil)
+        [selected, set-selected!] (rum/use-state 0)
+        select-fn! #(when-let [ldx (and (seq results) (dec (count results)))]
+                      (set-selected!
+                        (case %
+                          :up (if (zero? selected) ldx (max (dec selected) 0))
+                          :down (if (= selected ldx) 0 (min (inc selected) ldx))
+                          :dune)))
+
+        q (util/trim-safe q)
+        active? (not (string/blank? (util/trim-safe q)))
+        reset-q! #(->> "" (set! (.-value (rum/deref *input-ref))) (set-q!))
+        focus-q! #(some-> (rum/deref *input-ref) (.focus))]
+
+    (rum/use-effect!
+      #(focus-q!)
+      [pane-state])
+
+    (rum/use-effect!
+      (fn []
+        (let [pane-nodes (:children (second pane-state))
+              pane-nodes (and (seq pane-nodes)
+                              (mapcat #(conj (:children %) %) pane-nodes))]
+
+          (set-search-state!
+            (merge search-state {:active? active?}))
+
+          (if (and (seq handbooks-nodes) active?)
+            (-> (or pane-nodes
+                    ;; global
+                    (vals (dissoc handbooks-nodes "__root")))
+                (search/fuzzy-search q :limit 30 :extract-fn :title)
+                (set-results!))
+            (set-results! nil))
+
+          (set-selected! 0)))
+      [q])
+
+    [:div.search
+     [:div.input-wrap.relative
+      [:span.icon.absolute.opacity-90
+       {:style {:top 6 :left 7}}
+       (ui/icon "search" {:size 12})]
+
+      [:input {:placeholder   (t :handbook/search)
+               :auto-focus    true
+               :default-value q
+               :on-change     #(set-q! (util/evalue %))
+               :on-key-down   #(case (.-keyCode %)
+                                 ;; ESC
+                                 27
+                                 (if-not active?
+                                   (state/toggle! :ui/handbooks-open?)
+                                   (reset-q!))
+
+                                 ;; Up
+                                 38
+                                 (do
+                                   (util/stop %)
+                                   (select-fn! :up))
+
+                                 ;; Down
+                                 40
+                                 (do
+                                   (util/stop %)
+                                   (select-fn! :down))
+
+                                 ;; Enter
+                                 13
+                                 (when-let [topic (and active? (nth results selected))]
+                                   (util/stop %)
+                                   (nav! [:topic-detail topic (:title topic)] pane-state))
+
+                                 :dune)
+               :ref           *input-ref}]
+
+      (when active?
+        [:button.icon.absolute.opacity-50.hover:opacity-80.select-none
+         {:style    {:right 6 :top 7}
+          :on-click #(do (reset-q!) (focus-q!))}
+         (ui/icon "x" {:size 12})])]
+
+     (when (:active? search-state)
+       [:div.search-results-wrap
+        [:div.results-wrap
+         (for [[idx topic] (medley/indexed results)]
+           (rum/with-key
+             (topic-card topic #(nav! [:topic-detail topic (:title topic)] pane-state)
+                         {:class (util/classnames [{:active (= selected idx)}])})
+             (:key topic)))]])]))
+
+(rum/defc link-card
+  [opts child]
+
+  (let [{:keys [href]} opts]
+    [:div.link-card
+     (cond-> opts
+             (string? href)
+             (assoc :on-click #(util/open-url href)))
+     child]))
+
+;(rum/defc related-topics
+;  []
+;  [:div.related-topics
+;   (link-card {} [:strong.text-md "How to do something?"])])
+
+(def panes-mapping
+  {:dashboard    [pane-dashboard]
+   :topics       [pane-category-topics]
+   :topic-detail [pane-topic-detail]
+   :settings     [pane-settings]})
+
+
+(defonce discord-endpoint "https://plugins.logseq.io/ds")
+
+(rum/defc footer-link-cards
+  []
+  (let [[config _] (r/use-atom *config)
+        discord-count (:discord-online config)]
+
+    (rum/use-effect!
+      (fn []
+        (when (or (nil? discord-count)
+                  (> (- (js/Date.now) (:discord-online-created config)) (* 10 60 1000)))
+          (-> (js/window.fetch discord-endpoint)
+              (p/then #(.json %))
+              (p/then #(when-let [count (.-approximate_presence_count ^js %)]
+                         (swap! *config assoc
+                                :discord-online (.toLocaleString count)
+                                :discord-online-created (js/Date.now)))))))
+      [discord-count])
+
+    [:<>
+     ;; more links
+     [:div.flex.space-x-3
+      {:style {:padding-top "4px"}}
+      (link-card
+        {:class "flex-1" :href "https://discord.gg/KpN4eHY"}
+        [:div.inner.flex.space-x-1.flex-col
+         (ui/icon "brand-discord" {:class "opacity-30" :size 26})
+         [:h1.font-medium.py-1 "Chat on Discord"]
+         [:h2.text-xs.leading-4.opacity-40 "Ask quick questions, meet fellow users, and learn new workflows."]
+         [:small.flex.items-center.pt-1.5
+          [:i.block.rounded-full.bg-green-500 {:style {:width "8px" :height "8px"}}]
+          [:span.pl-2.opacity-90
+           [:strong.opacity-60 (or discord-count "?")]
+           [:span.opacity-70.font-light " users online"]]]])
+
+      (link-card
+        {:class "flex-1" :href "https://discuss.logseq.com"}
+        [:div.inner.flex.space-x-1.flex-col
+         (ui/icon "message-dots" {:class "opacity-30" :size 26})
+         [:h1.font-medium.py-1 "Visit the forum"]
+         [:h2.text-xs.leading-4.opacity-40 "Give feedback, request features, and have in-depth conversations."]
+         [:small.flex.items-center.pt-1.5
+          [:i.flex.items-center.opacity-50 (ui/icon "bolt" {:size 14})]
+          [:span.pl-1.opacity-90
+           [:strong.opacity-60 "800+"]
+           [:span.opacity-70.font-light " monthly posts"]]]])]]))
+
+(rum/defc ^:large-vars/data-var content
+  []
+  (let [[active-pane-state, set-active-pane-state!]
+        (rum/use-state [:dashboard nil (t :handbook/title)])
+
+        [handbooks-state, set-handbooks-state!]
+        (rum/use-state nil)
+
+        [handbooks-nodes, set-handbooks-nodes!]
+        (rum/use-state nil)
+
+        [history-state, set-history-state!]
+        (rum/use-state ())
+
+        [dev-watch?, set-dev-watch?]
+        (rum/use-state (storage/get :handbooks-dev-watch?))
+
+        [search-state, set-search-state!]
+        (rum/use-state {:active? false})
+
+        reset-handbooks! #(set-handbooks-state! {:status nil :data nil :error nil})
+        update-handbooks! #(set-handbooks-state! (fn [v] (merge v %)))
+        load-handbooks! (fn []
+                          (when-not (= :pending (:status handbooks-state))
+                            (reset-handbooks!)
+                            (update-handbooks! {:status :pending})
+                            (-> (p/let [^js res (js/fetch (get-handbooks-endpoint "/handbooks.edn"))
+                                        data (.text res)]
+                                  (update-handbooks! {:data (edn/read-string data)}))
+                                (p/catch #(update-handbooks! {:error (str %)}))
+                                (p/finally #(update-handbooks! {:status :completed})))))
+
+        active-pane-name (first active-pane-state)
+        pane-render (first (get panes-mapping active-pane-name))
+        pane-dashboard? (= :dashboard active-pane-name)
+        pane-settings? (= :settings active-pane-name)
+        pane-topic? (= :topic-detail active-pane-name)
+        force-nav-dashboard! (fn []
+                               (set-active-pane-state! [:dashboard])
+                               (set-history-state! '()))
+
+        handbooks-loaded? (and (seq (:data handbooks-state))
+                               (= :completed (:status handbooks-state)))
+        handbooks-data (:data handbooks-state)
+        nav-to-pane! (fn [next-state prev-state]
+                       (let [next-key (:key (second next-state))
+                             prev-key (:key (second prev-state))
+                             in-chapters? (and prev-key next-key (string/includes? prev-key "/")
+                                               (or (string/starts-with? next-key prev-key)
+                                                   (apply = (map parse-parent-key [prev-key next-key]))))]
+                         (when-not in-chapters?
+                           (set-history-state!
+                             (conj (sequence history-state) prev-state))))
+                       (set-active-pane-state! next-state))
+
+        [scrolled?, set-scrolled!] (rum/use-state false)
+        on-scroll (rum/use-memo #(util/debounce 100 (fn [^js e] (set-scrolled! (not (< (.. e -target -scrollTop) 10))))) [])]
+
+    ;; load handbooks
+    (rum/use-effect!
+      #(load-handbooks!)
+      [])
+
+    ;; navigation sentry
+    (rum/use-effect!
+      (fn []
+        (when (seq handbooks-nodes)
+          (let [c (:handbook/route-chan @state/state)]
+            (async/go-loop []
+                           (let [v (<! c)]
+                             (when (not= v :return)
+                               (when-let [to (get handbooks-nodes v)]
+                                 (nav-to-pane! [:topic-detail to (t :handbook/title)] [:dashboard]))
+                               (recur))))
+            #(async/go (>! c :return)))))
+      [handbooks-nodes])
+
+    (rum/use-effect!
+      (fn []
+        (let [*cnt-len (atom 0)
+              check! (fn []
+                       (-> (p/let [^js res (js/fetch (get-handbooks-endpoint "/handbooks.edn") #js{:method "HEAD"})]
+                             (when-let [cl (.get (.-headers res) "content-length")]
+                               (when (not= @*cnt-len cl)
+                                 (println "[Handbooks] dev reload!")
+                                 (load-handbooks!))
+                               (reset! *cnt-len cl)))
+                           (p/catch #(println "[Handbooks] dev check Error:" %))))
+              timer0 (if dev-watch?
+                       (js/setInterval check! 2000) 0)]
+          #(js/clearInterval timer0)))
+      [dev-watch?])
+
+    (rum/use-effect!
+      (fn []
+        (when handbooks-data
+          (let [nodes (->> (tree-seq map? :children handbooks-data)
+                           (reduce #(assoc %1 (or (:key %2) "__root") (bind-parent-key %2)) {}))]
+            (set-handbooks-nodes! nodes)
+            (set! (.-handbook-nodes js/window) (bean/->js nodes)))))
+      [handbooks-data])
+
+    [:div.cp__handbooks-content
+     {:class     (util/classnames [{:search-active (:active? search-state)
+                                    :scrolled      scrolled?}])
+      :on-scroll on-scroll}
+     [:div.pane-wrap
+      [:div.hd.flex.justify-between.select-none.draggable-handle
+       [:h1.text-xl.flex.items-center.font-bold
+        (if pane-dashboard?
+          [:span (t :handbook/title)]
+          [:button.active:opacity-80.flex.items-center.cursor-pointer
+           {:on-click (fn [] (let [prev (first history-state)
+                                   prev (cond-> prev
+                                                (nil? (seq prev))
+                                                [:dashboard])]
+                               (set-active-pane-state! prev)
+                               (set-history-state! (rest history-state))))}
+           [:span.pr-2.flex.items-center (ui/icon "chevron-left")]
+           (let [title (or (last active-pane-state) (t :handbook/title) "")]
+             [:span.truncate.title {:title title} title])])]
+
+       [:div.flex.items-center.space-x-3
+        (when (> (count history-state) 1)
+          [:a.flex.items-center {:aria-label (t :handbook/home) :tabIndex "0" :on-click #(force-nav-dashboard!)} (ui/icon "home")])
+        (when pane-topic?
+          [:a.flex.items-center
+           {:aria-label "Copy topic link" :tabIndex "0"
+            :on-click   (fn []
+                          (let [s (str "logseq://handbook/" (:key (second active-pane-state)))]
+                            (util/copy-to-clipboard! s)
+                            (notification/show!
+                              [:div [:strong.block "Handbook link copied!"]
+                               [:label.opacity-50 s]] :success)))}
+           (ui/icon "copy")])
+        (when (state/developer-mode?)
+          [:a.flex.items-center {:aria-label (t :handbook/settings)
+                                 :tabIndex   "0"
+                                 :on-click   #(nav-to-pane! [:settings nil "Settings"] active-pane-state)}
+           (ui/icon "settings")])
+        [:a.flex.items-center {:aria-label (t :handbook/close) :tabIndex "0" :on-click #(state/toggle! :ui/handbooks-open?)}
+         (ui/icon "x")]]]
+
+      (when (and (not pane-settings?) (not handbooks-loaded?))
+        [:div.flex.items-center.justify-center.pt-32
+         (if-not (:error handbooks-state)
+           (ui/loading "Loading ...")
+           [:code (:error handbooks-state)])])
+
+      (when (or pane-settings? handbooks-loaded?)
+        [:<>
+         ;; search bar
+         (when (or pane-dashboard? (= :topics active-pane-name))
+           (search-bar active-pane-state nav-to-pane!
+                       handbooks-nodes search-state set-search-state!))
+
+         ;; entry pane
+         (when pane-render
+           (apply pane-render
+                  (case active-pane-name
+                    :settings
+                    [dev-watch? #(do (set-dev-watch? %)
+                                     (storage/set :handbooks-dev-watch? %))]
+
+                    ;; default inputs
+                    [handbooks-nodes active-pane-state nav-to-pane!])))])]
+
+     (when handbooks-loaded?
+       ;; footer
+       (when pane-dashboard?
+         [:div.ft
+          (footer-link-cards)
+
+          ;; TODO: how to get related topics?
+          ;(when (= :topic-detail active-pane)
+          ;  [:<>
+          ;   [:h2.uppercase.opacity-60 "Related"]
+          ;   (related-topics)])
+          ]))]))

+ 412 - 0
src/main/frontend/extensions/handbooks/handbooks.css

@@ -0,0 +1,412 @@
+.cp__handbooks {
+  &-content {
+    @apply flex flex-col justify-between flex-1 overflow-y-auto;
+
+    -webkit-font-smoothing: antialiased;
+    overflow-y: overlay;
+
+    &-wrap {
+      @apply flex justify-center flex-col flex-1 h-full overflow-y-auto relative;
+    }
+
+    .hd {
+      @apply dark:text-white px-3 pt-3 pb-2 sticky top-0 left-0 z-[4]
+      transition-shadow duration-200;
+
+      background-color: var(--ls-tertiary-background-color);
+
+      .title {
+        text-align: left;
+        width: 266px;
+      }
+    }
+
+    &.scrolled {
+      .hd {
+        box-shadow: -3px 4px 6px -6px #ccc;
+      }
+    }
+
+    .search {
+      @apply flex flex-col pb-[6px] mb-0;
+
+      > .input-wrap {
+        @apply mx-4 mb-2 flex rounded-lg mt-1.5;
+
+        border: 3px solid var(--ls-primary-background-color);
+        background-color: var(--ls-primary-background-color);
+
+        &:focus-within {
+          border: 3px solid var(--ls-secondary-border-color);
+        }
+
+        > input {
+          @apply text-base leading-none w-full border-none py-[7px] px-[24px] bg-transparent
+          focus:outline-0 dark:text-gray-100 font-medium;
+        }
+
+      }
+
+      > .search-results-wrap {
+        @apply px-4 py-1;
+      }
+    }
+
+    .pane {
+      @apply py-1 px-4 dark:text-gray-50;
+    }
+
+    .pane > h2, .ft > h2 {
+      @apply py-2 text-base font-medium dark:text-gray-100;
+    }
+
+    .ft {
+      @apply px-4 pt-4 pb-2;
+
+      background-color: var(--ls-quaternary-background-color);
+
+      /*noinspection ALL*/
+
+      svg {
+        stroke-width: 1.5px;
+      }
+    }
+
+    .topic-card, .link-card {
+      @apply text-sm px-3 py-2.5 rounded-lg cursor-pointer
+      mb-2 active:opacity-90 select-none items-center;
+
+      background-color: var(--ls-secondary-background-color);
+      border: 1px solid var(--ls-border-color);
+      transition: background-color .3s;
+
+      > .l {
+        @apply pr-2.5 w-[80px] min-h-[64px] bg-transparent rounded overflow-hidden;
+
+        img {
+          mix-blend-mode: luminosity;
+          opacity: .8;
+          float: left;
+          width: 100%;
+        }
+      }
+
+      > .r {
+        @apply leading-none flex-1;
+
+        > strong {
+          @apply font-medium text-sm pt-0.5 pb-[1px] opacity-90 leading-5 dark:text-gray-5;
+        }
+
+        > span {
+          @apply text-xs opacity-40 leading-4;
+        }
+      }
+
+      &:hover, &.active {
+        background-color: var(--ls-primary-background-color);
+        border-color: var(--ls-secondary-border-color);
+
+        > .l {
+          img {
+            mix-blend-mode: unset;
+            opacity: 1;
+          }
+        }
+      }
+    }
+
+    .link-card {
+      @apply dark:text-gray-100;
+
+      border-color: var(--ls-tertiary-border-color);
+
+      &:hover {
+        border-color: var(--ls-tertiary-border-color);
+      }
+
+      &.as-primary {
+        @apply bg-indigo-500 text-white;
+      }
+    }
+
+    .category-card {
+      @apply flex rounded px-2 py-3 active:opacity-90 cursor-pointer transition-colors items-end;
+
+      border-left: 4px solid var(--ls-secondary-background-color);
+      background-color: var(--ls-secondary-background-color);
+
+      &[data-total="0"] {
+        @apply hidden;
+      }
+
+      &:hover, &:active {
+        background-color: var(--ls-primary-background-color);
+      }
+
+      > .icon-wrap {
+        @apply flex justify-end pr-2 pb-[2px] opacity-20;
+      }
+
+      > .text-wrap {
+        @apply flex flex-col min-h-[48px] justify-end;
+
+        > strong {
+          @apply font-medium leading-tight text-sm;
+        }
+
+        > span {
+          @apply text-xs pt-1;
+
+          color: var(--ls-primary-text-color);
+        }
+      }
+    }
+
+    .categories-list {
+      @apply grid grid-cols-2 gap-3;
+    }
+
+    .pane-topic-detail {
+      @apply flex flex-col h-full;
+
+      > h1 {
+        @apply pb-1;
+      }
+
+      > .demos {
+        img, video {
+          @apply w-full;
+        }
+
+        &.glide {
+          @apply mb-[10px];
+        }
+
+        .glide__slide {
+          background-color: var(--ls-secondary-border-color);
+        }
+      }
+
+      .content {
+        @apply overflow-hidden pt-1 leading-6;
+
+        &-wrap {
+          @apply flex flex-col justify-around;
+        }
+      }
+
+      iframe {
+        margin: 0;
+      }
+    }
+
+    .glide {
+      &__bullets {
+        @apply w-full bottom-0 left-0 transform-none
+        flex items-center justify-end pb-2 pr-1;
+      }
+
+      &__bullet {
+        @apply dark:text-black;
+
+        width: 24px;
+        height: 24px;
+        font-size: 13px;
+        border: none;
+        margin: 0 5px;
+      }
+
+      &--swipeable {
+        cursor: default !important;
+      }
+    }
+
+    &.search-active {
+      .pane {
+        &:not(.pane-topic-detail) {
+          display: none;
+        }
+      }
+
+      .ft {
+        display: none;
+      }
+    }
+
+    .markdown-body {
+      @apply pt-4;
+
+      -webkit-font-smoothing: initial;
+
+      h1 {
+        @apply py-1 text-2xl font-bold;
+      }
+
+      h2 {
+        @apply py-1 text-xl font-bold;
+      }
+
+      h3, h4 {
+        @apply py-1 text-lg font-semibold;
+      }
+
+      h4 {
+        @apply text-base;
+      }
+
+      h5 {
+        @apply py-0.5 font-semibold text-sm;
+      }
+
+      h6 {
+        @apply py-0.5 text-xs font-semibold;
+      }
+
+      p {
+        @apply leading-[1.6rem] my-[0.75rem];
+      }
+
+      blockquote {
+        margin: 0;
+      }
+    }
+
+    .chapters {
+      &-wrap {
+
+      }
+
+      &-select {
+        .select-trigger {
+          @apply relative flex flex-col rounded py-2 px-3 leading-5 select-none z-[1];
+
+          color: var(--ls-primary-text-color);
+          background-color: var(--ls-secondary-background-color);
+
+          small {
+            @apply text-[11px] opacity-50 pl-0.5;
+          }
+
+          strong {
+            @apply text-sm dark:text-gray-100;
+          }
+
+          .ui__icon {
+            @apply absolute right-2 top-5 opacity-70;
+          }
+
+          &:active {
+            .ui__icon, strong {
+              @apply opacity-80;
+            }
+          }
+
+          ul {
+            @apply absolute top-[58px] left-0 w-full list-none m-0 rounded-b py-2;
+
+            background-color: var(--ls-secondary-background-color);
+            transform: translateY(-5px);
+            max-height: 300px;
+            overflow: auto;
+
+            li {
+              @apply list-none px-3 py-1 transition-colors text-sm;
+
+              &:hover {
+                background-color: var(--ls-tertiary-background-color);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    :not(pre) > code {
+      white-space: nowrap;
+    }
+
+    img {
+      @apply cursor-pointer active:opacity-80;
+    }
+
+    img, video {
+      @apply inline-block my-1;
+    }
+  }
+
+  &-popup {
+    @apply fixed rounded-lg overflow-hidden
+    z-[19] shadow-lg flex justify-center flex-col;
+
+    background-color: var(--ls-tertiary-background-color);
+    border: 1px solid var(--ls-tertiary-background-color);
+    touch-action: none;
+    height: 686px;
+    max-height: 86vh;
+    width: 420px;
+    right: 32px;
+    bottom: 58px;
+  }
+}
+
+html[data-theme="light"] {
+  .cp__handbooks-popup {
+    background-color: var(--ls-primary-background-color);
+
+    .input-wrap {
+      background-color: #f1f1f1;
+
+      &:focus-within {
+        background-color: transparent;
+      }
+    }
+
+    .topic-card, :not(.as-primary).link-card {
+      &:hover, &.active {
+        background-color: var(--ls-tertiary-background-color);
+        border-color: var(--ls-secondary-border-color);
+      }
+    }
+  }
+
+  .cp__handbooks-content {
+    .hd {
+      background-color: var(--ls-primary-background-color);
+    }
+
+    .ft {
+      background-color: var(--ls-primary-background-color);
+    }
+
+    .search {
+      background-color: var(--ls-primary-background-color);
+    }
+
+    .chapters-select {
+      .select-trigger {
+        background-color: var(--ls-tertiary-background-color);
+      }
+    }
+
+    .categories-list {
+      .category-card {
+        &:hover, &:active {
+          background-color: var(--ls-tertiary-background-color);
+        }
+      }
+    }
+
+    ul {
+      list-style: unset;
+
+      ul {
+        list-style: circle;
+
+        ul {
+          list-style: square;
+        }
+      }
+    }
+  }
+}

+ 24 - 24
src/main/frontend/extensions/video/youtube.cljs

@@ -28,17 +28,17 @@
 
 (defn register-player [state]
   (try
-    (let [id (first (:rum/args state))
-         node (rum/dom-node state)]
-     (when node
-       (let [player (js/window.YT.Player.
-                     node
-                     (clj->js
-                      {:events
-                       {"onReady" (fn [_e] (js/console.log id " ready"))}}))]
-         (state/update-state! [:youtube/players]
-                              (fn [players]
-                                (assoc players id player))))))
+    (let [id   (first (:rum/args state))
+          node (rum/dom-node state)]
+      (when node
+        (let [player (js/window.YT.Player.
+                      node
+                      (clj->js
+                       {:events
+                        {"onReady" (fn [_e] (js/console.log id " ready"))}}))]
+          (state/update-state! [:youtube/players]
+                               (fn [players]
+                                 (assoc players id player))))))
     (catch :default _e
       nil)))
 
@@ -51,14 +51,14 @@
        (<! (load-youtube-api))
        (register-player state))
      state)}
-  [state id]
-  (let [width  (min (- (util/get-width) 96)
-                    560)
-        height (int (* width (/ 315 560)))]
+  [state id {:keys [width height] :as _opts}]
+  (let [width  (or width (min (- (util/get-width) 96)
+                              560))
+        height (or height (int (* width (/ 315 560))))]
     [:iframe
      {:id                (str "youtube-player-" id)
       :allow-full-screen "allowfullscreen"
-      :allow "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
+      :allow             "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
       :frame-border      "0"
       :src               (str "https://www.youtube.com/embed/" id "?enablejsapi=1")
       :height            height
@@ -141,13 +141,13 @@ Remember: You can paste a raw YouTube url as embedded video on mobile."
   (re-matches #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$" "123:22:23") ;; => ["123:22:23" "123" "22" "23"]
   (re-matches #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$" "30:23") ;; => ["30:23" nil "30" "23"]
 
-  (parse-timestamp "01:23") ;; => 83
+ (parse-timestamp "01:23")                                  ;; => 83
 
-  (parse-timestamp "01:01:23") ;; => 3683
+ (parse-timestamp "01:01:23")                               ;; => 3683
 
-  ;; seconds->display
-  ;; https://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript
-  (seconds->display 129600) ;; => "36:00:00"
-  (seconds->display 13545) ;; => "03:45:45"
-  (seconds->display 18) ;; => "00:18"
-  )
+ ;; seconds->display
+ ;; https://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript
+ (seconds->display 129600)                                  ;; => "36:00:00"
+ (seconds->display 13545)                                   ;; => "03:45:45"
+ (seconds->display 18)                                      ;; => "00:18"
+ )

+ 1 - 5
src/main/frontend/handler/ui.cljs

@@ -68,11 +68,7 @@
 
 (defn toggle-help!
   []
-  (when-let [current-repo (state/get-current-repo)]
-    (let [id "help"]
-      (if (state/sidebar-block-exists? id)
-        (state/sidebar-remove-block! id)
-        (state/sidebar-add-block! current-repo id :help)))))
+  (state/toggle! :ui/help-open?))
 
 (defn toggle-settings-modal!
   []

+ 76 - 68
src/main/frontend/modules/layout/core.cljs

@@ -16,19 +16,19 @@
   [identity]
   (when-let [^js/HTMLElement container (and (> (count @*movable-containers) 1)
                                             (get @*movable-containers identity))]
-    (let [zdx (->> @*movable-containers
-                   (map (fn [[_ ^js el]]
-                          (let [^js c (js/getComputedStyle el)
-                                v1 (.-visibility c)
-                                v2 (.-display c)]
-                            (when-let [z (and (= "visible" v1)
-                                              (not= "none" v2)
-                                              (.-zIndex c))]
-                              z))))
-                   (remove nil?))
-          zdx (bean/->js zdx)
-          zdx (and zdx (js/Math.max.apply nil zdx))
-          zdx' (util/safe-parse-int (.. container -style -zIndex))]
+    (let [zdx  (->> @*movable-containers
+                    (map (fn [[_ ^js el]]
+                           (let [^js c (js/getComputedStyle el)
+                                 v1    (.-visibility c)
+                                 v2    (.-display c)]
+                             (when-let [z (and (= "visible" v1)
+                                               (not= "none" v2)
+                                               (.-zIndex c))]
+                               z))))
+                    (remove nil?))
+          zdx  (bean/->js zdx)
+          zdx  (and zdx (js/Math.max.apply nil zdx))
+          zdx' (some-> (.. container -style -zIndex) (parse-long))]
 
       (when (or (nil? zdx') (not= zdx zdx'))
         (set! (.. container -style -zIndex) (inc zdx))))))
@@ -36,35 +36,38 @@
 (defn ^:export setup-draggable-container!
   [^js/HTMLElement el callback]
   (when-let [^js/HTMLElement handle (.querySelector el ".draggable-handle")]
-    (let [^js cls (.-classList el)
-          ^js ds (.-dataset el)
+    (let [^js cls  (.-classList el)
+          ^js ds   (.-dataset el)
           identity (.-identity ds)
-          ing? "is-dragging"]
+          ing?     "is-dragging"]
 
       ;; draggable
       (-> (js/interact handle)
           (.draggable
-            (bean/->js
-              {:listeners
-               {:move (fn [^js/MouseEvent e]
-                        (let [^js dset (.-dataset el)
-                              dx (.-dx e)
-                              dy (.-dy e)
-                              dx' (util/safe-parse-float (.-dx dset))
-                              dy' (util/safe-parse-float (.-dy dset))
-                              x (+ dx (if dx' dx' 0))
-                              y (+ dy (if dy' dy' 0))]
-
-                          ;; update container position
-                          (set! (.. el -style -transform) (str "translate(" x "px, " y "px)"))
-
-                          ;; cache dx dy
-                          (set! (.. el -dataset -dx) x)
-                          (set! (.. el -dataset -dy) y)))}}))
+           (bean/->js
+            {:listeners
+             {:move (fn [^js/MouseEvent e]
+                      (let [^js dset (.-dataset el)
+                            dx       (.-dx e)
+                            dy       (.-dy e)
+                            dx'      (.-dx dset)
+                            dy'      (.-dy dset)
+                            dx'      (and dx' (util/safe-parse-float dx'))
+                            dy'      (and dy' (util/safe-parse-float dy'))
+                            x        (+ dx (or dx' 0))
+                            y        (+ dy (or dy' 0))]
+
+                        ;; update container position
+                        (set! (.. el -style -transform) (str "translate(" x "px, " y "px)"))
+
+                        ;; cache dx dy
+                        (set! (.. el -dataset -dx) x)
+                        (set! (.. el -dataset -dy) y)))}}))
           (.on "dragstart" (fn [] (.add cls ing?)))
           (.on "dragend" (fn [e]
                            (.remove cls ing?)
-                           (callback (bean/->js (calc-layout-data el e))))))
+                           (when (fn? callback)
+                             (callback (bean/->js (calc-layout-data el e)))))))
       ;; manager
       (swap! *movable-containers assoc identity el)
 
@@ -72,45 +75,50 @@
 
 (defn ^:export setup-resizable-container!
   [^js/HTMLElement el callback]
-  (let [^js cls (.-classList el)
-        ^js ds (.-dataset el)
+  (let [^js cls  (.-classList el)
+        ^js ds   (.-dataset el)
         identity (.-identity ds)
-        ing? "is-resizing"]
+        ing?     "is-resizing"]
 
     ;; resizable
     (-> (js/interact el)
         (.resizable
-          (bean/->js
-            {:edges
-             {:left true :top true :bottom true :right true}
-
-             :listeners
-             {:start (fn [] (.add cls ing?))
-              :end   (fn [e] (.remove cls ing?) (callback (bean/->js (calc-layout-data el e))))
-              :move  (fn [^js/MouseEvent e]
-                       (let [^js dset (.-dataset el)
-                             w (.. e -rect -width)
-                             h (.. e -rect -height)
-
-                             ;; update position from top/left
-                             dx (.. e -deltaRect -left)
-                             dy (.. e -deltaRect -top)
-
-                             dx' (util/safe-parse-float (.-dx dset))
-                             dy' (util/safe-parse-float (.-dy dset))
-
-                             x (+ dx (if dx' dx' 0))
-                             y (+ dy (if dy' dy' 0))]
-
-                         ;; update container position
-                         (set! (.. el -style -transform) (str "translate(" x "px, " y "px)"))
-
-                         ;; update container size
-                         (set! (.. el -style -width) (str w "px"))
-                         (set! (.. el -style -height) (str h "px"))
-
-                         (set! (. dset -dx) x)
-                         (set! (. dset -dy) y)))}})))
+         (bean/->js
+          {:edges
+           {:left true :top true :bottom true :right true}
+
+           :listeners
+           {:start (fn [] (.add cls ing?))
+            :end   (fn [e]
+                     (.remove cls ing?)
+                     (when (fn? callback)
+                       (callback (bean/->js (calc-layout-data el e)))))
+            :move  (fn [^js/MouseEvent e]
+                     (let [^js dset (.-dataset el)
+                           w        (.. e -rect -width)
+                           h        (.. e -rect -height)
+
+                           ;; update position from top/left
+                           dx       (.. e -deltaRect -left)
+                           dy       (.. e -deltaRect -top)
+
+                           dx'      (.-dx dset)
+                           dy'      (.-dy dset)
+                           dx'      (and dx' (util/safe-parse-float dx'))
+                           dy'      (and dy' (util/safe-parse-float dy'))
+
+                           x        (+ dx (or dx' 0))
+                           y        (+ dy (or dy' 0))]
+
+                       ;; update container position
+                       (set! (.. el -style -transform) (str "translate(" x "px, " y "px)"))
+
+                       ;; update container size
+                       (set! (.. el -style -width) (str w "px"))
+                       (set! (.. el -style -height) (str h "px"))
+
+                       (set! (. dset -dx) x)
+                       (set! (. dset -dy) y)))}})))
 
     ;; manager
     (swap! *movable-containers assoc identity el)

+ 21 - 1
src/main/frontend/state.cljs

@@ -2,7 +2,7 @@
   "Provides main application state, fns associated to set and state based rum
   cursors"
   (:require [cljs-bean.core :as bean]
-            [cljs.core.async :as async :refer [<!]]
+            [cljs.core.async :as async :refer [<! >!]]
             [cljs.spec.alpha :as s]
             [clojure.string :as string]
             [dommy.core :as dom]
@@ -74,6 +74,9 @@
      :ui/navigation-item-collapsed?         {}
 
      ;; right sidebar
+     :ui/handbooks-open?                    false
+     :ui/help-open?                         false
+     :ui/fullscreen?                        false
      :ui/settings-open?                     false
      :ui/sidebar-open?                      false
      :ui/sidebar-width                      "40%"
@@ -285,6 +288,8 @@
      :graph/importing                       nil
      :graph/importing-state                 {}
 
+     :handbook/route-chan                   (async/chan (async/sliding-buffer 1))
+
      :whiteboard/onboarding-whiteboard?     (or (storage/get :ls-onboarding-whiteboard?) false)
      :whiteboard/onboarding-tour?           (or (storage/get :whiteboard-onboarding-tour?) false)
      :whiteboard/last-persisted-at          {}
@@ -2194,6 +2199,21 @@ Similar to re-frame subscriptions"
   []
   (storage/remove :user-groups))
 
+(defn handbook-open?
+  []
+  (:ui/handbooks-open? @state))
+
+(defn get-handbook-route-chan
+  []
+  (:handbook/route-chan @state))
+
+(defn open-handbook-pane!
+  [k]
+  (when-not (handbook-open?)
+    (set-state! :ui/handbooks-open? true))
+  (js/setTimeout #(async/go
+                    (>! (get-handbook-route-chan) k))))
+
 (defn set-page-properties-changed!
   [page-name]
   (when-not (string/blank? page-name)

+ 7 - 1
src/main/frontend/ui.cljs

@@ -64,6 +64,12 @@
    "purple"
    "gray"])
 
+(defn ->block-background-color
+ [color]
+ (if (some #{color} built-in-colors)
+   (str "var(--ls-highlight-color-" color ")")
+   color))
+
 (defn built-in-color?
   [color]
   (some #{color} built-in-colors))
@@ -1038,7 +1044,7 @@
            :as   option}]
   (let [klass (if-not intent ".bg-indigo-600.hover:bg-indigo-700.focus:border-indigo-700.active:bg-indigo-700.text-center" intent)
         klass (if background (string/replace klass "indigo" background) klass)
-        klass (if small? (str klass ".px-2.py-1") klass)
+        klass (if small? (str klass ".is-small") klass)
         klass (if large? (str klass ".text-base") klass)
         klass (if disabled? (str klass "disabled:opacity-75") klass)]
     [:button.ui__button

+ 3 - 3
src/main/frontend/ui.css

@@ -275,7 +275,7 @@ html.is-mobile {
 
 .ui__button {
   @apply inline-flex items-center px-3 py-2 border border-transparent
-  text-sm leading-4 font-medium rounded-md text-white
+  text-sm leading-4 font-medium rounded-[6px] text-white
   focus:outline-none transition ease-in-out duration-150;
 
   &:disabled {
@@ -325,8 +325,8 @@ html.is-mobile {
     border: 1px solid;
   }
 
-  &.p-1 {
-    padding: 0.25rem 0.5rem !important;
+  &.is-small {
+    @apply px-2.5 py-1;
   }
 }
 

+ 24 - 0
src/main/frontend/util.cljc

@@ -225,6 +225,13 @@
   [pred coll]
   (first (filter pred coll)))
 
+(defn find-index
+  "Find first index of an element in list"
+  [pred-or-val coll]
+  (let [pred (if (fn? pred-or-val) pred-or-val #(= pred-or-val %))]
+    (reduce-kv #(if (pred %3) (reduced %2) %1) -1
+               (cond-> coll (list? coll) (vec)))))
+
 ;; (defn format
 ;;   [fmt & args]
 ;;   (apply gstring/format fmt args))
@@ -1435,6 +1442,23 @@
       (fn [resolve]
         (load url resolve)))))
 
+#?(:cljs
+   (defn css-load$
+     ([url] (css-load$ url nil))
+     ([url id]
+      (p/create
+       (fn [resolve reject]
+         (let [id (str "css-load-" (or id url))]
+           (if-not (gdom/getElement id)
+             (let [^js link (js/document.createElement "link")]
+               (set! (.-id link) id)
+               (set! (.-rel link) "stylesheet")
+               (set! (.-href link) url)
+               (set! (.-onload link) resolve)
+               (set! (.-onerror link) reject)
+               (.append (.-head js/document) link))
+             (resolve))))))))
+
 #?(:cljs
    (defn copy-image-to-clipboard
      [src]

+ 8 - 0
src/resources/dicts/en.edn

@@ -17,6 +17,14 @@
  :on-boarding/tour-whiteboard-home-description "Whiteboards have their own section in the app where you can see them at a glance, create new ones or delete them easily."
  :on-boarding/tour-whiteboard-new "{1} Create new whiteboard"
  :on-boarding/tour-whiteboard-new-description "There are multiple ways of creating a new whiteboard. One of them is always right here in the dashboard."
+ :handbook/title "Help"
+ :handbook/topics "Topics"
+ :handbook/popular-topics "Popular topics"
+ :handbook/help-categories "Help categories"
+ :handbook/search "Search"
+ :handbook/home "Home"
+ :handbook/settings "Settings"
+ :handbook/close "Close"
  :on-boarding/tour-whiteboard-btn-next "Next"
  :on-boarding/tour-whiteboard-btn-back "Back"
  :on-boarding/tour-whiteboard-btn-finish "Finish"

+ 8 - 8
static/yarn.lock

@@ -2093,10 +2093,10 @@ electron-winstaller@^5.0.0:
     lodash.template "^4.2.2"
     temp "^0.9.0"
 
-electron@*, electron@24.6.3:
-  version "24.6.3"
-  resolved "https://registry.yarnpkg.com/electron/-/electron-24.6.3.tgz#fc41279a5ec7b0aa3d48128df61fa29ca8a21199"
-  integrity sha512-hWy2ot0987DRzhOxIyv9tgybd0yrAcc9MRFYZ+znjXgdmbvcSveXdcGKGdtpgw1EW/TKUonJMH3VfDNeAmdPUg==
+electron@*, electron@26.4.2:
+  version "26.4.2"
+  resolved "https://registry.yarnpkg.com/electron/-/electron-26.4.2.tgz#2f976a3c30558f09ced3f5876862b4c21172c02c"
+  integrity sha512-BOfQUOIvsq5NnssWOMqcZnA5M0ull620wvQoJq3WhXN1wJAsWu+cdjHvREyxnHbArPkV+F+x3YAi5Dt+UKoqhw==
   dependencies:
     "@electron/get" "^2.0.0"
     "@types/node" "^18.11.18"
@@ -3634,10 +3634,10 @@ nice-try@^1.0.4:
   resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
   integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
 
-node-abi@^3.0.0, node-abi@^3.3.0:
-  version "3.40.0"
-  resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz#51d8ed44534f70ff1357dfbc3a89717b1ceac1b4"
-  integrity sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==
+[email protected], node-abi@^3.0.0, node-abi@^3.3.0:
+  version "3.51.0"
+  resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.51.0.tgz#970bf595ef5a26a271307f8a4befa02823d4e87d"
+  integrity sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==
   dependencies:
     semver "^7.3.5"
 

+ 28 - 14
tldraw/cljs-demo/yarn.lock

@@ -30,11 +30,16 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
   integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
 
-bn.js@^5.0.0, bn.js@^5.1.1:
+bn.js@^5.0.0:
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
   integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
 
+bn.js@^5.2.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
+  integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
+
 brorand@^1.0.1, brorand@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@@ -71,7 +76,7 @@ browserify-des@^1.0.0:
     inherits "^2.0.1"
     safe-buffer "^5.1.2"
 
-browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+browserify-rsa@^4.0.0, browserify-rsa@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
   integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
@@ -80,19 +85,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
     randombytes "^2.0.1"
 
 browserify-sign@^4.0.0:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
-  integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e"
+  integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==
   dependencies:
-    bn.js "^5.1.1"
-    browserify-rsa "^4.0.1"
+    bn.js "^5.2.1"
+    browserify-rsa "^4.1.0"
     create-hash "^1.2.0"
     create-hmac "^1.1.7"
-    elliptic "^6.5.3"
+    elliptic "^6.5.4"
     inherits "^2.0.4"
-    parse-asn1 "^5.1.5"
-    readable-stream "^3.6.0"
-    safe-buffer "^5.2.0"
+    parse-asn1 "^5.1.6"
+    readable-stream "^3.6.2"
+    safe-buffer "^5.2.1"
 
 browserify-zlib@^0.2.0:
   version "0.2.0"
@@ -213,7 +218,7 @@ domain-browser@^1.1.1:
   resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
   integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
 
-elliptic@^6.5.3:
+elliptic@^6.5.3, elliptic@^6.5.4:
   version "6.5.4"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
   integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
@@ -383,7 +388,7 @@ pako@~1.0.5:
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
   integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
 
-parse-asn1@^5.0.0, parse-asn1@^5.1.5:
+parse-asn1@^5.0.0, parse-asn1@^5.1.6:
   version "5.1.6"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
   integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
@@ -506,6 +511,15 @@ readable-stream@^3.6.0:
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
+readable-stream@^3.6.2:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
 readline-sync@^1.4.7:
   version "1.4.10"
   resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
@@ -519,7 +533,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^3.0.0"
     inherits "^2.0.1"
 
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==

+ 142 - 65
tldraw/yarn.lock

@@ -17,6 +17,14 @@
   dependencies:
     "@babel/highlight" "^7.18.6"
 
+"@babel/code-frame@^7.22.13":
+  version "7.22.13"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+  integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
+  dependencies:
+    "@babel/highlight" "^7.22.13"
+    chalk "^2.4.2"
+
 "@babel/compat-data@^7.20.0":
   version "7.20.1"
   resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
@@ -43,16 +51,7 @@
     json5 "^2.2.1"
     semver "^6.3.0"
 
-"@babel/generator@^7.19.0":
-  version "7.19.0"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a"
-  integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==
-  dependencies:
-    "@babel/types" "^7.19.0"
-    "@jridgewell/gen-mapping" "^0.3.2"
-    jsesc "^2.5.1"
-
-"@babel/generator@^7.20.1", "@babel/generator@^7.20.2":
+"@babel/generator@^7.20.2":
   version "7.20.4"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8"
   integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==
@@ -61,6 +60,16 @@
     "@jridgewell/gen-mapping" "^0.3.2"
     jsesc "^2.5.1"
 
+"@babel/generator@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+  integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+  dependencies:
+    "@babel/types" "^7.23.0"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
 "@babel/helper-annotate-as-pure@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
@@ -96,6 +105,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
   integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
 
+"@babel/helper-environment-visitor@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+  integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
 "@babel/helper-function-name@^7.19.0":
   version "7.19.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
@@ -104,12 +118,20 @@
     "@babel/template" "^7.18.10"
     "@babel/types" "^7.19.0"
 
-"@babel/helper-hoist-variables@^7.18.6":
-  version "7.18.6"
-  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
-  integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
+"@babel/helper-function-name@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+  integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
   dependencies:
-    "@babel/types" "^7.18.6"
+    "@babel/template" "^7.22.15"
+    "@babel/types" "^7.23.0"
+
+"@babel/helper-hoist-variables@^7.22.5":
+  version "7.22.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
+  integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
+  dependencies:
+    "@babel/types" "^7.22.5"
 
 "@babel/helper-member-expression-to-functions@^7.18.9":
   version "7.18.9"
@@ -181,6 +203,13 @@
   dependencies:
     "@babel/types" "^7.18.6"
 
+"@babel/helper-split-export-declaration@^7.22.6":
+  version "7.22.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
+  integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
+  dependencies:
+    "@babel/types" "^7.22.5"
+
 "@babel/helper-string-parser@^7.18.10":
   version "7.18.10"
   resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
@@ -191,6 +220,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
   integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
 
+"@babel/helper-string-parser@^7.22.5":
+  version "7.22.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
+  integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+
 "@babel/helper-validator-identifier@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
@@ -201,6 +235,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
   integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
 
+"@babel/helper-validator-identifier@^7.22.20":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+  integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
 "@babel/helper-validator-option@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
@@ -224,21 +263,30 @@
     chalk "^2.0.0"
     js-tokens "^4.0.0"
 
+"@babel/highlight@^7.22.13":
+  version "7.22.20"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
+  integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.22.20"
+    chalk "^2.4.2"
+    js-tokens "^4.0.0"
+
 "@babel/parser@^7.18.10":
   version "7.18.11"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9"
   integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==
 
-"@babel/parser@^7.19.1":
-  version "7.19.1"
-  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
-  integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
-
-"@babel/parser@^7.20.1", "@babel/parser@^7.20.2":
+"@babel/parser@^7.20.2":
   version "7.20.3"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2"
   integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==
 
+"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+  integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
 "@babel/plugin-proposal-decorators@^7.20.2":
   version "7.20.2"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.2.tgz#1c6c32b2a44b154ebeec2bb534f9eaebdb541fb6"
@@ -323,35 +371,28 @@
     "@babel/parser" "^7.18.10"
     "@babel/types" "^7.18.10"
 
-"@babel/traverse@^7.19.1":
-  version "7.19.1"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347"
-  integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==
-  dependencies:
-    "@babel/code-frame" "^7.18.6"
-    "@babel/generator" "^7.19.0"
-    "@babel/helper-environment-visitor" "^7.18.9"
-    "@babel/helper-function-name" "^7.19.0"
-    "@babel/helper-hoist-variables" "^7.18.6"
-    "@babel/helper-split-export-declaration" "^7.18.6"
-    "@babel/parser" "^7.19.1"
-    "@babel/types" "^7.19.0"
-    debug "^4.1.0"
-    globals "^11.1.0"
-
-"@babel/traverse@^7.20.1":
-  version "7.20.1"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8"
-  integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==
-  dependencies:
-    "@babel/code-frame" "^7.18.6"
-    "@babel/generator" "^7.20.1"
-    "@babel/helper-environment-visitor" "^7.18.9"
-    "@babel/helper-function-name" "^7.19.0"
-    "@babel/helper-hoist-variables" "^7.18.6"
-    "@babel/helper-split-export-declaration" "^7.18.6"
-    "@babel/parser" "^7.20.1"
-    "@babel/types" "^7.20.0"
+"@babel/template@^7.22.15":
+  version "7.22.15"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+  integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
+  dependencies:
+    "@babel/code-frame" "^7.22.13"
+    "@babel/parser" "^7.22.15"
+    "@babel/types" "^7.22.15"
+
+"@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1":
+  version "7.23.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+  integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
+  dependencies:
+    "@babel/code-frame" "^7.22.13"
+    "@babel/generator" "^7.23.0"
+    "@babel/helper-environment-visitor" "^7.22.20"
+    "@babel/helper-function-name" "^7.23.0"
+    "@babel/helper-hoist-variables" "^7.22.5"
+    "@babel/helper-split-export-declaration" "^7.22.6"
+    "@babel/parser" "^7.23.0"
+    "@babel/types" "^7.23.0"
     debug "^4.1.0"
     globals "^11.1.0"
 
@@ -382,6 +423,15 @@
     "@babel/helper-validator-identifier" "^7.19.1"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+  integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+  dependencies:
+    "@babel/helper-string-parser" "^7.22.5"
+    "@babel/helper-validator-identifier" "^7.22.20"
+    to-fast-properties "^2.0.0"
+
 "@esbuild/[email protected]":
   version "0.15.14"
   resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.14.tgz#5d0027f920eeeac313c01fd6ecb8af50c306a466"
@@ -497,6 +547,11 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
   integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
 
+"@jridgewell/resolve-uri@^3.1.0":
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+  integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
 "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
@@ -507,6 +562,19 @@
   resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
   integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
 
+"@jridgewell/sourcemap-codec@^1.4.14":
+  version "1.4.15"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.17":
+  version "0.3.20"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
+  integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
+  dependencies:
+    "@jridgewell/resolve-uri" "^3.1.0"
+    "@jridgewell/sourcemap-codec" "^1.4.14"
+
 "@jridgewell/trace-mapping@^0.3.9":
   version "0.3.15"
   resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"
@@ -1632,7 +1700,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
   integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
 
-bn.js@^5.0.0, bn.js@^5.1.1:
+bn.js@^5.0.0, bn.js@^5.2.1:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
   integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
@@ -1688,7 +1756,7 @@ browserify-des@^1.0.0:
     inherits "^2.0.1"
     safe-buffer "^5.1.2"
 
-browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+browserify-rsa@^4.0.0, browserify-rsa@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
   integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
@@ -1697,19 +1765,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
     randombytes "^2.0.1"
 
 browserify-sign@^4.0.0:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
-  integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e"
+  integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==
   dependencies:
-    bn.js "^5.1.1"
-    browserify-rsa "^4.0.1"
+    bn.js "^5.2.1"
+    browserify-rsa "^4.1.0"
     create-hash "^1.2.0"
     create-hmac "^1.1.7"
-    elliptic "^6.5.3"
+    elliptic "^6.5.4"
     inherits "^2.0.4"
-    parse-asn1 "^5.1.5"
-    readable-stream "^3.6.0"
-    safe-buffer "^5.2.0"
+    parse-asn1 "^5.1.6"
+    readable-stream "^3.6.2"
+    safe-buffer "^5.2.1"
 
 browserify-zlib@^0.2.0:
   version "0.2.0"
@@ -1789,7 +1857,7 @@ caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795"
   integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==
 
-chalk@^2.0.0:
+chalk@^2.0.0, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
   integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2166,7 +2234,7 @@ electron-to-chromium@^1.4.251:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
   integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
 
-elliptic@^6.5.3:
+elliptic@^6.5.3, elliptic@^6.5.4:
   version "6.5.4"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
   integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
@@ -3752,7 +3820,7 @@ parent-module@^1.0.0:
   dependencies:
     callsites "^3.0.0"
 
-parse-asn1@^5.0.0, parse-asn1@^5.1.5:
+parse-asn1@^5.0.0, parse-asn1@^5.1.6:
   version "5.1.6"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
   integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
@@ -4142,6 +4210,15 @@ readable-stream@^3.6.0:
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
+readable-stream@^3.6.2:
+  version "3.6.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
 readdirp@~3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@@ -4261,7 +4338,7 @@ sade@^1.7.3:
   dependencies:
     mri "^1.1.0"
 
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==

+ 57 - 33
yarn.lock

@@ -62,6 +62,16 @@
     "@jridgewell/trace-mapping" "^0.3.17"
     jsesc "^2.5.1"
 
+"@babel/generator@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+  integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+  dependencies:
+    "@babel/types" "^7.23.0"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    "@jridgewell/trace-mapping" "^0.3.17"
+    jsesc "^2.5.1"
+
 "@babel/helper-compilation-targets@^7.22.15":
   version "7.22.15"
   resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
@@ -78,13 +88,13 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
   integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
 
-"@babel/helper-function-name@^7.22.5":
-  version "7.22.5"
-  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
-  integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
+"@babel/helper-function-name@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+  integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
   dependencies:
-    "@babel/template" "^7.22.5"
-    "@babel/types" "^7.22.5"
+    "@babel/template" "^7.22.15"
+    "@babel/types" "^7.23.0"
 
 "@babel/helper-hoist-variables@^7.22.5":
   version "7.22.5"
@@ -163,6 +173,11 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
   integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==
 
+"@babel/parser@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+  integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
 "@babel/[email protected]":
   version "7.11.2"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
@@ -177,7 +192,7 @@
   dependencies:
     regenerator-runtime "^0.14.0"
 
-"@babel/template@^7.22.15", "@babel/template@^7.22.5":
+"@babel/template@^7.22.15":
   version "7.22.15"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
   integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
@@ -187,18 +202,18 @@
     "@babel/types" "^7.22.15"
 
 "@babel/traverse@^7.22.15", "@babel/traverse@^7.22.20":
-  version "7.22.20"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.20.tgz#db572d9cb5c79e02d83e5618b82f6991c07584c9"
-  integrity sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==
+  version "7.23.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+  integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
   dependencies:
     "@babel/code-frame" "^7.22.13"
-    "@babel/generator" "^7.22.15"
+    "@babel/generator" "^7.23.0"
     "@babel/helper-environment-visitor" "^7.22.20"
-    "@babel/helper-function-name" "^7.22.5"
+    "@babel/helper-function-name" "^7.23.0"
     "@babel/helper-hoist-variables" "^7.22.5"
     "@babel/helper-split-export-declaration" "^7.22.6"
-    "@babel/parser" "^7.22.16"
-    "@babel/types" "^7.22.19"
+    "@babel/parser" "^7.23.0"
+    "@babel/types" "^7.23.0"
     debug "^4.1.0"
     globals "^11.1.0"
 
@@ -211,6 +226,15 @@
     "@babel/helper-validator-identifier" "^7.22.19"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.23.0":
+  version "7.23.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+  integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+  dependencies:
+    "@babel/helper-string-parser" "^7.22.5"
+    "@babel/helper-validator-identifier" "^7.22.20"
+    to-fast-properties "^2.0.0"
+
 "@capacitor/android@^5.0.0":
   version "5.4.1"
   resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-5.4.1.tgz#5b0445202ca5e48fcb79d0c88e4403acc32504bc"
@@ -1467,7 +1491,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
   integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
 
-bn.js@^5.0.0, bn.js@^5.1.1:
+bn.js@^5.0.0, bn.js@^5.2.1:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
   integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
@@ -1563,7 +1587,7 @@ browserify-des@^1.0.0:
     inherits "^2.0.1"
     safe-buffer "^5.1.2"
 
-browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+browserify-rsa@^4.0.0, browserify-rsa@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d"
   integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==
@@ -1572,19 +1596,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
     randombytes "^2.0.1"
 
 browserify-sign@^4.0.0:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
-  integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e"
+  integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==
   dependencies:
-    bn.js "^5.1.1"
-    browserify-rsa "^4.0.1"
+    bn.js "^5.2.1"
+    browserify-rsa "^4.1.0"
     create-hash "^1.2.0"
     create-hmac "^1.1.7"
-    elliptic "^6.5.3"
+    elliptic "^6.5.4"
     inherits "^2.0.4"
-    parse-asn1 "^5.1.5"
-    readable-stream "^3.6.0"
-    safe-buffer "^5.2.0"
+    parse-asn1 "^5.1.6"
+    readable-stream "^3.6.2"
+    safe-buffer "^5.2.1"
 
 browserify-zlib@^0.2.0:
   version "0.2.0"
@@ -2643,10 +2667,10 @@ electron-to-chromium@^1.4.526:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.528.tgz#7c900fd73d9d2e8bb0dab0e301f25f0f4776ef2c"
   integrity sha512-UdREXMXzLkREF4jA8t89FQjA8WHI6ssP38PMY4/4KhXFQbtImnghh4GkCgrtiZwLKUKVD2iTVXvDVQjfomEQuA==
 
-electron@24.6.3:
-  version "24.6.3"
-  resolved "https://registry.yarnpkg.com/electron/-/electron-24.6.3.tgz#fc41279a5ec7b0aa3d48128df61fa29ca8a21199"
-  integrity sha512-hWy2ot0987DRzhOxIyv9tgybd0yrAcc9MRFYZ+znjXgdmbvcSveXdcGKGdtpgw1EW/TKUonJMH3VfDNeAmdPUg==
+electron@26.4.2:
+  version "26.4.2"
+  resolved "https://registry.yarnpkg.com/electron/-/electron-26.4.2.tgz#2f976a3c30558f09ced3f5876862b4c21172c02c"
+  integrity sha512-BOfQUOIvsq5NnssWOMqcZnA5M0ull620wvQoJq3WhXN1wJAsWu+cdjHvREyxnHbArPkV+F+x3YAi5Dt+UKoqhw==
   dependencies:
     "@electron/get" "^2.0.0"
     "@types/node" "^18.11.18"
@@ -2666,7 +2690,7 @@ elementtree@^0.1.7:
   dependencies:
     sax "1.1.4"
 
-elliptic@^6.5.3:
+elliptic@^6.5.3, elliptic@^6.5.4:
   version "6.5.4"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
   integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
@@ -5405,7 +5429,7 @@ parent-module@^1.0.0:
   dependencies:
     callsites "^3.0.0"
 
-parse-asn1@^5.0.0, parse-asn1@^5.1.5:
+parse-asn1@^5.0.0, parse-asn1@^5.1.6:
   version "5.1.6"
   resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4"
   integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==
@@ -6455,7 +6479,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.6.0:
+"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.6.0, readable-stream@^3.6.2:
   version "3.6.2"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
   integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
@@ -6753,7 +6777,7 @@ safe-array-concat@^1.0.1:
     has-symbols "^1.0.3"
     isarray "^2.0.5"
 
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff