Skip to content

Commit

Permalink
Added theming support and structured the core library into multiple n…
Browse files Browse the repository at this point in the history
…amespaces
  • Loading branch information
hasith committed Sep 6, 2024
1 parent f25fa21 commit b0a9e8e
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 140 deletions.
56 changes: 56 additions & 0 deletions docs/theming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Theming
layout: home
nav_order: 4
---

# Theming

The Product-led library allows users to customize the look and feel of its components. It provides a default theme that can be easily overridden or changed to suit specific requirements.

## Default Theme

The library's default theme consists of the following properties:

```typescript
export const defaultTheme: Theme = {
primaryColor: '#3498db',
secondaryColor: '#2ecc71',
backgroundColor: '#ffffff',
textColor: '#333333',
fontSize: '16px',
fontFamily: 'Arial, sans-serif',
borderRadius: '4px',
boxShadow: '0px 4px 6px rgba(0, 0, 0, 0.1)',
spacing: '8px',
linkColor: '#2980b9',
errorColor: '#e74c3c',
successColor: '#2ecc71',
warningColor: '#f39c12',
infoColor: '#3498db',
};
```

## Overriding the Default Theme

You can override the default theme by using CSS variables. To change specific properties, simply define your custom values in your CSS file.

Example:

```css
:root {
--primaryColor: #473ce7;
}
```

In this example, the primaryColor is set to a new value.

## Programmatically Changing the Theme

To dynamically update the theme in your application, use the following method:

```typescript
Productled.getInstance().applyCustomTheme(customTheme: Partial<Theme>);
```

This method allows you to pass a custom theme object to override the default or previously applied theme properties. You only need to provide the properties you want to change.
8 changes: 0 additions & 8 deletions packages/@productled/core/src/Plugin.ts

This file was deleted.

100 changes: 0 additions & 100 deletions packages/@productled/core/src/Productled.test.ts

This file was deleted.

24 changes: 19 additions & 5 deletions packages/@productled/core/src/Productled.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import HookExecuter from './HookExecuter';
import HookStore from './HookStore';
import Plugin from './Plugin';
import HookExecuter from './hooks/HookExecuter';
import HookStore from './hooks/HookStore';
import Plugin from './plugins/Plugin';
import ConfigStore from './ConfigStore';
import PluginStore from './PluginStore';
import PluginStore from './plugins/PluginStore';
import DocumentService from './DocumentService';
import { RouteListener } from "./RouteListener";
import { Theme, ThemeManager } from './theme/ThemeManager';

/**
* The Productled class represents the core functionality of the Productled library.
Expand All @@ -17,6 +18,7 @@ class Productled {
protected pluginStore: PluginStore;
protected documentService: DocumentService;
protected routeListener: RouteListener;
protected themeManager: ThemeManager;

/**
* The constructor is private to ensure that the class is a singleton.
Expand All @@ -28,6 +30,7 @@ class Productled {
this.documentService = new DocumentService();
this.configStore = new ConfigStore();
this.routeListener = new RouteListener();
this.themeManager = new ThemeManager();
this.routeListener.addListener(this.routeChanged.bind(this));
}

Expand All @@ -43,6 +46,17 @@ class Productled {
return Productled.instance;
}


/**
* Applies a custom theme to the product.
*
* @param customTheme - The partial theme object containing the custom theme properties.
* @returns void
*/
public applyCustomTheme(customTheme: Partial<Theme>): void {
this.themeManager.applyCustomTheme(customTheme);
}

/**
* This method registers the hook configuration with the Productled instance.
*/
Expand All @@ -59,7 +73,7 @@ class Productled {
private routeChanged(url: string) {
const hooks = this.hookStore.getHooks(url);

const hookExecuter = new HookExecuter(this.pluginStore, this.documentService);
const hookExecuter = new HookExecuter(this.pluginStore, this.documentService, this.themeManager.Theme);
hookExecuter.executeHooks(hooks);
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import Hook from "./Hook";
import PluginStore from "./PluginStore";
import DocumentService from "./DocumentService";
import PluginStore from "../plugins/PluginStore";
import DocumentService from "../DocumentService";
import { Theme } from "../theme/ThemeManager";

class HookExecuter {
private pluginStore: PluginStore;
private documentService: DocumentService;
private theme: Theme;

constructor(pluginStore: PluginStore, documentService: DocumentService) {
constructor(pluginStore: PluginStore, documentService: DocumentService, theme: Theme) {
this.pluginStore = pluginStore;
this.documentService = documentService;
this.theme = theme;
}

public async executeHooks(hooks: Hook[]) {
Expand All @@ -25,7 +28,7 @@ class HookExecuter {
console.warn(`Plugin with name ${hook.pluginName} not found`);
return;
}
plugin.create(element, hook)
plugin.create(element, hook, this.theme)
};
}
}
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions packages/@productled/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as Productled } from './Productled';
export { default as Plugin } from './Plugin';
export { default as Hook } from './Hook';
export { default as Plugin } from './plugins/Plugin';
export { default as Hook } from './hooks/Hook';
export { Theme} from './theme/ThemeManager';
9 changes: 9 additions & 0 deletions packages/@productled/core/src/plugins/Plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Theme } from "../theme/ThemeManager";

interface Plugin {
get Name(): string;
create(element: HTMLElement, conf: any, theme: Theme): void;
removeAll(): void;
}

export default Plugin;
73 changes: 73 additions & 0 deletions packages/@productled/core/src/theme/ThemeManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { defaultTheme } from "../theme/defaultTheme";

export interface Theme {
primaryColor: string; // Main color used in buttons, links, etc.
secondaryColor: string; // Supporting color for accents or highlights
backgroundColor: string; // General background color
textColor: string; // Main text color
fontSize: string; // Base font size for text
fontFamily: string; // Font family for text
borderRadius: string; // Rounded corners for UI components
boxShadow: string; // Shadow styling for depth
spacing: string; // General spacing (padding/margins)
linkColor: string; // Color for links
errorColor: string; // Color for error messages
successColor: string; // Color for success notifications
warningColor: string; // Color for warnings
infoColor: string; // Color for informational messages
[key: string]: string; // Allows additional properties
}

export class ThemeManager {


private currentTheme: Theme;

constructor() {
this.currentTheme = defaultTheme;
this.applyTheme();
}

public get Theme(): Theme {
return this.currentTheme;
}

// Fetch theme values from CSS variables, fallback to default if not found
getCSSVariable(variable: string): string {
const value = getComputedStyle(document.documentElement).getPropertyValue(`--${variable}`).trim();
return value || this.currentTheme[variable];
}

// Apply the theme, picking from CSS variables or default values
applyTheme(): void {
Object.keys(defaultTheme).forEach((key) => {
const themeValue = this.getCSSVariable(key);
document.documentElement.style.setProperty(`--${key}`, themeValue);
});
}

// Update and apply the theme dynamically
updateTheme(newTheme: Theme): void {
Object.keys(newTheme).forEach((key) => {
this.currentTheme[key] = newTheme[key];
document.documentElement.style.setProperty(`--${key}`, newTheme[key]);
});
}

/**
* Applies a new theme by merging it with the default theme and updating CSS variables.
* @param customTheme Partial theme object to override default theme properties.
*/
public applyCustomTheme(customTheme: Partial<Theme>): void {
const newTheme = { ...this.currentTheme, ...customTheme } as Theme;
this.updateTheme(newTheme);
}

/**
* Resets the theme to the default theme.
*/
public resetTheme(): void {
this.updateTheme(defaultTheme);
}

}
18 changes: 18 additions & 0 deletions packages/@productled/core/src/theme/defaultTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Theme } from './theme/ThemeManager';

export const defaultTheme: Theme = {
primaryColor: '#3498db',
secondaryColor: '#2ecc71',
backgroundColor: '#ffffff',
textColor: '#333333',
fontSize: '16px',
fontFamily: 'Arial, sans-serif',
borderRadius: '4px',
boxShadow: '0px 4px 6px rgba(0, 0, 0, 0.1)',
spacing: '8px',
linkColor: '#2980b9',
errorColor: '#e74c3c',
successColor: '#2ecc71',
warningColor: '#f39c12',
infoColor: '#3498db'
};
Loading

0 comments on commit b0a9e8e

Please sign in to comment.