Skip to content

Commit

Permalink
[add] Event handlers of ECharts elements
Browse files Browse the repository at this point in the history
  • Loading branch information
TechQuery committed Feb 16, 2024
1 parent 50133ce commit cf6c6e5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 8 deletions.
26 changes: 22 additions & 4 deletions source/component/ECharts/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
ChartType,
ECChartOptionName,
ECComponentOptionName,
ZRElementEventHandler,
ZRElementEventName,
loadChart,
loadComponent,
loadRenderer,
Expand All @@ -19,7 +21,9 @@ export class EChartsElement extends HTMLElement implements CustomElement {
#data: EChartsOption = {};
#type: ChartType;
#core?: ECharts;
#buffer = [];
#eventHandlerBuffer: [ZRElementEventName, string, ZRElementEventHandler][] =
[];
#eventDataBuffer = [];

toJSON() {
return this.#core?.getOption();
Expand Down Expand Up @@ -60,14 +64,19 @@ export class EChartsElement extends HTMLElement implements CustomElement {

this.setOption(this.#data);

for (const option of this.#buffer) this.setOption(option);
for (const [event, selector, handler] of this.#eventHandlerBuffer)
this.onChild(event, selector, handler);

this.#buffer.length = 0;
this.#eventHandlerBuffer.length = 0;

for (const option of this.#eventDataBuffer) this.setOption(option);

this.#eventDataBuffer.length = 0;
}

async setOption(data: EChartsOption) {
if (!this.#core) {
this.#buffer.push(data);
this.#eventDataBuffer.push(data);
return;
}

Expand Down Expand Up @@ -98,6 +107,15 @@ export class EChartsElement extends HTMLElement implements CustomElement {

this.setOption(this.#data);
}

onChild(
event: ZRElementEventName,
selector: string,
handler: ZRElementEventHandler
) {
if (this.#core) this.#core.on(event, selector, handler);
else this.#eventHandlerBuffer.push([event, selector, handler]);
}
}

customElements.define('ec-chart', EChartsElement);
Expand Down
30 changes: 29 additions & 1 deletion source/component/ECharts/Option.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { JsxProps } from 'dom-renderer';
import { EChartsOption } from 'echarts';
import { ECElementEvent } from 'echarts/core';
import { CustomElement, toCamelCase, toHyphenCase } from 'web-utility';

import { EChartsElement } from './Chart';
import {
BUILTIN_CHARTS_MAP,
BUITIN_COMPONENTS_MAP,
ECChartOptionName,
ECComponentOptionName,
EventKeyPattern,
ZRElementEventHandler,
ZRElementEventName,
proxyPrototype
} from './utility';

Expand Down Expand Up @@ -36,6 +42,12 @@ export abstract class ECOptionElement
}

connectedCallback() {
for (const [key, value] of Object.entries(this.#data))
if (EventKeyPattern.test(key) && typeof value === 'function')
this.on(
key.slice(2) as ZRElementEventName,
value as ZRElementEventHandler
);
this.update();
}

Expand All @@ -50,6 +62,10 @@ export abstract class ECOptionElement
if (value) super.setAttribute(key, key + '');
else super.removeAttribute(key);
break;
case 'function':
if (EventKeyPattern.test(key))
this.on(key.slice(2) as ECElementEvent['type'], value);
break;
default:
super.setAttribute(key, value + '');
}
Expand All @@ -71,6 +87,15 @@ export abstract class ECOptionElement
);
}

on(event: ZRElementEventName, handler: ZRElementEventHandler) {
if (this.isConnected)
this.closest<EChartsElement>('ec-chart')?.onChild(
event,
[this.chartTagName, this['type']].filter(Boolean).join('.'),
handler
);
}

setAttribute(key: string, value: string) {
super.setAttribute(key, value);

Expand All @@ -89,12 +114,15 @@ for (const name of Object.keys({
class extends ECOptionElement {}
);

type HyphenCase<T> = T extends `${infer L}${infer R}`
? `${L extends Uppercase<L> ? `-${Lowercase<L>}` : L}${HyphenCase<R>}`
: T;
type PickSingle<T> = T extends infer S | (infer S)[] ? S : T;

type ECOptionElements = {
[K in
| ECComponentOptionName
| ECChartOptionName as `ec-${K}`]: JsxProps<ECOptionElement> &
| ECChartOptionName as `ec-${HyphenCase<K>}`]: JsxProps<ECOptionElement> &
PickSingle<EChartsOption[K]>;
};

Expand Down
7 changes: 6 additions & 1 deletion source/component/ECharts/utility.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { use } from 'echarts/core';
import { ECElementEvent, use } from 'echarts/core';
import memoize from 'lodash.memoize';
import { IndexKey } from 'web-utility';

Expand Down Expand Up @@ -27,6 +27,11 @@ export function proxyPrototype<T extends object>(
Object.setPrototypeOf(target, prototypeProxy);
}

export const EventKeyPattern = /^on(\w+)/;

export type ZRElementEventName = ECElementEvent['type'];
export type ZRElementEventHandler = (event: ECElementEvent) => boolean | void;

/**
* @see {@link https://github.com/apache/echarts/blob/031a908fafaa57e2277b2f720087195925ec38cf/src/model/Global.ts#L83-L111}
*/
Expand Down
4 changes: 2 additions & 2 deletions source/page/Map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ export default class MapsPage extends HTMLElement implements CustomElement {
const { loading, virusData } = this;

return (
<ec-chart style={{ height: '75vh' }}>
<ec-title text="test" />
<ec-chart style={{ height: '75vh' }} useUTC>
<ec-title text="test" triggerEvent onClick={console.log} />
</ec-chart>
);
}
Expand Down

1 comment on commit cf6c6e5

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

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

Deploy preview for wuhan2020 ready!

✅ Preview
https://wuhan2020-fjrbfon84-techquery.vercel.app

Built with commit cf6c6e5.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.