UNPKG

@v4fire/client

Version:

V4Fire client core library

209 lines (174 loc) • 4.91 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ /** * [[include:super/i-page/README.md]] * @packageDocumentation */ import symbolGenerator from 'core/symbol'; import iVisible from 'traits/i-visible/i-visible'; import iData, { component, prop, system, computed, watch, hook, ModsDecl } from 'super/i-data/i-data'; import type { TitleValue, StageTitles, ScrollOptions, DescriptionValue } from 'super/i-page/interface'; export * from 'super/i-data/i-data'; export * from 'super/i-page/interface'; export const $$ = symbolGenerator(); /** * Superclass for all page components */ @component({inheritMods: false}) export default abstract class iPage extends iData implements iVisible { override readonly reloadOnActivation: boolean = true; override readonly syncRouterStoreOnInit: boolean = true; /** @see [[iVisible.prototype.hideIfOffline]] */ @prop(Boolean) readonly hideIfOffline: boolean = false; /** * An initial page title. * Basically this title is set via `document.title`. */ @prop({type: [String, Function]}) readonly pageTitleProp: TitleValue = ''; /** * An initial page title. * Basically this title is set via `document.title`. */ @prop({type: [String, Function]}) readonly pageDescriptionProp: DescriptionValue = ''; /** * A dictionary of page titles (basically these titles are set via `document.title`). * The dictionary values are tied to the `stage` values. * * A key with the name `[[DEFAULT]]` is used by default. If a key value is defined as a function, * it will be invoked (the result will be used as a title). */ @prop({type: Object, required: false}) readonly stagePageTitles?: StageTitles<this>; /** * Current page title * * @see [[iPage.pageTitleProp]] * @see [[iPage.stagePageTitles]] */ @computed({cache: false}) get pageTitle(): string { return this.r.PageMetaData.title; } /** * Sets a new page title. * Basically this title is set via `document.title`. */ set pageTitle(value: string) { if (this.isActivated) { this.r.PageMetaData.title = value; } } /** * A wrapped version of the `scrollTo` method. * The calling cancels all previous tasks. * * @see [[iPage.scrollTo]] */ @computed({cache: true}) get scrollToProxy(): this['scrollTo'] { return (...args) => { this.async.setImmediate(() => this.scrollTo(...args), { label: $$.scrollTo }); }; } static override readonly mods: ModsDecl = { ...iVisible.mods }; /** * Page title store */ @system((o) => o.sync.link((v) => Object.isFunction(v) ? v(o) : v)) protected pageTitleStore!: string; /** * Page description store */ @system((o) => o.sync.link((v) => Object.isFunction(v) ? v(o) : v)) protected pageDescriptionStore!: string; /** * Scrolls a page by the specified options * @param opts */ scrollTo(opts: ScrollOptions): void; /** * Scrolls a page to the specified coordinates * * @param x * @param y */ scrollTo(x?: number, y?: number): void; scrollTo(p?: ScrollOptions | number, y?: number): void { this.async.cancelProxy({label: $$.scrollTo}); const scroll = (opts: ScrollToOptions) => { try { globalThis.scrollTo(opts); } catch { globalThis.scrollTo(opts.left == null ? pageXOffset : opts.left, opts.top == null ? pageYOffset : opts.top); } }; if (Object.isPlainObject(p)) { scroll({left: p.x, top: p.y, ...Object.reject(p, ['x', 'y'])}); } else { scroll({left: p, top: y}); } } override activate(force?: boolean): void { this.setRootMod('active', true); super.activate(force); } override deactivate(): void { this.setRootMod('active', false); super.deactivate(); } /** * Synchronization for the `stagePageTitles` field */ @watch('!:onStageChange') protected syncStageTitles(): CanUndef<string> { const stageTitles = this.stagePageTitles; if (stageTitles == null) { return; } if (this.stage != null) { let v = stageTitles[this.stage]; if (v == null) { v = stageTitles['[[DEFAULT]]']; } // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (v != null) { return this.r.PageMetaData.title = Object.isFunction(v) ? v(this) : v; } } } /** * Initializes a custom page title */ @hook(['created', 'activated']) protected initPageMetaData(): void { if (this.syncStageTitles() == null && Object.isTruly(this.pageTitleStore)) { this.r.PageMetaData.title = this.pageTitleStore; } if (Object.isTruly(this.pageDescriptionStore)) { this.r.PageMetaData.description = this.pageDescriptionStore; } } protected override initModEvents(): void { super.initModEvents(); iVisible.initModEvents(this); } protected override beforeDestroy(): void { this.removeRootMod('active'); super.beforeDestroy(); } }