From ab5dd2621b9de21347bbd695811e1c87aa9e1b96 Mon Sep 17 00:00:00 2001 From: xiange Date: Mon, 29 Jan 2024 23:42:22 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=88=20perf:=20Clear=20Control?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/chili-ui/src/editor.ts | 4 +- packages/chili-ui/src/project/projectView.ts | 16 +++--- .../chili-ui/src/property/input.module.css | 9 ++- packages/chili-ui/src/property/input.ts | 56 +++++++++++-------- .../chili-ui/src/property/propertyView.ts | 38 ++++++++++--- 5 files changed, 79 insertions(+), 44 deletions(-) diff --git a/packages/chili-ui/src/editor.ts b/packages/chili-ui/src/editor.ts index b62c551d..7436a833 100644 --- a/packages/chili-ui/src/editor.ts +++ b/packages/chili-ui/src/editor.ts @@ -25,8 +25,8 @@ export const Editor = () => { { className: style.content }, div( { className: style.sidebar }, - new ProjectView().addClass(style.sidebarItem), - new PropertyView().addClass(style.sidebarItem), + new ProjectView({ className: style.sidebarItem }), + new PropertyView({ className: style.sidebarItem }), ), viewport, ), diff --git a/packages/chili-ui/src/project/projectView.ts b/packages/chili-ui/src/project/projectView.ts index 2b985a07..0f45e3c4 100644 --- a/packages/chili-ui/src/project/projectView.ts +++ b/packages/chili-ui/src/project/projectView.ts @@ -1,14 +1,13 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. import { IDocument, PubSub } from "chili-core"; -import { Control, Panel } from "../components"; import { ToolBar } from "./toolBar"; import { Tree } from "./tree"; -import { div, localize, span } from "../controls"; +import { BindableElement, div, localize, span } from "../controls"; import style from "./projectView.module.css"; -export class ProjectView extends Control { +export class ProjectView extends BindableElement { readonly #documentTreeMap = new WeakMap(); #activeDocument: IDocument | undefined; @@ -16,11 +15,14 @@ export class ProjectView extends Control { return this.#activeDocument; } - private panel: Panel; + private panel: HTMLDivElement; - constructor() { - super(style.root); - this.panel = new Panel().addClass(style.itemsPanel); + constructor(props: { className: string }) { + super(); + this.classList.add(style.root, props.className); + this.panel = div({ + className: style.itemsPanel, + }); this.append( div( { className: style.headerPanel }, diff --git a/packages/chili-ui/src/property/input.module.css b/packages/chili-ui/src/property/input.module.css index d4cd3141..78cbc690 100644 --- a/packages/chili-ui/src/property/input.module.css +++ b/packages/chili-ui/src/property/input.module.css @@ -13,10 +13,13 @@ } .box { - font-size: 14px; + flex: 1; + font-size: 1rem; + padding: 4px; + outline: none; + background-color: transparent; + border: 1px solid var(--border-color); border-radius: 4px; - padding: 0px 6px; margin: 0px; - flex: 1 1 100%; } diff --git a/packages/chili-ui/src/property/input.ts b/packages/chili-ui/src/property/input.ts index ef055416..b03909db 100644 --- a/packages/chili-ui/src/property/input.ts +++ b/packages/chili-ui/src/property/input.ts @@ -1,6 +1,7 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. import { + I18n, IConverter, IDocument, IPropertyChanged, @@ -13,15 +14,15 @@ import { XYZ, XYZConverter, } from "chili-core"; -import { Label, Panel, TextBox } from "../components"; +import { div, input, span } from "../controls"; import commonStyle from "./common.module.css"; import style from "./input.module.css"; import { PropertyBase } from "./propertyBase"; export class InputProperty extends PropertyBase { - readonly valueBox: TextBox; - readonly error: Label; + readonly valueBox: HTMLInputElement; + readonly error: HTMLSpanElement; readonly converter: IConverter | undefined; constructor( @@ -32,36 +33,44 @@ export class InputProperty extends PropertyBase { ) { super(objects); this.converter = property.converter ?? this.getConverter(); - this.valueBox = new TextBox() - .addClass(style.box) - .setText(this.getDefaultValue()) - .setReadOnly(this.isReadOnly()); - let name = new Label() - .i18nText(property.display) - .addClass(commonStyle.propertyName) - .setTitle(property.display); - this.error = new Label().i18nText("error.default").addClass(style.error, style.hidden); - let panel = new Panel().addClass(commonStyle.panel); - if (showTitle) panel.addItem(name); - panel.addItem(this.valueBox); - this.append(panel, this.error); + this.valueBox = input({ + className: style.box, + value: this.getDefaultValue(), + readOnly: this.isReadOnly(), + onkeydown: this.handleKeyDown, + }); + this.error = span({ + classList: `${style.error} ${style.hidden}`, + textContent: I18n.translate("error.default"), + }); + this.append( + div( + { className: commonStyle.panel }, + showTitle + ? span({ + className: commonStyle.propertyName, + textContent: I18n.translate(property.display), + }) + : "", + this.valueBox, + ), + this.error, + ); } override connectedCallback(): void { super.connectedCallback(); - this.valueBox.addEventListener("keydown", this.handleKeyDown); (this.objects.at(0) as IPropertyChanged)?.onPropertyChanged(this.handlePropertyChanged); } override disconnectedCallback(): void { super.disconnectedCallback(); - this.valueBox.removeEventListener("keydown", this.handleKeyDown); (this.objects.at(0) as IPropertyChanged)?.removePropertyChanged(this.handlePropertyChanged); } private handlePropertyChanged = (property: string) => { if (property === this.property.name) { - this.valueBox.setText(this.getValueString(this.objects[0])); + this.valueBox.value = this.getValueString(this.objects[0]); } }; @@ -114,12 +123,13 @@ export class InputProperty extends PropertyBase { } private handleKeyDown = (e: KeyboardEvent) => { + e.stopPropagation(); if (this.converter === undefined) return; if (e.key === "Enter") { - let newValue = this.converter.convertBack?.(this.valueBox.text); + let newValue = this.converter.convertBack?.(this.valueBox.value); if (!newValue?.success) { - this.error.text(newValue?.error ?? "error"); - this.error.addClass(style.hidden); + this.error.textContent = newValue?.error ?? "error"; + this.error.classList.add(style.hidden); return; } Transaction.excute(this.document, "modify property", () => { @@ -129,7 +139,7 @@ export class InputProperty extends PropertyBase { this.document.visual.viewer.update(); }); } else { - this.error.addClass(style.hidden); + this.error.classList.add(style.hidden); } }; } diff --git a/packages/chili-ui/src/property/propertyView.ts b/packages/chili-ui/src/property/propertyView.ts index fabf784d..54767dfa 100644 --- a/packages/chili-ui/src/property/propertyView.ts +++ b/packages/chili-ui/src/property/propertyView.ts @@ -1,25 +1,45 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. -import { Color, GeometryModel, I18nKeys, IConverter, IDocument, INode, Property, PubSub } from "chili-core"; -import { Control, Expander, Label, Panel } from "../components"; +import { + Color, + GeometryModel, + I18n, + I18nKeys, + IConverter, + IDocument, + INode, + Property, + PubSub, +} from "chili-core"; +import { Expander } from "../components"; -import { div } from "../controls"; +import { BindableElement, div, label } from "../controls"; import { CheckProperty } from "./check"; import { ColorProperty } from "./colorProperty"; import { InputProperty } from "./input"; import { MatrixConverter } from "./matrixConverter"; import style from "./propertyView.module.css"; -export class PropertyView extends Control { - private panel = new Panel(style.panel); - constructor() { - super(style.root); - this.append(new Label().i18nText("properties.header").addClass(style.header), this.panel); +export class PropertyView extends BindableElement { + private panel = div({ className: style.panel }); + constructor(props: { className: string }) { + super(); + this.classList.add(props.className, style.root); + this.append( + label({ + className: style.header, + textContent: I18n.translate("properties.header"), + }), + this.panel, + ); PubSub.default.sub("selectionChanged", this.selectionChanged); } private selectionChanged = (document: IDocument, selected: INode[], unselected: INode[]) => { - this.panel.clearChildren(); + while (this.panel.lastElementChild) { + this.panel.removeChild(this.panel.lastElementChild); + } + if (selected.length === 0) return; this.addDefault(document, selected); this.addTransform(document, selected);