Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.18
15 changes: 0 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"react-redux": "^7.2.4",
"react-text-loop": "^2.3.0",
"react-vk": "^5.0.2",
"react-yandex-maps": "^4.6.0",
"react-youtube": "^7.13.1",
"redux": "^4.1.0",
"redux-thunk": "^2.3.0",
Expand Down
3 changes: 1 addition & 2 deletions src/ScrollAnimationCustom/ScrollAnimationCustom.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import React, { useMemo, useEffect, useRef } from 'react';
import { Box } from '@quarkly/widgets';
import { useOverrides } from '@quarkly/components';
import ComponentNotice from '../ComponentNotice';
import { isEmptyChildren } from '../utils';
import { isEmptyChildren, useScript } from '../utils';
import { propInfo, defaultProps, overrides } from './props';
import useScript from './hooks/useScript';
import makeAnim from './utils/makeAnim';

const duration = 1000; // Totally arbitrary!
Expand Down
13 changes: 13 additions & 0 deletions src/YandexMap/Control.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useEffect } from 'react';
import { toggleControl } from './utils';

// hack to not break the react hooks rule
function Control({ map, control, enabled }) {
useEffect(() => {
toggleControl(map.current, control, enabled);
}, [map, control, enabled]);

return null;
}

export default Control;
109 changes: 50 additions & 59 deletions src/YandexMap/YandexMap.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import React, { useRef } from 'react';
import useResizeObserver from '@react-hook/resize-observer';
import React, { useEffect, useRef } from 'react';
import { Box } from '@quarkly/widgets';

import {
YMaps,
Map,
ZoomControl,
RulerControl,
TrafficControl,
TypeSelector,
SearchControl,
GeolocationControl,
FullscreenControl,
} from 'react-yandex-maps';
import { useDebounce } from '../utils';
import { useDebounce, useScript } from '../utils';
import { propInfo, defaultProps } from './props';
import withPropsTransformer from '../utils/withPropsTransformer';
import { getInitialControls } from './utils';
import Control from './Control';

const YandexMap = ({
apikey,
Expand All @@ -24,59 +14,60 @@ const YandexMap = ({
longitudeCenter,
trafficControl,
rulerControl,
typeSelectorContol,
typeSelectorContol: typeSelector,
searchControl,
geolocationControl,
fullscreenControl,
...props
}) => {
const ymapRef = useRef({});
const containerRef = useRef(null);
const map = useRef(null);

const mapRef = useRef(null);
const dapiKey = useDebounce(apikey, 2000);
const key = useDebounce(
`yandexmap${zoomValue}${latitudeCenter}${longitudeCenter}`,
2000
);

useResizeObserver(containerRef, () =>
ymapRef.current?.container?.fitToViewport()
const ns = `ymaps_${dapiKey}`;

const { ready } = useScript(
`https://api-maps.yandex.ru/2.1?apikey=${dapiKey}&lang=ru_RU&ns=${ns}`
Comment thread
Maks1mS marked this conversation as resolved.
Outdated
);

const controls = {
trafficControl,
rulerControl,
typeSelector,
searchControl,
geolocationControl,
fullscreenControl,
zoomControl,
};

useEffect(() => {
if (ready) {
window[ns].ready(() => {
const ymaps = window[ns];

if (!map.current) {
map.current = new ymaps.Map(mapRef.current, {
Comment thread
Maks1mS marked this conversation as resolved.
center: [latitudeCenter, longitudeCenter],
zoom: zoomValue,
controls: getInitialControls(controls),
});
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ready]);

useEffect(() => {
map.current?.setCenter([latitudeCenter, longitudeCenter], zoomValue);
}, [latitudeCenter, longitudeCenter, zoomValue]);

return (
<Box ref={containerRef} height="250px" display="block" {...props}>
<YMaps key={dapiKey} query={{ apikey: dapiKey }}>
<Map
key={key}
height="100%"
width="100%"
defaultState={{
center: [
parseFloat(latitudeCenter),
parseFloat(longitudeCenter),
],
zoom: parseInt(zoomValue, 10),
}}
options={{
autoFitToViewport: 'allways',
}}
defaultOptions={{
autoFitToViewport: 'allways',
}}
instanceRef={ymapRef}
>
{fullscreenControl && <FullscreenControl />}
{geolocationControl && <GeolocationControl />}
{zoomControl && <ZoomControl />}
{trafficControl && <TrafficControl />}
{rulerControl && <RulerControl />}
{typeSelectorContol && <TypeSelector />}
{searchControl && (
<SearchControl
options={{ provider: 'yandex#search' }}
/>
)}
</Map>
</YMaps>
<Box height="250px" display="block" {...props}>
<Box height="100%" ref={mapRef} />
Comment thread
Maks1mS marked this conversation as resolved.
Outdated
{Object.entries(controls).map(([key, value]) => (
<Control key={key} map={map} control={key} enabled={value} />
))}
</Box>
);
};
Expand All @@ -91,4 +82,4 @@ Object.assign(YandexMap, {
defaultProps,
});

export default YandexMap;
export default withPropsTransformer(YandexMap);
12 changes: 12 additions & 0 deletions src/YandexMap/YandexMap.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,16 @@ export default {

export const StoryDefault = (props) => <YandexMap {...props} />;

export const StoryMultiple = (props) => (
<>
<YandexMap {...props} />
<YandexMap {...props} />
<YandexMap {...props} />
<YandexMap {...props} />
<YandexMap {...props} />
<YandexMap {...props} />
<YandexMap {...props} />
</>
);

StoryDefault.storyName = 'Default';
7 changes: 7 additions & 0 deletions src/YandexMap/props/propsDefault.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ export default {
latitudeCenter: 40.714599,
longitudeCenter: -74.002791,
zoomValue: 9,
searchControl: false,
fullscreenControl: false,
geolocationControl: false,
zoomControl: false,
trafficControl: false,
rulerControl: false,
typeSelectorContol: false,
};
4 changes: 2 additions & 2 deletions src/YandexMap/props/propsInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default {
ru: 'Широта',
},
control: 'input',
type: 'text',
type: 'number',
category: 'Center',
weight: 0.5,
},
Expand All @@ -38,7 +38,7 @@ export default {
ru: 'Долгота',
},
control: 'input',
type: 'text',
type: 'number',
category: 'Center',
weight: 0.5,
},
Expand Down
23 changes: 23 additions & 0 deletions src/YandexMap/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export function getInitialControls(controlsObject) {
const controls = [];

Object.entries(controlsObject).forEach(([key, value]) => {
if (value) controls.push(key);
});

return controls;
}

export function toggleControls(map, controlsObject) {
Object.entries(controlsObject).forEach(([key, value]) =>
toggleControl(map, key, value)
);
}

export function toggleControl(map, key, value) {
if (value) {
map?.controls?.add(key);
} else {
map?.controls?.remove(key);
}
}
1 change: 1 addition & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { default as useDebounce } from './useDebounce';
export { default as useDebouncedCallback } from './useDebouncedCallback';
export { default as useUpdateEffect } from './useUpdateEffect';
export { default as useUniqueId } from './useUniqueId';
export { default as useScript } from './useScript';

export { default as isString } from './isString';

Expand Down
File renamed without changes.
46 changes: 46 additions & 0 deletions src/utils/withPropsTransformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import getNumber from './getNumber';

const numberTransformer = (v, d) => getNumber(v, d);
const boolTransformer = (v) => {
return !!v;
};

const emptyTransformer = (v) => {
return v;
};

const getTransformer = (prop) => {
if (prop.type === 'number') {
return numberTransformer;
}

if (prop.type === 'checkbox') {
return boolTransformer;
}

return emptyTransformer;
};

const withPropsTransformer = (Component) => {
const { propInfo, defaultProps } = Component;

function WrappedComponent(props) {
const newProps = {};

Object.keys(propInfo).forEach((p) => {
if (p in props) {
const transformer = getTransformer(propInfo[p]);
newProps[p] = transformer(props[p], defaultProps[p], {
propInfo: propInfo[p],
});
}
}, []);

return <Component {...props} {...newProps} />;
}

return Object.assign(WrappedComponent, Component);
};

export default withPropsTransformer;