diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel
index bfc097a3e50..942e155b4f3 100644
--- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/BUILD.bazel
@@ -1,7 +1,7 @@
-load("//devtools/tools:ng_module.bzl", "ng_module")
load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
-load("//devtools/tools:typescript.bzl", "ts_library", "ts_test_library")
load("//devtools/tools:defaults.bzl", "karma_web_test_suite")
+load("//devtools/tools:ng_module.bzl", "ng_module")
+load("//devtools/tools:typescript.bzl", "ts_library", "ts_test_library")
package(default_visibility = ["//:__subpackages__"])
@@ -20,10 +20,10 @@ ng_module(
"injector-tree.component.html",
],
deps = [
- ":injector_providers",
":injector_tree_fns",
"//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:injector_tree_visualizer",
"//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path",
+ "//devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers",
"//devtools/projects/ng-devtools/src/lib/vendor/angular-split",
"//devtools/projects/protocol",
"//packages/common",
@@ -35,21 +35,6 @@ ng_module(
],
)
-ng_module(
- name = "injector_providers",
- srcs = [
- "injector-providers.component.ts",
- ],
- deps = [
- "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path",
- "//devtools/projects/protocol",
- "//packages/animations",
- "//packages/common",
- "//packages/core",
- "@npm//@angular/material",
- ],
-)
-
karma_web_test_suite(
name = "test",
deps = [
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts
deleted file mode 100644
index 3653fc885ca..00000000000
--- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers.component.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-/**
- * @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.dev/license
- */
-
-import {Component, computed, inject, input, signal} from '@angular/core';
-import {MatOption} from '@angular/material/core';
-import {MatFormField, MatLabel} from '@angular/material/form-field';
-import {MatIcon} from '@angular/material/icon';
-import {MatInput} from '@angular/material/input';
-import {MatSelect} from '@angular/material/select';
-import {MatTableModule} from '@angular/material/table';
-import {MatTooltip} from '@angular/material/tooltip';
-import {Events, MessageBus, SerializedInjector, SerializedProviderRecord} from 'protocol';
-
-@Component({
- selector: 'ng-injector-providers',
- template: `
-
Providers for {{ injector()?.name }}
- @if (injector()) {
-
-
- Search by token
-
- close
-
-
- Search by type
-
- None
- @for (type of providerTypes; track type) {
- {{ $any(providerTypeToLabel)[type] }}
- }
-
-
- @if (visibleProviders().length > 0) {
-
-
- Token |
- {{ provider.token }} |
-
-
- Type |
-
- @if (provider.type === 'multi') { multi (x{{ provider.index.length }}) } @else {
- {{ $any(providerTypeToLabel)[provider.type] }}
- }
- |
-
-
- Is View Provider |
-
- {{ provider.isViewProvider ? 'check_circle' : 'cancel' }}
- |
-
-
- |
-
- send
- |
-
-
-
-
- }
-
- }
- `,
- styles: [
- `
- .select {
- cursor: pointer;
- }
-
- :host {
- display: block;
- padding: 16px;
- }
-
- .form-field-spacer {
- margin: 0 4px 0 4px;
- }
-
- table {
- width: 100%;
- }
-
- .column-title {
- margin: 0;
- }
-
- tr.example-detail-row {
- height: 0;
- }
-
- .example-element-row td {
- border-bottom-width: 0;
- cursor: pointer;
- }
-
- .example-element-detail {
- overflow: hidden;
- display: flex;
- }
-
- .example-element-diagram {
- min-width: 80px;
- border: 2px solid black;
- padding: 8px;
- font-weight: lighter;
- margin: 8px 0;
- height: 104px;
- }
-
- .example-element-symbol {
- font-weight: bold;
- font-size: 40px;
- line-height: normal;
- }
-
- .example-element-description {
- padding: 16px;
- }
-
- .example-element-description-attribution {
- opacity: 0.5;
- }
-
- :host-context(.dark-theme) {
- .providers-title {
- color: #ffffff;
- }
- }
- `,
- ],
- imports: [
- MatTableModule,
- MatIcon,
- MatTooltip,
- MatInput,
- MatSelect,
- MatFormField,
- MatLabel,
- MatOption,
- ],
-})
-export class InjectorProvidersComponent {
- readonly injector = input.required();
- readonly providers = input([]);
-
- readonly searchToken = signal('');
- readonly searchType = signal('');
- readonly visibleProviders = computed(() => {
- const searchToken = this.searchToken().toLowerCase();
- const searchType = this.searchType();
-
- const predicates: ((provider: SerializedProviderRecord) => boolean)[] = [];
- searchToken &&
- predicates.push((provider) => provider.token.toLowerCase().includes(searchToken));
- searchType && predicates.push((provider) => provider.type === searchType);
-
- return this.providers().filter((provider) =>
- predicates.every((predicate) => predicate(provider)),
- );
- });
-
- providerTypeToLabel = {
- type: 'Type',
- existing: 'useExisting',
- factory: 'useFactory',
- class: 'useClass',
- value: 'useValue',
- };
-
- providerTypes = Object.keys(this.providerTypeToLabel);
-
- messageBus = inject>(MessageBus);
-
- select(row: SerializedProviderRecord) {
- const {id, type, name} = this.injector();
- this.messageBus.emit('logProvider', [{id, type, name}, row]);
- }
-
- get displayedColumns(): string[] {
- if (this.injector()?.type === 'element') {
- return ['token', 'type', 'isViewProvider', 'log'];
- }
- return ['token', 'type', 'log'];
- }
-}
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel
new file mode 100644
index 00000000000..31cd6c2b28e
--- /dev/null
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/BUILD.bazel
@@ -0,0 +1,32 @@
+load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")
+load("//devtools/tools:ng_module.bzl", "ng_module")
+
+package(default_visibility = ["//visibility:public"])
+
+sass_binary(
+ name = "injector_providers_component_styles",
+ src = "injector-providers.component.scss",
+ include_paths = [
+ "external/npm/node_modules",
+ ],
+ deps = ["//devtools:material_sass_deps"],
+)
+
+ng_module(
+ name = "injector-providers",
+ srcs = [
+ "injector-providers.component.ts",
+ ],
+ angular_assets = [
+ "injector-providers.component.html",
+ ":injector_providers_component_styles",
+ ],
+ deps = [
+ "//devtools/projects/ng-devtools/src/lib/devtools-tabs/dependency-injection:resolution_path",
+ "//devtools/projects/protocol",
+ "//packages/animations",
+ "//packages/common",
+ "//packages/core",
+ "@npm//@angular/material",
+ ],
+)
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html
new file mode 100644
index 00000000000..aa022c8ea8c
--- /dev/null
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.html
@@ -0,0 +1,65 @@
+Providers for {{ injector()?.name }}
+@if (injector()) {
+
+
+
+ Search by token
+
+ close
+
+
+ Search by type
+
+ None
+ @for (type of providerTypes; track type) {
+ {{ $any(providerTypeToLabel)[type] }}
+ }
+
+
+
+ @if (visibleProviders().length > 0) {
+
+
+ Token |
+ {{ provider.token }} |
+
+
+ Type |
+
+ @if (provider.type === 'multi') {
+ multi (x{{ provider.index.length }})
+ } @else {
+ {{ $any(providerTypeToLabel)[provider.type] }}
+ }
+ |
+
+
+ Is View Provider |
+
+ {{ provider.isViewProvider ? 'check_circle' : 'cancel' }}
+ |
+
+
+ |
+
+ send
+ |
+
+
+
+
+ }
+
+}
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss
new file mode 100644
index 00000000000..a5867686b19
--- /dev/null
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.scss
@@ -0,0 +1,89 @@
+@use '@angular/material' as mat;
+
+h2 {
+ font-size: 0.875rem;
+}
+
+.select {
+ cursor: pointer;
+}
+
+:host {
+ display: block;
+ padding: 16px;
+}
+
+.filter {
+ display: flex;
+ gap: 0.5rem;
+
+ mat-form-field {
+ @include mat.form-field-density(-5);
+ @include mat.form-field-overrides(
+ (
+ container-text-size: 0.8rem,
+ outlined-label-text-size: 0.8rem,
+ )
+ );
+
+ &:first-child {
+ flex: 1;
+ }
+ }
+}
+
+table {
+ width: 100%;
+ --mat-table-row-item-label-text-size: 0.8rem;
+ --mat-table-header-container-height: 42px;
+ --mat-table-row-item-container-height: 42px;
+}
+
+.column-title {
+ margin: 0;
+ font-size: 0.8rem;
+ font-weight: bold;
+}
+
+tr.example-detail-row {
+ height: 0;
+}
+
+.example-element-row td {
+ border-bottom-width: 0;
+ cursor: pointer;
+}
+
+.example-element-detail {
+ overflow: hidden;
+ display: flex;
+}
+
+.example-element-diagram {
+ min-width: 80px;
+ border: 2px solid black;
+ padding: 8px;
+ font-weight: lighter;
+ margin: 8px 0;
+ height: 104px;
+}
+
+.example-element-symbol {
+ font-weight: bold;
+ font-size: 40px;
+ line-height: normal;
+}
+
+.example-element-description {
+ padding: 16px;
+}
+
+.example-element-description-attribution {
+ opacity: 0.5;
+}
+
+:host-context(.dark-theme) {
+ .providers-title {
+ color: #ffffff;
+ }
+}
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts
new file mode 100644
index 00000000000..1299a2c4ad5
--- /dev/null
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-providers/injector-providers.component.ts
@@ -0,0 +1,77 @@
+/**
+ * @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.dev/license
+ */
+
+import {Component, computed, inject, input, signal} from '@angular/core';
+import {MatOption} from '@angular/material/core';
+import {MatFormField, MatLabel} from '@angular/material/form-field';
+import {MatIcon} from '@angular/material/icon';
+import {MatInput} from '@angular/material/input';
+import {MatSelect} from '@angular/material/select';
+import {MatTableModule} from '@angular/material/table';
+import {MatTooltip} from '@angular/material/tooltip';
+import {Events, MessageBus, SerializedInjector, SerializedProviderRecord} from 'protocol';
+
+@Component({
+ selector: 'ng-injector-providers',
+ templateUrl: './injector-providers.component.html',
+ styleUrl: './injector-providers.component.scss',
+ imports: [
+ MatTableModule,
+ MatIcon,
+ MatTooltip,
+ MatInput,
+ MatSelect,
+ MatFormField,
+ MatLabel,
+ MatOption,
+ ],
+})
+export class InjectorProvidersComponent {
+ readonly injector = input.required();
+ readonly providers = input([]);
+
+ readonly searchToken = signal('');
+ readonly searchType = signal('');
+ readonly visibleProviders = computed(() => {
+ const searchToken = this.searchToken().toLowerCase();
+ const searchType = this.searchType();
+
+ const predicates: ((provider: SerializedProviderRecord) => boolean)[] = [];
+ searchToken &&
+ predicates.push((provider) => provider.token.toLowerCase().includes(searchToken));
+ searchType && predicates.push((provider) => provider.type === searchType);
+
+ return this.providers().filter((provider) =>
+ predicates.every((predicate) => predicate(provider)),
+ );
+ });
+
+ providerTypeToLabel = {
+ type: 'Type',
+ existing: 'useExisting',
+ factory: 'useFactory',
+ class: 'useClass',
+ value: 'useValue',
+ };
+
+ providerTypes = Object.keys(this.providerTypeToLabel);
+
+ messageBus = inject>(MessageBus);
+
+ select(row: SerializedProviderRecord) {
+ const {id, type, name} = this.injector();
+ this.messageBus.emit('logProvider', [{id, type, name}, row]);
+ }
+
+ get displayedColumns(): string[] {
+ if (this.injector()?.type === 'element') {
+ return ['token', 'type', 'isViewProvider', 'log'];
+ }
+ return ['token', 'type', 'log'];
+ }
+}
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html
index 45cbbaacb83..a044dc3676b 100644
--- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/injector-tree/injector-tree.component.html
@@ -11,10 +11,14 @@
[disabled]="true"
>
-
- Hide injectors with no providers
-
- Hide framework injectors
+
+
+ Hide injectors with no providers
+
+
+ Hide framework injectors
+
+
@@ -23,7 +27,7 @@