feat(devtools): create demo application that uses standalone APIs and standalone components/directives/pipes (#48533)

The existing DevTools demo app that is used for developing on DevTools is exclusively an NgModule application. This commit creates a copy of the old demo app but with no NgModules and only standalone APIs/Components/Directives/Pipes

PR Close #48533
This commit is contained in:
AleksanderBodurri
2022-12-19 02:52:24 -05:00
committed by Pawel Kozlowski
parent b1aed48993
commit dbadfea67f
32 changed files with 1051 additions and 1 deletions
@@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])
@@ -0,0 +1,90 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
load("@build_bazel_rules_nodejs//:index.bzl", "pkg_web")
load("//tools:defaults.bzl", "esbuild", "http_server")
load("//devtools/tools/esbuild:index.bzl", "LINKER_PROCESSED_FW_PACKAGES")
package(default_visibility = ["//visibility:public"])
sass_binary(
name = "demo_styles",
src = "styles.scss",
include_paths = ["external/npm/node_modules"],
sourcemap = False,
deps = ["//devtools:material_sass_deps"],
)
sass_binary(
name = "firefox_styles",
src = "styles/firefox_styles.scss",
)
sass_binary(
name = "chrome_styles",
src = "styles/chrome_styles.scss",
)
ng_module(
name = "demo",
srcs = ["main.ts"],
deps = [
"//devtools/projects/demo-standalone/src/app",
"//devtools/src:demo_application_environment",
"//devtools/src:demo_application_operations",
"//packages/common",
"//packages/common/http",
"//packages/core",
"//packages/core/src/util",
"//packages/platform-browser",
"@npm//@types",
"@npm//rxjs",
],
)
esbuild(
name = "bundle",
config = "//devtools/tools/esbuild:esbuild_config_esm",
entry_points = [":main.ts"],
platform = "browser",
splitting = True,
target = "es2016",
deps = LINKER_PROCESSED_FW_PACKAGES + [":demo"],
)
exports_files(["index.html"])
filegroup(
name = "dev_app_static_files",
srcs = [
":chrome_styles",
":demo_styles",
":firefox_styles",
":index.html",
"//packages/zone.js/bundles:zone.umd.js",
],
)
pkg_web(
name = "devapp",
srcs = [":dev_app_static_files"] + [
":bundle",
"@npm//:node_modules/tslib/tslib.js",
],
# Currently, ibazel doesn't allow passing in flags to bazel run.
# This means we are not able to use --config snapshot-build
# to access the current commit SHA.
# Since we still want to be able to use ibazel to speed up
# local development, we supply an empty string for the SHA substitution.
# This does not effect production builds.
substitutions = {"BUILD_SCM_COMMIT_SHA": ""},
)
http_server(
name = "devserver",
srcs = [":dev_app_static_files"],
additional_root_paths = ["angular/devtools/projects/demo-standalone/src/devapp"],
tags = ["manual"],
deps = [
":devapp",
],
)
@@ -0,0 +1,19 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
package(default_visibility = ["//visibility:public"])
ng_module(
name = "app",
srcs = [
"app.component.ts",
],
deps = [
"//devtools/projects/demo-standalone/src/app/demo-app",
"//devtools/projects/demo-standalone/src/app/devtools-app",
"//devtools/projects/ng-devtools",
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser/animations",
"//packages/router",
],
)
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component} from '@angular/core';
import {Router, RouterOutlet} from '@angular/router';
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`,
standalone: true,
imports: [RouterOutlet]
})
export class AppComponent {
constructor(public router: Router) {}
}
@@ -0,0 +1,41 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary", "sass_library")
package(default_visibility = ["//visibility:public"])
sass_library(
name = "todo_mvc",
srcs = [
"@npm//:node_modules/todomvc-app-css/index.css",
"@npm//:node_modules/todomvc-common/base.css",
],
)
sass_binary(
name = "demo_app_component_styles",
src = "demo-app.component.scss",
deps = [
":todo_mvc",
],
)
ng_module(
name = "demo-app",
srcs = [
"demo-app.component.ts",
"heavy.component.ts",
"zippy.component.ts",
],
angular_assets = [
"demo-app.component.html",
":demo_app_component_styles",
],
deps = [
"//devtools/projects/demo-standalone/src/app/demo-app/todo",
"//devtools/projects/ng-devtools-backend",
"//devtools/src:zone-unaware-iframe_message_bus",
"//packages/core",
"//packages/elements",
"//packages/router",
],
)
@@ -0,0 +1,4 @@
<router-outlet></router-outlet>
<app-zippy [title]="getTitle()">This is my content</app-zippy>
<app-heavy></app-heavy>
<div #elementReference>HTMLElement</div>
@@ -0,0 +1,2 @@
@use 'external/npm/node_modules/todomvc-app-css/index.css';
@use 'external/npm/node_modules/todomvc-common/base.css';
@@ -0,0 +1,65 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, EventEmitter, inject, Injector, Input, Output, ViewChild, ViewEncapsulation} from '@angular/core';
import {createCustomElement} from '@angular/elements';
import {RouterOutlet} from '@angular/router';
import {initializeMessageBus} from 'ng-devtools-backend';
import {ZoneUnawareIFrameMessageBus} from '../../../../../src/zone-unaware-iframe-message-bus';
import {HeavyComponent} from './heavy.component';
import {ZippyComponent} from './zippy.component';
@Component({
selector: 'app-demo-component',
templateUrl: './demo-app.component.html',
styleUrls: ['./demo-app.component.scss'],
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [HeavyComponent, RouterOutlet],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class DemoAppComponent {
@ViewChild(ZippyComponent) zippy: ZippyComponent;
@ViewChild('elementReference') elementRef: ElementRef;
@Input('input_one') inputOne = 'input one';
@Input() inputTwo = 'input two';
@Output() outputOne = new EventEmitter();
@Output('output_two') outputTwo = new EventEmitter();
constructor() {
const el = createCustomElement(ZippyComponent, {injector: inject(Injector)});
customElements.define('app-zippy', el as any);
}
getTitle(): '► Click to expand'|'▼ Click to collapse' {
if (!this.zippy || !this.zippy.visible) {
return '► Click to expand';
}
return '▼ Click to collapse';
}
}
export const ROUTES = [
{
path: '',
component: DemoAppComponent,
children: [
{
path: '',
loadChildren: () => import('./todo/todo-app.component').then((m) => m.ROUTES),
},
],
},
];
initializeMessageBus(new ZoneUnawareIFrameMessageBus(
'angular-devtools-backend', 'angular-devtools', () => window.parent));
@@ -0,0 +1,43 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Input} from '@angular/core';
const fib = (n: number) => {
if (n === 1 || n === 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
};
@Component({selector: 'app-heavy', template: `<h1>{{ calculate() }}</h1>`, standalone: true})
export class HeavyComponent {
@Input()
set foo(_: any) {
}
state = {
nested: {
props: {
foo: 1,
bar: 2,
},
[Symbol(3)]():
number {
return 1.618;
},
get foo():
number {
return 42;
},
},
};
calculate(): number {
return fib(15);
}
}
@@ -0,0 +1,20 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
package(default_visibility = ["//visibility:public"])
ng_module(
name = "todo",
srcs = [
"dialog.component.ts",
"todo-app.component.ts",
],
deps = [
"//devtools/projects/demo-standalone/src/app/demo-app/todo/about",
"//devtools/projects/demo-standalone/src/app/demo-app/todo/home",
"//packages/common",
"//packages/core",
"//packages/forms",
"//packages/router",
"@npm//@angular/material",
],
)
@@ -0,0 +1,12 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
package(default_visibility = ["//visibility:public"])
ng_module(
name = "about",
srcs = ["about.component.ts"],
deps = [
"//packages/core",
"//packages/router",
],
)
@@ -0,0 +1,24 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component} from '@angular/core';
import {RouterLink, RouterOutlet} from '@angular/router';
@Component({
selector: 'app-about',
standalone: true,
imports: [RouterOutlet, RouterLink],
template: `
About component
<a [routerLink]="">Home</a>
<a [routerLink]="">Home</a>
<a [routerLink]="">Home</a>
`
})
export class AboutComponent {
}
@@ -0,0 +1,48 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {CommonModule} from '@angular/common';
import {Component, Inject} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA, MatLegacyDialogModule as MatDialogModule, MatLegacyDialogRef as MatDialogRef} from '@angular/material/legacy-dialog';
import {MatLegacyFormFieldModule as MatFormFieldModule} from '@angular/material/legacy-form-field';
export interface DialogData {
animal: string;
name: string;
}
@Component({
selector: 'app-dialog',
standalone: true,
imports: [MatDialogModule, MatFormFieldModule, FormsModule, CommonModule],
template: `
<h1 mat-dialog-title>Hi {{ data.name }}</h1>
<div mat-dialog-content>
<p>What's your favorite animal?</p>
<mat-form-field>
<mat-label>Favorite Animal</mat-label>
<input matInput [(ngModel)]="data.animal" />
</mat-form-field>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">No Thanks</button>
<button mat-button [mat-dialog-close]="data.animal" cdkFocusInitial>Ok</button>
</div>
`,
})
export class DialogComponent {
constructor(
public dialogRef: MatDialogRef<DialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
@@ -0,0 +1,18 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
package(default_visibility = ["//visibility:public"])
ng_module(
name = "home",
srcs = [
"sample.pipe.ts",
"todo.component.ts",
"todos.component.ts",
"tooltip.directive.ts",
],
deps = [
"//packages/common",
"//packages/core",
"//packages/router",
],
)
@@ -0,0 +1,21 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OnDestroy, Pipe, PipeTransform} from '@angular/core';
@Pipe({name: 'sample', pure: false, standalone: true})
export class SamplePipe implements PipeTransform, OnDestroy {
transform(val: any): void {
return val;
}
ngOnDestroy(): void {
// tslint:disable-next-line:no-console
console.log('Destroying');
}
}
@@ -0,0 +1,68 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {CommonModule} from '@angular/common';
import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
import {TooltipDirective} from './tooltip.directive';
export interface Todo {
id: string;
completed: boolean;
label: string;
}
@Component({
selector: 'app-todo',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, TooltipDirective],
styles: [`
.destroy {
cursor: pointer;
display: unset !important;
}
`],
template: `
<li [class.completed]="todo.completed">
<div class="view" appTooltip>
<input class="toggle" type="checkbox" [checked]="todo.completed" (change)="toggle()" />
<label (dblclick)="enableEditMode()" [style.display]="editMode ? 'none' : 'block'">{{ todo.label }}</label>
<button class="destroy" (click)="delete.emit(todo)"></button>
</div>
<input
class="edit"
[value]="todo.label"
[style.display]="editMode ? 'block' : 'none'"
(keydown.enter)="completeEdit($any($event.target).value)"
/>
</li>
`
})
export class TodoComponent {
@Input() todo: Todo;
@Output() update = new EventEmitter();
@Output() delete = new EventEmitter();
editMode = false;
toggle(): void {
this.todo.completed = !this.todo.completed;
this.update.emit(this.todo);
}
completeEdit(label: string): void {
this.todo.label = label;
this.editMode = false;
this.update.emit(this.todo);
}
enableEditMode(): void {
this.editMode = true;
}
}
@@ -0,0 +1,165 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {NgForOf} from '@angular/common';
import {ChangeDetectorRef, Component, EventEmitter, OnDestroy, OnInit, Output, Pipe, PipeTransform} from '@angular/core';
import {RouterLink} from '@angular/router';
import {SamplePipe} from './sample.pipe';
import {Todo, TodoComponent} from './todo.component';
import {TooltipDirective} from './tooltip.directive';
export const enum TodoFilter {
All = 'all',
Completed = 'completed',
Active = 'active',
}
@Pipe({pure: false, name: 'todosFilter', standalone: true})
export class TodosFilter implements PipeTransform {
transform(todos: Todo[], filter: TodoFilter): Todo[] {
return (todos || []).filter((t) => {
if (filter === TodoFilter.All) {
return true;
}
if (filter === TodoFilter.Active && !t.completed) {
return true;
}
if (filter === TodoFilter.Completed && t.completed) {
return true;
}
return false;
});
}
}
const fib = (n: number) => {
if (n === 1 || n === 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
};
@Component({
selector: 'app-todos',
imports: [NgForOf, RouterLink, TodoComponent, SamplePipe, TodosFilter, TooltipDirective],
standalone: true,
template: `
<a [routerLink]="">Home</a>
<a [routerLink]="">Home</a>
<a [routerLink]="">Home</a>
<p>{{ 'Sample text processed by a pipe' | sample }}</p>
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<input (keydown.enter)="addTodo(input)" #input class="new-todo" placeholder="What needs to be done?" autofocus />
</header>
<section class="main">
<input id="toggle-all" class="toggle-all" type="checkbox" />
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<app-todo
appTooltip
*ngFor="let todo of todos | todosFilter: filterValue"
[todo]="todo"
(delete)="onDelete($event)"
(update)="onChange($event)"
></app-todo>
</ul>
</section>
<footer class="footer">
<span class="todo-count">
<strong>{{ itemsLeft }}</strong> item left
</span>
<button class="clear-completed" (click)="clearCompleted()">Clear completed</button>
</footer>
</section>
`
})
export class TodosComponent implements OnInit, OnDestroy {
todos: Todo[] = [
{
label: 'Buy milk',
completed: false,
id: '42',
},
{
label: 'Build something fun!',
completed: false,
id: '43',
},
];
@Output() update = new EventEmitter();
@Output() delete = new EventEmitter();
@Output() add = new EventEmitter();
private hashListener: EventListenerOrEventListenerObject;
constructor(private cdRef: ChangeDetectorRef) {}
ngOnInit(): void {
if (typeof window !== 'undefined') {
window.addEventListener('hashchange', (this.hashListener = () => this.cdRef.markForCheck()));
}
}
ngOnDestroy(): void {
fib(40);
if (typeof window !== 'undefined') {
window.removeEventListener('hashchange', this.hashListener);
}
}
get filterValue(): TodoFilter {
if (typeof window !== 'undefined') {
return (window.location.hash.replace(/^#\//, '') as TodoFilter) || TodoFilter.All;
}
return TodoFilter.All;
}
get itemsLeft(): number {
return (this.todos || []).filter((t) => !t.completed).length;
}
clearCompleted(): void {
(this.todos || []).filter((t) => t.completed).forEach((t) => this.delete.emit(t));
}
addTodo(input: HTMLInputElement): void {
const todo = {
completed: false,
label: input.value,
};
const result: Todo = {...todo, id: Math.random().toString()};
this.todos.push(result);
input.value = '';
}
onChange(todo: Todo): void {
if (!todo.id) {
return;
}
}
onDelete(todo: Todo): void {
if (!todo.id) {
return;
}
const idx = this.todos.findIndex((t) => t.id === todo.id);
if (idx < 0) {
return;
}
// tslint:disable-next-line:no-console
console.log('Deleting', idx);
this.todos.splice(idx, 1);
}
}
@@ -0,0 +1,35 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, HostListener} from '@angular/core';
@Directive({selector: '[appTooltip]', standalone: true})
export class TooltipDirective {
visible = false;
nested = {
child: {
grandchild: {
prop: 1,
},
},
};
constructor() {
// setInterval(() => this.nested.child.grandchild.prop++, 500);
}
@HostListener('click')
handleClick(): void {
this.visible = !this.visible;
if (this.visible) {
(this as any).extraProp = true;
} else {
delete (this as any).extraProp;
}
}
}
@@ -0,0 +1,98 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {CommonModule} from '@angular/common';
import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MatLegacyDialog as MatDialog, MatLegacyDialogModule as MatDialogModule} from '@angular/material/legacy-dialog';
import {MatLegacyFormFieldModule as MatFormFieldModule} from '@angular/material/legacy-form-field';
import {MatLegacyInputModule as MatInputModule} from '@angular/material/legacy-input';
import {RouterLink, RouterOutlet} from '@angular/router';
import {DialogComponent} from './dialog.component';
@Component({
selector: 'app-todo-demo',
standalone: true,
imports: [
RouterLink, RouterOutlet, MatDialogModule, MatFormFieldModule, MatInputModule, FormsModule,
CommonModule
],
styles: [`
nav {
padding-top: 20px;
padding-bottom: 10px;
a {
margin-right: 15px;
text-decoration: none;
}
}
.dialog-open-button {
border: 1px solid #ccc;
padding: 10px;
margin-right: 20px;
}
`],
template: `
<nav>
<a routerLink="/demo-app/todos/app">Todos</a>
<a routerLink="/demo-app/todos/about">About</a>
</nav>
<button class="dialog-open-button" (click)="openDialog()">Open dialog</button>
<router-outlet></router-outlet>
`
})
export class TodoAppComponent {
name: string;
animal: string;
constructor(public dialog: MatDialog) {}
openDialog(): void {
const dialogRef = this.dialog.open(DialogComponent, {
width: '250px',
data: {name: this.name, animal: this.animal},
});
dialogRef.afterClosed().subscribe((result) => {
// tslint:disable-next-line:no-console
console.log('The dialog was closed');
this.animal = result;
});
}
}
export const ROUTES = [
{
path: 'todos',
component: TodoAppComponent,
children: [
{
path: 'app',
loadComponent: () => import('./home/todos.component').then((m) => m.TodosComponent),
},
{
path: 'about',
loadComponent: () => import('./about/about.component').then((m) => m.AboutComponent),
},
{
path: '**',
redirectTo: 'app',
},
],
},
{
path: '**',
redirectTo: 'todos',
},
];
@@ -0,0 +1,47 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Input} from '@angular/core';
@Component({
selector: 'app-zippy',
standalone: true,
styles: [`
:host {
user-select: none;
}
header {
max-width: 120px;
border: 1px solid #ccc;
padding-left: 10px;
padding-right: 10px;
cursor: pointer;
}
div {
max-width: 120px;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
padding: 10px;
}
`],
template: `
<section>
<header (click)="visible = !visible">{{ title }}</header>
<div [hidden]="!visible">
<ng-content></ng-content>
</div>
</section>
`
})
export class ZippyComponent {
@Input() title: string;
visible = false;
}
@@ -0,0 +1,16 @@
load("//devtools/tools:ng_module.bzl", "ng_module")
package(default_visibility = ["//visibility:public"])
ng_module(
name = "devtools-app",
srcs = ["devtools-app.component.ts"],
deps = [
"//devtools/projects/ng-devtools",
"//devtools/projects/protocol",
"//devtools/src:iframe_message_bus",
"//packages/common",
"//packages/core",
"//packages/router",
],
)
@@ -0,0 +1,51 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, ElementRef, ViewChild} from '@angular/core';
import {DevToolsModule as NgDevToolsModule} from 'ng-devtools';
import {Events, MessageBus, PriorityAwareMessageBus} from 'protocol';
import {IFrameMessageBus} from '../../../../../src/iframe-message-bus';
@Component({
standalone: true,
imports: [NgDevToolsModule],
providers: [
{
provide: MessageBus,
useFactory(): MessageBus<Events> {
return new PriorityAwareMessageBus(new IFrameMessageBus(
'angular-devtools', 'angular-devtools-backend',
// tslint:disable-next-line: no-non-null-assertion
() => (document.querySelector('#sample-app') as HTMLIFrameElement).contentWindow!));
},
},
],
styles: [`
iframe {
height: 340px;
width: 100%;
border: 0;
}
.devtools-wrapper {
height: calc(100vh - 345px);
}
`],
template: `
<iframe #ref src="demo-app/todos/app" id="sample-app"></iframe>
<br />
<div class="devtools-wrapper">
<ng-devtools></ng-devtools>
</div>
`
})
export class DevToolsComponent {
messageBus: IFrameMessageBus|null = null;
@ViewChild('ref') iframe: ElementRef;
}
@@ -0,0 +1,13 @@
load("//devtools/tools:typescript.bzl", "ts_library")
package(default_visibility = ["//visibility:public"])
ts_library(
name = "environments",
srcs = [
"environment.ts",
],
deps = [
"//packages/platform-browser",
],
)
@@ -0,0 +1,12 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export const environment = {
production: false,
LATEST_SHA: 'BUILD_SCM_COMMIT_SHA', // Stamped at build time by bazel
};
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AngularDevtools</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="assets/icon16.png" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div>
<app-root></app-root>
</div>
<script src="./angular/packages/zone.js/bundles/zone.umd.js"></script>
<script type="module" src="./bundle/main.js"></script>
</body>
</html>
@@ -0,0 +1,44 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {bootstrapApplication} from '@angular/platform-browser';
import {provideAnimations} from '@angular/platform-browser/animations';
import {provideRouter} from '@angular/router';
import {ApplicationEnvironment, ApplicationOperations} from 'ng-devtools';
import {DemoApplicationEnvironment} from '../../../src/demo-application-environment';
import {DemoApplicationOperations} from '../../../src/demo-application-operations';
import {AppComponent} from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
provideAnimations(),
provideRouter([
{
path: '',
loadComponent: () =>
import('./app/devtools-app/devtools-app.component').then((m) => m.DevToolsComponent),
pathMatch: 'full',
},
{
path: 'demo-app',
loadChildren: () => import('./app/demo-app/demo-app.component').then((m) => m.ROUTES),
},
]),
{
provide: ApplicationOperations,
useClass: DemoApplicationOperations,
},
{
provide: ApplicationEnvironment,
useClass: DemoApplicationEnvironment,
},
]
});
@@ -0,0 +1,48 @@
@use 'sass:map';
@use 'external/npm/node_modules/@angular/material/index' as mat;
@include mat.all-legacy-component-typographies();
@include mat.legacy-core();
html,
body {
padding: 0;
margin: 0;
}
// Light theme
$light-primary: mat.define-palette(mat.$grey-palette, 700, 200);
$light-accent: mat.define-palette(mat.$blue-palette, 800);
$light-theme: mat.define-light-theme($light-primary, $light-accent);
// Dark theme
$dark-primary: mat.define-palette(mat.$blue-grey-palette, 50);
$dark-accent: mat.define-palette(mat.$blue-palette, 200);
$dark-theme: map.deep-merge(
mat.define-dark-theme($dark-primary, $dark-accent),
(
'color': (
'background': (
background: #202124,
card: #202124,
),
'foreground': (
text: #bcc5ce,
),
),
'background': (
background: #202124,
card: #202124,
),
'foreground': (
'text': #bcc5ce,
),
)
);
.light-theme {
@include mat.all-legacy-component-themes($light-theme);
}
.dark-theme {
@include mat.all-legacy-component-themes($dark-theme);
}
@@ -0,0 +1,2 @@
/** Specific style for Chrome browser */
@@ -0,0 +1,2 @@
/** Specific style for Firefox browser */
-1
View File
@@ -8,7 +8,6 @@
<link rel="icon" type="image/x-icon" href="assets/icon16.png" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<!-- <script src="https://unpkg.com/@webcomponents/webcomponentsjs@2.0.3/custom-elements-es5-adapter.js"></script> -->
<link rel="stylesheet" href="./styles.css">
</head>
<body>
+1
View File
@@ -39,6 +39,7 @@
"ts-circular-deps:approve": "yarn -s ng-dev ts-circular-deps approve --config ./packages/circular-deps-test.conf.js",
"check-tooling-setup": "yarn tsc --project .ng-dev/tsconfig.json && yarn tsc --project scripts/tsconfig.json",
"devtools:devserver": "ibazel run //devtools/src:devserver",
"devtools:devserver:demo-standalone": "ibazel run //devtools/projects/demo-standalone/src:devserver",
"devtools:build:chrome": "bazelisk build --config snapshot-build --//devtools/projects/shell-browser/src:flag_browser=chrome -- devtools/projects/shell-browser/src:prodapp",
"devtools:build:firefox": "bazelisk build --config snapshot-build --//devtools/projects/shell-browser/src:flag_browser=firefox -- devtools/projects/shell-browser/src:prodapp",
"devtools:test": "bazelisk test --config snapshot-build --//devtools/projects/shell-browser/src:flag_browser=chrome -- //devtools/..."