diff --git a/components/BMd3TextField.tsx b/components/BMd3TextField.tsx new file mode 100644 index 0000000..9b429ad --- /dev/null +++ b/components/BMd3TextField.tsx @@ -0,0 +1,146 @@ +import { Component, ComponentChildren, ContextType } from "preact"; +import { BCtx } from "./BContext.tsx"; +import { Ref, useRef, useState } from "preact/hooks"; +import type _TextField from "../server/md3/md-outlined-text-field.ts"; +import type { MdOutlinedTextField as _TextFieldE } from "../server/md3/md-outlined-text-field.ts"; +import { MdOutlinedTextField } from "../server/dmodule.ts"; +import List from "preact-material-components/List"; + +interface TextType { + text: string; + password: string; + number: number; +} + +interface DataType { + text: never; + password: never; + number: number; +} + +type Props = { + /**@default {true} */ + clear_cache?: boolean; + label?: string; + description?: string; + value?: TextType[T]; + name?: string; + type: T; + disabled?: boolean; + children?: ComponentChildren; + set_value?: (v?: TextType[T]) => void; + min?: DataType[T]; + max?: DataType[T]; + id?: string; + list?: string; + datalist?: { value: TextType[T]; label?: string }[]; +}; + +export default class BMd3TextField + extends Component, unknown> { + static contextType = BCtx; + ref: Ref | undefined; + declare context: ContextType; + get clear_cache() { + return this.props.clear_cache !== undefined + ? this.props.clear_cache + : true; + } + get_value(e: _TextFieldE): TextType[T] | undefined { + const type = this.props.type; + if (!e.value.length) return undefined; + // @ts-ignore Checked + if (type === "text" || type === "password") return e.value; + // @ts-ignore Checked + return e.valueAsNumber; + } + render() { + this.ref = useRef(null); + if (!MdOutlinedTextField.value) return null; + let datalist_div = null; + const [display_datalist, set_display_datalist] = useState(false); + let cn = "b-text-field md3 text"; + if (this.props.label) cn += " label"; + if (this.props.datalist && this.props.datalist.length) { + cn += " datalist"; + let cn2 = "datalist"; + if (display_datalist) cn2 += " open"; + const v = this.props.value?.toString(); + datalist_div = ( + + {this.props.datalist.map((d) => { + if (v !== undefined) { + if (!d.value.toString().startsWith(v)) return null; + } + let label_div = null; + if (d.label) { + label_div =
{d.label}
; + } + return ( + { + this.set_value(d.value); + }} + > +
{d.value}
+ {label_div} +
+ ); + })} +
+ ); + } + const TextField = MdOutlinedTextField.value; + let desc = null; + if (this.props.description) { + desc = ; + } + let value: string | undefined; + if (this.props.value !== undefined) { + if (typeof this.props.value === "string") { + value = this.props.value; + } else { + value = this.props.value.toString(); + } + } else if (this.clear_cache) { + value = ""; + } + return ( +
+ {desc} + { + if (ev.target) { + const e = ev.target as _TextFieldE; + this.set_value(this.get_value(e)); + } + }} + onFocus={() => set_display_datalist(true)} + onBlur={() => set_display_datalist(false)} + /> + {datalist_div} + {this.props.children} +
+ ); + } + set_value(value?: TextType[T]) { + if (this.props.set_value) { + this.props.set_value(value); + } else if (this.context) { + this.context.set_value((v) => { + v[this.props.name || ""] = value; + return v; + }); + } + } +} diff --git a/components/CreateRootUser.tsx b/components/CreateRootUser.tsx index ee9c81c..5d3ea1f 100644 --- a/components/CreateRootUser.tsx +++ b/components/CreateRootUser.tsx @@ -1,6 +1,8 @@ import { Component, ContextType } from "preact"; import { GlobalCtx } from "./GlobalContext.tsx"; -import { MdOutlinedTextField } from "../server/dmodule.ts"; +import BMd3TextField from "./BMd3TextField.tsx"; +import t from "../server/i18n.ts"; +import { useState } from "preact/hooks"; type Props = { show: boolean; @@ -10,12 +12,17 @@ export default class CreateRootUser extends Component { static contextType = GlobalCtx; declare context: ContextType; render() { - if (!MdOutlinedTextField.value) return null; if (!this.props.show) return null; - const OutlinedTextField = MdOutlinedTextField.value; + const [username, set_username] = useState(); + console.log(username); return (
- +
); } diff --git a/islands/Container.tsx b/islands/Container.tsx index a9a64e0..dad8b96 100644 --- a/islands/Container.tsx +++ b/islands/Container.tsx @@ -42,6 +42,7 @@ export default class Container extends Component { const [display, set_display] = useState(false); const [state, set_state1] = useState("#/"); const [darkmode, set_darkmode1] = useState(DarkMode.Auto); + const [dmodule_loaded, set_dmodule_loaded] = useState(false); const set_darkmode: StateUpdater = (u) => { const v = typeof u === "function" ? u(darkmode) : u; set_darkmode1(v); @@ -88,10 +89,24 @@ export default class Container extends Component { } } }); - load_dmodule().catch((e) => { + load_dmodule().then(() => set_dmodule_loaded(true)).catch((e) => { console.error(e); }); }, []); + let main = null; + if (dmodule_loaded) { + main = ( +
+ + + + +
+ ); + } return (
@@ -156,15 +171,7 @@ export default class Container extends Component { settings -
- - - - -
+ {main}
); } diff --git a/server/dmodule.ts b/server/dmodule.ts index 810bee0..80bad62 100644 --- a/server/dmodule.ts +++ b/server/dmodule.ts @@ -6,6 +6,6 @@ export const MdOutlinedTextField = signal< >(undefined); export async function load_dmodule() { - const m = await import("./md3/md-outlined-text-field.ts"); - MdOutlinedTextField.value = m.default; + MdOutlinedTextField.value = + (await import("./md3/md-outlined-text-field.ts")).default; } diff --git a/server/i18ns.ts b/server/i18ns.ts index edec77b..db5073e 100644 --- a/server/i18ns.ts +++ b/server/i18ns.ts @@ -7,8 +7,8 @@ import { get_host } from "./utils.ts"; const whole_maps = new Map(); const LANGUAGES = ["zh-cn"]; -type MODULE = "common" | "settings" | "task"; -const MODULES: MODULE[] = ["common", "settings", "task"]; +type MODULE = "common" | "settings" | "task" | "user"; +const MODULES: MODULE[] = ["common", "settings", "task", "user"]; export async function load_translation(signal?: AbortSignal) { const base = import.meta.resolve("../translation").slice(8); diff --git a/server/md3/md-outlined-text-field.ts b/server/md3/md-outlined-text-field.ts index d205346..33c7d7d 100644 --- a/server/md3/md-outlined-text-field.ts +++ b/server/md3/md-outlined-text-field.ts @@ -9,4 +9,5 @@ const MdOutlinedTextField = createComponent({ react: Preact, }); +export { _MdOutlinedTextField as MdOutlinedTextField }; export default MdOutlinedTextField; diff --git a/static/common.css b/static/common.css index a6fdc76..76f5711 100644 --- a/static/common.css +++ b/static/common.css @@ -313,6 +313,43 @@ div.new_task div.content .text .mdc-text-field { position: relative; } +.dark-scheme { + --md-sys-color-primary: #4CDADA; + --md-sys-color-primary-container: #004F4F; + --md-sys-color-on-primary: #003737; + --md-sys-color-on-primary-container: #6FF7F6; + --md-sys-color-secondary: #B0CCCB; + --md-sys-color-secondary-container: #324B4B; + --md-sys-color-on-secondary: #1B3534; + --md-sys-color-on-secondary-container: #CCE8E7; + --md-sys-color-tertiary: #B3C8E8; + --md-sys-color-tertiary-container: #334863; + --md-sys-color-on-tertiary: #1C314B; + --md-sys-color-on-tertiary-container: #D3E4FF; + --md-sys-color-error: #FFB4AB; + --md-sys-color-error-container: #93000A; + --md-sys-color-on-error: #690005; + --md-sys-color-on-error-container: #FFDAD6; + --md-sys-color-outline: #889392; + --md-sys-color-background: #191C1C; + --md-sys-color-on-background: #E0E3E2; + --md-sys-color-surface: #191C1C; + --md-sys-color-on-surface: #E0E3E2; + --md-sys-color-surface-variant: #3F4948; + --md-sys-color-on-surface-variant: #BEC9C8; + --md-sys-color-inverse-surface: #E0E3E2; + --md-sys-color-inverse-on-surface: #191C1C; + --md-sys-color-inverse-primary: #006A6A; + --md-sys-color-shadow: #000000; + --md-sys-color-surface-tint: #4CDADA; + --md-sys-color-outline-variant: #3F4948; + --md-sys-color-scrim: #000000; +} + +.b-text-field.md3.label md-outlined-text-field { + margin-top: 6px; +} + @media (max-width:1280px) { .settings { margin: 0; diff --git a/translation/en/user.jsonc b/translation/en/user.jsonc new file mode 100644 index 0000000..53485c5 --- /dev/null +++ b/translation/en/user.jsonc @@ -0,0 +1,3 @@ +{ + "username": "Username" +} diff --git a/translation/zh-cn/user.jsonc b/translation/zh-cn/user.jsonc new file mode 100644 index 0000000..9bac8bb --- /dev/null +++ b/translation/zh-cn/user.jsonc @@ -0,0 +1,3 @@ +{ + "username": "用户名" +}