From 770ca39b80f77bcfd423b600d4373c3922622275 Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Wed, 11 Mar 2020 13:34:43 +0000 Subject: [PATCH 01/10] theme-variant-config --- package-lock.json | 41 +++++++++-------------------- src/core/interfaces.d.ts | 17 ++++++++++++ src/core/middleware/theme.ts | 51 ++++++++++++++++++++++++++++++------ 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1021ff78b..f4250415a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1309,9 +1309,9 @@ } }, "cldrjs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.1.tgz", - "integrity": "sha512-xyiP8uAm8K1IhmpDndZLraloW1yqu0L+HYdQ7O1aGPxx9Cr+BMnPANlNhSt++UKfxytL2hd2NPXgTjiy7k43Ew==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.0.tgz", + "integrity": "sha1-N76S2NGo5myO4S8TA+0xbYXY6zc=" }, "cli-cursor": { "version": "1.0.2", @@ -2341,21 +2341,6 @@ "pend": "~1.2.0" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, "yauzl": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", @@ -4744,18 +4729,18 @@ } }, "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "0.0.8" }, "dependencies": { "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } } @@ -6755,9 +6740,9 @@ }, "dependencies": { "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.3.tgz", + "integrity": "sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw==", "dev": true } } diff --git a/src/core/interfaces.d.ts b/src/core/interfaces.d.ts index 1afa9fdd4..808ec7cef 100644 --- a/src/core/interfaces.d.ts +++ b/src/core/interfaces.d.ts @@ -124,6 +124,23 @@ export interface Theme { [key: string]: object; } +export interface Variant { + root: string; +} + +export interface ThemeVariant { + theme: Theme; + variant: Variant; +} + +export interface ThemeVariantConfig { + theme: Theme; + variants: { + default: Variant; + [key: string]: Variant; + }; +} + export interface Classes { [widgetKey: string]: { [classKey: string]: SupportedClassName[]; diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index 42b9b89c0..1dd304883 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -1,4 +1,4 @@ -import { Theme, Classes, ClassNames } from './../interfaces'; +import { Theme, Classes, ClassNames, ThemeVariant, ThemeVariantConfig } from './../interfaces'; import { create, invalidator, diffProperty, getRegistry } from '../vdom'; import icache from './icache'; import injector from './injector'; @@ -10,7 +10,7 @@ import Registry from '../Registry'; export { Theme, Classes, ClassNames } from './../interfaces'; export interface ThemeProperties { - theme?: Theme; + theme?: Theme | ThemeVariant; classes?: Classes; } @@ -18,6 +18,14 @@ export const THEME_KEY = ' _key'; export const INJECTED_THEME_KEY = '__theme_injector'; +function isThemeVariant(theme: Theme | ThemeVariant): theme is ThemeVariant { + return theme.hasOwnProperty('variant'); +} + +function isThemeVariantConfig(theme: Theme | ThemeVariantConfig): theme is ThemeVariantConfig { + return theme.hasOwnProperty('variants'); +} + function registerThemeInjector(theme: any, themeRegistry: Registry): Injector { const themeInjector = new Injector(theme); themeRegistry.defineInjector(INJECTED_THEME_KEY, (invalidator) => { @@ -75,6 +83,21 @@ export const theme = factory( icache.clear(); invalidator(); }); + + function set(theme: Theme): void; + function set(theme: ThemeVariantConfig, variant?: keyof ThemeVariantConfig['variants']): void; + function set(theme: Theme | ThemeVariantConfig, variant?: keyof ThemeVariantConfig['variants']): void { + const currentTheme = injector.get>(INJECTED_THEME_KEY); + + if (currentTheme) { + if (isThemeVariantConfig(theme)) { + theme = { theme: theme.theme, variant: theme.variants[variant || 'default'] }; + } + + currentTheme.set(theme); + } + } + return { classes(css: T): T { let theme = icache.get(css); @@ -100,14 +123,26 @@ export const theme = factory( icache.set(css, theme, false); return theme; }, - set(css: Theme): void { - const currentTheme = injector.get>(INJECTED_THEME_KEY); - if (currentTheme) { - currentTheme.set(css); + variant() { + let theme; + const { theme: themeProp } = properties(); + + if (themeProp) { + theme = themeProp; + } else { + const currentTheme = injector.get>(INJECTED_THEME_KEY); + if (currentTheme) { + theme = currentTheme.get(); + } + } + + if (theme && isThemeVariant(theme)) { + return theme.variant.root; } }, - get(): Theme | undefined { - const currentTheme = injector.get>(INJECTED_THEME_KEY); + set, + get(): Theme | ThemeVariant | undefined { + const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { return currentTheme.get(); } From 1264ddfc0396dafb27bebe91b7bb8ba8a450fb26 Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Wed, 11 Mar 2020 14:54:11 +0000 Subject: [PATCH 02/10] correct set --- src/core/middleware/theme.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index 1dd304883..fd224dfe5 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -108,6 +108,11 @@ export const theme = factory( themeKeys.add(key); theme = classes as T; let { theme: currentTheme, classes: currentClasses } = properties(); + + if (currentTheme && isThemeVariant(currentTheme)) { + currentTheme = currentTheme.theme; + } + if (currentTheme && currentTheme[key]) { theme = { ...theme, ...currentTheme[key] }; } From 03c227ff84506d39727c26b0190be726385104a7 Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Wed, 11 Mar 2020 15:36:57 +0000 Subject: [PATCH 03/10] mixin changes --- src/core/mixins/Themed.ts | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index 96227f3b6..d24be9981 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -1,4 +1,12 @@ -import { Theme, Classes, ClassNames, Constructor, SupportedClassName } from './../interfaces'; +import { + Theme, + Classes, + ClassNames, + Constructor, + SupportedClassName, + ThemeVariant, + ThemeVariantConfig +} from './../interfaces'; import { Registry } from './../Registry'; import { Injector } from './../Injector'; import { inject } from './../decorators/inject'; @@ -13,7 +21,7 @@ export { Theme, Classes, ClassNames } from './../interfaces'; */ export interface ThemedProperties { /** Overriding custom theme for the widget */ - theme?: Theme; + theme?: Theme | ThemeVariant; /** Map of widget keys and associated overriding classes */ classes?: Classes; /** Extra classes to be applied to the widget */ @@ -24,12 +32,17 @@ export const THEME_KEY = ' _key'; export const INJECTED_THEME_KEY = '__theme_injector'; +function isThemeVariant(theme: Theme | ThemeVariant): theme is ThemeVariant { + return theme.hasOwnProperty('variant'); +} + /** * Interface for the ThemedMixin */ export interface ThemedMixin { theme(classes: SupportedClassName): SupportedClassName; theme(classes: SupportedClassName[]): SupportedClassName[]; + variant(): string | undefined; properties: ThemedProperties; } @@ -140,6 +153,13 @@ export function ThemedMixin Date: Wed, 11 Mar 2020 16:28:01 +0000 Subject: [PATCH 04/10] allow theme config to be passed via theme prop --- src/core/interfaces.d.ts | 4 ++-- src/core/middleware/theme.ts | 22 +++++++++++++++++----- src/core/mixins/Themed.ts | 23 +++++++++++++++++++---- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/core/interfaces.d.ts b/src/core/interfaces.d.ts index 808ec7cef..5ac61b5de 100644 --- a/src/core/interfaces.d.ts +++ b/src/core/interfaces.d.ts @@ -129,8 +129,8 @@ export interface Variant { } export interface ThemeVariant { - theme: Theme; - variant: Variant; + theme: Theme | ThemeVariantConfig; + variant: Variant | string; } export interface ThemeVariantConfig { diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index fd224dfe5..9bb69582b 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -1,4 +1,4 @@ -import { Theme, Classes, ClassNames, ThemeVariant, ThemeVariantConfig } from './../interfaces'; +import { Theme, Classes, ClassNames, ThemeVariant, ThemeVariantConfig, Variant } from './../interfaces'; import { create, invalidator, diffProperty, getRegistry } from '../vdom'; import icache from './icache'; import injector from './injector'; @@ -26,6 +26,10 @@ function isThemeVariantConfig(theme: Theme | ThemeVariantConfig): theme is Theme return theme.hasOwnProperty('variants'); } +function isVariantModule(variant: string | Variant): variant is Variant { + return typeof variant !== 'string'; +} + function registerThemeInjector(theme: any, themeRegistry: Registry): Injector { const themeInjector = new Injector(theme); themeRegistry.defineInjector(INJECTED_THEME_KEY, (invalidator) => { @@ -85,8 +89,8 @@ export const theme = factory( }); function set(theme: Theme): void; - function set(theme: ThemeVariantConfig, variant?: keyof ThemeVariantConfig['variants']): void; - function set(theme: Theme | ThemeVariantConfig, variant?: keyof ThemeVariantConfig['variants']): void { + function set(theme: T, variant?: keyof T['variants']): void; + function set(theme: Theme | T, variant?: keyof T['variants']): void { const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { @@ -110,7 +114,9 @@ export const theme = factory( let { theme: currentTheme, classes: currentClasses } = properties(); if (currentTheme && isThemeVariant(currentTheme)) { - currentTheme = currentTheme.theme; + currentTheme = isThemeVariantConfig(currentTheme.theme) + ? currentTheme.theme.theme + : currentTheme.theme; } if (currentTheme && currentTheme[key]) { @@ -142,7 +148,13 @@ export const theme = factory( } if (theme && isThemeVariant(theme)) { - return theme.variant.root; + if (isVariantModule(theme.variant)) { + return theme.variant.root; + } + + if (isThemeVariantConfig(theme.theme)) { + return theme.theme.variants[theme.variant].root; + } } }, set, diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index d24be9981..9becd09e9 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -5,7 +5,8 @@ import { Constructor, SupportedClassName, ThemeVariant, - ThemeVariantConfig + ThemeVariantConfig, + Variant } from './../interfaces'; import { Registry } from './../Registry'; import { Injector } from './../Injector'; @@ -36,6 +37,14 @@ function isThemeVariant(theme: Theme | ThemeVariant): theme is ThemeVariant { return theme.hasOwnProperty('variant'); } +function isThemeVariantConfig(theme: Theme | ThemeVariantConfig): theme is ThemeVariantConfig { + return theme.hasOwnProperty('variants'); +} + +function isVariantModule(variant: string | Variant): variant is Variant { + return typeof variant !== 'string'; +} + /** * Interface for the ThemedMixin */ @@ -155,8 +164,14 @@ export function ThemedMixin Date: Wed, 11 Mar 2020 16:44:18 +0000 Subject: [PATCH 05/10] fix function override --- src/core/middleware/theme.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index 9bb69582b..4c94b7020 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -89,8 +89,11 @@ export const theme = factory( }); function set(theme: Theme): void; - function set(theme: T, variant?: keyof T['variants']): void; - function set(theme: Theme | T, variant?: keyof T['variants']): void { + function set(theme: T, variant?: Extract): void; + function set( + theme: Theme | T, + variant?: Extract + ): void { const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { From bdb14a5968e4510d6fad1ce475c9a7e662a8c972 Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Wed, 11 Mar 2020 17:03:10 +0000 Subject: [PATCH 06/10] use template string --- src/core/middleware/theme.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index 4c94b7020..13d1552e4 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -89,16 +89,13 @@ export const theme = factory( }); function set(theme: Theme): void; - function set(theme: T, variant?: Extract): void; - function set( - theme: Theme | T, - variant?: Extract - ): void { + function set(theme: T, variant?: keyof T['variants']): void; + function set(theme: Theme | T, variant?: keyof T['variants']): void { const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { if (isThemeVariantConfig(theme)) { - theme = { theme: theme.theme, variant: theme.variants[variant || 'default'] }; + theme = { theme: theme.theme, variant: theme.variants[`${variant || 'default'}`] }; } currentTheme.set(theme); From 1577c7928a4c1df641e2c4a321f72dd64979d9df Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Thu, 19 Mar 2020 19:43:52 +0000 Subject: [PATCH 07/10] pr comments --- src/core/interfaces.d.ts | 8 +++---- src/core/middleware/theme.ts | 46 +++++++++++++----------------------- src/core/mixins/Themed.ts | 16 ++++++------- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/core/interfaces.d.ts b/src/core/interfaces.d.ts index 5ac61b5de..f78e8a859 100644 --- a/src/core/interfaces.d.ts +++ b/src/core/interfaces.d.ts @@ -128,13 +128,13 @@ export interface Variant { root: string; } -export interface ThemeVariant { - theme: Theme | ThemeVariantConfig; +export interface ThemeWithVariant { + css: Theme | ThemeWithVariants; variant: Variant | string; } -export interface ThemeVariantConfig { - theme: Theme; +export interface ThemeWithVariants { + css: Theme; variants: { default: Variant; [key: string]: Variant; diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index 13d1552e4..ede2ebb22 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -1,4 +1,4 @@ -import { Theme, Classes, ClassNames, ThemeVariant, ThemeVariantConfig, Variant } from './../interfaces'; +import { Theme, Classes, ClassNames, ThemeWithVariant, ThemeWithVariants, Variant } from './../interfaces'; import { create, invalidator, diffProperty, getRegistry } from '../vdom'; import icache from './icache'; import injector from './injector'; @@ -10,7 +10,7 @@ import Registry from '../Registry'; export { Theme, Classes, ClassNames } from './../interfaces'; export interface ThemeProperties { - theme?: Theme | ThemeVariant; + theme?: Theme | ThemeWithVariant; classes?: Classes; } @@ -18,11 +18,11 @@ export const THEME_KEY = ' _key'; export const INJECTED_THEME_KEY = '__theme_injector'; -function isThemeVariant(theme: Theme | ThemeVariant): theme is ThemeVariant { +function isThemeWithVariant(theme: Theme | ThemeWithVariant): theme is ThemeWithVariant { return theme.hasOwnProperty('variant'); } -function isThemeVariantConfig(theme: Theme | ThemeVariantConfig): theme is ThemeVariantConfig { +function isThemeWithVariants(theme: Theme | ThemeWithVariants): theme is ThemeWithVariants { return theme.hasOwnProperty('variants'); } @@ -89,13 +89,13 @@ export const theme = factory( }); function set(theme: Theme): void; - function set(theme: T, variant?: keyof T['variants']): void; - function set(theme: Theme | T, variant?: keyof T['variants']): void { - const currentTheme = injector.get>(INJECTED_THEME_KEY); + function set(theme: T, variant?: keyof T['variants']): void; + function set(theme: Theme | T, variant?: keyof T['variants']): void { + const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { - if (isThemeVariantConfig(theme)) { - theme = { theme: theme.theme, variant: theme.variants[`${variant || 'default'}`] }; + if (isThemeWithVariants(theme)) { + theme = { css: theme.css, variant: theme.variants[`${variant || 'default'}`] }; } currentTheme.set(theme); @@ -113,10 +113,8 @@ export const theme = factory( theme = classes as T; let { theme: currentTheme, classes: currentClasses } = properties(); - if (currentTheme && isThemeVariant(currentTheme)) { - currentTheme = isThemeVariantConfig(currentTheme.theme) - ? currentTheme.theme.theme - : currentTheme.theme; + if (currentTheme && isThemeWithVariant(currentTheme)) { + currentTheme = isThemeWithVariants(currentTheme.css) ? currentTheme.css.css : currentTheme.css; } if (currentTheme && currentTheme[key]) { @@ -135,31 +133,21 @@ export const theme = factory( return theme; }, variant() { - let theme; - const { theme: themeProp } = properties(); - - if (themeProp) { - theme = themeProp; - } else { - const currentTheme = injector.get>(INJECTED_THEME_KEY); - if (currentTheme) { - theme = currentTheme.get(); - } - } + const { theme } = properties(); - if (theme && isThemeVariant(theme)) { + if (theme && isThemeWithVariant(theme)) { if (isVariantModule(theme.variant)) { return theme.variant.root; } - if (isThemeVariantConfig(theme.theme)) { - return theme.theme.variants[theme.variant].root; + if (isThemeWithVariants(theme.css)) { + return theme.css.variants[theme.variant].root; } } }, set, - get(): Theme | ThemeVariant | undefined { - const currentTheme = injector.get>(INJECTED_THEME_KEY); + get(): Theme | ThemeWithVariant | undefined { + const currentTheme = injector.get>(INJECTED_THEME_KEY); if (currentTheme) { return currentTheme.get(); } diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index 9becd09e9..449a85ed4 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -4,8 +4,8 @@ import { ClassNames, Constructor, SupportedClassName, - ThemeVariant, - ThemeVariantConfig, + ThemeWithVariant, + ThemeWithVariants, Variant } from './../interfaces'; import { Registry } from './../Registry'; @@ -22,7 +22,7 @@ export { Theme, Classes, ClassNames } from './../interfaces'; */ export interface ThemedProperties { /** Overriding custom theme for the widget */ - theme?: Theme | ThemeVariant; + theme?: Theme | ThemeWithVariant; /** Map of widget keys and associated overriding classes */ classes?: Classes; /** Extra classes to be applied to the widget */ @@ -33,11 +33,11 @@ export const THEME_KEY = ' _key'; export const INJECTED_THEME_KEY = '__theme_injector'; -function isThemeVariant(theme: Theme | ThemeVariant): theme is ThemeVariant { +function isThemeVariant(theme: Theme | ThemeWithVariant): theme is ThemeWithVariant { return theme.hasOwnProperty('variant'); } -function isThemeVariantConfig(theme: Theme | ThemeVariantConfig): theme is ThemeVariantConfig { +function isThemeVariantConfig(theme: Theme | ThemeWithVariants): theme is ThemeWithVariants { return theme.hasOwnProperty('variants'); } @@ -169,8 +169,8 @@ export function ThemedMixin Date: Mon, 23 Mar 2020 11:19:52 +0000 Subject: [PATCH 08/10] tests for themed mixin / middleware --- src/core/middleware/theme.ts | 5 +- src/core/mixins/Themed.ts | 2 +- tests/core/unit/middleware/theme.tsx | 152 +++++++++++++++++++++++++++ tests/core/unit/mixins/Themed.ts | 123 ++++++++++++++++++++++ 4 files changed, 279 insertions(+), 3 deletions(-) diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index ede2ebb22..cc93978d0 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -19,11 +19,11 @@ export const THEME_KEY = ' _key'; export const INJECTED_THEME_KEY = '__theme_injector'; function isThemeWithVariant(theme: Theme | ThemeWithVariant): theme is ThemeWithVariant { - return theme.hasOwnProperty('variant'); + return theme && theme.hasOwnProperty('variant'); } function isThemeWithVariants(theme: Theme | ThemeWithVariants): theme is ThemeWithVariants { - return theme.hasOwnProperty('variants'); + return theme && theme.hasOwnProperty('variants'); } function isVariantModule(variant: string | Variant): variant is Variant { @@ -52,6 +52,7 @@ export const theme = factory( icache.clear(); invalidator(); } + if (!next.theme && themeInjector) { return themeInjector.get(); } diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index 449a85ed4..3ce65e031 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -163,7 +163,7 @@ export function ThemedMixin { '
{"test-key":{"root":"themed-root"}}
' ); }); + + it('returns theme variant class', () => { + const factory = create({ theme }); + const themeWithVariant = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variant: { + root: 'variant-root' + } + }; + + const App = factory(function App({ middleware: { theme } }) { + const variantRoot = theme.variant(); + return
; + }); + const root = document.createElement('div'); + const r = renderer(() => ); + r.mount({ domNode: root }); + assert.strictEqual(root.innerHTML, '
'); + }); + + it('selects default variant theme with variants is set', () => { + const factory = create({ theme }); + const themeWithVariants = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variants: { + default: { + root: 'default-variant-root' + } + } + }; + + const App = factory(function App({ middleware: { theme } }) { + const variantRoot = theme.variant(); + return ( +
+
+ ); + }); + const root = document.createElement('div'); + const r = renderer(() => ); + r.mount({ domNode: root }); + (root.children[0].children[0] as HTMLButtonElement).click(); + resolvers.resolve(); + assert.strictEqual(root.innerHTML, '
'); + }); + + it('selects keyes variant theme with variants is set with variant key', () => { + const factory = create({ theme }); + const themeWithVariants = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variants: { + default: { + root: 'default-variant-root' + }, + foo: { + root: 'foo-variant-root' + } + } + }; + + const App = factory(function App({ middleware: { theme } }) { + const variantRoot = theme.variant(); + return ( +
+
+ ); + }); + const root = document.createElement('div'); + const r = renderer(() => ); + r.mount({ domNode: root }); + (root.children[0].children[0] as HTMLButtonElement).click(); + resolvers.resolve(); + assert.strictEqual(root.innerHTML, '
'); + }); + + it('selects specific variant when passed', () => { + const factory = create({ theme }); + const themeWithVariants = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variants: { + default: { + root: 'default-variant-root' + }, + foo: { + root: 'foo-variant-root' + } + } + }; + + const App = factory(function App({ middleware: { theme } }) { + const variantRoot = theme.variant(); + return
; + }); + const root = document.createElement('div'); + const r = renderer(() => ); + r.mount({ domNode: root }); + assert.strictEqual(root.innerHTML, '
'); + }); + + it('selects specific variant when key passed', () => { + const factory = create({ theme }); + const themeWithVariants = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variants: { + default: { + root: 'default-variant-root' + }, + bar: { + root: 'bar-variant-root' + } + } + }; + + const App = factory(function App({ middleware: { theme } }) { + const variantRoot = theme.variant(); + return
; + }); + const root = document.createElement('div'); + const r = renderer(() => ); + r.mount({ domNode: root }); + assert.strictEqual(root.innerHTML, '
'); + }); }); diff --git a/tests/core/unit/mixins/Themed.ts b/tests/core/unit/mixins/Themed.ts index 994d50296..537988851 100644 --- a/tests/core/unit/mixins/Themed.ts +++ b/tests/core/unit/mixins/Themed.ts @@ -353,6 +353,129 @@ registerSuite('ThemedMixin', { fixedClassName ]); } + }, + variants: { + 'theme variant can be injected via a registry'() { + const themeWithVariant = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variant: { + root: 'default-variant-root' + } + }; + + registerThemeInjector(themeWithVariant, testRegistry); + class InjectedTheme extends TestWidget { + render() { + return v('div', { classes: this.variant() }); + } + } + const themedInstance = new InjectedTheme(); + themedInstance.registry.base = testRegistry; + themedInstance.__setProperties__({}); + const renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, 'default-variant-root'); + }, + 'theme variant can be set via theme context'() { + const theme = { + 'test-key': { + root: 'themed-root' + } + }; + + const themeWithVariant = { + css: { + 'test-key': { + root: 'variant-themed-root' + } + }, + variant: { + root: 'variant-root' + } + }; + + const themeInjectorContext = registerThemeInjector(theme, testRegistry); + class InjectedTheme extends TestWidget { + render() { + return v('div', { classes: this.variant() }); + } + } + const themedInstance = new InjectedTheme(); + themedInstance.registry.base = testRegistry; + themedInstance.__setProperties__({}); + let renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, undefined); + themeInjectorContext.set(themeWithVariant); + themedInstance.__setProperties__({}); + renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, 'variant-root'); + }, + 'theme variant can be set at the widget level'() { + const themeWithVariant = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variant: { + root: 'variant-root' + } + }; + + class ThemedWidget extends TestWidget { + render() { + return v('div', { classes: this.variant() }); + } + } + const themedInstance = new ThemedWidget(); + themedInstance.__setProperties__({}); + let renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, undefined); + themedInstance.__setProperties__({ theme: themeWithVariant }); + renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, 'variant-root'); + }, + 'theme property overrides injected property'() { + const themeWithVariant = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variant: { + root: 'variant-root' + } + }; + + const secondThemeWithVariant = { + css: { + 'test-key': { + root: 'themed-root' + } + }, + variant: { + root: 'second-variant-root' + } + }; + + registerThemeInjector(themeWithVariant, testRegistry); + class InjectedTheme extends TestWidget { + render() { + return v('div', { classes: this.variant() }); + } + } + const themedInstance = new InjectedTheme(); + themedInstance.registry.base = testRegistry; + themedInstance.__setProperties__({}); + let renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, 'variant-root'); + themedInstance.__setProperties__({ theme: secondThemeWithVariant }); + renderResult = themedInstance.__render__() as VNode; + assert.deepEqual(renderResult.properties.classes, 'second-variant-root'); + } } } }); From 22d905ce8f656e9a2a9336b2fef6ebe58f11891c Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Mon, 23 Mar 2020 11:24:09 +0000 Subject: [PATCH 09/10] type theme injector --- src/core/middleware/theme.ts | 2 +- src/core/mixins/Themed.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/middleware/theme.ts b/src/core/middleware/theme.ts index cc93978d0..c71705845 100644 --- a/src/core/middleware/theme.ts +++ b/src/core/middleware/theme.ts @@ -30,7 +30,7 @@ function isVariantModule(variant: string | Variant): variant is Variant { return typeof variant !== 'string'; } -function registerThemeInjector(theme: any, themeRegistry: Registry): Injector { +function registerThemeInjector(theme: Theme | ThemeWithVariant | undefined, themeRegistry: Registry): Injector { const themeInjector = new Injector(theme); themeRegistry.defineInjector(INJECTED_THEME_KEY, (invalidator) => { themeInjector.setInvalidator(invalidator); diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index 3ce65e031..b976b30c2 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -92,7 +92,7 @@ function createThemeClassesLookup(classes: ClassNames[]): ClassNames { * * @returns the theme injector used to set the theme */ -export function registerThemeInjector(theme: any, themeRegistry: Registry): Injector { +export function registerThemeInjector(theme: Theme | ThemeWithVariant, themeRegistry: Registry): Injector { const themeInjector = new Injector(theme); themeRegistry.defineInjector(INJECTED_THEME_KEY, (invalidator) => { themeInjector.setInvalidator(invalidator); From 6a549170d6e0b1c659a9dca6fea1776c8d6fe3d6 Mon Sep 17 00:00:00 2001 From: Tom Dye Date: Mon, 23 Mar 2020 15:55:50 +0000 Subject: [PATCH 10/10] fix code coverage --- src/core/mixins/Themed.ts | 3 --- tests/core/unit/mixins/Themed.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/core/mixins/Themed.ts b/src/core/mixins/Themed.ts index b976b30c2..0770ecb80 100644 --- a/src/core/mixins/Themed.ts +++ b/src/core/mixins/Themed.ts @@ -169,9 +169,6 @@ export function ThemedMixin