extension model + other stuff added in conversation with Jesper.

This commit is contained in:
Niels Lyngsø
2023-01-30 11:20:06 +01:00
parent 43ddc90d11
commit dae471a119
9 changed files with 80 additions and 35 deletions

View File

@@ -18,6 +18,7 @@ import type { ManifestCollectionBulkAction } from './collection-bulk-action.mode
import type { ManifestCollectionView } from './collection-view.models';
import type { ManifestHealthCheck } from './health-check.models';
import type { ManifestSidebarMenuItem } from './sidebar-menu-item.models';
import type { ManifestTheme } from './theme.models';
export * from './header-app.models';
export * from './section.models';
@@ -39,6 +40,7 @@ export * from './collection-bulk-action.models';
export * from './collection-view.models';
export * from './health-check.models';
export * from './sidebar-menu-item.models';
export * from './theme.models';
export type ManifestTypes =
| ManifestCustom
@@ -63,7 +65,8 @@ export type ManifestTypes =
| ManifestCollectionBulkAction
| ManifestCollectionView
| ManifestHealthCheck
| ManifestSidebarMenuItem;
| ManifestSidebarMenuItem
| ManifestTheme;
export type ManifestStandardTypes = ManifestTypes['type'];
@@ -78,11 +81,15 @@ export interface ManifestBase {
weight?: number;
}
export interface ManifestElement extends ManifestBase {
export interface ManifestWithLoader<LoaderReturnType> extends ManifestBase {
loader?: () => Promise<LoaderReturnType>;
}
export interface ManifestElement extends ManifestWithLoader<object | HTMLElement> {
type: ManifestStandardTypes;
js?: string;
elementName?: string;
loader?: () => Promise<object | HTMLElement>;
//loader?: () => Promise<object | HTMLElement>;
meta?: any;
}

View File

@@ -0,0 +1,7 @@
import type { ManifestWithLoader } from "./models";
// TODO: make or find type for JS Module with default export: Would be nice to support css file directly.
export interface ManifestTheme extends ManifestWithLoader<any> {
type: 'theme';
}

View File

@@ -33,7 +33,7 @@ import { UmbDocumentBlueprintTreeStore } from './documents/document-blueprints/d
import { UmbDataTypeDetailStore } from './settings/data-types/data-type.detail.store';
import { UmbDataTypeTreeStore } from './settings/data-types/data-type.tree.store';
import { UmbThemeContext } from './themes/theme.service';
import { UmbThemeContext } from './themes/theme.context';
import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification';
// Domains

View File

@@ -0,0 +1,12 @@
import type { ManifestTheme } from '@umbraco-cms/models';
export const themes: Array<ManifestTheme> = [
{
type: 'theme',
alias: 'umb-dark-theme',
name: 'Dark',
loader: () => import('./themes/dark.theme')
},
];
export const manifests = themes;

View File

@@ -1,15 +1,21 @@
import { dark, highContrast } from './themes';
import { map } from 'rxjs';
//import { dark, highContrast } from './themes';
import type { CSSResult } from 'lit';
import { manifests } from './manifests';
import { UmbContextProviderController, UmbContextToken } from '@umbraco-cms/context-api';
import { StringState, UmbObserverController } from '@umbraco-cms/observable-api';
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
import { map } from 'rxjs';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { ManifestTheme } from '@umbraco-cms/extensions-registry';
export interface UmbTheme {
name: string;
css: string;
css: CSSResult;
}
const LOCAL_STORAGE_KEY = 'umb-theme-alias';
export class UmbThemeContext {
// TODO: Turn this into a extension type, get rid of the #themes subject and #themes observable
@@ -36,40 +42,47 @@ export class UmbThemeContext {
this._host = host;
new UmbContextProviderController(host, UMB_THEME_SERVICE_CONTEXT_TOKEN, this);
console.log("Theme COntext")
new UmbContextProviderController(host, UMB_THEME_CONTEXT_TOKEN, this);
//TODO: Figure out how to extend this with themes from packages
//this.addTheme(dark);
//this.addTheme(highContrast);
this.#styleElement = document.createElement('style');
const storedTheme = localStorage.getItem('umb-theme');
const storedTheme = localStorage.getItem(LOCAL_STORAGE_KEY);
if(storedTheme) {
this.setThemeByName(storedTheme);
this.setThemeByAlias(storedTheme);
}
document.documentElement.insertAdjacentElement('beforeend', this.#styleElement);
}
private setThemeByName(themeName: string | null) {
public setThemeByAlias(themeAlias: string | null) {
this.#theme.next(themeName);
this.#theme.next(themeAlias);
this.themeSubscription?.destroy();
if(themeName != null) {
localStorage.setItem('umb-theme', themeName);
if(themeAlias != null) {
localStorage.setItem(LOCAL_STORAGE_KEY, themeAlias);
this.themeSubscription = new UmbObserverController(this._host,
umbExtensionsRegistry.extensionsOfType('theme').pipe(map(
(value) => value.name === themeName
(extensions) => extensions.filter((extension) => extension.alias === themeAlias)
))
,
(theme) => {
async (themes) => {
if (themes.length > 0 && themes[0].loader) {
const result = await themes[0].loader();
console.log("result from loader: ", result.default);
this.#styleElement.innerHTML = result.default;
}
// how to get CSS.
//this.#styleElement.innerHTML = "";
}
);
} else {
localStorage.removeItem('umb-theme');
localStorage.removeItem(LOCAL_STORAGE_KEY);
this.#styleElement.innerHTML = "";
}
@@ -82,8 +95,15 @@ export class UmbThemeContext {
*/
}
export const UMB_THEME_SERVICE_CONTEXT_TOKEN = new UmbContextToken<UmbThemeContext>(UmbThemeContext.name);
function UmbObserveController(arg0: Subscription): any {
throw new Error('Function not implemented.');
}
export const UMB_THEME_CONTEXT_TOKEN = new UmbContextToken<UmbThemeContext>('umbThemeContext');
// TODO: Can we do this in a smarter way:
const registerExtensions = (manifests: Array<ManifestTheme>) => {
manifests.forEach((manifest) => {
umbExtensionsRegistry.register(manifest);
});
};
registerExtensions([...manifests]);

View File

@@ -1,5 +1,5 @@
import { css } from 'lit';
import { UmbTheme } from '../theme.service';
import { UmbTheme } from '../theme.context';
// TODO: We should get this from UUI, and it should be served through an extension.
const name = 'Dark';
@@ -53,7 +53,4 @@ const cssResult = css`
}
`;
export const dark: UmbTheme = {
name: name,
css: cssResult.cssText,
};
export default cssResult.cssText;

View File

@@ -1,5 +1,5 @@
import { css } from 'lit';
import { UmbTheme } from '../theme.service';
import { UmbTheme } from '../theme.context';
// TODO: We should get this from UUI, and it should be served through an extension.
const name = 'High Contrast';

View File

@@ -1,2 +0,0 @@
export * from './dark.theme';
export * from './high-contrast.theme';

View File

@@ -2,7 +2,7 @@ import { css, html } from 'lit';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { customElement, state } from 'lit/decorators.js';
import { UUISelectEvent } from '@umbraco-ui/uui';
import { UmbThemeService, UMB_THEME_SERVICE_CONTEXT_TOKEN } from '../../themes/theme.service';
import { UmbThemeContext, UMB_THEME_CONTEXT_TOKEN } from '../../themes/theme.context';
import { UmbLitElement } from '@umbraco-cms/element';
@customElement('umb-user-dashboard-test')
@@ -23,25 +23,29 @@ export class UmbUserDashboardTestElement extends UmbLitElement {
`,
];
#themeService?: UmbThemeService;
#themeService?: UmbThemeContext;
@state()
private _theme = '';
private _theme: string | null = null;
@state()
private _themes: Array<string> = [];
constructor() {
super();
this.consumeContext(UMB_THEME_SERVICE_CONTEXT_TOKEN, (instance) => {
this.consumeContext(UMB_THEME_CONTEXT_TOKEN, (instance) => {
console.log("ThemeCOntext", instance)
this.#themeService = instance;
instance.theme.subscribe((theme) => {
this._theme = theme;
});
instance.setThemeByAlias('umb-dark-theme');
// TODO: We should get rid of the #themes state and instead use an extension point:
instance.themes.subscribe((themes) => {
/*instance.themes.subscribe((themes) => {
this._themes = themes.map((t) => t.name);
});
});*/
});
}