expo-arcgis 0.1.8 → 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/android/src/main/java/expo/modules/arcgis/ExpoArcgisExtrasModule.kt +48 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisMapView.kt +31 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisModule.kt +14 -31
- package/android/src/main/java/expo/modules/arcgis/GraphicsOverlayRef.kt +45 -3
- package/android/src/main/java/expo/modules/arcgis/ImageOverlayRef.kt +28 -0
- package/android/src/main/java/expo/modules/arcgis/LayerRef.kt +39 -0
- package/build/DynamicEntityLayer.d.ts.map +1 -1
- package/build/ExpoArcgis.types.d.ts +111 -7
- package/build/ExpoArcgis.types.d.ts.map +1 -1
- package/build/ExpoArcgis.types.js.map +1 -1
- package/build/ExpoArcgisExtrasModule.d.ts +7 -1
- package/build/ExpoArcgisExtrasModule.d.ts.map +1 -1
- package/build/ExpoArcgisExtrasModule.js.map +1 -1
- package/build/ExpoArcgisModule.d.ts +8 -4
- package/build/ExpoArcgisModule.d.ts.map +1 -1
- package/build/ExpoArcgisModule.js.map +1 -1
- package/build/ImageOverlay.d.ts +8 -0
- package/build/ImageOverlay.d.ts.map +1 -0
- package/build/ImageOverlay.js +30 -0
- package/build/ImageOverlay.js.map +1 -0
- package/build/MapView.d.ts.map +1 -1
- package/build/MapView.js +4 -1
- package/build/MapView.js.map +1 -1
- package/build/SceneView.d.ts.map +1 -1
- package/build/SceneView.js +3 -0
- package/build/SceneView.js.map +1 -1
- package/build/UtilityNetwork.d.ts.map +1 -1
- package/build/UtilityNetwork.js +3 -2
- package/build/UtilityNetwork.js.map +1 -1
- package/build/contexts.d.ts +7 -2
- package/build/contexts.d.ts.map +1 -1
- package/build/contexts.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/ios/ExpoArcgisExtrasModule.swift +48 -0
- package/ios/ExpoArcgisMapView.swift +27 -1
- package/ios/ExpoArcgisModule.swift +14 -31
- package/ios/GraphicsOverlayRef.swift +35 -3
- package/ios/ImageOverlayRef.swift +23 -0
- package/ios/LayerRef.swift +47 -0
- package/package.json +1 -1
- package/src/ExpoArcgis.types.ts +123 -7
- package/src/ExpoArcgisExtrasModule.ts +10 -1
- package/src/ExpoArcgisModule.ts +20 -1
- package/src/ImageOverlay.tsx +36 -0
- package/src/MapView.tsx +14 -1
- package/src/SceneView.tsx +3 -0
- package/src/UtilityNetwork.tsx +4 -2
- package/src/contexts.ts +11 -1
- package/src/index.ts +1 -0
|
@@ -41,6 +41,12 @@ class ExpoArcgisExtrasModule : Module() {
|
|
|
41
41
|
AsyncFunction("addFeature") Coroutine { ref: FeatureLayerRef, attributes: Map<String, Any?>, geometry: Map<String, Any?>?, apply: Boolean? ->
|
|
42
42
|
ref.addFeature(attributes, geometry, apply)
|
|
43
43
|
}
|
|
44
|
+
AsyncFunction("addFeatureWithTemplate") Coroutine { ref: FeatureLayerRef, templateName: String, attributes: Map<String, Any?>?, geometry: Map<String, Any?>?, apply: Boolean? ->
|
|
45
|
+
ref.addFeatureWithTemplate(templateName, attributes, geometry, apply)
|
|
46
|
+
}
|
|
47
|
+
AsyncFunction("addFeatureWithSubtype") Coroutine { ref: FeatureLayerRef, subtypeName: String, attributes: Map<String, Any?>?, geometry: Map<String, Any?>?, apply: Boolean? ->
|
|
48
|
+
ref.addFeatureWithSubtype(subtypeName, attributes, geometry, apply)
|
|
49
|
+
}
|
|
44
50
|
AsyncFunction("updateFeature") Coroutine { ref: FeatureLayerRef, objectId: Long, changes: Map<String, Any?>, apply: Boolean? ->
|
|
45
51
|
ref.updateFeature(objectId, changes, apply)
|
|
46
52
|
}
|
|
@@ -144,5 +150,47 @@ class ExpoArcgisExtrasModule : Module() {
|
|
|
144
150
|
Function("getFeatureTableNames") { ref: GeodatabaseRef -> ref.getFeatureTableNames() }
|
|
145
151
|
Function("getFeatureLayer") { ref: GeodatabaseRef, tableName: String -> ref.getFeatureLayer(tableName) }
|
|
146
152
|
}
|
|
153
|
+
|
|
154
|
+
// Moved from the main module to stay under the Android 64 KB method-size limit on definition().
|
|
155
|
+
Class(UtilityNetworkRef::class) {
|
|
156
|
+
Constructor { props: Map<String, Any?> ->
|
|
157
|
+
UtilityNetworkRef(appContext, props["serviceGeodatabaseUrl"] as? String ?: "")
|
|
158
|
+
}
|
|
159
|
+
AsyncFunction("load") Coroutine { ref: UtilityNetworkRef, map: MapRef ->
|
|
160
|
+
ref.load(map)
|
|
161
|
+
}
|
|
162
|
+
Function("describeNetwork") { ref: UtilityNetworkRef -> ref.describeNetwork() }
|
|
163
|
+
AsyncFunction("trace") Coroutine { ref: UtilityNetworkRef, traceType: String, startingLocations: List<Map<String, Any?>> ->
|
|
164
|
+
ref.trace(traceType, startingLocations)
|
|
165
|
+
}
|
|
166
|
+
AsyncFunction("traceFromQuery") Coroutine { ref: UtilityNetworkRef, tableName: String, whereClause: String, traceType: String ->
|
|
167
|
+
ref.traceFromQuery(tableName, whereClause, traceType)
|
|
168
|
+
}
|
|
169
|
+
AsyncFunction("queryNamedTraceConfigurations") Coroutine { ref: UtilityNetworkRef ->
|
|
170
|
+
ref.queryNamedTraceConfigurations()
|
|
171
|
+
}
|
|
172
|
+
AsyncFunction("traceWithConfiguration") Coroutine { ref: UtilityNetworkRef, configGlobalId: String, tableName: String, whereClause: String ->
|
|
173
|
+
ref.traceWithConfiguration(configGlobalId, tableName, whereClause)
|
|
174
|
+
}
|
|
175
|
+
AsyncFunction("associations") Coroutine { ref: UtilityNetworkRef, tableName: String, whereClause: String ->
|
|
176
|
+
ref.associations(tableName, whereClause)
|
|
177
|
+
}
|
|
178
|
+
Function("getTerminalConfigurations") { ref: UtilityNetworkRef ->
|
|
179
|
+
ref.getTerminalConfigurations()
|
|
180
|
+
}
|
|
181
|
+
AsyncFunction("getState") Coroutine { ref: UtilityNetworkRef -> ref.getState() }
|
|
182
|
+
Function("validateNetworkTopology") { ref: UtilityNetworkRef, extent: Map<String, Any?> ->
|
|
183
|
+
ref.validateNetworkTopology(extent)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Georeferenced image overlay (added to a <MapView> via <ImageOverlay>).
|
|
188
|
+
Class(ImageOverlayRef::class) {
|
|
189
|
+
Constructor { ImageOverlayRef(appContext) }
|
|
190
|
+
Function("setFrame") { ref: ImageOverlayRef, imagePath: String, extent: Map<String, Any?>, opacity: Double? ->
|
|
191
|
+
ref.setFrame(imagePath, extent, opacity)
|
|
192
|
+
}
|
|
193
|
+
Function("setOpacity") { ref: ImageOverlayRef, opacity: Double -> ref.setOpacity(opacity) }
|
|
194
|
+
}
|
|
147
195
|
}
|
|
148
196
|
}
|
|
@@ -131,6 +131,11 @@ class ExpoArcgisMapView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
131
131
|
mapView.graphicsOverlays.addAll(refs.map { it.overlay })
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
fun setImageOverlays(refs: List<ImageOverlayRef>) {
|
|
135
|
+
mapView.imageOverlays.clear()
|
|
136
|
+
mapView.imageOverlays.addAll(refs.map { it.overlay })
|
|
137
|
+
}
|
|
138
|
+
|
|
134
139
|
/** Animates the view to a runtime viewpoint sent from JS. */
|
|
135
140
|
fun setViewpoint(vp: Map<String, Any?>?) {
|
|
136
141
|
vp ?: return
|
|
@@ -231,6 +236,32 @@ class ExpoArcgisMapView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
231
236
|
}
|
|
232
237
|
}
|
|
233
238
|
|
|
239
|
+
/** Returns the names of the displayed map's bookmarks (e.g. those saved in a loaded web map). */
|
|
240
|
+
fun getBookmarkNames(promise: Promise) {
|
|
241
|
+
val map = mapView.map ?: run { promise.resolve(emptyList<String>()); return }
|
|
242
|
+
scope.launch {
|
|
243
|
+
map.load()
|
|
244
|
+
.onSuccess { promise.resolve(map.bookmarks.map { it.name }) }
|
|
245
|
+
.onFailure { e -> promise.reject("BOOKMARK_ERROR", e.message ?: "Failed to load map", e) }
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Navigates to the named bookmark's viewpoint; resolves whether a matching bookmark was found. */
|
|
250
|
+
fun setBookmark(name: String, promise: Promise) {
|
|
251
|
+
val map = mapView.map ?: run { promise.resolve(false); return }
|
|
252
|
+
scope.launch {
|
|
253
|
+
try {
|
|
254
|
+
map.load().getOrThrow()
|
|
255
|
+
val viewpoint = map.bookmarks.firstOrNull { it.name == name }?.viewpoint
|
|
256
|
+
?: run { promise.resolve(false); return@launch }
|
|
257
|
+
mapView.setViewpointAnimated(viewpoint, 0.5f)
|
|
258
|
+
promise.resolve(true)
|
|
259
|
+
} catch (e: Exception) {
|
|
260
|
+
promise.reject("BOOKMARK_ERROR", e.message ?: "Failed", e)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
234
265
|
override fun onAttachedToWindow() {
|
|
235
266
|
super.onAttachedToWindow()
|
|
236
267
|
// The view-based MapView renders only while observing a lifecycle.
|
|
@@ -336,37 +336,8 @@ class ExpoArcgisModule : Module() {
|
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
// Utility network — loaded from a feature service, attached to a <Map>; runs traces.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
UtilityNetworkRef(appContext, props["serviceGeodatabaseUrl"] as? String ?: "")
|
|
342
|
-
}
|
|
343
|
-
AsyncFunction("load") Coroutine { ref: UtilityNetworkRef, map: MapRef ->
|
|
344
|
-
ref.load(map)
|
|
345
|
-
}
|
|
346
|
-
Function("describeNetwork") { ref: UtilityNetworkRef -> ref.describeNetwork() }
|
|
347
|
-
AsyncFunction("trace") Coroutine { ref: UtilityNetworkRef, traceType: String, startingLocations: List<Map<String, Any?>> ->
|
|
348
|
-
ref.trace(traceType, startingLocations)
|
|
349
|
-
}
|
|
350
|
-
AsyncFunction("traceFromQuery") Coroutine { ref: UtilityNetworkRef, tableName: String, whereClause: String, traceType: String ->
|
|
351
|
-
ref.traceFromQuery(tableName, whereClause, traceType)
|
|
352
|
-
}
|
|
353
|
-
AsyncFunction("queryNamedTraceConfigurations") Coroutine { ref: UtilityNetworkRef ->
|
|
354
|
-
ref.queryNamedTraceConfigurations()
|
|
355
|
-
}
|
|
356
|
-
AsyncFunction("traceWithConfiguration") Coroutine { ref: UtilityNetworkRef, configGlobalId: String, tableName: String, whereClause: String ->
|
|
357
|
-
ref.traceWithConfiguration(configGlobalId, tableName, whereClause)
|
|
358
|
-
}
|
|
359
|
-
AsyncFunction("associations") Coroutine { ref: UtilityNetworkRef, tableName: String, whereClause: String ->
|
|
360
|
-
ref.associations(tableName, whereClause)
|
|
361
|
-
}
|
|
362
|
-
Function("getTerminalConfigurations") { ref: UtilityNetworkRef ->
|
|
363
|
-
ref.getTerminalConfigurations()
|
|
364
|
-
}
|
|
365
|
-
AsyncFunction("getState") Coroutine { ref: UtilityNetworkRef -> ref.getState() }
|
|
366
|
-
Function("validateNetworkTopology") { ref: UtilityNetworkRef, extent: Map<String, Any?> ->
|
|
367
|
-
ref.validateNetworkTopology(extent)
|
|
368
|
-
}
|
|
369
|
-
}
|
|
339
|
+
// UtilityNetworkRef is registered in ExpoArcgisExtras (this module's definition() hit the
|
|
340
|
+
// Android 64 KB method-size limit). SharedObjects are global, so it still attaches to a <Map> here.
|
|
370
341
|
|
|
371
342
|
// Interactive GeometryEditor — bound to a <MapView> for sketching; emits onGeometryChange.
|
|
372
343
|
Class(GeometryEditorRef::class) {
|
|
@@ -393,6 +364,10 @@ class ExpoArcgisModule : Module() {
|
|
|
393
364
|
view.setGraphicsOverlays(refs)
|
|
394
365
|
}
|
|
395
366
|
|
|
367
|
+
Prop("imageOverlays") { view: ExpoArcgisMapView, refs: List<ImageOverlayRef> ->
|
|
368
|
+
view.setImageOverlays(refs)
|
|
369
|
+
}
|
|
370
|
+
|
|
396
371
|
Prop("viewpoint") { view: ExpoArcgisMapView, vp: Map<String, Any?>? ->
|
|
397
372
|
view.setViewpoint(vp)
|
|
398
373
|
}
|
|
@@ -420,6 +395,14 @@ class ExpoArcgisModule : Module() {
|
|
|
420
395
|
AsyncFunction("retryLoad") { view: ExpoArcgisMapView, promise: Promise ->
|
|
421
396
|
view.retryLoad(promise)
|
|
422
397
|
}
|
|
398
|
+
|
|
399
|
+
AsyncFunction("getBookmarkNames") { view: ExpoArcgisMapView, promise: Promise ->
|
|
400
|
+
view.getBookmarkNames(promise)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
AsyncFunction("setBookmark") { view: ExpoArcgisMapView, name: String, promise: Promise ->
|
|
404
|
+
view.setBookmark(name, promise)
|
|
405
|
+
}
|
|
423
406
|
}
|
|
424
407
|
|
|
425
408
|
// 3D scene host — named so JS resolves it via requireNativeView('ExpoArcgis', 'ExpoArcgisSceneView').
|
|
@@ -21,9 +21,15 @@ import com.arcgismaps.mapping.symbology.DistanceSymbolRange
|
|
|
21
21
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbol
|
|
22
22
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbolStyle
|
|
23
23
|
import com.arcgismaps.mapping.symbology.MultilayerPointSymbol
|
|
24
|
+
import com.arcgismaps.mapping.symbology.MultilayerPolygonSymbol
|
|
25
|
+
import com.arcgismaps.mapping.symbology.MultilayerPolylineSymbol
|
|
24
26
|
import com.arcgismaps.mapping.symbology.PictureFillSymbol
|
|
25
27
|
import com.arcgismaps.mapping.symbology.PictureMarkerSymbol
|
|
26
28
|
import com.arcgismaps.mapping.symbology.PictureMarkerSymbolLayer
|
|
29
|
+
import com.arcgismaps.mapping.symbology.SolidFillSymbolLayer
|
|
30
|
+
import com.arcgismaps.mapping.symbology.SolidStrokeSymbolLayer
|
|
31
|
+
import com.arcgismaps.mapping.symbology.VectorMarkerSymbolElement
|
|
32
|
+
import com.arcgismaps.mapping.symbology.VectorMarkerSymbolLayer
|
|
27
33
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol
|
|
28
34
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle
|
|
29
35
|
import com.arcgismaps.mapping.symbology.SimpleRenderer
|
|
@@ -375,10 +381,8 @@ private fun buildSymbol(s: Map<*, *>): Symbol? = when (s["type"]) {
|
|
|
375
381
|
CompositeSymbol(symbolList)
|
|
376
382
|
}
|
|
377
383
|
"multilayer-point" -> {
|
|
378
|
-
// Build each
|
|
384
|
+
// Build each symbol layer and assemble a MultilayerPointSymbol.
|
|
379
385
|
// symbolLayers on MultilayerSymbol is a mutable List — populated via the constructor.
|
|
380
|
-
// DEFER: vector-marker layers (VectorMarkerSymbolLayer) require VectorMarkerSymbolElement
|
|
381
|
-
// from geometry+symbol objects and cannot be cleanly constructed from a plain dict; skip.
|
|
382
386
|
val layerDicts = s["symbolLayers"] as? List<*> ?: emptyList<Any>()
|
|
383
387
|
val symbolLayers = layerDicts.mapNotNull { ld ->
|
|
384
388
|
val ldMap = ld as? Map<*, *> ?: return@mapNotNull null
|
|
@@ -393,6 +397,44 @@ private fun buildSymbol(s: Map<*, *>): Symbol? = when (s["type"]) {
|
|
|
393
397
|
(ldMap["offsetY"] as? Number)?.toDouble()?.let { offsetY = it }
|
|
394
398
|
}
|
|
395
399
|
}
|
|
400
|
+
"vector-marker" -> {
|
|
401
|
+
val geomMap = ldMap["geometry"] as? Map<*, *> ?: return@mapNotNull null
|
|
402
|
+
val geom = geometryFromDict(geomMap) ?: return@mapNotNull null
|
|
403
|
+
val elementSymbol = when (geomMap["type"]) {
|
|
404
|
+
"polygon" -> {
|
|
405
|
+
val fillColor = colorOf(ldMap["fillColor"]) ?: Color.fromRgba(255, 0, 0, 255)
|
|
406
|
+
val elementLayers = buildList {
|
|
407
|
+
add(SolidFillSymbolLayer(fillColor))
|
|
408
|
+
colorOf(ldMap["outlineColor"])?.let { outlineColor ->
|
|
409
|
+
val outlineWidth = (ldMap["outlineWidth"] as? Number)?.toDouble() ?: 1.0
|
|
410
|
+
add(SolidStrokeSymbolLayer(outlineWidth, outlineColor))
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
MultilayerPolygonSymbol(elementLayers)
|
|
414
|
+
}
|
|
415
|
+
"polyline" -> {
|
|
416
|
+
val strokeColor = colorOf(ldMap["fillColor"]) ?: colorOf(ldMap["outlineColor"]) ?: Color.fromRgba(255, 0, 0, 255)
|
|
417
|
+
val strokeWidth = (ldMap["outlineWidth"] as? Number)?.toDouble() ?: 1.0
|
|
418
|
+
MultilayerPolylineSymbol(listOf(SolidStrokeSymbolLayer(strokeWidth, strokeColor)))
|
|
419
|
+
}
|
|
420
|
+
"multipoint" -> {
|
|
421
|
+
val fillColor = colorOf(ldMap["fillColor"]) ?: Color.fromRgba(255, 0, 0, 255)
|
|
422
|
+
val elementLayers = buildList {
|
|
423
|
+
add(SolidFillSymbolLayer(fillColor))
|
|
424
|
+
colorOf(ldMap["outlineColor"])?.let { outlineColor ->
|
|
425
|
+
val outlineWidth = (ldMap["outlineWidth"] as? Number)?.toDouble() ?: 1.0
|
|
426
|
+
add(SolidStrokeSymbolLayer(outlineWidth, outlineColor))
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
MultilayerPointSymbol(elementLayers)
|
|
430
|
+
}
|
|
431
|
+
else -> return@mapNotNull null // unsupported geometry type — skip gracefully
|
|
432
|
+
}
|
|
433
|
+
val element = VectorMarkerSymbolElement(geom, elementSymbol)
|
|
434
|
+
VectorMarkerSymbolLayer(listOf(element)).apply {
|
|
435
|
+
(ldMap["size"] as? Number)?.toDouble()?.let { size = it }
|
|
436
|
+
}
|
|
437
|
+
}
|
|
396
438
|
else -> null
|
|
397
439
|
}
|
|
398
440
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import com.arcgismaps.geometry.Envelope
|
|
4
|
+
import com.arcgismaps.mapping.view.ImageFrame
|
|
5
|
+
import com.arcgismaps.mapping.view.ImageOverlay
|
|
6
|
+
import expo.modules.kotlin.AppContext
|
|
7
|
+
import expo.modules.kotlin.sharedobjects.SharedObject
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* An [ImageOverlay] that displays a single georeferenced image frame — a local image file shown at a
|
|
11
|
+
* map extent, with adjustable opacity. Added to a `<MapView>` via the `<ImageOverlay>` component.
|
|
12
|
+
*/
|
|
13
|
+
class ImageOverlayRef(appContext: AppContext) : SharedObject(appContext) {
|
|
14
|
+
val overlay = ImageOverlay()
|
|
15
|
+
|
|
16
|
+
/** Sets the displayed frame from a local image file path and its geographic extent (clears on null). */
|
|
17
|
+
fun setFrame(imagePath: String, extent: Map<String, Any?>, opacity: Double?) {
|
|
18
|
+
val envelope = geometryFromDict(extent + ("type" to "envelope")) as? Envelope
|
|
19
|
+
if (envelope == null) {
|
|
20
|
+
overlay.imageFrame = null
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
overlay.imageFrame = ImageFrame(imagePath, envelope)
|
|
24
|
+
opacity?.let { overlay.opacity = it.toFloat() }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun setOpacity(opacity: Double) { overlay.opacity = opacity.toFloat() }
|
|
28
|
+
}
|
|
@@ -117,6 +117,45 @@ class FeatureLayerRef(appContext: AppContext, private val table: FeatureTable) :
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Adds a feature created from the named template (inheriting its prototype attributes), then
|
|
122
|
+
* optionally applies [attributes] on top and sets [geometry]. When [apply] is not `false`,
|
|
123
|
+
* pushes the edit and returns the new object id; pass `apply = false` for a local-only edit.
|
|
124
|
+
*/
|
|
125
|
+
suspend fun addFeatureWithTemplate(templateName: String, attributes: Map<String, Any?>?, geometry: Map<String, Any?>?, apply: Boolean?): Long? {
|
|
126
|
+
table.load().getOrThrow()
|
|
127
|
+
val arcGISTable = table as? ArcGISFeatureTable
|
|
128
|
+
?: throw IllegalStateException("addFeatureWithTemplate requires an ArcGIS feature table (not a shapefile or WFS table)")
|
|
129
|
+
val template = arcGISTable.getFeatureTemplate(templateName)
|
|
130
|
+
?: throw IllegalArgumentException("No feature template named '$templateName' found in the table")
|
|
131
|
+
val geom = geometry?.let { geometryFromDict(it) }
|
|
132
|
+
val feature = arcGISTable.createFeature(template, geom)
|
|
133
|
+
if (attributes != null) applyAttributes(feature, attributes)
|
|
134
|
+
table.addFeature(feature).getOrThrow()
|
|
135
|
+
if (apply == false) return null
|
|
136
|
+
return persistEdits()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Adds a feature created from the named subtype (sets the subtype field and inherits its
|
|
141
|
+
* default attribute values), then optionally applies [attributes] on top and sets [geometry].
|
|
142
|
+
* When [apply] is not `false`, pushes the edit and returns the new object id; pass
|
|
143
|
+
* `apply = false` for a local-only edit.
|
|
144
|
+
*/
|
|
145
|
+
suspend fun addFeatureWithSubtype(subtypeName: String, attributes: Map<String, Any?>?, geometry: Map<String, Any?>?, apply: Boolean?): Long? {
|
|
146
|
+
table.load().getOrThrow()
|
|
147
|
+
val arcGISTable = table as? ArcGISFeatureTable
|
|
148
|
+
?: throw IllegalStateException("addFeatureWithSubtype requires an ArcGIS feature table (not a shapefile or WFS table)")
|
|
149
|
+
val subtype = arcGISTable.featureSubtypes.firstOrNull { it.name == subtypeName }
|
|
150
|
+
?: throw IllegalArgumentException("No feature subtype named '$subtypeName' found in the table")
|
|
151
|
+
val geom = geometry?.let { geometryFromDict(it) }
|
|
152
|
+
val feature = arcGISTable.createFeature(subtype, geom)
|
|
153
|
+
if (attributes != null) applyAttributes(feature, attributes)
|
|
154
|
+
table.addFeature(feature).getOrThrow()
|
|
155
|
+
if (apply == false) return null
|
|
156
|
+
return persistEdits()
|
|
157
|
+
}
|
|
158
|
+
|
|
120
159
|
/**
|
|
121
160
|
* Adds a feature. When `apply` is not `false`, pushes the edit and returns the new object id;
|
|
122
161
|
* pass `apply = false` to make a local-only edit (batch with `applyEdits`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAO5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;
|
|
1
|
+
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAO5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;mBAwDkhmC,CAAC;gBAAkB,CAAC;;;;;;;4DADpkmC,CAAC"}
|
|
@@ -441,6 +441,10 @@ export type MapViewHandle = {
|
|
|
441
441
|
}): Promise<PopupResult[]>;
|
|
442
442
|
/** Retries loading the map after a failure (e.g. a network outage). Re-fires `onMapLoaded`/`onMapLoadError`. */
|
|
443
443
|
retryLoad(): Promise<void>;
|
|
444
|
+
/** Names of the displayed map's bookmarks (e.g. those saved in a loaded web map). */
|
|
445
|
+
getBookmarkNames(): Promise<string[]>;
|
|
446
|
+
/** Navigates to the named bookmark's viewpoint; resolves to whether a matching bookmark was found. */
|
|
447
|
+
setBookmark(name: string): Promise<boolean>;
|
|
444
448
|
};
|
|
445
449
|
/** Imperative handle exposed by `<SceneView>` via `ref`. */
|
|
446
450
|
export type SceneViewHandle = {
|
|
@@ -513,6 +517,42 @@ export type FeatureLayerHandle = {
|
|
|
513
517
|
* edit, then batch with `applyEdits`. Resolves to `null` for non-service tables or local edits.
|
|
514
518
|
*/
|
|
515
519
|
addFeature(attributes: Record<string, unknown>, geometry?: Geometry, apply?: boolean): Promise<number | null>;
|
|
520
|
+
/**
|
|
521
|
+
* Creates a feature from the named editing template (so the new feature inherits the template's
|
|
522
|
+
* prototype attributes), then optionally overrides `attributes` on top and sets `geometry`.
|
|
523
|
+
* By default pushes the edit to the service and resolves to the new object id; pass
|
|
524
|
+
* `apply: false` to make a local-only edit. Rejects if no template with that name exists.
|
|
525
|
+
* Requires an ArcGIS feature table (service or mobile geodatabase) — rejects for shapefiles
|
|
526
|
+
* and WFS tables, which do not expose editing templates.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```ts
|
|
530
|
+
* const id = await layer.current.addFeatureWithTemplate(
|
|
531
|
+
* 'Residential',
|
|
532
|
+
* { ADDRESS: '1 Main St' },
|
|
533
|
+
* { type: 'point', x: -117.19, y: 34.05 }
|
|
534
|
+
* );
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
addFeatureWithTemplate(templateName: string, attributes?: Record<string, unknown>, geometry?: Geometry, apply?: boolean): Promise<number | null>;
|
|
538
|
+
/**
|
|
539
|
+
* Creates a feature from the named feature subtype (sets the subtype field and inherits the
|
|
540
|
+
* subtype's default attribute values), then optionally overrides `attributes` on top and sets
|
|
541
|
+
* `geometry`. By default pushes the edit to the service and resolves to the new object id;
|
|
542
|
+
* pass `apply: false` to make a local-only edit. Rejects if no subtype with that name exists.
|
|
543
|
+
* Requires an ArcGIS feature table (service or mobile geodatabase) — rejects for shapefiles
|
|
544
|
+
* and WFS tables, which do not expose feature subtypes.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* const id = await layer.current.addFeatureWithSubtype(
|
|
549
|
+
* 'Arterial',
|
|
550
|
+
* { ROADNAME: 'Main St' },
|
|
551
|
+
* { type: 'point', x: -117.19, y: 34.05 }
|
|
552
|
+
* );
|
|
553
|
+
* ```
|
|
554
|
+
*/
|
|
555
|
+
addFeatureWithSubtype(subtypeName: string, attributes?: Record<string, unknown>, geometry?: Geometry, apply?: boolean): Promise<number | null>;
|
|
516
556
|
/** Updates the feature with `objectId`. Pass `apply: false` for a local-only edit. */
|
|
517
557
|
updateFeature(objectId: number, changes: {
|
|
518
558
|
attributes?: Record<string, unknown>;
|
|
@@ -933,6 +973,15 @@ export type Envelope = {
|
|
|
933
973
|
/** Coordinate system WKID. Defaults to `4326` (WGS84). */
|
|
934
974
|
spatialReference?: SpatialReference;
|
|
935
975
|
};
|
|
976
|
+
/** Props for the `<ImageOverlay>` component — a georeferenced image displayed on a `<MapView>`. */
|
|
977
|
+
export type ImageOverlayProps = {
|
|
978
|
+
/** Local image file path to display (e.g. a downloaded or bundled PNG/JPEG). */
|
|
979
|
+
imagePath: string;
|
|
980
|
+
/** The geographic extent (envelope) the image is stretched to fill. */
|
|
981
|
+
extent: Envelope;
|
|
982
|
+
/** Overlay opacity, 0–1. Defaults to `1`. */
|
|
983
|
+
opacity?: number;
|
|
984
|
+
};
|
|
936
985
|
/**
|
|
937
986
|
* A geometry value. The `type` discriminator mirrors the ArcGIS web API
|
|
938
987
|
* (`"point"` / `"multipoint"` / `"polyline"` / `"polygon"` / `"envelope"`) and
|
|
@@ -1712,10 +1761,6 @@ export type CompositeSymbolType = {
|
|
|
1712
1761
|
* NOTE: `size` sets a uniform size (overrides `width`/`height` when all three are supplied).
|
|
1713
1762
|
* `width` and `height` are applied in order, so supplying both sets size to the last one;
|
|
1714
1763
|
* use `size` for a uniform value. `offsetX`/`offsetY` shift the layer in points.
|
|
1715
|
-
*
|
|
1716
|
-
* DEFER: `VectorMarkerSymbolLayer` (the vector-marker kind) requires constructing
|
|
1717
|
-
* `VectorMarkerSymbolElement` objects from geometry + symbol objects, which cannot be
|
|
1718
|
-
* expressed as a plain flat dict. It is not yet implemented.
|
|
1719
1764
|
*/
|
|
1720
1765
|
export type PictureMarkerSymbolLayerSpec = {
|
|
1721
1766
|
type: 'picture-marker';
|
|
@@ -1732,19 +1777,78 @@ export type PictureMarkerSymbolLayerSpec = {
|
|
|
1732
1777
|
/** Vertical offset of the layer, in points. */
|
|
1733
1778
|
offsetY?: number;
|
|
1734
1779
|
};
|
|
1780
|
+
/**
|
|
1781
|
+
* One vector-marker symbol layer within a `MultilayerPointSymbolType`.
|
|
1782
|
+
* Mirrors the native `VectorMarkerSymbolLayer` (a shape drawn from a geometry with fill/stroke,
|
|
1783
|
+
* requiring no image).
|
|
1784
|
+
*
|
|
1785
|
+
* Supported `geometry` types and how they are symbolised:
|
|
1786
|
+
* - `polygon` — `MultilayerPolygonSymbol([SolidFillSymbolLayer, SolidStrokeSymbolLayer?])`;
|
|
1787
|
+
* `fillColor` is the fill, `outlineColor`/`outlineWidth` add an optional stroke.
|
|
1788
|
+
* - `polyline` — `MultilayerPolylineSymbol([SolidStrokeSymbolLayer])`; `fillColor` is used as the
|
|
1789
|
+
* stroke color (falls back to `outlineColor`, then red), `outlineWidth` sets the stroke width.
|
|
1790
|
+
* - `multipoint` — `MultilayerPointSymbol([SolidFillSymbolLayer, SolidStrokeSymbolLayer?])`;
|
|
1791
|
+
* same color/width props as `polygon`.
|
|
1792
|
+
*
|
|
1793
|
+
* Any other `geometry` type is silently skipped (the layer is omitted from the symbol).
|
|
1794
|
+
* Geometries use a local coordinate space (not geographic) — use small integer-scale coordinates
|
|
1795
|
+
* (e.g. `x` / `y` in the range `[-1, 1]`).
|
|
1796
|
+
*
|
|
1797
|
+
* @example — filled triangle (polygon)
|
|
1798
|
+
* ```ts
|
|
1799
|
+
* { type: 'multilayer-point', symbolLayers: [
|
|
1800
|
+
* { type: 'vector-marker', size: 24,
|
|
1801
|
+
* geometry: { type: 'polygon', points: [
|
|
1802
|
+
* { x: -1, y: -1 }, { x: 0, y: 1 }, { x: 1, y: -1 },
|
|
1803
|
+
* ] },
|
|
1804
|
+
* fillColor: '#e63946', outlineColor: '#1d3557', outlineWidth: 1 },
|
|
1805
|
+
* ] }
|
|
1806
|
+
* ```
|
|
1807
|
+
*/
|
|
1808
|
+
export type VectorMarkerSymbolLayerSpec = {
|
|
1809
|
+
type: 'vector-marker';
|
|
1810
|
+
/**
|
|
1811
|
+
* The geometry that defines the marker shape. Supported types: `polygon`, `polyline`,
|
|
1812
|
+
* `multipoint`. Unsupported types are silently skipped. The geometry is defined in a local
|
|
1813
|
+
* coordinate space (not geographic) — use small integer-scale coordinates
|
|
1814
|
+
* (e.g. `x` / `y` in the range `[-1, 1]`).
|
|
1815
|
+
*/
|
|
1816
|
+
geometry: Geometry;
|
|
1817
|
+
/** Overall size of the marker, in points. Scales the geometry uniformly. Defaults to 12. */
|
|
1818
|
+
size?: number;
|
|
1819
|
+
/** Fill color as a `#RRGGBB` / `#RRGGBBAA` hex string. Defaults to red. */
|
|
1820
|
+
fillColor?: string;
|
|
1821
|
+
/** Outline stroke color as a `#RRGGBB` / `#RRGGBBAA` hex string. Omit to suppress outline. */
|
|
1822
|
+
outlineColor?: string;
|
|
1823
|
+
/** Outline stroke width in points. Defaults to 1. */
|
|
1824
|
+
outlineWidth?: number;
|
|
1825
|
+
};
|
|
1735
1826
|
/** Union of all supported symbol layer kinds within a `MultilayerPointSymbolType`. */
|
|
1736
|
-
export type SymbolLayerSpec = PictureMarkerSymbolLayerSpec;
|
|
1827
|
+
export type SymbolLayerSpec = PictureMarkerSymbolLayerSpec | VectorMarkerSymbolLayerSpec;
|
|
1737
1828
|
/**
|
|
1738
1829
|
* A multilayer point symbol composed of one or more symbol layers.
|
|
1739
1830
|
* Mirrors the native `MultilayerPointSymbol`. Useful for rich point icons built from stacked
|
|
1740
|
-
* picture images (e.g. a
|
|
1831
|
+
* picture images or vector shapes (e.g. a filled triangle marker, or a pin body + badge).
|
|
1741
1832
|
*
|
|
1742
|
-
*
|
|
1833
|
+
* Supported layer kinds: `picture-marker` and `vector-marker`.
|
|
1834
|
+
*
|
|
1835
|
+
* @example — picture marker
|
|
1743
1836
|
* ```ts
|
|
1744
1837
|
* { type: 'multilayer-point', symbolLayers: [
|
|
1745
1838
|
* { type: 'picture-marker', url: 'https://example.com/pin.png', width: 30, height: 30 },
|
|
1746
1839
|
* ] }
|
|
1747
1840
|
* ```
|
|
1841
|
+
*
|
|
1842
|
+
* @example — vector marker (filled triangle)
|
|
1843
|
+
* ```ts
|
|
1844
|
+
* { type: 'multilayer-point', symbolLayers: [
|
|
1845
|
+
* { type: 'vector-marker', size: 24,
|
|
1846
|
+
* geometry: { type: 'polygon', points: [
|
|
1847
|
+
* { x: 0, y: 1 }, { x: 1, y: -1 }, { x: -1, y: -1 },
|
|
1848
|
+
* ] },
|
|
1849
|
+
* fillColor: '#e63946', outlineColor: '#1d3557', outlineWidth: 1.5 },
|
|
1850
|
+
* ] }
|
|
1851
|
+
* ```
|
|
1748
1852
|
*/
|
|
1749
1853
|
export type MultilayerPointSymbolType = {
|
|
1750
1854
|
type: 'multilayer-point';
|