From 1fd936f97042e75cce9926dae82e9560689cace1 Mon Sep 17 00:00:00 2001 From: Aleem Isiaka Date: Fri, 29 Dec 2023 17:34:52 +0100 Subject: [PATCH] add complete support for hmap --- package.json | 1 + src/components/Map/Map.tsx | 26 +++++++------ src/components/Platform/index.tsx | 8 ++-- src/components/index.ts | 1 + src/components/libs/buildMap.ts | 40 ++++++++------------ src/components/libs/initInteraction.ts | 23 +++++++++++ src/components/libs/initInteractionStyles.ts | 8 ++++ src/components/libs/initPlatform.ts | 2 +- src/contexts/platform.tsx | 4 +- src/index.tsx | 3 +- stories/Map.stories.tsx | 31 +++++++++++++-- stories/Platform.stories.tsx | 36 ++++++++++++++++++ stories/Thing.stories.tsx | 28 -------------- stories/useHPlatform.stories.tsx | 36 ++++++++++++++++++ tsconfig.json | 3 ++ yarn.lock | 5 +++ 16 files changed, 180 insertions(+), 75 deletions(-) create mode 100644 src/components/libs/initInteraction.ts create mode 100644 src/components/libs/initInteractionStyles.ts create mode 100644 stories/Platform.stories.tsx delete mode 100644 stories/Thing.stories.tsx create mode 100644 stories/useHPlatform.stories.tsx diff --git a/package.json b/package.json index dd4b388..06567c5 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@storybook/addons": "^7.6.5", "@storybook/react": "^7.6.5", "@storybook/react-webpack5": "^7.6.5", + "@types/heremaps": "^3.1.14", "@types/lodash.merge": "^4.6.9", "@types/react": "^18.2.45", "@types/react-dom": "^18.2.17", diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx index 4656a28..d93b721 100644 --- a/src/components/Map/Map.tsx +++ b/src/components/Map/Map.tsx @@ -53,7 +53,6 @@ export const HMap = (props: IHMapProps) => { props.options ); - const buildResult = buildMap(platformState.platform, mergedOptions); setMapState(buildResult); @@ -74,16 +73,19 @@ export const HMap = (props: IHMapProps) => { const h = window.H; return ( - -
- {typeof h === 'undefined' && !options && loading} - {typeof h === 'object' && options && children} -
-
+ // only render map provider when there is a platform state + platformState.platform && ( + +
+ {typeof h === 'undefined' && !options && loading} + {typeof h === 'object' && options && children} +
+
+ ) ); }; diff --git a/src/components/Platform/index.tsx b/src/components/Platform/index.tsx index d60d961..925cf86 100644 --- a/src/components/Platform/index.tsx +++ b/src/components/Platform/index.tsx @@ -11,7 +11,7 @@ export interface IHPlatform { export interface IHPlatformState { options?: DefaultOptionsType; - platform?: any; + platform: H.service.Platform | null; reInitMap?: () => void; } @@ -36,7 +36,7 @@ export const HPlatform = (props: IHPlatform) => { const [platformState, setPlatformState] = useState({ reInitMap: initilizePlatform, - platform: {}, + platform: null, }); useEffect(() => { @@ -45,10 +45,10 @@ export const HPlatform = (props: IHPlatform) => { }, [platformState.options]); const { platform, options } = platformState; - console.log({ ops: options, platform }); + return ( - {platform?.a == options?.apikey && + {typeof platform?.setBaseUrl == 'function' && (options?.app_code || options?.apikey) && props.children} diff --git a/src/components/index.ts b/src/components/index.ts index f251395..30646fd 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1 +1,2 @@ export * from './Map'; +export * from './Platform'; \ No newline at end of file diff --git a/src/components/libs/buildMap.ts b/src/components/libs/buildMap.ts index 950f599..190ea5a 100644 --- a/src/components/libs/buildMap.ts +++ b/src/components/libs/buildMap.ts @@ -11,32 +11,27 @@ import { } from './defaults'; import { IHMapOptions, IHMapOptionsMerged } from '../Map'; import { validateMapType } from './validateMapType'; +import { initInteractionStyles } from './initInteractionStyles'; const initMap = ( container: React.RefObject, mapLayer: any, mapOptions: IHMapOptions ) => { - // @ts-ignore - const h = window.H; - // Instantiate (and display) a map object: return ( - container.current && new h.Map(container.current, mapLayer, mapOptions) + container.current && new H.Map(container.current, mapLayer, mapOptions) ); }; export const initInteraction = ( - map: any, + map: H.Map, interactive: boolean, useEvents: boolean, events: typeof mapEvents ) => { - console.log(interactive, useEvents, map); - // @ts-ignore - const h = window.H; const behavior = interactive - ? new h.mapevents.Behavior(new h.mapevents.MapEvents(map)) + ? new H.mapevents.Behavior(new H.mapevents.MapEvents(map)) : null; if (useEvents && interactive) { for (const type in events) { @@ -61,10 +56,8 @@ export const initDefaultUI = ( throw new Error('includeUI must be set to true to initialize default UI'); } - // @ts-ignore - const h = window.H; // Create the default UI components - return h.ui.UI.createDefault(map, platform.createDefaultLayers(), uiLang); + return H.ui.UI.createDefault(map, platform.createDefaultLayers(), uiLang); }; export const buildMap = ( @@ -76,10 +69,10 @@ export const buildMap = ( useEvents, mapEvents, interactive, - // includeUI, + includeUI, mapType, mapOptions, - // uiLang, + uiLang, container, build, } = options; @@ -111,18 +104,17 @@ export const buildMap = ( useEvents, mapEvents ); - // if (includeUI) { - // retObject.ui = initDefaultUI(platform, retObject.map, includeUI, uiLang); - // } + if (includeUI) { + retObject.ui = initDefaultUI( + platform, + retObject.map, + includeUI, + uiLang + ); + } // Adds the grabbing to the document - // initInteractionStyles(); + initInteractionStyles(); } - } else { - // ret.createMap = initMap; - // ret.createPlatform = initPlatform; - // ret.createInteraction = initInteraction; - // ret.createDefaultUI = initDefaultUI; - // ret.createInteractionStyles = initInteractionStyles; } return retObject; }; diff --git a/src/components/libs/initInteraction.ts b/src/components/libs/initInteraction.ts new file mode 100644 index 0000000..2aadefb --- /dev/null +++ b/src/components/libs/initInteraction.ts @@ -0,0 +1,23 @@ +import { mapEventTypes, mapEvents } from './defaults'; + +export const initInteraction = ( + map: H.Map, + interactive: boolean, + useEvents: boolean, + events: typeof mapEvents +) => { + let behavior = interactive + ? new H.mapevents.Behavior(new H.mapevents.MapEvents(map)) + : null; + if (useEvents && interactive) { + for (const type in events) { + if (events.hasOwnProperty(type)) { + const callback = events[type as mapEventTypes]; + if (callback && typeof callback === 'function') { + map.addEventListener(type, callback); + } + } + } + } + return behavior; +}; diff --git a/src/components/libs/initInteractionStyles.ts b/src/components/libs/initInteractionStyles.ts new file mode 100644 index 0000000..861cbae --- /dev/null +++ b/src/components/libs/initInteractionStyles.ts @@ -0,0 +1,8 @@ +export const initInteractionStyles = () => { + const style = document.createElement('style'); + const css = `.grab = {cursor: move;cursor: grab;cursor: -moz-grab;cursor: -webkit-grab;}.grabbing{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}`; + style.type = 'text/css'; + style.appendChild(document.createTextNode(css)); + const head = document.head || document.getElementsByTagName('head')[0]; + head.appendChild(style); +}; diff --git a/src/components/libs/initPlatform.ts b/src/components/libs/initPlatform.ts index 9f0a344..f8584d0 100644 --- a/src/components/libs/initPlatform.ts +++ b/src/components/libs/initPlatform.ts @@ -10,5 +10,5 @@ export const initHPlatform = (options?: DefaultOptionsType) => { if (typeof h === 'undefined' || !h.service) { throw new Error('Here Map JavaScript files are not loaded.'); } - return new h.service.Platform({ apikey }); + return new h.service.Platform({ apikey: String(apikey) }); }; diff --git a/src/contexts/platform.tsx b/src/contexts/platform.tsx index 8b11246..74dc9c1 100644 --- a/src/contexts/platform.tsx +++ b/src/contexts/platform.tsx @@ -5,4 +5,6 @@ import { createContext } from 'react'; import { IHPlatformState } from '../components/Platform'; // create a hook for the platform context -export const PlatformContext = createContext({}); +export const PlatformContext = createContext({ + platform: null, +}); diff --git a/src/index.tsx b/src/index.tsx index 5bc75c1..260722a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,7 +10,8 @@ export interface Props extends HTMLAttributes { // Please do not use types off of a default export module or else Storybook Docs will suffer. // see: https://github.com/storybookjs/storybook/issues/9556 -export const Thing: FC = () => { +export const Thing: FC = props => { + console.log({ props }); const renderHereComponents = useHPlatform( { appId: 'EF8K24SYpkpXUO9rkbfA', diff --git a/stories/Map.stories.tsx b/stories/Map.stories.tsx index e989ed0..9902c6c 100644 --- a/stories/Map.stories.tsx +++ b/stories/Map.stories.tsx @@ -1,17 +1,40 @@ import React from 'react'; import { Meta, Story } from '@storybook/react'; -import { HMap, IHMapProps } from '../src'; - +import { HMap, IHMapProps, useHPlatform } from '../src'; +const appId = 'EF8K24SYpkpXUO9rkbfA'; +const apiKey = 'TIAGlD6jic7l9Aa8Of8IFxo3EUemmcZlHm_agfAm6Ew'; const meta: Meta = { title: 'HMap', component: HMap, argTypes: {}, - parameters: {}, + args: { + options: { + center: { lat: 52.5321472, lng: 13.3935785 }, + }, + style: { + height: '480px', + width: '100%', + }, + useEvents: true, + }, }; export default meta; -const Template: Story = args => ; +const Template: Story = args => { + const renderHMapComponents = useHPlatform( + { + appId, + apiKey, + includeUI: true, + includePlaces: false, + version: 'v3/3.1', + interactive: true, + }, + + ); + return renderHMapComponents; +}; // By passing using the Args format for exported stories, you can control the props for a component for reuse in a test // https://storybook.js.org/docs/react/workflows/unit-testing diff --git a/stories/Platform.stories.tsx b/stories/Platform.stories.tsx new file mode 100644 index 0000000..ce6c107 --- /dev/null +++ b/stories/Platform.stories.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { HPlatform, IHPlatform } from '../src/'; +const appId = 'EF8K24SYpkpXUO9rkbfA'; +const apiKey = 'TIAGlD6jic7l9Aa8Of8IFxo3EUemmcZlHm_agfAm6Ew'; +const meta: Meta = { + title: 'HPlatform JSX', + component: HPlatform, + args: { + options: { + appId, + apiKey, + includeUI: true, + includePlaces: false, + version: 'v3/3.1', + interactive: true, + }, + children: <>Overriden Children If all went well, yaay! 🙂 , + }, +}; + +export default meta; + +const Template: Story = args => { + return ( + + {args.children || 'Render Anything'} + + ); +}; + +// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test +// https://storybook.js.org/docs/react/workflows/unit-testing +export const Default = Template.bind({}); + +Default.args = {}; diff --git a/stories/Thing.stories.tsx b/stories/Thing.stories.tsx deleted file mode 100644 index 3e9f7e6..0000000 --- a/stories/Thing.stories.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { Meta, Story } from '@storybook/react'; -import { Thing, Props } from '../src'; - -const meta: Meta = { - title: 'Welcome', - component: Thing, - argTypes: { - children: { - control: { - type: 'text', - }, - }, - }, - parameters: { - controls: { expanded: true }, - }, -}; - -export default meta; - -const Template: Story = args => ; - -// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test -// https://storybook.js.org/docs/react/workflows/unit-testing -export const Default = Template.bind({}); - -Default.args = {}; diff --git a/stories/useHPlatform.stories.tsx b/stories/useHPlatform.stories.tsx new file mode 100644 index 0000000..6704069 --- /dev/null +++ b/stories/useHPlatform.stories.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { HPlatform, IHPlatform, useHPlatform } from '../src'; +import { ILoadHMapOptions } from '../src/components/libs/loadHMap'; +const appId = 'EF8K24SYpkpXUO9rkbfA'; +const apiKey = 'TIAGlD6jic7l9Aa8Of8IFxo3EUemmcZlHm_agfAm6Ew'; +const meta: Meta = { + title: 'useHPlatform', + component: HPlatform, + args: { + options: { + appId, + apiKey, + includeUI: true, + includePlaces: false, + version: 'v3/3.1', + interactive: true, + }, + children: <>Overriden Children If all went well, yaay! 🙂 , + }, +}; + +export default meta; + +const Template: Story = args => { + return useHPlatform( + { ...args }, + <>Render Some Children Here, if Platform did load successfully + ); +}; + +// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test +// https://storybook.js.org/docs/react/workflows/unit-testing +export const Default = Template.bind({}); + +Default.args = {}; diff --git a/tsconfig.json b/tsconfig.json index 2c85b2d..98346a9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,5 +31,8 @@ "forceConsistentCasingInFileNames": true, // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc` "noEmit": true, + "typeRoots": [ + "node_modules/@types" + ], } } diff --git a/yarn.lock b/yarn.lock index 0d2b33d..01f741d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3277,6 +3277,11 @@ dependencies: "@types/node" "*" +"@types/heremaps@^3.1.14": + version "3.1.14" + resolved "https://registry.yarnpkg.com/@types/heremaps/-/heremaps-3.1.14.tgz#a3b26b038db05eff7344e6099ecc6a89813e9012" + integrity sha512-jB0VomahI9fJjde6Fwn+nwnDcBFgJNGd4SQSN4pNq0GPImNKJdzgEKO+Ea+uKcWi6iB/ZiWbcpMZqCs3Qu+0QQ== + "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"