Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@equinor/fusion-framework-cookbook-app-react-ag-grid": patch
---

Add test theme override example in cookbook configuration.

Demonstrates how to use the theme function API with custom theme parameters.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@equinor/fusion-framework-cookbook-app-react-charts": patch
---

Update AG Charts imports to use new `@equinor/fusion-framework-react-ag-grid/charts` export path.

Migrate from direct `ag-charts-react` imports to the framework's unified charts export.
20 changes: 20 additions & 0 deletions .changeset/module-ag-grid_theme-function.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@equinor/fusion-framework-module-ag-grid": minor
---

Internal: `theme` config property now expects a function `() => Theme` for lazy evaluation, but consumer APIs remain backward compatible.

Most consumers using `builder.setTheme()` do not need to migrate; it still accepts both `Theme` objects and functions. Only direct construction of `AgGridConfig` requires the function wrapper.

```typescript
// Internal API change (rare, direct config construction)
const config: AgGridConfig = {
theme: () => myTheme
};

// Builder API remains backward compatible
builder.setTheme(myTheme); // still works
builder.setTheme((theme) => theme.withParams({...})); // also works
```

Fixes: https://github.com/equinor/fusion-framework/issues/747
15 changes: 15 additions & 0 deletions .changeset/react-ag-grid_add-charts-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@equinor/fusion-framework-react-ag-grid": minor
---

Add new `./charts` export path for AG Charts React components and enterprise module.

The package now exports `AgCharts` and `AgChartsEnterpriseModule` from a dedicated `./charts` export path. This provides a cleaner separation from the enterprise exports.

```typescript
import { AgCharts, AgChartsEnterpriseModule } from '@equinor/fusion-framework-react-ag-grid/charts';
```

Note: Charts exports are still available from `./enterprise` for backward compatibility but will be removed in a future minor release.

Fixes: https://github.com/equinor/fusion-framework/issues/747
5 changes: 5 additions & 0 deletions cookbooks/app-react-ag-grid/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export const configure: AppModuleInitiator = (configurator, { env }) => {
IntegratedChartsModule.with(AgChartsEnterpriseModule),
AllCommunityModule,
]);
builder.setTheme((theme) =>
theme.withParams({
headerTextColor: 'cornflowerblue',
}),
);
});

/** callback when configurations is created */
Expand Down
7 changes: 3 additions & 4 deletions cookbooks/app-react-charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,16 @@
"@equinor/fusion-framework-cli": "workspace:^",
"@equinor/fusion-framework-module-navigation": "workspace:^",
"@equinor/fusion-framework-react-app": "workspace:^",
"@equinor/fusion-framework-react-ag-grid": "workspace:^",
"@types/react": "^18.2.50",
"@types/react-dom": "^18.2.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^7.6.0",
"typescript": "^5.8.2",
"styled-components": "^6.1.19"
"styled-components": "^6.1.19",
"typescript": "^5.8.2"
},
"dependencies": {
"ag-charts-community": "^12.2.0",
"ag-charts-react": "^12.2.0",
"chart.js": "^4.4.9",
"react-chartjs-2": "^5.3.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AgChartOptions } from 'ag-charts-community';
import { salesData } from './Data';
import { type ReactElement, useMemo } from 'react';
import Styled from '../../App.style';
import { AgCharts } from 'ag-charts-react';
import { AgCharts } from '@equinor/fusion-framework-react-ag-grid/charts';

/**
* AgArea Component - Stacked Area Chart Visualization
Expand Down
2 changes: 1 addition & 1 deletion cookbooks/app-react-charts/src/pages/ag-charts/AgBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AgChartOptions } from 'ag-charts-community';
import { salesData } from './Data';
import { type ReactElement, useMemo } from 'react';
import Styled from '../../App.style';
import { AgCharts } from 'ag-charts-react';
import { AgCharts } from '@equinor/fusion-framework-react-ag-grid/charts';

/**
* AgBar Component - Bar Chart Visualization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AgChartOptions } from 'ag-charts-community';
import { temperatureData } from './Data';
import { type ReactElement, useMemo } from 'react';
import Styled from '../../App.style';
import { AgCharts } from 'ag-charts-react';
import { AgCharts } from '@equinor/fusion-framework-react-ag-grid/charts';

/**
* AgLine Component - Line Chart Visualization
Expand Down
2 changes: 1 addition & 1 deletion cookbooks/app-react-charts/src/pages/ag-charts/AgPie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AgChartOptions } from 'ag-charts-community';
import { marketShareData } from './Data';
import { type ReactElement, useMemo } from 'react';
import Styled from '../../App.style';
import { AgCharts } from 'ag-charts-react';
import { AgCharts } from '@equinor/fusion-framework-react-ag-grid/charts';

/**
* AgPie Component - Pie Chart Visualization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Theme, Module } from 'ag-grid-community';

export interface AgGridConfig {
licenseKey?: string;
theme?: Theme;
theme?: () => Theme;
modules?: Array<Module>;
}

Expand Down
11 changes: 6 additions & 5 deletions packages/modules/ag-grid/src/AgGridConfigurator.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { BaseConfigBuilder } from '@equinor/fusion-framework-module';

import { type Theme, type Module, createTheme } from 'ag-grid-community';
import type { Theme, Module } from 'ag-grid-community';
import type { AgGridConfig, IAgGridConfigurator } from './AgGridConfigurator.interface';
import { createTheme } from './themes';

export class AgGridConfigurator
extends BaseConfigBuilder<AgGridConfig>
implements IAgGridConfigurator
{
// local template variables
#modules: Set<Module>;
#theme: Theme | undefined;
#theme: () => Theme;

constructor(args: Partial<AgGridConfig> = {}) {
super();

// set default values
this.#modules = new Set(args.modules || []);
this.#theme = args.theme ?? createTheme();
this.#theme = args.theme ?? (() => createTheme());

// set config properties
this._set('modules', async () => [...this.#modules]);
Expand All @@ -30,9 +31,9 @@ export class AgGridConfigurator

setTheme(valueOrCallback: Theme | ((baseTheme: Theme) => Theme) | null): void {
if (typeof valueOrCallback === 'function') {
this.#theme = valueOrCallback(this.#theme ?? createTheme());
this._set('theme', async () => () => valueOrCallback(this.#theme()));
} else {
this.#theme = valueOrCallback ?? undefined;
this._set('theme', async () => () => valueOrCallback as Theme);
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When valueOrCallback is null, this code casts it to Theme and wraps it in a function. This will result in () => null, which will cause issues when the theme is used.

The handling of null should either set theme to undefined or to a default theme function:

this._set('theme', async () => valueOrCallback ? () => valueOrCallback as Theme : () => createTheme());

Copilot uses AI. Check for mistakes.
}
}
Comment on lines 32 to 38
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setTheme method updates the config via _set() but doesn't update the #theme field. This means subsequent calls to setTheme with a callback will use the old theme function, not the newly set one.

The method should also update #theme:

setTheme(valueOrCallback: Theme | ((baseTheme: Theme) => Theme) | null): void {
  if (typeof valueOrCallback === 'function') {
    this.#theme = () => valueOrCallback(this.#theme());
    this._set('theme', async () => this.#theme);
  } else {
    this.#theme = () => (valueOrCallback ?? createTheme());
    this._set('theme', async () => this.#theme);
  }
}

Copilot uses AI. Check for mistakes.

Expand Down
4 changes: 2 additions & 2 deletions packages/modules/ag-grid/src/AgGridProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class AgGridProvider implements IAgGridProvider {
* @returns {Theme | undefined} The current theme if configured, otherwise undefined.
*/
get theme(): Theme | undefined {
return this._config.theme;
return this._config.theme?.();
}

constructor(protected _config: AgGridConfig) {
Expand All @@ -36,7 +36,7 @@ export class AgGridProvider implements IAgGridProvider {
LicenseManager.setLicenseKey(this.licenseKey);
}
provideGlobalGridOptions({
theme: this._config.theme,
theme: this._config.theme?.(),
});

if (this._config.modules) {
Expand Down
4 changes: 2 additions & 2 deletions packages/modules/ag-grid/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { type IAgGridProvider, AgGridProvider } from './AgGridProvider';

import type { IAgGridConfigurator } from './AgGridConfigurator.interface';

import { fusionTheme, createThemeFromTheme } from './themes';
import { createThemeFromTheme, fusionTheme } from './themes';

export type AgGridModule = Module<'agGrid', IAgGridProvider, IAgGridConfigurator>;

Expand All @@ -21,7 +21,7 @@ export const module: AgGridModule = {
configure: (ref?: ModulesInstanceType<[AgGridModule]>) => {
const licenseKey = ref?.agGrid?.licenseKey;

const theme = ref?.agGrid?.theme ? createThemeFromTheme(ref.agGrid.theme) : fusionTheme;
const theme = () => (ref?.agGrid?.theme ? createThemeFromTheme(ref.agGrid.theme) : fusionTheme);
return new AgGridConfigurator({
licenseKey,
theme,
Expand Down
12 changes: 11 additions & 1 deletion packages/react/ag-grid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"import": "./dist/esm/enterprise.js",
"types": "./dist/types/enterprise.d.ts"
},
"./charts": {
"import": "./dist/esm/charts.js",
"types": "./dist/types/charts.d.ts"
},
"./themes": {
"import": "./dist/esm/themes.js",
"types": "./dist/types/themes.d.ts"
Expand All @@ -35,6 +39,9 @@
"enterprise": [
"dist/types/enterprise.d.ts"
],
"charts": [
"dist/types/charts.d.ts"
],
"themes": [
"dist/types/themes.d.ts"
]
Expand All @@ -61,6 +68,7 @@
"dependencies": {
"@equinor/fusion-framework-module-ag-grid": "workspace:*",
"ag-charts-enterprise": "~12.3.1",
"ag-charts-react": "~12.3.1",
"ag-grid-community": "~34.3.1",
"ag-grid-enterprise": "~34.3.1",
"ag-grid-react": "~34.3.1"
Expand All @@ -70,6 +78,8 @@
"typescript": "^5.8.2"
},
"peerDependencies": {
"@equinor/fusion-framework-react-module": "workspace:^"
"@equinor/fusion-framework-react-module": "workspace:^",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}
}
2 changes: 2 additions & 0 deletions packages/react/ag-grid/src/charts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { AgChartsEnterpriseModule } from 'ag-charts-enterprise';
export * from 'ag-charts-react';
1 change: 1 addition & 0 deletions packages/react/ag-grid/src/enterprise.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from 'ag-grid-enterprise';
// todo remove in next minor release - use ./charts instead
export { AgChartsEnterpriseModule } from 'ag-charts-enterprise';
Loading
Loading