mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
feat(devtools): improve value highlighting in object previews
Introduce a more fine-grained value preview highlighting based on the property type in the `ng-object-tree-explorer`.
This commit is contained in:
parent
f8045272b5
commit
1cb2e6bf5b
11 changed files with 118 additions and 7 deletions
|
|
@ -159,7 +159,8 @@ export class PropActionsMenuComponent {
|
|||
}
|
||||
|
||||
private getSignalNode(node: FlatNode): DevtoolsSignalGraphNode | null {
|
||||
if (node.prop.descriptor.containerType?.includes('Signal')) {
|
||||
const containerType = node.prop.descriptor.containerType;
|
||||
if (containerType === 'WritableSignal' || containerType === 'ReadonlySignal') {
|
||||
return this.signalGraph.graph()?.nodes.find((sn) => sn.label === node.prop.name) ?? null;
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
load("//devtools/tools:defaults.bzl", "ng_project", "sass_binary")
|
||||
|
||||
package(default_visibility = ["//devtools:__subpackages__"])
|
||||
|
||||
sass_binary(
|
||||
name = "styles",
|
||||
src = "prop-value-highlighter.scss",
|
||||
)
|
||||
|
||||
ng_project(
|
||||
name = "prop-value-highlighter",
|
||||
srcs = [
|
||||
"prop-value-highlighter.directive.ts",
|
||||
],
|
||||
deps = [
|
||||
"//:node_modules/@angular/core",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer:types",
|
||||
"//devtools/projects/protocol",
|
||||
],
|
||||
)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @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 {computed, Directive, input} from '@angular/core';
|
||||
import {Property} from '../object-tree-types';
|
||||
import {PropType} from '../../../../../../protocol';
|
||||
|
||||
/** Should be used in conjunction with prop-value-highlighter.scss */
|
||||
@Directive({
|
||||
selector: '[ngPropValueHighlighter]',
|
||||
host: {
|
||||
'[class]': 'typeClass()',
|
||||
},
|
||||
})
|
||||
export class PropValueHighlighterDirective {
|
||||
protected readonly ngPropValueHighlighter = input.required<Property>();
|
||||
|
||||
protected readonly typeClass = computed<string>(() => {
|
||||
const prop = this.ngPropValueHighlighter();
|
||||
|
||||
// Containers and class getters can have types.
|
||||
// Since their preview differs, we don't want to
|
||||
// use the specific value type highlighting.
|
||||
if (prop.descriptor.containerType !== null || prop.descriptor.preview === '(...)') {
|
||||
return 'type-default';
|
||||
}
|
||||
|
||||
switch (prop.descriptor.type) {
|
||||
case PropType.Number:
|
||||
case PropType.Boolean:
|
||||
return 'type-scalar';
|
||||
case PropType.String:
|
||||
return 'type-string';
|
||||
case PropType.Null:
|
||||
case PropType.Undefined:
|
||||
return 'type-nullish';
|
||||
case PropType.BigInt:
|
||||
case PropType.Date:
|
||||
case PropType.Set:
|
||||
case PropType.Map:
|
||||
case PropType.Symbol:
|
||||
case PropType.HTMLNode:
|
||||
return 'type-object-based';
|
||||
default:
|
||||
return 'type-default';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
.type-scalar {
|
||||
color: var(--color-prop-value-scalar);
|
||||
}
|
||||
|
||||
.type-string {
|
||||
color: var(--color-prop-value-string);
|
||||
}
|
||||
|
||||
.type-nullish {
|
||||
color: var(--color-prop-value-nullish);
|
||||
}
|
||||
|
||||
.type-object-based {
|
||||
color: var(--color-prop-value-object-based);
|
||||
}
|
||||
|
|
@ -18,10 +18,12 @@ ng_project(
|
|||
angular_assets = [
|
||||
"property-editor.component.html",
|
||||
":property-editor_styles",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer/prop-value-highlighter:styles",
|
||||
],
|
||||
deps = [
|
||||
"//:node_modules/@angular/core",
|
||||
"//:node_modules/@angular/forms",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer:types",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer/prop-value-highlighter",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
@switch (currentPropertyState()) {
|
||||
@case (readState) {
|
||||
<span class="editable">{{ property().descriptor.preview }}</span>
|
||||
<span class="editable" [ngPropValueHighlighter]="property()">{{
|
||||
property().descriptor.preview
|
||||
}}</span>
|
||||
}
|
||||
@case (writeState) {
|
||||
<div class="value-input">
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {Property} from '../object-tree-types';
|
||||
import {PropValueHighlighterDirective} from '../prop-value-highlighter/prop-value-highlighter.directive';
|
||||
|
||||
type EditorType = string | number | boolean;
|
||||
type EditorResult = EditorType | Array<EditorType>;
|
||||
|
|
@ -39,8 +40,11 @@ const parseValue = (value: EditorResult): EditorResult => {
|
|||
@Component({
|
||||
templateUrl: './property-editor.component.html',
|
||||
selector: 'ng-property-editor',
|
||||
styleUrls: ['./property-editor.component.scss'],
|
||||
imports: [FormsModule],
|
||||
styleUrls: [
|
||||
'./property-editor.component.scss',
|
||||
'../prop-value-highlighter/prop-value-highlighter.scss',
|
||||
],
|
||||
imports: [FormsModule, PropValueHighlighterDirective],
|
||||
host: {
|
||||
'(click)': 'onClick()',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,10 +18,12 @@ ng_project(
|
|||
angular_assets = [
|
||||
"property-preview.component.html",
|
||||
":property-preview_styles",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer/prop-value-highlighter:styles",
|
||||
],
|
||||
deps = [
|
||||
"//:node_modules/@angular/core",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer:types",
|
||||
"//devtools/projects/ng-devtools/src/lib/shared/object-tree-explorer/prop-value-highlighter",
|
||||
"//devtools/projects/protocol",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<span
|
||||
class="value"
|
||||
[class.function]="isClickableProp()"
|
||||
[ngPropValueHighlighter]="node().prop"
|
||||
(click)="isClickableProp() && inspect.emit()"
|
||||
>{{ node().prop.descriptor.preview }}</span
|
||||
>
|
||||
|
|
|
|||
|
|
@ -9,11 +9,16 @@
|
|||
import {Component, computed, input, output} from '@angular/core';
|
||||
import {PropType} from '../../../../../../protocol';
|
||||
import {FlatNode} from '../object-tree-types';
|
||||
import {PropValueHighlighterDirective} from '../prop-value-highlighter/prop-value-highlighter.directive';
|
||||
|
||||
@Component({
|
||||
selector: 'ng-property-preview',
|
||||
templateUrl: './property-preview.component.html',
|
||||
styleUrls: ['./property-preview.component.scss'],
|
||||
styleUrls: [
|
||||
'./property-preview.component.scss',
|
||||
'../prop-value-highlighter/prop-value-highlighter.scss',
|
||||
],
|
||||
imports: [PropValueHighlighterDirective],
|
||||
})
|
||||
export class PropertyPreviewComponent {
|
||||
readonly node = input.required<FlatNode>();
|
||||
|
|
|
|||
|
|
@ -102,7 +102,10 @@ $_colors: (
|
|||
--color-tree-node-highlighted: #cddffd;
|
||||
--color-tree-node-matched: #f3ce49;
|
||||
|
||||
--color-property-list-name: #71a2f7;
|
||||
--color-prop-value-scalar: #0842a0;
|
||||
--color-prop-value-string: #db362e;
|
||||
--color-prop-value-nullish: #aaaaaa;
|
||||
--color-prop-value-object-based: #747474;
|
||||
}
|
||||
|
||||
@mixin _dark-colors {
|
||||
|
|
@ -148,7 +151,10 @@ $_colors: (
|
|||
--color-tree-node-highlighted: #00416c;
|
||||
--color-tree-node-matched: #906921;
|
||||
|
||||
--color-property-list-name: #0c3a96;
|
||||
--color-prop-value-scalar: #9980ff;
|
||||
--color-prop-value-string: #5cd5fb;
|
||||
--color-prop-value-nullish: #6f6f6f;
|
||||
--color-prop-value-object-based: #ababab;
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
|
|
|||
Loading…
Reference in a new issue