extension model + other stuff added in conversation with Jesper.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
@@ -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
|
||||
|
||||
12
src/Umbraco.Web.UI.Client/src/backoffice/themes/manifests.ts
Normal file
12
src/Umbraco.Web.UI.Client/src/backoffice/themes/manifests.ts
Normal 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;
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './dark.theme';
|
||||
export * from './high-contrast.theme';
|
||||
@@ -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);
|
||||
});
|
||||
});*/
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user