From c833176b638eeb1cdc8b30d4aef632a25ede3777 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 14 Jul 2023 23:01:33 +0800 Subject: ... --- FrontEnd/src/common.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'FrontEnd/src/common.ts') diff --git a/FrontEnd/src/common.ts b/FrontEnd/src/common.ts index 965f9933..6dcd2a9e 100644 --- a/FrontEnd/src/common.ts +++ b/FrontEnd/src/common.ts @@ -8,3 +8,13 @@ export const highlightTimelineUsername = "crupest"; export type { I18nText } from "./i18n"; export { c, convertI18nText } from "./i18n"; export { default as useC } from "./utilities/hooks/use-c"; + +export const themeColors = [ + "primary", + "secondary", + "tertiary", + "danger", + "success", +] as const; + +export type ThemeColor = (typeof themeColors)[number]; -- cgit v1.2.3 From 59c424a38809be6afb170f11eadb0e4d14f10f69 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 14 Jul 2023 23:35:46 +0800 Subject: ... --- FrontEnd/src/common.ts | 10 - FrontEnd/src/index.css | 1 - FrontEnd/src/views/common/Card.css | 7 +- FrontEnd/src/views/common/button/Button.css | 12 +- FrontEnd/src/views/common/button/FlatButton.css | 2 +- FrontEnd/src/views/common/index.css | 8 + FrontEnd/src/views/common/theme-color.css | 260 +++++++++++++++++++++++ FrontEnd/src/views/common/theme.css | 261 +----------------------- 8 files changed, 279 insertions(+), 282 deletions(-) create mode 100644 FrontEnd/src/views/common/theme-color.css (limited to 'FrontEnd/src/common.ts') diff --git a/FrontEnd/src/common.ts b/FrontEnd/src/common.ts index 6dcd2a9e..965f9933 100644 --- a/FrontEnd/src/common.ts +++ b/FrontEnd/src/common.ts @@ -8,13 +8,3 @@ export const highlightTimelineUsername = "crupest"; export type { I18nText } from "./i18n"; export { c, convertI18nText } from "./i18n"; export { default as useC } from "./utilities/hooks/use-c"; - -export const themeColors = [ - "primary", - "secondary", - "tertiary", - "danger", - "success", -] as const; - -export type ThemeColor = (typeof themeColors)[number]; diff --git a/FrontEnd/src/index.css b/FrontEnd/src/index.css index 925d9c26..3478db05 100644 --- a/FrontEnd/src/index.css +++ b/FrontEnd/src/index.css @@ -1,4 +1,3 @@ -@import "npm:bootstrap/dist/css/bootstrap-reboot.css"; @import "npm:bootstrap/dist/css/bootstrap-grid.css"; @import "npm:bootstrap-icons/font/bootstrap-icons.css"; diff --git a/FrontEnd/src/views/common/Card.css b/FrontEnd/src/views/common/Card.css index 6de0dd8e..fa470130 100644 --- a/FrontEnd/src/views/common/Card.css +++ b/FrontEnd/src/views/common/Card.css @@ -1,15 +1,10 @@ -:root { - --cru-card-border-radius: 8px; -} - .cru-card { border: 1px solid; border-color: #e9ecef; border-radius: var(--cru-card-border-radius); - background: #fefeff; transition: all 0.3s; } .cru-card:hover { border-color: var(--cru-primary-color); -} +} \ No newline at end of file diff --git a/FrontEnd/src/views/common/button/Button.css b/FrontEnd/src/views/common/button/Button.css index 7a271446..0df22ebe 100644 --- a/FrontEnd/src/views/common/button/Button.css +++ b/FrontEnd/src/views/common/button/Button.css @@ -9,11 +9,11 @@ } .cru-button:not(.outline):hover { - background-color: var(--cru-theme-b1-color); + background-color: var(--cru-theme-d1-color); } .cru-button:not(.outline):active { - background-color: var(--cru-theme-b2-color); + background-color: var(--cru-theme-d2-color); } .cru-button:not(.outline):disabled { @@ -32,14 +32,14 @@ } .cru-button.outline:hover { - color: var(--cru-theme-b1-color); - border-color: var(--cru-theme-b1-color); + color: var(--cru-theme-d1-color); + border-color: var(--cru-theme-d1-color); background-color: var(--cru-background-color); } .cru-button.outline:active { - color: var(--cru-theme-b2-color); - border-color: var(--cru-theme-b2-color); + color: var(--cru-theme-l2-color); + border-color: var(--cru-theme-l2-color); background-color: var(--cru-background-1-color); } diff --git a/FrontEnd/src/views/common/button/FlatButton.css b/FrontEnd/src/views/common/button/FlatButton.css index ea45e783..01eabca9 100644 --- a/FrontEnd/src/views/common/button/FlatButton.css +++ b/FrontEnd/src/views/common/button/FlatButton.css @@ -9,7 +9,7 @@ } .cru-flat-button.disabled { - color: var(--cru-theme-f1-color); + color: var(--cru-disabled-color); cursor: default; } diff --git a/FrontEnd/src/views/common/index.css b/FrontEnd/src/views/common/index.css index 16a7f924..9d69997b 100644 --- a/FrontEnd/src/views/common/index.css +++ b/FrontEnd/src/views/common/index.css @@ -1,10 +1,18 @@ @import "./theme.css"; +* { + box-sizing: border-box; + margin-inline: 0; + margin-block: 0; +} + body { background: var(--cru-bg-color); color: var(--cru-text-color); + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } + .cru-text-center { text-align: center; } diff --git a/FrontEnd/src/views/common/theme-color.css b/FrontEnd/src/views/common/theme-color.css new file mode 100644 index 00000000..9dfa1d9a --- /dev/null +++ b/FrontEnd/src/views/common/theme-color.css @@ -0,0 +1,260 @@ +/* Generated by theme-generator.ts */ + +:root { + --cru-primary-color: hsl(210 100% 50%); + --cru-primary-l1-color: hsl(210 100% 55%); + --cru-primary-l2-color: hsl(210 100% 60%); + --cru-primary-l3-color: hsl(210 100% 65%); + --cru-primary-d1-color: hsl(210 100% 45%); + --cru-primary-d2-color: hsl(210 100% 40%); + --cru-primary-d3-color: hsl(210 100% 35%); + --cru-primary-f1-color: hsl(210 100% 55%); + --cru-primary-f2-color: hsl(210 100% 60%); + --cru-primary-f3-color: hsl(210 100% 65%); + --cru-primary-b1-color: hsl(210 100% 45%); + --cru-primary-b2-color: hsl(210 100% 40%); + --cru-primary-b3-color: hsl(210 100% 35%); + --cru-secondary-color: hsl(40 100% 50%); + --cru-secondary-l1-color: hsl(40 100% 55%); + --cru-secondary-l2-color: hsl(40 100% 60%); + --cru-secondary-l3-color: hsl(40 100% 65%); + --cru-secondary-d1-color: hsl(40 100% 45%); + --cru-secondary-d2-color: hsl(40 100% 40%); + --cru-secondary-d3-color: hsl(40 100% 35%); + --cru-secondary-f1-color: hsl(40 100% 55%); + --cru-secondary-f2-color: hsl(40 100% 60%); + --cru-secondary-f3-color: hsl(40 100% 65%); + --cru-secondary-b1-color: hsl(40 100% 45%); + --cru-secondary-b2-color: hsl(40 100% 40%); + --cru-secondary-b3-color: hsl(40 100% 35%); + --cru-tertiary-color: hsl(160 100% 50%); + --cru-tertiary-l1-color: hsl(160 100% 55%); + --cru-tertiary-l2-color: hsl(160 100% 60%); + --cru-tertiary-l3-color: hsl(160 100% 65%); + --cru-tertiary-d1-color: hsl(160 100% 45%); + --cru-tertiary-d2-color: hsl(160 100% 40%); + --cru-tertiary-d3-color: hsl(160 100% 35%); + --cru-tertiary-f1-color: hsl(160 100% 55%); + --cru-tertiary-f2-color: hsl(160 100% 60%); + --cru-tertiary-f3-color: hsl(160 100% 65%); + --cru-tertiary-b1-color: hsl(160 100% 45%); + --cru-tertiary-b2-color: hsl(160 100% 40%); + --cru-tertiary-b3-color: hsl(160 100% 35%); + --cru-danger-color: hsl(0 100% 50%); + --cru-danger-l1-color: hsl(0 100% 55%); + --cru-danger-l2-color: hsl(0 100% 60%); + --cru-danger-l3-color: hsl(0 100% 65%); + --cru-danger-d1-color: hsl(0 100% 45%); + --cru-danger-d2-color: hsl(0 100% 40%); + --cru-danger-d3-color: hsl(0 100% 35%); + --cru-danger-f1-color: hsl(0 100% 55%); + --cru-danger-f2-color: hsl(0 100% 60%); + --cru-danger-f3-color: hsl(0 100% 65%); + --cru-danger-b1-color: hsl(0 100% 45%); + --cru-danger-b2-color: hsl(0 100% 40%); + --cru-danger-b3-color: hsl(0 100% 35%); + --cru-success-color: hsl(120 60% 50%); + --cru-success-l1-color: hsl(120 60% 55%); + --cru-success-l2-color: hsl(120 60% 60%); + --cru-success-l3-color: hsl(120 60% 65%); + --cru-success-d1-color: hsl(120 60% 45%); + --cru-success-d2-color: hsl(120 60% 40%); + --cru-success-d3-color: hsl(120 60% 35%); + --cru-success-f1-color: hsl(120 60% 55%); + --cru-success-f2-color: hsl(120 60% 60%); + --cru-success-f3-color: hsl(120 60% 65%); + --cru-success-b1-color: hsl(120 60% 45%); + --cru-success-b2-color: hsl(120 60% 40%); + --cru-success-b3-color: hsl(120 60% 35%); + --cru-text-color: hsl(0 0% 0%); + --cru-text-1-color: hsl(0 0% 5%); + --cru-text-2-color: hsl(0 0% 10%); + --cru-text-3-color: hsl(0 0% 15%); + --cru-bg-color: hsl(0 0% 100%); + --cru-bg-1-color: hsl(0 0% 95%); + --cru-bg-2-color: hsl(0 0% 90%); + --cru-bg-3-color: hsl(0 0% 85%); + --cru-light-color: hsl(0 0% 100%); + --cru-light-1-color: hsl(0 0% 95%); + --cru-light-2-color: hsl(0 0% 90%); + --cru-light-3-color: hsl(0 0% 85%); + --cru-dark-color: hsl(0 0% 0%); + --cru-dark-1-color: hsl(0 0% 5%); + --cru-dark-2-color: hsl(0 0% 10%); + --cru-dark-3-color: hsl(0 0% 15%); + --cru-disabled-color: hsl(0 0% 75%); + --cru-disabled-1-color: hsl(0 0% 70%); + --cru-disabled-2-color: hsl(0 0% 65%); + --cru-disabled-3-color: hsl(0 0% 60%); +} + +@media (prefers-color-scheme: dark) { + :root { + --cru-primary-color: hsl(210 100% 50%); + --cru-primary-l1-color: hsl(210 100% 55%); + --cru-primary-l2-color: hsl(210 100% 60%); + --cru-primary-l3-color: hsl(210 100% 65%); + --cru-primary-d1-color: hsl(210 100% 45%); + --cru-primary-d2-color: hsl(210 100% 40%); + --cru-primary-d3-color: hsl(210 100% 35%); + --cru-primary-f1-color: hsl(210 100% 45%); + --cru-primary-f2-color: hsl(210 100% 40%); + --cru-primary-f3-color: hsl(210 100% 35%); + --cru-primary-b1-color: hsl(210 100% 55%); + --cru-primary-b2-color: hsl(210 100% 60%); + --cru-primary-b3-color: hsl(210 100% 65%); + --cru-secondary-color: hsl(40 100% 50%); + --cru-secondary-l1-color: hsl(40 100% 55%); + --cru-secondary-l2-color: hsl(40 100% 60%); + --cru-secondary-l3-color: hsl(40 100% 65%); + --cru-secondary-d1-color: hsl(40 100% 45%); + --cru-secondary-d2-color: hsl(40 100% 40%); + --cru-secondary-d3-color: hsl(40 100% 35%); + --cru-secondary-f1-color: hsl(40 100% 45%); + --cru-secondary-f2-color: hsl(40 100% 40%); + --cru-secondary-f3-color: hsl(40 100% 35%); + --cru-secondary-b1-color: hsl(40 100% 55%); + --cru-secondary-b2-color: hsl(40 100% 60%); + --cru-secondary-b3-color: hsl(40 100% 65%); + --cru-tertiary-color: hsl(160 100% 50%); + --cru-tertiary-l1-color: hsl(160 100% 55%); + --cru-tertiary-l2-color: hsl(160 100% 60%); + --cru-tertiary-l3-color: hsl(160 100% 65%); + --cru-tertiary-d1-color: hsl(160 100% 45%); + --cru-tertiary-d2-color: hsl(160 100% 40%); + --cru-tertiary-d3-color: hsl(160 100% 35%); + --cru-tertiary-f1-color: hsl(160 100% 45%); + --cru-tertiary-f2-color: hsl(160 100% 40%); + --cru-tertiary-f3-color: hsl(160 100% 35%); + --cru-tertiary-b1-color: hsl(160 100% 55%); + --cru-tertiary-b2-color: hsl(160 100% 60%); + --cru-tertiary-b3-color: hsl(160 100% 65%); + --cru-danger-color: hsl(0 100% 50%); + --cru-danger-l1-color: hsl(0 100% 55%); + --cru-danger-l2-color: hsl(0 100% 60%); + --cru-danger-l3-color: hsl(0 100% 65%); + --cru-danger-d1-color: hsl(0 100% 45%); + --cru-danger-d2-color: hsl(0 100% 40%); + --cru-danger-d3-color: hsl(0 100% 35%); + --cru-danger-f1-color: hsl(0 100% 45%); + --cru-danger-f2-color: hsl(0 100% 40%); + --cru-danger-f3-color: hsl(0 100% 35%); + --cru-danger-b1-color: hsl(0 100% 55%); + --cru-danger-b2-color: hsl(0 100% 60%); + --cru-danger-b3-color: hsl(0 100% 65%); + --cru-success-color: hsl(120 60% 50%); + --cru-success-l1-color: hsl(120 60% 55%); + --cru-success-l2-color: hsl(120 60% 60%); + --cru-success-l3-color: hsl(120 60% 65%); + --cru-success-d1-color: hsl(120 60% 45%); + --cru-success-d2-color: hsl(120 60% 40%); + --cru-success-d3-color: hsl(120 60% 35%); + --cru-success-f1-color: hsl(120 60% 45%); + --cru-success-f2-color: hsl(120 60% 40%); + --cru-success-f3-color: hsl(120 60% 35%); + --cru-success-b1-color: hsl(120 60% 55%); + --cru-success-b2-color: hsl(120 60% 60%); + --cru-success-b3-color: hsl(120 60% 65%); + --cru-text-color: hsl(0 0% 100%); + --cru-text-1-color: hsl(0 0% 95%); + --cru-text-2-color: hsl(0 0% 90%); + --cru-text-3-color: hsl(0 0% 85%); + --cru-bg-color: hsl(0 0% 0%); + --cru-bg-1-color: hsl(0 0% 5%); + --cru-bg-2-color: hsl(0 0% 10%); + --cru-bg-3-color: hsl(0 0% 15%); + --cru-light-color: hsl(0 0% 100%); + --cru-light-1-color: hsl(0 0% 95%); + --cru-light-2-color: hsl(0 0% 90%); + --cru-light-3-color: hsl(0 0% 85%); + --cru-dark-color: hsl(0 0% 0%); + --cru-dark-1-color: hsl(0 0% 5%); + --cru-dark-2-color: hsl(0 0% 10%); + --cru-dark-3-color: hsl(0 0% 15%); + --cru-disabled-color: hsl(0 0% 25%); + --cru-disabled-1-color: hsl(0 0% 30%); + --cru-disabled-2-color: hsl(0 0% 35%); + --cru-disabled-3-color: hsl(0 0% 40%); + } +} + +.cru-primary { + --cru-theme-color: var(--cru-primary-color); + --cru-theme-l1-color: var(--cru-primary-l1-color); + --cru-theme-l2-color: var(--cru-primary-l2-color); + --cru-theme-l3-color: var(--cru-primary-l3-color); + --cru-theme-d1-color: var(--cru-primary-d1-color); + --cru-theme-d2-color: var(--cru-primary-d2-color); + --cru-theme-d3-color: var(--cru-primary-d3-color); + --cru-theme-f1-color: var(--cru-primary-f1-color); + --cru-theme-f2-color: var(--cru-primary-f2-color); + --cru-theme-f3-color: var(--cru-primary-f3-color); + --cru-theme-b1-color: var(--cru-primary-b1-color); + --cru-theme-b2-color: var(--cru-primary-b2-color); + --cru-theme-b3-color: var(--cru-primary-b3-color); +} + +.cru-secondary { + --cru-theme-color: var(--cru-secondary-color); + --cru-theme-l1-color: var(--cru-secondary-l1-color); + --cru-theme-l2-color: var(--cru-secondary-l2-color); + --cru-theme-l3-color: var(--cru-secondary-l3-color); + --cru-theme-d1-color: var(--cru-secondary-d1-color); + --cru-theme-d2-color: var(--cru-secondary-d2-color); + --cru-theme-d3-color: var(--cru-secondary-d3-color); + --cru-theme-f1-color: var(--cru-secondary-f1-color); + --cru-theme-f2-color: var(--cru-secondary-f2-color); + --cru-theme-f3-color: var(--cru-secondary-f3-color); + --cru-theme-b1-color: var(--cru-secondary-b1-color); + --cru-theme-b2-color: var(--cru-secondary-b2-color); + --cru-theme-b3-color: var(--cru-secondary-b3-color); +} + +.cru-tertiary { + --cru-theme-color: var(--cru-tertiary-color); + --cru-theme-l1-color: var(--cru-tertiary-l1-color); + --cru-theme-l2-color: var(--cru-tertiary-l2-color); + --cru-theme-l3-color: var(--cru-tertiary-l3-color); + --cru-theme-d1-color: var(--cru-tertiary-d1-color); + --cru-theme-d2-color: var(--cru-tertiary-d2-color); + --cru-theme-d3-color: var(--cru-tertiary-d3-color); + --cru-theme-f1-color: var(--cru-tertiary-f1-color); + --cru-theme-f2-color: var(--cru-tertiary-f2-color); + --cru-theme-f3-color: var(--cru-tertiary-f3-color); + --cru-theme-b1-color: var(--cru-tertiary-b1-color); + --cru-theme-b2-color: var(--cru-tertiary-b2-color); + --cru-theme-b3-color: var(--cru-tertiary-b3-color); +} + +.cru-danger { + --cru-theme-color: var(--cru-danger-color); + --cru-theme-l1-color: var(--cru-danger-l1-color); + --cru-theme-l2-color: var(--cru-danger-l2-color); + --cru-theme-l3-color: var(--cru-danger-l3-color); + --cru-theme-d1-color: var(--cru-danger-d1-color); + --cru-theme-d2-color: var(--cru-danger-d2-color); + --cru-theme-d3-color: var(--cru-danger-d3-color); + --cru-theme-f1-color: var(--cru-danger-f1-color); + --cru-theme-f2-color: var(--cru-danger-f2-color); + --cru-theme-f3-color: var(--cru-danger-f3-color); + --cru-theme-b1-color: var(--cru-danger-b1-color); + --cru-theme-b2-color: var(--cru-danger-b2-color); + --cru-theme-b3-color: var(--cru-danger-b3-color); +} + +.cru-success { + --cru-theme-color: var(--cru-success-color); + --cru-theme-l1-color: var(--cru-success-l1-color); + --cru-theme-l2-color: var(--cru-success-l2-color); + --cru-theme-l3-color: var(--cru-success-l3-color); + --cru-theme-d1-color: var(--cru-success-d1-color); + --cru-theme-d2-color: var(--cru-success-d2-color); + --cru-theme-d3-color: var(--cru-success-d3-color); + --cru-theme-f1-color: var(--cru-success-f1-color); + --cru-theme-f2-color: var(--cru-success-f2-color); + --cru-theme-f3-color: var(--cru-success-f3-color); + --cru-theme-b1-color: var(--cru-success-b1-color); + --cru-theme-b2-color: var(--cru-success-b2-color); + --cru-theme-b3-color: var(--cru-success-b3-color); +} + diff --git a/FrontEnd/src/views/common/theme.css b/FrontEnd/src/views/common/theme.css index 9dfa1d9a..28c16627 100644 --- a/FrontEnd/src/views/common/theme.css +++ b/FrontEnd/src/views/common/theme.css @@ -1,260 +1,5 @@ -/* Generated by theme-generator.ts */ +@import "./theme-color.css"; :root { - --cru-primary-color: hsl(210 100% 50%); - --cru-primary-l1-color: hsl(210 100% 55%); - --cru-primary-l2-color: hsl(210 100% 60%); - --cru-primary-l3-color: hsl(210 100% 65%); - --cru-primary-d1-color: hsl(210 100% 45%); - --cru-primary-d2-color: hsl(210 100% 40%); - --cru-primary-d3-color: hsl(210 100% 35%); - --cru-primary-f1-color: hsl(210 100% 55%); - --cru-primary-f2-color: hsl(210 100% 60%); - --cru-primary-f3-color: hsl(210 100% 65%); - --cru-primary-b1-color: hsl(210 100% 45%); - --cru-primary-b2-color: hsl(210 100% 40%); - --cru-primary-b3-color: hsl(210 100% 35%); - --cru-secondary-color: hsl(40 100% 50%); - --cru-secondary-l1-color: hsl(40 100% 55%); - --cru-secondary-l2-color: hsl(40 100% 60%); - --cru-secondary-l3-color: hsl(40 100% 65%); - --cru-secondary-d1-color: hsl(40 100% 45%); - --cru-secondary-d2-color: hsl(40 100% 40%); - --cru-secondary-d3-color: hsl(40 100% 35%); - --cru-secondary-f1-color: hsl(40 100% 55%); - --cru-secondary-f2-color: hsl(40 100% 60%); - --cru-secondary-f3-color: hsl(40 100% 65%); - --cru-secondary-b1-color: hsl(40 100% 45%); - --cru-secondary-b2-color: hsl(40 100% 40%); - --cru-secondary-b3-color: hsl(40 100% 35%); - --cru-tertiary-color: hsl(160 100% 50%); - --cru-tertiary-l1-color: hsl(160 100% 55%); - --cru-tertiary-l2-color: hsl(160 100% 60%); - --cru-tertiary-l3-color: hsl(160 100% 65%); - --cru-tertiary-d1-color: hsl(160 100% 45%); - --cru-tertiary-d2-color: hsl(160 100% 40%); - --cru-tertiary-d3-color: hsl(160 100% 35%); - --cru-tertiary-f1-color: hsl(160 100% 55%); - --cru-tertiary-f2-color: hsl(160 100% 60%); - --cru-tertiary-f3-color: hsl(160 100% 65%); - --cru-tertiary-b1-color: hsl(160 100% 45%); - --cru-tertiary-b2-color: hsl(160 100% 40%); - --cru-tertiary-b3-color: hsl(160 100% 35%); - --cru-danger-color: hsl(0 100% 50%); - --cru-danger-l1-color: hsl(0 100% 55%); - --cru-danger-l2-color: hsl(0 100% 60%); - --cru-danger-l3-color: hsl(0 100% 65%); - --cru-danger-d1-color: hsl(0 100% 45%); - --cru-danger-d2-color: hsl(0 100% 40%); - --cru-danger-d3-color: hsl(0 100% 35%); - --cru-danger-f1-color: hsl(0 100% 55%); - --cru-danger-f2-color: hsl(0 100% 60%); - --cru-danger-f3-color: hsl(0 100% 65%); - --cru-danger-b1-color: hsl(0 100% 45%); - --cru-danger-b2-color: hsl(0 100% 40%); - --cru-danger-b3-color: hsl(0 100% 35%); - --cru-success-color: hsl(120 60% 50%); - --cru-success-l1-color: hsl(120 60% 55%); - --cru-success-l2-color: hsl(120 60% 60%); - --cru-success-l3-color: hsl(120 60% 65%); - --cru-success-d1-color: hsl(120 60% 45%); - --cru-success-d2-color: hsl(120 60% 40%); - --cru-success-d3-color: hsl(120 60% 35%); - --cru-success-f1-color: hsl(120 60% 55%); - --cru-success-f2-color: hsl(120 60% 60%); - --cru-success-f3-color: hsl(120 60% 65%); - --cru-success-b1-color: hsl(120 60% 45%); - --cru-success-b2-color: hsl(120 60% 40%); - --cru-success-b3-color: hsl(120 60% 35%); - --cru-text-color: hsl(0 0% 0%); - --cru-text-1-color: hsl(0 0% 5%); - --cru-text-2-color: hsl(0 0% 10%); - --cru-text-3-color: hsl(0 0% 15%); - --cru-bg-color: hsl(0 0% 100%); - --cru-bg-1-color: hsl(0 0% 95%); - --cru-bg-2-color: hsl(0 0% 90%); - --cru-bg-3-color: hsl(0 0% 85%); - --cru-light-color: hsl(0 0% 100%); - --cru-light-1-color: hsl(0 0% 95%); - --cru-light-2-color: hsl(0 0% 90%); - --cru-light-3-color: hsl(0 0% 85%); - --cru-dark-color: hsl(0 0% 0%); - --cru-dark-1-color: hsl(0 0% 5%); - --cru-dark-2-color: hsl(0 0% 10%); - --cru-dark-3-color: hsl(0 0% 15%); - --cru-disabled-color: hsl(0 0% 75%); - --cru-disabled-1-color: hsl(0 0% 70%); - --cru-disabled-2-color: hsl(0 0% 65%); - --cru-disabled-3-color: hsl(0 0% 60%); -} - -@media (prefers-color-scheme: dark) { - :root { - --cru-primary-color: hsl(210 100% 50%); - --cru-primary-l1-color: hsl(210 100% 55%); - --cru-primary-l2-color: hsl(210 100% 60%); - --cru-primary-l3-color: hsl(210 100% 65%); - --cru-primary-d1-color: hsl(210 100% 45%); - --cru-primary-d2-color: hsl(210 100% 40%); - --cru-primary-d3-color: hsl(210 100% 35%); - --cru-primary-f1-color: hsl(210 100% 45%); - --cru-primary-f2-color: hsl(210 100% 40%); - --cru-primary-f3-color: hsl(210 100% 35%); - --cru-primary-b1-color: hsl(210 100% 55%); - --cru-primary-b2-color: hsl(210 100% 60%); - --cru-primary-b3-color: hsl(210 100% 65%); - --cru-secondary-color: hsl(40 100% 50%); - --cru-secondary-l1-color: hsl(40 100% 55%); - --cru-secondary-l2-color: hsl(40 100% 60%); - --cru-secondary-l3-color: hsl(40 100% 65%); - --cru-secondary-d1-color: hsl(40 100% 45%); - --cru-secondary-d2-color: hsl(40 100% 40%); - --cru-secondary-d3-color: hsl(40 100% 35%); - --cru-secondary-f1-color: hsl(40 100% 45%); - --cru-secondary-f2-color: hsl(40 100% 40%); - --cru-secondary-f3-color: hsl(40 100% 35%); - --cru-secondary-b1-color: hsl(40 100% 55%); - --cru-secondary-b2-color: hsl(40 100% 60%); - --cru-secondary-b3-color: hsl(40 100% 65%); - --cru-tertiary-color: hsl(160 100% 50%); - --cru-tertiary-l1-color: hsl(160 100% 55%); - --cru-tertiary-l2-color: hsl(160 100% 60%); - --cru-tertiary-l3-color: hsl(160 100% 65%); - --cru-tertiary-d1-color: hsl(160 100% 45%); - --cru-tertiary-d2-color: hsl(160 100% 40%); - --cru-tertiary-d3-color: hsl(160 100% 35%); - --cru-tertiary-f1-color: hsl(160 100% 45%); - --cru-tertiary-f2-color: hsl(160 100% 40%); - --cru-tertiary-f3-color: hsl(160 100% 35%); - --cru-tertiary-b1-color: hsl(160 100% 55%); - --cru-tertiary-b2-color: hsl(160 100% 60%); - --cru-tertiary-b3-color: hsl(160 100% 65%); - --cru-danger-color: hsl(0 100% 50%); - --cru-danger-l1-color: hsl(0 100% 55%); - --cru-danger-l2-color: hsl(0 100% 60%); - --cru-danger-l3-color: hsl(0 100% 65%); - --cru-danger-d1-color: hsl(0 100% 45%); - --cru-danger-d2-color: hsl(0 100% 40%); - --cru-danger-d3-color: hsl(0 100% 35%); - --cru-danger-f1-color: hsl(0 100% 45%); - --cru-danger-f2-color: hsl(0 100% 40%); - --cru-danger-f3-color: hsl(0 100% 35%); - --cru-danger-b1-color: hsl(0 100% 55%); - --cru-danger-b2-color: hsl(0 100% 60%); - --cru-danger-b3-color: hsl(0 100% 65%); - --cru-success-color: hsl(120 60% 50%); - --cru-success-l1-color: hsl(120 60% 55%); - --cru-success-l2-color: hsl(120 60% 60%); - --cru-success-l3-color: hsl(120 60% 65%); - --cru-success-d1-color: hsl(120 60% 45%); - --cru-success-d2-color: hsl(120 60% 40%); - --cru-success-d3-color: hsl(120 60% 35%); - --cru-success-f1-color: hsl(120 60% 45%); - --cru-success-f2-color: hsl(120 60% 40%); - --cru-success-f3-color: hsl(120 60% 35%); - --cru-success-b1-color: hsl(120 60% 55%); - --cru-success-b2-color: hsl(120 60% 60%); - --cru-success-b3-color: hsl(120 60% 65%); - --cru-text-color: hsl(0 0% 100%); - --cru-text-1-color: hsl(0 0% 95%); - --cru-text-2-color: hsl(0 0% 90%); - --cru-text-3-color: hsl(0 0% 85%); - --cru-bg-color: hsl(0 0% 0%); - --cru-bg-1-color: hsl(0 0% 5%); - --cru-bg-2-color: hsl(0 0% 10%); - --cru-bg-3-color: hsl(0 0% 15%); - --cru-light-color: hsl(0 0% 100%); - --cru-light-1-color: hsl(0 0% 95%); - --cru-light-2-color: hsl(0 0% 90%); - --cru-light-3-color: hsl(0 0% 85%); - --cru-dark-color: hsl(0 0% 0%); - --cru-dark-1-color: hsl(0 0% 5%); - --cru-dark-2-color: hsl(0 0% 10%); - --cru-dark-3-color: hsl(0 0% 15%); - --cru-disabled-color: hsl(0 0% 25%); - --cru-disabled-1-color: hsl(0 0% 30%); - --cru-disabled-2-color: hsl(0 0% 35%); - --cru-disabled-3-color: hsl(0 0% 40%); - } -} - -.cru-primary { - --cru-theme-color: var(--cru-primary-color); - --cru-theme-l1-color: var(--cru-primary-l1-color); - --cru-theme-l2-color: var(--cru-primary-l2-color); - --cru-theme-l3-color: var(--cru-primary-l3-color); - --cru-theme-d1-color: var(--cru-primary-d1-color); - --cru-theme-d2-color: var(--cru-primary-d2-color); - --cru-theme-d3-color: var(--cru-primary-d3-color); - --cru-theme-f1-color: var(--cru-primary-f1-color); - --cru-theme-f2-color: var(--cru-primary-f2-color); - --cru-theme-f3-color: var(--cru-primary-f3-color); - --cru-theme-b1-color: var(--cru-primary-b1-color); - --cru-theme-b2-color: var(--cru-primary-b2-color); - --cru-theme-b3-color: var(--cru-primary-b3-color); -} - -.cru-secondary { - --cru-theme-color: var(--cru-secondary-color); - --cru-theme-l1-color: var(--cru-secondary-l1-color); - --cru-theme-l2-color: var(--cru-secondary-l2-color); - --cru-theme-l3-color: var(--cru-secondary-l3-color); - --cru-theme-d1-color: var(--cru-secondary-d1-color); - --cru-theme-d2-color: var(--cru-secondary-d2-color); - --cru-theme-d3-color: var(--cru-secondary-d3-color); - --cru-theme-f1-color: var(--cru-secondary-f1-color); - --cru-theme-f2-color: var(--cru-secondary-f2-color); - --cru-theme-f3-color: var(--cru-secondary-f3-color); - --cru-theme-b1-color: var(--cru-secondary-b1-color); - --cru-theme-b2-color: var(--cru-secondary-b2-color); - --cru-theme-b3-color: var(--cru-secondary-b3-color); -} - -.cru-tertiary { - --cru-theme-color: var(--cru-tertiary-color); - --cru-theme-l1-color: var(--cru-tertiary-l1-color); - --cru-theme-l2-color: var(--cru-tertiary-l2-color); - --cru-theme-l3-color: var(--cru-tertiary-l3-color); - --cru-theme-d1-color: var(--cru-tertiary-d1-color); - --cru-theme-d2-color: var(--cru-tertiary-d2-color); - --cru-theme-d3-color: var(--cru-tertiary-d3-color); - --cru-theme-f1-color: var(--cru-tertiary-f1-color); - --cru-theme-f2-color: var(--cru-tertiary-f2-color); - --cru-theme-f3-color: var(--cru-tertiary-f3-color); - --cru-theme-b1-color: var(--cru-tertiary-b1-color); - --cru-theme-b2-color: var(--cru-tertiary-b2-color); - --cru-theme-b3-color: var(--cru-tertiary-b3-color); -} - -.cru-danger { - --cru-theme-color: var(--cru-danger-color); - --cru-theme-l1-color: var(--cru-danger-l1-color); - --cru-theme-l2-color: var(--cru-danger-l2-color); - --cru-theme-l3-color: var(--cru-danger-l3-color); - --cru-theme-d1-color: var(--cru-danger-d1-color); - --cru-theme-d2-color: var(--cru-danger-d2-color); - --cru-theme-d3-color: var(--cru-danger-d3-color); - --cru-theme-f1-color: var(--cru-danger-f1-color); - --cru-theme-f2-color: var(--cru-danger-f2-color); - --cru-theme-f3-color: var(--cru-danger-f3-color); - --cru-theme-b1-color: var(--cru-danger-b1-color); - --cru-theme-b2-color: var(--cru-danger-b2-color); - --cru-theme-b3-color: var(--cru-danger-b3-color); -} - -.cru-success { - --cru-theme-color: var(--cru-success-color); - --cru-theme-l1-color: var(--cru-success-l1-color); - --cru-theme-l2-color: var(--cru-success-l2-color); - --cru-theme-l3-color: var(--cru-success-l3-color); - --cru-theme-d1-color: var(--cru-success-d1-color); - --cru-theme-d2-color: var(--cru-success-d2-color); - --cru-theme-d3-color: var(--cru-success-d3-color); - --cru-theme-f1-color: var(--cru-success-f1-color); - --cru-theme-f2-color: var(--cru-success-f2-color); - --cru-theme-f3-color: var(--cru-success-f3-color); - --cru-theme-b1-color: var(--cru-success-b1-color); - --cru-theme-b2-color: var(--cru-success-b2-color); - --cru-theme-b3-color: var(--cru-success-b3-color); -} - + --cru-card-border-radius: 8px; +} \ No newline at end of file -- cgit v1.2.3 From 2226efed8c8604a938d060d62565b611722e837c Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 20 Jul 2023 23:01:58 +0800 Subject: ... --- FrontEnd/src/common.ts | 1 + FrontEnd/src/locales/en/translation.json | 3 +- FrontEnd/src/locales/zh/translation.json | 2 +- FrontEnd/src/pages/setting/index.tsx | 279 +++++++++++------------- FrontEnd/src/views/common/Card.tsx | 2 +- FrontEnd/src/views/common/button/Button.tsx | 4 +- FrontEnd/src/views/common/button/FlatButton.tsx | 4 +- FrontEnd/src/views/common/common.ts | 2 +- 8 files changed, 133 insertions(+), 164 deletions(-) (limited to 'FrontEnd/src/common.ts') diff --git a/FrontEnd/src/common.ts b/FrontEnd/src/common.ts index 965f9933..7c053140 100644 --- a/FrontEnd/src/common.ts +++ b/FrontEnd/src/common.ts @@ -6,5 +6,6 @@ export class UiLogicError extends Error {} export const highlightTimelineUsername = "crupest"; export type { I18nText } from "./i18n"; +export type { I18nText as Text } from "./i18n"; export { c, convertI18nText } from "./i18n"; export { default as useC } from "./utilities/hooks/use-c"; diff --git a/FrontEnd/src/locales/en/translation.json b/FrontEnd/src/locales/en/translation.json index 95c722c9..a73472d2 100644 --- a/FrontEnd/src/locales/en/translation.json +++ b/FrontEnd/src/locales/en/translation.json @@ -176,7 +176,7 @@ "noAccount": "If you don't have an account and know a register code, then click <1>here to register." }, "settings": { - "subheaders": { + "subheader": { "account": "Account", "customization": "Customization" }, @@ -186,7 +186,6 @@ "logout": "Log out this account", "changeAvatar": "Change avatar", "changeNickname": "Change nickname", - "changeBookmarkVisibility": "Change bookmark visibility", "myRegisterCode": "My register code:", "myRegisterCodeDesc": "Click to create a new register code.", "renewRegisterCode": "Renew Register Code", diff --git a/FrontEnd/src/locales/zh/translation.json b/FrontEnd/src/locales/zh/translation.json index b7212128..8a2f628f 100644 --- a/FrontEnd/src/locales/zh/translation.json +++ b/FrontEnd/src/locales/zh/translation.json @@ -176,7 +176,7 @@ "noAccount": "如果你没有账号但有一个注册码,请点击<1>这里注册账号。" }, "settings": { - "subheaders": { + "subheader": { "account": "账户", "customization": "个性化" }, diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 00503dcf..4e28585e 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -1,16 +1,21 @@ -import { useState, ReactNode } from "react"; -import { useNavigate } from "react-router-dom"; +import { + useState, + useEffect, + ReactNode, + ComponentPropsWithoutRef, +} from "react"; import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; import classNames from "classnames"; -import { useC, I18nText } from "@/common"; +import { useC, Text } from "@/common"; import { useUser, userService } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; import { TimelineVisibility } from "@/http/timeline"; -import ConfirmDialog from "../common/dialog/ConfirmDialog"; -import Card from "../common/Card"; -import Spinner from "../common/Spinner"; +import ConfirmDialog from "@/views/common/dialog/ConfirmDialog"; +import Card from "@/views/common/Card"; +import Spinner from "@/views/common/Spinner"; import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; @@ -18,99 +23,94 @@ import ChangeNicknameDialog from "./ChangeNicknameDialog"; import "./index.css"; import { pushAlert } from "@/services/alert"; -interface SettingSectionProps { - title: I18nText; +interface SettingSectionProps + extends Omit, "title"> { + title: Text; children: ReactNode; } -function SettingSection({ title, children }: SettingSectionProps) { +function SettingSection({ + title, + className, + children, + ...otherProps +}: SettingSectionProps) { const c = useC(); return ( - -

{c(title)}

+ +

{c(title)}

{children}
); } -interface SettingItemContainerWithoutChildrenProps { - title: I18nText; - subtext?: I18nText; - first?: boolean; - danger?: boolean; - style?: React.CSSProperties; - className?: string; - onClick?: () => void; -} - interface SettingItemContainerProps - extends SettingItemContainerWithoutChildrenProps { - children?: React.ReactNode; + extends Omit, "title"> { + title: Text; + description?: Text; + danger?: boolean; + extraClassName?: string; } function SettingItemContainer({ title, - subtext, - first, + description, danger, - children, - style, + extraClassName, className, - onClick, -}: SettingItemContainerProps): JSX.Element { - const { t } = useTranslation(); + children, + ...otherProps +}: SettingItemContainerProps) { + const c = useC(); return (
-
-
- {convertI18nText(title, t)} -
- - {convertI18nText(subtext, t)} - +
+
{c(title)}
+ {c(description)}
-
{children}
+
{children}
); } -type ButtonSettingItemProps = SettingItemContainerWithoutChildrenProps; +type ButtonSettingItemProps = Omit; -const ButtonSettingItem: React.FC = ({ ...props }) => { - return ; -}; +function ButtonSettingItem(props: ButtonSettingItemProps) { + return ( + + ); +} interface SelectSettingItemProps - extends SettingItemContainerWithoutChildrenProps { + extends Omit { options: { value: string; - label: I18nText; + label: Text; }[]; - value?: string; + value?: string | null; onSelect: (value: string) => void; } -const SelectSettingsItem: React.FC = ({ +function SelectSettingsItem({ options, value, onSelect, - ...props -}) => { - const { t } = useTranslation(); + ...extraProps +}: SelectSettingItemProps) { + const c = useC(); return ( - + {value == null ? ( ) : ( @@ -122,53 +122,30 @@ const SelectSettingsItem: React.FC = ({ > {options.map(({ value, label }) => ( ))} )} ); -}; +} -const SettingsPage: React.FC = () => { - const { i18n } = useTranslation(); +function RegisterCodeSettingItem({ + openRenewDialog, +}: { + openRenewDialog: () => void; +}) { const user = useUser(); - const navigate = useNavigate(); - - const [dialog, setDialog] = useState< - | null - | "changepassword" - | "changeavatar" - | "changenickname" - | "logout" - | "renewregistercode" - >(null); - const [registerCode, setRegisterCode] = useState( - undefined, - ); - - const [bookmarkVisibility, setBookmarkVisibility] = - useState(); - - React.useEffect(() => { - if (user != null) { - void getHttpUserClient() - .getBookmarkVisibility(user.username) - .then(({ visibility }) => { - setBookmarkVisibility(visibility); - }); - } else { - setBookmarkVisibility(undefined); - } - }, [user]); + // undefined: loading + const [registerCode, setRegisterCode] = useState(); - React.useEffect(() => { + useEffect(() => { setRegisterCode(undefined); }, [user]); - React.useEffect(() => { + useEffect(() => { if (user != null && registerCode === undefined) { void getHttpUserClient() .getRegisterCode(user.username) @@ -178,87 +155,81 @@ const SettingsPage: React.FC = () => { } }, [user, registerCode]); + return ( + + {registerCode === undefined ? ( + + ) : registerCode === null ? ( + Noop + ) : ( + { + void navigator.clipboard.writeText(registerCode).then(() => { + pushAlert({ + type: "success", + message: "settings.myRegisterCodeCopied", + }); + }); + event.stopPropagation(); + }} + > + {registerCode} + + )} + + ); +} + +export default function SettingsPage() { + const c = useC(); + const { i18n } = useTranslation(); + const user = useUser(); + const navigate = useNavigate(); + + type DialogName = + | "change-password" + | "change-avatar" + | "change-nickname" + | "logout" + | "renew-register-code"; + + const [dialog, setDialog] = useState(null); + + function dialogOpener(name: DialogName): () => void { + return () => setDialog(name); + } + const language = i18n.language.slice(0, 2); return ( <>
{user ? ( - - setDialog("renewregistercode")} - > - {registerCode === undefined ? ( - - ) : registerCode === null ? ( - Noop - ) : ( - { - void navigator.clipboard - .writeText(registerCode) - .then(() => { - pushAlert({ - type: "success", - message: "settings.myRegisterCodeCopied", - }); - }); - event.stopPropagation(); - }} - > - {registerCode} - - )} - + + setDialog("changeavatar")} - first + onClick={dialogOpener("change-avatar")} /> setDialog("changenickname")} - /> - { - void getHttpUserClient() - .putBookmarkVisibility(user.username, { - visibility: value as TimelineVisibility, - }) - .then(() => { - setBookmarkVisibility(value as TimelineVisibility); - }); - }} + onClick={dialogOpener("change-nickname")} /> setDialog("changepassword")} + onClick={dialogOpener("change-password")} danger /> { - setDialog("logout"); - }} + onClick={dialogOpener("logout")} danger /> @@ -330,6 +301,4 @@ const SettingsPage: React.FC = () => { /> ); -}; - -export default SettingsPage; +} diff --git a/FrontEnd/src/views/common/Card.tsx b/FrontEnd/src/views/common/Card.tsx index 50632006..5ff89b61 100644 --- a/FrontEnd/src/views/common/Card.tsx +++ b/FrontEnd/src/views/common/Card.tsx @@ -4,7 +4,7 @@ import classNames from "classnames"; import "./Card.css"; interface CardProps extends ComponentPropsWithoutRef<"div"> { - containerRef: Ref; + containerRef?: Ref | null; } export default function Card({ diff --git a/FrontEnd/src/views/common/button/Button.tsx b/FrontEnd/src/views/common/button/Button.tsx index e1015f71..0f1bbf2b 100644 --- a/FrontEnd/src/views/common/button/Button.tsx +++ b/FrontEnd/src/views/common/button/Button.tsx @@ -1,13 +1,13 @@ import { ComponentPropsWithoutRef, Ref } from "react"; import classNames from "classnames"; -import { I18nText, useC, ThemeColor } from "../common"; +import { Text, useC, ThemeColor } from "../common"; import "./Button.css"; interface ButtonProps extends ComponentPropsWithoutRef<"button"> { color?: ThemeColor; - text?: I18nText; + text?: Text; outline?: boolean; buttonRef?: Ref | null; } diff --git a/FrontEnd/src/views/common/button/FlatButton.tsx b/FrontEnd/src/views/common/button/FlatButton.tsx index 7b268b6d..ed01f613 100644 --- a/FrontEnd/src/views/common/button/FlatButton.tsx +++ b/FrontEnd/src/views/common/button/FlatButton.tsx @@ -1,13 +1,13 @@ import { ComponentPropsWithoutRef, Ref } from "react"; import classNames from "classnames"; -import { I18nText, useC, ThemeColor } from "../common"; +import { Text, useC, ThemeColor } from "../common"; import "./FlatButton.css"; interface FlatButtonProps extends ComponentPropsWithoutRef<"button"> { color?: ThemeColor; - text?: I18nText; + text?: Text; buttonRef?: Ref | null; } diff --git a/FrontEnd/src/views/common/common.ts b/FrontEnd/src/views/common/common.ts index d3db9f93..4ad41edc 100644 --- a/FrontEnd/src/views/common/common.ts +++ b/FrontEnd/src/views/common/common.ts @@ -1,4 +1,4 @@ -export type { I18nText } from "@/common"; +export type { Text, I18nText } from "@/common"; export { c, convertI18nText, useC } from "@/common"; export const themeColors = [ -- cgit v1.2.3 From 256cc9592a3f31fc392e1ccdb699aa206b7b47ce Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Aug 2023 23:49:28 +0800 Subject: ... --- FrontEnd/src/common.ts | 2 - FrontEnd/src/components/AppBar.tsx | 3 +- FrontEnd/src/components/Card.tsx | 1 + FrontEnd/src/components/LoadFailReload.tsx | 37 ------------------ FrontEnd/src/components/LoadingPage.tsx | 13 ------- FrontEnd/src/components/SearchInput.tsx | 2 +- FrontEnd/src/components/button/ButtonRowV2.tsx | 3 +- FrontEnd/src/components/button/LoadingButton.tsx | 1 - FrontEnd/src/components/common.ts | 1 - FrontEnd/src/components/dialog/ConfirmDialog.css | 0 FrontEnd/src/components/dialog/ConfirmDialog.tsx | 1 - FrontEnd/src/components/dialog/OperationDialog.tsx | 7 +--- FrontEnd/src/components/dialog/index.ts | 1 + FrontEnd/src/components/hooks.ts | 14 ------- FrontEnd/src/components/hooks/index.ts | 3 ++ FrontEnd/src/components/hooks/responsive.ts | 7 ++++ FrontEnd/src/components/hooks/useClickOutside.ts | 38 ++++++++++++++++++ FrontEnd/src/components/hooks/useScrollToBottom.ts | 44 +++++++++++++++++++++ FrontEnd/src/components/input/InputGroup.tsx | 16 ++++---- FrontEnd/src/components/menu/Menu.tsx | 2 +- FrontEnd/src/components/menu/PopupMenu.tsx | 6 +-- FrontEnd/src/pages/login/index.tsx | 14 ++----- FrontEnd/src/pages/register/index.tsx | 26 +++++-------- FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx | 5 +-- .../src/pages/setting/ChangePasswordDialog.tsx | 17 ++++---- FrontEnd/src/pages/setting/index.tsx | 11 +++--- FrontEnd/src/pages/timeline/Timeline.tsx | 3 +- .../src/pages/timeline/TimelineDeleteDialog.tsx | 4 +- FrontEnd/src/pages/timeline/TimelinePostView.tsx | 8 ++-- FrontEnd/src/utilities/hooks.ts | 5 --- FrontEnd/src/utilities/hooks/mediaQuery.ts | 5 --- FrontEnd/src/utilities/hooks/useClickOutside.ts | 38 ------------------ FrontEnd/src/utilities/hooks/useScrollToBottom.ts | 45 ---------------------- 33 files changed, 149 insertions(+), 234 deletions(-) delete mode 100644 FrontEnd/src/components/LoadFailReload.tsx delete mode 100644 FrontEnd/src/components/LoadingPage.tsx delete mode 100644 FrontEnd/src/components/dialog/ConfirmDialog.css delete mode 100644 FrontEnd/src/components/hooks.ts create mode 100644 FrontEnd/src/components/hooks/index.ts create mode 100644 FrontEnd/src/components/hooks/responsive.ts create mode 100644 FrontEnd/src/components/hooks/useClickOutside.ts create mode 100644 FrontEnd/src/components/hooks/useScrollToBottom.ts delete mode 100644 FrontEnd/src/utilities/hooks.ts delete mode 100644 FrontEnd/src/utilities/hooks/mediaQuery.ts delete mode 100644 FrontEnd/src/utilities/hooks/useClickOutside.ts delete mode 100644 FrontEnd/src/utilities/hooks/useScrollToBottom.ts (limited to 'FrontEnd/src/common.ts') diff --git a/FrontEnd/src/common.ts b/FrontEnd/src/common.ts index 7c053140..1ca796c3 100644 --- a/FrontEnd/src/common.ts +++ b/FrontEnd/src/common.ts @@ -3,8 +3,6 @@ // This error should never occur. If it does, it indicates there is some logic bug in codes. export class UiLogicError extends Error {} -export const highlightTimelineUsername = "crupest"; - export type { I18nText } from "./i18n"; export type { I18nText as Text } from "./i18n"; export { c, convertI18nText } from "./i18n"; diff --git a/FrontEnd/src/components/AppBar.tsx b/FrontEnd/src/components/AppBar.tsx index da3a946f..1a5c1941 100644 --- a/FrontEnd/src/components/AppBar.tsx +++ b/FrontEnd/src/components/AppBar.tsx @@ -2,9 +2,10 @@ import { useState } from "react"; import classnames from "classnames"; import { Link, NavLink } from "react-router-dom"; -import { I18nText, useC, useMobile } from "./common"; import { useUser } from "~src/services/user"; +import { I18nText, useC } from "./common"; +import { useMobile } from "./hooks"; import TimelineLogo from "./TimelineLogo"; import { IconButton } from "./button"; import UserAvatar from "./user/UserAvatar"; diff --git a/FrontEnd/src/components/Card.tsx b/FrontEnd/src/components/Card.tsx index a8f0d3cc..5d3ef630 100644 --- a/FrontEnd/src/components/Card.tsx +++ b/FrontEnd/src/components/Card.tsx @@ -2,6 +2,7 @@ import { ComponentPropsWithoutRef, Ref } from "react"; import classNames from "classnames"; import { ThemeColor } from "./common"; + import "./Card.css"; interface CardProps extends ComponentPropsWithoutRef<"div"> { diff --git a/FrontEnd/src/components/LoadFailReload.tsx b/FrontEnd/src/components/LoadFailReload.tsx deleted file mode 100644 index 81ba1f67..00000000 --- a/FrontEnd/src/components/LoadFailReload.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from "react"; -import { Trans } from "react-i18next"; - -export interface LoadFailReloadProps { - className?: string; - style?: React.CSSProperties; - onReload: () => void; -} - -const LoadFailReload: React.FC = ({ - onReload, - className, - style, -}) => { - return ( - - 0 - { - onReload(); - e.preventDefault(); - }} - > - 1 - - 2 - - ); -}; - -export default LoadFailReload; diff --git a/FrontEnd/src/components/LoadingPage.tsx b/FrontEnd/src/components/LoadingPage.tsx deleted file mode 100644 index 35ee1aa8..00000000 --- a/FrontEnd/src/components/LoadingPage.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from "react"; - -import Spinner from "./Spinner"; - -const LoadingPage: React.FC = () => { - return ( -
- -
- ); -}; - -export default LoadingPage; diff --git a/FrontEnd/src/components/SearchInput.tsx b/FrontEnd/src/components/SearchInput.tsx index e3216b86..71820bfa 100644 --- a/FrontEnd/src/components/SearchInput.tsx +++ b/FrontEnd/src/components/SearchInput.tsx @@ -1,7 +1,7 @@ import classNames from "classnames"; import { useC, Text } from "./common"; -import LoadingButton from "./button/LoadingButton"; +import { LoadingButton } from "./button"; import "./SearchInput.css"; diff --git a/FrontEnd/src/components/button/ButtonRowV2.tsx b/FrontEnd/src/components/button/ButtonRowV2.tsx index 3467ad52..5129e7f1 100644 --- a/FrontEnd/src/components/button/ButtonRowV2.tsx +++ b/FrontEnd/src/components/button/ButtonRowV2.tsx @@ -1,13 +1,14 @@ import { ComponentPropsWithoutRef, Ref } from "react"; import classNames from "classnames"; +import { Text, ThemeColor } from "../common"; + import Button from "./Button"; import FlatButton from "./FlatButton"; import IconButton from "./IconButton"; import LoadingButton from "./LoadingButton"; import "./ButtonRow.css"; -import { Text, ThemeColor } from "../common"; interface ButtonRowV2ButtonBase { key: string | number; diff --git a/FrontEnd/src/components/button/LoadingButton.tsx b/FrontEnd/src/components/button/LoadingButton.tsx index 7e7d08e6..d9d41ddb 100644 --- a/FrontEnd/src/components/button/LoadingButton.tsx +++ b/FrontEnd/src/components/button/LoadingButton.tsx @@ -1,7 +1,6 @@ import classNames from "classnames"; import { I18nText, ThemeColor, useC } from "../common"; - import Spinner from "../Spinner"; import "./LoadingButton.css"; diff --git a/FrontEnd/src/components/common.ts b/FrontEnd/src/components/common.ts index e6f7319f..b96388ab 100644 --- a/FrontEnd/src/components/common.ts +++ b/FrontEnd/src/components/common.ts @@ -11,4 +11,3 @@ export const themeColors = [ export type ThemeColor = (typeof themeColors)[number]; export { breakpoints } from "./breakpoints"; -export { useMobile } from "./hooks"; diff --git a/FrontEnd/src/components/dialog/ConfirmDialog.css b/FrontEnd/src/components/dialog/ConfirmDialog.css deleted file mode 100644 index e69de29b..00000000 diff --git a/FrontEnd/src/components/dialog/ConfirmDialog.tsx b/FrontEnd/src/components/dialog/ConfirmDialog.tsx index 26939c9b..1d997305 100644 --- a/FrontEnd/src/components/dialog/ConfirmDialog.tsx +++ b/FrontEnd/src/components/dialog/ConfirmDialog.tsx @@ -1,5 +1,4 @@ import { useC, Text, ThemeColor } from "../common"; - import Dialog from "./Dialog"; import DialogContainer from "./DialogContainer"; diff --git a/FrontEnd/src/components/dialog/OperationDialog.tsx b/FrontEnd/src/components/dialog/OperationDialog.tsx index e5db7f4f..96766825 100644 --- a/FrontEnd/src/components/dialog/OperationDialog.tsx +++ b/FrontEnd/src/components/dialog/OperationDialog.tsx @@ -2,23 +2,18 @@ import { useState, ReactNode, ComponentProps } from "react"; import classNames from "classnames"; import { useC, Text, ThemeColor } from "../common"; - import { useInputs, InputGroup, Initializer as InputInitializer, - InputValueDict, - InputErrorDict, InputConfirmValueDict, } from "../input"; +import { ButtonRow } from "../button"; import Dialog from "./Dialog"; import DialogContainer from "./DialogContainer"; -import { ButtonRow } from "../button"; import "./OperationDialog.css"; -export type { InputInitializer, InputValueDict, InputErrorDict }; - interface OperationDialogPromptProps { message?: Text; customMessage?: Text; diff --git a/FrontEnd/src/components/dialog/index.ts b/FrontEnd/src/components/dialog/index.ts index 59f15791..17db8fd0 100644 --- a/FrontEnd/src/components/dialog/index.ts +++ b/FrontEnd/src/components/dialog/index.ts @@ -4,6 +4,7 @@ export { default as Dialog } from "./Dialog"; export { default as FullPageDialog } from "./FullPageDialog"; export { default as OperationDialog } from "./OperationDialog"; export { default as ConfirmDialog } from "./ConfirmDialog"; +export { default as DialogContainer } from "./DialogContainer"; type DialogMap = { [K in D]: V; diff --git a/FrontEnd/src/components/hooks.ts b/FrontEnd/src/components/hooks.ts deleted file mode 100644 index 523a4538..00000000 --- a/FrontEnd/src/components/hooks.ts +++ /dev/null @@ -1,14 +0,0 @@ -// TODO: Migrate hooks - -export { - useIsSmallScreen, - useClickOutside, - useScrollToBottom, -} from "~src/utilities/hooks"; - -import { useMediaQuery } from "react-responsive"; -import { breakpoints } from "./breakpoints"; - -export function useMobile(): boolean { - return useMediaQuery({ maxWidth: breakpoints.sm }); -} diff --git a/FrontEnd/src/components/hooks/index.ts b/FrontEnd/src/components/hooks/index.ts new file mode 100644 index 00000000..3c9859bc --- /dev/null +++ b/FrontEnd/src/components/hooks/index.ts @@ -0,0 +1,3 @@ +export { useMobile } from "./responsive"; +export { default as useClickOutside } from "./useClickOutside"; +export { default as useScrollToBottom } from "./useScrollToBottom"; diff --git a/FrontEnd/src/components/hooks/responsive.ts b/FrontEnd/src/components/hooks/responsive.ts new file mode 100644 index 00000000..6bcce96c --- /dev/null +++ b/FrontEnd/src/components/hooks/responsive.ts @@ -0,0 +1,7 @@ +import { useMediaQuery } from "react-responsive"; + +import { breakpoints } from "../breakpoints"; + +export function useMobile(): boolean { + return useMediaQuery({ maxWidth: breakpoints.sm }); +} diff --git a/FrontEnd/src/components/hooks/useClickOutside.ts b/FrontEnd/src/components/hooks/useClickOutside.ts new file mode 100644 index 00000000..828ce7e3 --- /dev/null +++ b/FrontEnd/src/components/hooks/useClickOutside.ts @@ -0,0 +1,38 @@ +import { useRef, useEffect } from "react"; + +export default function useClickOutside( + element: HTMLElement | null | undefined, + onClickOutside: () => void, + nextTick?: boolean, +): void { + const onClickOutsideRef = useRef<() => void>(onClickOutside); + + useEffect(() => { + onClickOutsideRef.current = onClickOutside; + }, [onClickOutside]); + + useEffect(() => { + if (element != null) { + const handler = (event: MouseEvent): void => { + let e: HTMLElement | null = event.target as HTMLElement; + while (e) { + if (e == element) { + return; + } + e = e.parentElement; + } + onClickOutsideRef.current(); + }; + if (nextTick) { + setTimeout(() => { + document.addEventListener("click", handler); + }); + } else { + document.addEventListener("click", handler); + } + return () => { + document.removeEventListener("click", handler); + }; + } + }, [element, nextTick]); +} diff --git a/FrontEnd/src/components/hooks/useScrollToBottom.ts b/FrontEnd/src/components/hooks/useScrollToBottom.ts new file mode 100644 index 00000000..79fcda16 --- /dev/null +++ b/FrontEnd/src/components/hooks/useScrollToBottom.ts @@ -0,0 +1,44 @@ +import { useRef, useEffect } from "react"; +import { fromEvent, filter, throttleTime } from "rxjs"; + +function useScrollToBottom( + handler: () => void, + enable = true, + option = { + maxOffset: 5, + throttle: 1000, + }, +): void { + const handlerRef = useRef<(() => void) | null>(null); + + useEffect(() => { + handlerRef.current = handler; + + return () => { + handlerRef.current = null; + }; + }, [handler]); + + useEffect(() => { + const subscription = fromEvent(window, "scroll") + .pipe( + filter( + () => + window.scrollY >= + document.body.scrollHeight - window.innerHeight - option.maxOffset, + ), + throttleTime(option.throttle), + ) + .subscribe(() => { + if (enable) { + handlerRef.current?.(); + } + }); + + return () => { + subscription.unsubscribe(); + }; + }, [enable, option.maxOffset, option.throttle]); +} + +export default useScrollToBottom; diff --git a/FrontEnd/src/components/input/InputGroup.tsx b/FrontEnd/src/components/input/InputGroup.tsx index 4f487344..47a43b38 100644 --- a/FrontEnd/src/components/input/InputGroup.tsx +++ b/FrontEnd/src/components/input/InputGroup.tsx @@ -72,12 +72,9 @@ export type InputDirtyDict = Record; // use never so you don't have to cast everywhere export type InputConfirmValueDict = Record; -export type GeneralInputErrorDict = - | { - [key: string]: Text | null | undefined; - } - | null - | undefined; +export type GeneralInputErrorDict = { + [key: string]: Text | null | undefined; +}; type MakeInputInfo = Omit; @@ -87,8 +84,9 @@ export type InputInfo = { export type Validator = ( values: InputValueDict, + errors: GeneralInputErrorDict, inputs: InputInfo[], -) => GeneralInputErrorDict; +) => void; export type InputScheme = { inputs: InputInfo[]; @@ -157,7 +155,9 @@ function validate( values: InputValueDict, inputs: InputInfo[], ): InputErrorDict { - return cleanObject(validator?.(values, inputs) ?? {}); + const errors: GeneralInputErrorDict = {}; + validator?.(values, errors, inputs); + return cleanObject(errors); } export function useInputs(options: { init: Initializer }): { diff --git a/FrontEnd/src/components/menu/Menu.tsx b/FrontEnd/src/components/menu/Menu.tsx index e8099c76..c01c6cfb 100644 --- a/FrontEnd/src/components/menu/Menu.tsx +++ b/FrontEnd/src/components/menu/Menu.tsx @@ -2,9 +2,9 @@ import { CSSProperties } from "react"; import classNames from "classnames"; import { useC, Text, ThemeColor } from "../common"; +import Icon from "../Icon"; import "./Menu.css"; -import Icon from "../Icon"; export type MenuItem = | { diff --git a/FrontEnd/src/components/menu/PopupMenu.tsx b/FrontEnd/src/components/menu/PopupMenu.tsx index 23a67f79..9d90799d 100644 --- a/FrontEnd/src/components/menu/PopupMenu.tsx +++ b/FrontEnd/src/components/menu/PopupMenu.tsx @@ -3,11 +3,9 @@ import classNames from "classnames"; import { createPortal } from "react-dom"; import { usePopper } from "react-popper"; -import { useClickOutside } from "~src/utilities/hooks"; - -import Menu, { MenuItems } from "./Menu"; - import { ThemeColor } from "../common"; +import { useClickOutside } from "../hooks"; +import Menu, { MenuItems } from "./Menu"; import "./PopupMenu.css"; diff --git a/FrontEnd/src/pages/login/index.tsx b/FrontEnd/src/pages/login/index.tsx index 582ebd0f..39ea3831 100644 --- a/FrontEnd/src/pages/login/index.tsx +++ b/FrontEnd/src/pages/login/index.tsx @@ -6,11 +6,7 @@ import { useUser, userService } from "~src/services/user"; import { useC } from "~src/components/common"; import LoadingButton from "~src/components/button/LoadingButton"; -import { - InputErrorDict, - InputGroup, - useInputs, -} from "~src/components/input/InputGroup"; +import { InputGroup, useInputs } from "~src/components/input/InputGroup"; import Page from "~src/components/Page"; import "./index.css"; @@ -47,15 +43,13 @@ export default function LoginPage() { label: "user.rememberMe", }, ], - validator: ({ username, password }) => { - const result: InputErrorDict = {}; + validator: ({ username, password }, errors) => { if (username === "") { - result["username"] = "login.emptyUsername"; + errors["username"] = "login.emptyUsername"; } if (password === "") { - result["password"] = "login.emptyPassword"; + errors["password"] = "login.emptyPassword"; } - return result; }, }, dataInit: {}, diff --git a/FrontEnd/src/pages/register/index.tsx b/FrontEnd/src/pages/register/index.tsx index 9e478612..fa25c2c2 100644 --- a/FrontEnd/src/pages/register/index.tsx +++ b/FrontEnd/src/pages/register/index.tsx @@ -7,11 +7,7 @@ import { getHttpTokenClient } from "~src/http/token"; import { userService, useUser } from "~src/services/user"; import { LoadingButton } from "~src/components/button"; -import { - useInputs, - InputErrorDict, - InputGroup, -} from "~src/components/input/InputGroup"; +import { useInputs, InputGroup } from "~src/components/input/InputGroup"; import "./index.css"; @@ -51,26 +47,22 @@ export default function RegisterPage() { label: "register.registerCode", }, ], - validator: ({ - username, - password, - confirmPassword, - registerCode, - }) => { - const result: InputErrorDict = {}; + validator: ( + { username, password, confirmPassword, registerCode }, + errors, + ) => { if (username === "") { - result["username"] = "register.error.usernameEmpty"; + errors["username"] = "register.error.usernameEmpty"; } if (password === "") { - result["password"] = "register.error.passwordEmpty"; + errors["password"] = "register.error.passwordEmpty"; } if (confirmPassword !== password) { - result["confirmPassword"] = "register.error.confirmPasswordWrong"; + errors["confirmPassword"] = "register.error.confirmPasswordWrong"; } if (registerCode === "") { - result["registerCode"] = "register.error.registerCodeEmpty"; + errors["registerCode"] = "register.error.registerCodeEmpty"; } - return result; }, }, dataInit: {}, diff --git a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx index c34bcf4f..011c5059 100644 --- a/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangeAvatarDialog.tsx @@ -11,9 +11,8 @@ import ImageCropper, { applyClipToImage, } from "~src/components/ImageCropper"; import BlobImage from "~src/components/BlobImage"; -import ButtonRowV2 from "~src/components/button/ButtonRowV2"; -import Dialog from "~src/components/dialog/Dialog"; -import DialogContainer from "~src/components/dialog/DialogContainer"; +import { ButtonRowV2 } from "~src/components/button"; +import { Dialog, DialogContainer } from "~src/components/dialog"; import "./ChangeAvatarDialog.css"; diff --git a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx index bfcea92d..946b9fbe 100644 --- a/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx +++ b/FrontEnd/src/pages/setting/ChangePasswordDialog.tsx @@ -3,9 +3,7 @@ import { useNavigate } from "react-router-dom"; import { userService } from "~src/services/user"; -import OperationDialog, { - InputErrorDict, -} from "~src/components/dialog/OperationDialog"; +import { OperationDialog } from "~src/components/dialog"; interface ChangePasswordDialogProps { open: boolean; @@ -47,21 +45,22 @@ export function ChangePasswordDialog(props: ChangePasswordDialogProps) { password: true, }, ], - validator: ({ oldPassword, newPassword, retypedNewPassword }) => { - const result: InputErrorDict = {}; + validator: ( + { oldPassword, newPassword, retypedNewPassword }, + errors, + ) => { if (oldPassword === "") { - result["oldPassword"] = + errors["oldPassword"] = "settings.dialogChangePassword.errorEmptyOldPassword"; } if (newPassword === "") { - result["newPassword"] = + errors["newPassword"] = "settings.dialogChangePassword.errorEmptyNewPassword"; } if (retypedNewPassword !== newPassword) { - result["retypedNewPassword"] = + errors["retypedNewPassword"] = "settings.dialogChangePassword.errorRetypeNotMatch"; } - return result; }, }} onProcess={async ({ oldPassword, newPassword }) => { diff --git a/FrontEnd/src/pages/setting/index.tsx b/FrontEnd/src/pages/setting/index.tsx index 67416a08..918a77b5 100644 --- a/FrontEnd/src/pages/setting/index.tsx +++ b/FrontEnd/src/pages/setting/index.tsx @@ -4,25 +4,26 @@ import { ReactNode, ComponentPropsWithoutRef, } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "react-i18next"; // For change language. import { useNavigate } from "react-router-dom"; import classNames from "classnames"; -import { useC, Text } from "~src/common"; import { useUser, userService } from "~src/services/user"; import { getHttpUserClient } from "~src/http/user"; +import { pushAlert } from "~src/services/alert"; + +import { useC, Text } from "~src/common"; -import { useDialog } from "~src/components/dialog"; -import ConfirmDialog from "~src/components/dialog/ConfirmDialog"; +import { useDialog, ConfirmDialog } from "~src/components/dialog"; import Card from "~src/components/Card"; import Spinner from "~src/components/Spinner"; import Page from "~src/components/Page"; + import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; import "./index.css"; -import { pushAlert } from "~src/services/alert"; interface SettingSectionProps extends Omit, "title"> { diff --git a/FrontEnd/src/pages/timeline/Timeline.tsx b/FrontEnd/src/pages/timeline/Timeline.tsx index f266ec9d..caf4f502 100644 --- a/FrontEnd/src/pages/timeline/Timeline.tsx +++ b/FrontEnd/src/pages/timeline/Timeline.tsx @@ -1,6 +1,5 @@ import { useState, useEffect } from "react"; import classnames from "classnames"; -import { useScrollToBottom } from "~src/utilities/hooks"; import { HubConnectionState } from "@microsoft/signalr"; import { @@ -16,6 +15,8 @@ import { import { getTimelinePostUpdate$ } from "~src/services/timeline"; +import { useScrollToBottom } from "~src/components/hooks"; + import TimelinePostList from "./TimelinePostList"; import TimelinePostEdit from "./TimelinePostCreateView"; import TimelineCard from "./TimelineCard"; diff --git a/FrontEnd/src/pages/timeline/TimelineDeleteDialog.tsx b/FrontEnd/src/pages/timeline/TimelineDeleteDialog.tsx index 7b7b8e8c..a7209e75 100644 --- a/FrontEnd/src/pages/timeline/TimelineDeleteDialog.tsx +++ b/FrontEnd/src/pages/timeline/TimelineDeleteDialog.tsx @@ -39,9 +39,9 @@ const TimelineDeleteDialog: React.FC = (props) => { label: "", }, ], - validator: ({ name }) => { + validator: ({ name }, errors) => { if (name !== timeline.nameV2) { - return { name: "timeline.deleteDialog.notMatch" }; + errors.name = "timeline.deleteDialog.notMatch"; } }, }} diff --git a/FrontEnd/src/pages/timeline/TimelinePostView.tsx b/FrontEnd/src/pages/timeline/TimelinePostView.tsx index 2a8c5947..6b87ef2a 100644 --- a/FrontEnd/src/pages/timeline/TimelinePostView.tsx +++ b/FrontEnd/src/pages/timeline/TimelinePostView.tsx @@ -1,11 +1,13 @@ import { useState } from "react"; -import { getHttpTimelineClient, HttpTimelinePostInfo } from "~src/http/timeline"; +import { + getHttpTimelineClient, + HttpTimelinePostInfo, +} from "~src/http/timeline"; import { pushAlert } from "~src/services/alert"; -import { useClickOutside } from "~src/utilities/hooks"; - +import { useClickOutside } from "~src/components/hooks"; import UserAvatar from "~src/components/user/UserAvatar"; import { useDialog } from "~src/components/dialog"; import FlatButton from "~src/components/button/FlatButton"; diff --git a/FrontEnd/src/utilities/hooks.ts b/FrontEnd/src/utilities/hooks.ts deleted file mode 100644 index a59f7167..00000000 --- a/FrontEnd/src/utilities/hooks.ts +++ /dev/null @@ -1,5 +0,0 @@ -import useClickOutside from "./hooks/useClickOutside"; -import useScrollToBottom from "./hooks/useScrollToBottom"; -import { useIsSmallScreen } from "./hooks/mediaQuery"; - -export { useClickOutside, useScrollToBottom, useIsSmallScreen }; diff --git a/FrontEnd/src/utilities/hooks/mediaQuery.ts b/FrontEnd/src/utilities/hooks/mediaQuery.ts deleted file mode 100644 index ad55c3c0..00000000 --- a/FrontEnd/src/utilities/hooks/mediaQuery.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { useMediaQuery } from "react-responsive"; - -export function useIsSmallScreen(): boolean { - return useMediaQuery({ maxWidth: 576 }); -} diff --git a/FrontEnd/src/utilities/hooks/useClickOutside.ts b/FrontEnd/src/utilities/hooks/useClickOutside.ts deleted file mode 100644 index 6dcbf7b3..00000000 --- a/FrontEnd/src/utilities/hooks/useClickOutside.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useRef, useEffect } from "react"; - -export default function useClickOutside( - element: HTMLElement | null | undefined, - onClickOutside: () => void, - nextTick?: boolean -): void { - const onClickOutsideRef = useRef<() => void>(onClickOutside); - - useEffect(() => { - onClickOutsideRef.current = onClickOutside; - }, [onClickOutside]); - - useEffect(() => { - if (element != null) { - const handler = (event: MouseEvent): void => { - let e: HTMLElement | null = event.target as HTMLElement; - while (e) { - if (e == element) { - return; - } - e = e.parentElement; - } - onClickOutsideRef.current(); - }; - if (nextTick) { - setTimeout(() => { - document.addEventListener("click", handler); - }); - } else { - document.addEventListener("click", handler); - } - return () => { - document.removeEventListener("click", handler); - }; - } - }, [element, nextTick]); -} diff --git a/FrontEnd/src/utilities/hooks/useScrollToBottom.ts b/FrontEnd/src/utilities/hooks/useScrollToBottom.ts deleted file mode 100644 index 216746f4..00000000 --- a/FrontEnd/src/utilities/hooks/useScrollToBottom.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { useRef, useEffect } from "react"; -import { fromEvent } from "rxjs"; -import { filter, throttleTime } from "rxjs/operators"; - -function useScrollToBottom( - handler: () => void, - enable = true, - option = { - maxOffset: 5, - throttle: 1000, - } -): void { - const handlerRef = useRef<(() => void) | null>(null); - - useEffect(() => { - handlerRef.current = handler; - - return () => { - handlerRef.current = null; - }; - }, [handler]); - - useEffect(() => { - const subscription = fromEvent(window, "scroll") - .pipe( - filter( - () => - window.scrollY >= - document.body.scrollHeight - window.innerHeight - option.maxOffset - ), - throttleTime(option.throttle) - ) - .subscribe(() => { - if (enable) { - handlerRef.current?.(); - } - }); - - return () => { - subscription.unsubscribe(); - }; - }, [enable, option.maxOffset, option.throttle]); -} - -export default useScrollToBottom; -- cgit v1.2.3