@d3-maps/react 0.1.0 → 0.2.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 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 [LICENCE](../../LICENCE) for more details.
54
+ MIT licensed. Copyright © 2020 Georgii Bukharov. See [LICENSE](./LICENSE) for more details.
package/dist/index.d.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import "@d3-maps/core/index.css";
2
2
  import * as react0 from "react";
3
- import { CSSProperties, FocusEventHandler, MouseEventHandler, ReactElement, ReactNode, SVGProps } from "react";
4
- import { ExtendedFeature, ExtendedFeatureCollection, GeoPath, GeoProjection } from "d3-geo";
5
- import { mesh } from "topojson-client";
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
9
-
10
9
  /**
11
10
  * Supported interaction states for map objects.
12
11
  */
@@ -27,8 +26,6 @@ type MapFeature$1 = (ExtendedFeature & Record<string, unknown>) | ExtendedFeatur
27
26
  interface MapFeatureProps$1<TStyle = unknown> {
28
27
  data: MapFeature$1;
29
28
  styles?: MapObjectStyles$1<TStyle>;
30
- fill?: string;
31
- stroke?: string;
32
29
  }
33
30
  //#endregion
34
31
  //#region ../../node_modules/.pnpm/@types+geojson@7946.0.16/node_modules/@types/geojson/index.d.ts
@@ -367,7 +364,6 @@ type ModifierArgs<P$1 extends unknown[]> = P$1 extends [infer Only] ? Only exten
367
364
  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
365
  //#endregion
369
366
  //#region ../core/src/lib/map.d.ts
370
- type MapMesh$1 = ReturnType<typeof mesh>;
371
367
  type MapData = ExtendedFeatureCollection | Topology;
372
368
  type DataTransformer = (features: MapFeature$1[]) => MapFeature$1[];
373
369
  /**
@@ -419,12 +415,21 @@ interface MapContext {
419
415
  height: number;
420
416
  projection?: GeoProjection;
421
417
  features: MapFeature$1[];
422
- mesh?: MapMesh$1;
423
418
  path: GeoPath;
424
- renderPath: (feature: MapFeature$1) => ReturnType<GeoPath>;
425
419
  renderMesh: () => ReturnType<GeoPath>;
426
420
  }
427
421
  //#endregion
422
+ //#region ../core/src/lib/graticule.d.ts
423
+ /**
424
+ * Extra graticule generator method calls to apply before rendering.
425
+ *
426
+ * Uses d3-geo `geoGraticule()` setter method names as keys.
427
+ * Example: `{ step: [[10, 10]], precision: 2.5 }`
428
+ *
429
+ * @see https://d3js.org/d3-geo/shape#geoGraticule
430
+ */
431
+ interface GraticuleConfig extends MethodsToModifiers<GeoGraticuleGenerator> {}
432
+ //#endregion
428
433
  //#region ../core/src/lib/marker.d.ts
429
434
  type MapMarkerCoordinates = [number, number];
430
435
  /**
@@ -478,15 +483,10 @@ interface MapFeatureProps extends MapFeatureProps$1<CSSProperties>, Omit<SVGProp
478
483
  declare function MapFeature({
479
484
  data,
480
485
  styles,
481
- fill,
482
- stroke,
483
486
  onMouseEnter,
484
487
  onMouseLeave,
485
488
  onMouseDown,
486
489
  onMouseUp,
487
- onClick,
488
- onFocus,
489
- onBlur,
490
490
  ...pathProps
491
491
  }: MapFeatureProps): ReactElement | null;
492
492
  //#endregion
@@ -499,19 +499,13 @@ interface UseMapObjectOptions<TElement extends Element> {
499
499
  onMouseLeave?: MouseEventHandler<TElement>;
500
500
  onMouseDown?: MouseEventHandler<TElement>;
501
501
  onMouseUp?: MouseEventHandler<TElement>;
502
- onClick?: MouseEventHandler<TElement>;
503
- onFocus?: FocusEventHandler<TElement>;
504
- onBlur?: FocusEventHandler<TElement>;
505
502
  }
506
503
  interface UseMapObjectResult<TElement extends Element> {
507
- computedStyle: MapObjectStyle | undefined;
504
+ style: MapObjectStyle | undefined;
508
505
  onMouseEnter: MouseEventHandler<TElement>;
509
506
  onMouseLeave: MouseEventHandler<TElement>;
510
507
  onMouseDown: MouseEventHandler<TElement>;
511
508
  onMouseUp: MouseEventHandler<TElement>;
512
- onClick: MouseEventHandler<TElement>;
513
- onFocus: FocusEventHandler<TElement>;
514
- onBlur: FocusEventHandler<TElement>;
515
509
  }
516
510
  declare function useMapObject<TElement extends Element>(options: UseMapObjectOptions<TElement>): UseMapObjectResult<TElement>;
517
511
  //#endregion
@@ -520,21 +514,38 @@ interface MapFeaturesRenderProps {
520
514
  features: MapFeature$1[];
521
515
  }
522
516
  type MapFeaturesChildren = ReactNode | ((props: MapFeaturesRenderProps) => ReactNode);
523
- interface MapFeaturesProps {
517
+ type MapFeaturesElementProps = Omit<SVGProps<SVGGElement>, 'children'>;
518
+ interface MapFeaturesProps extends MapFeaturesElementProps {
524
519
  idKey?: string;
525
- fill?: string;
526
- stroke?: string;
527
520
  styles?: MapObjectStyles;
528
521
  children?: MapFeaturesChildren;
529
522
  }
530
523
  declare function MapFeatures({
531
524
  idKey,
532
- fill,
533
- stroke,
534
525
  styles,
535
- children
526
+ children,
527
+ ...groupProps
536
528
  }: MapFeaturesProps): ReactElement;
537
529
  //#endregion
530
+ //#region src/components/MapGraticule.d.ts
531
+ interface MapGraticuleProps extends Omit<SVGProps<SVGPathElement>, 'children' | 'd' | 'style' | 'fill'> {
532
+ config?: GraticuleConfig;
533
+ background?: boolean | string;
534
+ border?: boolean | string;
535
+ styles?: MapObjectStyles;
536
+ }
537
+ declare function MapGraticule({
538
+ config,
539
+ background,
540
+ border,
541
+ styles,
542
+ onMouseEnter,
543
+ onMouseLeave,
544
+ onMouseDown,
545
+ onMouseUp,
546
+ ...pathProps
547
+ }: MapGraticuleProps): ReactElement | null;
548
+ //#endregion
538
549
  //#region src/components/MapMarker.d.ts
539
550
  interface MapMarkerProps extends MapMarkerProps$1<CSSProperties>, Omit<SVGProps<SVGGElement>, 'style'> {}
540
551
  declare function MapMarker({
@@ -545,29 +556,19 @@ declare function MapMarker({
545
556
  onMouseLeave,
546
557
  onMouseDown,
547
558
  onMouseUp,
548
- onClick,
549
- onFocus,
550
- onBlur,
551
559
  ...groupProps
552
560
  }: MapMarkerProps): ReactElement;
553
561
  //#endregion
554
562
  //#region src/components/MapMesh.d.ts
555
563
  interface MapMeshProps extends Omit<SVGProps<SVGPathElement>, 'children' | 'd' | 'style'> {
556
- fill?: string;
557
- stroke?: string;
558
564
  styles?: MapObjectStyles;
559
565
  }
560
566
  declare function MapMesh({
561
- fill,
562
- stroke,
563
567
  styles,
564
568
  onMouseEnter,
565
569
  onMouseLeave,
566
570
  onMouseDown,
567
571
  onMouseUp,
568
- onClick,
569
- onFocus,
570
- onBlur,
571
572
  ...pathProps
572
573
  }: MapMeshProps): ReactElement | null;
573
574
  //#endregion
@@ -596,4 +597,4 @@ declare function MapZoom({
596
597
  declare const MapContextValue: react0.Context<MapContext | undefined>;
597
598
  declare function useMapContext(): MapContext | undefined;
598
599
  //#endregion
599
- export { Map, MapContextValue, MapFeature, MapFeatures, MapMarker, MapMesh, MapObjectStyle, MapObjectStyles, MapZoom, UseMapObjectOptions, UseMapObjectResult, useMapContext, useMapObject };
600
+ export { Map, MapContextValue, MapFeature, MapFeatures, MapGraticule, MapMarker, MapMesh, MapObjectStyle, MapObjectStyles, MapZoom, UseMapObjectOptions, UseMapObjectResult, useMapContext, useMapObject };
@@ -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 d(e){let[t,i]=(0,r.useState)(`default`),a=u(e.onMouseEnter),o=u(e.onMouseLeave),s=u(e.onMouseDown),c=u(e.onMouseUp),l=u(e.onClick),d=u(e.onFocus),f=u(e.onBlur),p=(0,r.useCallback)(e=>{i(t=>{let r=(0,n.getObjectStateUpdate)(e);return t===r?t:r})},[]);return{computedStyle:(0,r.useMemo)(()=>(0,n.resolveObjectStyle)(t,e.styles),[t,e.styles]),onMouseEnter:(0,r.useCallback)(e=>{p(`mouseenter`),a.current?.(e)},[p]),onMouseLeave:(0,r.useCallback)(e=>{p(`mouseleave`),o.current?.(e)},[p]),onMouseDown:(0,r.useCallback)(e=>{p(`mousedown`),s.current?.(e)},[p]),onMouseUp:(0,r.useCallback)(e=>{p(`mouseup`),c.current?.(e)},[p]),onClick:(0,r.useCallback)(e=>{p(`mouseup`),l.current?.(e)},[p]),onFocus:(0,r.useCallback)(e=>{p(`focus`),d.current?.(e)},[p]),onBlur:(0,r.useCallback)(e=>{p(`blur`),f.current?.(e)},[p])}}function f({data:e,styles:t,fill:n,stroke:a,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,onClick:f,onFocus:p,onBlur:m,...h}){let g=o(),_=(0,r.useMemo)(()=>g?.renderPath(e)??null,[g,e]),{computedStyle:v,onMouseEnter:y,onMouseLeave:b,onMouseDown:x,onMouseUp:S,onClick:C,onFocus:w,onBlur:T}=d({styles:t,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,onClick:f,onFocus:p,onBlur:m});return _?(0,i.jsx)(`path`,{...h,d:_,style:v,fill:n,stroke:a,onMouseEnter:y,onMouseLeave:b,onMouseDown:x,onMouseUp:S,onClick:C,onFocus:w,onBlur:T}):null}function p(e){return typeof e==`function`}function m({idKey:e=`id`,fill:t,stroke:r,styles:a,children:s}){let c=o()?.features??[];return(0,i.jsx)(`g`,{children:(p(s)?s({features:c}):s)??c.map((o,s)=>(0,i.jsx)(f,{data:o,fill:t,stroke:r,styles:a},(0,n.getFeatureKey)(o,e,s)))})}let h=[0,0];function g({coordinates:e=h,styles:t,children:a,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,onClick:f,onFocus:p,onBlur:m,...g}){let _=o(),v=(0,r.useMemo)(()=>(0,n.getMarkerTransform)(_,e),[_,e[0],e[1]]),{computedStyle:y,onMouseEnter:b,onMouseLeave:x,onMouseDown:S,onMouseUp:C,onClick:w,onFocus:T,onBlur:E}=d({styles:t,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,onClick:f,onFocus:p,onBlur:m});return(0,i.jsx)(`g`,{...g,transform:v,style:y,onMouseEnter:b,onMouseLeave:x,onMouseDown:S,onMouseUp:C,onClick:w,onFocus:T,onBlur:E,children:a})}function _({fill:e=`none`,stroke:t,styles:n,onMouseEnter:a,onMouseLeave:s,onMouseDown:c,onMouseUp:l,onClick:u,onFocus:f,onBlur:p,...m}){let h=o(),g=(0,r.useMemo)(()=>h?.renderMesh()??null,[h]),{computedStyle:_,onMouseEnter:v,onMouseLeave:y,onMouseDown:b,onMouseUp:x,onClick:S,onFocus:C,onBlur:w}=d({styles:n,onMouseEnter:a,onMouseLeave:s,onMouseDown:c,onMouseUp:l,onClick:u,onFocus:f,onBlur:p});return g?(0,i.jsx)(`path`,{...m,d:g,style:_,fill:e,stroke:t,onMouseEnter:v,onMouseLeave:y,onMouseDown:b,onMouseUp:x,onClick:S,onFocus:C,onBlur:w}):null}function v({center:e,zoom:t,minZoom:a=n.ZOOM_DEFAULTS.minZoom,maxZoom:s=n.ZOOM_DEFAULTS.maxZoom,config:c,onZoomStart:l,onZoom:d,onZoomEnd:f,children:p,className:m,...h}){let g=(0,r.useRef)(null),_=(0,r.useRef)(!1),v=o(),y=u(l),b=u(d),x=u(f),S=e??n.ZOOM_DEFAULTS.center,C=t??n.ZOOM_DEFAULTS.zoom,w=S[0],T=S[1],E=(0,r.useMemo)(()=>(0,n.createZoomBehavior)(v,{minZoom:a,maxZoom:s,config:c,onZoomStart:e=>{y.current?.(e)},onZoom:e=>{(0,n.applyZoomGroupTransform)(g.current,e.transform),b.current?.(e)},onZoomEnd:e=>{x.current?.(e)}}),[v,a,s,c]);(0,r.useEffect)(()=>{_.current=!0,(0,n.setupZoom)({element:g.current,behavior:E,center:S,zoom:C})},[E]),(0,r.useEffect)(()=>{if(_.current){_.current=!1;return}(0,n.applyZoomTransform)({element:g.current,behavior:E,center:[w,T],zoom:C})},[E,w,T,C]);let D=m?`d3-map-zoom ${m}`:`d3-map-zoom`;return(0,i.jsx)(`g`,{...h,ref:g,className:D,children:p})}e.Map=l,e.MapContextValue=a,e.MapFeature=f,e.MapFeatures=m,e.MapMarker=g,e.MapMesh=_,e.MapZoom=v,e.useMapContext=o,e.useMapObject=d})(this.D3Maps=this.D3Maps||{},_d3_maps_core_index_css,D3Maps,React,ReactJSXRuntime);
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 d(e){let[t,i]=(0,r.useState)(`default`),a=u(e.onMouseEnter),o=u(e.onMouseLeave),s=u(e.onMouseDown),c=u(e.onMouseUp),l=(0,r.useCallback)(e=>{i(t=>{let r=(0,n.getObjectStateUpdate)(e);return t===r?t:r})},[]);return{style:(0,r.useMemo)(()=>(0,n.resolveObjectStyle)(t,e.styles),[t,e.styles]),onMouseEnter:(0,r.useCallback)(e=>{l(`mouseenter`),a.current?.(e)},[l]),onMouseLeave:(0,r.useCallback)(e=>{l(`mouseleave`),o.current?.(e)},[l]),onMouseDown:(0,r.useCallback)(e=>{l(`mousedown`),s.current?.(e)},[l]),onMouseUp:(0,r.useCallback)(e=>{l(`mouseup`),c.current?.(e)},[l])}}function f({data:e,styles:t,onMouseEnter:n,onMouseLeave:a,onMouseDown:s,onMouseUp:c,...l}){let u=o(),f=(0,r.useMemo)(()=>u?.path(e)??void 0,[u,e]),{style:p,...m}=d({styles:t,onMouseEnter:n,onMouseLeave:a,onMouseDown:s,onMouseUp:c});return(0,i.jsx)(`path`,{...l,d:f,style:p,name:`feature`,...m})}function p(e){return typeof e==`function`}function m({idKey:e=`id`,styles:t,children:r,...a}){let s=o()?.features??[],c=p(r)?r({features:s}):r;return(0,i.jsx)(`g`,{...a,name:`features`,children:c??s.map((r,a)=>(0,i.jsx)(f,{data:r,styles:t},(0,n.getFeatureKey)(r,e,a)))})}function h({config:e,background:t,border:a,styles:s,onMouseEnter:c,onMouseLeave:l,onMouseDown:u,onMouseUp:f,...p}){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}=d({styles:s,onMouseEnter:c,onMouseLeave:l,onMouseDown:u,onMouseUp:f});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`,{...p,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 g=[0,0];function _({coordinates:e=g,styles:t,children:a,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u,...f}){let p=o(),m=(0,r.useMemo)(()=>(0,n.getMarkerTransform)(p,e),[p,e[0],e[1]]),{style:h,..._}=d({styles:t,onMouseEnter:s,onMouseLeave:c,onMouseDown:l,onMouseUp:u});return(0,i.jsx)(`g`,{...f,transform:m,style:h,name:`marker`,..._,children:a})}function v({styles:e,onMouseEnter:t,onMouseLeave:n,onMouseDown:a,onMouseUp:s,...c}){let l=o(),u=(0,r.useMemo)(()=>l?.renderMesh()??void 0,[l]),{style:f,...p}=d({styles:e,onMouseEnter:t,onMouseLeave:n,onMouseDown:a,onMouseUp:s}),m=c.fill??`none`;return(0,i.jsx)(`path`,{...c,d:u,style:f,fill:m,name:`mesh`,...p})}function y({center:e,zoom:t,minZoom:a=n.ZOOM_DEFAULTS.minZoom,maxZoom:s=n.ZOOM_DEFAULTS.maxZoom,config:c,onZoomStart:l,onZoom:d,onZoomEnd:f,children:p,className:m,...h}){let g=(0,r.useRef)(null),_=(0,r.useRef)(!1),v=o(),y=u(l),b=u(d),x=u(f),S=e??n.ZOOM_DEFAULTS.center,C=t??n.ZOOM_DEFAULTS.zoom,w=S[0],T=S[1],E=(0,r.useMemo)(()=>(0,n.createZoomBehavior)(v,{minZoom:a,maxZoom:s,config:c,onZoomStart:e=>{y.current?.(e)},onZoom:e=>{(0,n.applyZoomGroupTransform)(g.current,e.transform),b.current?.(e)},onZoomEnd:e=>{x.current?.(e)}}),[v,a,s,c]);(0,r.useEffect)(()=>{_.current=!0,(0,n.setupZoom)({element:g.current,behavior:E,center:S,zoom:C})},[E]),(0,r.useEffect)(()=>{if(_.current){_.current=!1;return}(0,n.applyZoomTransform)({element:g.current,behavior:E,center:[w,T],zoom:C})},[E,w,T,C]);let D=m?`d3-map-zoom ${m}`:`d3-map-zoom`;return(0,i.jsx)(`g`,{...h,ref:g,className:D,name:`zoom`,children:p})}e.Map=l,e.MapContextValue=a,e.MapFeature=f,e.MapFeatures=m,e.MapGraticule=h,e.MapMarker=_,e.MapMesh=v,e.MapZoom=y,e.useMapContext=o,e.useMapObject=d})(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, getObjectStateUpdate, makeMapContext, resolveObjectStyle, setupZoom } from "@d3-maps/core";
4
+ import { ZOOM_DEFAULTS, applyZoomGroupTransform, applyZoomTransform, createZoomBehavior, getFeatureKey, getMarkerTransform, getObjectStateUpdate, makeMapContext, renderGraticule, renderOutline, resolveObjectStyle, setupZoom } 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);
@@ -73,9 +73,6 @@ function useMapObject(options) {
73
73
  const onMouseLeaveRef = useLatest(options.onMouseLeave);
74
74
  const onMouseDownRef = useLatest(options.onMouseDown);
75
75
  const onMouseUpRef = useLatest(options.onMouseUp);
76
- const onClickRef = useLatest(options.onClick);
77
- const onFocusRef = useLatest(options.onFocus);
78
- const onBlurRef = useLatest(options.onBlur);
79
76
  const setStateForEvent = useCallback((eventName) => {
80
77
  setState((currentState) => {
81
78
  const nextState = getObjectStateUpdate(eventName);
@@ -83,7 +80,7 @@ function useMapObject(options) {
83
80
  });
84
81
  }, []);
85
82
  return {
86
- computedStyle: useMemo(() => {
83
+ style: useMemo(() => {
87
84
  return resolveObjectStyle(state, options.styles);
88
85
  }, [state, options.styles]),
89
86
  onMouseEnter: useCallback((event) => {
@@ -101,53 +98,31 @@ function useMapObject(options) {
101
98
  onMouseUp: useCallback((event) => {
102
99
  setStateForEvent("mouseup");
103
100
  onMouseUpRef.current?.(event);
104
- }, [setStateForEvent]),
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
101
  }, [setStateForEvent])
117
102
  };
118
103
  }
119
104
 
120
105
  //#endregion
121
106
  //#region src/components/MapFeature.tsx
122
- function MapFeature({ data, styles, fill, stroke, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, onClick, onFocus, onBlur, ...pathProps }) {
107
+ function MapFeature({ data, styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
123
108
  const context = useMapContext();
124
109
  const path = useMemo(() => {
125
- return context?.renderPath(data) ?? null;
110
+ return context?.path(data) ?? void 0;
126
111
  }, [context, data]);
127
- const { computedStyle, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onClick: handleClick, onFocus: handleFocus, onBlur: handleBlur } = useMapObject({
112
+ const { style, ...events } = useMapObject({
128
113
  styles,
129
114
  onMouseEnter,
130
115
  onMouseLeave,
131
116
  onMouseDown,
132
- onMouseUp,
133
- onClick,
134
- onFocus,
135
- onBlur
117
+ onMouseUp
136
118
  });
137
- return path ? /* @__PURE__ */ jsx("path", {
119
+ return /* @__PURE__ */ jsx("path", {
138
120
  ...pathProps,
139
121
  d: path,
140
- style: computedStyle,
141
- fill,
142
- stroke,
143
- onMouseEnter: handleMouseEnter,
144
- onMouseLeave: handleMouseLeave,
145
- onMouseDown: handleMouseDown,
146
- onMouseUp: handleMouseUp,
147
- onClick: handleClick,
148
- onFocus: handleFocus,
149
- onBlur: handleBlur
150
- }) : null;
122
+ style,
123
+ name: "feature",
124
+ ...events
125
+ });
151
126
  }
152
127
 
153
128
  //#endregion
@@ -155,20 +130,72 @@ function MapFeature({ data, styles, fill, stroke, onMouseEnter, onMouseLeave, on
155
130
  function isRenderProp(children) {
156
131
  return typeof children === "function";
157
132
  }
158
- function MapFeatures({ idKey = "id", fill, stroke, styles, children }) {
133
+ function MapFeatures({ idKey = "id", styles, children, ...groupProps }) {
159
134
  const features = useMapContext()?.features ?? [];
160
- return /* @__PURE__ */ jsx("g", { children: (isRenderProp(children) ? children({ features }) : children) ?? features.map((feature, index) => /* @__PURE__ */ jsx(MapFeature, {
161
- data: feature,
162
- fill,
163
- stroke,
164
- styles
165
- }, getFeatureKey(feature, idKey, index))) });
135
+ const resolvedChildren = isRenderProp(children) ? children({ features }) : children;
136
+ return /* @__PURE__ */ jsx("g", {
137
+ ...groupProps,
138
+ name: "features",
139
+ children: resolvedChildren ?? features.map((feature, index) => /* @__PURE__ */ jsx(MapFeature, {
140
+ data: feature,
141
+ styles
142
+ }, getFeatureKey(feature, idKey, index)))
143
+ });
144
+ }
145
+
146
+ //#endregion
147
+ //#region src/components/MapGraticule.tsx
148
+ function MapGraticule({ config, background, border, styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
149
+ const context = useMapContext();
150
+ const graticulePath = useMemo(() => {
151
+ if (!context) return void 0;
152
+ return renderGraticule(context, config) ?? void 0;
153
+ }, [context, config]);
154
+ const showBackground = background === true || typeof background === "string";
155
+ const showBorder = border === true || typeof border === "string";
156
+ const backgroundColor = typeof background === "string" ? background : void 0;
157
+ const borderColor = typeof border === "string" ? border : void 0;
158
+ const shouldRenderOutline = showBackground || showBorder;
159
+ const outlinePath = useMemo(() => {
160
+ if (!context || !shouldRenderOutline) return void 0;
161
+ return renderOutline(context) ?? void 0;
162
+ }, [context, shouldRenderOutline]);
163
+ const { style, ...events } = useMapObject({
164
+ styles,
165
+ onMouseEnter,
166
+ onMouseLeave,
167
+ onMouseDown,
168
+ onMouseUp
169
+ });
170
+ return /* @__PURE__ */ jsxs("g", { children: [
171
+ showBackground ? /* @__PURE__ */ jsx("path", {
172
+ d: outlinePath ?? void 0,
173
+ fill: backgroundColor,
174
+ name: "background",
175
+ pointerEvents: "none"
176
+ }) : null,
177
+ /* @__PURE__ */ jsx("path", {
178
+ ...pathProps,
179
+ d: graticulePath ?? void 0,
180
+ style,
181
+ fill: "none",
182
+ name: "graticule",
183
+ ...events
184
+ }),
185
+ showBorder ? /* @__PURE__ */ jsx("path", {
186
+ d: outlinePath ?? void 0,
187
+ fill: "none",
188
+ stroke: borderColor,
189
+ name: "border",
190
+ pointerEvents: "none"
191
+ }) : null
192
+ ] });
166
193
  }
167
194
 
168
195
  //#endregion
169
196
  //#region src/components/MapMarker.tsx
170
197
  const DEFAULT_COORDINATES = [0, 0];
171
- function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, onClick, onFocus, onBlur, ...groupProps }) {
198
+ function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...groupProps }) {
172
199
  const context = useMapContext();
173
200
  const transform = useMemo(() => {
174
201
  return getMarkerTransform(context, coordinates);
@@ -177,62 +204,46 @@ function MapMarker({ coordinates = DEFAULT_COORDINATES, styles, children, onMous
177
204
  coordinates[0],
178
205
  coordinates[1]
179
206
  ]);
180
- const { computedStyle, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onClick: handleClick, onFocus: handleFocus, onBlur: handleBlur } = useMapObject({
207
+ const { style, ...events } = useMapObject({
181
208
  styles,
182
209
  onMouseEnter,
183
210
  onMouseLeave,
184
211
  onMouseDown,
185
- onMouseUp,
186
- onClick,
187
- onFocus,
188
- onBlur
212
+ onMouseUp
189
213
  });
190
214
  return /* @__PURE__ */ jsx("g", {
191
215
  ...groupProps,
192
216
  transform,
193
- style: computedStyle,
194
- onMouseEnter: handleMouseEnter,
195
- onMouseLeave: handleMouseLeave,
196
- onMouseDown: handleMouseDown,
197
- onMouseUp: handleMouseUp,
198
- onClick: handleClick,
199
- onFocus: handleFocus,
200
- onBlur: handleBlur,
217
+ style,
218
+ name: "marker",
219
+ ...events,
201
220
  children
202
221
  });
203
222
  }
204
223
 
205
224
  //#endregion
206
225
  //#region src/components/MapMesh.tsx
207
- function MapMesh({ fill = "none", stroke, styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, onClick, onFocus, onBlur, ...pathProps }) {
226
+ function MapMesh({ styles, onMouseEnter, onMouseLeave, onMouseDown, onMouseUp, ...pathProps }) {
208
227
  const context = useMapContext();
209
228
  const path = useMemo(() => {
210
- return context?.renderMesh() ?? null;
229
+ return context?.renderMesh() ?? void 0;
211
230
  }, [context]);
212
- const { computedStyle, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onClick: handleClick, onFocus: handleFocus, onBlur: handleBlur } = useMapObject({
231
+ const { style, ...events } = useMapObject({
213
232
  styles,
214
233
  onMouseEnter,
215
234
  onMouseLeave,
216
235
  onMouseDown,
217
- onMouseUp,
218
- onClick,
219
- onFocus,
220
- onBlur
236
+ onMouseUp
221
237
  });
222
- return path ? /* @__PURE__ */ jsx("path", {
238
+ const fill = pathProps.fill ?? "none";
239
+ return /* @__PURE__ */ jsx("path", {
223
240
  ...pathProps,
224
241
  d: path,
225
- style: computedStyle,
242
+ style,
226
243
  fill,
227
- stroke,
228
- onMouseEnter: handleMouseEnter,
229
- onMouseLeave: handleMouseLeave,
230
- onMouseDown: handleMouseDown,
231
- onMouseUp: handleMouseUp,
232
- onClick: handleClick,
233
- onFocus: handleFocus,
234
- onBlur: handleBlur
235
- }) : null;
244
+ name: "mesh",
245
+ ...events
246
+ });
236
247
  }
237
248
 
238
249
  //#endregion
@@ -301,9 +312,10 @@ function MapZoom({ center, zoom, minZoom = ZOOM_DEFAULTS.minZoom, maxZoom = ZOOM
301
312
  ...groupProps,
302
313
  ref: containerRef,
303
314
  className: mergedClassName,
315
+ name: "zoom",
304
316
  children
305
317
  });
306
318
  }
307
319
 
308
320
  //#endregion
309
- export { Map, MapContextValue, MapFeature, MapFeatures, MapMarker, MapMesh, MapZoom, useMapContext, useMapObject };
321
+ 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.1.0",
4
+ "version": "0.2.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": "workspace:*"
48
+ "@d3-maps/core": "0.5.0"
56
49
  },
57
50
  "devDependencies": {
58
- "@testing-library/react": "catalog:",
59
- "@types/geojson": "catalog:",
60
- "@types/react": "catalog:",
61
- "@types/react-dom": "catalog:",
62
- "@types/topojson-client": "catalog:",
63
- "@types/topojson-specification": "catalog:",
64
- "@vitejs/plugin-react": "catalog:",
65
- "jsdom": "catalog:",
66
- "react": "catalog:",
67
- "react-dom": "catalog:",
68
- "tsdown": "catalog:",
69
- "typescript": "catalog:",
70
- "vite-tsconfig-paths": "catalog:",
71
- "vitest": "catalog:"
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
+ }