Skip to content

Commit

Permalink
fixed a but of elements not getting cleared upon navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
hasith committed Sep 8, 2024
1 parent 5e1deda commit 613a750
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 47 deletions.
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion packages/@productled/core/src/Productled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,12 @@ class Productled {
* @returns {Promise<void>}
*/
private routeChanged(url: string) {
const hooks = this.hookStore.getHooks(url);
// clear all the previously created elements
this.pluginStore.clearPluginElements();

// Get the hooks for the current route
const hooks = this.hookStore.getHooks(url);
// Execute the hooks
const hookExecuter = new HookExecuter(this.pluginStore, this.documentService, this.themeManager.Theme);
hookExecuter.executeHooks(hooks);
}
Expand Down
7 changes: 7 additions & 0 deletions packages/@productled/core/src/plugins/PluginStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ class PluginStore {
return this.definitionDictionary[pluginName];
}

public clearPluginElements() {
// iterate over all the plugins and remove all the elements
Object.keys(this.definitionDictionary).forEach(key => {
this.definitionDictionary[key].removeAll();
});
}

}

export default PluginStore;
17 changes: 8 additions & 9 deletions packages/@productled/spotlights/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",

"scripts": {
"build": "tsc",
"test": "jest",
"clean": "rm -rf dist"
"build": "tsc",
"test": "jest",
"clean": "rm -rf dist"
},
"dependencies": {

"@productled/tooltip": "^1.0.0"
},
"devDependencies": {
"@types/node": "^20.14.9",
"ts-node": "^10.9.2",
"typescript": "^4.9.5"
"@types/node": "^20.14.9",
"ts-node": "^10.9.2",
"typescript": "^4.9.5"
}
}
}
20 changes: 14 additions & 6 deletions packages/@productled/spotlights/src/Spotlight.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Theme } from '@productled/core';
import { StylesElement } from './StylesElement';
import { Tooltip } from '@productled/tooltip';
export interface Positioning {
left: string;
top: string;
}
export interface SpotlightConf {
title: String;
description: String;
link: String;
title: string;
description: string;
link: string;
positioning: Positioning;
}
export class Spotlight {
Expand All @@ -22,15 +23,15 @@ export class Spotlight {
this.theme = theme;
}

create(spotlightConf: SpotlightConf): void {
create(conf: SpotlightConf): void {
// Position the spotlight relative to the target element
(this.targetElement as HTMLElement).style.position = 'relative';

const container = document.createElement('div');
container.classList.add(Spotlight.SELECTOR);
container.style.position = 'absolute';
container.style.left = `${spotlightConf.positioning.left}px`;
container.style.top = `${spotlightConf.positioning.top}px`;
container.style.left = `${conf.positioning.left}px`;
container.style.top = `${conf.positioning.top}px`;

const styles = new StylesElement(this.theme);
container.appendChild(styles.Element);
Expand All @@ -39,5 +40,12 @@ export class Spotlight {
const spotlight = document.createElement('span');
spotlight.classList.add('beacon');
container.appendChild(spotlight);

const tooltip = new Tooltip(spotlight, this.theme);
tooltip.create({
title: conf.title,
description: conf.description,
link: conf.link,
});
}
}
2 changes: 1 addition & 1 deletion packages/@productled/spotlights/src/SpotlightPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SpotlightPlugin implements Plugin {
}
}
removeAll(): void {
const spotlights = document.querySelectorAll(Spotlight.SELECTOR);
const spotlights = document.querySelectorAll('.' + Spotlight.SELECTOR);
spotlights.forEach(spotlight => {
spotlight.remove();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/@productled/tooltip/src/StylesElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class StylesElement {
content: '';
position: absolute;
bottom: 100%; /* Place the arrow at the top edge */
left: 10%;
left: 10px;
transform: translateX(-50%);
border-width: 8px;
border-style: solid;
Expand Down
57 changes: 36 additions & 21 deletions packages/@productled/tooltip/src/Tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { Theme } from '@productled/core';
import { StylesElement } from './StylesElement';

// Interface for positioning of the tooltip
export interface Positioning {
left: string;
top: string;
}

// Interface for tooltip configuration
export interface TooltipConf {
title: string;
description: string;
link: string;
positioning: Positioning;
}

// Tooltip class
export class Tooltip {
private element: Element;
private theme: Theme;
private tooltip: HTMLElement | null = null;

// Constants
public static SELECTOR = 'productled-tooltip';
public static PLUGIN_NAME = 'tooltip';

Expand All @@ -26,10 +29,14 @@ export class Tooltip {
this.theme = theme;
}

/**
* Creates the tooltip based on the provided configuration.
* @param conf - The tooltip configuration.
*/
create(conf: TooltipConf): void {

// Create tooltip container
this.tooltip = document.createElement('div');
this.tooltip.classList.add(Tooltip.SELECTOR);
this.tooltip.style.position = 'absolute';
this.tooltip.style.backgroundColor = this.theme.backgroundColor;
this.tooltip.style.color = this.theme.textColor;
Expand All @@ -44,7 +51,7 @@ export class Tooltip {
this.tooltip.appendChild(styles.Element);

// Add class for the tooltip
this.tooltip.classList.add('productled-tooltip');
this.tooltip.classList.add(Tooltip.SELECTOR);

// Create title
const title = document.createElement('h3');
Expand Down Expand Up @@ -75,13 +82,8 @@ export class Tooltip {
});

// Hide tooltip when leaving both the element and the tooltip
this.element.addEventListener('mouseleave', (e) => {
this.element.addEventListener('mouseleave', (e) => {
const isMouseOnTooltip = (e as MouseEvent).relatedTarget === this.tooltip;
if (!isMouseOnTooltip) {
this.hideTooltipWithDelay(500);
}
});
this.element.addEventListener('mouseleave', () => {
this.hideTooltipWithDelay(500);
});

// Keep tooltip visible when hovering over the tooltip
Expand All @@ -91,27 +93,40 @@ export class Tooltip {
});

// Hide tooltip when leaving the tooltip
this.tooltip.addEventListener('mouseleave', (e) => {
const isMouseOnElement = (e as MouseEvent).relatedTarget === this.element;
if (!isMouseOnElement) {
this.hideTooltipWithDelay();
}
this.tooltip.addEventListener('mouseleave', () => {
this.hideTooltipWithDelay(500);
});
}

private positionTooltip() {
/**
* Checks if the mouse is on the target element or the tooltip.
* @returns True if the mouse is on the target element or the tooltip, false otherwise.
*/
private isMouseOn(): boolean {
// Find if mouse is on this.element or this.tooltip
const isMouseOnElement = this.element.matches(':hover') || false;
const isMouseOnTooltip = this.tooltip?.matches(':hover') || false;
return isMouseOnElement || isMouseOnTooltip;
}

/**
* Positions the tooltip relative to the target element.
*/
private positionTooltip(): void {
const rect = this.element.getBoundingClientRect();
this.tooltip!.style.left = `${rect.left + window.scrollX}px`;
this.tooltip!.style.top = `${rect.bottom + window.scrollY}px`;
};
}

// Hide tooltip after a small delay to handle fast mouse movements
private hideTooltipWithDelay(delay = 200) {
/**
* Hides the tooltip after a small delay to handle fast mouse movements.
* @param delay - The delay in milliseconds.
*/
private hideTooltipWithDelay(delay = 200): void {
setTimeout(() => {
if (this.tooltip) {
if (this.tooltip && !this.isMouseOn()) {
this.tooltip.style.display = 'none';
}
}, delay); // 200ms delay to avoid flicker during fast mouse transitions
}, delay);
}
}
2 changes: 1 addition & 1 deletion packages/@productled/tooltip/src/TooltipPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TooltipPlugin implements Plugin {
}
}
removeAll(): void {
const elements = document.querySelectorAll(Tooltip.SELECTOR);
const elements = document.querySelectorAll('.' + Tooltip.SELECTOR);
elements.forEach(element => {
element.remove();
});
Expand Down
1 change: 1 addition & 0 deletions packages/@productled/tooltip/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as ToolTipPlugin } from './TooltipPlugin';
export { Tooltip } from './Tooltip';
1 change: 1 addition & 0 deletions packages/samples/react-sample/src/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const Page: React.FC = () => {
return (
<div>
<h2>Page</h2>
<button className='btn tooltip-me'>Tooltip Me</button>
<Outlet /> {/* This will render the nested routes */}
</div>
);
Expand Down
1 change: 0 additions & 1 deletion packages/samples/react-sample/src/SubPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const SubPage: React.FC = () => {
<p>Donec auctor, nunc id aliquet lacinia, nisl justo lacinia nunc, id lacinia lectus nisl in nunc. Sed auctor, nunc id aliquet lacinia, nisl justo lacinia nunc, id lacinia lectus nisl in nunc.</p>
</div>
<button className='btn spot-me' style={{ marginRight: '20px' }}>Spot Me</button>
<button className='btn tooltip-me'>Tooltip Me</button>
</div>
);
}
Expand Down
12 changes: 6 additions & 6 deletions packages/samples/react-sample/src/productled-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
}
},
"config": {
"title": "New Click Me Feature",
"description": "You can now send emails directly from here",
"link": "http://myblog.com/new_feature_intro",
"title": "New Feature Spotlight",
"description": "You can now do the impossible with this new feature",
"link": "https://99x-incubator.github.io/productled/plugins/spotlight.html",
"positioning": {
"left": "60",
"top": "10"
Expand All @@ -35,9 +35,9 @@
}
},
"config": {
"title": "New Click Me Feature",
"description": "You can now send emails directly from here",
"link": "http://myblog.com/new_feature_intro",
"title": "I'm a Tooltip Title",
"description": "This tooltip is here to help you understand the feature",
"link": "https://99x-incubator.github.io/productled/plugins/tooltip.html",
"positioning": {
"left": "60",
"top": "10"
Expand Down

0 comments on commit 613a750

Please sign in to comment.