Skip to content

Commit 0389607

Browse files
Merge pull request #14 from trash-and-fire/ref_to_contaner_and_attributes
provide ref callback and rest spread for dom container
2 parents ef42dfb + cc409b1 commit 0389607

File tree

5 files changed

+140
-7
lines changed

5 files changed

+140
-7
lines changed

src/demo/app.svelte

+9-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,15 @@
414414
{#if components}
415415
<fieldset name="chart-component">
416416
<legend>Chart component:</legend>
417-
<Chart {...(params.options ?? {})} ref={reference}>
417+
<Chart
418+
{...(params.options ?? {})}
419+
ref={reference}
420+
container={{
421+
class: 'chart',
422+
// eslint-disable-next-line no-console
423+
ref: console.log
424+
}}
425+
>
418426
{#if mainProps.type === 'Area' }
419427
<AreaSeries
420428
{...(mainProps.options ?? {})}

src/package/components/__tests__/chart.ts

+83
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,87 @@ describe('Chart component', () => {
103103

104104
expect(CHART_ACTION_OBJECT.destroy).toHaveBeenCalledTimes(1);
105105
});
106+
107+
it('should handle dom reference', async () => {
108+
const { default: Chart } = await import('../chart.svelte');
109+
const ref = jest.fn<HTMLElement | null, []>();
110+
const target = document.createElement('div');
111+
const component = new Chart({
112+
target,
113+
props: {
114+
width: 100,
115+
height: 100,
116+
container: {
117+
ref,
118+
}
119+
},
120+
});
121+
122+
await tick();
123+
124+
expect(ref).toHaveBeenCalledTimes(1);
125+
expect(ref).toHaveBeenLastCalledWith(target.firstElementChild);
126+
127+
component.$set({
128+
width: 100,
129+
height: 100,
130+
container: {
131+
ref,
132+
}
133+
});
134+
135+
await tick();
136+
137+
expect(ref).toHaveBeenCalledTimes(1);
138+
139+
const nextRef = jest.fn<HTMLElement | null, []>();
140+
component.$set({
141+
width: 100,
142+
height: 100,
143+
container: {
144+
ref: nextRef,
145+
}
146+
});
147+
148+
await tick();
149+
150+
expect(ref).toHaveBeenCalledTimes(2);
151+
expect(ref).toHaveBeenLastCalledWith(null);
152+
153+
expect(nextRef).toHaveBeenCalledTimes(1);
154+
expect(nextRef).toHaveBeenLastCalledWith(target.firstElementChild);
155+
156+
component.$destroy();
157+
158+
await tick();
159+
160+
expect(ref).toHaveBeenCalledTimes(2);
161+
162+
expect(nextRef).toHaveBeenCalledTimes(2);
163+
expect(nextRef).toHaveBeenLastCalledWith(null);
164+
});
165+
166+
it('should spread attributes to dom container', async () => {
167+
const { default: Chart } = await import('../chart.svelte');
168+
169+
const target = document.createElement('div')
170+
new Chart({
171+
target,
172+
props: {
173+
width: 100,
174+
height: 100,
175+
container: {
176+
class: 'container',
177+
id: 'container',
178+
'data-test': 'container',
179+
}
180+
},
181+
});
182+
183+
await tick();
184+
185+
expect(target.firstElementChild.className).toBe('container');
186+
expect(target.firstElementChild.id).toBe('container');
187+
expect(target.firstElementChild.getAttribute('data-test')).toBe('container');
188+
});
106189
})

src/package/components/chart.interface.ts

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import type {Reference} from '../types';
88

99
export interface $$PROPS extends DeepPartial<ChartOptions> {
1010
ref?: Reference<IChartApi>;
11+
container?: {
12+
ref?: Reference<HTMLElement>;
13+
class?: string;
14+
id?: string;
15+
}
1116
}
1217

1318
export interface $$EVENTS {

src/package/components/chart.svelte

+20-6
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
import type {Reference} from '../types';
77
88
import {createEventDispatcher} from 'svelte';
9+
import {element} from './internal/element';
910
import ContextProvider from './internal/context-provider.svelte';
1011
import {chart} from '../index';
1112
1213
const dispatch = createEventDispatcher<$$EVENTS>();
1314
15+
export let container: $$PROPS['container'] = undefined;
16+
1417
/** Height of the chart */
1518
export let width: $$PROPS['width'] = 0;
1619
/** Width of the chart */
@@ -67,6 +70,13 @@
6770
}
6871
})(ref);
6972
73+
// Dom container attributes
74+
let attrs: $$PROPS['container'] = {};
75+
$: {
76+
attrs = Object.assign({}, container);
77+
delete attrs.ref;
78+
}
79+
7080
function handleCrosshairMove(params: MouseEventParams): void {
7181
dispatch('crosshairMove', params);
7282
}
@@ -76,12 +86,16 @@
7686
}
7787
</script>
7888

79-
<div use:chart={{
80-
options,
81-
onCrosshairMove: handleCrosshairMove,
82-
onClick: handleClick,
83-
reference: handleReference,
84-
}}>
89+
<div
90+
{...attrs}
91+
use:element={container?.ref}
92+
use:chart={{
93+
options,
94+
onCrosshairMove: handleCrosshairMove,
95+
onClick: handleClick,
96+
reference: handleReference,
97+
}}
98+
>
8599
{#if reference !== null}
86100
<ContextProvider value={reference}><slot/></ContextProvider>
87101
{/if}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type {ActionResult, Reference} from '../../types';
2+
3+
export function element(
4+
node: HTMLElement,
5+
reference: Reference<HTMLElement> | undefined
6+
): ActionResult<Reference<HTMLElement> | undefined> {
7+
let ref = reference;
8+
ref?.(node);
9+
10+
return {
11+
update(nextReference: Reference<HTMLElement | null> | undefined): void {
12+
if (nextReference === ref) {
13+
return;
14+
}
15+
ref?.(null);
16+
ref = nextReference;
17+
ref?.(node);
18+
},
19+
destroy(): void {
20+
ref?.(null);
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)