Skip to content

Commit

Permalink
Do not rely on any to extend the option context
Browse files Browse the repository at this point in the history
This is a breaking change for TypeScript projects since now, in order
to extend the option context, it's required to declare a custom type
or to use module augmentation. Add TypeScript documentation but also
a migration guide for the upcoming versions 1.x & 2.x.
  • Loading branch information
simonbrunel committed Dec 28, 2020
1 parent e8fa4f3 commit b5cd8aa
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Requires [Chart.js](https://github.com/chartjs/Chart.js/releases) **2.7.0** or l
- [Positioning](https://chartjs-plugin-datalabels.netlify.app/guide/positioning.html)
- [Formatting](https://chartjs-plugin-datalabels.netlify.app/guide/formatting.html)
- [Events](https://chartjs-plugin-datalabels.netlify.app/guide/events.html)
- [TypeScript](https://chartjs-plugin-datalabels.netlify.app/guide/typescript.html)
- [Migration](https://chartjs-plugin-datalabels.netlify.app/guide/migration.html)
- [Samples](https://chartjs-plugin-datalabels.netlify.app/samples/)

## Development
Expand Down
2 changes: 2 additions & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ module.exports = {
'positioning',
'formatting',
'events',
'typescript',
'migration',
],
'/samples/': [
{
Expand Down
4 changes: 3 additions & 1 deletion docs/guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ This plugin doesn't provide any public API (except the plugin options), thus you
* [Options](options.md)
* [Labels](labels.md)
* [Positioning](positioning.md)
* [Formating](formatting.md)
* [Formatting](formatting.md)
* [Events](events.md)
* [TypeScript](typescript)
* [Migration](migration)
* [Samples](../samples)

## License
Expand Down
20 changes: 20 additions & 0 deletions docs/guide/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Migration

## Migrating to v1.0.0

### Breaking Changes

#### Extending the Option Context <Badge text="TS only"/>

In order to extend the [option context](options.md#option-context), you now need to use one of the methods described [in this section](typescript.md#option-context). Peviously, this feature relied on the use of `any`. If for whatever reasons you need that flexibility, the old behavior can be achieved using:

```ts
import {Context} from 'chartjs-plugin-datalabels';

// OLD BEHAVIOR: NOT RECOMMENDED!
declare module 'chartjs-plugin-datalabels' {
interface Context {
[key: string]: any;
}
}
```
4 changes: 4 additions & 0 deletions docs/guide/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ The context object contains the following properties:
| `dataset` | `object` | The dataset at index `datasetIndex`.
| `datasetIndex` | `number` | The index of the associated dataset.

::: tip
The option context can be extended dynamically with user custom properties, for example to implement [event based label customizations & interactions](events.md#listeners).
:::

## Indexable Options

Indexable options also accept an array in which each item corresponds to the element at the same index. Note that this method requires to provide as many items as data, so, in most cases, using a [function](#scriptable-options) is more appropriate.
Expand Down
94 changes: 94 additions & 0 deletions docs/guide/typescript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# TypeScript

This plugin provides TypeScript type declaration files bundled in the npm package so that types of this plugin options are checked when building your TypeScript project. Note that you also need the `@types/chart.js` package, if not already installed:

```sh
npm install --save-dev @types/chart.js
```

## Option Context

The declaration of the [option context](options.md#option-context) is exported as `Context`:

```ts
import {Context} from 'chartjs-plugin-datalabels';

const chart = new Chart('foo', {
options: {
plugins: {
datalabels: {
rotation: (ctx: Context) => {
return ctx.dataIndex % 2 ? 180 : 0;
},
}
}
}
});
```

Extending this context can be done using one of the following methods:

### Custom Interface

```ts
import {Context} from 'chartjs-plugin-datalabels';

interface FooContext extends Context {
foo?: number;
}

const chart = new Chart('foo', {
options: {
plugins: {
datalabels: {
rotation: (ctx: FooContext) => ctx.foo || 0,
listeners: {
click: (ctx: FooContext) => {
ctx.foo += (ctx.foo || 0) + 10;
return true;
}
}
}
}
}
});
```

::: tip
This method allows to declare different context interfaces to use in different charts.
:::

### Module Augmentation

```ts
// shims-chartjs-plugin-datalabels.d.ts
import {Context} from 'chartjs-plugin-datalabels';

declare module 'chartjs-plugin-datalabels' {
interface Context {
foo?: number;
}
}
```

```ts
// index.ts
const chart = new Chart('foo', {
options: {
plugins: {
datalabels: {
rotation: (ctx: Context) => ctx.foo || 0,
listeners: {
click: (ctx: Context) => {
ctx.foo += (ctx.foo || 0) + 10;
return true;
}
}
}
}
}
});
```
::: warning
The augmented `Context` declaration will be the same for all charts. This method should be considered only if all charts should share the same context declaration. Read more about [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation).
:::
6 changes: 0 additions & 6 deletions types/context.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,4 @@ export interface Context {
* @since 0.1.0
*/
datasetIndex: number;

// NOTE(SB) context can be extended dynamically with user properties, for
// example to implement event based label customizations / interactions.
// https://chartjs-plugin-datalabels.netlify.app/guide/events.html#example
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
4 changes: 2 additions & 2 deletions types/test/options.basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const options: Options = {
click: (ctx: Context) => true,
enter: (ctx: Context) => false,
leave: (ctx: Context) => {
ctx.foo = 42;
// return void
}
},
padding: {
Expand All @@ -69,7 +69,7 @@ const options: Options = {
click: (ctx: Context) => true,
enter: (ctx: Context) => false,
leave: (ctx: Context) => {
ctx.foo = 42;
// return void
}
},
offset: 42,
Expand Down
31 changes: 31 additions & 0 deletions types/test/options.context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Chart} from 'chart.js';
import {Context} from '../context';
import {Options} from '../options';

interface CustomContext extends Context {
foo?: number;
}

const options: Options = {
rotation: (ctx: CustomContext) => ctx.foo || 0,
listeners: {
click: (ctx: CustomContext) => {
ctx.foo = 42;
}
},
};

const chart = new Chart('id', {
data: {
datasets: [
{
datalabels: options
}
]
},
options: {
plugins: {
datalabels: options
}
}
});

0 comments on commit b5cd8aa

Please sign in to comment.