Skip to content

Commit 81b98d1

Browse files
author
Savina Shen (Manpower Services Taiwan Co Ltd)
committed
add interactive popup example
1 parent 64a5ead commit 81b98d1

File tree

9 files changed

+178
-9
lines changed

9 files changed

+178
-9
lines changed

src/key.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
import { IAzureMapOptions, AuthenticationType } from 'react-azure-maps';
22

3+
// export const mapOptions: IAzureMapOptions = {
4+
// authOptions: {
5+
// authType: AuthenticationType.anonymous,
6+
// clientId: '2a60774c-f588-423b-b004-56d213773ee6',
7+
// getToken: (resolve, reject) => {
8+
// fetch('https://anonymous-auth.azurewebsites.net/api/GetAccessToken-Prod')
9+
// .then((result) => result.text())
10+
// .then((result) => resolve(result))
11+
// .catch((error) => reject(new Error(`Failed to fetch anon auth token: ${error.message}`)));
12+
// },
13+
// },
14+
// center: [0, 0],
15+
// view: 'Auto',
16+
// };
17+
318
export const mapOptions: IAzureMapOptions = {
419
authOptions: {
5-
authType: AuthenticationType.anonymous,
6-
clientId: '2a60774c-f588-423b-b004-56d213773ee6',
7-
getToken: (resolve, reject) => {
8-
fetch('https://anonymous-auth.azurewebsites.net/api/GetAccessToken-Prod')
9-
.then((result) => result.text())
10-
.then((result) => resolve(result))
11-
.catch((error) => reject(new Error(`Failed to fetch anon auth token: ${error.message}`)));
12-
},
20+
authType: AuthenticationType.subscriptionKey,
21+
subscriptionKey: '013GHvO6nMXUbB0yrRDmgizOaO3tRzevKMzPA6Yl4PeFMPgqFuelJQQJ99AGACrJL3JAArohAAAgAZMPQDp7',
1322
},
1423
center: [0, 0],
1524
view: 'Auto',
File renamed without changes.

src/stories/MapAnnotations/Popup/Popup.tsx renamed to src/stories/MapAnnotations/Popup/Basic/Popup.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { AzureMap, AzureMapsProvider, AzureMapPopup, IAzureMapPopup } from 'react-azure-maps';
2-
import { mapOptions } from '../../../key';
2+
import PopupContent from '../Interactive/PopupContent';
3+
import { mapOptions } from '../../../../key';
34

45
const Popup = ({ isVisible, options }: IAzureMapPopup) => {
56
// use position as argument would be better
@@ -11,6 +12,7 @@ const Popup = ({ isVisible, options }: IAzureMapPopup) => {
1112
isVisible={isVisible}
1213
options={options}
1314
popupContent={<div style={{ padding: '20px' }}>Hello World</div>}
15+
// popupContent={<PopupContent />}
1416
/>
1517
</AzureMap>
1618
</div>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Meta, Source } from '@storybook/blocks';
2+
3+
import * as InteractivePopupStories from './InteractivePopup.stories';
4+
5+
import Popup from './InteractivePopup';
6+
7+
<Meta of={InteractivePopupStories} />
8+
9+
# Popup
10+
A popup is an information window anchored at a specified position on a map.
11+
With **react-azure-maps**, you can quickly customize the `Popup` component with these 3 props:
12+
<Popup isVisible options={{ position: [0, 0] }} />
13+
{/* show basic code */}
14+
15+
<Source code={`
16+
<AzureMapPopup
17+
isVisible
18+
options={{ position: [0, 0] }}
19+
popupContent={<div style={{ padding: '20px' }}>Hello World</div>}
20+
/>
21+
`} />
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
import InteractivePopup from './InteractivePopupExample';
3+
4+
const meta: Meta<typeof InteractivePopup> = {
5+
title: 'Map Annotations/Interactive Popup',
6+
component: InteractivePopup,
7+
args: {
8+
isVisible: true,
9+
options: {
10+
position: [0, 0],
11+
},
12+
},
13+
parameters: {
14+
storySource: {
15+
source: `
16+
import { AzureMap, AzureMapsProvider, AzureMapPopup, IAzureMapPopup } from 'react-azure-maps';
17+
18+
const Popup = () => {
19+
20+
return (
21+
<AzureMapsProvider>
22+
<AzureMap options={your_options}>
23+
<AzureMapPopup
24+
isVisible
25+
options={{ position: [0, 0] }}
26+
popupContent={<div style={{ padding: '20px' }}>Hello World</div>}
27+
/>
28+
</AzureMap>
29+
</AzureMapsProvider>
30+
);
31+
};
32+
`,
33+
},
34+
},
35+
};
36+
37+
export default meta;
38+
39+
type Story = StoryObj<typeof InteractivePopup>;
40+
41+
export const Example: Story = {};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { useContext, useEffect, useState, useRef } from 'react';
2+
import { createRoot } from 'react-dom/client';
3+
import atlas from 'azure-maps-control';
4+
import { IAzureMapsContextProps, MapType, IAzureMapPopup, AzureMapsContext } from 'react-azure-maps';
5+
6+
const InteractivePopup = ({ isVisible, popupContent, options, events }: IAzureMapPopup) => {
7+
const { mapRef } = useContext<IAzureMapsContextProps>(AzureMapsContext);
8+
const containerRef = document.createElement('div');
9+
const root = createRoot(containerRef);
10+
11+
const [popupRef] = useState<atlas.Popup>(new atlas.Popup({ ...options, content: containerRef }));
12+
13+
useCheckRefMount<MapType, boolean>(mapRef, true, (mref) => {
14+
events &&
15+
events.forEach(({ eventName, callback }) => {
16+
mref.events.add(eventName, popupRef, callback);
17+
});
18+
return () => {
19+
mref.popups.remove(popupRef);
20+
};
21+
});
22+
23+
useEffect(() => {
24+
root.render(popupContent);
25+
popupRef.setOptions({
26+
...options,
27+
content: containerRef,
28+
});
29+
if (mapRef && isVisible && !popupRef.isOpen()) {
30+
popupRef.open(mapRef);
31+
}
32+
}, [options, popupContent]);
33+
34+
useEffect(() => {
35+
if (mapRef) {
36+
if (isVisible && !popupRef.isOpen()) {
37+
popupRef.open(mapRef);
38+
} else if (mapRef.popups.getPopups().length && !isVisible && popupRef.isOpen()) {
39+
popupRef.close();
40+
}
41+
}
42+
}, [isVisible]);
43+
44+
return null;
45+
};
46+
47+
function useCheckRefMount<T, T1>(dep: T | null, on: T1 | null, callback: (dep: T, on: T1) => void) {
48+
useEffect(() => {
49+
if (dep && on) {
50+
return callback(dep, on);
51+
}
52+
}, []);
53+
}
54+
55+
export default InteractivePopup;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { AzureMap, AzureMapsProvider, IAzureMapPopup } from 'react-azure-maps';
2+
import { mapOptions } from '../../../../key';
3+
import InteractivePopup from './InteractivePopup';
4+
import PopupContent from './PopupContent';
5+
import { useState } from 'react';
6+
7+
const Popup = ({ isVisible, options }: IAzureMapPopup) => {
8+
const [text, setText] = useState('Hello World');
9+
10+
// use position as argument would be better
11+
return (
12+
<AzureMapsProvider>
13+
<div className="defaultMap sb-unstyled">
14+
<button onClick={() => setText(text + '1')}>Change text</button>
15+
<AzureMap options={mapOptions}>
16+
<InteractivePopup isVisible={isVisible} options={options} popupContent={<PopupContent text={text} />} />
17+
</AzureMap>
18+
</div>
19+
</AzureMapsProvider>
20+
);
21+
};
22+
23+
export default Popup;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const PopupContent = ({ text }: { text: string }) => {
2+
const handleClick = () => {
3+
alert(text);
4+
};
5+
// use position as argument would be better
6+
return (
7+
<div>
8+
<button
9+
style={{ height: '100px', width: '120px', border: '1px', padding: '4px', cursor: 'pointer' }}
10+
onClick={handleClick}
11+
>
12+
Click me
13+
</button>
14+
</div>
15+
);
16+
};
17+
18+
export default PopupContent;

0 commit comments

Comments
 (0)