diff --git a/lib/block.dart b/lib/block.dart index fe40ce8ff..6257ae9b7 100644 --- a/lib/block.dart +++ b/lib/block.dart @@ -407,6 +407,10 @@ class ComponentWrapper { ComponentWrapper(this.directiveRef, this.controller, this.elementRoot, this.parser, $compiler, $http) { var directive = directiveRef.directive; var shadowRoot = elementRoot.createShadowRoot(); + shadowRoot.applyAuthorStyles = + directive.$shadowRootOptions.$applyAuthorStyles; + shadowRoot.resetStyleInheritance = + directive.$shadowRootOptions.$resetStyleInheritance; var styleData = ''; if (directive.$cssUrl != null) { diff --git a/lib/directive.dart b/lib/directive.dart index 23e38ba81..d4b065d58 100644 --- a/lib/directive.dart +++ b/lib/directive.dart @@ -16,6 +16,7 @@ class Directive { String $cssUrl; Map $map; String $visibility; + ShadowRootOptions $shadowRootOptions; bool isComponent = false; bool isStructural = false; @@ -46,15 +47,10 @@ class Directive { $template = reflectStaticField(type, '\$template'); $templateUrl = reflectStaticField(type, '\$templateUrl'); $cssUrl = reflectStaticField(type, '\$cssUrl'); - $priority = reflectStaticField(type, '\$priority'); - $visibility = reflectStaticField(type, '\$visibility'); - if ($visibility == null) { - $visibility = DirectiveVisibility.LOCAL; - } + $priority = _defaultIfNull(reflectStaticField(type, '\$priority'), 0); + $visibility = _defaultIfNull( + reflectStaticField(type, '\$visibility'), DirectiveVisibility.LOCAL); $map = reflectStaticField(type, '\$map'); - if ($priority == null) { - $priority = 0; - } isStructural = $transclude != null; var $selector = reflectStaticField(type, r'$selector'); if ($selector != null) { @@ -63,9 +59,17 @@ class Directive { if (isComponent && $map == null) { $map = new Map(); } + if (isComponent) { + $shadowRootOptions = _defaultIfNull( + reflectStaticField(type, '\$shadowRootOptions'), + new ShadowRootOptions()); + } } } +dynamic _defaultIfNull(dynamic value, dynamic defaultValue) => + value == null ? defaultValue : value; + class DirectiveRef { dom.Node element; String selector; @@ -119,6 +123,17 @@ abstract class DirectiveVisibility { static const String DIRECT_CHILDREN = 'direct_children'; } +/** + * See: + * http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/#toc-style-inheriting + */ +class ShadowRootOptions { + bool $applyAuthorStyles = false; + bool $resetStyleInheritance = false; + ShadowRootOptions([this.$applyAuthorStyles = false, + this.$resetStyleInheritance = false]); +} + class Controller { } diff --git a/test/directive_spec.dart b/test/directive_spec.dart index 49904dd86..69f241082 100644 --- a/test/directive_spec.dart +++ b/test/directive_spec.dart @@ -12,6 +12,13 @@ class ExplicitNullTranscludeDirective { static var $transclude = null; } +class WithDefaultShadowRootOptionsComponent { +} + +class WithCustomShadowRootOptionsComponent { + static var $shadowRootOptions = new ShadowRootOptions(true, true); +} + main() { describe('directive factory', () { it('should guess the directive name correctly', () { @@ -38,5 +45,17 @@ main() { Directive factory = new Directive(ExplicitNullTranscludeDirective); expect(factory.$transclude).toEqual(null); }); + + it('should default \$shadowRootOptions to false/false', () { + Directive factory = new Directive(WithDefaultShadowRootOptionsComponent); + expect(factory.$shadowRootOptions.$applyAuthorStyles, isFalse); + expect(factory.$shadowRootOptions.$resetStyleInheritance, isFalse); + }); + + it('should override \$shadowRootOptions with values provided by component type', () { + Directive factory = new Directive(WithCustomShadowRootOptionsComponent); + expect(factory.$shadowRootOptions.$applyAuthorStyles, isTrue); + expect(factory.$shadowRootOptions.$resetStyleInheritance, isTrue); + }); }); }