@d3-maps/react 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE +21 -0
- package/README.md +1 -1
- package/dist/index.d.ts +60 -64
- package/dist/index.iife.js +1 -1
- package/dist/index.js +129 -97
- package/package.json +24 -24
package/LICENCE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Georgii Bukharov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -51,4 +51,4 @@ If you need strict stylesheet ordering, load your global reset/theme styles befo
|
|
|
51
51
|
|
|
52
52
|
## License
|
|
53
53
|
|
|
54
|
-
MIT licensed. Copyright © 2020 Georgii Bukharov. See [
|
|
54
|
+
MIT licensed. Copyright © 2020 Georgii Bukharov. See [LICENSE](./LICENSE) for more details.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@d3-maps/core/index.css";
|
|
2
2
|
import * as react0 from "react";
|
|
3
|
-
import { CSSProperties,
|
|
4
|
-
import { ExtendedFeature, ExtendedFeatureCollection, GeoPath, GeoProjection } from "d3-geo";
|
|
5
|
-
import
|
|
3
|
+
import { CSSProperties, MouseEventHandler, ReactElement, ReactNode, SVGProps } from "react";
|
|
4
|
+
import { ExtendedFeature, ExtendedFeatureCollection, GeoGraticuleGenerator, GeoPath, GeoProjection } from "d3-geo";
|
|
5
|
+
import "topojson-client";
|
|
6
6
|
import { D3ZoomEvent, ZoomBehavior } from "d3-zoom";
|
|
7
7
|
|
|
8
8
|
//#region ../core/src/lib/mapObject.d.ts
|
|
@@ -12,7 +12,9 @@ import { D3ZoomEvent, ZoomBehavior } from "d3-zoom";
|
|
|
12
12
|
*/
|
|
13
13
|
declare const mapObjectState: readonly ["default", "hover", "active"];
|
|
14
14
|
type MapObjectState = typeof mapObjectState[number];
|
|
15
|
-
|
|
15
|
+
interface MapObject<TStyle = unknown> {
|
|
16
|
+
styles?: Partial<Record<MapObjectState, TStyle>>;
|
|
17
|
+
}
|
|
16
18
|
//#endregion
|
|
17
19
|
//#region ../core/src/lib/feature.d.ts
|
|
18
20
|
/**
|
|
@@ -24,11 +26,8 @@ type MapFeature$1 = (ExtendedFeature & Record<string, unknown>) | ExtendedFeatur
|
|
|
24
26
|
/**
|
|
25
27
|
* Shared props contract for a single rendered feature.
|
|
26
28
|
*/
|
|
27
|
-
interface MapFeatureProps$1<TStyle = unknown> {
|
|
29
|
+
interface MapFeatureProps$1<TStyle = unknown> extends MapObject<TStyle> {
|
|
28
30
|
data: MapFeature$1;
|
|
29
|
-
styles?: MapObjectStyles$1<TStyle>;
|
|
30
|
-
fill?: string;
|
|
31
|
-
stroke?: string;
|
|
32
31
|
}
|
|
33
32
|
//#endregion
|
|
34
33
|
//#region ../../node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index.d.ts
|
|
@@ -367,7 +366,6 @@ type ModifierArgs<P$1 extends unknown[]> = P$1 extends [infer Only] ? Only exten
|
|
|
367
366
|
type MethodsToModifiers<T extends object> = { [K in OwnKeys<T> as Extract<T[K], AnyFn> extends never ? never : HasArgs<Extract<T[K], AnyFn>> extends true ? K : never]?: ModifierArgs<Extract<SetterArgs<Extract<T[K], AnyFn>>, unknown[]>> };
|
|
368
367
|
//#endregion
|
|
369
368
|
//#region ../core/src/lib/map.d.ts
|
|
370
|
-
type MapMesh$1 = ReturnType<typeof mesh>;
|
|
371
369
|
type MapData = ExtendedFeatureCollection | Topology;
|
|
372
370
|
type DataTransformer = (features: MapFeature$1[]) => MapFeature$1[];
|
|
373
371
|
/**
|
|
@@ -419,20 +417,28 @@ interface MapContext {
|
|
|
419
417
|
height: number;
|
|
420
418
|
projection?: GeoProjection;
|
|
421
419
|
features: MapFeature$1[];
|
|
422
|
-
mesh?: MapMesh$1;
|
|
423
420
|
path: GeoPath;
|
|
424
|
-
renderPath: (feature: MapFeature$1) => ReturnType<GeoPath>;
|
|
425
421
|
renderMesh: () => ReturnType<GeoPath>;
|
|
426
422
|
}
|
|
427
423
|
//#endregion
|
|
424
|
+
//#region ../core/src/lib/graticule.d.ts
|
|
425
|
+
/**
|
|
426
|
+
* Extra graticule generator method calls to apply before rendering.
|
|
427
|
+
*
|
|
428
|
+
* Uses d3-geo `geoGraticule()` setter method names as keys.
|
|
429
|
+
* Example: `{ step: [[10, 10]], precision: 2.5 }`
|
|
430
|
+
*
|
|
431
|
+
* @see https://d3js.org/d3-geo/shape#geoGraticule
|
|
432
|
+
*/
|
|
433
|
+
interface GraticuleConfig extends MethodsToModifiers<GeoGraticuleGenerator> {}
|
|
434
|
+
//#endregion
|
|
428
435
|
//#region ../core/src/lib/marker.d.ts
|
|
429
436
|
type MapMarkerCoordinates = [number, number];
|
|
430
437
|
/**
|
|
431
438
|
* Shared props contract for marker layers.
|
|
432
439
|
*/
|
|
433
|
-
interface MapMarkerProps$1<TStyle = unknown> {
|
|
440
|
+
interface MapMarkerProps$1<TStyle = unknown> extends MapObject<TStyle> {
|
|
434
441
|
coordinates?: MapMarkerCoordinates;
|
|
435
|
-
styles?: MapObjectStyles$1<TStyle>;
|
|
436
442
|
}
|
|
437
443
|
//#endregion
|
|
438
444
|
//#region ../core/src/lib/zoom.d.ts
|
|
@@ -478,63 +484,48 @@ interface MapFeatureProps extends MapFeatureProps$1<CSSProperties>, Omit<SVGProp
|
|
|
478
484
|
declare function MapFeature({
|
|
479
485
|
data,
|
|
480
486
|
styles,
|
|
481
|
-
fill,
|
|
482
|
-
stroke,
|
|
483
487
|
onMouseEnter,
|
|
484
488
|
onMouseLeave,
|
|
485
489
|
onMouseDown,
|
|
486
490
|
onMouseUp,
|
|
487
|
-
onClick,
|
|
488
|
-
onFocus,
|
|
489
|
-
onBlur,
|
|
490
491
|
...pathProps
|
|
491
492
|
}: MapFeatureProps): ReactElement | null;
|
|
492
493
|
//#endregion
|
|
493
|
-
//#region src/hooks/useMapObject.d.ts
|
|
494
|
-
type MapObjectStyle = CSSProperties;
|
|
495
|
-
type MapObjectStyles = MapObjectStyles$1<MapObjectStyle>;
|
|
496
|
-
interface UseMapObjectOptions<TElement extends Element> {
|
|
497
|
-
styles?: MapObjectStyles;
|
|
498
|
-
onMouseEnter?: MouseEventHandler<TElement>;
|
|
499
|
-
onMouseLeave?: MouseEventHandler<TElement>;
|
|
500
|
-
onMouseDown?: MouseEventHandler<TElement>;
|
|
501
|
-
onMouseUp?: MouseEventHandler<TElement>;
|
|
502
|
-
onClick?: MouseEventHandler<TElement>;
|
|
503
|
-
onFocus?: FocusEventHandler<TElement>;
|
|
504
|
-
onBlur?: FocusEventHandler<TElement>;
|
|
505
|
-
}
|
|
506
|
-
interface UseMapObjectResult<TElement extends Element> {
|
|
507
|
-
computedStyle: MapObjectStyle | undefined;
|
|
508
|
-
onMouseEnter: MouseEventHandler<TElement>;
|
|
509
|
-
onMouseLeave: MouseEventHandler<TElement>;
|
|
510
|
-
onMouseDown: MouseEventHandler<TElement>;
|
|
511
|
-
onMouseUp: MouseEventHandler<TElement>;
|
|
512
|
-
onClick: MouseEventHandler<TElement>;
|
|
513
|
-
onFocus: FocusEventHandler<TElement>;
|
|
514
|
-
onBlur: FocusEventHandler<TElement>;
|
|
515
|
-
}
|
|
516
|
-
declare function useMapObject<TElement extends Element>(options: UseMapObjectOptions<TElement>): UseMapObjectResult<TElement>;
|
|
517
|
-
//#endregion
|
|
518
494
|
//#region src/components/MapFeatures.d.ts
|
|
519
495
|
interface MapFeaturesRenderProps {
|
|
520
496
|
features: MapFeature$1[];
|
|
521
497
|
}
|
|
522
498
|
type MapFeaturesChildren = ReactNode | ((props: MapFeaturesRenderProps) => ReactNode);
|
|
523
|
-
|
|
499
|
+
type MapFeaturesElementProps = Omit<SVGProps<SVGGElement>, 'children'>;
|
|
500
|
+
interface MapFeaturesProps extends MapFeaturesElementProps, MapObject<CSSProperties> {
|
|
524
501
|
idKey?: string;
|
|
525
|
-
fill?: string;
|
|
526
|
-
stroke?: string;
|
|
527
|
-
styles?: MapObjectStyles;
|
|
528
502
|
children?: MapFeaturesChildren;
|
|
529
503
|
}
|
|
530
504
|
declare function MapFeatures({
|
|
531
505
|
idKey,
|
|
532
|
-
fill,
|
|
533
|
-
stroke,
|
|
534
506
|
styles,
|
|
535
|
-
children
|
|
507
|
+
children,
|
|
508
|
+
...groupProps
|
|
536
509
|
}: MapFeaturesProps): ReactElement;
|
|
537
510
|
//#endregion
|
|
511
|
+
//#region src/components/MapGraticule.d.ts
|
|
512
|
+
interface MapGraticuleProps extends Omit<SVGProps<SVGPathElement>, 'children' | 'd' | 'style' | 'fill'>, MapObject<CSSProperties> {
|
|
513
|
+
config?: GraticuleConfig;
|
|
514
|
+
background?: boolean | string;
|
|
515
|
+
border?: boolean | string;
|
|
516
|
+
}
|
|
517
|
+
declare function MapGraticule({
|
|
518
|
+
config,
|
|
519
|
+
background,
|
|
520
|
+
border,
|
|
521
|
+
styles,
|
|
522
|
+
onMouseEnter,
|
|
523
|
+
onMouseLeave,
|
|
524
|
+
onMouseDown,
|
|
525
|
+
onMouseUp,
|
|
526
|
+
...pathProps
|
|
527
|
+
}: MapGraticuleProps): ReactElement | null;
|
|
528
|
+
//#endregion
|
|
538
529
|
//#region src/components/MapMarker.d.ts
|
|
539
530
|
interface MapMarkerProps extends MapMarkerProps$1<CSSProperties>, Omit<SVGProps<SVGGElement>, 'style'> {}
|
|
540
531
|
declare function MapMarker({
|
|
@@ -545,29 +536,17 @@ declare function MapMarker({
|
|
|
545
536
|
onMouseLeave,
|
|
546
537
|
onMouseDown,
|
|
547
538
|
onMouseUp,
|
|
548
|
-
onClick,
|
|
549
|
-
onFocus,
|
|
550
|
-
onBlur,
|
|
551
539
|
...groupProps
|
|
552
540
|
}: MapMarkerProps): ReactElement;
|
|
553
541
|
//#endregion
|
|
554
542
|
//#region src/components/MapMesh.d.ts
|
|
555
|
-
interface MapMeshProps extends Omit<SVGProps<SVGPathElement>, 'children' | 'd' | 'style'> {
|
|
556
|
-
fill?: string;
|
|
557
|
-
stroke?: string;
|
|
558
|
-
styles?: MapObjectStyles;
|
|
559
|
-
}
|
|
543
|
+
interface MapMeshProps extends Omit<SVGProps<SVGPathElement>, 'children' | 'd' | 'style'>, MapObject<CSSProperties> {}
|
|
560
544
|
declare function MapMesh({
|
|
561
|
-
fill,
|
|
562
|
-
stroke,
|
|
563
545
|
styles,
|
|
564
546
|
onMouseEnter,
|
|
565
547
|
onMouseLeave,
|
|
566
548
|
onMouseDown,
|
|
567
549
|
onMouseUp,
|
|
568
|
-
onClick,
|
|
569
|
-
onFocus,
|
|
570
|
-
onBlur,
|
|
571
550
|
...pathProps
|
|
572
551
|
}: MapMeshProps): ReactElement | null;
|
|
573
552
|
//#endregion
|
|
@@ -596,4 +575,21 @@ declare function MapZoom({
|
|
|
596
575
|
declare const MapContextValue: react0.Context<MapContext | undefined>;
|
|
597
576
|
declare function useMapContext(): MapContext | undefined;
|
|
598
577
|
//#endregion
|
|
599
|
-
|
|
578
|
+
//#region src/hooks/useMapObject.d.ts
|
|
579
|
+
type MapObjectStyle = CSSProperties;
|
|
580
|
+
interface UseMapObjectOptions<TElement extends Element> extends MapObject<MapObjectStyle> {
|
|
581
|
+
onMouseEnter?: MouseEventHandler<TElement>;
|
|
582
|
+
onMouseLeave?: MouseEventHandler<TElement>;
|
|
583
|
+
onMouseDown?: MouseEventHandler<TElement>;
|
|
584
|
+
onMouseUp?: MouseEventHandler<TElement>;
|
|
585
|
+
}
|
|
586
|
+
interface UseMapObjectResult<TElement extends Element> {
|
|
587
|
+
style: MapObjectStyle | undefined;
|
|
588
|
+
onMouseEnter: MouseEventHandler<TElement>;
|
|
589
|
+
onMouseLeave: MouseEventHandler<TElement>;
|
|
590
|
+
onMouseDown: MouseEventHandler<TElement>;
|
|
591
|
+
onMouseUp: MouseEventHandler<TElement>;
|
|
592
|
+
}
|
|
593
|
+
declare function useMapObject<TElement extends Element>(options: UseMapObjectOptions<TElement>): UseMapObjectResult<TElement>;
|
|
594
|
+
//#endregion
|
|
595
|
+
export { Map, MapContextValue, MapFeature, MapFeatures, MapGraticule, MapMarker, MapMesh, MapObjectStyle, MapZoom, UseMapObjectOptions, UseMapObjectResult, useMapContext, useMapObject };
|
package/dist/index.iife.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";(function(e,t,n,r,i){let a=(0,r.createContext)(void 0);function o(){return(0,r.useContext)(a)}function s({context:e,children:t}){return(0,i.jsx)(a.Provider,{value:e,children:t})}function c(e){return typeof e==`function`}function l({width:e,height:t,aspectRatio:a,projection:o,projectionConfig:l,data:u,dataTransformer:d,children:f,className:p,...m}){let h=(0,r.useMemo)(()=>(0,n.makeMapContext)({width:e,height:t,aspectRatio:a,projection:o,projectionConfig:l,data:u,dataTransformer:d}),[e,t,a,o,l,u,d]),g=c(f)?f(h):f;return(0,i.jsx)(s,{context:h,children:(0,i.jsx)(`svg`,{...m,className:`d3-map ${p??``}`,viewBox:`0 0 ${h.width} ${h.height}`,children:g})})}function u(e){let t=(0,r.useRef)(e);return t.current=e,t}function
|
|
1
|
+
"use client";(function(e,t,n,r,i){let a=(0,r.createContext)(void 0);function o(){return(0,r.useContext)(a)}function s({context:e,children:t}){return(0,i.jsx)(a.Provider,{value:e,children:t})}function c(e){return typeof e==`function`}function l({width:e,height:t,aspectRatio:a,projection:o,projectionConfig:l,data:u,dataTransformer:d,children:f,className:p,...m}){let h=(0,r.useMemo)(()=>(0,n.makeMapContext)({width:e,height:t,aspectRatio:a,projection:o,projectionConfig:l,data:u,dataTransformer:d}),[e,t,a,o,l,u,d]),g=c(f)?f(h):f;return(0,i.jsx)(s,{context:h,children:(0,i.jsx)(`svg`,{...m,className:`d3-map ${p??``}`,viewBox:`0 0 ${h.width} ${h.height}`,children:g})})}let u=(0,r.createContext)(!1);function d(){return(0,r.useContext)(u)}function f(e){let t=(0,r.useRef)(e);return t.current=e,t}function p(e){let[t,i]=(0,r.useState)(`default`),a=(0,r.useRef)(t),o=d(),s=f(e.onMouseEnter),c=f(e.onMouseLeave),l=f(e.onMouseDown),u=f(e.onMouseUp);(0,r.useEffect)(()=>{a.current=t},[t]);let p=(0,r.useCallback)(e=>{a.current!==e&&(a.current=e,i(e))},[]),m=(0,r.useMemo)(()=>(0,n.useMapObjectEvents)(p,o),[o,p]);return(0,r.useEffect)(()=>()=>{m.dispose()},[m]),{style:(0,r.useMemo)(()=>(0,n.resolveObjectStyle)(t,e.styles),[t,e.styles]),onMouseEnter:(0,r.useCallback)(e=>{m.onMouseenter(),s.current?.(e)},[m]),onMouseLeave:(0,r.useCallback)(e=>{m.onMouseleave(),c.current?.(e)},[m]),onMouseDown:(0,r.useCallback)(e=>{m.onMousedown(e),l.current?.(e)},[m]),onMouseUp:(0,r.useCallback)(e=>{m.onMouseup(),u.current?.(e)},[m])}}function m({data:e,styles:t,onMouseEnter:n,onMouseLeave:a,onMouseDown:s,onMouseUp:c,...l}){let u=o(),d=(0,r.useMemo)(()=>u?.path(e)??void 0,[u,e]),{style:f,...m}=p({styles:t,onMouseEnter:n,onMouseLeave:a,onMouseDown:s,onMouseUp:c});return(0,i.jsx)(`path`,{...l,d,style:f,name:`feature`,...m})}function h(e){return typeof e==`function`}function g({idKey:e=`id`,styles:t,children:r,...a}){let s=o()?.features??[],c=h(r)?r({features:s}):r;return(0,i.jsx)(`g`,{...a,name:`features`,children:c??s.map((r,a)=>(0,i.jsx)(m,{data:r,styles:t},(0,n.getFeatureKey)(r,e,a)))})}function _({config:e,background:t,border:a,styles:s,onMouseEnter:c,onMouseLeave:l,onMouseDown:u,onMouseUp:d,...f}){let m=o(),h=(0,r.useMemo)(()=>{if(m)return(0,n.renderGraticule)(m,e)??void 0},[m,e]),g=t===!0||typeof t==`string`,_=a===!0||typeof a==`string`,v=typeof t==`string`?t:void 0,y=typeof a==`string`?a:void 0,b=g||_,x=(0,r.useMemo)(()=>{if(!(!m||!b))return(0,n.renderOutline)(m)??void 0},[m,b]),{style:S,...C}=p({styles:s,onMouseEnter:c,onMouseLeave:l,onMouseDown:u,onMouseUp:d});return(0,i.jsxs)(`g`,{children:[g?(0,i.jsx)(`path`,{d:x??void 0,fill:v,name:`background`,pointerEvents:`none`}):null,(0,i.jsx)(`path`,{...f,d:h??void 0,style:S,fill:`none`,name:`graticule`,...C}),_?(0,i.jsx)(`path`,{d:x??void 0,fill:`none`,stroke:y,name:`border`,pointerEvents:`none`}):null]})}let v=[0,0];function y({coordinates:e=v,styles:t,children:a,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,...d}){let f=o(),m=(0,r.useMemo)(()=>(0,n.getMarkerTransform)(f,e),[f,e[0],e[1]]),{style:h,...g}=p({styles:t,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u});return(0,i.jsx)(`g`,{...d,transform:m,style:h,name:`marker`,...g,children:a})}function b({styles:e,onMouseEnter:t,onMouseLeave:n,onMouseDown:a,onMouseUp:s,...c}){let l=o(),u=(0,r.useMemo)(()=>l?.renderMesh()??void 0,[l]),{style:d,...f}=p({styles:e,onMouseEnter:t,onMouseLeave:n,onMouseDown:a,onMouseUp:s}),m=c.fill??`none`;return(0,i.jsx)(`path`,{...c,d:u,style:d,fill:m,name:`mesh`,...f})}function x({center:e,zoom:t,minZoom:a=n.ZOOM_DEFAULTS.minZoom,maxZoom:s=n.ZOOM_DEFAULTS.maxZoom,config:c,onZoomStart:l,onZoom:d,onZoomEnd:p,children:m,className:h,...g}){let _=(0,r.useRef)(null),v=(0,r.useRef)(!1),y=o(),b=f(l),x=f(d),S=f(p),C=e??n.ZOOM_DEFAULTS.center,w=t??n.ZOOM_DEFAULTS.zoom,T=C[0],E=C[1],D=(0,r.useMemo)(()=>(0,n.createZoomBehavior)(y,{minZoom:a,maxZoom:s,config:c,onZoomStart:e=>{b.current?.(e)},onZoom:e=>{(0,n.applyZoomGroupTransform)(_.current,e.transform),x.current?.(e)},onZoomEnd:e=>{S.current?.(e)}}),[y,a,s,c]);(0,r.useEffect)(()=>{v.current=!0,(0,n.setupZoom)({element:_.current,behavior:D,center:C,zoom:w})},[D]),(0,r.useEffect)(()=>{if(v.current){v.current=!1;return}(0,n.applyZoomTransform)({element:_.current,behavior:D,center:[T,E],zoom:w})},[D,T,E,w]);let O=h?`d3-map-zoom ${h}`:`d3-map-zoom`;return(0,i.jsx)(u.Provider,{value:!0,children:(0,i.jsx)(`g`,{...g,ref:_,className:O,name:`zoom`,children:m})})}e.Map=l,e.MapContextValue=a,e.MapFeature=m,e.MapFeatures=g,e.MapGraticule=_,e.MapMarker=y,e.MapMesh=b,e.MapZoom=x,e.useMapContext=o,e.useMapObject=p})(this.D3Maps=this.D3Maps||{},_d3_maps_core_index_css,D3Maps,React,ReactJSXRuntime);
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import "@d3-maps/core/index.css";
|
|
4
|
-
import { ZOOM_DEFAULTS, applyZoomGroupTransform, applyZoomTransform, createZoomBehavior, getFeatureKey, getMarkerTransform,
|
|
4
|
+
import { ZOOM_DEFAULTS, applyZoomGroupTransform, applyZoomTransform, createZoomBehavior, getFeatureKey, getMarkerTransform, makeMapContext, renderGraticule, renderOutline, resolveObjectStyle, setupZoom, useMapObjectEvents } from "@d3-maps/core";
|
|
5
5
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/hooks/useMapContext.ts
|
|
9
9
|
const MapContextValue = createContext(void 0);
|
|
@@ -57,6 +57,13 @@ function Map({ width, height, aspectRatio, projection, projectionConfig, data, d
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/hooks/useInsideZoom.ts
|
|
62
|
+
const InsideZoomContext = createContext(false);
|
|
63
|
+
function useInsideZoom() {
|
|
64
|
+
return useContext(InsideZoomContext);
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
//#endregion
|
|
61
68
|
//#region src/hooks/useLatest.ts
|
|
62
69
|
function useLatest(value) {
|
|
@@ -69,85 +76,70 @@ function useLatest(value) {
|
|
|
69
76
|
//#region src/hooks/useMapObject.ts
|
|
70
77
|
function useMapObject(options) {
|
|
71
78
|
const [state, setState] = useState("default");
|
|
79
|
+
const stateRef = useRef(state);
|
|
80
|
+
const insideZoom = useInsideZoom();
|
|
72
81
|
const onMouseEnterRef = useLatest(options.onMouseEnter);
|
|
73
82
|
const onMouseLeaveRef = useLatest(options.onMouseLeave);
|
|
74
83
|
const onMouseDownRef = useLatest(options.onMouseDown);
|
|
75
84
|
const onMouseUpRef = useLatest(options.onMouseUp);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
stateRef.current = state;
|
|
87
|
+
}, [state]);
|
|
88
|
+
const syncState = useCallback((nextState) => {
|
|
89
|
+
if (stateRef.current === nextState) return;
|
|
90
|
+
stateRef.current = nextState;
|
|
91
|
+
setState(nextState);
|
|
84
92
|
}, []);
|
|
93
|
+
const interactionController = useMemo(() => {
|
|
94
|
+
return useMapObjectEvents(syncState, insideZoom);
|
|
95
|
+
}, [insideZoom, syncState]);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
return () => {
|
|
98
|
+
interactionController.dispose();
|
|
99
|
+
};
|
|
100
|
+
}, [interactionController]);
|
|
85
101
|
return {
|
|
86
|
-
|
|
87
|
-
return resolveObjectStyle(state, options.styles);
|
|
88
|
-
}, [state, options.styles]),
|
|
102
|
+
style: useMemo(() => resolveObjectStyle(state, options.styles), [state, options.styles]),
|
|
89
103
|
onMouseEnter: useCallback((event) => {
|
|
90
|
-
|
|
104
|
+
interactionController.onMouseenter();
|
|
91
105
|
onMouseEnterRef.current?.(event);
|
|
92
|
-
}, [
|
|
106
|
+
}, [interactionController]),
|
|
93
107
|
onMouseLeave: useCallback((event) => {
|
|
94
|
-
|
|
108
|
+
interactionController.onMouseleave();
|
|
95
109
|
onMouseLeaveRef.current?.(event);
|
|
96
|
-
}, [
|
|
110
|
+
}, [interactionController]),
|
|
97
111
|
onMouseDown: useCallback((event) => {
|
|
98
|
-
|
|
112
|
+
interactionController.onMousedown(event);
|
|
99
113
|
onMouseDownRef.current?.(event);
|
|
100
|
-
}, [
|
|
114
|
+
}, [interactionController]),
|
|
101
115
|
onMouseUp: useCallback((event) => {
|
|
102
|
-
|
|
116
|
+
interactionController.onMouseup();
|
|
103
117
|
onMouseUpRef.current?.(event);
|
|
104
|
-
}, [
|
|
105
|
-
onClick: useCallback((event) => {
|
|
106
|
-
setStateForEvent("mouseup");
|
|
107
|
-
onClickRef.current?.(event);
|
|
108
|
-
}, [setStateForEvent]),
|
|
109
|
-
onFocus: useCallback((event) => {
|
|
110
|
-
setStateForEvent("focus");
|
|
111
|
-
onFocusRef.current?.(event);
|
|
112
|
-
}, [setStateForEvent]),
|
|
113
|
-
onBlur: useCallback((event) => {
|
|
114
|
-
setStateForEvent("blur");
|
|
115
|
-
onBlurRef.current?.(event);
|
|
116
|
-
}, [setStateForEvent])
|
|
118
|
+
}, [interactionController])
|
|
117
119
|
};
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
//#endregion
|
|
121
123
|
//#region src/components/MapFeature.tsx
|
|
122
|
-
function MapFeature({ data, styles,
|
|
124
|
+
function MapFeature({ data, styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
|
|
123
125
|
const context = useMapContext();
|
|
124
126
|
const path = useMemo(() => {
|
|
125
|
-
return context?.
|
|
127
|
+
return context?.path(data) ?? void 0;
|
|
126
128
|
}, [context, data]);
|
|
127
|
-
const {
|
|
129
|
+
const { style, ...events } = useMapObject({
|
|
128
130
|
styles,
|
|
129
131
|
onMouseEnter,
|
|
130
132
|
onMouseLeave,
|
|
131
133
|
onMouseDown,
|
|
132
|
-
onMouseUp
|
|
133
|
-
onClick,
|
|
134
|
-
onFocus,
|
|
135
|
-
onBlur
|
|
134
|
+
onMouseUp
|
|
136
135
|
});
|
|
137
|
-
return
|
|
136
|
+
return /* @__PURE__ */ jsx("path", {
|
|
138
137
|
...pathProps,
|
|
139
138
|
d: path,
|
|
140
|
-
style
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
onMouseLeave: handleMouseLeave,
|
|
145
|
-
onMouseDown: handleMouseDown,
|
|
146
|
-
onMouseUp: handleMouseUp,
|
|
147
|
-
onClick: handleClick,
|
|
148
|
-
onFocus: handleFocus,
|
|
149
|
-
onBlur: handleBlur
|
|
150
|
-
}) : null;
|
|
139
|
+
style,
|
|
140
|
+
name: "feature",
|
|
141
|
+
...events
|
|
142
|
+
});
|
|
151
143
|
}
|
|
152
144
|
|
|
153
145
|
//#endregion
|
|
@@ -155,20 +147,72 @@ function MapFeature({ data, styles, fill, stroke, onMouseEnter, onMouseLeave, on
|
|
|
155
147
|
function isRenderProp(children) {
|
|
156
148
|
return typeof children === "function";
|
|
157
149
|
}
|
|
158
|
-
function MapFeatures({ idKey = "id",
|
|
150
|
+
function MapFeatures({ idKey = "id", styles, children, ...groupProps }) {
|
|
159
151
|
const features = useMapContext()?.features ?? [];
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
152
|
+
const resolvedChildren = isRenderProp(children) ? children({ features }) : children;
|
|
153
|
+
return /* @__PURE__ */ jsx("g", {
|
|
154
|
+
...groupProps,
|
|
155
|
+
name: "features",
|
|
156
|
+
children: resolvedChildren ?? features.map((feature, index) => /* @__PURE__ */ jsx(MapFeature, {
|
|
157
|
+
data: feature,
|
|
158
|
+
styles
|
|
159
|
+
}, getFeatureKey(feature, idKey, index)))
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/components/MapGraticule.tsx
|
|
165
|
+
function MapGraticule({ config, background, border, styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
|
|
166
|
+
const context = useMapContext();
|
|
167
|
+
const graticulePath = useMemo(() => {
|
|
168
|
+
if (!context) return void 0;
|
|
169
|
+
return renderGraticule(context, config) ?? void 0;
|
|
170
|
+
}, [context, config]);
|
|
171
|
+
const showBackground = background === true || typeof background === "string";
|
|
172
|
+
const showBorder = border === true || typeof border === "string";
|
|
173
|
+
const backgroundColor = typeof background === "string" ? background : void 0;
|
|
174
|
+
const borderColor = typeof border === "string" ? border : void 0;
|
|
175
|
+
const shouldRenderOutline = showBackground || showBorder;
|
|
176
|
+
const outlinePath = useMemo(() => {
|
|
177
|
+
if (!context || !shouldRenderOutline) return void 0;
|
|
178
|
+
return renderOutline(context) ?? void 0;
|
|
179
|
+
}, [context, shouldRenderOutline]);
|
|
180
|
+
const { style, ...events } = useMapObject({
|
|
181
|
+
styles,
|
|
182
|
+
onMouseEnter,
|
|
183
|
+
onMouseLeave,
|
|
184
|
+
onMouseDown,
|
|
185
|
+
onMouseUp
|
|
186
|
+
});
|
|
187
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
188
|
+
showBackground ? /* @__PURE__ */ jsx("path", {
|
|
189
|
+
d: outlinePath ?? void 0,
|
|
190
|
+
fill: backgroundColor,
|
|
191
|
+
name: "background",
|
|
192
|
+
pointerEvents: "none"
|
|
193
|
+
}) : null,
|
|
194
|
+
/* @__PURE__ */ jsx("path", {
|
|
195
|
+
...pathProps,
|
|
196
|
+
d: graticulePath ?? void 0,
|
|
197
|
+
style,
|
|
198
|
+
fill: "none",
|
|
199
|
+
name: "graticule",
|
|
200
|
+
...events
|
|
201
|
+
}),
|
|
202
|
+
showBorder ? /* @__PURE__ */ jsx("path", {
|
|
203
|
+
d: outlinePath ?? void 0,
|
|
204
|
+
fill: "none",
|
|
205
|
+
stroke: borderColor,
|
|
206
|
+
name: "border",
|
|
207
|
+
pointerEvents: "none"
|
|
208
|
+
}) : null
|
|
209
|
+
] });
|
|
166
210
|
}
|
|
167
211
|
|
|
168
212
|
//#endregion
|
|
169
213
|
//#region src/components/MapMarker.tsx
|
|
170
214
|
const DEFAULT_COORDINATES = [0, 0];
|
|
171
|
-
function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp,
|
|
215
|
+
function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...groupProps }) {
|
|
172
216
|
const context = useMapContext();
|
|
173
217
|
const transform = useMemo(() => {
|
|
174
218
|
return getMarkerTransform(context, coordinates);
|
|
@@ -177,62 +221,46 @@ function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMous
|
|
|
177
221
|
coordinates[0],
|
|
178
222
|
coordinates[1]
|
|
179
223
|
]);
|
|
180
|
-
const {
|
|
224
|
+
const { style, ...events } = useMapObject({
|
|
181
225
|
styles,
|
|
182
226
|
onMouseEnter,
|
|
183
227
|
onMouseLeave,
|
|
184
228
|
onMouseDown,
|
|
185
|
-
onMouseUp
|
|
186
|
-
onClick,
|
|
187
|
-
onFocus,
|
|
188
|
-
onBlur
|
|
229
|
+
onMouseUp
|
|
189
230
|
});
|
|
190
231
|
return /* @__PURE__ */ jsx("g", {
|
|
191
232
|
...groupProps,
|
|
192
233
|
transform,
|
|
193
|
-
style
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
onMouseDown: handleMouseDown,
|
|
197
|
-
onMouseUp: handleMouseUp,
|
|
198
|
-
onClick: handleClick,
|
|
199
|
-
onFocus: handleFocus,
|
|
200
|
-
onBlur: handleBlur,
|
|
234
|
+
style,
|
|
235
|
+
name: "marker",
|
|
236
|
+
...events,
|
|
201
237
|
children
|
|
202
238
|
});
|
|
203
239
|
}
|
|
204
240
|
|
|
205
241
|
//#endregion
|
|
206
242
|
//#region src/components/MapMesh.tsx
|
|
207
|
-
function MapMesh({
|
|
243
|
+
function MapMesh({ styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
|
|
208
244
|
const context = useMapContext();
|
|
209
245
|
const path = useMemo(() => {
|
|
210
|
-
return context?.renderMesh() ??
|
|
246
|
+
return context?.renderMesh() ?? void 0;
|
|
211
247
|
}, [context]);
|
|
212
|
-
const {
|
|
248
|
+
const { style, ...events } = useMapObject({
|
|
213
249
|
styles,
|
|
214
250
|
onMouseEnter,
|
|
215
251
|
onMouseLeave,
|
|
216
252
|
onMouseDown,
|
|
217
|
-
onMouseUp
|
|
218
|
-
onClick,
|
|
219
|
-
onFocus,
|
|
220
|
-
onBlur
|
|
253
|
+
onMouseUp
|
|
221
254
|
});
|
|
222
|
-
|
|
255
|
+
const fill = pathProps.fill ?? "none";
|
|
256
|
+
return /* @__PURE__ */ jsx("path", {
|
|
223
257
|
...pathProps,
|
|
224
258
|
d: path,
|
|
225
|
-
style
|
|
259
|
+
style,
|
|
226
260
|
fill,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
onMouseDown: handleMouseDown,
|
|
231
|
-
onMouseUp: handleMouseUp,
|
|
232
|
-
onClick: handleClick,
|
|
233
|
-
onFocus: handleFocus,
|
|
234
|
-
onBlur: handleBlur
|
|
235
|
-
}) : null;
|
|
261
|
+
name: "mesh",
|
|
262
|
+
...events
|
|
263
|
+
});
|
|
236
264
|
}
|
|
237
265
|
|
|
238
266
|
//#endregion
|
|
@@ -297,13 +325,17 @@ function MapZoom({ center, zoom, minZoom = ZOOM_DEFAULTS.minZoom, maxZoom = ZOOM
|
|
|
297
325
|
resolvedZoom
|
|
298
326
|
]);
|
|
299
327
|
const mergedClassName = className ? `d3-map-zoom ${className}` : "d3-map-zoom";
|
|
300
|
-
return /* @__PURE__ */ jsx(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
328
|
+
return /* @__PURE__ */ jsx(InsideZoomContext.Provider, {
|
|
329
|
+
value: true,
|
|
330
|
+
children: /* @__PURE__ */ jsx("g", {
|
|
331
|
+
...groupProps,
|
|
332
|
+
ref: containerRef,
|
|
333
|
+
className: mergedClassName,
|
|
334
|
+
name: "zoom",
|
|
335
|
+
children
|
|
336
|
+
})
|
|
305
337
|
});
|
|
306
338
|
}
|
|
307
339
|
|
|
308
340
|
//#endregion
|
|
309
|
-
export { Map, MapContextValue, MapFeature, MapFeatures, MapMarker, MapMesh, MapZoom, useMapContext, useMapObject };
|
|
341
|
+
export { Map, MapContextValue, MapFeature, MapFeatures, MapGraticule, MapMarker, MapMesh, MapZoom, useMapContext, useMapObject };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d3-maps/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "React bindings for @d3-maps/core to build reactive D3 SVG maps",
|
|
7
7
|
"author": "Georgii Bukharov <souljorje@gmail.com>",
|
|
@@ -40,34 +40,34 @@
|
|
|
40
40
|
"files": [
|
|
41
41
|
"dist/*"
|
|
42
42
|
],
|
|
43
|
-
"scripts": {
|
|
44
|
-
"typecheck": "tsc --noEmit",
|
|
45
|
-
"typecheck:test": "tsc -p tsconfig.test.json --noEmit",
|
|
46
|
-
"build": "pnpm run typecheck && tsdown",
|
|
47
|
-
"test": "vitest run",
|
|
48
|
-
"test:watch": "vitest"
|
|
49
|
-
},
|
|
50
43
|
"peerDependencies": {
|
|
51
44
|
"react": ">=19 <20",
|
|
52
45
|
"react-dom": ">=19 <20"
|
|
53
46
|
},
|
|
54
47
|
"dependencies": {
|
|
55
|
-
"@d3-maps/core": "
|
|
48
|
+
"@d3-maps/core": "0.6.0"
|
|
56
49
|
},
|
|
57
50
|
"devDependencies": {
|
|
58
|
-
"@testing-library/react": "
|
|
59
|
-
"@types/geojson": "
|
|
60
|
-
"@types/react": "
|
|
61
|
-
"@types/react-dom": "
|
|
62
|
-
"@types/topojson-client": "
|
|
63
|
-
"@types/topojson-specification": "
|
|
64
|
-
"@vitejs/plugin-react": "
|
|
65
|
-
"jsdom": "
|
|
66
|
-
"react": "
|
|
67
|
-
"react-dom": "
|
|
68
|
-
"tsdown": "
|
|
69
|
-
"typescript": "
|
|
70
|
-
"vite-tsconfig-paths": "
|
|
71
|
-
"vitest": "
|
|
51
|
+
"@testing-library/react": "^16.3.0",
|
|
52
|
+
"@types/geojson": "^7946.0.16",
|
|
53
|
+
"@types/react": "^19.2.2",
|
|
54
|
+
"@types/react-dom": "^19.2.2",
|
|
55
|
+
"@types/topojson-client": "^3.1.5",
|
|
56
|
+
"@types/topojson-specification": "^1.0.5",
|
|
57
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
58
|
+
"jsdom": "^27.3.0",
|
|
59
|
+
"react": "^19.2.0",
|
|
60
|
+
"react-dom": "^19.2.0",
|
|
61
|
+
"tsdown": "0.19.0",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vite-tsconfig-paths": "^6.1.1",
|
|
64
|
+
"vitest": "^4.0.15"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"typecheck:test": "tsc -p tsconfig.test.json --noEmit",
|
|
69
|
+
"build": "pnpm run typecheck && tsdown",
|
|
70
|
+
"test": "vitest run",
|
|
71
|
+
"test:watch": "vitest"
|
|
72
72
|
}
|
|
73
|
-
}
|
|
73
|
+
}
|