From 3f4a7da1ec2872f414b08c381e5e003f7872a278 Mon Sep 17 00:00:00 2001 From: Anthony Johnston Date: Tue, 30 Oct 2018 10:41:44 +0000 Subject: [PATCH 1/4] feat(component): allow delegatesFocus on the component decorator --- .../transpile/datacollection/component-decorator.ts | 3 ++- src/core/host-snapshot.ts | 2 +- src/core/test/host-snapshot.spec.ts | 10 ++++++++++ src/declarations/component.ts | 1 + src/declarations/decorators.ts | 1 + 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/compiler/transpile/datacollection/component-decorator.ts b/src/compiler/transpile/datacollection/component-decorator.ts index c787fd8cad1..7ce4aaf3fdc 100644 --- a/src/compiler/transpile/datacollection/component-decorator.ts +++ b/src/compiler/transpile/datacollection/component-decorator.ts @@ -47,7 +47,8 @@ It will be removed in future versions. Please use the "hostData()" method instea assetsDirsMeta: [], hostMeta: getHostMeta(diagnostics, componentOptions.host), dependencies: [], - jsdoc: serializeSymbol(checker, symbol) + jsdoc: serializeSymbol(checker, symbol), + delegatesFocus: componentOptions.delegatesFocus }; // normalizeEncapsulation diff --git a/src/core/host-snapshot.ts b/src/core/host-snapshot.ts index 9a16361963b..a4d1c642406 100644 --- a/src/core/host-snapshot.ts +++ b/src/core/host-snapshot.ts @@ -55,7 +55,7 @@ export function initHostSnapshot(domApi: d.DomApi, cmpMeta: d.ComponentMeta, hos // this component is using shadow dom // and this browser supports shadow dom // add the read-only property "shadowRoot" to the host element - domApi.$attachShadow(hostElm, { mode: 'open' }); + domApi.$attachShadow(hostElm, { mode: 'open', delegatesFocus: cmpMeta.delegatesFocus }); } } diff --git a/src/core/test/host-snapshot.spec.ts b/src/core/test/host-snapshot.spec.ts index 0117d17e569..7358891f0fa 100644 --- a/src/core/test/host-snapshot.spec.ts +++ b/src/core/test/host-snapshot.spec.ts @@ -54,6 +54,16 @@ describe('host-snapshot', () => { expect(hostElm.shadowRoot).toBe(hostElm); }); + it('delegates focus is set', () => { + cmpMeta.encapsulationMeta = ENCAPSULATION.ShadowDom; + domApi.$supportsShadowDom = true; + let delegatesFocusWasSet = false; + cmpMeta.delegatesFocus = true; + domApi.$attachShadow = (_, o) => delegatesFocusWasSet = o.delegatesFocus; + initHostSnapshot(domApi, cmpMeta, hostElm); + expect(delegatesFocusWasSet).toBe(true); + }); + it('do not set content reference node is shadow and supports shadow', () => { domApi.$attachShadow = () => {/**/}; domApi.$supportsShadowDom = true; diff --git a/src/declarations/component.ts b/src/declarations/component.ts index 0917ae5d8ce..9313ae354cb 100644 --- a/src/declarations/component.ts +++ b/src/declarations/component.ts @@ -35,6 +35,7 @@ export interface ComponentMeta { jsdoc?: JsDoc; styleDocs?: StyleDoc[]; hmrLoad?: () => void; + delegatesFocus?: boolean; } diff --git a/src/declarations/decorators.ts b/src/declarations/decorators.ts index 19800b3992f..d4f6351a683 100644 --- a/src/declarations/decorators.ts +++ b/src/declarations/decorators.ts @@ -17,6 +17,7 @@ export interface ComponentOptions { host?: d.HostMeta; assetsDir?: string; assetsDirs?: string[]; + delegatesFocus?: boolean; } From 0dcb32a9013cf6747615c1241e73a8d2573e2b59 Mon Sep 17 00:00:00 2001 From: Anthony Johnston Date: Tue, 30 Oct 2018 17:12:55 +0000 Subject: [PATCH 2/4] shadow root init options make delegatesFocus available ```@Component({ ... shadow?: boolean | ShadowDomOptions })``` --- .../datacollection/component-decorator.ts | 26 +++++++++++++----- .../test/component-decorator.spec.ts | 27 ++++++++++++++++++- .../fixtures/component-shadow-w-options.ts | 8 ++++++ src/core/host-snapshot.ts | 2 +- src/core/test/host-snapshot.spec.ts | 10 ------- src/declarations/component.ts | 4 +-- src/declarations/decorators.ts | 5 ++-- src/util/constants.ts | 7 +++++ 8 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 src/compiler/transpile/datacollection/test/fixtures/component-shadow-w-options.ts diff --git a/src/compiler/transpile/datacollection/component-decorator.ts b/src/compiler/transpile/datacollection/component-decorator.ts index 7ce4aaf3fdc..7e885348dd9 100644 --- a/src/compiler/transpile/datacollection/component-decorator.ts +++ b/src/compiler/transpile/datacollection/component-decorator.ts @@ -1,11 +1,10 @@ import * as d from '../../../declarations'; import { buildWarn } from '../../util'; -import { ENCAPSULATION } from '../../../util/constants'; +import { ENCAPSULATION, DEFAULT_SHADOW_ROOT_INIT } from '../../../util/constants'; import { getDeclarationParameters, isDecoratorNamed, serializeSymbol } from './utils'; import { getStylesMeta } from './styles-meta'; import ts from 'typescript'; - export function getComponentDecoratorMeta(diagnostics: d.Diagnostic[], checker: ts.TypeChecker, node: ts.ClassDeclaration): d.ComponentMeta | undefined { if (!node.decorators) { return undefined; @@ -47,15 +46,24 @@ It will be removed in future versions. Please use the "hostData()" method instea assetsDirsMeta: [], hostMeta: getHostMeta(diagnostics, componentOptions.host), dependencies: [], - jsdoc: serializeSymbol(checker, symbol), - delegatesFocus: componentOptions.delegatesFocus + jsdoc: serializeSymbol(checker, symbol) }; - // normalizeEncapsulation - cmpMeta.encapsulationMeta = - componentOptions.shadow ? ENCAPSULATION.ShadowDom : + // shadow dom options + if(componentOptions.shadow){ + cmpMeta.encapsulationMeta = ENCAPSULATION.ShadowDom + if(isShadowDomOptions(componentOptions.shadow)) { + cmpMeta.shadowRootInit = Object.assign({}, DEFAULT_SHADOW_ROOT_INIT, { + delegatesFocus: componentOptions.shadow.delegatesFocus + }); + }else { + cmpMeta.shadowRootInit = DEFAULT_SHADOW_ROOT_INIT; + } + } else { + cmpMeta.encapsulationMeta = componentOptions.scoped ? ENCAPSULATION.ScopedCss : ENCAPSULATION.NoEncapsulation; + } // assetsDir: './somedir' if (componentOptions.assetsDir) { @@ -108,3 +116,7 @@ function getHostMeta(diagnostics: d.Diagnostic[], hostData: d.HostMeta) { return hostData; } + +function isShadowDomOptions(o: any): o is d.ShadowDomOptions { + return typeof(o) != typeof(true); +} \ No newline at end of file diff --git a/src/compiler/transpile/datacollection/test/component-decorator.spec.ts b/src/compiler/transpile/datacollection/test/component-decorator.spec.ts index a7231e9ec4e..06fb443e59c 100644 --- a/src/compiler/transpile/datacollection/test/component-decorator.spec.ts +++ b/src/compiler/transpile/datacollection/test/component-decorator.spec.ts @@ -1,4 +1,4 @@ -import { ENCAPSULATION } from '../../../../util/constants'; +import { ENCAPSULATION, DEFAULT_SHADOW_ROOT_INIT } from '../../../../util/constants'; import { getComponentDecoratorMeta } from '../component-decorator'; import { gatherMetadata } from './test-utils'; import * as path from 'path'; @@ -42,6 +42,31 @@ describe('component decorator', () => { hostMeta: {}, stylesMeta: {}, encapsulationMeta: ENCAPSULATION.ShadowDom, + shadowRootInit: DEFAULT_SHADOW_ROOT_INIT, + jsdoc: { + documentation: '', + name: 'ActionSheet', + tags: [], + type: 'typeof ActionSheet' + }, + assetsDirsMeta: [], + dependencies: [] + }); + }); + + it('shadow encapsulation with options', () => { + let response; + const sourceFilePath = path.resolve(__dirname, './fixtures/component-shadow-w-options'); + gatherMetadata(sourceFilePath, (checker, classNode) => { + response = getComponentDecoratorMeta([], checker, classNode); + }); + + expect(response).toEqual({ + tagNameMeta: 'ion-action-sheet', + hostMeta: {}, + stylesMeta: {}, + encapsulationMeta: ENCAPSULATION.ShadowDom, + shadowRootInit: Object.assign({}, DEFAULT_SHADOW_ROOT_INIT, { delegatesFocus: true }), jsdoc: { documentation: '', name: 'ActionSheet', diff --git a/src/compiler/transpile/datacollection/test/fixtures/component-shadow-w-options.ts b/src/compiler/transpile/datacollection/test/fixtures/component-shadow-w-options.ts new file mode 100644 index 00000000000..2bcf2ce62e2 --- /dev/null +++ b/src/compiler/transpile/datacollection/test/fixtures/component-shadow-w-options.ts @@ -0,0 +1,8 @@ +import { Component } from '../../../../../index'; + +@Component({ + tag: 'ion-action-sheet', + shadow: { delegatesFocus: true } +}) +class ActionSheet { +} diff --git a/src/core/host-snapshot.ts b/src/core/host-snapshot.ts index a4d1c642406..662bc011a05 100644 --- a/src/core/host-snapshot.ts +++ b/src/core/host-snapshot.ts @@ -55,7 +55,7 @@ export function initHostSnapshot(domApi: d.DomApi, cmpMeta: d.ComponentMeta, hos // this component is using shadow dom // and this browser supports shadow dom // add the read-only property "shadowRoot" to the host element - domApi.$attachShadow(hostElm, { mode: 'open', delegatesFocus: cmpMeta.delegatesFocus }); + domApi.$attachShadow(hostElm, cmpMeta.shadowRootInit); } } diff --git a/src/core/test/host-snapshot.spec.ts b/src/core/test/host-snapshot.spec.ts index 7358891f0fa..0117d17e569 100644 --- a/src/core/test/host-snapshot.spec.ts +++ b/src/core/test/host-snapshot.spec.ts @@ -54,16 +54,6 @@ describe('host-snapshot', () => { expect(hostElm.shadowRoot).toBe(hostElm); }); - it('delegates focus is set', () => { - cmpMeta.encapsulationMeta = ENCAPSULATION.ShadowDom; - domApi.$supportsShadowDom = true; - let delegatesFocusWasSet = false; - cmpMeta.delegatesFocus = true; - domApi.$attachShadow = (_, o) => delegatesFocusWasSet = o.delegatesFocus; - initHostSnapshot(domApi, cmpMeta, hostElm); - expect(delegatesFocusWasSet).toBe(true); - }); - it('do not set content reference node is shadow and supports shadow', () => { domApi.$attachShadow = () => {/**/}; domApi.$supportsShadowDom = true; diff --git a/src/declarations/component.ts b/src/declarations/component.ts index 9313ae354cb..0046ba02763 100644 --- a/src/declarations/component.ts +++ b/src/declarations/component.ts @@ -28,14 +28,14 @@ export interface ComponentMeta { listenersMeta?: ListenMeta[]; hostMeta?: HostMeta; encapsulationMeta?: number; + shadowRootInit?: Readonly; assetsDirsMeta?: AssetsMeta[]; componentConstructor?: ComponentConstructor; componentClass?: string; dependencies?: ComponentDependencies; jsdoc?: JsDoc; styleDocs?: StyleDoc[]; - hmrLoad?: () => void; - delegatesFocus?: boolean; + hmrLoad?: () => void; } diff --git a/src/declarations/decorators.ts b/src/declarations/decorators.ts index d4f6351a683..bf60832ab34 100644 --- a/src/declarations/decorators.ts +++ b/src/declarations/decorators.ts @@ -13,14 +13,15 @@ export interface ComponentOptions { styleUrls?: string[] | d.ModeStyles; styles?: string; scoped?: boolean; - shadow?: boolean; + shadow?: boolean | ShadowDomOptions; host?: d.HostMeta; assetsDir?: string; assetsDirs?: string[]; +} +export interface ShadowDomOptions { delegatesFocus?: boolean; } - export interface PropDecorator { (opts?: PropOptions): PropertyDecorator; } diff --git a/src/util/constants.ts b/src/util/constants.ts index 0ece246f412..1cbadb8e1f7 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -52,6 +52,13 @@ export const enum ENCAPSULATION { ScopedCss = 2, } +/** + * DEFAULT_SHADOW_ROOT_INIT + */ +export const DEFAULT_SHADOW_ROOT_INIT: Readonly = { + mode: 'open' +}; + /** * Node Types From 25f31753a863276a3c61d66e795c24a5842c9abb Mon Sep 17 00:00:00 2001 From: Anthony Johnston Date: Wed, 31 Oct 2018 10:01:55 +0000 Subject: [PATCH 3/4] updates per code review --- .../transpile/datacollection/component-decorator.ts | 12 ++++-------- .../datacollection/test/component-decorator.spec.ts | 5 ++--- src/core/host-snapshot.ts | 2 +- src/declarations/component.ts | 4 ++-- src/util/constants.ts | 7 ------- 5 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/compiler/transpile/datacollection/component-decorator.ts b/src/compiler/transpile/datacollection/component-decorator.ts index 7e885348dd9..32c5d2284c1 100644 --- a/src/compiler/transpile/datacollection/component-decorator.ts +++ b/src/compiler/transpile/datacollection/component-decorator.ts @@ -1,6 +1,6 @@ import * as d from '../../../declarations'; import { buildWarn } from '../../util'; -import { ENCAPSULATION, DEFAULT_SHADOW_ROOT_INIT } from '../../../util/constants'; +import { ENCAPSULATION } from '../../../util/constants'; import { getDeclarationParameters, isDecoratorNamed, serializeSymbol } from './utils'; import { getStylesMeta } from './styles-meta'; import ts from 'typescript'; @@ -46,18 +46,14 @@ It will be removed in future versions. Please use the "hostData()" method instea assetsDirsMeta: [], hostMeta: getHostMeta(diagnostics, componentOptions.host), dependencies: [], - jsdoc: serializeSymbol(checker, symbol) + jsdoc: serializeSymbol(checker, symbol) }; // shadow dom options if(componentOptions.shadow){ cmpMeta.encapsulationMeta = ENCAPSULATION.ShadowDom if(isShadowDomOptions(componentOptions.shadow)) { - cmpMeta.shadowRootInit = Object.assign({}, DEFAULT_SHADOW_ROOT_INIT, { - delegatesFocus: componentOptions.shadow.delegatesFocus - }); - }else { - cmpMeta.shadowRootInit = DEFAULT_SHADOW_ROOT_INIT; + cmpMeta.shadowRootOptions = componentOptions.shadow; } } else { cmpMeta.encapsulationMeta = @@ -118,5 +114,5 @@ function getHostMeta(diagnostics: d.Diagnostic[], hostData: d.HostMeta) { } function isShadowDomOptions(o: any): o is d.ShadowDomOptions { - return typeof(o) != typeof(true); + return o && typeof(o) === 'object'; } \ No newline at end of file diff --git a/src/compiler/transpile/datacollection/test/component-decorator.spec.ts b/src/compiler/transpile/datacollection/test/component-decorator.spec.ts index 06fb443e59c..9c3522b9985 100644 --- a/src/compiler/transpile/datacollection/test/component-decorator.spec.ts +++ b/src/compiler/transpile/datacollection/test/component-decorator.spec.ts @@ -1,4 +1,4 @@ -import { ENCAPSULATION, DEFAULT_SHADOW_ROOT_INIT } from '../../../../util/constants'; +import { ENCAPSULATION } from '../../../../util/constants'; import { getComponentDecoratorMeta } from '../component-decorator'; import { gatherMetadata } from './test-utils'; import * as path from 'path'; @@ -42,7 +42,6 @@ describe('component decorator', () => { hostMeta: {}, stylesMeta: {}, encapsulationMeta: ENCAPSULATION.ShadowDom, - shadowRootInit: DEFAULT_SHADOW_ROOT_INIT, jsdoc: { documentation: '', name: 'ActionSheet', @@ -66,7 +65,7 @@ describe('component decorator', () => { hostMeta: {}, stylesMeta: {}, encapsulationMeta: ENCAPSULATION.ShadowDom, - shadowRootInit: Object.assign({}, DEFAULT_SHADOW_ROOT_INIT, { delegatesFocus: true }), + shadowRootOptions: { delegatesFocus: true }, jsdoc: { documentation: '', name: 'ActionSheet', diff --git a/src/core/host-snapshot.ts b/src/core/host-snapshot.ts index 662bc011a05..a181f9edc95 100644 --- a/src/core/host-snapshot.ts +++ b/src/core/host-snapshot.ts @@ -55,7 +55,7 @@ export function initHostSnapshot(domApi: d.DomApi, cmpMeta: d.ComponentMeta, hos // this component is using shadow dom // and this browser supports shadow dom // add the read-only property "shadowRoot" to the host element - domApi.$attachShadow(hostElm, cmpMeta.shadowRootInit); + domApi.$attachShadow(hostElm, { mode: "open", ...cmpMeta.shadowRootOptions }); } } diff --git a/src/declarations/component.ts b/src/declarations/component.ts index 0046ba02763..3f4513d68f8 100644 --- a/src/declarations/component.ts +++ b/src/declarations/component.ts @@ -28,14 +28,14 @@ export interface ComponentMeta { listenersMeta?: ListenMeta[]; hostMeta?: HostMeta; encapsulationMeta?: number; - shadowRootInit?: Readonly; + shadowRootOptions?: Readonly; assetsDirsMeta?: AssetsMeta[]; componentConstructor?: ComponentConstructor; componentClass?: string; dependencies?: ComponentDependencies; jsdoc?: JsDoc; styleDocs?: StyleDoc[]; - hmrLoad?: () => void; + hmrLoad?: () => void; } diff --git a/src/util/constants.ts b/src/util/constants.ts index 1cbadb8e1f7..0ece246f412 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -52,13 +52,6 @@ export const enum ENCAPSULATION { ScopedCss = 2, } -/** - * DEFAULT_SHADOW_ROOT_INIT - */ -export const DEFAULT_SHADOW_ROOT_INIT: Readonly = { - mode: 'open' -}; - /** * Node Types From acfe35e1e0833b13405a8524c1f9891088753143 Mon Sep 17 00:00:00 2001 From: Anthony Johnston Date: Wed, 31 Oct 2018 10:16:24 +0000 Subject: [PATCH 4/4] correct quotes --- src/core/host-snapshot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/host-snapshot.ts b/src/core/host-snapshot.ts index a181f9edc95..aeff7ce43b3 100644 --- a/src/core/host-snapshot.ts +++ b/src/core/host-snapshot.ts @@ -55,7 +55,7 @@ export function initHostSnapshot(domApi: d.DomApi, cmpMeta: d.ComponentMeta, hos // this component is using shadow dom // and this browser supports shadow dom // add the read-only property "shadowRoot" to the host element - domApi.$attachShadow(hostElm, { mode: "open", ...cmpMeta.shadowRootOptions }); + domApi.$attachShadow(hostElm, { mode: 'open', ...cmpMeta.shadowRootOptions }); } }