esrieact 0.2.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/README.md CHANGED
@@ -76,7 +76,7 @@ Instead, wrapper components are available to make map presentation clear and dec
76
76
 
77
77
  ```ts
78
78
  import React from "react";
79
- import { FeatureLayer, MapView } from "./esri";
79
+ import { FeatureLayer, MapView } from "esrieact";
80
80
 
81
81
  export const ReactMap: React.FC = ({ layerList }) => {
82
82
  return (
@@ -119,7 +119,7 @@ Beacuse react-wrapped ESRI component props extend directly from ESRI class optio
119
119
 
120
120
  ```ts
121
121
  import React from "react";
122
- import { FeatureLayer, MapView } from "./esri";
122
+ import { FeatureLayer, MapView } from "esrieact";
123
123
 
124
124
  export const ReactMap: React.FC = ({ layerList }) => {
125
125
  return (
@@ -142,7 +142,7 @@ However, any propery then updated within the above `new Extent` would not regist
142
142
 
143
143
  ```ts
144
144
  import React from "react";
145
- import { FeatureLayer, MapView } from "./esri";
145
+ import { FeatureLayer, MapView } from "esrieact";
146
146
  import FeatureEffect from '@arcgis/core/layers/FeatureEffect'
147
147
  import FeatureFilter from '@arcgis/core/layers/FeatureFilter'
148
148
 
@@ -165,7 +165,7 @@ Because the property being updated is deeply nested within class-based ESRI comp
165
165
 
166
166
  ```ts
167
167
  import React from "react";
168
- import { FeatureLayer, MapView } from "./esri";
168
+ import { FeatureLayer, MapView } from "esrieact";
169
169
 
170
170
  export const ReactMap: React.FC = ({ layerList }) => {
171
171
  const [clause, setClause] = useState("SOME SQL CLAUSE");
@@ -247,7 +247,7 @@ One of the most used layer types is the `FeatureLayer`. A `FeatureLayer` can be
247
247
 
248
248
  ```ts
249
249
  import React from "react";
250
- import { FeatureLayer, FeautureLayerView, MapView } from "./esri";
250
+ import { FeatureLayer, FeautureLayerView, MapView } from "esrieact";
251
251
 
252
252
  export const ReactMap: React.FC = () => {
253
253
  const flRef = useRef<__esri.FeatureLayer>();
@@ -10,4 +10,12 @@ export type RendererProps<T extends __esri.RendererProperties = __esri.RendererP
10
10
  * any esri properties that extend esri.LayerProperties, and optional children
11
11
  */
12
12
  export type CreateRendererFunction<T extends RendererProps> = (properties: T) => __esri.Renderer;
13
+ /**
14
+ * Factory function to create an esrieact renderer component
15
+ * @param createRenderer - Function that takes in renderer properties and returns an esri Renderer instance. Properties must be
16
+ * any esri properties that extend esri.RendererProperties, and optional children
17
+ * @param ref - Ref to the renderer instance
18
+ * @param properties - Renderer properties
19
+ * @returns A context provider whose context is the renderer instance to be passed to children, or if there are no children, returns null
20
+ */
13
21
  export declare const createRendererComponent: (createRenderer: CreateRendererFunction<RendererProps>, ref: Ref<__esri.Renderer>, { children, ...properties }: RendererProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useEffect, useImperativeHandle, useMemo, } from "react";
2
+ import { createContext, useContext, useEffect, useImperativeHandle, useMemo, useRef, } from "react";
3
3
  import FeatureLayer from "@arcgis/core/layers/FeatureLayer";
4
4
  import SceneLayer from "@arcgis/core/layers/SceneLayer";
5
5
  import Sublayer from "@arcgis/core/layers/support/Sublayer";
@@ -15,11 +15,25 @@ import { useEsriPropertyUpdates } from "../../utils";
15
15
  * and makes available to its descendants
16
16
  */
17
17
  export const RendererContext = createContext({});
18
+ /**
19
+ * Factory function to create an esrieact renderer component
20
+ * @param createRenderer - Function that takes in renderer properties and returns an esri Renderer instance. Properties must be
21
+ * any esri properties that extend esri.RendererProperties, and optional children
22
+ * @param ref - Ref to the renderer instance
23
+ * @param properties - Renderer properties
24
+ * @returns A context provider whose context is the renderer instance to be passed to children, or if there are no children, returns null
25
+ */
18
26
  export const createRendererComponent = (createRenderer, ref, { children, ...properties }) => {
19
27
  const parent = useContext(LayerContext);
20
- const defaultRenderer = parent.renderer;
21
- const instance = useMemo(() => {
22
- const renderer = createRenderer(properties);
28
+ const defaultRenderer = useRef(parent.renderer?.clone());
29
+ // Just create the renderer instance (pure calculation)
30
+ const instance = useMemo(() => createRenderer(properties), []);
31
+ useImperativeHandle(ref, () => instance);
32
+ useEsriPropertyUpdates(instance, properties);
33
+ /**
34
+ * Assign the renderer on mount and clean up on unmount
35
+ */
36
+ useEffect(() => {
23
37
  if (parent instanceof FeatureLayer ||
24
38
  parent instanceof SceneLayer ||
25
39
  parent instanceof Sublayer ||
@@ -28,21 +42,12 @@ export const createRendererComponent = (createRenderer, ref, { children, ...prop
28
42
  parent instanceof OGCFeatureLayer ||
29
43
  parent instanceof StreamLayer ||
30
44
  parent instanceof WFSLayer) {
31
- parent.renderer = renderer;
45
+ parent.renderer = instance;
32
46
  }
33
47
  else {
34
- // Allow this because it only happens in development and is helpful for devs
35
- // eslint-disable-next-line
48
+ // eslint-disable-next-line no-console
36
49
  console.error("You are trying to use a <Renderer /> component as the descendant of a component that does not take an ESRI renderer.");
37
50
  }
38
- return renderer;
39
- }, []);
40
- useImperativeHandle(ref, () => instance);
41
- useEsriPropertyUpdates(instance, properties);
42
- /**
43
- * Set the renderer of the parent layer back to its initial default on unmount
44
- */
45
- useEffect(() => {
46
51
  return () => {
47
52
  if (parent instanceof FeatureLayer ||
48
53
  parent instanceof SceneLayer ||
@@ -52,10 +57,10 @@ export const createRendererComponent = (createRenderer, ref, { children, ...prop
52
57
  parent instanceof OGCFeatureLayer ||
53
58
  parent instanceof StreamLayer ||
54
59
  parent instanceof WFSLayer) {
55
- parent.renderer = defaultRenderer;
60
+ parent.renderer = defaultRenderer.current;
56
61
  }
57
62
  };
58
- }, []);
63
+ }, [parent, instance, defaultRenderer]);
59
64
  // If no children, there is no need to render a context provider
60
65
  if (!children)
61
66
  return null;
@@ -1,10 +1,6 @@
1
- import React, { useContext, useImperativeHandle, useMemo } from "react";
1
+ import React from "react";
2
2
  import EsriPictureMarkerSymbol from "@arcgis/core/symbols/PictureMarkerSymbol.js";
3
- import Graphic from "@arcgis/core/Graphic";
4
- import Renderer from "@arcgis/core/renderers/Renderer";
5
- import { GraphicContext } from "../Graphic";
6
- import { useEsriPropertyUpdates } from "../../utils";
7
- import { RendererContext } from "../renderers";
3
+ import { createSymbolComponent } from "./createSymbolComponent";
8
4
  /**
9
5
  * A PictureMarkerSymbol component, must be rendered as a child of a Renderer component or Graphic component
10
6
  *
@@ -12,32 +8,5 @@ import { RendererContext } from "../renderers";
12
8
  * - [PictureMarkerSymbol](https://developers.arcgis.com/javascript/latest/api-reference/esri-symbols-PictureMarkerSymbol.html)
13
9
  */
14
10
  export const PictureMarkerSymbol = React.forwardRef((properties, ref) => {
15
- const parentGraphic = useContext(GraphicContext);
16
- const parentRenderer = useContext(RendererContext);
17
- /**
18
- * Create instance only on first mount
19
- */
20
- const instance = useMemo(() => {
21
- const symbol = new EsriPictureMarkerSymbol(properties);
22
- if (!(parentGraphic instanceof Graphic) &&
23
- !(parentRenderer instanceof Renderer)) {
24
- // Allow this because it only happens in development and is helpful for devs
25
- // eslint-disable-next-line
26
- console.error("You are trying to render a PictureMarkerSymbol component that is not a descendant of a Graphic or Renderer.", "Did you forget to wrap your PictureMarkerSymbol in a Graphic or Renderer?");
27
- return;
28
- }
29
- if (parentRenderer) {
30
- // @ts-expect-error allow this for renderers that do take a symbol
31
- parentRenderer.symbol = symbol;
32
- return symbol;
33
- }
34
- if (parentGraphic) {
35
- parentGraphic.symbol = symbol;
36
- return symbol;
37
- }
38
- return symbol;
39
- }, []);
40
- useImperativeHandle(ref, () => instance);
41
- useEsriPropertyUpdates(instance, properties);
42
- return null;
11
+ return createSymbolComponent((props) => new EsriPictureMarkerSymbol(props), ref, properties, "PictureMarkerSymbol");
43
12
  });
@@ -1,9 +1,6 @@
1
- import React, { useContext, useImperativeHandle, useMemo } from "react";
1
+ import React from "react";
2
2
  import EsriSimpleFillSymbol from "@arcgis/core/symbols/SimpleFillSymbol";
3
- import Graphic from "@arcgis/core/Graphic";
4
- import Renderer from "@arcgis/core/renderers/Renderer";
5
- import { GraphicContext } from "../Graphic";
6
- import { useEsriPropertyUpdates } from "../../utils";
3
+ import { createSymbolComponent } from "./createSymbolComponent";
7
4
  /**
8
5
  * A SimpleFillSymbol component, must be rendered as a child of a Renderer component or Graphic component
9
6
  *
@@ -11,24 +8,5 @@ import { useEsriPropertyUpdates } from "../../utils";
11
8
  * - [SimpleFillSymbol](https://developers.arcgis.com/javascript/latest/api-reference/esri-symbols-SimpleFillSymbol.html)
12
9
  */
13
10
  export const SimpleFillSymbol = React.forwardRef((properties, ref) => {
14
- const parent = useContext(GraphicContext);
15
- /**
16
- * Create instance only on first mount
17
- */
18
- const instance = useMemo(() => {
19
- const symbol = new EsriSimpleFillSymbol(properties);
20
- if (!(parent instanceof Graphic) || !(parent instanceof Renderer)) {
21
- // Allow this because it only happens in development and is helpful for devs
22
- // eslint-disable-next-line
23
- console.error("You are trying to render a SimpleFillSymbol component that is not a descendant of a Graphic or Renderer.", "Did you forget to wrap your SimpleFillSymbol in a Graphic or Renderer?");
24
- return;
25
- }
26
- if (parent) {
27
- parent.symbol = symbol;
28
- }
29
- return symbol;
30
- }, []);
31
- useImperativeHandle(ref, () => instance);
32
- useEsriPropertyUpdates(instance, properties);
33
- return null;
11
+ return createSymbolComponent((props) => new EsriSimpleFillSymbol(props), ref, properties, "SimpleFillSymbol");
34
12
  });
@@ -0,0 +1,22 @@
1
+ import React, { Ref } from "react";
2
+ /**
3
+ * The react context object that any symbol component creates when rendered
4
+ * and makes available to its descendants
5
+ */
6
+ export declare const SymbolContext: React.Context<__esri.Symbol>;
7
+ export type SymbolProps<T extends __esri.SymbolProperties = __esri.SymbolProperties> = React.PropsWithChildren<T>;
8
+ /**
9
+ * Function that takes in symbol properties and returns an esri Symbol instance. Properties must be
10
+ * any esri properties that extend esri.SymbolProperties, and optional children
11
+ */
12
+ export type CreateSymbolFunction<T extends SymbolProps> = (properties: T) => __esri.Symbol;
13
+ /**
14
+ * Factory function to create an esrieact symbol component
15
+ * @param createSymbol - Function that takes in symbol properties and returns an esri Symbol instance. Properties must be
16
+ * any esri properties that extend esri.SymbolProperties, and optional children
17
+ * @param ref - Ref to the symbol instance
18
+ * @param properties - Symbol properties
19
+ * @param componentName - Name of the component for error messages
20
+ * @returns A context provider whose context is the symbol instance to be passed to children, or if there are no children, returns null
21
+ */
22
+ export declare const createSymbolComponent: (createSymbol: CreateSymbolFunction<SymbolProps>, ref: Ref<__esri.Symbol>, properties: SymbolProps, componentName: string) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useEffect, useImperativeHandle, useMemo, } from "react";
3
+ import Graphic from "@arcgis/core/Graphic";
4
+ import Renderer from "@arcgis/core/renderers/Renderer";
5
+ import { GraphicContext } from "../Graphic";
6
+ import { useEsriPropertyUpdates } from "../../utils";
7
+ import { RendererContext } from "../renderers";
8
+ /**
9
+ * The react context object that any symbol component creates when rendered
10
+ * and makes available to its descendants
11
+ */
12
+ export const SymbolContext = createContext({});
13
+ /**
14
+ * Factory function to create an esrieact symbol component
15
+ * @param createSymbol - Function that takes in symbol properties and returns an esri Symbol instance. Properties must be
16
+ * any esri properties that extend esri.SymbolProperties, and optional children
17
+ * @param ref - Ref to the symbol instance
18
+ * @param properties - Symbol properties
19
+ * @param componentName - Name of the component for error messages
20
+ * @returns A context provider whose context is the symbol instance to be passed to children, or if there are no children, returns null
21
+ */
22
+ export const createSymbolComponent = (createSymbol, ref, properties, componentName) => {
23
+ const parentGraphic = useContext(GraphicContext);
24
+ const parentRenderer = useContext(RendererContext);
25
+ // Just create the symbol instance (pure calculation)
26
+ const instance = useMemo(() => createSymbol(properties), []);
27
+ useImperativeHandle(ref, () => instance);
28
+ useEsriPropertyUpdates(instance, properties);
29
+ /**
30
+ * Assign the symbol on mount and clean up on unmount
31
+ */
32
+ useEffect(() => {
33
+ if (!(parentGraphic instanceof Graphic) &&
34
+ !(parentRenderer instanceof Renderer)) {
35
+ // Allow this because it only happens in development and is helpful for devs
36
+ // eslint-disable-next-line
37
+ console.error(`You are trying to render a ${componentName} component that is not a descendant of a Graphic or Renderer.`, `Did you forget to wrap your ${componentName} in a Graphic or Renderer?`);
38
+ return;
39
+ }
40
+ if (parentRenderer) {
41
+ // @ts-expect-error allow this for renderers that do take a symbol
42
+ parentRenderer.symbol = instance;
43
+ }
44
+ if (parentGraphic) {
45
+ // @ts-expect-error Allow generic __esri.Symbol to be assigned to various specific parent graphic symbol types
46
+ parentGraphic.symbol = instance;
47
+ }
48
+ }, [instance, parentGraphic, parentRenderer, componentName]);
49
+ // If no children, there is no need to render a context provider
50
+ if (!properties.children)
51
+ return null;
52
+ return (_jsx(SymbolContext.Provider, { value: instance, children: properties.children }));
53
+ };
@@ -1,2 +1,3 @@
1
1
  export * from "./PictureMarkerSymbol";
2
2
  export * from "./SimpleFillSymbol";
3
+ export * from "./createSymbolComponent";
@@ -1,2 +1,3 @@
1
1
  export * from "./PictureMarkerSymbol";
2
2
  export * from "./SimpleFillSymbol";
3
+ export * from "./createSymbolComponent";
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import EsriGeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer";
3
+ /**
4
+ * An event handler function map for events specific to a GeoJSONLayer
5
+ *
6
+ * From [ArcGIS JS API documentation](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html#events-summary)
7
+ */
8
+ export type GeoJSONLayerEventHandlerFnMap = Partial<{
9
+ refresh: __esri.GeoJSONLayerRefreshEventHandler;
10
+ edits: __esri.GeoJSONLayerEditsEventHandler;
11
+ "layerview-create": __esri.GeoJSONLayerLayerviewCreateEventHandler;
12
+ "layerview-create-error": __esri.GeoJSONLayerLayerviewCreateErrorEventHandler;
13
+ "layerview-destroy": __esri.GeoJSONLayerLayerviewDestroyEventHandler;
14
+ }>;
15
+ /**
16
+ * A FeatureLayer component
17
+ *
18
+ * ArcGIS JS API Source Components:
19
+ * - [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html)
20
+ */
21
+ export declare const GeoJSONLayer: React.ForwardRefExoticComponent<__esri.GeoJSONLayerProperties & {
22
+ children?: React.ReactNode;
23
+ } & {
24
+ events?: Partial<{
25
+ refresh: __esri.GeoJSONLayerRefreshEventHandler;
26
+ edits: __esri.GeoJSONLayerEditsEventHandler;
27
+ "layerview-create": __esri.GeoJSONLayerLayerviewCreateEventHandler;
28
+ "layerview-create-error": __esri.GeoJSONLayerLayerviewCreateErrorEventHandler;
29
+ "layerview-destroy": __esri.GeoJSONLayerLayerviewDestroyEventHandler;
30
+ }> | undefined;
31
+ layerOrder?: number | undefined;
32
+ } & React.RefAttributes<EsriGeoJSONLayer>>;
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import EsriGeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer";
3
+ import { createLayerComponent, } from "./createLayerComponent";
4
+ /**
5
+ * Function that takes in properties of a GeoJSONLayer, and returns the GeoJSONLayer instance
6
+ */
7
+ const createLayer = (properties) => {
8
+ return new EsriGeoJSONLayer(properties);
9
+ };
10
+ /**
11
+ * A FeatureLayer component
12
+ *
13
+ * ArcGIS JS API Source Components:
14
+ * - [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html)
15
+ */
16
+ export const GeoJSONLayer = React.forwardRef((properties, ref) => createLayerComponent(createLayer, ref, properties));
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
2
  import EsriMapImageLayer from "@arcgis/core/layers/MapImageLayer";
3
+ export type MapImageLayerEventHandlerFnMap = Partial<{
4
+ refresh: __esri.MapImageLayerRefreshEventHandler;
5
+ "layerview-create": __esri.MapImageLayerLayerviewCreateEventHandler;
6
+ "layerview-create-error": __esri.MapImageLayerLayerviewCreateErrorEventHandler;
7
+ "layerview-destroy": __esri.MapImageLayerLayerviewDestroyEventHandler;
8
+ }>;
3
9
  /**
4
10
  * A MapImageLayer component
5
11
  *
@@ -9,6 +15,11 @@ import EsriMapImageLayer from "@arcgis/core/layers/MapImageLayer";
9
15
  export declare const MapImageLayer: React.ForwardRefExoticComponent<__esri.MapImageLayerProperties & {
10
16
  children?: React.ReactNode;
11
17
  } & {
12
- events?: {} | undefined;
18
+ events?: Partial<{
19
+ refresh: __esri.MapImageLayerRefreshEventHandler;
20
+ "layerview-create": __esri.MapImageLayerLayerviewCreateEventHandler;
21
+ "layerview-create-error": __esri.MapImageLayerLayerviewCreateErrorEventHandler;
22
+ "layerview-destroy": __esri.MapImageLayerLayerviewDestroyEventHandler;
23
+ }> | undefined;
13
24
  layerOrder?: number | undefined;
14
25
  } & React.RefAttributes<EsriMapImageLayer>>;
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
2
  import EsriVectorTileLayer from "@arcgis/core/layers/VectorTileLayer";
3
+ export type VectorTileLayerEventHandlerFnMap = Partial<{
4
+ refresh: __esri.VectorTileLayerRefreshEventHandler;
5
+ "layerview-create": __esri.VectorTileLayerLayerviewCreateEventHandler;
6
+ "layerview-create-error": __esri.VectorTileLayerLayerviewCreateErrorEventHandler;
7
+ "layerview-destroy": __esri.VectorTileLayerLayerviewDestroyEventHandler;
8
+ }>;
3
9
  /**
4
10
  * A VectorTileLayer component
5
11
  *
@@ -9,6 +15,11 @@ import EsriVectorTileLayer from "@arcgis/core/layers/VectorTileLayer";
9
15
  export declare const VectorTileLayer: React.ForwardRefExoticComponent<__esri.VectorTileLayerProperties & {
10
16
  children?: React.ReactNode;
11
17
  } & {
12
- events?: {} | undefined;
18
+ events?: Partial<{
19
+ refresh: __esri.VectorTileLayerRefreshEventHandler;
20
+ "layerview-create": __esri.VectorTileLayerLayerviewCreateEventHandler;
21
+ "layerview-create-error": __esri.VectorTileLayerLayerviewCreateErrorEventHandler;
22
+ "layerview-destroy": __esri.VectorTileLayerLayerviewDestroyEventHandler;
23
+ }> | undefined;
13
24
  layerOrder?: number | undefined;
14
25
  } & React.RefAttributes<EsriVectorTileLayer>>;
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
2
  import EsriWMSLayer from "@arcgis/core/layers/WMSLayer";
3
+ export type WMSLayerEventHandlerFnMap = Partial<{
4
+ refresh: __esri.WMSLayerRefreshEventHandler;
5
+ "layerview-create": __esri.WMSLayerLayerviewCreateEventHandler;
6
+ "layerview-create-error": __esri.WMSLayerLayerviewCreateErrorEventHandler;
7
+ "layerview-destroy": __esri.WMSLayerLayerviewDestroyEventHandler;
8
+ }>;
3
9
  /**
4
10
  * A WMS Layer component
5
11
  *
@@ -9,6 +15,11 @@ import EsriWMSLayer from "@arcgis/core/layers/WMSLayer";
9
15
  export declare const WMSLayer: React.ForwardRefExoticComponent<__esri.WMSLayerProperties & {
10
16
  children?: React.ReactNode;
11
17
  } & {
12
- events?: {} | undefined;
18
+ events?: Partial<{
19
+ refresh: __esri.WMSLayerRefreshEventHandler;
20
+ "layerview-create": __esri.WMSLayerLayerviewCreateEventHandler;
21
+ "layerview-create-error": __esri.WMSLayerLayerviewCreateErrorEventHandler;
22
+ "layerview-destroy": __esri.WMSLayerLayerviewDestroyEventHandler;
23
+ }> | undefined;
13
24
  layerOrder?: number | undefined;
14
25
  } & React.RefAttributes<EsriWMSLayer>>;
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
2
  import EsriWebTileLayer from "@arcgis/core/layers/WebTileLayer";
3
+ export type WebTileLayerEventHandlerFnMap = Partial<{
4
+ refresh: __esri.WebTileLayerRefreshEventHandler;
5
+ "layerview-create": __esri.WebTileLayerLayerviewCreateEventHandler;
6
+ "layerview-create-error": __esri.WebTileLayerLayerviewCreateErrorEventHandler;
7
+ "layerview-destroy": __esri.WebTileLayerLayerviewDestroyEventHandler;
8
+ }>;
3
9
  /**
4
10
  * An WebTileLayer component
5
11
  *
@@ -9,6 +15,11 @@ import EsriWebTileLayer from "@arcgis/core/layers/WebTileLayer";
9
15
  export declare const WebTileLayer: React.ForwardRefExoticComponent<__esri.WebTileLayerProperties & {
10
16
  children?: React.ReactNode;
11
17
  } & {
12
- events?: {} | undefined;
18
+ events?: Partial<{
19
+ refresh: __esri.WebTileLayerRefreshEventHandler;
20
+ "layerview-create": __esri.WebTileLayerLayerviewCreateEventHandler;
21
+ "layerview-create-error": __esri.WebTileLayerLayerviewCreateErrorEventHandler;
22
+ "layerview-destroy": __esri.WebTileLayerLayerviewDestroyEventHandler;
23
+ }> | undefined;
13
24
  layerOrder?: number | undefined;
14
25
  } & React.RefAttributes<EsriWebTileLayer>>;
@@ -8,9 +8,9 @@ export declare const LayerContext: React.Context<__esri.Layer | __esri.GroupLaye
8
8
  * Event handlers for all Layer components, some layer components may extend from this
9
9
  */
10
10
  export interface LayerEventHandlerFnMap {
11
- "layerview-create": __esri.FeatureLayerLayerviewCreateEventHandler;
12
- "layerview-create-error": __esri.FeatureLayerLayerviewCreateErrorEventHandler;
13
- "layerview-destroy": __esri.FeatureLayerLayerviewDestroyEventHandler;
11
+ "layerview-create": __esri.LayerLayerviewCreateEventHandler;
12
+ "layerview-create-error": __esri.LayerLayerviewCreateErrorEventHandler;
13
+ "layerview-destroy": __esri.LayerLayerviewDestroyEventHandler;
14
14
  }
15
15
  /**
16
16
  * Properties that can be applied to any ESRIEACT Layer component. Extends from
@@ -21,18 +21,7 @@ export const createLayerComponent = (createLayer, ref, { children, events, layer
21
21
  /**
22
22
  * Create instance only on first mount
23
23
  */
24
- const instance = useMemo(() => {
25
- const layer = createLayer(properties);
26
- // If the parent is a GroupLayer (or any EsriInstance that has the .add(layer) method), add it to that,
27
- // otherwise, add directly to the map
28
- if (parent && parent.add) {
29
- parent.add(layer, layerOrder);
30
- }
31
- else {
32
- map.add(layer, layerOrder);
33
- }
34
- return layer;
35
- }, []);
24
+ const instance = useMemo(() => createLayer(properties), []);
36
25
  useImperativeHandle(ref, () => instance);
37
26
  useEsriPropertyUpdates(instance, properties);
38
27
  useEvents(instance, events);
@@ -43,6 +32,12 @@ export const createLayerComponent = (createLayer, ref, { children, events, layer
43
32
  * https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/fade-a-layer-on-off-smoothly/m-p/70174
44
33
  */
45
34
  useEffect(() => {
35
+ if (parent && parent.add) {
36
+ parent.add(instance, layerOrder);
37
+ }
38
+ else {
39
+ map.add(instance, layerOrder);
40
+ }
46
41
  return () => {
47
42
  if (parent && parent.remove) {
48
43
  parent.remove(instance);
@@ -51,7 +46,7 @@ export const createLayerComponent = (createLayer, ref, { children, events, layer
51
46
  map.remove(instance);
52
47
  }
53
48
  };
54
- }, []);
49
+ }, [instance, parent, map, layerOrder]);
55
50
  // If no children, there is no need to render a context provider
56
51
  if (!children)
57
52
  return null;
@@ -10,3 +10,4 @@ export * from "./WebTileLayer";
10
10
  export * from "./WMSLayer";
11
11
  export * from "./VectorTileLayer";
12
12
  export * from "./MapImageLayer";
13
+ export * from "./GeoJSONLayer";
@@ -10,3 +10,4 @@ export * from "./WebTileLayer";
10
10
  export * from "./WMSLayer";
11
11
  export * from "./VectorTileLayer";
12
12
  export * from "./MapImageLayer";
13
+ export * from "./GeoJSONLayer";
@@ -4,7 +4,9 @@ import EsriWidget from "@arcgis/core/widgets/Widget";
4
4
  * Properties that can be applied to any ESRIEACT Widget component. Extends from
5
5
  * esri's WidgetProperties to include child components and the widget position
6
6
  */
7
- export type WidgetComponentProps<T extends __esri.WidgetProperties = __esri.WidgetProperties, E extends Record<string, Function> = {}> = React.PropsWithChildren<T> & {
7
+ export type WidgetComponentProps<T extends __esri.WidgetProperties = __esri.WidgetProperties & {
8
+ view?: __esri.MapView;
9
+ }, E extends Record<string, Function> = {}> = React.PropsWithChildren<T> & {
8
10
  events?: E;
9
11
  position?: string | __esri.UIAddPosition;
10
12
  };
@@ -26,4 +28,4 @@ export declare const WidgetContext: React.Context<EsriWidget>;
26
28
  * @param properties The widget properties
27
29
  * @returns A context provider whose context is the instance to be passed to children, or if there are no children, returns null
28
30
  */
29
- export declare function createWidgetComponent<P extends WidgetComponentProps>(createWidget: CreateWidgetFunction, ref: Ref<EsriWidget>, { children, events, position, ...properties }: P): import("react/jsx-runtime").JSX.Element | null;
31
+ export declare function createWidgetComponent<P extends WidgetComponentProps>(createWidget: CreateWidgetFunction, ref: Ref<EsriWidget>, { children, events, position, view, ...properties }: P): import("react/jsx-runtime").JSX.Element | null;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useEffect, useImperativeHandle, useMemo, } from "react";
2
+ import React, { createContext, useContext, useEffect, useImperativeHandle, useMemo, useRef, } from "react";
3
3
  import Expand from "@arcgis/core/widgets/Expand";
4
4
  import { useMap } from "..";
5
5
  import { useEsriPropertyUpdates, useEvents } from "../utils";
@@ -16,9 +16,10 @@ export const WidgetContext = createContext({});
16
16
  * @param properties The widget properties
17
17
  * @returns A context provider whose context is the instance to be passed to children, or if there are no children, returns null
18
18
  */
19
- export function createWidgetComponent(createWidget, ref, { children, events, position, ...properties }) {
19
+ export function createWidgetComponent(createWidget, ref, { children, events, position, view: viewFromProps, ...properties }) {
20
20
  const { view } = useMap();
21
21
  const parentWidgetContext = useContext(WidgetContext);
22
+ const childrenRef = useRef(null);
22
23
  const instance = useMemo(() => {
23
24
  const instance = createWidget({ ...properties, view });
24
25
  if (parentWidgetContext instanceof Expand) {
@@ -29,10 +30,23 @@ export function createWidgetComponent(createWidget, ref, { children, events, pos
29
30
  view.ui.add(instance, position);
30
31
  }
31
32
  return instance;
32
- }, []);
33
+ }, [view]);
33
34
  useImperativeHandle(ref, () => instance);
34
35
  useEsriPropertyUpdates(instance, properties);
35
36
  useEvents(instance, events);
37
+ /**
38
+ * Check if children is a singular HTML element and assign its ref to instance.content,
39
+ * enables dev to make arbitrary UI elements children of an Expand widget
40
+ */
41
+ useEffect(() => {
42
+ if (children && childrenRef.current && instance) {
43
+ if (React.isValidElement(children)) {
44
+ if (instance instanceof Expand) {
45
+ instance.content = childrenRef.current;
46
+ }
47
+ }
48
+ }
49
+ }, [children, instance]);
36
50
  /**
37
51
  * Remove widget on unmount
38
52
  */
@@ -43,5 +57,8 @@ export function createWidgetComponent(createWidget, ref, { children, events, pos
43
57
  }, []);
44
58
  if (!children)
45
59
  return null;
46
- return (_jsx(WidgetContext.Provider, { value: instance, children: children }));
60
+ // Pass ref to the child element - works for both HTML elements and forwardRef components
61
+ return (_jsx(WidgetContext.Provider, { value: instance, children: React.cloneElement(children, {
62
+ ref: childrenRef,
63
+ }) }));
47
64
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "esrieact",
3
3
  "private": false,
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [