Skip to content

Commit

Permalink
✨ Event propagation updates Vue 2 internal events
Browse files Browse the repository at this point in the history
* Using custom events for Vue 2 internal events instead of event bus
* Added group events to listen on group related events.
* Storybook Vue 2 console error fixes
  • Loading branch information
govind-srinidhi committed Nov 13, 2023
1 parent ea5d81f commit b8677b8
Show file tree
Hide file tree
Showing 11 changed files with 7,519 additions and 3,416 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
enable-pre-post-scripts=true
package-import-method=clone-or-copy
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ export const CustomTooltip: Story = {
}
return [];
};
return { args, computedColor, customItemsFunction };
return { args, computedColor, customItemsFunction, captureAction };
},
template: `
<div :style="{ width: args.width + 'px', height: args.orientation !== 'horizontal' ? args.height + 'px' : undefined }">
<lume-bar-chart v-bind="args" :color="computedColor">
<lume-bar-chart v-bind="args" :color="computedColor" ${actionEventHandlerTemplate}>
<template #tooltip = "{ opened, data, hoveredIndex, targetElement }">
<lume-tooltip v-if="opened" :items="customItemsFunction(data, hoveredIndex)" :target-element="targetElement" position="top"/>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ export const CustomTooltip: Story = {
}
return [];
};
return { args, customItemsFunction, computedColor };
return { args, customItemsFunction, computedColor, captureAction };
},
template: `<div :style="{ width: args.width + 'px', height: args.height + 'px' }">
<lume-line-chart v-bind="args">
<lume-line-chart v-bind="args" ${actionEventHandlerTemplate}>
<template #tooltip = "{ opened, data, hoveredIndex, targetElement }">
<lume-tooltip v-if="opened" :items="customItemsFunction(data, hoveredIndex)" :target-element="targetElement" position="top"/>
</template>
Expand Down
24 changes: 24 additions & 0 deletions packages/lib/src/components/core/lume-chart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ It is used internally to build all Lume charts but it can also be used to create
- [Payload](#payload-23)
- [`link-mouseleave`](#link-mouseleave)
- [Payload](#payload-24)
- [`group-mouseenter`](#group-mouseenter)
- [Payload](#payload-25)
- [`group-mouseleave`](#group-mouseleave)
- [Payload](#payload-26)
- [Examples](#examples)
- [Custom data group](#custom-data-group)
- [Custom tooltip element](#custom-tooltip-element)
Expand Down Expand Up @@ -572,6 +576,26 @@ p: {
}
```

#### `group-mouseenter`

Fired upon [mouseenter](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event) to a chart group.

##### Payload

```ts
index: number; // The group index user moused over.
```

#### `group-mouseleave`

Fired upon a chart group's [mouseleave](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseleave_event).

##### Payload

```ts
index: number; // The group index user mouse left.
```

## Examples

### Custom data group
Expand Down
6 changes: 4 additions & 2 deletions packages/lib/src/components/core/lume-chart/lume-chart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ const { allOptions } = useOptions<ChartOptions>(options);
const { internalData, computedLabels, containerSize, updateSize, chartID } =
useBase(data, labels, color, allOptions, orientation);
const { busListen } = useEvents(emit, chartID);
const { listenInternalEvent } = useEvents(emit, chartID);
const { xScale, yScale } = useBaseScales(
internalData,
Expand Down Expand Up @@ -427,6 +427,7 @@ function handleInternalHover(index: number) {
if (index === internalHoveredIndex.value) return;
// Update hoveredIndex
emit('group-mouseleave', internalHoveredIndex.value);
allOptions.value.withHover !== false && (internalHoveredIndex.value = index);
if (allOptions.value.withTooltip !== false) {
Expand All @@ -438,6 +439,7 @@ function handleInternalHover(index: number) {
: allOptions.value.tooltipOptions.targetElement;
showTooltip(targetElement);
}
emit('group-mouseenter', index);
}
function handleHideTooltip() {
Expand Down Expand Up @@ -514,7 +516,7 @@ onMounted(async () => {
}
if (__VUE_VERSION__ === 2) {
await busListen('lume__internal--hover', handleInternalHover);
listenInternalEvent('lume__internal--hover', handleInternalHover);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const {
const chartID = inject<string>('chartID');
const { busEmit } = useEvents(emit, chartID);
const { emitInternalEvent } = useEvents(emit, chartID);
const { groupedData } = useBarMixin(data);
Expand Down Expand Up @@ -122,7 +122,7 @@ async function handleInternalHover(groupIndex: number) {
emit('lume__internal--hover', groupIndex);
if (__VUE_VERSION__ === 2) {
await busEmit('lume__internal--hover', groupIndex);
emitInternalEvent('lume__internal--hover', groupIndex);
}
}
</script>
49 changes: 19 additions & 30 deletions packages/lib/src/composables/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,36 @@ const CHART_EVENTS = [
'tooltip-opened',
'tooltip-moved',
'tooltip-closed',
];

interface EventBusInstance {
$on: (
event: string | Array<string>,
fn: (...args: Array<unknown>) => void
) => void;
$emit: (event: string, ...args: Array<unknown>) => void;
}

interface EventBusInstanceConstructor {
new (): EventBusInstance;
}

let eventBus: EventBusInstance | null = null;
'group-mouseenter',
'group-mouseleave',
];

// Used to propagate events from the top-most component (needed for Vue 2)
export const useEvents = (
emit: (e: string, p: unknown) => void,
chartID: string
) => {
async function initEventBus() {
if (__VUE_VERSION__ === 3) return null;

const Vue = (await import('vue')).default;
eventBus = new (Vue as unknown as EventBusInstanceConstructor)();
function emitInternalEvent(eventName: string, ...args: Array<unknown>) {
if (__VUE_VERSION__ === 2) {
document.dispatchEvent(
new CustomEvent(`${chartID}_${eventName}`, {
detail: [...args],
})
);
}
}

async function busEmit(eventName: string, ...args: Array<unknown>) {
if (!eventBus) await initEventBus();

eventBus.$emit(`${chartID}_${eventName}`, ...args);
}

async function busListen(
function listenInternalEvent(
eventName: string,
listener: (...args: Array<unknown>) => void
) {
if (!eventBus) await initEventBus();

eventBus.$on(`${chartID}_${eventName}`, listener);
if (__VUE_VERSION__ === 2) {
document.addEventListener(
`${chartID}_${eventName}`,
(e: CustomEventInit) => listener(e.detail[0])
);
}
}

const componentEventPropagator =
Expand All @@ -81,5 +70,5 @@ export const useEvents = (
}, {})
: {};

return { componentEventPropagator, busEmit, busListen };
return { componentEventPropagator, emitInternalEvent, listenInternalEvent };
};
3 changes: 3 additions & 0 deletions packages/lib/src/docs/storybook-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const CHART_EVENTS = [
'tooltip-closed',
'tooltip-mouseenter',
'tooltip-mouseleave',

'group-mouseenter',
'group-mouseleave',
];

export const COLOR_CLASS_MAP = {
Expand Down
8 changes: 7 additions & 1 deletion packages/lib/src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,16 @@ export interface TooltipEvents {
(e: 'tooltip-mouseleave'): void;
}

export interface GroupEvents {
(e: 'group-mouseenter', index: number): void;
(e: 'group-mouseleave', index: number): void;
}

export type ChartEmits = AxisEvents &
AlluvialDiagramEvents &
BarChartEvents &
ChartEvents &
LegendEvents &
LineChartEvents &
TooltipEvents;
TooltipEvents &
GroupEvents;
5 changes: 5 additions & 0 deletions packages/vue2/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ import { getDecorators } from 'storybook-utils/preview';
export { parameters } from 'storybook-utils/preview';

export const decorators = getDecorators(2);

// Fixes method "toJSON" is not defined on click event in storybook
// See https://github.com/storybookjs/storybook/issues/14933#issuecomment-920578274
const Vue = (await import('vue')).default;
Vue.prototype.toJSON = () => {};
Loading

0 comments on commit b8677b8

Please sign in to comment.