Skip to content

Commit

Permalink
fix(ie): global css variables
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Jun 24, 2019
1 parent 71ebdac commit 56c5f68
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 145 deletions.
46 changes: 24 additions & 22 deletions src/client/polyfills/css-shim/custom-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,35 @@ export class CustomStyle {
hostEl: HTMLElement,
cssScopeId: string,
cssText: string,
isScoped: boolean
) {
if (this.hostScopeMap.has(hostEl)) {
throw new Error('host style already created');
}
const baseScope = this.registerHostTemplate(cssText, cssScopeId);
const isDynamicScoped = !!(baseScope.isDynamic && baseScope.cssScopeId);
const needStyleEl = isDynamicScoped || !baseScope.styleEl;
const baseScope = this.registerHostTemplate(cssText, cssScopeId, isScoped);
const styleEl = this.doc.createElement('style');

if (!needStyleEl) {
if (!baseScope.usesCssVars) {
// This component does not use (read) css variables
styleEl.innerHTML = cssText;
} else {
if (isDynamicScoped) {
(styleEl as any)['s-sc'] = cssScopeId = `${baseScope.cssScopeId}-${this.count}`;
styleEl.innerHTML = '/*needs update*/';
this.hostStyleMap.set(hostEl, styleEl);
this.hostScopeMap.set(hostEl, reScope(baseScope, cssScopeId));
this.count++;

} else {
baseScope.styleEl = styleEl;
if (!baseScope.isDynamic) {
styleEl.innerHTML = executeTemplate(baseScope.template, {});
}
this.globalScopes.push(baseScope);
this.updateGlobal();
this.hostScopeMap.set(hostEl, baseScope);
} else if (isScoped) {
// This component is dynamic: uses css var and is scoped
(styleEl as any)['s-sc'] = cssScopeId = `${baseScope.scopeId}-${this.count}`;
styleEl.innerHTML = '/*needs update*/';
this.hostStyleMap.set(hostEl, styleEl);
this.hostScopeMap.set(hostEl, reScope(baseScope, cssScopeId));
this.count++;

} else {
// This component uses css vars, but it's no-encapsulation (global static)
baseScope.styleEl = styleEl;
if (!baseScope.usesCssVars) {
styleEl.innerHTML = executeTemplate(baseScope.template, {});
}
this.globalScopes.push(baseScope);
this.updateGlobal();
this.hostScopeMap.set(hostEl, baseScope);
}
return styleEl;
}
Expand All @@ -84,7 +85,7 @@ export class CustomStyle {

updateHost(hostEl: HTMLElement) {
const scope = this.hostScopeMap.get(hostEl);
if (scope && scope.isDynamic && scope.cssScopeId) {
if (scope && scope.usesCssVars && scope.isScoped) {
const styleEl = this.hostStyleMap.get(hostEl);
if (styleEl) {
const selectors = getActiveSelectors(hostEl, this.hostScopeMap, this.globalScopes);
Expand All @@ -98,11 +99,12 @@ export class CustomStyle {
updateGlobalScopes(this.globalScopes);
}

private registerHostTemplate(cssText: string, scopeId: string) {
private registerHostTemplate(cssText: string, scopeId: string, isScoped: boolean) {
let scope = this.scopesMap.get(scopeId);
if (!scope) {
scope = parseCSS(cssText);
scope.cssScopeId = scopeId;
scope.scopeId = scopeId;
scope.isScoped = isScoped;
this.scopesMap.set(scopeId, scope);
}
return scope;
Expand Down
5 changes: 3 additions & 2 deletions src/client/polyfills/css-shim/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ export interface Declaration {
export interface CSSScope {
original: string;

cssScopeId?: string;
scopeId?: string;
isScoped?: boolean;

selectors: CSSSelector[];
template: CSSTemplate;
isDynamic: boolean;
usesCssVars: boolean;
styleEl?: HTMLStyleElement;
}
12 changes: 6 additions & 6 deletions src/client/polyfills/css-shim/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function parseCSS(original: string): CSSScope {
original,
template,
selectors,
isDynamic: template.length > 1
usesCssVars: template.length > 1
};
}

Expand All @@ -26,32 +26,32 @@ export function updateGlobalScopes(scopes: CSSScope[]) {
const selectors = getSelectorsForScopes(scopes);
const props = resolveValues(selectors);
scopes.forEach(scope => {
if (scope.isDynamic) {
if (scope.usesCssVars) {
scope.styleEl.innerHTML = executeTemplate(scope.template, props);
}
});
}

export function reScope(scope: CSSScope, cssScopeId: string): CSSScope {
export function reScope(scope: CSSScope, scopeId: string): CSSScope {

const template = scope.template.map(segment => {
return (typeof segment === 'string')
? replaceScope(segment, scope.cssScopeId, cssScopeId)
? replaceScope(segment, scope.scopeId, scopeId)
: segment;
});

const selectors = scope.selectors.map(sel => {
return {
...sel,
selector: replaceScope(sel.selector, scope.cssScopeId, cssScopeId)
selector: replaceScope(sel.selector, scope.scopeId, scopeId)
};
});

return {
...scope,
template,
selectors,
cssScopeId,
scopeId,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/declarations/css-var-shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface CssVarSim {
hostEl: HTMLElement,
templateName: string,
cssText: string,
isScoped: boolean
): HTMLStyleElement;

removeHost(hostEl: HTMLElement): void;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/connected-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const connectedCallback = (elm: d.HostElement, cmpMeta: d.ComponentRuntim
hostId = elm.getAttribute(HYDRATE_ID);
if (hostId) {
if (BUILD.shadowDom && supportsShadowDom && cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) {
const scopeId = addStyle(elm.shadowRoot, cmpMeta.$tagName$, elm.getAttribute('s-mode'));
const scopeId = addStyle(elm.shadowRoot, cmpMeta, elm.getAttribute('s-mode'));
elm.classList.remove(scopeId + '-h');
elm.classList.remove(scopeId + '-s');
}
Expand Down
10 changes: 5 additions & 5 deletions src/runtime/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ export const registerStyle = (scopeId: string, cssText: string, allowCS: boolean
styles.set(scopeId, style);
};

export const addStyle = (styleContainerNode: any, tagName: string, mode: string, hostElm?: HTMLElement) => {
let scopeId = getScopeId(tagName, mode);
export const addStyle = (styleContainerNode: any, cmpMeta: d.ComponentRuntimeMeta, mode: string, hostElm?: HTMLElement) => {
let scopeId = getScopeId(cmpMeta.$tagName$, mode);
let style = styles.get(scopeId);

// if an element is NOT connected then getRootNode() will return the wrong root node
// so the fallback is to always use the document for the root node in those cases
styleContainerNode = (styleContainerNode.nodeType === NODE_TYPE.DocumentFragment ? styleContainerNode : doc);

if (BUILD.mode && !style) {
scopeId = getScopeId(tagName);
scopeId = getScopeId(cmpMeta.$tagName$);
style = styles.get(scopeId);
}

Expand All @@ -52,7 +52,7 @@ export const addStyle = (styleContainerNode: any, tagName: string, mode: string,

} else {
if (cssVarShim) {
styleElm = cssVarShim.createHostStyle(hostElm, scopeId, style);
styleElm = cssVarShim.createHostStyle(hostElm, scopeId, style, !!(cmpMeta.$flags$ & CMP_FLAGS.needsScopedEncapsulation));
const newScopeId = (styleElm as any)['s-sc'];
if (newScopeId) {
scopeId = newScopeId;
Expand Down Expand Up @@ -98,7 +98,7 @@ export const attachStyles = (elm: d.HostElement, cmpMeta: d.ComponentRuntimeMeta
const styleId = addStyle(
(BUILD.shadowDom && supportsShadowDom && elm.shadowRoot)
? elm.shadowRoot
: elm.getRootNode(), cmpMeta.$tagName$, mode, elm);
: elm.getRootNode(), cmpMeta, mode, elm);

if ((BUILD.shadowDom || BUILD.scoped) && BUILD.cssAnnotations && cmpMeta.$flags$ & CMP_FLAGS.needsScopedEncapsulation) {
// only required when we're NOT using native shadow dom (slot)
Expand Down
1 change: 1 addition & 0 deletions test/karma/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const config = {
],
copy: [
{ src: '**/*.html' },
{ src: '**/*.css' },
{ src: 'noscript.js' }
],
excludeSrc: [],
Expand Down
32 changes: 16 additions & 16 deletions test/karma/test-app/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export namespace Components {
interface ConditionalRerender {}
interface ConditionalRerenderRoot {}
interface CssCmp {}
interface CssVariables {}
interface CssVariablesRoot {}
interface CssVariablesNoEncapsulation {}
interface CssVariablesShadowDom {}
interface CustomEventRoot {}
interface DomReattach {
'didLoad': number;
Expand Down Expand Up @@ -260,16 +260,16 @@ declare global {
new (): HTMLCssCmpElement;
};

interface HTMLCssVariablesElement extends Components.CssVariables, HTMLStencilElement {}
var HTMLCssVariablesElement: {
prototype: HTMLCssVariablesElement;
new (): HTMLCssVariablesElement;
interface HTMLCssVariablesNoEncapsulationElement extends Components.CssVariablesNoEncapsulation, HTMLStencilElement {}
var HTMLCssVariablesNoEncapsulationElement: {
prototype: HTMLCssVariablesNoEncapsulationElement;
new (): HTMLCssVariablesNoEncapsulationElement;
};

interface HTMLCssVariablesRootElement extends Components.CssVariablesRoot, HTMLStencilElement {}
var HTMLCssVariablesRootElement: {
prototype: HTMLCssVariablesRootElement;
new (): HTMLCssVariablesRootElement;
interface HTMLCssVariablesShadowDomElement extends Components.CssVariablesShadowDom, HTMLStencilElement {}
var HTMLCssVariablesShadowDomElement: {
prototype: HTMLCssVariablesShadowDomElement;
new (): HTMLCssVariablesShadowDomElement;
};

interface HTMLCustomEventRootElement extends Components.CustomEventRoot, HTMLStencilElement {}
Expand Down Expand Up @@ -746,8 +746,8 @@ declare global {
'conditional-rerender': HTMLConditionalRerenderElement;
'conditional-rerender-root': HTMLConditionalRerenderRootElement;
'css-cmp': HTMLCssCmpElement;
'css-variables': HTMLCssVariablesElement;
'css-variables-root': HTMLCssVariablesRootElement;
'css-variables-no-encapsulation': HTMLCssVariablesNoEncapsulationElement;
'css-variables-shadow-dom': HTMLCssVariablesShadowDomElement;
'custom-event-root': HTMLCustomEventRootElement;
'dom-reattach': HTMLDomReattachElement;
'dynamic-css-variable': HTMLDynamicCssVariableElement;
Expand Down Expand Up @@ -863,8 +863,8 @@ declare namespace LocalJSX {
interface ConditionalRerender extends JSXBase.HTMLAttributes<HTMLConditionalRerenderElement> {}
interface ConditionalRerenderRoot extends JSXBase.HTMLAttributes<HTMLConditionalRerenderRootElement> {}
interface CssCmp extends JSXBase.HTMLAttributes<HTMLCssCmpElement> {}
interface CssVariables extends JSXBase.HTMLAttributes<HTMLCssVariablesElement> {}
interface CssVariablesRoot extends JSXBase.HTMLAttributes<HTMLCssVariablesRootElement> {}
interface CssVariablesNoEncapsulation extends JSXBase.HTMLAttributes<HTMLCssVariablesNoEncapsulationElement> {}
interface CssVariablesShadowDom extends JSXBase.HTMLAttributes<HTMLCssVariablesShadowDomElement> {}
interface CustomEventRoot extends JSXBase.HTMLAttributes<HTMLCustomEventRootElement> {}
interface DomReattach extends JSXBase.HTMLAttributes<HTMLDomReattachElement> {
'didLoad'?: number;
Expand Down Expand Up @@ -1016,8 +1016,8 @@ declare namespace LocalJSX {
'conditional-rerender': ConditionalRerender;
'conditional-rerender-root': ConditionalRerenderRoot;
'css-cmp': CssCmp;
'css-variables': CssVariables;
'css-variables-root': CssVariablesRoot;
'css-variables-no-encapsulation': CssVariablesNoEncapsulation;
'css-variables-shadow-dom': CssVariablesShadowDom;
'custom-event-root': CustomEventRoot;
'dom-reattach': DomReattach;
'dynamic-css-variable': DynamicCssVariable;
Expand Down
23 changes: 23 additions & 0 deletions test/karma/test-app/css-variables/cmp-no-encapsulation.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
:root {
--font-weight: 800;
}

.black-local {
--background: black;
--color: white;

background: var(--background);
color: var(--color);
}

.black-global {
background: var(--global-background);
color: var(--global-color);
font-weight: var(--font-weight);
}

.yellow-global {
background: var(--link-background);
color: black;
}

25 changes: 25 additions & 0 deletions test/karma/test-app/css-variables/cmp-no-encapsulation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, h, Host } from '@stencil/core';

@Component({
tag: 'css-variables-no-encapsulation',
styleUrl: 'cmp-no-encapsulation.css'
})
export class CssVariablesNoEncapsulation {

render() {
return (
<Host>
<div class="black-local">
No encapsulation: Black background
</div>
<div class="black-global">
No encapsulation: Black background (global style)
</div>
<div class="yellow-global">
No encapsulation: Yellow background (global link)
</div>
</Host>
);
}

}
36 changes: 0 additions & 36 deletions test/karma/test-app/css-variables/cmp-root.css

This file was deleted.

16 changes: 0 additions & 16 deletions test/karma/test-app/css-variables/cmp-root.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions test/karma/test-app/css-variables/cmp-shadow-dom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

:host {
--color: blue;
--background: red;
}

:host(.set-green) {
--background: green;
}

.inner-div {
background: var(--background);
color: var(--color);
}

.black-global {
background: var(--global-background);
color: var(--global-color);
font-weight: var(--font-weight);
}

1 comment on commit 56c5f68

@bbellmyers
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can confirm this does fix my test project with components that are set to shadow:false.

Please sign in to comment.