Skip to content

Commit

Permalink
feat(devexp): highlight components by group
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieu-crouzet committed Jan 2, 2025
1 parent f4e354c commit 5e2bf4a
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 0 deletions.
41 changes: 41 additions & 0 deletions packages/@o3r/components/src/devkit/components-devkit.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import type {
import type {
PlaceholderMode,
} from '../stores';
import {
GroupInfo,
} from './highlight/models';
import {
OtterLikeComponentInfo,
} from './inspector';
Expand All @@ -32,6 +35,40 @@ export interface ToggleInspectorMessage extends OtterMessageContent<'toggleInspe
isRunning: boolean;
}

/**
* Message to toggle the highlight
*/
export interface ToggleHighlightMessage extends OtterMessageContent<'toggleHighlight'> {
/** Is the highlight displayed */
isRunning: boolean;
}

/**
* Message the change the configuration of the `HighlightService`
*/
export interface ChangeHighlightConfiguration extends OtterMessageContent<'changeHighlightConfiguration'> {
/**
* Minimum width of HTMLElement to be considered
*/
elementMinWidth?: number;
/**
* Minimum height of HTMLElement to be considered
*/
elementMinHeight?: number;
/**
* Throttle interval
*/
throttleInterval?: number;
/**
* Group information to detect elements
*/
groupsInfo?: Record<string, GroupInfo>;
/**
* Maximum number of ancestors
*/
maxDepth?: number;
}

/**
* Message to toggle the placeholder mode
*/
Expand All @@ -51,6 +88,8 @@ type ComponentsMessageContents =
| IsComponentSelectionAvailableMessage
| SelectedComponentInfoMessage
| ToggleInspectorMessage
| ToggleHighlightMessage
| ChangeHighlightConfiguration
| PlaceholderModeMessage;

/** List of possible DataTypes for Components messages */
Expand All @@ -74,5 +113,7 @@ export const isComponentsMessage = (message: any): message is AvailableComponent
|| message.dataType === 'isComponentSelectionAvailable'
|| message.dataType === 'placeholderMode'
|| message.dataType === 'toggleInspector'
|| message.dataType === 'toggleHighlight'
|| message.dataType === 'changeHighlightConfiguration'
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ import {
OTTER_COMPONENTS_DEVTOOLS_DEFAULT_OPTIONS,
OTTER_COMPONENTS_DEVTOOLS_OPTIONS,
} from './components-devtools.token';
import {
HighlightService,
} from './highlight/highlight.service';
import {
OtterInspectorService,
OtterLikeComponentInfo,
Expand All @@ -51,6 +54,7 @@ import {
export class ComponentsDevtoolsMessageService implements DevtoolsServiceInterface {
private readonly options: ComponentsDevtoolsServiceOptions;
private readonly inspectorService: OtterInspectorService;
private readonly highlightService: HighlightService;
private readonly sendMessage = sendOtterMessage<AvailableComponentsMessageContents>;
private readonly destroyRef = inject(DestroyRef);

Expand All @@ -65,6 +69,8 @@ export class ComponentsDevtoolsMessageService implements DevtoolsServiceInterfac
};

this.inspectorService = new OtterInspectorService();
this.highlightService = new HighlightService();

Check warning on line 72 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L72

Added line #L72 was not covered by tests

if (this.options.isActivatedOnBootstrap) {
this.activate();
}
Expand Down Expand Up @@ -130,6 +136,36 @@ export class ComponentsDevtoolsMessageService implements DevtoolsServiceInterfac
this.inspectorService.toggleInspector(message.isRunning);
break;
}
case 'toggleHighlight': {
if (message.isRunning) {
this.highlightService.start();

Check warning on line 141 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L141

Added line #L141 was not covered by tests
} else {
this.highlightService.stop();

Check warning on line 143 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L143

Added line #L143 was not covered by tests
}
break;

Check warning on line 145 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L145

Added line #L145 was not covered by tests
}
case 'changeHighlightConfiguration': {
if (message.elementMinWidth) {
this.highlightService.elementMinWidth = message.elementMinWidth;

Check warning on line 149 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L149

Added line #L149 was not covered by tests
}
if (message.elementMinHeight) {
this.highlightService.elementMinHeight = message.elementMinHeight;

Check warning on line 152 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L152

Added line #L152 was not covered by tests
}
if (message.throttleInterval) {
this.highlightService.throttleInterval = message.throttleInterval;

Check warning on line 155 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L155

Added line #L155 was not covered by tests
}
if (message.groupsInfo) {
this.highlightService.groupsInfo = message.groupsInfo;

Check warning on line 158 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L158

Added line #L158 was not covered by tests
}
if (message.maxDepth) {
this.highlightService.maxDepth = message.maxDepth;

Check warning on line 161 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L161

Added line #L161 was not covered by tests
}
if (this.highlightService.isRunning()) {
// Re-start to recompute the highlight with the new configuration
this.highlightService.start();

Check warning on line 165 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L165

Added line #L165 was not covered by tests
}
break;

Check warning on line 167 in packages/@o3r/components/src/devkit/components-devtools.message.service.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/components-devtools.message.service.ts#L167

Added line #L167 was not covered by tests
}
case 'placeholderMode': {
this.store.dispatch(togglePlaceholderModeTemplate({ mode: message.mode }));
break;
Expand Down
32 changes: 32 additions & 0 deletions packages/@o3r/components/src/devkit/highlight/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Class applied on the wrapper of highlight elements
*/
export const HIGHLIGHT_WRAPPER_CLASS = 'highlight-wrapper';

/**
* Class applied on the overlay elements
*/
export const HIGHLIGHT_OVERLAY_CLASS = 'highlight-overlay';

/**
* Class applied on the chip elements
*/
export const HIGHLIGHT_CHIP_CLASS = 'highlight-chip';

/**
* Default value for maximum number of ancestors
*/
export const DEFAULT_MAX_DEPTH = 10;

/**
* Default value for element min height
*/
export const DEFAULT_ELEMENT_MIN_HEIGHT = 30;
/**
* Default value for element min width
*/
export const DEFAULT_ELEMENT_MIN_WIDTH = 60;
/**
* Default value for throttle interval
*/
export const DEFAULT_THROTTLE_INTERVAL = 500;
77 changes: 77 additions & 0 deletions packages/@o3r/components/src/devkit/highlight/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {
HIGHLIGHT_WRAPPER_CLASS,
} from './constants';
import {
ElementWithGroupInfo,
} from './models';

/**
* Retrieve the identifier of the element
* @param element
*/
export function getIdentifier(element: ElementWithGroupInfo): string {
const { tagName, attributes, classList } = element.htmlElement;
const regexp = new RegExp(element.regexp, 'i');

Check warning on line 14 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L13-L14

Added lines #L13 - L14 were not covered by tests
if (!regexp.test(tagName)) {
const attribute = Array.from(attributes).find((att) => regexp.test(att.name));

Check warning on line 16 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L16

Added line #L16 was not covered by tests
if (attribute) {
return `${attribute.name}${attribute.value ? `="${attribute.value}"` : ''}`;
}
const className = Array.from(classList).find((cName) => regexp.test(cName));

Check warning on line 20 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L20

Added line #L20 was not covered by tests
if (className) {
return className;

Check warning on line 22 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L22

Added line #L22 was not covered by tests
}
}
return tagName;

Check warning on line 25 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L25

Added line #L25 was not covered by tests
}

/**
* Compute the number of ancestors of a given element based on a list of elements
* @param element
* @param elementList
*/
export function computeNumberOfAncestors(element: HTMLElement, elementList: HTMLElement[]) {
return elementList.filter((el: HTMLElement) => el.contains(element)).length;

Check warning on line 34 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L34

Added line #L34 was not covered by tests
}

/**
* Throttle {@link fn} with a {@link delay}
* @param fn method to run
* @param delay given in ms
*/
export function throttle<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void {
let timerFlag: ReturnType<typeof setTimeout> | null = null;

Check warning on line 43 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L43

Added line #L43 was not covered by tests

const throttleFn = (...args: Parameters<T>) => {

Check warning on line 45 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L45

Added line #L45 was not covered by tests
if (timerFlag === null) {
fn(...args);
timerFlag = setTimeout(() => {
fn(...args);
timerFlag = null;

Check warning on line 50 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L47-L50

Added lines #L47 - L50 were not covered by tests
}, delay);
}
};
return throttleFn;

Check warning on line 54 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L54

Added line #L54 was not covered by tests
}

/**
* Run {@link refreshFn} if {@link mutations} implies to refresh elements inside {@link highlightWrapper}
* @param mutations
* @param highlightWrapper
* @param refreshFn
*/
export function runRefreshIfNeeded(mutations: MutationRecord[], highlightWrapper: Element | null, refreshFn: () => void) {
if (
mutations.some((mutation) =>

Check warning on line 65 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L65

Added line #L65 was not covered by tests
mutation.target !== highlightWrapper
|| (
mutation.target === document.body
&& Array.from<HTMLElement>(mutation.addedNodes.values() as any)
.concat(...mutation.removedNodes.values() as any)
.some((node) => !node.classList.contains(HIGHLIGHT_WRAPPER_CLASS))

Check warning on line 71 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L71

Added line #L71 was not covered by tests
)
)
) {
refreshFn();

Check warning on line 75 in packages/@o3r/components/src/devkit/highlight/helpers.ts

View check run for this annotation

Codecov / codecov/patch

packages/@o3r/components/src/devkit/highlight/helpers.ts#L75

Added line #L75 was not covered by tests
}
}
Loading

0 comments on commit 5e2bf4a

Please sign in to comment.