mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-10 10:22:29 +08:00
chore(types): allow containers to constrain children
This commit is contained in:
parent
4cfb0d6161
commit
6d41af98fd
@ -12,12 +12,12 @@ import { CommandMappings, CommandNames } from './app_context.js';
|
||||
* - although the execution is async, we are collecting all the promises, and therefore it is possible to wait until the
|
||||
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
||||
*/
|
||||
export default class Component {
|
||||
export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
|
||||
$widget!: JQuery<HTMLElement>;
|
||||
componentId: string;
|
||||
children: Component[];
|
||||
children: ChildT[];
|
||||
initialized: Promise<void> | null;
|
||||
parent?: Component;
|
||||
parent?: TypedComponent<any>;
|
||||
position!: number;
|
||||
|
||||
constructor() {
|
||||
@ -31,12 +31,12 @@ export default class Component {
|
||||
return this.constructor.name.replace(/[^A-Z0-9]/ig, "_");
|
||||
}
|
||||
|
||||
setParent(parent: Component) {
|
||||
setParent(parent: TypedComponent<any>) {
|
||||
this.parent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
child(...components: Component[]) {
|
||||
child(...components: ChildT[]) {
|
||||
for (const component of components) {
|
||||
component.setParent(this);
|
||||
|
||||
@ -122,3 +122,5 @@ export default class Component {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
export default class Component extends TypedComponent<Component> {}
|
||||
|
@ -1,14 +1,9 @@
|
||||
import Component from "../components/component.js";
|
||||
import Component, { TypedComponent } from "../components/component.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import toastService from "../services/toast.js";
|
||||
|
||||
/**
|
||||
* This is the base widget for all other widgets.
|
||||
*
|
||||
* For information on using widgets, see the tutorial {@tutorial widget_basics}.
|
||||
*/
|
||||
class BasicWidget extends Component {
|
||||
export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedComponent<T> {
|
||||
protected attrs: Record<string, string>;
|
||||
private classes: string[];
|
||||
private childPositionCounter: number;
|
||||
@ -27,7 +22,7 @@ class BasicWidget extends Component {
|
||||
this.childPositionCounter = 10;
|
||||
}
|
||||
|
||||
child(...components: Component[]) {
|
||||
child(...components: T[]) {
|
||||
if (!components) {
|
||||
return this;
|
||||
}
|
||||
@ -53,7 +48,7 @@ class BasicWidget extends Component {
|
||||
* @param components the components to be added as children to this component provided the condition is truthy.
|
||||
* @returns self for chaining.
|
||||
*/
|
||||
optChild(condition: boolean, ...components: Component[]) {
|
||||
optChild(condition: boolean, ...components: T[]) {
|
||||
if (condition) {
|
||||
return this.child(...components);
|
||||
} else {
|
||||
@ -259,4 +254,11 @@ class BasicWidget extends Component {
|
||||
cleanup() {}
|
||||
}
|
||||
|
||||
export default BasicWidget;
|
||||
/**
|
||||
* This is the base widget for all other widgets.
|
||||
*
|
||||
* For information on using widgets, see the tutorial {@tutorial widget_basics}.
|
||||
*/
|
||||
export default class BasicWidget extends TypedBasicWidget<Component> {
|
||||
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
|
||||
export default class Container extends BasicWidget {
|
||||
doRender() {
|
||||
this.$widget = $(`<div>`);
|
||||
this.renderChildren();
|
||||
}
|
||||
|
||||
renderChildren() {
|
||||
for (const widget of this.children) {
|
||||
try {
|
||||
this.$widget.append(widget.render());
|
||||
} catch (e) {
|
||||
widget.logRenderingError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
src/public/app/widgets/containers/container.ts
Normal file
30
src/public/app/widgets/containers/container.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import Component, { TypedComponent } from "../../components/component.js";
|
||||
import BasicWidget, { TypedBasicWidget } from "../basic_widget.js";
|
||||
|
||||
export default class Container<T extends TypedComponent<any>> extends TypedBasicWidget<T> {
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(`<div>`);
|
||||
this.renderChildren();
|
||||
}
|
||||
|
||||
renderChildren() {
|
||||
for (const widget of this.children) {
|
||||
if (!("render" in widget)) {
|
||||
throw "Non-renderable widget encountered.";
|
||||
}
|
||||
|
||||
const typedWidget = widget as unknown as TypedBasicWidget<any>;
|
||||
|
||||
try {
|
||||
if ("render" in widget) {
|
||||
this.$widget.append(typedWidget.render());
|
||||
}
|
||||
|
||||
} catch (e: any) {
|
||||
typedWidget.logRenderingError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import { TypedComponent } from "../../components/component.js";
|
||||
import Container from "./container.js";
|
||||
|
||||
export type FlexDirection = "row" | "column";
|
||||
|
||||
export default class FlexContainer extends Container {
|
||||
export default class FlexContainer<T extends TypedComponent<any>> extends Container<T> {
|
||||
|
||||
constructor(direction: FlexDirection) {
|
||||
super();
|
||||
@ -13,4 +14,5 @@ export default class FlexContainer extends Container {
|
||||
|
||||
this.attrs.style = `display: flex; flex-direction: ${direction};`;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import appContext, { EventData } from "../../components/app_context.js";
|
||||
import LauncherWidget from "./launcher.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
export default class LauncherContainer extends FlexContainer {
|
||||
export default class LauncherContainer extends FlexContainer<LauncherWidget> {
|
||||
private isHorizontalLayout: boolean;
|
||||
|
||||
constructor(isHorizontalLayout: boolean) {
|
||||
|
@ -1,7 +1,11 @@
|
||||
import FlexContainer from "./flex_container.js";
|
||||
import splitService from "../../services/resizer.js";
|
||||
import RightPanelWidget from "../right_panel_widget.js";
|
||||
|
||||
export default class RightPaneContainer extends FlexContainer<RightPanelWidget> {
|
||||
|
||||
private rightPaneHidden: boolean;
|
||||
|
||||
export default class RightPaneContainer extends FlexContainer {
|
||||
constructor() {
|
||||
super('column');
|
||||
|
||||
@ -19,7 +23,7 @@ export default class RightPaneContainer extends FlexContainer {
|
||||
&& !!this.children.find(ch => ch.isEnabled() && ch.canBeShown());
|
||||
}
|
||||
|
||||
handleEventInChildren(name, data) {
|
||||
handleEventInChildren(name: string, data: unknown) {
|
||||
const promise = super.handleEventInChildren(name, data);
|
||||
|
||||
if (['activeContextChanged', 'noteSwitchedAndActivated', 'noteSwitched'].includes(name)) {
|
@ -1,5 +1,6 @@
|
||||
import { EventData } from "../../components/app_context.js";
|
||||
import { Screen } from "../../components/mobile_screen_switcher.js";
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
import FlexContainer, { FlexDirection } from "../containers/flex_container.js";
|
||||
|
||||
const DRAG_STATE_NONE = 0;
|
||||
@ -14,7 +15,7 @@ const DRAG_CLOSED_START_THRESHOLD = 10;
|
||||
/** The number of pixels the user has to drag across the screen to the left when the sidebar is opened to trigger the drag close animation. */
|
||||
const DRAG_OPENED_START_THRESHOLD = 80;
|
||||
|
||||
export default class SidebarContainer extends FlexContainer {
|
||||
export default class SidebarContainer extends FlexContainer<BasicWidget> {
|
||||
|
||||
private screenName: Screen;
|
||||
/** The screen name that is currently active, according to the screen changed event. */
|
||||
|
@ -1,6 +1,5 @@
|
||||
import BasicWidget from "./basic_widget.js";
|
||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
|
||||
const WIDGET_TPL = `
|
||||
<div class="card widget">
|
||||
@ -19,6 +18,12 @@ const WIDGET_TPL = `
|
||||
* @extends {NoteContextAwareWidget}
|
||||
*/
|
||||
class RightPanelWidget extends NoteContextAwareWidget {
|
||||
|
||||
private $bodyWrapper!: JQuery<HTMLElement>;
|
||||
$body!: JQuery<HTMLElement>;
|
||||
private $title!: JQuery<HTMLElement>;
|
||||
private $buttons!: JQuery<HTMLElement>;
|
||||
|
||||
/** Title to show in the panel. */
|
||||
get widgetTitle() { return "Untitled widget"; }
|
||||
|
||||
@ -53,7 +58,7 @@ class RightPanelWidget extends NoteContextAwareWidget {
|
||||
this.$buttons.empty();
|
||||
|
||||
for (const buttonWidget of this.children) {
|
||||
this.$buttons.append(buttonWidget.render());
|
||||
this.$buttons.append((buttonWidget as BasicWidget).render());
|
||||
}
|
||||
|
||||
this.initialized = this.doRenderBody().catch(e => {
|
Loading…
x
Reference in New Issue
Block a user