This commit is contained in:
2023-07-04 17:02:56 +08:00
parent fa8e791753
commit 734655b06c
7 changed files with 82 additions and 60 deletions

View File

@@ -1,10 +1,7 @@
import { Component, ComponentChildren, ContextType } from "preact";
import { BCtx } from "./BContext.tsx";
import { Ref, useRef, useState } from "preact/hooks";
import type {
_MdOutlinedTextField as _TextFieldE,
MdOutlinedTextField as _TextField,
} from "../server/md3.ts";
import { useState } from "preact/hooks";
import type { _MdOutlinedTextField as _TextField } from "../server/md3.ts";
import { MdOutlinedTextField } from "../server/dmodule.ts";
import List from "preact-material-components/List";
@@ -41,14 +38,13 @@ type Props<T extends keyof TextType> = {
export default class BMd3TextField<T extends keyof TextType>
extends Component<Props<T>, unknown> {
static contextType = BCtx;
ref: Ref<typeof _TextField | null> | undefined;
declare context: ContextType<typeof BCtx>;
get clear_cache() {
return this.props.clear_cache !== undefined
? this.props.clear_cache
: true;
}
get_value(e: _TextFieldE): TextType[T] | undefined {
get_value(e: _TextField): TextType[T] | undefined {
const type = this.props.type;
if (!e.value.length) return undefined;
// @ts-ignore Checked
@@ -57,7 +53,6 @@ export default class BMd3TextField<T extends keyof TextType>
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);
@@ -111,8 +106,6 @@ export default class BMd3TextField<T extends keyof TextType>
<div class={cn} id={this.props.id}>
{desc}
<TextField
/**@ts-ignore */
ref={this.ref}
value={value}
type={this.props.type}
label={this.props.label}
@@ -123,7 +116,7 @@ export default class BMd3TextField<T extends keyof TextType>
/**@ts-ignore */
onInput={(ev: InputEvent) => {
if (ev.target) {
const e = ev.target as _TextFieldE;
const e = ev.target as _TextField;
this.set_value(this.get_value(e));
}
}}

View File

@@ -28,8 +28,7 @@ type State = {
selectedIndex: number;
};
export default class SettingsSelect<T extends obj>
extends Component<Props<T>, State> {
export default class BSelect<T extends obj> extends Component<Props<T>, State> {
static contextType = BCtx;
declare context: ContextType<typeof BCtx>;
ref: Ref<Select | undefined> | undefined;

View File

@@ -1,5 +1,6 @@
import { Component, VNode } from "preact";
import { MdOutlinedSelect, MdSelectOption } from "../server/dmodule.ts";
import type { _MdOutlinedSelect } from "../server/md3.ts";
type OProps = {
value: string;
@@ -42,6 +43,7 @@ type Props = {
hasTrailingIcon?: boolean;
displayText?: string;
selectedIndex?: number;
set_index?: (index: number) => void;
};
type State = {
@@ -82,6 +84,13 @@ export default class Md3Select extends Component<Props, State> {
hasTrailingIcon={this.props.hasTrailingIcon}
displayText={this.props.displayText}
selectedIndex={this.state.selectedIndex}
onChange={(e) => {
const t = e.target as _MdOutlinedSelect;
this.setState({ selectedIndex: t.selectedIndex });
if (this.props.set_index) {
this.props.set_index(t.selectedIndex);
}
}}
>
{/**@ts-ignore */}
{this.props.children}

View File

@@ -1,7 +1,7 @@
import { Component, ContextType } from "preact";
import { SettingsCtx } from "./SettingsContext.tsx";
import { ConfigType } from "../config.ts";
import Select from "preact-material-components/Select";
import Md3Select from "./Md3Select.tsx";
import { Ref, StateUpdater, useRef } from "preact/hooks";
interface obj {
@@ -16,10 +16,6 @@ type Props<T extends obj> = {
selectedIndex?: number;
/**@default {false}*/
disabled?: boolean;
/**@default {false}*/
box?: boolean;
/**@default {false}*/
outlined?: boolean;
hintText?: string;
set_value?: StateUpdater<T>;
};
@@ -32,7 +28,6 @@ export default class SettingsSelect<T extends obj>
extends Component<Props<T>, State> {
static contextType = SettingsCtx;
declare context: ContextType<typeof SettingsCtx>;
ref: Ref<Select | undefined> | undefined;
constructor(props: Props<T>) {
super(props);
if (!props.list.length) throw Error("No list.");
@@ -44,27 +39,17 @@ export default class SettingsSelect<T extends obj>
): void {
const selectedIndex = nextProps.selectedIndex || 0;
this.setState({ selectedIndex });
this.update(selectedIndex);
}
componentDidMount(): void {
this.update(this.state.selectedIndex);
}
render() {
this.ref = useRef<Select>();
const id = `s-${this.props.name}`;
return (
<div class="s-select" id={id}>
<label>{this.props.description}</label>
<Select
ref={this.ref}
hintText={this.props.hintText}
<Md3Select
supportingText={this.props.hintText}
disabled={this.props.disabled}
box={this.props.box}
outlined={this.props.outlined}
onChange={(e: Event) => {
if (!e.target) return;
/**@ts-ignore */
const selectedIndex: number = e.target.selectedIndex;
selectedIndex={this.state.selectedIndex}
set_index={(selectedIndex) => {
this.setState({ selectedIndex });
this.set_value(selectedIndex);
}}
@@ -72,10 +57,10 @@ export default class SettingsSelect<T extends obj>
{this.props.list.map((v) => {
const t = v.text ? v.text : v.value.toString();
return (
<Select.Item disabled={v.disabled}>{t}</Select.Item>
<Md3Select.Option disabled={v.disabled} value={t} />
);
})}
</Select>
</Md3Select>
</div>
);
}
@@ -103,17 +88,4 @@ export default class SettingsSelect<T extends obj>
});
}
}
update(index: number) {
const e = this.ref?.current;
if (e) {
const b = e.base;
if (b) {
const t = b as HTMLElement;
const s = t.querySelector("select");
if (s) {
s.selectedIndex = index;
}
}
}
}
}

View File

@@ -1,7 +1,6 @@
import { Component, ContextType } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import Button from "preact-material-components/Button";
import Dialog from "preact-material-components/Dialog";
import Snackbar from "preact-material-components/Snackbar";
import { tw } from "twind";
import { GlobalCtx } from "../components/GlobalContext.tsx";
@@ -11,6 +10,8 @@ import SettingsContext from "../components/SettingsContext.tsx";
import SettingsText from "../components/SettingsText.tsx";
import t from "../server/i18n.ts";
import SettingsSelect from "../components/SettingsSelect.tsx";
import type { _MdDialog, DialogAction } from "../server/md3.ts";
import { MdDialog, MdTextButton } from "../server/dmodule.ts";
export type SettingsProps = {
show: boolean;
@@ -21,6 +22,10 @@ export default class Settings extends Component<SettingsProps> {
declare context: ContextType<typeof GlobalCtx>;
render() {
if (!this.props.show) return;
if (!MdDialog.value) return;
if (!MdTextButton.value) return;
const Dialog = MdDialog.value;
const TextButton = MdTextButton.value;
const [settings, set_settings] = useState<ConfigType | undefined>();
const [error, set_error] = useState<string | undefined>();
const [changed, set_changed] = useState<Set<string>>(new Set());
@@ -69,13 +74,13 @@ export default class Settings extends Component<SettingsProps> {
data = <div class={tw`text-red-500`}>{error}</div>;
} else if (settings) {
const ref = useRef<SettingsText<"text">>();
const dlg = useRef<Dialog>();
const dlg = useRef<_MdDialog>();
const showDlg = () => {
if (!changed.size) {
show_snack(t("settings.no_changed"));
return;
}
dlg.current?.MDComponent?.show();
dlg.current?.show();
};
const save = () => {
set_disabled(true);
@@ -141,7 +146,6 @@ export default class Settings extends Component<SettingsProps> {
}]}
description={t("settings.thumbnail_method")}
selectedIndex={settings.thumbnail_method}
outlined={true}
/>
<SettingsText
name="port"
@@ -270,16 +274,25 @@ export default class Settings extends Component<SettingsProps> {
<Button onClick={showDlg} disabled={disabled}>
{t("common.save")}
</Button>
<Dialog ref={dlg} onAccept={save}>
<Dialog.Header>{t("settings.save_dlg")}</Dialog.Header>
<Dialog.Footer>
<Dialog.FooterButton accept={true}>
<Dialog
/**@ts-ignore */
ref={dlg}
onclosed={(ev) => {
const e = ev as CustomEvent<DialogAction>;
if (e.detail.action === "yes") {
save();
}
}}
>
<span slot="headline">{t("settings.save_dlg")}</span>
<div slot="footer">
<TextButton dialog-action="yes">
{t("common.yes")}
</Dialog.FooterButton>
<Dialog.FooterButton cancel={true}>
</TextButton>
<TextButton dialog-action="close">
{t("common.no")}
</Dialog.FooterButton>
</Dialog.Footer>
</TextButton>
</div>
</Dialog>
</div>
);

View File

@@ -1,9 +1,11 @@
import { signal } from "@preact/signals";
import type {
MdDialog as _MdDialog,
MdOutlinedButton as _MdOutlinedButton,
MdOutlinedSelect as _MdOutlinedSelect,
MdOutlinedTextField as _MdOutlinedTextField,
MdSelectOption as _MdSelectOption,
MdTextButton as _MdTextButton,
MdTonalButton as _MdTonalButton,
} from "./md3.ts";
@@ -27,6 +29,10 @@ export const MdOutlinedSelect = signal<typeof _MdOutlinedSelect | undefined>(
undefined,
);
export const MdDialog = signal<typeof _MdDialog | undefined>(undefined);
export const MdTextButton = signal<typeof _MdTextButton | undefined>(undefined);
export async function load_dmodule() {
const md3 = await import("./md3.ts");
MdOutlinedTextField.value = md3.MdOutlinedTextField;
@@ -34,4 +40,6 @@ export async function load_dmodule() {
MdTonalButton.value = md3.MdTonalButton;
MdSelectOption.value = md3.MdSelectOption;
MdOutlinedSelect.value = md3.MdOutlinedSelect;
MdDialog.value = md3.MdDialog;
MdTextButton.value = md3.MdTextButton;
}

View File

@@ -3,6 +3,8 @@ import { MdOutlinedButton as _MdOutlinedButton } from "@material/web/button/outl
import { MdTonalButton as _MdTonalButton } from "@material/web/button/tonal-button.js?dts=1";
import { MdSelectOption as _MdSelectOption } from "@material/web/select/select-option.js?dts=1";
import { MdOutlinedSelect as _MdOutlinedSelect } from "@material/web/select/outlined-select.js?dts=1";
import { MdDialog as _MdDialog } from "@material/web/dialog/dialog.js?dts=1";
import { MdTextButton as _MdTextButton } from "@material/web/button/text-button.js?dts=1";
import { createComponent } from "@lit-labs/react/?target=es2022";
import * as Preact from "preact/compat";
@@ -41,8 +43,34 @@ export const MdOutlinedSelect = createComponent({
react: Preact,
});
export type DialogAction = {
action: string;
};
export const MdDialog = createComponent({
tagName: "md-dialog",
elementClass: _MdDialog,
// @ts-ignore Checked
react: Preact,
events: {
"onopening": "opening",
"onopened": "opened",
"onclosing": "closing",
"onclosed": "closed",
},
});
export const MdTextButton = createComponent({
tagName: "md-text-button",
elementClass: _MdTextButton,
// @ts-ignore Checked
react: Preact,
});
export { _MdOutlinedTextField };
export { _MdOutlinedButton };
export { _MdTonalButton };
export { _MdSelectOption };
export { _MdOutlinedSelect };
export { _MdDialog };
export { _MdTextButton };