web: redesign auth pages (#10107)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> web: auth pages design fixes Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> web: minor ui fixes web: update button text in auth container Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> web: define & use new button variants Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> web: enhance MFA code component styling and layout Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> theme: set button's line height to 100% for new variants Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> web: retain email/password field data when navigating back from mfa screens Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
45769
apps/web/package-lock.json
generated
@@ -31,6 +31,7 @@
|
||||
"@notesnook/themes-server": "file:../../servers/themes",
|
||||
"@notesnook/ui": "file:../../packages/ui",
|
||||
"@notesnook/web-clipper": "file:../../extensions/web-clipper",
|
||||
"@notesnook/icons": "file:../../packages/icons",
|
||||
"@paddle/paddle-js": "^1.4.2",
|
||||
"@react-pdf-viewer/core": "^3.12.0",
|
||||
"@react-pdf-viewer/toolbar": "^3.12.0",
|
||||
|
||||
26
apps/web/src/assets/auth/capa-green.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 1037.43 399.406" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Capa 1">
|
||||
<path id="Vector" d="M89.0592 387.435C265.408 309.423 325.587 223.39 347.396 158.124C371.734 85.2836 359.183 5.67247 385.456 0.728544C402.279 -2.43832 422.979 27.2894 461.571 92.456C578.604 290.066 581.254 342.543 631.115 356.164C700.964 375.257 744.023 285.431 851.39 287.367C930.248 288.792 994.059 338.806 1037.07 383.264" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_2" d="M84.8244 379.593C256.208 303.26 319.843 219.634 343.382 158.466C369.687 90.1088 357.264 14.61 383.263 11.0393C399.978 8.74193 420.289 37.9612 457.568 100.895C570.86 292.121 574.374 345.252 623.852 358.2C694.106 376.326 735.288 280.002 843.794 278.691C846.159 278.662 848.488 278.662 850.82 278.719C927.806 280.655 992.527 330.693 1036.46 374.877" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_3" d="M80.6032 371.75C247.008 297.104 314.05 216.027 339.379 158.812C367.61 95.0379 355.364 23.5566 381.082 21.3542C397.694 19.9288 417.619 48.642 453.573 109.34C563.101 294.173 567.459 348.128 616.608 360.235C687.204 377.625 726.593 274.525 836.216 270.011C838.621 269.912 841.018 269.812 843.415 269.824C921.673 270.213 989.759 321.285 1035.86 366.488" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_4" d="M76.3728 363.908C237.823 290.928 308.167 212.595 335.37 159.159C365.449 100.072 353.467 32.511 378.891 31.6723C395.409 31.1259 414.924 59.3212 449.571 117.784C555.348 296.245 560.568 350.911 609.357 362.271C680.329 378.797 717.905 269.009 828.631 261.333C831.089 261.162 833.544 260.998 835.991 260.927C915.516 258.632 986.972 311.875 1035.24 358.095" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_5" d="M72.1436 356.066C228.628 284.773 302.166 209.345 331.359 159.507C363.165 105.209 351.583 41.4751 376.704 41.9906C393.13 42.3256 412.24 70.003 445.573 126.23C547.596 298.307 553.682 353.686 602.108 364.305C673.477 379.957 709.228 263.453 821.048 252.645C823.558 252.408 826.071 252.17 828.592 252.023C909.379 247.647 984.204 302.46 1034.65 349.706" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_6" d="M67.914 348.223C219.436 278.614 296.012 206.292 327.355 159.855C360.707 110.44 349.698 50.4453 374.522 52.3055C390.862 53.5314 409.559 80.6814 441.578 134.675C539.852 300.369 546.805 356.451 594.863 366.341C666.624 381.106 700.559 257.857 813.469 243.973C816.035 243.657 818.6 243.337 821.187 243.132C903.233 236.694 981.444 293.056 1034.05 341.324" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_7" d="M63.6879 340.381C210.242 272.449 289.659 203.434 323.342 160.202C357.995 115.723 347.83 59.4279 372.331 62.6232C388.589 64.7424 406.87 91.3698 437.572 143.118C532.096 302.428 539.924 359.209 587.609 368.374C659.777 382.246 691.882 252.229 805.881 235.295C808.51 234.905 811.123 234.506 813.767 234.237C897.067 225.751 978.661 283.653 1033.43 332.935" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_8" d="M59.4588 332.539C201.047 266.286 275.265 193.795 319.334 160.549C346.024 115.631 345.959 68.4227 370.144 72.939C386.32 75.9609 404.187 102.042 433.575 151.576C524.345 304.503 533.048 361.97 580.36 370.422C652.932 383.387 683.208 246.58 798.296 226.628C800.972 226.165 803.65 225.69 806.36 225.352C890.919 214.84 975.904 274.25 1032.84 324.559" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_9" d="M55.2298 324.697C191.856 260.124 268.079 189.565 315.325 160.896C342.353 119.967 344.087 77.4294 367.958 83.2571C384.055 87.1866 401.501 112.716 429.574 160.01C516.58 306.553 526.177 364.7 573.113 372.447C646.093 384.492 674.532 240.876 790.713 217.938C793.441 217.399 796.175 216.848 798.951 216.444C884.768 203.921 973.12 264.83 1032.23 316.158" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_10" d="M50.9997 316.854C182.66 253.961 260.889 185.338 311.313 161.243C338.677 124.3 342.215 86.4452 365.77 93.5724C381.786 98.4166 398.816 123.398 425.573 168.453C508.841 308.622 519.308 367.429 565.863 374.478C639.258 385.594 665.846 235.155 783.128 209.255C785.909 208.642 788.701 208.017 791.54 207.544C878.617 193.023 970.347 255.418 1031.63 307.767" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_11" d="M46.7726 309.012C173.47 247.798 253.703 181.109 307.305 161.592C335.005 128.638 340.341 95.4751 363.58 103.89C379.514 109.658 396.132 134.081 421.574 176.892C501.089 310.67 512.442 370.147 558.613 376.509C632.423 386.68 657.156 229.405 775.544 200.571C778.381 199.88 781.227 199.186 784.127 198.642C872.471 182.137 967.573 246.005 1031.02 299.373" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_12" d="M42.5431 301.168C164.27 241.639 246.521 176.88 303.298 161.949C331.335 132.984 338.464 104.52 361.39 114.218C377.238 120.917 393.446 144.77 417.571 185.355C493.334 312.749 505.573 372.877 551.366 378.56C625.597 387.775 648.458 223.661 767.961 191.909C770.852 191.142 773.744 190.375 776.717 189.771C866.328 171.293 964.8 236.619 1030.42 291.009" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_13" d="M38.3144 293.325C155.079 235.475 239.325 172.651 299.288 162.286C327.661 137.31 336.575 113.557 359.207 124.523C374.962 132.159 390.763 155.441 413.574 193.791C485.597 314.801 498.713 375.573 544.114 380.586C618.766 388.827 639.745 217.859 760.378 183.221C763.32 182.375 766.279 181.539 769.315 180.857C860.199 160.426 962.035 227.184 1029.82 282.605" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_14" d="M34.0934 285.483C145.884 229.313 232.136 168.425 295.28 162.638C323.987 141.651 334.68 122.609 357.02 134.842C372.681 143.418 388.079 166.121 409.576 202.234C477.838 316.864 491.851 378.277 536.865 382.622C611.943 389.878 631.023 212.044 752.793 174.543C755.789 173.619 758.807 172.711 761.898 171.96C854.056 149.571 959.255 217.784 1029.22 274.217" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_15" d="M29.858 277.64C136.689 223.15 224.949 164.196 291.271 162.982C320.314 145.983 332.779 131.662 354.832 145.164C370.391 154.683 385.395 176.804 405.564 210.684C470.075 318.93 484.976 380.963 529.604 384.66C605.105 390.915 622.28 206.242 745.198 165.866C748.247 164.866 751.323 163.889 754.474 163.067C847.918 138.735 956.47 208.38 1028.6 265.832" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_16" d="M25.6291 269.798C127.495 216.988 217.76 159.967 287.26 163.329C316.642 150.319 330.868 140.721 352.646 155.475C368.097 165.942 382.709 187.481 401.577 219.126C462.334 320.986 478.124 383.639 522.368 386.692C598.292 391.93 613.548 200.395 737.625 157.195C740.727 156.116 743.86 155.071 747.088 154.18C841.804 127.9 953.708 198.965 1028 257.43" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_17" d="M21.3996 261.956C118.302 210.827 210.571 155.748 283.251 163.676C312.954 154.648 328.949 149.785 350.459 165.793C365.794 177.208 380.025 198.16 397.576 227.562C454.582 323.038 471.26 386.302 515.118 388.716C591.466 392.921 604.793 194.537 730.042 148.495C733.196 147.336 736.387 146.224 739.665 145.262C835.685 117.076 950.943 189.557 1027.4 249.051" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_18" d="M17.1708 254.104C109.108 204.656 203.382 151.503 279.24 164.016C309.293 158.982 327.023 158.837 348.267 176.099C363.487 188.453 377.339 208.83 393.573 236.006C446.828 325.096 464.395 388.966 507.867 390.752C584.64 393.917 596.027 188.686 722.459 139.831C725.663 138.591 728.915 137.413 732.253 136.379C829.574 106.262 948.162 180.152 1026.79 240.674" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_19" d="M12.9426 246.264C99.9119 198.511 195.195 177.113 275.233 164.372C305.183 159.604 325.092 167.909 346.081 186.426C361.177 199.73 374.657 219.52 389.576 244.46C439.078 327.172 457.531 391.631 500.618 392.797C577.809 394.885 587.248 182.812 714.874 131.145C718.128 129.828 721.446 128.581 724.842 127.476C823.463 95.4443 945.38 170.739 1026.19 232.273" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_20" d="M8.71306 238.424C90.7248 192.335 187.194 149.742 271.224 164.714C301.537 170.117 323.152 176.966 343.894 196.739C358.861 210.994 371.97 230.194 385.576 252.902C431.329 329.23 450.662 394.273 493.369 394.826C570.975 395.834 578.458 176.928 707.288 122.462C710.597 121.065 713.972 119.758 717.432 118.577C817.433 84.8155 942.614 161.329 1025.59 223.884" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_21" d="M4.4838 230.584C81.5249 186.174 180.654 142.149 267.216 165.063C297.92 173.193 321.207 186.029 341.707 207.057C356.54 222.262 369.286 240.878 381.575 261.347C423.577 331.294 443.794 397.081 486.119 396.864C564.138 396.465 569.566 170.874 699.704 113.785C703.06 112.303 706.498 110.935 710.019 109.682C811.304 73.9249 939.841 151.918 1024.98 215.493" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
<path id="Vector_22" d="M0.254973 222.744C72.3307 180.016 174.627 134.604 263.205 165.415C396.737 211.87 408.29 399.994 478.873 398.901C559.333 397.656 560.979 152.919 702.61 100.788C805.172 63.0371 937.079 142.511 1024.38 207.109" stroke="var(--stroke-0, #008836)" stroke-opacity="0.16" stroke-miterlimit="10"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
BIN
apps/web/src/assets/auth/notesnook-phone.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
@@ -84,11 +84,7 @@ const routes = {
|
||||
},
|
||||
"/login": {
|
||||
component: () => import("./views/auth"),
|
||||
props: { route: "login:email" }
|
||||
},
|
||||
"/login/password": {
|
||||
component: () => import("./views/auth"),
|
||||
props: { route: "login:email" }
|
||||
props: { route: "login" }
|
||||
},
|
||||
"/recover": {
|
||||
component: () => import("./views/auth"),
|
||||
@@ -96,11 +92,11 @@ const routes = {
|
||||
},
|
||||
"/login/mfa/code": {
|
||||
component: () => import("./views/auth"),
|
||||
props: { route: "login:email" }
|
||||
props: { route: "login" }
|
||||
},
|
||||
"/login/mfa/select": {
|
||||
component: () => import("./views/auth"),
|
||||
props: { route: "login:email" }
|
||||
props: { route: "login" }
|
||||
},
|
||||
default: { component: () => import("./app"), props: null }
|
||||
} as const;
|
||||
@@ -111,8 +107,7 @@ const sessionExpiryExceptions: Routes[] = [
|
||||
"/account/recovery",
|
||||
"/sessionexpired",
|
||||
"/login/mfa/code",
|
||||
"/login/mfa/select",
|
||||
"/login/password"
|
||||
"/login/mfa/select"
|
||||
];
|
||||
|
||||
function getRoute(): RouteWithPath<AuthProps> | RouteWithPath {
|
||||
|
||||
283
apps/web/src/common/theme.ts
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ThemeDefinition } from "@notesnook/theme";
|
||||
|
||||
export const THEME_LIGHT: any = {
|
||||
$schema:
|
||||
"https://raw.githubusercontent.com/streetwriters/notesnook-themes/main/schemas/v1.schema.json",
|
||||
name: "Notesnook Light",
|
||||
id: "default-light",
|
||||
version: 2.1,
|
||||
license: "GPL-3.0-or-later",
|
||||
homepage: "https://notesnook.com",
|
||||
description: "The default light theme for Notesnook app.",
|
||||
colorScheme: "light",
|
||||
codeBlockCSS: ``,
|
||||
compatibilityVersion: 1,
|
||||
authors: [
|
||||
{
|
||||
name: "Streetwriters",
|
||||
email: "support@streetwriters.co",
|
||||
url: "https://streetwriters.co"
|
||||
}
|
||||
],
|
||||
scopes: {
|
||||
base: {
|
||||
primary: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#5b5b5b",
|
||||
background: "#ffffff",
|
||||
border: "#E2E2E2",
|
||||
heading: "#181818",
|
||||
icon: "#181818",
|
||||
separator: "#F0F0F0",
|
||||
placeholder: "#858585",
|
||||
hover: "#eee",
|
||||
backdrop: "#0000001a",
|
||||
buttonForeground: "#181818"
|
||||
},
|
||||
secondary: {
|
||||
accent: "#0D9E46",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#858585",
|
||||
background: "#F7F7F7",
|
||||
border: "#EFEFEF",
|
||||
heading: "#4B4B4B",
|
||||
icon: "#666666",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#999999",
|
||||
hover: "#dbdbdb",
|
||||
backdrop: "#0000001a",
|
||||
buttonForeground: "#181818"
|
||||
},
|
||||
tertiary: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#777",
|
||||
background: "#ECECEC",
|
||||
border: "#E8E8E8",
|
||||
heading: "#666",
|
||||
icon: "#777",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#a9a9a9",
|
||||
hover: "#dbdbdb",
|
||||
backdrop: "#0000001a"
|
||||
},
|
||||
disabled: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#A6A6A6",
|
||||
background: "#ffffff",
|
||||
border: "#E8E8E8",
|
||||
heading: "#212121",
|
||||
icon: "#DADADA",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#a9a9a9",
|
||||
hover: "#00000010",
|
||||
backdrop: "#0000001a"
|
||||
},
|
||||
selected: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#181818",
|
||||
background: "#E2EDE6",
|
||||
border: "#008836",
|
||||
heading: "#212121",
|
||||
icon: "#181818",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#a9a9a9",
|
||||
hover: "#eee",
|
||||
backdrop: "#0000001a"
|
||||
},
|
||||
error: {
|
||||
accent: "#f54b42",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#FF242E",
|
||||
background: "#FFEDEE",
|
||||
border: "#F7999D",
|
||||
heading: "#f54b42",
|
||||
icon: "#FB2C36",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#a9a9a9",
|
||||
hover: "#00000010",
|
||||
backdrop: "#0000001a"
|
||||
},
|
||||
success: {
|
||||
accent: "#4F8A10",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#4F8A10",
|
||||
background: "#85ce68",
|
||||
border: "#E8E8E8",
|
||||
heading: "#4F8A10",
|
||||
icon: "#4F8A10",
|
||||
separator: "#E8E8E8",
|
||||
placeholder: "#a9a9a9",
|
||||
hover: "#00000010",
|
||||
backdrop: "#0000001a"
|
||||
}
|
||||
},
|
||||
statusBar: {
|
||||
primary: { paragraph: "#5E5E5E", background: "#f7f7f7" }
|
||||
},
|
||||
navigationMenu: {
|
||||
primary: {
|
||||
background: "#f7f7f7",
|
||||
paragraph: "#666",
|
||||
icon: "#666",
|
||||
hover: "#eee"
|
||||
},
|
||||
secondary: { background: "#EEEEEE" },
|
||||
selected: {
|
||||
background: "#00883610",
|
||||
hover: "#eee"
|
||||
}
|
||||
},
|
||||
contextMenu: { primary: { background: "#f7f7f7" } },
|
||||
editor: { selected: { background: "#e1e1e1" } },
|
||||
sheet: { selected: { paragraph: "#008836" } },
|
||||
list: {
|
||||
secondary: {
|
||||
heading: "#A6A6A6"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const THEME_DARK: any = {
|
||||
name: "Notesnook Dark",
|
||||
id: "default-dark",
|
||||
version: 2.1,
|
||||
license: "GPL-3.0-or-later",
|
||||
homepage: "https://notesnook.com",
|
||||
description: "The default dark theme for the Notesnook app",
|
||||
colorScheme: "dark",
|
||||
codeBlockCSS: ``,
|
||||
compatibilityVersion: 1,
|
||||
authors: [
|
||||
{
|
||||
name: "Streetwriters",
|
||||
email: "support@streetwriters.co",
|
||||
url: "https://streetwriters.co"
|
||||
}
|
||||
],
|
||||
scopes: {
|
||||
base: {
|
||||
primary: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#F2F2F2",
|
||||
background: "#181818",
|
||||
border: "#2A2A2A",
|
||||
heading: "#FFFFFF",
|
||||
icon: "#FFFFFF",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#2b2b2b",
|
||||
backdrop: "#35353580",
|
||||
buttonForeground: "#FFFFFF"
|
||||
},
|
||||
secondary: {
|
||||
accent: "#0D9E46",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#A1A1A1",
|
||||
background: "#252525",
|
||||
border: "#0A5729",
|
||||
heading: "#C0BFBF",
|
||||
icon: "#808080",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580",
|
||||
buttonForeground: "#BFBFBF"
|
||||
},
|
||||
tertiary: {
|
||||
accent: "#0D9E46",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#818589",
|
||||
background: "#2C2C2C",
|
||||
border: "#2b2b2b",
|
||||
heading: "#808080",
|
||||
icon: "#808080",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580"
|
||||
},
|
||||
disabled: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#505050",
|
||||
background: "#ffffff",
|
||||
border: "#383838",
|
||||
heading: "#212121",
|
||||
icon: "#FFFFFF",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580"
|
||||
},
|
||||
selected: {
|
||||
accent: "#008836",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#FBFBFB",
|
||||
background: "#494949",
|
||||
border: "#008836",
|
||||
heading: "#e3e3e3",
|
||||
icon: "#008836",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580"
|
||||
},
|
||||
error: {
|
||||
accent: "#f54b42",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#f54b42",
|
||||
background: "#250b0a",
|
||||
border: "#F7999D",
|
||||
heading: "#f54b42",
|
||||
icon: "#f54b42",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580"
|
||||
},
|
||||
success: {
|
||||
accent: "#4F8A10",
|
||||
accentForeground: "#ffffff",
|
||||
paragraph: "#4F8A10",
|
||||
background: "#132204",
|
||||
border: "#383838",
|
||||
heading: "#4F8A10",
|
||||
icon: "#4F8A10",
|
||||
separator: "#383838",
|
||||
placeholder: "#404040",
|
||||
hover: "#ffffff10",
|
||||
backdrop: "#35353580"
|
||||
}
|
||||
},
|
||||
list: { selected: { background: "#202020" } },
|
||||
contextMenu: { primary: { background: "#202020" } },
|
||||
sheet: { selected: { paragraph: "#008836" } }
|
||||
},
|
||||
$schema:
|
||||
"https://raw.githubusercontent.com/streetwriters/notesnook-themes/main/schemas/v1.schema.json"
|
||||
};
|
||||
@@ -26,244 +26,141 @@ import Cameron from "../../assets/testimonials/cameron.jpg";
|
||||
import { hosts } from "@notesnook/core";
|
||||
import { SettingsDialog } from "../../dialogs/settings";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
username: "HolensteinDan",
|
||||
image: Holenstein,
|
||||
name: "Dan Holenstein",
|
||||
link: "https://twitter.com/HolensteinDan/status/1439728355935342592",
|
||||
text: "@notesnook app is what @evernote should have become long ago. And they're still improving."
|
||||
},
|
||||
{
|
||||
username: "jasonbereklewis",
|
||||
image: Jason,
|
||||
name: "Jason Berek-Lewis",
|
||||
link: "https://twitter.com/jasonbereklewis/status/1438635808727044098",
|
||||
text: "I work in content writing and communications. My day starts and ends in Notesnook. My Chrome app is always open; it's where I take all my notes. The clean design, focus mode, the tagging and color coding are all features that help keep my work organised every day."
|
||||
},
|
||||
{
|
||||
username: "camflint",
|
||||
image: Cameron,
|
||||
name: "Cameron Flint",
|
||||
link: "https://twitter.com/camflint/status/1481061416434286592",
|
||||
text: "I'm pretty impressed at the progress @notesnook are making on their app — particularly in respect to how performant the app runs and behaves, despite the overhead of end-to-end encrypting user data."
|
||||
}
|
||||
];
|
||||
|
||||
function getRandomTestimonial() {
|
||||
return testimonials[getRandom(0, testimonials.length - 1)];
|
||||
}
|
||||
|
||||
function randomTitle() {
|
||||
return strings.webAuthTitles[
|
||||
getRandom(0, strings.webAuthTitles.length - 1)
|
||||
]();
|
||||
}
|
||||
import NotesnookPhoneImage from "../../assets/auth/notesnook-phone.png";
|
||||
import CapaGreen from "../../assets/auth/capa-green.svg";
|
||||
|
||||
function AuthContainer(props) {
|
||||
const testimonial = useMemo(() => getRandomTestimonial(), []);
|
||||
const title = useMemo(() => randomTitle(), []);
|
||||
|
||||
const version = usePromise(
|
||||
async () =>
|
||||
await fetch(`${hosts.API_HOST}/version`)
|
||||
.then((r) => r.json())
|
||||
.catch(() => undefined)
|
||||
);
|
||||
// const version = usePromise(
|
||||
// async () =>
|
||||
// await fetch(`${hosts.API_HOST}/version`)
|
||||
// .then((r) => r.json())
|
||||
// .catch(() => undefined)
|
||||
// );
|
||||
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
position: "relative",
|
||||
height: "100%",
|
||||
bg: "background"
|
||||
bg: "background",
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
flexDirection: "column",
|
||||
display: ["none", "none", "flex"],
|
||||
flex: 1
|
||||
width: "fit-content",
|
||||
padding: "spacing8",
|
||||
height: [0, 0, "100%"],
|
||||
width: [0, 0, "48vw"]
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
as="svg"
|
||||
version="1.1"
|
||||
viewBox="0 0 1920 1080"
|
||||
preserveAspectRatio="xMinYMin slice"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: -100,
|
||||
left: 0,
|
||||
height: "100%"
|
||||
// opacity: 0.7,
|
||||
bg: "shade",
|
||||
height: "100%",
|
||||
borderRadius: "radius4",
|
||||
position: "relative",
|
||||
overflow: "hidden"
|
||||
}}
|
||||
>
|
||||
<g mask='url("#SvgjsMask1017")' fill="none">
|
||||
<path
|
||||
d="M1184.21-85.14C1033.8-60.27 964.89 302.42 717.38 307.22 469.87 312.02 483.97 244.72 250.55 244.72 17.13 244.72-98.53 307.08-216.28 307.22"
|
||||
stroke="var(--icon)"
|
||||
strokeWidth="2"
|
||||
></path>
|
||||
<path
|
||||
d="M641.38-10.43C534.57 43 590.55 387.5 384.53 392.38 178.52 397.26 2.17 282.99-129.16 282.38"
|
||||
stroke="var(--icon)"
|
||||
strokeWidth="2"
|
||||
></path>
|
||||
<path
|
||||
d="M1136.18-29.24C957.53-5.77 852.26 404.49 561.01 405.07 269.76 405.65 142.54 160.4-14.16 155.07"
|
||||
stroke="var(--icon)"
|
||||
strokeWidth="2"
|
||||
></path>
|
||||
<path
|
||||
d="M508.47-71.88C398.16-66.29 333.42 117.75 114.38 127.84-104.65 137.93-170.96 308.31-279.7 312.84"
|
||||
stroke="var(--icon)"
|
||||
strokeWidth="2"
|
||||
></path>
|
||||
<path
|
||||
d="M1104.88-26.74C976.63-19.04 883.5 217.2 653.03 218.11 422.55 219.02 427.1 155.61 201.17 155.61-24.75 155.61-136.64 217.96-250.68 218.11"
|
||||
stroke="var(--icon)"
|
||||
strokeWidth="2"
|
||||
></path>
|
||||
</g>
|
||||
<defs>
|
||||
<mask id="SvgjsMask1017">
|
||||
<rect width="1440" height="500" fill="#ffffff"></rect>
|
||||
</mask>
|
||||
</defs>
|
||||
</Box>
|
||||
|
||||
<Flex
|
||||
p={50}
|
||||
sx={{
|
||||
zIndex: 1,
|
||||
flex: 1,
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
justifyContent: "end"
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
style={{
|
||||
height: 90,
|
||||
width: 90,
|
||||
alignSelf: "start",
|
||||
marginBottom: 20
|
||||
}}
|
||||
>
|
||||
<use href="#full-logo" />
|
||||
</svg>
|
||||
<Text variant={"heading"} sx={{ fontSize: 48 }}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
variant="body"
|
||||
mt={10}
|
||||
sx={{ fontSize: 14, color: "paragraph-secondary" }}
|
||||
>
|
||||
{testimonial.text} —{" "}
|
||||
<Link
|
||||
sx={{ fontStyle: "italic", color: "paragraph-secondary" }}
|
||||
href={testimonial.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
source
|
||||
</Link>
|
||||
</Text>
|
||||
<Flex mt={2} sx={{ alignItems: "center", justifyContent: "center" }}>
|
||||
<Image
|
||||
src={testimonial.image}
|
||||
sx={{ borderRadius: 50, width: 40 }}
|
||||
/>
|
||||
<Flex ml={2} sx={{ flexDirection: "column" }}>
|
||||
<Text variant="body" sx={{ fontSize: 14, fontWeight: "bold" }}>
|
||||
{testimonial.name}
|
||||
</Text>
|
||||
<Text variant="subBody">@{testimonial.username}</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
mt={2}
|
||||
pt={2}
|
||||
sx={{
|
||||
justifyContent: "space-between",
|
||||
borderTop: "1px solid var(--border)",
|
||||
width: "100%"
|
||||
flexDirection: "column",
|
||||
gap: "76px",
|
||||
position: "relative",
|
||||
zIndex: 1,
|
||||
height: "100%"
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
gap: "spacing6",
|
||||
flexDirection: "column",
|
||||
marginX: "spacing11",
|
||||
marginTop: "60px"
|
||||
}}
|
||||
>
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text
|
||||
sx={{
|
||||
color: "heading",
|
||||
fontWeight: 700,
|
||||
fontSize: "2xl"
|
||||
}}
|
||||
>
|
||||
End-to-end encrypted.
|
||||
</Text>
|
||||
<Text
|
||||
sx={{
|
||||
color: "heading",
|
||||
fontWeight: 700,
|
||||
fontSize: "2xl"
|
||||
}}
|
||||
>
|
||||
Privacy Simplified.
|
||||
</Text>
|
||||
</Flex>
|
||||
<Text
|
||||
sx={{
|
||||
color: "paragraph",
|
||||
fontWeight: 400,
|
||||
fontSize: "md"
|
||||
}}
|
||||
>
|
||||
Write notes with absolute freedom. No spying, no tracking, no
|
||||
backdoor access. Just you and your thoughts.
|
||||
</Text>
|
||||
</Flex>
|
||||
<Image
|
||||
src={NotesnookPhoneImage}
|
||||
sx={{
|
||||
marginLeft: "58px",
|
||||
objectFit: "contain",
|
||||
height: "100%",
|
||||
flex: 0.95,
|
||||
overflow: "hidden"
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 50,
|
||||
left: -100,
|
||||
width: "998px",
|
||||
height: "245px",
|
||||
transform: "rotate(-34.33deg)",
|
||||
transformOrigin: "center center"
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={CapaGreen}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "auto",
|
||||
display: "block",
|
||||
pointerEvents: "none"
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: "20px",
|
||||
right: "30px",
|
||||
zIndex: 1
|
||||
}}
|
||||
>
|
||||
<Text variant={"subBody"}>
|
||||
{version.status === "fulfilled" &&
|
||||
!!version.value &&
|
||||
version.value.instance !== "default" ? (
|
||||
<>
|
||||
{strings.usingInstance(
|
||||
version.value.instance,
|
||||
version.value.version
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>{strings.usingOfficialInstance()}</>
|
||||
)}
|
||||
</Text>
|
||||
<Button
|
||||
variant="anchor"
|
||||
variant="new_anchor"
|
||||
onClick={() => SettingsDialog.show({ activeSection: "servers" })}
|
||||
>
|
||||
{strings.configure()}
|
||||
{"Change server"}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
<Flex
|
||||
sx={{
|
||||
position: "relative",
|
||||
flex: 1.5,
|
||||
flexDirection: "column"
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
as="svg"
|
||||
version="1.1"
|
||||
viewBox="0 0 1920 1080"
|
||||
preserveAspectRatio="xMinYMin slice"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: "130%",
|
||||
height: "100%"
|
||||
}}
|
||||
>
|
||||
<path
|
||||
d="M0 336L29.2 316.2C58.3 296.3 116.7 256.7 174.8 267.5C233 278.3 291 339.7 349.2 361.3C407.3 383 465.7 365 523.8 359.5C582 354 640 361 698.2 346.5C756.3 332 814.7 296 872.8 267.2C931 238.3 989 216.7 1047.2 202.3C1105.3 188 1163.7 181 1221.8 202.7C1280 224.3 1338 274.7 1396.2 298C1454.3 321.3 1512.7 317.7 1570.8 332C1629 346.3 1687 378.7 1745.2 366.2C1803.3 353.7 1861.7 296.3 1890.8 267.7L1920 239L1920 0L1890.8 0C1861.7 0 1803.3 0 1745.2 0C1687 0 1629 0 1570.8 0C1512.7 0 1454.3 0 1396.2 0C1338 0 1280 0 1221.8 0C1163.7 0 1105.3 0 1047.2 0C989 0 931 0 872.8 0C814.7 0 756.3 0 698.2 0C640 0 582 0 523.8 0C465.7 0 407.3 0 349.2 0C291 0 233 0 174.8 0C116.7 0 58.3 0 29.2 0L0 0Z"
|
||||
fill="var(--background-secondary)"
|
||||
></path>
|
||||
<path
|
||||
d="M0 627L29.2 607.3C58.3 587.7 116.7 548.3 174.8 564.7C233 581 291 653 349.2 683.5C407.3 714 465.7 703 523.8 703C582 703 640 714 698.2 724.8C756.3 735.7 814.7 746.3 872.8 742.7C931 739 989 721 1047.2 670.7C1105.3 620.3 1163.7 537.7 1221.8 528.7C1280 519.7 1338 584.3 1396.2 623.8C1454.3 663.3 1512.7 677.7 1570.8 666.8C1629 656 1687 620 1745.2 602C1803.3 584 1861.7 584 1890.8 584L1920 584L1920 237L1890.8 265.7C1861.7 294.3 1803.3 351.7 1745.2 364.2C1687 376.7 1629 344.3 1570.8 330C1512.7 315.7 1454.3 319.3 1396.2 296C1338 272.7 1280 222.3 1221.8 200.7C1163.7 179 1105.3 186 1047.2 200.3C989 214.7 931 236.3 872.8 265.2C814.7 294 756.3 330 698.2 344.5C640 359 582 352 523.8 357.5C465.7 363 407.3 381 349.2 359.3C291 337.7 233 276.3 174.8 265.5C116.7 254.7 58.3 294.3 29.2 314.2L0 334Z"
|
||||
fill="var(--hover)"
|
||||
></path>
|
||||
<path
|
||||
d="M0 735L29.2 731.5C58.3 728 116.7 721 174.8 739C233 757 291 800 349.2 832.3C407.3 864.7 465.7 886.3 523.8 886.3C582 886.3 640 864.7 698.2 859.3C756.3 854 814.7 865 872.8 870.5C931 876 989 876 1047.2 845.3C1105.3 814.7 1163.7 753.3 1221.8 729.8C1280 706.3 1338 720.7 1396.2 738.7C1454.3 756.7 1512.7 778.3 1570.8 789.2C1629 800 1687 800 1745.2 814.5C1803.3 829 1861.7 858 1890.8 872.5L1920 887L1920 582L1890.8 582C1861.7 582 1803.3 582 1745.2 600C1687 618 1629 654 1570.8 664.8C1512.7 675.7 1454.3 661.3 1396.2 621.8C1338 582.3 1280 517.7 1221.8 526.7C1163.7 535.7 1105.3 618.3 1047.2 668.7C989 719 931 737 872.8 740.7C814.7 744.3 756.3 733.7 698.2 722.8C640 712 582 701 523.8 701C465.7 701 407.3 712 349.2 681.5C291 651 233 579 174.8 562.7C116.7 546.3 58.3 585.7 29.2 605.3L0 625Z"
|
||||
fill="var(--border)"
|
||||
></path>
|
||||
<path
|
||||
d="M0 897L29.2 895.3C58.3 893.7 116.7 890.3 174.8 908.3C233 926.3 291 965.7 349.2 985.3C407.3 1005 465.7 1005 523.8 1003.3C582 1001.7 640 998.3 698.2 996.7C756.3 995 814.7 995 872.8 986C931 977 989 959 1047.2 939.2C1105.3 919.3 1163.7 897.7 1221.8 894C1280 890.3 1338 904.7 1396.2 911.8C1454.3 919 1512.7 919 1570.8 928C1629 937 1687 955 1745.2 960.3C1803.3 965.7 1861.7 958.3 1890.8 954.7L1920 951L1920 885L1890.8 870.5C1861.7 856 1803.3 827 1745.2 812.5C1687 798 1629 798 1570.8 787.2C1512.7 776.3 1454.3 754.7 1396.2 736.7C1338 718.7 1280 704.3 1221.8 727.8C1163.7 751.3 1105.3 812.7 1047.2 843.3C989 874 931 874 872.8 868.5C814.7 863 756.3 852 698.2 857.3C640 862.7 582 884.3 523.8 884.3C465.7 884.3 407.3 862.7 349.2 830.3C291 798 233 755 174.8 737C116.7 719 58.3 726 29.2 729.5L0 733Z"
|
||||
fill="var(--hover)"
|
||||
></path>
|
||||
<path
|
||||
d="M0 1081L29.2 1081C58.3 1081 116.7 1081 174.8 1081C233 1081 291 1081 349.2 1081C407.3 1081 465.7 1081 523.8 1081C582 1081 640 1081 698.2 1081C756.3 1081 814.7 1081 872.8 1081C931 1081 989 1081 1047.2 1081C1105.3 1081 1163.7 1081 1221.8 1081C1280 1081 1338 1081 1396.2 1081C1454.3 1081 1512.7 1081 1570.8 1081C1629 1081 1687 1081 1745.2 1081C1803.3 1081 1861.7 1081 1890.8 1081L1920 1081L1920 949L1890.8 952.7C1861.7 956.3 1803.3 963.7 1745.2 958.3C1687 953 1629 935 1570.8 926C1512.7 917 1454.3 917 1396.2 909.8C1338 902.7 1280 888.3 1221.8 892C1163.7 895.7 1105.3 917.3 1047.2 937.2C989 957 931 975 872.8 984C814.7 993 756.3 993 698.2 994.7C640 996.3 582 999.7 523.8 1001.3C465.7 1003 407.3 1003 349.2 983.3C291 963.7 233 924.3 174.8 906.3C116.7 888.3 58.3 891.7 29.2 893.3L0 895Z"
|
||||
fill="var(--border)"
|
||||
></path>
|
||||
</Box>
|
||||
{props.children}
|
||||
</Flex>
|
||||
</Box>
|
||||
{props.children}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { Flex, FlexProps, Text } from "@theme-ui/components";
|
||||
|
||||
import { Error as ErrorIcon } from "../icons";
|
||||
import { Error as ErrorIcon, Warning } from "../icons";
|
||||
|
||||
type ErrorTextProps = { error?: string | Error | null | false } & FlexProps;
|
||||
export function ErrorText(props: ErrorTextProps) {
|
||||
@@ -59,3 +59,42 @@ export function ErrorText(props: ErrorTextProps) {
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export function AuthErrorText(props: ErrorTextProps) {
|
||||
const { error, sx, ...restProps } = props;
|
||||
|
||||
if (!error) return null;
|
||||
return (
|
||||
<Flex
|
||||
p={1}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
overflowY: "auto",
|
||||
...sx
|
||||
}}
|
||||
{...restProps}
|
||||
>
|
||||
<Warning size={13} color="icon-error" />
|
||||
<Text
|
||||
className="selectable"
|
||||
ml="spacing3"
|
||||
sx={{
|
||||
whiteSpace: "pre-wrap",
|
||||
fontWeight: 400,
|
||||
fontSize: "xs",
|
||||
color: "paragraph-error"
|
||||
}}
|
||||
>
|
||||
{error instanceof Error ? (
|
||||
<>
|
||||
{error.name}: {error.message}
|
||||
<br />
|
||||
{error.stack}
|
||||
</>
|
||||
) : (
|
||||
error
|
||||
)}
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button, Flex, Text, InputProps } from "@theme-ui/components";
|
||||
import { Input, Label } from "@theme-ui/components";
|
||||
import { Button, Flex, Text, InputProps, Input, Label } from "@notesnook/ui";
|
||||
import { ThemeUIStyleObject } from "@theme-ui/css";
|
||||
import { PasswordVisible, PasswordInvisible, Icon } from "../icons";
|
||||
import { useStore as useThemeStore } from "../../stores/theme-store";
|
||||
@@ -78,10 +77,9 @@ function Field(props: FieldProps) {
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
m: "2px",
|
||||
mr: "2px",
|
||||
// m: "2px",
|
||||
// mr: "2px",
|
||||
opacity: disabled ? 0.7 : 1,
|
||||
gap: 1,
|
||||
...sx,
|
||||
flexDirection: "column"
|
||||
}}
|
||||
@@ -89,10 +87,7 @@ function Field(props: FieldProps) {
|
||||
<Label
|
||||
htmlFor={id}
|
||||
sx={{
|
||||
fontSize: "subtitle",
|
||||
fontWeight: "bold",
|
||||
fontFamily: "body",
|
||||
color: "paragraph",
|
||||
flexDirection: "column",
|
||||
...styles?.label
|
||||
}}
|
||||
@@ -150,7 +145,11 @@ function Field(props: FieldProps) {
|
||||
":hover": { bg: "border" }
|
||||
}}
|
||||
>
|
||||
{isPasswordVisible ? <PasswordVisible /> : <PasswordInvisible />}
|
||||
{isPasswordVisible ? (
|
||||
<PasswordVisible size={15} />
|
||||
) : (
|
||||
<PasswordInvisible size={15} />
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
@@ -178,7 +177,7 @@ function Field(props: FieldProps) {
|
||||
p: 0,
|
||||
px: 1,
|
||||
height: "100%",
|
||||
bg: "transparent",
|
||||
// bg: "transparent",
|
||||
borderRadius: 0,
|
||||
margin: 0,
|
||||
display: "flex",
|
||||
@@ -221,7 +220,7 @@ function Field(props: FieldProps) {
|
||||
p: 0,
|
||||
px: 1,
|
||||
height: "100%",
|
||||
bg: "transparent",
|
||||
// bg: "transparent",
|
||||
borderRadius: 0,
|
||||
margin: 0,
|
||||
display: "flex",
|
||||
|
||||
@@ -237,6 +237,15 @@ import { useTheme } from "@emotion/react";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import { Flex, FlexProps } from "@theme-ui/components";
|
||||
import { isThemeColor, SchemeColors } from "@notesnook/theme";
|
||||
import EyeClosed from "@notesnook/icons/eye-closed.svg?react";
|
||||
import EyeOpen from "@notesnook/icons/eye-open.svg?react";
|
||||
import ChatIcon from "@notesnook/icons/chat.svg?react";
|
||||
import EnvelopeSimple from "@notesnook/icons/envelope-simple.svg?react";
|
||||
import LockSimple from "@notesnook/icons/lock-simple.svg?react";
|
||||
import ChevronLeftIcon from "@notesnook/icons/chevron-left.svg?react";
|
||||
import ChevronRightIcon from "@notesnook/icons/chevron-right.svg?react";
|
||||
import ClockIcon from "@notesnook/icons/clock.svg?react";
|
||||
import WarningCircle from "@notesnook/icons/warning-circle.svg?react";
|
||||
|
||||
type MDIIconWrapperProps = {
|
||||
title?: string;
|
||||
@@ -325,6 +334,33 @@ export function createIcon(path: string, rotate = false) {
|
||||
return NNIcon;
|
||||
}
|
||||
|
||||
export function createSvgIcon(
|
||||
Component: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
|
||||
) {
|
||||
const NNIcon: Icon = function Icon(props) {
|
||||
const { sx, size = 24, color = "icon", ...restProps } = props;
|
||||
return (
|
||||
<Flex
|
||||
{...restProps}
|
||||
sx={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexShrink: 0,
|
||||
color,
|
||||
width: size,
|
||||
height: size,
|
||||
...sx
|
||||
}}
|
||||
>
|
||||
<Component width="100%" height="100%" fill="currentColor" />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
NNIcon.isReactComponent = true;
|
||||
NNIcon.path = "";
|
||||
return NNIcon;
|
||||
}
|
||||
|
||||
export const Plus = createIcon(mdiPlus);
|
||||
export const NoteAdd = createIcon(mdiNoteEditOutline);
|
||||
export const Note = createIcon(mdiNoteOutline);
|
||||
@@ -361,7 +397,6 @@ export const Search = createIcon(mdiMagnify);
|
||||
export const TableOfContents = createIcon(mdiFormatListBulleted);
|
||||
export const Menu = createIcon(mdiMenu);
|
||||
export const Login = createIcon(mdiLoginVariant);
|
||||
export const Email = createIcon(mdiEmailAlertOutline);
|
||||
export const Signup = createIcon(mdiAccountOutline);
|
||||
export const Logout = createIcon(mdiLogoutVariant);
|
||||
export const FocusMode = createIcon(mdiGlasses);
|
||||
@@ -377,8 +412,6 @@ export const Export = createIcon(mdiExportVariant);
|
||||
export const AddToNotebook = createIcon(mdiBookPlusMultipleOutline);
|
||||
export const Expand = createIcon(mdiArrowExpandDown);
|
||||
export const Shortcut = createIcon(mdiArrowTopRightThick);
|
||||
export const ChevronLeft = createIcon(mdiChevronLeft);
|
||||
export const ChevronRight = createIcon(mdiChevronRight);
|
||||
export const Close = createIcon(mdiClose);
|
||||
export const Tag = createIcon(mdiPound);
|
||||
export const Tag2 = createIcon(mdiPound);
|
||||
@@ -418,8 +451,6 @@ export const ChevronDown = createIcon(mdiChevronDown);
|
||||
export const ChevronUp = createIcon(mdiChevronUp);
|
||||
export const SortAsc = createIcon(mdiSortAscending);
|
||||
export const SortDesc = createIcon(mdiSortDescending);
|
||||
export const PasswordInvisible = createIcon(mdiEyeOutline);
|
||||
export const PasswordVisible = createIcon(mdiEyeOffOutline);
|
||||
export const Fullscreen = createIcon(mdiFullscreen);
|
||||
export const ExitFullscreen = createIcon(mdiFullscreenExit);
|
||||
export const Announcement = createIcon(mdiBullhorn);
|
||||
@@ -428,7 +459,6 @@ export const Colors = createIcon(mdiPaletteOutline);
|
||||
export const Published = createIcon(mdiCloudCheckOutline);
|
||||
export const Copy = createIcon(mdiContentCopy);
|
||||
export const Refresh = createIcon(mdiRefresh);
|
||||
export const Clock = createIcon(mdiClockTimeFiveOutline);
|
||||
export const Duplicate = createIcon(mdiContentDuplicate);
|
||||
export const InternalLink = createIcon(mdiLink);
|
||||
export const Select = createIcon(mdiCheckboxMultipleMarkedCircleOutline);
|
||||
@@ -590,3 +620,13 @@ export const Inbox = createIcon(mdiInbox);
|
||||
export const SpellCheck = createIcon(mdiSpellcheck);
|
||||
export const ClearTrash = createIcon(mdiDeleteSweepOutline);
|
||||
export const CloseCircle = createIcon(mdiCloseCircle);
|
||||
|
||||
export const PasswordInvisible = createSvgIcon(EyeOpen);
|
||||
export const PasswordVisible = createSvgIcon(EyeClosed);
|
||||
export const Chat = createSvgIcon(ChatIcon);
|
||||
export const Email = createSvgIcon(EnvelopeSimple);
|
||||
export const RecoveryCode = createSvgIcon(LockSimple);
|
||||
export const ChevronLeft = createSvgIcon(ChevronLeftIcon);
|
||||
export const ChevronRight = createSvgIcon(ChevronRightIcon);
|
||||
export const Clock = createSvgIcon(ClockIcon);
|
||||
export const Warning = createSvgIcon(WarningCircle);
|
||||
|
||||
180
apps/web/src/components/otp-input/index.tsx
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
useCallback,
|
||||
useRef,
|
||||
useEffect,
|
||||
KeyboardEvent,
|
||||
ClipboardEvent
|
||||
} from "react";
|
||||
import { Flex, Input } from "@notesnook/ui";
|
||||
|
||||
type OtpInputProps = {
|
||||
length?: number;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
autoFocus?: boolean;
|
||||
disabled?: boolean;
|
||||
type?: "number" | "text";
|
||||
};
|
||||
|
||||
export function OtpInput({
|
||||
length = 6,
|
||||
value,
|
||||
onChange,
|
||||
autoFocus = true,
|
||||
disabled = false
|
||||
}: OtpInputProps) {
|
||||
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
inputRefs.current = inputRefs.current.slice(0, length);
|
||||
}, [length]);
|
||||
|
||||
useEffect(() => {
|
||||
if (autoFocus && inputRefs.current[0]) {
|
||||
inputRefs.current[0].focus();
|
||||
}
|
||||
}, [autoFocus]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(index: number, e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const char = e.target.value.replace(/\D/g, "").slice(-1);
|
||||
if (!char) return;
|
||||
|
||||
const newValue = Array.from({ length }, (_, i) => value[i] || "");
|
||||
newValue[index] = char;
|
||||
onChange(newValue.join(""));
|
||||
|
||||
if (index < length - 1) {
|
||||
const next = inputRefs.current[index + 1];
|
||||
if (next) next.focus();
|
||||
}
|
||||
},
|
||||
[value, length, onChange]
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(index: number, e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Backspace" || e.key === "Delete") {
|
||||
e.preventDefault();
|
||||
const newValue = Array.from({ length }, (_, i) => value[i] || "");
|
||||
if (newValue[index]) {
|
||||
newValue[index] = "";
|
||||
onChange(newValue.join(""));
|
||||
} else if (index > 0) {
|
||||
newValue[index - 1] = "";
|
||||
onChange(newValue.join(""));
|
||||
const prev = inputRefs.current[index - 1];
|
||||
if (prev) prev.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === "ArrowLeft") {
|
||||
e.preventDefault();
|
||||
if (index > 0) {
|
||||
inputRefs.current[index - 1]?.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === "ArrowRight") {
|
||||
e.preventDefault();
|
||||
if (index < length - 1) {
|
||||
inputRefs.current[index + 1]?.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
},
|
||||
[value, length, onChange]
|
||||
);
|
||||
|
||||
const handlePaste = useCallback(
|
||||
(e: ClipboardEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
const pasted = e.clipboardData.getData("text").replace(/\D/g, "");
|
||||
const newValue = Array.from({ length }, (_, i) => pasted[i] || value[i] || "");
|
||||
onChange(newValue.join(""));
|
||||
},
|
||||
[length, onChange, value]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
sx={{
|
||||
gap: "15px",
|
||||
justifyContent: "center",
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
{Array.from({ length }, (_, index) => (
|
||||
<Input
|
||||
key={index}
|
||||
ref={(el) => {
|
||||
inputRefs.current[index] = el;
|
||||
}}
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
pattern="[0-9]*"
|
||||
maxLength={1}
|
||||
autoComplete="one-time-code"
|
||||
value={value[index] || ""}
|
||||
disabled={disabled}
|
||||
onChange={(e) => handleChange(index, e)}
|
||||
onKeyDown={(e) => handleKeyDown(index, e)}
|
||||
onPaste={index === 0 ? handlePaste : undefined}
|
||||
onFocus={(e) => e.target.select()}
|
||||
sx={{
|
||||
width: 45,
|
||||
height: 45,
|
||||
textAlign: "center",
|
||||
fontSize: "md",
|
||||
fontWeight: 500,
|
||||
color: "heading",
|
||||
bg: "background",
|
||||
borderRadius: "radius1",
|
||||
border: "1px solid",
|
||||
borderColor: "border",
|
||||
p: 0,
|
||||
outline: "none",
|
||||
"&:focus": {
|
||||
borderColor: "accent",
|
||||
boxShadow: "0 0 0 1px var(--accent)"
|
||||
},
|
||||
"-moz-appearance": "textfield",
|
||||
"::-webkit-inner-spin-button": {
|
||||
"-webkit-appearance": "none"
|
||||
},
|
||||
"::-webkit-outer-spin-button": {
|
||||
"-webkit-appearance": "none"
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<input name="code" type="hidden" value={value} onChange={() => {}} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -21,16 +21,14 @@ import { getCurrentPath } from "./index";
|
||||
|
||||
export type AuthRoutes =
|
||||
| "sessionExpiry"
|
||||
| "login:email"
|
||||
| "login:password"
|
||||
| "login"
|
||||
| "signup"
|
||||
| "recover"
|
||||
| "mfa:code"
|
||||
| "mfa:select";
|
||||
|
||||
export const authRoutes: Record<AuthRoutes, string> = {
|
||||
"login:email": "/login",
|
||||
"login:password": "/login/password",
|
||||
login: "/login",
|
||||
"mfa:code": "/login/mfa/code",
|
||||
"mfa:select": "/login/mfa/select",
|
||||
recover: "/recover",
|
||||
@@ -39,8 +37,7 @@ export const authRoutes: Record<AuthRoutes, string> = {
|
||||
};
|
||||
|
||||
const unauthorizedRoutes: AuthRoutes[] = [
|
||||
"login:email",
|
||||
"login:password",
|
||||
"login",
|
||||
"signup",
|
||||
"mfa:code",
|
||||
"mfa:select",
|
||||
|
||||
@@ -153,7 +153,7 @@ function RouteWrapper(props: {
|
||||
</div>
|
||||
);
|
||||
performance.mark("render:app");
|
||||
return <Component route={routeProps?.route || "login:email"} />;
|
||||
return <Component route={routeProps?.route || "login"} />;
|
||||
}
|
||||
|
||||
if (import.meta.hot) import.meta.hot.accept();
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
ThemeLight
|
||||
} from "@notesnook/theme";
|
||||
import { ThemesRouter } from "../common/themes-router";
|
||||
import { THEME_DARK, THEME_LIGHT } from "../common/theme";
|
||||
|
||||
type ColorScheme = "dark" | "light";
|
||||
class ThemeStore extends BaseStore<ThemeStore> {
|
||||
@@ -109,18 +110,19 @@ function getTheme(colorScheme: ColorScheme) {
|
||||
}
|
||||
|
||||
async function updateTheme(theme: ThemeDefinition) {
|
||||
const { id, version } = theme;
|
||||
try {
|
||||
const updatedTheme = await ThemesRouter.updateTheme.query({
|
||||
compatibilityVersion: THEME_COMPATIBILITY_VERSION,
|
||||
id,
|
||||
version
|
||||
});
|
||||
if (!updatedTheme) return theme;
|
||||
return updatedTheme;
|
||||
} catch (e) {
|
||||
return theme;
|
||||
}
|
||||
// const { id, version } = theme;
|
||||
// try {
|
||||
// const updatedTheme = await ThemesRouter.updateTheme.query({
|
||||
// compatibilityVersion: THEME_COMPATIBILITY_VERSION,
|
||||
// id,
|
||||
// version
|
||||
// });
|
||||
// if (!updatedTheme) return theme;
|
||||
// return updatedTheme;
|
||||
// } catch (e) {
|
||||
// return theme;
|
||||
// }
|
||||
return theme.colorScheme === "dark" ? THEME_DARK : THEME_LIGHT;
|
||||
}
|
||||
|
||||
function changeDesktopTheme(theme: ThemeDefinition, system: boolean) {
|
||||
|
||||
@@ -38,6 +38,12 @@ class UserStore extends BaseStore<UserStore> {
|
||||
user?: User = undefined;
|
||||
counter = 0;
|
||||
|
||||
private _pendingLogin?: {
|
||||
email: string;
|
||||
password: string;
|
||||
sessionExpired: boolean;
|
||||
};
|
||||
|
||||
init = () => {
|
||||
db.eventManager.subscribe(EVENTS.userSessionExpired, async () => {
|
||||
Config.set("sessionExpired", true);
|
||||
@@ -112,8 +118,8 @@ class UserStore extends BaseStore<UserStore> {
|
||||
|
||||
login = async (
|
||||
form:
|
||||
| { email: string }
|
||||
| { email: string; password: string }
|
||||
| { email: string }
|
||||
| { code: string; method: AuthenticatorType | "recoveryCode" },
|
||||
skipInit = false,
|
||||
sessionExpired = false
|
||||
@@ -121,21 +127,32 @@ class UserStore extends BaseStore<UserStore> {
|
||||
this.set((state) => (state.isLoggingIn = true));
|
||||
|
||||
try {
|
||||
if ("email" in form && !("password" in form)) {
|
||||
if ("email" in form && "password" in form) {
|
||||
this._pendingLogin = {
|
||||
email: form.email,
|
||||
password: form.password,
|
||||
sessionExpired: Config.get("sessionExpired", false)
|
||||
};
|
||||
return await db.user.authenticateEmail(form.email);
|
||||
} else if ("email" in form) {
|
||||
return await db.user.authenticateEmail(form.email);
|
||||
} else if ("code" in form) {
|
||||
const { code, method } = form;
|
||||
return await db.user.authenticateMultiFactorCode(code, method);
|
||||
} else if ("password" in form) {
|
||||
const { email, password } = form;
|
||||
await db.user.authenticatePassword(
|
||||
email,
|
||||
password,
|
||||
undefined,
|
||||
sessionExpired
|
||||
);
|
||||
Config.set("encryptBackups", true);
|
||||
await db.user.authenticateMultiFactorCode(code, method);
|
||||
|
||||
if (this._pendingLogin) {
|
||||
const { email, password, sessionExpired: sessExp } =
|
||||
this._pendingLogin;
|
||||
this._pendingLogin = undefined;
|
||||
await db.user.authenticatePassword(
|
||||
email,
|
||||
password,
|
||||
undefined,
|
||||
sessExp
|
||||
);
|
||||
}
|
||||
|
||||
Config.set("encryptBackups", true);
|
||||
if (skipInit) return true;
|
||||
return this.init();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Button, Flex, Link, Text } from "@theme-ui/components";
|
||||
import { Button, Flex, Link, Text, Box } from "@notesnook/ui";
|
||||
import {
|
||||
CheckCircle,
|
||||
Loading,
|
||||
@@ -26,10 +26,17 @@ import {
|
||||
MfaSms,
|
||||
MfaEmail,
|
||||
MfaRecoveryCode,
|
||||
ChevronRight,
|
||||
ChevronLeft,
|
||||
Clock,
|
||||
Icon,
|
||||
Warn
|
||||
Warn,
|
||||
Chat,
|
||||
Email,
|
||||
RecoveryCode
|
||||
} from "../components/icons";
|
||||
import Field, { FieldProps } from "../components/field";
|
||||
import { OtpInput } from "../components/otp-input";
|
||||
import { getQueryParams, hardNavigate, makeURL } from "../navigation";
|
||||
import { store as userstore } from "../stores/user-store";
|
||||
import { db } from "../common/db";
|
||||
@@ -38,7 +45,7 @@ import { Loader } from "../components/loader";
|
||||
import { showToast } from "../utils/toast";
|
||||
import AuthContainer from "../components/auth-container";
|
||||
import { useTimer } from "../hooks/use-timer";
|
||||
import { ErrorText } from "../components/error-text";
|
||||
import { AuthErrorText } from "../components/error-text";
|
||||
import { AuthenticatorType, User } from "@notesnook/core";
|
||||
import { ConfirmDialog, showLogoutConfirmation } from "../dialogs/confirm";
|
||||
import { TaskManager } from "../common/task-manager";
|
||||
@@ -54,17 +61,18 @@ type EmailFormData = {
|
||||
email: string;
|
||||
};
|
||||
|
||||
type PasswordFormData = EmailFormData & {
|
||||
password: string;
|
||||
};
|
||||
|
||||
type MFALoginFormData = {
|
||||
code: string;
|
||||
method: MFAMethodType;
|
||||
};
|
||||
|
||||
type LoginFormData = {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
type SignupFormData = EmailFormData &
|
||||
PasswordFormData & {
|
||||
LoginFormData & {
|
||||
"confirm-password": string;
|
||||
};
|
||||
|
||||
@@ -78,6 +86,7 @@ type MFAFormData = EmailFormData & {
|
||||
code?: string;
|
||||
secondaryMethod?: MFAMethodType;
|
||||
phoneNumber?: string;
|
||||
password?: string;
|
||||
};
|
||||
|
||||
type MFAErrorData = {
|
||||
@@ -87,10 +96,9 @@ type MFAErrorData = {
|
||||
};
|
||||
|
||||
type AuthFormData = {
|
||||
"login:email": EmailFormData;
|
||||
"login:password": PasswordFormData;
|
||||
login: LoginFormData;
|
||||
signup: SignupFormData;
|
||||
sessionExpiry: EmailFormData;
|
||||
sessionExpiry: LoginFormData;
|
||||
recover: AccountRecoveryFormData;
|
||||
"mfa:code": MFAFormData;
|
||||
"mfa:select": MFAFormData;
|
||||
@@ -99,7 +107,7 @@ type AuthFormData = {
|
||||
type BaseFormData =
|
||||
| MFAFormData
|
||||
| EmailFormData
|
||||
| PasswordFormData
|
||||
| LoginFormData
|
||||
| AccountRecoveryFormData
|
||||
| SignupFormData;
|
||||
|
||||
@@ -133,10 +141,8 @@ function getRouteComponent<TRoute extends AuthRoutes>(
|
||||
route: TRoute
|
||||
): AuthComponent<TRoute> | undefined {
|
||||
switch (route) {
|
||||
case "login:email":
|
||||
return LoginEmail as AuthComponent<TRoute>;
|
||||
case "login:password":
|
||||
return LoginPassword as AuthComponent<TRoute>;
|
||||
case "login":
|
||||
return Login as AuthComponent<TRoute>;
|
||||
case "signup":
|
||||
return Signup as AuthComponent<TRoute>;
|
||||
case "sessionExpiry":
|
||||
@@ -210,12 +216,12 @@ export function HeadlessAuth(props: AuthProps) {
|
||||
);
|
||||
}
|
||||
|
||||
function LoginEmail(props: BaseAuthComponentProps<"login:email">) {
|
||||
const { navigate, canSkip = true, openURL } = props;
|
||||
function Login(props: BaseAuthComponentProps<"login">) {
|
||||
const { navigate, canSkip = true, openURL, formData } = props;
|
||||
|
||||
return (
|
||||
<AuthForm
|
||||
type="login:email"
|
||||
type="login"
|
||||
title={strings.welcomeBack()}
|
||||
canSkip={canSkip}
|
||||
openURL={openURL}
|
||||
@@ -226,23 +232,30 @@ function LoginEmail(props: BaseAuthComponentProps<"login:email">) {
|
||||
/>
|
||||
}
|
||||
loading={{
|
||||
title: strings.verifyingEmail(),
|
||||
title: strings.loggingIn(),
|
||||
subtitle: strings.authWait()
|
||||
}}
|
||||
onSubmit={async (form) => {
|
||||
const { primaryMethod, phoneNumber, secondaryMethod } =
|
||||
(await userstore.login(form)) as MFAErrorData;
|
||||
const result = (await userstore.login(form)) as
|
||||
| MFAErrorData
|
||||
| undefined;
|
||||
|
||||
if (!result) {
|
||||
openURL("/plans", { authenticated: true });
|
||||
return;
|
||||
}
|
||||
|
||||
navigate("mfa:code", {
|
||||
email: form.email,
|
||||
selectedMethod: primaryMethod,
|
||||
primaryMethod,
|
||||
phoneNumber,
|
||||
secondaryMethod
|
||||
password: form.password,
|
||||
selectedMethod: result.primaryMethod,
|
||||
primaryMethod: result.primaryMethod,
|
||||
phoneNumber: result.phoneNumber,
|
||||
secondaryMethod: result.secondaryMethod
|
||||
});
|
||||
}}
|
||||
>
|
||||
{(form?: EmailFormData) => (
|
||||
{(form?: LoginFormData) => (
|
||||
<>
|
||||
{IS_BETA ? (
|
||||
<Flex
|
||||
@@ -262,64 +275,27 @@ function LoginEmail(props: BaseAuthComponentProps<"login:email">) {
|
||||
autoComplete="email"
|
||||
label={strings.enterEmailAddress()}
|
||||
autoFocus
|
||||
defaultValue={form?.email}
|
||||
defaultValue={form?.email ?? formData?.email}
|
||||
/>
|
||||
<SubmitButton text={strings.continue()} />
|
||||
</>
|
||||
)}
|
||||
</AuthForm>
|
||||
);
|
||||
}
|
||||
|
||||
function LoginPassword(props: BaseAuthComponentProps<"login:password">) {
|
||||
const { navigate, formData, openURL } = props;
|
||||
|
||||
if (!formData) {
|
||||
openURL("/", { authenticated: false });
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthForm
|
||||
type="login:password"
|
||||
title={strings.accountPassword()}
|
||||
subtitle={strings.accountPassDesc()}
|
||||
loadForever
|
||||
loading={{
|
||||
title: strings.loggingIn(),
|
||||
subtitle: strings.authWait()
|
||||
}}
|
||||
openURL={openURL}
|
||||
onSubmit={async (form) => {
|
||||
await userstore.login(
|
||||
{
|
||||
password: form.password,
|
||||
email: formData.email
|
||||
},
|
||||
false,
|
||||
Config.get("sessionExpired", false)
|
||||
);
|
||||
Config.set("sessionExpired", false);
|
||||
openURL("/plans", { authenticated: true });
|
||||
}}
|
||||
>
|
||||
{(form?: PasswordFormData) => (
|
||||
<>
|
||||
<AuthField
|
||||
id="password"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
label={strings.enterPassword()}
|
||||
autoFocus
|
||||
defaultValue={form?.password}
|
||||
defaultValue={form?.password ?? formData?.password}
|
||||
/>
|
||||
<Button
|
||||
data-test-id="auth-forgot-password"
|
||||
type="button"
|
||||
mt={2}
|
||||
variant="anchor"
|
||||
onClick={() => navigate("recover", { email: formData.email })}
|
||||
sx={{ color: "paragraph", alignSelf: "end" }}
|
||||
variant="new_anchor"
|
||||
onClick={() => navigate("recover", { email: form?.email || "" })}
|
||||
sx={{
|
||||
mt: "spacing4",
|
||||
fontSize: "xs",
|
||||
color: "paragraph-secondary",
|
||||
textDecoration: "none",
|
||||
alignSelf: "end"
|
||||
}}
|
||||
>
|
||||
{strings.forgotPassword()}
|
||||
</Button>
|
||||
@@ -338,12 +314,13 @@ function Signup(props: BaseAuthComponentProps<"signup">) {
|
||||
type="signup"
|
||||
title={strings.createAccount()}
|
||||
canSkip={canSkip}
|
||||
showAgreement
|
||||
subtitle={
|
||||
<SubtitleWithAction
|
||||
text={strings.alreadyHaveAccount()}
|
||||
action={{
|
||||
text: strings.login(),
|
||||
onClick: () => navigate("login:email")
|
||||
onClick: () => navigate("login")
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@@ -386,30 +363,6 @@ function Signup(props: BaseAuthComponentProps<"signup">) {
|
||||
defaultValue={form?.["confirm-password"]}
|
||||
/>
|
||||
<SubmitButton text={strings.createAccount()} />
|
||||
<Text
|
||||
mt={4}
|
||||
variant="subBody"
|
||||
sx={{ fontSize: 13, textAlign: "center" }}
|
||||
>
|
||||
{strings.signupAgreement[0]()}{" "}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://notesnook.com/tos"
|
||||
sx={{ color: "accent" }}
|
||||
>
|
||||
{strings.signupAgreement[1]()}
|
||||
</Link>{" "}
|
||||
{strings.signupAgreement[2]()}{" "}
|
||||
<Link
|
||||
rel="noreferrer"
|
||||
href="https://notesnook.com/privacy"
|
||||
sx={{ color: "accent" }}
|
||||
>
|
||||
{strings.signupAgreement[3]()}
|
||||
</Link>
|
||||
. {strings.signupAgreement[4]()}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</AuthForm>
|
||||
@@ -427,7 +380,7 @@ function SessionExpiry(props: BaseAuthComponentProps<"sessionExpiry">) {
|
||||
setUser(user);
|
||||
} else if (!user) {
|
||||
Config.set("sessionExpired", false);
|
||||
navigate("login:email");
|
||||
navigate("login");
|
||||
} else openURL("/", { authenticated: true });
|
||||
})();
|
||||
}, [navigate, openURL]);
|
||||
@@ -448,18 +401,27 @@ function SessionExpiry(props: BaseAuthComponentProps<"sessionExpiry">) {
|
||||
subtitle: strings.pleaseWaitLogin()
|
||||
}}
|
||||
openURL={openURL}
|
||||
onSubmit={async () => {
|
||||
onSubmit={async (form) => {
|
||||
if (!user) return;
|
||||
|
||||
const { primaryMethod, phoneNumber, secondaryMethod } =
|
||||
(await userstore.login(user)) as MFAErrorData;
|
||||
const result = (await userstore.login({
|
||||
email: user.email,
|
||||
password: form.password
|
||||
})) as MFAErrorData | undefined;
|
||||
|
||||
Config.set("sessionExpired", false);
|
||||
|
||||
if (!result) {
|
||||
openURL("/", { authenticated: true });
|
||||
return;
|
||||
}
|
||||
|
||||
navigate("mfa:code", {
|
||||
email: user.email,
|
||||
selectedMethod: primaryMethod,
|
||||
primaryMethod,
|
||||
phoneNumber,
|
||||
secondaryMethod
|
||||
selectedMethod: result.primaryMethod,
|
||||
primaryMethod: result.primaryMethod,
|
||||
phoneNumber: result.phoneNumber,
|
||||
secondaryMethod: result.secondaryMethod
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -473,6 +435,13 @@ function SessionExpiry(props: BaseAuthComponentProps<"sessionExpiry">) {
|
||||
disabled
|
||||
required={false}
|
||||
/>
|
||||
<AuthField
|
||||
id="password"
|
||||
type="password"
|
||||
autoComplete={"false"}
|
||||
label={strings.enterPassword()}
|
||||
autoFocus
|
||||
/>
|
||||
<Button
|
||||
data-test-id="auth-forgot-password"
|
||||
type="button"
|
||||
@@ -489,7 +458,7 @@ function SessionExpiry(props: BaseAuthComponentProps<"sessionExpiry">) {
|
||||
variant="anchor"
|
||||
sx={{
|
||||
mt: 5,
|
||||
color: "var(--paragraph-error)",
|
||||
color: "paragraph-error",
|
||||
textDecoration: "none",
|
||||
":hover": {
|
||||
color: "var(--paragraph-error)"
|
||||
@@ -503,7 +472,7 @@ function SessionExpiry(props: BaseAuthComponentProps<"sessionExpiry">) {
|
||||
action: () => db.user.logout(true),
|
||||
subtitle: strings.loggingOutDesc()
|
||||
});
|
||||
navigate("login:email");
|
||||
navigate("login");
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -526,7 +495,7 @@ function AccountRecovery(props: BaseAuthComponentProps<"recover">) {
|
||||
text={strings.rememberedYourPassword()}
|
||||
action={{
|
||||
text: strings.login(),
|
||||
onClick: () => navigate("login:email")
|
||||
onClick: () => navigate("login")
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@@ -610,6 +579,7 @@ function getTexts(formData: MFAFormData) {
|
||||
function MFACode(props: BaseAuthComponentProps<"mfa:code">) {
|
||||
const { navigate, formData, openURL } = props;
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
const [otpValue, setOtpValue] = useState("");
|
||||
const { elapsed, enabled, setEnabled } = useTimer(
|
||||
`2fa.${formData?.primaryMethod}`,
|
||||
60
|
||||
@@ -667,61 +637,150 @@ function MFACode(props: BaseAuthComponentProps<"mfa:code">) {
|
||||
}}
|
||||
openURL={openURL}
|
||||
onSubmit={async (form) => {
|
||||
if (!form.code) throw new Error(strings.coreRequired());
|
||||
const code = selectedMethod !== "recoveryCode" ? otpValue : form.code;
|
||||
if (!code || code.length < (selectedMethod !== "recoveryCode" ? 6 : 1))
|
||||
throw new Error(strings.coreRequired());
|
||||
|
||||
const loginForm: MFALoginFormData = {
|
||||
code: form.code,
|
||||
code,
|
||||
method: formData.selectedMethod
|
||||
};
|
||||
await userstore.login(loginForm);
|
||||
navigate("login:password", {
|
||||
openURL("/plans", { authenticated: true });
|
||||
}}
|
||||
onBack={() => {
|
||||
navigate("login", {
|
||||
email: formData.email,
|
||||
// TODO
|
||||
password: ""
|
||||
password: formData.password ?? ""
|
||||
});
|
||||
}}
|
||||
>
|
||||
<AuthField
|
||||
id="code"
|
||||
type={selectedMethod !== "recoveryCode" ? "number" : "text"}
|
||||
autoComplete={"one-time-code"}
|
||||
label={texts.label}
|
||||
autoFocus
|
||||
pattern={selectedMethod !== "recoveryCode" ? "[0-9]*" : undefined}
|
||||
inputMode={selectedMethod !== "recoveryCode" ? "numeric" : undefined}
|
||||
helpText={texts.instructions}
|
||||
action={
|
||||
selectedMethod === "sms" || selectedMethod === "email"
|
||||
? {
|
||||
disabled: isSending || !enabled,
|
||||
component: (
|
||||
<Text variant={"body"}>
|
||||
{isSending ? (
|
||||
<Loading size={18} />
|
||||
) : enabled ? (
|
||||
strings.resendCode()
|
||||
) : (
|
||||
strings.resendCode(elapsed)
|
||||
)}
|
||||
</Text>
|
||||
),
|
||||
onClick: async () => {
|
||||
await sendCode(selectedMethod);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
{selectedMethod !== "recoveryCode" ? (
|
||||
<OtpInput
|
||||
length={6}
|
||||
value={otpValue}
|
||||
onChange={setOtpValue}
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
<AuthField id="code" type="text" label={texts.label} autoFocus />
|
||||
)}
|
||||
<SubmitButton text={strings.submit()} />
|
||||
<Button
|
||||
type="button"
|
||||
mt={4}
|
||||
variant={"anchor"}
|
||||
onClick={() => navigate("mfa:select", formData)}
|
||||
sx={{ color: "paragraph" }}
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: "column",
|
||||
my: "spacing7",
|
||||
gap: "spacing4"
|
||||
}}
|
||||
>
|
||||
{texts.selector}
|
||||
</Button>
|
||||
{(selectedMethod === "sms" || selectedMethod === "email") && (
|
||||
<>
|
||||
<Flex
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
background: "background-secondary",
|
||||
p: "spacing5",
|
||||
borderRadius: "radius2"
|
||||
}}
|
||||
>
|
||||
<Flex sx={{ alignItems: "center", gap: "10px" }}>
|
||||
<Flex
|
||||
sx={{
|
||||
bg: "background-tertiary",
|
||||
borderRadius: "5px",
|
||||
width: 32,
|
||||
height: 32,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<Clock size={15} color="icon" />
|
||||
</Flex>
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text
|
||||
sx={{ fontSize: "sm", fontWeight: 500, color: "heading" }}
|
||||
>
|
||||
{"Didn't receive code?"}
|
||||
</Text>
|
||||
{!enabled && (
|
||||
<Text
|
||||
sx={{
|
||||
color: "paragraph",
|
||||
fontSize: "xs",
|
||||
fontWeight: 400
|
||||
}}
|
||||
>
|
||||
{`${strings.resendCodeWait()} `}
|
||||
<Text as="span" sx={{ color: "accent" }}>
|
||||
{elapsed}s
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Button
|
||||
type="button"
|
||||
variant="anchor"
|
||||
disabled={isSending || !enabled}
|
||||
onClick={() => sendCode(selectedMethod as "sms" | "email")}
|
||||
sx={{
|
||||
fontSize: "xs",
|
||||
fontWeight: 500,
|
||||
color:
|
||||
enabled && !isSending ? "accent" : "paragraph-secondary",
|
||||
textDecoration: "none"
|
||||
}}
|
||||
>
|
||||
{isSending ? <Loading size={18} /> : strings.resendCode()}
|
||||
</Button>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
p: "spacing5",
|
||||
textAlign: "left",
|
||||
borderRadius: "radius2"
|
||||
}}
|
||||
onClick={() => navigate("mfa:select", formData)}
|
||||
>
|
||||
<Flex sx={{ alignItems: "center", gap: "10px" }}>
|
||||
<Flex
|
||||
sx={{
|
||||
bg: "background-tertiary",
|
||||
borderRadius: "5px",
|
||||
width: 32,
|
||||
height: 32,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
{selectedMethod === "email" ? (
|
||||
<MfaEmail size={16} color="icon" />
|
||||
) : selectedMethod === "sms" ? (
|
||||
<MfaSms size={16} color="icon" />
|
||||
) : selectedMethod === "app" ? (
|
||||
<MfaAuthenticator size={16} color="icon" />
|
||||
) : (
|
||||
<MfaRecoveryCode size={16} color="icon" />
|
||||
)}
|
||||
</Flex>
|
||||
<Text sx={{ fontWeight: 500, fontSize: "sm", color: "heading" }}>
|
||||
{texts.selector}
|
||||
</Text>
|
||||
</Flex>
|
||||
<ChevronRight size={13} color="icon" sx={{ flexShrink: 0 }} />
|
||||
</Button>
|
||||
</Flex>
|
||||
</AuthForm>
|
||||
);
|
||||
}
|
||||
@@ -731,16 +790,36 @@ type MFAMethod = {
|
||||
type: MFAMethodType;
|
||||
title: string;
|
||||
icon: Icon;
|
||||
description: string;
|
||||
};
|
||||
const MFAMethods: MFAMethod[] = [
|
||||
{ type: "app", title: strings.sendCode(), icon: MfaAuthenticator },
|
||||
{ type: "sms", title: strings.sendCodeSms(), icon: MfaSms },
|
||||
{ type: "email", title: strings.sendCodeEmail(), icon: MfaEmail },
|
||||
{ type: "recoveryCode", title: strings.recoveryCode(), icon: MfaRecoveryCode }
|
||||
{
|
||||
type: "app",
|
||||
title: strings.sendCode(),
|
||||
icon: MfaAuthenticator,
|
||||
description: "Use the authenticator app"
|
||||
},
|
||||
{
|
||||
type: "sms",
|
||||
title: strings.sendCodeSms(),
|
||||
icon: Chat,
|
||||
description: "Text message to my registered number"
|
||||
},
|
||||
{
|
||||
type: "email",
|
||||
title: strings.sendCodeEmail(),
|
||||
icon: Email,
|
||||
description: "Verify via registered inbox"
|
||||
},
|
||||
{
|
||||
type: "recoveryCode",
|
||||
title: strings.recoveryCode(),
|
||||
icon: RecoveryCode,
|
||||
description: "Use my original emergency key"
|
||||
}
|
||||
];
|
||||
function MFASelector(props: BaseAuthComponentProps<"mfa:select">) {
|
||||
const { navigate, formData, openURL } = props;
|
||||
const [selected, setSelected] = useState(0);
|
||||
const isValidMethod = useCallback(
|
||||
(method: MFAMethodType) => {
|
||||
return (
|
||||
@@ -766,56 +845,84 @@ function MFASelector(props: BaseAuthComponentProps<"mfa:select">) {
|
||||
subtitle: strings.authWait()
|
||||
}}
|
||||
openURL={openURL}
|
||||
onSubmit={async () => {
|
||||
const selectedType = MFAMethods[selected];
|
||||
formData.selectedMethod = selectedType.type;
|
||||
navigate("mfa:code", formData);
|
||||
}}
|
||||
onSubmit={async () => {}}
|
||||
onBack={() => navigate("mfa:code", formData)}
|
||||
>
|
||||
{MFAMethods.map(
|
||||
(method, index) =>
|
||||
(method) =>
|
||||
isValidMethod(method.type) && (
|
||||
<Button
|
||||
key={method.type}
|
||||
type="submit"
|
||||
variant={"secondary"}
|
||||
mt={2}
|
||||
type="button"
|
||||
variant="secondary"
|
||||
sx={{
|
||||
":first-of-type": { mt: 2 },
|
||||
display: "flex",
|
||||
bg: "background",
|
||||
alignSelf: "stretch",
|
||||
alignItems: "center",
|
||||
textAlign: "left",
|
||||
px: 2
|
||||
justifyContent: "space-between",
|
||||
bg: "background-secondary",
|
||||
alignSelf: "stretch",
|
||||
p: "spacing5",
|
||||
gap: "20px",
|
||||
borderRadius: "10px",
|
||||
":not(:first-of-type)": { mt: "10px" },
|
||||
textAlign: "left"
|
||||
}}
|
||||
onClick={() => {
|
||||
formData.selectedMethod = method.type;
|
||||
navigate("mfa:code", formData);
|
||||
}}
|
||||
onClick={() => setSelected(index)}
|
||||
>
|
||||
<method.icon
|
||||
<Flex
|
||||
sx={{
|
||||
bg: selected === index ? "shade" : "border",
|
||||
borderRadius: 100,
|
||||
width: 35,
|
||||
height: 35,
|
||||
mr: 2
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
flex: "1 1 auto",
|
||||
minWidth: 0
|
||||
}}
|
||||
size={16}
|
||||
color={selected === index ? "accent" : "icon"}
|
||||
/>
|
||||
<Text variant={"title"} sx={{ fontWeight: "body" }}>
|
||||
{method.title}
|
||||
</Text>
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
bg: "background-tertiary",
|
||||
borderRadius: "radius1",
|
||||
width: 32,
|
||||
height: 32,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<method.icon size={15} color="icon" />
|
||||
</Flex>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: "column",
|
||||
gap: "spacing3"
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
sx={{
|
||||
fontWeight: 500,
|
||||
color: "heading",
|
||||
fontSize: "sm"
|
||||
}}
|
||||
>
|
||||
{method.title}
|
||||
</Text>
|
||||
<Text
|
||||
sx={{
|
||||
fontWeight: 400,
|
||||
color: "paragraph",
|
||||
fontSize: "xs"
|
||||
}}
|
||||
>
|
||||
{method.description}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<ChevronRight size={13} />
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
{/* <SubmitButton
|
||||
text="Submit"
|
||||
disabled={!isAppLoaded}
|
||||
loading={!isAppLoaded}
|
||||
/> */}
|
||||
{/* <Button type="button" mt={4} variant={"anchor"} sx={{color: "paragraph"}}>
|
||||
Don't have access to your {mfaMethodToPhrase(formData.primaryMethod)}?
|
||||
</Button> */}
|
||||
</AuthForm>
|
||||
);
|
||||
}
|
||||
@@ -831,13 +938,24 @@ type AuthFormProps<TType extends AuthRoutes> = {
|
||||
openURL: OpenURLFunction;
|
||||
loadForever?: boolean;
|
||||
canSkip?: boolean;
|
||||
showAgreement?: boolean;
|
||||
onBack?: () => void;
|
||||
children?:
|
||||
| React.ReactNode
|
||||
| ((form?: AuthFormData[TType]) => React.ReactNode);
|
||||
};
|
||||
|
||||
export function AuthForm<T extends AuthRoutes>(props: AuthFormProps<T>) {
|
||||
const { title, subtitle, children, canSkip, loadForever, openURL } = props;
|
||||
const {
|
||||
title,
|
||||
subtitle,
|
||||
children,
|
||||
canSkip,
|
||||
loadForever,
|
||||
openURL,
|
||||
showAgreement,
|
||||
onBack
|
||||
} = props;
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [error, setError] = useState<string>();
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
@@ -878,23 +996,89 @@ export function AuthForm<T extends AuthRoutes>(props: AuthFormProps<T>) {
|
||||
sx={{
|
||||
flex: 1,
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: ["95%", "95%", "45%"],
|
||||
alignSelf: "center"
|
||||
alignItems: "left",
|
||||
// justifyContent: "center",
|
||||
width: ["95%", "95%", "65%"],
|
||||
maxWidth: "500px",
|
||||
alignSelf: "center",
|
||||
mt: "149px"
|
||||
}}
|
||||
>
|
||||
<Text variant={"heading"} sx={{ fontSize: 32, textAlign: "center" }}>
|
||||
{onBack ? (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
sx={{
|
||||
background: "background",
|
||||
borderRadius: "radius2",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "spacing4",
|
||||
px: "spacing6",
|
||||
py: "spacing5",
|
||||
alignSelf: "flex-start",
|
||||
mb: "spacing9",
|
||||
border: "1px solid var(--border)"
|
||||
}}
|
||||
>
|
||||
<ChevronLeft size={14} color="icon" />
|
||||
<Text
|
||||
sx={{
|
||||
fontSize: "sm",
|
||||
fontWeight: 600,
|
||||
color: "heading"
|
||||
}}
|
||||
>
|
||||
{strings.goBack()}
|
||||
</Text>
|
||||
</Button>
|
||||
) : (
|
||||
<Flex
|
||||
sx={{
|
||||
mb: "70px",
|
||||
alignItems: "center",
|
||||
gap: "spacing4"
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
style={{
|
||||
borderRadius: "default",
|
||||
height: 30,
|
||||
width: 30,
|
||||
alignSelf: "center"
|
||||
}}
|
||||
>
|
||||
<use href="#full-logo" />
|
||||
</svg>
|
||||
<Text
|
||||
sx={{
|
||||
fontSize: "2xl",
|
||||
fontWeight: 600,
|
||||
color: "heading"
|
||||
}}
|
||||
>
|
||||
Notesnook
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
<Text
|
||||
sx={{
|
||||
fontSize: "xl",
|
||||
textAlign: "left",
|
||||
fontWeight: 600,
|
||||
color: "heading"
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Text
|
||||
variant="body"
|
||||
mt={2}
|
||||
mb={35}
|
||||
sx={{
|
||||
fontSize: "title",
|
||||
textAlign: "center",
|
||||
color: "var(--paragraph-secondary)"
|
||||
mt: "spacing3",
|
||||
mb: "spacing7",
|
||||
fontSize: "sm",
|
||||
textAlign: "left",
|
||||
color: "paragraph",
|
||||
fontWeight: 400
|
||||
}}
|
||||
>
|
||||
{subtitle}
|
||||
@@ -903,30 +1087,58 @@ export function AuthForm<T extends AuthRoutes>(props: AuthFormProps<T>) {
|
||||
{canSkip && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="anchor"
|
||||
sx={{
|
||||
mt: 5,
|
||||
color: "paragraph",
|
||||
textDecoration: "none",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 5
|
||||
}}
|
||||
onClick={async () => {
|
||||
const result = await ConfirmDialog.show({
|
||||
title: strings.offlineMode(),
|
||||
message: strings.offlineModeDesc(),
|
||||
negativeButtonText: strings.cancel(),
|
||||
positiveButtonText: strings.understand()
|
||||
});
|
||||
if (result) openURL("/notes/", { authenticated: false });
|
||||
variant="new_bordered"
|
||||
sx={{ width: "100%", mt: "spacing4" }}
|
||||
onClick={() => {
|
||||
openURL("/notes/", { authenticated: false });
|
||||
}}
|
||||
>
|
||||
{strings.skipAndGoToApp()}
|
||||
</Button>
|
||||
)}
|
||||
{showAgreement && (
|
||||
<Text
|
||||
mt={4}
|
||||
sx={{
|
||||
color: "paragraph",
|
||||
fontSize: "xs",
|
||||
textAlign: "center",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
mt: "auto",
|
||||
mb: "spacing11"
|
||||
}}
|
||||
>
|
||||
{strings.signupAgreement[0]()}{" "}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://notesnook.com/tos"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
color: "accent",
|
||||
textDecoration: "none"
|
||||
}}
|
||||
>
|
||||
{strings.signupAgreement[1]()}
|
||||
</Link>{" "}
|
||||
{strings.signupAgreement[2]()}{" "}
|
||||
<Link
|
||||
rel="noreferrer"
|
||||
href="https://notesnook.com/privacy"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
color: "accent",
|
||||
textDecoration: "none"
|
||||
}}
|
||||
>
|
||||
{strings.signupAgreement[3]()}
|
||||
</Link>
|
||||
. {strings.signupAgreement[4]()}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<ErrorText error={error} mt={5} />
|
||||
<AuthErrorText error={error} mt={"spacing7"} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -946,11 +1158,11 @@ function SubtitleWithAction(props: SubtitleWithActionProps) {
|
||||
type="button"
|
||||
variant="anchor"
|
||||
sx={{
|
||||
textDecoration: "underline",
|
||||
fontWeight: "bold",
|
||||
fontSize: "subtitle",
|
||||
color: "paragraph",
|
||||
cursor: "pointer"
|
||||
fontWeight: 600,
|
||||
fontSize: "sm",
|
||||
color: "accent",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none"
|
||||
}}
|
||||
onClick={props.action.onClick}
|
||||
>
|
||||
@@ -967,14 +1179,20 @@ export function AuthField(props: FieldProps) {
|
||||
{...props}
|
||||
name={props.name || props.id}
|
||||
data-test-id={props["data-test-id"] || props.id}
|
||||
sx={{ mt: 2, width: "100%" }}
|
||||
sx={{ mt: 2, width: "100%", gap: "spacing3" }}
|
||||
styles={{
|
||||
// label: { fontWeight: "normal" },
|
||||
label: {
|
||||
fontSize: "xs",
|
||||
fontWeight: 400,
|
||||
color: "paragraph-secondary"
|
||||
},
|
||||
input: {
|
||||
p: "12px",
|
||||
borderRadius: "default",
|
||||
bg: "background",
|
||||
boxShadow: "0px 0px 5px 0px #00000019",
|
||||
fontSize: "xs",
|
||||
borderRadius: "spacing4",
|
||||
outline: 0,
|
||||
bg: "background-secondary",
|
||||
paddingY: "spacing6",
|
||||
paddingX: "spacing4",
|
||||
"::-moz-appearance": "textfield",
|
||||
"::-webkit-inner-spin-button": {
|
||||
"-webkit-appearance": "none"
|
||||
@@ -998,15 +1216,10 @@ export function SubmitButton(props: SubmitButtonProps) {
|
||||
<Button
|
||||
data-test-id="submitButton"
|
||||
type="submit"
|
||||
mt={50}
|
||||
variant="accent"
|
||||
px={50}
|
||||
variant="new_accent"
|
||||
sx={{
|
||||
borderRadius: 50,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
alignSelf: "center",
|
||||
display: "flex"
|
||||
marginTop: "spacing8",
|
||||
width: "100%"
|
||||
}}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
|
||||
73
packages/editor/package-lock.json
generated
@@ -1540,39 +1540,6 @@
|
||||
"@styled-system/css": "^5.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@theme-ui/color-modes": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@theme-ui/color-modes/-/color-modes-0.16.2.tgz",
|
||||
"integrity": "sha512-jWEWx53lxNgWCT38i/kwLV2rsvJz8lVZgi5oImnVwYba9VejXD23q1ckbNFJHosQ8KKXY87ht0KPC6BQFIiHtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@theme-ui/core": "^0.16.2",
|
||||
"@theme-ui/css": "^0.16.2",
|
||||
"deepmerge": "^4.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@theme-ui/color-modes/node_modules/@theme-ui/core": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
|
||||
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@theme-ui/css": "^0.16.2",
|
||||
"deepmerge": "^4.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@theme-ui/components": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@theme-ui/components/-/components-0.16.1.tgz",
|
||||
@@ -1618,39 +1585,6 @@
|
||||
"@emotion/react": "^11.11.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@theme-ui/theme-provider": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@theme-ui/theme-provider/-/theme-provider-0.16.2.tgz",
|
||||
"integrity": "sha512-LRnVevODcGqO0JyLJ3wht+PV3ZoZcJ7XXLJAJWDoGeII4vZcPQKwVy4Lpz/juHsZppQxKcB3U+sQDGBnP25irQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@theme-ui/color-modes": "^0.16.2",
|
||||
"@theme-ui/core": "^0.16.2",
|
||||
"@theme-ui/css": "^0.16.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@theme-ui/theme-provider/node_modules/@theme-ui/core": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
|
||||
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@theme-ui/css": "^0.16.2",
|
||||
"deepmerge": "^4.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.11.1",
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@tiptap/core": {
|
||||
"version": "2.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.6.6.tgz",
|
||||
@@ -3498,7 +3432,8 @@
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
@@ -3607,6 +3542,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
@@ -5139,6 +5075,7 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -5159,6 +5096,7 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -5473,6 +5411,7 @@
|
||||
"version": "0.23.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
|
||||
13
packages/icons/package-lock.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@notesnook/icons",
|
||||
"version": "2.1.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/icons",
|
||||
"version": "2.1.3",
|
||||
"license": "GPL-3.0-or-later"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.5 3H2.50002C2.2348 3 1.98045 3.10536 1.79291 3.29289C1.60537 3.48043 1.50002 3.73478 1.50002 4V14C1.49886 14.1907 1.55281 14.3777 1.65537 14.5384C1.75793 14.6992 1.90473 14.8269 2.07814 14.9062C2.21029 14.9678 2.35425 14.9998 2.50002 15C2.73477 14.9994 2.96174 14.9157 3.14064 14.7638L3.14627 14.7594L5.18752 13H13.5C13.7652 13 14.0196 12.8946 14.2071 12.7071C14.3947 12.5196 14.5 12.2652 14.5 12V4C14.5 3.73478 14.3947 3.48043 14.2071 3.29289C14.0196 3.10536 13.7652 3 13.5 3ZM13.5 12H5.00002C4.87996 12.0001 4.76394 12.0433 4.67314 12.1219L2.50002 14V4H13.5V12Z" fill="white"/>
|
||||
<path d="M13.5 3H2.50002C2.2348 3 1.98045 3.10536 1.79291 3.29289C1.60537 3.48043 1.50002 3.73478 1.50002 4V14C1.49886 14.1907 1.55281 14.3777 1.65537 14.5384C1.75793 14.6992 1.90473 14.8269 2.07814 14.9062C2.21029 14.9678 2.35425 14.9998 2.50002 15C2.73477 14.9994 2.96174 14.9157 3.14064 14.7638L3.14627 14.7594L5.18752 13H13.5C13.7652 13 14.0196 12.8946 14.2071 12.7071C14.3947 12.5196 14.5 12.2652 14.5 12V4C14.5 3.73478 14.3947 3.48043 14.2071 3.29289C14.0196 3.10536 13.7652 3 13.5 3ZM13.5 12H5.00002C4.87996 12.0001 4.76394 12.0433 4.67314 12.1219L2.50002 14V4H13.5V12Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 703 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 12L10 8L6 4" stroke="#181818" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.5 15L12.5 10L7.5 5" stroke="currentColor" stroke-width="0.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 213 B After Width: | Height: | Size: 225 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 1.5C6.71442 1.5 5.45772 1.88122 4.3888 2.59545C3.31988 3.30968 2.48676 4.32484 1.99479 5.51256C1.50282 6.70028 1.37409 8.00721 1.6249 9.26809C1.8757 10.529 2.49477 11.6872 3.40381 12.5962C4.31285 13.5052 5.47104 14.1243 6.73192 14.3751C7.99279 14.6259 9.29973 14.4972 10.4874 14.0052C11.6752 13.5132 12.6903 12.6801 13.4046 11.6112C14.1188 10.5423 14.5 9.28558 14.5 8C14.4982 6.27665 13.8128 4.62441 12.5942 3.40582C11.3756 2.18722 9.72335 1.50182 8 1.5ZM8 13.5C6.91221 13.5 5.84884 13.1774 4.94437 12.5731C4.0399 11.9687 3.33495 11.1098 2.91867 10.1048C2.50238 9.09977 2.39347 7.9939 2.60568 6.927C2.8179 5.86011 3.34173 4.8801 4.11092 4.11091C4.8801 3.34172 5.86011 2.8179 6.92701 2.60568C7.9939 2.39346 9.09977 2.50238 10.1048 2.91866C11.1098 3.33494 11.9687 4.03989 12.5731 4.94436C13.1774 5.84883 13.5 6.9122 13.5 8C13.4983 9.45818 12.9184 10.8562 11.8873 11.8873C10.8562 12.9184 9.45819 13.4983 8 13.5ZM12 8C12 8.13261 11.9473 8.25979 11.8536 8.35355C11.7598 8.44732 11.6326 8.5 11.5 8.5H8C7.86739 8.5 7.74022 8.44732 7.64645 8.35355C7.55268 8.25979 7.5 8.13261 7.5 8V4.5C7.5 4.36739 7.55268 4.24021 7.64645 4.14645C7.74022 4.05268 7.86739 4 8 4C8.13261 4 8.25979 4.05268 8.35356 4.14645C8.44732 4.24021 8.5 4.36739 8.5 4.5V7.5H11.5C11.6326 7.5 11.7598 7.55268 11.8536 7.64645C11.9473 7.74021 12 7.86739 12 8Z" fill="#181818"/>
|
||||
<path d="M8 1.5C6.71442 1.5 5.45772 1.88122 4.3888 2.59545C3.31988 3.30968 2.48676 4.32484 1.99479 5.51256C1.50282 6.70028 1.37409 8.00721 1.6249 9.26809C1.8757 10.529 2.49477 11.6872 3.40381 12.5962C4.31285 13.5052 5.47104 14.1243 6.73192 14.3751C7.99279 14.6259 9.29973 14.4972 10.4874 14.0052C11.6752 13.5132 12.6903 12.6801 13.4046 11.6112C14.1188 10.5423 14.5 9.28558 14.5 8C14.4982 6.27665 13.8128 4.62441 12.5942 3.40582C11.3756 2.18722 9.72335 1.50182 8 1.5ZM8 13.5C6.91221 13.5 5.84884 13.1774 4.94437 12.5731C4.0399 11.9687 3.33495 11.1098 2.91867 10.1048C2.50238 9.09977 2.39347 7.9939 2.60568 6.927C2.8179 5.86011 3.34173 4.8801 4.11092 4.11091C4.8801 3.34172 5.86011 2.8179 6.92701 2.60568C7.9939 2.39346 9.09977 2.50238 10.1048 2.91866C11.1098 3.33494 11.9687 4.03989 12.5731 4.94436C13.1774 5.84883 13.5 6.9122 13.5 8C13.4983 9.45818 12.9184 10.8562 11.8873 11.8873C10.8562 12.9184 9.45819 13.4983 8 13.5ZM12 8C12 8.13261 11.9473 8.25979 11.8536 8.35355C11.7598 8.44732 11.6326 8.5 11.5 8.5H8C7.86739 8.5 7.74022 8.44732 7.64645 8.35355C7.55268 8.25979 7.5 8.13261 7.5 8V4.5C7.5 4.36739 7.55268 4.24021 7.64645 4.14645C7.74022 4.05268 7.86739 4 8 4C8.13261 4 8.25979 4.05268 8.35356 4.14645C8.44732 4.24021 8.5 4.36739 8.5 4.5V7.5H11.5C11.6326 7.5 11.7598 7.55268 11.8536 7.64645C11.9473 7.74021 12 7.86739 12 8Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 3H2C1.86739 3 1.74021 3.05268 1.64645 3.14645C1.55268 3.24021 1.5 3.36739 1.5 3.5V12C1.5 12.2652 1.60536 12.5196 1.79289 12.7071C1.98043 12.8946 2.23478 13 2.5 13H13.5C13.7652 13 14.0196 12.8946 14.2071 12.7071C14.3946 12.5196 14.5 12.2652 14.5 12V3.5C14.5 3.36739 14.4473 3.24021 14.3536 3.14645C14.2598 3.05268 14.1326 3 14 3ZM12.7144 4L8 8.32187L3.28562 4H12.7144ZM13.5 12H2.5V4.63688L7.66187 9.36875C7.75412 9.45343 7.87478 9.50041 8 9.50041C8.12522 9.50041 8.24588 9.45343 8.33813 9.36875L13.5 4.63688V12Z" fill="white"/>
|
||||
<path d="M14 3H2C1.86739 3 1.74021 3.05268 1.64645 3.14645C1.55268 3.24021 1.5 3.36739 1.5 3.5V12C1.5 12.2652 1.60536 12.5196 1.79289 12.7071C1.98043 12.8946 2.23478 13 2.5 13H13.5C13.7652 13 14.0196 12.8946 14.2071 12.7071C14.3946 12.5196 14.5 12.2652 14.5 12V3.5C14.5 3.36739 14.4473 3.24021 14.3536 3.14645C14.2598 3.05268 14.1326 3 14 3ZM12.7144 4L8 8.32187L3.28562 4H12.7144ZM13.5 12H2.5V4.63688L7.66187 9.36875C7.75412 9.45343 7.87478 9.50041 8 9.50041C8.12522 9.50041 8.24588 9.45343 8.33813 9.36875L13.5 4.63688V12Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 650 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.25 10.9376C14.1929 10.9702 14.1299 10.9911 14.0647 10.9993C13.9995 11.0075 13.9333 11.0028 13.8699 10.9854C13.8065 10.968 13.7471 10.9382 13.6952 10.8978C13.6434 10.8575 13.6 10.8073 13.5675 10.7501L12.38 8.67509C11.6896 9.14189 10.928 9.49355 10.125 9.71634L10.4919 11.9176C10.5027 11.9824 10.5006 12.0487 10.4858 12.1127C10.471 12.1767 10.4437 12.2372 10.4055 12.2906C10.3674 12.3441 10.319 12.3895 10.2632 12.4243C10.2075 12.459 10.1454 12.4825 10.0806 12.4932C10.054 12.4976 10.027 12.4999 10 12.5001C9.88171 12.4999 9.76732 12.4578 9.67715 12.3813C9.58698 12.3047 9.52687 12.1987 9.5075 12.082L9.14687 9.92072C8.38637 10.0265 7.61488 10.0265 6.85437 9.92072L6.49375 12.082C6.47434 12.1989 6.41405 12.3051 6.32362 12.3817C6.23319 12.4582 6.1185 12.5002 6 12.5001C5.97236 12.5 5.94477 12.4977 5.9175 12.4932C5.85269 12.4825 5.79063 12.459 5.73488 12.4243C5.67913 12.3895 5.63077 12.3441 5.59258 12.2906C5.55439 12.2372 5.5271 12.1767 5.51229 12.1127C5.49748 12.0487 5.49542 11.9824 5.50625 11.9176L5.875 9.71634C5.07227 9.49284 4.31112 9.14055 3.62125 8.67322L2.4375 10.7501C2.37119 10.8656 2.26171 10.9501 2.13313 10.9849C2.00455 11.0197 1.86741 11.002 1.75187 10.9357C1.63634 10.8694 1.55188 10.7599 1.51706 10.6313C1.48225 10.5028 1.49994 10.3656 1.56625 10.2501L2.81625 8.06259C2.37719 7.68327 1.97345 7.26489 1.61 6.81259C1.56467 6.76199 1.53014 6.70267 1.5085 6.63827C1.48686 6.57387 1.47857 6.50574 1.48413 6.43803C1.4897 6.37032 1.50901 6.30446 1.54088 6.24446C1.57275 6.18446 1.61651 6.13159 1.66949 6.08906C1.72248 6.04654 1.78357 6.01526 1.84905 5.99713C1.91452 5.97901 1.983 5.97441 2.05031 5.98363C2.11762 5.99286 2.18235 6.0157 2.24053 6.05076C2.29872 6.08583 2.34915 6.13239 2.38875 6.18759C3.42625 7.47134 5.24125 9.00009 8 9.00009C10.7587 9.00009 12.5737 7.46947 13.6112 6.18759C13.6504 6.13126 13.7007 6.08358 13.7591 6.04752C13.8174 6.01147 13.8826 5.98781 13.9505 5.97802C14.0184 5.96823 14.0876 5.97251 14.1537 5.99061C14.2199 6.0087 14.2817 6.04022 14.3351 6.0832C14.3886 6.12618 14.4326 6.1797 14.4645 6.24044C14.4964 6.30117 14.5155 6.36782 14.5205 6.43624C14.5255 6.50465 14.5164 6.57337 14.4938 6.63812C14.4711 6.70286 14.4354 6.76225 14.3887 6.81259C14.0253 7.26489 13.6216 7.68327 13.1825 8.06259L14.4325 10.2501C14.4661 10.3071 14.488 10.3702 14.4969 10.4358C14.5059 10.5013 14.5018 10.568 14.4848 10.632C14.4679 10.6959 14.4384 10.7558 14.3981 10.8083C14.3577 10.8608 14.3074 10.9047 14.25 10.9376Z" fill="white"/>
|
||||
<path d="M14.25 10.9376C14.1929 10.9702 14.1299 10.9911 14.0647 10.9993C13.9995 11.0075 13.9333 11.0028 13.8699 10.9854C13.8065 10.968 13.7471 10.9382 13.6952 10.8978C13.6434 10.8575 13.6 10.8073 13.5675 10.7501L12.38 8.67509C11.6896 9.14189 10.928 9.49355 10.125 9.71634L10.4919 11.9176C10.5027 11.9824 10.5006 12.0487 10.4858 12.1127C10.471 12.1767 10.4437 12.2372 10.4055 12.2906C10.3674 12.3441 10.319 12.3895 10.2632 12.4243C10.2075 12.459 10.1454 12.4825 10.0806 12.4932C10.054 12.4976 10.027 12.4999 10 12.5001C9.88171 12.4999 9.76732 12.4578 9.67715 12.3813C9.58698 12.3047 9.52687 12.1987 9.5075 12.082L9.14687 9.92072C8.38637 10.0265 7.61488 10.0265 6.85437 9.92072L6.49375 12.082C6.47434 12.1989 6.41405 12.3051 6.32362 12.3817C6.23319 12.4582 6.1185 12.5002 6 12.5001C5.97236 12.5 5.94477 12.4977 5.9175 12.4932C5.85269 12.4825 5.79063 12.459 5.73488 12.4243C5.67913 12.3895 5.63077 12.3441 5.59258 12.2906C5.55439 12.2372 5.5271 12.1767 5.51229 12.1127C5.49748 12.0487 5.49542 11.9824 5.50625 11.9176L5.875 9.71634C5.07227 9.49284 4.31112 9.14055 3.62125 8.67322L2.4375 10.7501C2.37119 10.8656 2.26171 10.9501 2.13313 10.9849C2.00455 11.0197 1.86741 11.002 1.75187 10.9357C1.63634 10.8694 1.55188 10.7599 1.51706 10.6313C1.48225 10.5028 1.49994 10.3656 1.56625 10.2501L2.81625 8.06259C2.37719 7.68327 1.97345 7.26489 1.61 6.81259C1.56467 6.76199 1.53014 6.70267 1.5085 6.63827C1.48686 6.57387 1.47857 6.50574 1.48413 6.43803C1.4897 6.37032 1.50901 6.30446 1.54088 6.24446C1.57275 6.18446 1.61651 6.13159 1.66949 6.08906C1.72248 6.04654 1.78357 6.01526 1.84905 5.99713C1.91452 5.97901 1.983 5.97441 2.05031 5.98363C2.11762 5.99286 2.18235 6.0157 2.24053 6.05076C2.29872 6.08583 2.34915 6.13239 2.38875 6.18759C3.42625 7.47134 5.24125 9.00009 8 9.00009C10.7587 9.00009 12.5737 7.46947 13.6112 6.18759C13.6504 6.13126 13.7007 6.08358 13.7591 6.04752C13.8174 6.01147 13.8826 5.98781 13.9505 5.97802C14.0184 5.96823 14.0876 5.97251 14.1537 5.99061C14.2199 6.0087 14.2817 6.04022 14.3351 6.0832C14.3886 6.12618 14.4326 6.1797 14.4645 6.24044C14.4964 6.30117 14.5155 6.36782 14.5205 6.43624C14.5255 6.50465 14.5164 6.57337 14.4938 6.63812C14.4711 6.70286 14.4354 6.76225 14.3887 6.81259C14.0253 7.26489 13.6216 7.68327 13.1825 8.06259L14.4325 10.2501C14.4661 10.3071 14.488 10.3702 14.4969 10.4358C14.5059 10.5013 14.5018 10.568 14.4848 10.632C14.4679 10.6959 14.4384 10.7558 14.3981 10.8083C14.3577 10.8608 14.3074 10.9047 14.25 10.9376Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,6 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2899_8437)">
|
||||
<path d="M7.99935 3C4.66602 3 1.81935 5.07333 0.666016 8C1.81935 10.9267 4.66602 13 7.99935 13C11.3327 13 14.1793 10.9267 15.3327 8C14.1793 5.07333 11.3327 3 7.99935 3ZM7.99935 11.3333C6.15935 11.3333 4.66602 9.84 4.66602 8C4.66602 6.16 6.15935 4.66667 7.99935 4.66667C9.83935 4.66667 11.3327 6.16 11.3327 8C11.3327 9.84 9.83935 11.3333 7.99935 11.3333ZM7.99935 6C6.89268 6 5.99935 6.89333 5.99935 8C5.99935 9.10667 6.89268 10 7.99935 10C9.10602 10 9.99935 9.10667 9.99935 8C9.99935 6.89333 9.10602 6 7.99935 6Z" fill="#666666"/>
|
||||
<path d="M7.99935 3C4.66602 3 1.81935 5.07333 0.666016 8C1.81935 10.9267 4.66602 13 7.99935 13C11.3327 13 14.1793 10.9267 15.3327 8C14.1793 5.07333 11.3327 3 7.99935 3ZM7.99935 11.3333C6.15935 11.3333 4.66602 9.84 4.66602 8C4.66602 6.16 6.15935 4.66667 7.99935 4.66667C9.83935 4.66667 11.3327 6.16 11.3327 8C11.3327 9.84 9.83935 11.3333 7.99935 11.3333ZM7.99935 6C6.89268 6 5.99935 6.89333 5.99935 8C5.99935 9.10667 6.89268 10 7.99935 10C9.10602 10 9.99935 9.10667 9.99935 8C9.99935 6.89333 9.10602 6 7.99935 6Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2899_8437">
|
||||
|
||||
|
Before Width: | Height: | Size: 779 B After Width: | Height: | Size: 784 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 5H11V3.5C11 2.70435 10.6839 1.94129 10.1213 1.37868C9.55871 0.81607 8.79565 0.5 8 0.5C7.20435 0.5 6.44129 0.81607 5.87868 1.37868C5.31607 1.94129 5 2.70435 5 3.5V5H3C2.73478 5 2.48043 5.10536 2.29289 5.29289C2.10536 5.48043 2 5.73478 2 6V13C2 13.2652 2.10536 13.5196 2.29289 13.7071C2.48043 13.8946 2.73478 14 3 14H13C13.2652 14 13.5196 13.8946 13.7071 13.7071C13.8946 13.5196 14 13.2652 14 13V6C14 5.73478 13.8946 5.48043 13.7071 5.29289C13.5196 5.10536 13.2652 5 13 5ZM6 3.5C6 2.96957 6.21071 2.46086 6.58579 2.08579C6.96086 1.71071 7.46957 1.5 8 1.5C8.53043 1.5 9.03914 1.71071 9.41421 2.08579C9.78929 2.46086 10 2.96957 10 3.5V5H6V3.5ZM13 13H3V6H13V13Z" fill="white"/>
|
||||
<path d="M13 5H11V3.5C11 2.70435 10.6839 1.94129 10.1213 1.37868C9.55871 0.81607 8.79565 0.5 8 0.5C7.20435 0.5 6.44129 0.81607 5.87868 1.37868C5.31607 1.94129 5 2.70435 5 3.5V5H3C2.73478 5 2.48043 5.10536 2.29289 5.29289C2.10536 5.48043 2 5.73478 2 6V13C2 13.2652 2.10536 13.5196 2.29289 13.7071C2.48043 13.8946 2.73478 14 3 14H13C13.2652 14 13.5196 13.8946 13.7071 13.7071C13.8946 13.5196 14 13.2652 14 13V6C14 5.73478 13.8946 5.48043 13.7071 5.29289C13.5196 5.10536 13.2652 5 13 5ZM6 3.5C6 2.96957 6.21071 2.46086 6.58579 2.08579C6.96086 1.71071 7.46957 1.5 8 1.5C8.53043 1.5 9.03914 1.71071 9.41421 2.08579C9.78929 2.46086 10 2.96957 10 3.5V5H6V3.5ZM13 13H3V6H13V13Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 789 B After Width: | Height: | Size: 796 B |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 1.4502C9.73659 1.45203 11.4019 2.14216 12.6299 3.37012C13.8578 4.59807 14.548 6.26341 14.5498 8L14.5459 8.24219C14.5011 9.4527 14.121 10.6288 13.4463 11.6387C12.7266 12.7158 11.7037 13.556 10.5068 14.0518C9.30998 14.5475 7.99226 14.6766 6.72168 14.4238C5.45131 14.171 4.28407 13.5477 3.36816 12.6318C2.45226 11.7159 1.82897 10.5487 1.57617 9.27832C1.32344 8.00774 1.45249 6.69002 1.94824 5.49316C2.444 4.29635 3.28422 3.27341 4.36133 2.55371C5.43841 1.83411 6.70465 1.4502 8 1.4502ZM10.0859 2.96484C9.09008 2.55235 7.99372 2.44401 6.93652 2.6543C5.87938 2.86461 4.90865 3.38432 4.14648 4.14648C3.38432 4.90865 2.8646 5.87938 2.6543 6.93652C2.44401 7.99372 2.55235 9.09008 2.96484 10.0859C3.37729 11.0815 4.07572 11.9325 4.97168 12.5312C5.86793 13.1301 6.92209 13.4502 8 13.4502L8.27051 13.4434C9.61689 13.375 10.8938 12.8093 11.8516 11.8516C12.8733 10.8298 13.4485 9.44492 13.4502 8L13.4355 7.59766C13.3663 6.66142 13.0553 5.75604 12.5312 4.97168C11.9325 4.07572 11.0815 3.37729 10.0859 2.96484ZM8 9.9502C8.21217 9.9502 8.4154 10.0345 8.56543 10.1846C8.71546 10.3346 8.7998 10.5378 8.7998 10.75C8.7998 10.9082 8.75294 11.0628 8.66504 11.1943C8.57713 11.3259 8.45184 11.4287 8.30566 11.4893C8.15961 11.5496 7.99877 11.565 7.84375 11.5342C7.68867 11.5033 7.54639 11.4272 7.43457 11.3154C7.32275 11.2036 7.24672 11.0613 7.21582 10.9062C7.18499 10.7512 7.20035 10.5904 7.26074 10.4443C7.32129 10.2982 7.4241 10.1729 7.55566 10.085C7.68722 9.99706 7.84178 9.9502 8 9.9502ZM8 4.4502C8.14587 4.4502 8.28553 4.50818 8.38867 4.61133C8.49182 4.71447 8.5498 4.85413 8.5498 5V8.5C8.5498 8.64587 8.49182 8.78553 8.38867 8.88867C8.28553 8.99182 8.14587 9.0498 8 9.0498C7.85413 9.0498 7.71447 8.99182 7.61133 8.88867C7.50818 8.78553 7.4502 8.64587 7.4502 8.5V5C7.4502 4.85413 7.50818 4.71447 7.61133 4.61133C7.71447 4.50818 7.85413 4.4502 8 4.4502Z" fill="#BB3431" stroke="#BB3431" stroke-width="0.1"/>
|
||||
<path d="M8 1.4502C9.73659 1.45203 11.4019 2.14216 12.6299 3.37012C13.8578 4.59807 14.548 6.26341 14.5498 8L14.5459 8.24219C14.5011 9.4527 14.121 10.6288 13.4463 11.6387C12.7266 12.7158 11.7037 13.556 10.5068 14.0518C9.30998 14.5475 7.99226 14.6766 6.72168 14.4238C5.45131 14.171 4.28407 13.5477 3.36816 12.6318C2.45226 11.7159 1.82897 10.5487 1.57617 9.27832C1.32344 8.00774 1.45249 6.69002 1.94824 5.49316C2.444 4.29635 3.28422 3.27341 4.36133 2.55371C5.43841 1.83411 6.70465 1.4502 8 1.4502ZM10.0859 2.96484C9.09008 2.55235 7.99372 2.44401 6.93652 2.6543C5.87938 2.86461 4.90865 3.38432 4.14648 4.14648C3.38432 4.90865 2.8646 5.87938 2.6543 6.93652C2.44401 7.99372 2.55235 9.09008 2.96484 10.0859C3.37729 11.0815 4.07572 11.9325 4.97168 12.5312C5.86793 13.1301 6.92209 13.4502 8 13.4502L8.27051 13.4434C9.61689 13.375 10.8938 12.8093 11.8516 11.8516C12.8733 10.8298 13.4485 9.44492 13.4502 8L13.4355 7.59766C13.3663 6.66142 13.0553 5.75604 12.5312 4.97168C11.9325 4.07572 11.0815 3.37729 10.0859 2.96484ZM8 9.9502C8.21217 9.9502 8.4154 10.0345 8.56543 10.1846C8.71546 10.3346 8.7998 10.5378 8.7998 10.75C8.7998 10.9082 8.75294 11.0628 8.66504 11.1943C8.57713 11.3259 8.45184 11.4287 8.30566 11.4893C8.15961 11.5496 7.99877 11.565 7.84375 11.5342C7.68867 11.5033 7.54639 11.4272 7.43457 11.3154C7.32275 11.2036 7.24672 11.0613 7.21582 10.9062C7.18499 10.7512 7.20035 10.5904 7.26074 10.4443C7.32129 10.2982 7.4241 10.1729 7.55566 10.085C7.68722 9.99706 7.84178 9.9502 8 9.9502ZM8 4.4502C8.14587 4.4502 8.28553 4.50818 8.38867 4.61133C8.49182 4.71447 8.5498 4.85413 8.5498 5V8.5C8.5498 8.64587 8.49182 8.78553 8.38867 8.88867C8.28553 8.99182 8.14587 9.0498 8 9.0498C7.85413 9.0498 7.71447 8.99182 7.61133 8.88867C7.50818 8.78553 7.4502 8.64587 7.4502 8.5V5C7.4502 4.85413 7.50818 4.71447 7.61133 4.61133C7.71447 4.50818 7.85413 4.4502 8 4.4502Z" fill="currentColor" stroke="currentColor" stroke-width="0.1"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2026-07-23 08:54+0500\n"
|
||||
"POT-Creation-Date: 2026-07-23 09:01+0500\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -1624,6 +1624,10 @@ msgstr "Change your account password"
|
||||
msgid "Change your primary two-factor authentication method"
|
||||
msgstr "Change your primary two-factor authentication method"
|
||||
|
||||
#: src/strings.ts:3040
|
||||
msgid "Changes from other devices won't be updated in the editor in real-time."
|
||||
msgstr "Changes from other devices won't be updated in the editor in real-time."
|
||||
|
||||
#: src/strings.ts:2785
|
||||
msgid "Changing Inbox PGP keys will delete all your unsynced inbox items."
|
||||
msgstr "Changing Inbox PGP keys will delete all your unsynced inbox items."
|
||||
@@ -2616,6 +2620,10 @@ msgstr "Did you save recovery key?"
|
||||
msgid "Disable"
|
||||
msgstr "Disable"
|
||||
|
||||
#: src/strings.ts:3035
|
||||
msgid "Disable auto sync"
|
||||
msgstr "Disable auto sync"
|
||||
|
||||
#: src/strings.ts:2071
|
||||
msgid "Disable editor margins"
|
||||
msgstr "Disable editor margins"
|
||||
@@ -2624,6 +2632,14 @@ msgstr "Disable editor margins"
|
||||
msgid "Disable Inbox API"
|
||||
msgstr "Disable Inbox API"
|
||||
|
||||
#: src/strings.ts:3038
|
||||
msgid "Disable realtime sync"
|
||||
msgstr "Disable realtime sync"
|
||||
|
||||
#: src/strings.ts:3041
|
||||
msgid "Disable sync"
|
||||
msgstr "Disable sync"
|
||||
|
||||
#: src/strings.ts:165
|
||||
msgid "Disabled"
|
||||
msgstr "Disabled"
|
||||
@@ -7805,6 +7821,10 @@ msgstr "Tue"
|
||||
msgid "Tuesday"
|
||||
msgstr "Tuesday"
|
||||
|
||||
#: src/strings.ts:3037
|
||||
msgid "Turn off automatic syncing. Changes from this client will be synced only when you run sync manually."
|
||||
msgstr "Turn off automatic syncing. Changes from this client will be synced only when you run sync manually."
|
||||
|
||||
#: src/strings.ts:939
|
||||
msgid "Turn off reminder"
|
||||
msgstr "Turn off reminder"
|
||||
@@ -7814,6 +7834,7 @@ msgid "Turn on reminder"
|
||||
msgstr "Turn on reminder"
|
||||
|
||||
#: src/strings.ts:1145
|
||||
#: src/strings.ts:3043
|
||||
msgid "Turns off syncing completely on this device. Any changes made will remain local only and new changes from your other devices won't sync to this device."
|
||||
msgstr "Turns off syncing completely on this device. Any changes made will remain local only and new changes from your other devices won't sync to this device."
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2026-07-23 08:54+0500\n"
|
||||
"POT-Creation-Date: 2026-07-23 09:01+0500\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -1624,6 +1624,10 @@ msgstr ""
|
||||
msgid "Change your primary two-factor authentication method"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:3040
|
||||
msgid "Changes from other devices won't be updated in the editor in real-time."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2785
|
||||
msgid "Changing Inbox PGP keys will delete all your unsynced inbox items."
|
||||
msgstr ""
|
||||
@@ -2605,6 +2609,10 @@ msgstr ""
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:3035
|
||||
msgid "Disable auto sync"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2071
|
||||
msgid "Disable editor margins"
|
||||
msgstr ""
|
||||
@@ -2613,6 +2621,14 @@ msgstr ""
|
||||
msgid "Disable Inbox API"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:3038
|
||||
msgid "Disable realtime sync"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:3041
|
||||
msgid "Disable sync"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:165
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
@@ -7764,6 +7780,10 @@ msgstr ""
|
||||
msgid "Tuesday"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:3037
|
||||
msgid "Turn off automatic syncing. Changes from this client will be synced only when you run sync manually."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:939
|
||||
msgid "Turn off reminder"
|
||||
msgstr ""
|
||||
@@ -7773,6 +7793,7 @@ msgid "Turn on reminder"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:1145
|
||||
#: src/strings.ts:3043
|
||||
msgid "Turns off syncing completely on this device. Any changes made will remain local only and new changes from your other devices won't sync to this device."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -3045,5 +3045,14 @@ Continue without attachments?`,
|
||||
enterVaultPassword: () => t`Enter vault password`,
|
||||
valueMustBeGreaterThan: (value: string) =>
|
||||
t`Value must be greater than ${value}`,
|
||||
openLocation: () => t`Open location`
|
||||
openLocation: () => t`Open location`,
|
||||
disableAutoSync: () => t`Disable auto sync`,
|
||||
disableAutoSyncDesc: () =>
|
||||
t`Turn off automatic syncing. Changes from this client will be synced only when you run sync manually.`,
|
||||
disableRealtimeSync: () => t`Disable realtime sync`,
|
||||
disableRealtimeSyncDesc: () =>
|
||||
t`Changes from other devices won't be updated in the editor in real-time.`,
|
||||
disableSync: () => t`Disable sync`,
|
||||
disableSyncDesc: () =>
|
||||
t`Turns off syncing completely on this device. Any changes made will remain local only and new changes from your other devices won't sync to this device.`
|
||||
};
|
||||
|
||||
@@ -88,7 +88,8 @@ export class ThemeFactory {
|
||||
spacing10: 35,
|
||||
spacing11: 40,
|
||||
spacing12: 45,
|
||||
spacing13: 50
|
||||
spacing13: 50,
|
||||
auto: "auto"
|
||||
}),
|
||||
sizes: { full: "100%", half: "50%" },
|
||||
radii: {
|
||||
|
||||
@@ -70,6 +70,50 @@ export const createButtonVariant = (
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* will eventually replace createButtonVariant when redesign is completed
|
||||
*/
|
||||
export const newCreateButtonVariant = (
|
||||
background: SchemeColors = "transparent",
|
||||
color: SchemeColors = "paragraph",
|
||||
states?: {
|
||||
hover?: ThemeUIStyleObject;
|
||||
active?: ThemeUIStyleObject;
|
||||
}
|
||||
): ThemeUIStyleObject => ({
|
||||
...createButtonVariant(background, color, states),
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
alignSelf: "center",
|
||||
display: "flex",
|
||||
paddingY: "spacing6",
|
||||
paddingX: "spacing5",
|
||||
fontSize: "md",
|
||||
fontWeight: 600,
|
||||
borderRadius: "radius2",
|
||||
lineHeight: "100%"
|
||||
});
|
||||
|
||||
const newAccent = newCreateButtonVariant("accent", "accentForeground", {
|
||||
hover: { bg: alpha("accent", 0.9) },
|
||||
active: { bg: alpha("accent", 0.8) }
|
||||
});
|
||||
|
||||
const newBordered: ThemeUIStyleObject = {
|
||||
...newCreateButtonVariant("transparent", "buttonForeground-secondary", {
|
||||
hover: { bg: "hover" },
|
||||
active: { bg: "hover" }
|
||||
}),
|
||||
border: "1px solid",
|
||||
borderColor: "border"
|
||||
};
|
||||
|
||||
const newAnchor: ThemeUIStyleObject = {
|
||||
variant: "buttons.anchor",
|
||||
fontSize: "sm",
|
||||
fontWeight: 500
|
||||
};
|
||||
|
||||
const primary = createButtonVariant("transparent", "paragraph", {
|
||||
hover: { bg: "hover" },
|
||||
active: { bg: "hover" }
|
||||
@@ -152,11 +196,14 @@ export const buttonVariants = {
|
||||
tertiary,
|
||||
|
||||
accent,
|
||||
new_accent: newAccent,
|
||||
new_bordered: newBordered,
|
||||
accentSecondary,
|
||||
error,
|
||||
errorSecondary,
|
||||
|
||||
anchor,
|
||||
new_anchor: newAnchor,
|
||||
dialog,
|
||||
statusitem: statusItem,
|
||||
icon: menuItem,
|
||||
|
||||
@@ -40,8 +40,6 @@ export interface FlexProps
|
||||
sx?: RestrictedSxProp;
|
||||
}
|
||||
|
||||
export const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
|
||||
(props, ref) => {
|
||||
return <ThemeUIFlex ref={ref} {...props} />;
|
||||
}
|
||||
);
|
||||
export const Flex = React.forwardRef<HTMLElement, FlexProps>((props, ref) => {
|
||||
return <ThemeUIFlex ref={ref} {...props} />;
|
||||
});
|
||||
|
||||
@@ -18,13 +18,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Theme, ThemeColor } from "@notesnook/theme";
|
||||
import { ThemeUIStyleObject } from "@theme-ui/core";
|
||||
import { ThemeUICSSObject } from "@theme-ui/core";
|
||||
|
||||
type ThemeSpace = Theme["space"];
|
||||
|
||||
type ValidSpaceValues =
|
||||
| Exclude<keyof ThemeSpace, keyof Array<any> | "small">
|
||||
| Exclude<keyof ThemeSpace, keyof Array<any> | "small" | "auto">
|
||||
| "small"
|
||||
| "auto"
|
||||
| number;
|
||||
|
||||
export type RestrictedColorProps = {
|
||||
@@ -66,7 +67,7 @@ export type RestrictedSpaceProps = {
|
||||
};
|
||||
|
||||
export type RestrictedSxProp = Omit<
|
||||
ThemeUIStyleObject,
|
||||
ThemeUICSSObject,
|
||||
keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
> &
|
||||
RestrictedSpaceProps &
|
||||
|
||||