Skip to content

Commit

Permalink
fix(material/core): drop sanity checks (#29688)
Browse files Browse the repository at this point in the history
Removes the sanity checks since they won't execute with standalone by default, they mostly aren't necessary now that we're loading structural styles automatically and they produce some concrete styles that are problematic for the new theming APIs.
  • Loading branch information
crisbeto authored Sep 5, 2024
1 parent 22b68e0 commit 54875a3
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 151 deletions.
22 changes: 0 additions & 22 deletions src/material/core/_core-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@
@use './tokens/m2/mat/full-pseudo-checkbox' as tokens-mat-full-pseudo-checkbox;
@use './tokens/m2/mat/minimal-pseudo-checkbox' as tokens-mat-minimal-pseudo-checkbox;

$_has-inserted-loaded-marker: false;

@mixin _theme-loaded-marker {
@if not $_has-inserted-loaded-marker {
$_has-inserted-loaded-marker: true !global;

// Marker that is used to determine whether the user has added a theme to their page.
// Needs to be generated at the root, because themes may be nested inside classes.
@at-root {
.mat-theme-loaded-marker {
display: none;
}
}
}
}

@mixin base($theme) {
@if inspection.get-theme-version($theme) == 1 {
@include _theme-from-tokens(inspection.get-theme-tokens($theme, base));
Expand All @@ -45,9 +29,6 @@ $_has-inserted-loaded-marker: false;
tokens-mat-app.get-unthemable-tokens());
}
}

// The marker is a concrete style no matter which Material version we're targeting.
@include _theme-loaded-marker;
}

@mixin color($theme) {
Expand Down Expand Up @@ -129,9 +110,6 @@ $_has-inserted-loaded-marker: false;
}
}
}

// The marker is a concrete style no matter which Material version we're targeting.
@include _theme-loaded-marker;
}

@mixin _theme-from-tokens($tokens, $options...) {
Expand Down
128 changes: 20 additions & 108 deletions src/material/core/common-behaviors/common-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,32 @@

import {HighContrastModeDetector} from '@angular/cdk/a11y';
import {BidiModule} from '@angular/cdk/bidi';
import {inject, Inject, InjectionToken, NgModule, Optional} from '@angular/core';
import {VERSION as CDK_VERSION} from '@angular/cdk';
import {DOCUMENT} from '@angular/common';
import {Platform, _isTestEnvironment} from '@angular/cdk/platform';
import {VERSION} from '../version';
import {inject, InjectionToken, NgModule} from '@angular/core';
import {_isTestEnvironment} from '@angular/cdk/platform';

/** @docs-private */
export function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {
return true;
}

/** Injection token that configures whether the Material sanity checks are enabled. */
/**
* Injection token that configures whether the Material sanity checks are enabled.
* @deprecated No longer used and will be removed.
* @breaking-change 21.0.0
*/
export const MATERIAL_SANITY_CHECKS = new InjectionToken<SanityChecks>('mat-sanity-checks', {
providedIn: 'root',
factory: MATERIAL_SANITY_CHECKS_FACTORY,
factory: () => true,
});

/**
* Possible sanity checks that can be enabled. If set to
* true/false, all checks will be enabled/disabled.
* @deprecated No longer used and will be removed.
* @breaking-change 21.0.0
*/
export type SanityChecks = boolean | GranularSanityChecks;

/** Object that can be used to configure the sanity checks granularly. */
/**
* Object that can be used to configure the sanity checks granularly.
* @deprecated No longer used and will be removed.
* @breaking-change 21.0.0
*/
export interface GranularSanityChecks {
doctype: boolean;
theme: boolean;
Expand All @@ -43,109 +45,19 @@ export interface GranularSanityChecks {
* components. This includes Bidi, etc.
*
* This module should be imported to each top-level component module (e.g., MatTabsModule).
* @deprecated No longer used and will be removed.
* @breaking-change 21.0.0
*/
@NgModule({
imports: [BidiModule],
exports: [BidiModule],
})
export class MatCommonModule {
/** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */
private _hasDoneGlobalChecks = false;
constructor(...args: any[]);

constructor(
highContrastModeDetector: HighContrastModeDetector,
@Optional() @Inject(MATERIAL_SANITY_CHECKS) private _sanityChecks: SanityChecks,
@Inject(DOCUMENT) private _document: Document,
) {
constructor() {
// While A11yModule also does this, we repeat it here to avoid importing A11yModule
// in MatCommonModule.
highContrastModeDetector._applyBodyHighContrastModeCssClasses();

if (!this._hasDoneGlobalChecks) {
this._hasDoneGlobalChecks = true;

if (typeof ngDevMode === 'undefined' || ngDevMode) {
// Inject in here so the reference to `Platform` can be removed in production mode.
const platform = inject(Platform, {optional: true});

if (this._checkIsEnabled('doctype')) {
_checkDoctypeIsDefined(this._document);
}

if (this._checkIsEnabled('theme')) {
_checkThemeIsPresent(this._document, !!platform?.isBrowser);
}

if (this._checkIsEnabled('version')) {
_checkCdkVersionMatch();
}
}
}
}

/** Gets whether a specific sanity check is enabled. */
private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {
if (_isTestEnvironment()) {
return false;
}

if (typeof this._sanityChecks === 'boolean') {
return this._sanityChecks;
}

return !!this._sanityChecks[name];
}
}

/** Checks that the page has a doctype. */
function _checkDoctypeIsDefined(doc: Document): void {
if (!doc.doctype) {
console.warn(
'Current document does not have a doctype. This may cause ' +
'some Angular Material components not to behave as expected.',
);
}
}

/** Checks that a theme has been included. */
function _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {
// We need to assert that the `body` is defined, because these checks run very early
// and the `body` won't be defined if the consumer put their scripts in the `head`.
if (!doc.body || !isBrowser) {
return;
}

const testElement = doc.createElement('div');
testElement.classList.add('mat-theme-loaded-marker');
doc.body.appendChild(testElement);

const computedStyle = getComputedStyle(testElement);

// In some situations the computed style of the test element can be null. For example in
// Firefox, the computed style is null if an application is running inside of a hidden iframe.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397
if (computedStyle && computedStyle.display !== 'none') {
console.warn(
'Could not find Angular Material core theme. Most Material ' +
'components may not work as expected. For more info refer ' +
'to the theming guide: https://material.angular.io/guide/theming',
);
}

testElement.remove();
}

/** Checks whether the Material version matches the CDK version. */
function _checkCdkVersionMatch(): void {
if (VERSION.full !== CDK_VERSION.full) {
console.warn(
'The Angular Material version (' +
VERSION.full +
') does not match ' +
'the Angular CDK version (' +
CDK_VERSION.full +
').\n' +
'Please ensure the versions of these two packages exactly match.',
);
inject(HighContrastModeDetector)._applyBodyHighContrastModeCssClasses();
}
}
8 changes: 2 additions & 6 deletions src/material/core/theming/tests/m3-theme.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,14 @@ describe('M3 theme', () => {
root.walkRules(rule => {
selectors.add(rule.selector);
});
expect(Array.from(selectors)).toEqual(['html', '.mat-theme-loaded-marker']);
expect(Array.from(selectors)).toEqual(['html']);
});

it('should only emit CSS variables', () => {
const root = parse(transpile(`html { @include mat.all-component-themes($theme); }`));
const nonVarProps: string[] = [];
root.walkDecls(decl => {
if (
!decl.prop.startsWith('--') &&
// Skip the theme loaded marker since it can't be a variable.
(decl.parent as Rule).selector !== '.mat-theme-loaded-marker'
) {
if (!decl.prop.startsWith('--')) {
nonVarProps.push(decl.prop);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,7 @@ describe('theming inspection api', () => {
div {
@include mat.all-component-themes($theme);
}`);
expect(css).toBe(
[
// The marker is always included.
`.mat-theme-loaded-marker {`,
` display: none;`,
`}`,
].join('\n'),
);
expect(css.trim()).toBe('');
});
});
});
13 changes: 6 additions & 7 deletions tools/public_api_guard/material/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { EventEmitter } from '@angular/core';
import { FocusableOption } from '@angular/cdk/a11y';
import { FocusOrigin } from '@angular/cdk/a11y';
import { FormGroupDirective } from '@angular/forms';
import { HighContrastModeDetector } from '@angular/cdk/a11y';
import * as i0 from '@angular/core';
import * as i1 from '@angular/cdk/bidi';
import { InjectionToken } from '@angular/core';
Expand Down Expand Up @@ -119,7 +118,7 @@ export class _ErrorStateTracker {
// @public
export function _getOptionScrollPosition(optionOffset: number, optionHeight: number, currentScrollPosition: number, panelHeight: number): number;

// @public
// @public @deprecated
export interface GranularSanityChecks {
// (undocumented)
doctype: boolean;
Expand Down Expand Up @@ -150,11 +149,11 @@ export const MAT_OPTION_PARENT_COMPONENT: InjectionToken<MatOptionParentComponen
// @public
export const MAT_RIPPLE_GLOBAL_OPTIONS: InjectionToken<RippleGlobalOptions>;

// @public
// @public @deprecated
export class MatCommonModule {
constructor(highContrastModeDetector: HighContrastModeDetector, _sanityChecks: SanityChecks, _document: Document);
constructor(...args: any[]);
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<MatCommonModule, [null, { optional: true; }, null]>;
static ɵfac: i0.ɵɵFactoryDeclaration<MatCommonModule, never>;
// (undocumented)
static ɵinj: i0.ɵɵInjectorDeclaration<MatCommonModule>;
// (undocumented)
Expand All @@ -175,7 +174,7 @@ export type MatDateFormats = {
};
};

// @public
// @public @deprecated
export const MATERIAL_SANITY_CHECKS: InjectionToken<SanityChecks>;

// @public
Expand Down Expand Up @@ -527,7 +526,7 @@ export interface RippleTarget {
rippleDisabled: boolean;
}

// @public
// @public @deprecated
export type SanityChecks = boolean | GranularSanityChecks;

// @public
Expand Down

0 comments on commit 54875a3

Please sign in to comment.