@tileflow/react-native 0.1.0-alpha.7 → 0.1.0-alpha.9
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 +19 -17
- package/dist/{contract-BaK24QZD.d.ts → contract-BWCbfMOx.d.ts} +19 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +444 -75
- package/dist/internal/camera.d.ts +1 -1
- package/dist/internal/initial-view.d.ts +1 -1
- package/dist/internal/interactions.js +1 -0
- package/dist/internal/native-admission.d.ts +1 -0
- package/dist/internal/native-admission.js +47 -21
- package/dist/internal/native-appearance.d.ts +1 -1
- package/dist/internal/session.d.ts +4 -1
- package/dist/internal/session.js +46 -20
- package/dist/internal/source-state.d.ts +1 -1
- package/package.json +3 -4
- package/docs/native-admission.md +0 -124
- package/docs/native-configuration.md +0 -210
- package/docs/native-interactions.md +0 -161
- package/docs/native-location.md +0 -148
package/dist/index.js
CHANGED
|
@@ -15,16 +15,25 @@ import {
|
|
|
15
15
|
Map as NativeMap
|
|
16
16
|
} from "@maplibre/maplibre-react-native";
|
|
17
17
|
import {
|
|
18
|
-
Fragment,
|
|
18
|
+
Fragment as Fragment2,
|
|
19
19
|
useImperativeHandle,
|
|
20
20
|
useLayoutEffect as useLayoutEffect3,
|
|
21
21
|
useMemo as useMemo3,
|
|
22
|
-
useRef,
|
|
22
|
+
useRef as useRef2,
|
|
23
23
|
useState as useState2,
|
|
24
24
|
useSyncExternalStore
|
|
25
25
|
} from "react";
|
|
26
26
|
import { AppState, findNodeHandle, View as View2 } from "react-native";
|
|
27
27
|
|
|
28
|
+
// src/native-annotation-clusters.ts
|
|
29
|
+
import {
|
|
30
|
+
createTileflowAnnotationClusterIndex
|
|
31
|
+
} from "@tileflow/interactions";
|
|
32
|
+
import { withTileflowClusterLabelFont } from "@tileflow/interactions";
|
|
33
|
+
function createNativeAnnotationClusters(annotations, options) {
|
|
34
|
+
return createTileflowAnnotationClusterIndex(annotations, options);
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
// src/native-interaction-input.ts
|
|
29
38
|
import {
|
|
30
39
|
tileflowInteractionJsonValueSchema,
|
|
@@ -36,6 +45,7 @@ var messages = {
|
|
|
36
45
|
DUPLICATE_ANNOTATION_ID: "Annotation IDs must be unique.",
|
|
37
46
|
INVALID_FIELD: "An interaction field is invalid.",
|
|
38
47
|
INVALID_ANNOTATION: "An annotation is invalid.",
|
|
48
|
+
INVALID_DATA_LAYER: "A data source or overlay is invalid.",
|
|
39
49
|
INVALID_DOCUMENT: "The interaction document is invalid.",
|
|
40
50
|
LIMIT_EXCEEDED: "The portable interaction limit was exceeded.",
|
|
41
51
|
MISSING_VIEW: "The interaction view is unavailable.",
|
|
@@ -828,8 +838,8 @@ function item(value, index) {
|
|
|
828
838
|
return descriptor.value;
|
|
829
839
|
}
|
|
830
840
|
function array2(value, maximum2) {
|
|
831
|
-
const
|
|
832
|
-
return Array.from({ length:
|
|
841
|
+
const count2 = length(value, maximum2);
|
|
842
|
+
return Array.from({ length: count2 }, (_, index) => item(value, index));
|
|
833
843
|
}
|
|
834
844
|
function name2(value) {
|
|
835
845
|
return typeof value === "string" && value.length > 0 && value.length <= 256;
|
|
@@ -914,8 +924,8 @@ function createNativeInteractionQuery(style, current, query) {
|
|
|
914
924
|
cancel();
|
|
915
925
|
return;
|
|
916
926
|
}
|
|
917
|
-
const
|
|
918
|
-
const read = Math.min(
|
|
927
|
+
const count2 = length(hits);
|
|
928
|
+
const read = Math.min(count2, nativePoiQueryLimit + 1 - features.length);
|
|
919
929
|
for (let index = 0; index < read; index++) {
|
|
920
930
|
const feature = item(hits, index);
|
|
921
931
|
if (nativeInteractionField(feature, "type") !== "Feature") throw new Error();
|
|
@@ -1501,10 +1511,245 @@ function NativeBoundaryFeatureState({
|
|
|
1501
1511
|
);
|
|
1502
1512
|
}
|
|
1503
1513
|
|
|
1514
|
+
// src/native-data-layers.tsx
|
|
1515
|
+
import {
|
|
1516
|
+
GeoJSONSource,
|
|
1517
|
+
Layer,
|
|
1518
|
+
Marker
|
|
1519
|
+
} from "@maplibre/maplibre-react-native";
|
|
1520
|
+
import { useRef } from "react";
|
|
1521
|
+
import { Pressable, Text } from "react-native";
|
|
1522
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1523
|
+
var bubble = Object.freeze({
|
|
1524
|
+
alignItems: "center",
|
|
1525
|
+
backgroundColor: "#2563eb",
|
|
1526
|
+
borderColor: "#ffffff",
|
|
1527
|
+
borderRadius: 22,
|
|
1528
|
+
borderWidth: 2,
|
|
1529
|
+
justifyContent: "center",
|
|
1530
|
+
minHeight: 44,
|
|
1531
|
+
minWidth: 44,
|
|
1532
|
+
paddingHorizontal: 6
|
|
1533
|
+
});
|
|
1534
|
+
var count = Object.freeze({ color: "#ffffff", fontSize: 14, fontWeight: "600" });
|
|
1535
|
+
function NativeDataLayers({
|
|
1536
|
+
camera,
|
|
1537
|
+
expand,
|
|
1538
|
+
onActivate,
|
|
1539
|
+
plan
|
|
1540
|
+
}) {
|
|
1541
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1542
|
+
plan.sources.map((source) => /* @__PURE__ */ jsx2(
|
|
1543
|
+
NativeDataSource,
|
|
1544
|
+
{
|
|
1545
|
+
camera,
|
|
1546
|
+
expand,
|
|
1547
|
+
onActivate,
|
|
1548
|
+
source
|
|
1549
|
+
},
|
|
1550
|
+
source.id
|
|
1551
|
+
)),
|
|
1552
|
+
plan.layers.map((layer) => /* @__PURE__ */ jsx2(Layer, { ...layer }, layer.id))
|
|
1553
|
+
] });
|
|
1554
|
+
}
|
|
1555
|
+
function NativeDataSource({
|
|
1556
|
+
camera,
|
|
1557
|
+
expand,
|
|
1558
|
+
onActivate,
|
|
1559
|
+
source
|
|
1560
|
+
}) {
|
|
1561
|
+
const ref = useRef(null);
|
|
1562
|
+
const pressable = source.clusterLayers.length > 0 || source.pointLayers.length > 0;
|
|
1563
|
+
return /* @__PURE__ */ jsx2(
|
|
1564
|
+
GeoJSONSource,
|
|
1565
|
+
{
|
|
1566
|
+
...source.definition,
|
|
1567
|
+
id: source.id,
|
|
1568
|
+
ref,
|
|
1569
|
+
data: source.data,
|
|
1570
|
+
onPress: pressable ? (event) => {
|
|
1571
|
+
const feature = event.nativeEvent.features[0];
|
|
1572
|
+
const coordinate2 = pointCoordinate(feature);
|
|
1573
|
+
if (!feature || !coordinate2) return;
|
|
1574
|
+
const properties2 = jsonProperties(feature.properties);
|
|
1575
|
+
const clusterId = properties2.cluster_id;
|
|
1576
|
+
if (typeof clusterId !== "number") {
|
|
1577
|
+
const layerId = source.pointLayers[0];
|
|
1578
|
+
if (!layerId) return;
|
|
1579
|
+
onActivate({
|
|
1580
|
+
coordinate: coordinate2,
|
|
1581
|
+
feature: { ...feature.id === void 0 ? {} : { id: feature.id }, properties: properties2 },
|
|
1582
|
+
kind: "style-feature",
|
|
1583
|
+
layerId
|
|
1584
|
+
});
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
onActivate({
|
|
1588
|
+
clusterId,
|
|
1589
|
+
coordinate: coordinate2,
|
|
1590
|
+
kind: "cluster",
|
|
1591
|
+
pointCount: typeof properties2.point_count === "number" ? properties2.point_count : 0,
|
|
1592
|
+
properties: properties2,
|
|
1593
|
+
source: source.id
|
|
1594
|
+
});
|
|
1595
|
+
if (!expand || !source.expandOnClick) return;
|
|
1596
|
+
ref.current?.getClusterExpansionZoom(clusterId).then(
|
|
1597
|
+
(zoom) => camera.current?.easeTo({
|
|
1598
|
+
center: [coordinate2[0], coordinate2[1]],
|
|
1599
|
+
duration: 400,
|
|
1600
|
+
zoom
|
|
1601
|
+
}),
|
|
1602
|
+
() => void 0
|
|
1603
|
+
);
|
|
1604
|
+
} : void 0,
|
|
1605
|
+
children: source.layers.map((layer) => /* @__PURE__ */ jsx2(Layer, { ...layer }, layer.id))
|
|
1606
|
+
}
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1609
|
+
function NativeClusterMarker({
|
|
1610
|
+
cluster,
|
|
1611
|
+
label,
|
|
1612
|
+
onPress
|
|
1613
|
+
}) {
|
|
1614
|
+
const press = (event) => {
|
|
1615
|
+
event?.stopPropagation();
|
|
1616
|
+
onPress();
|
|
1617
|
+
};
|
|
1618
|
+
return /* @__PURE__ */ jsx2(
|
|
1619
|
+
Marker,
|
|
1620
|
+
{
|
|
1621
|
+
id: `tileflow-cluster-${cluster.clusterId}`,
|
|
1622
|
+
lngLat: [cluster.coordinate[0], cluster.coordinate[1]],
|
|
1623
|
+
accessible: true,
|
|
1624
|
+
accessibilityLabel: label,
|
|
1625
|
+
accessibilityRole: "button",
|
|
1626
|
+
onAccessibilityTap: onPress,
|
|
1627
|
+
onPress: press,
|
|
1628
|
+
children: /* @__PURE__ */ jsx2(Pressable, { accessible: false, onPress: press, style: bubble, children: /* @__PURE__ */ jsx2(Text, { style: count, children: cluster.label }) })
|
|
1629
|
+
}
|
|
1630
|
+
);
|
|
1631
|
+
}
|
|
1632
|
+
function pointCoordinate(feature) {
|
|
1633
|
+
const coordinates = feature?.geometry?.coordinates;
|
|
1634
|
+
return feature?.geometry?.type === "Point" && Array.isArray(coordinates) && typeof coordinates[0] === "number" && typeof coordinates[1] === "number" ? [coordinates[0], coordinates[1]] : void 0;
|
|
1635
|
+
}
|
|
1636
|
+
function jsonProperties(properties2) {
|
|
1637
|
+
return Object.fromEntries(
|
|
1638
|
+
Object.entries(properties2 ?? {}).filter(([, value]) => value !== void 0)
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/native-data-layers-plan.ts
|
|
1643
|
+
var clusterMetadataKey = "tileflow:cluster";
|
|
1644
|
+
var placementMetadataKey = "tileflow:overlay-placement-manifest";
|
|
1645
|
+
function planNativeDataLayers(input) {
|
|
1646
|
+
const styleSources = input.style.sources ?? {};
|
|
1647
|
+
const styleLayers = input.style.layers ?? [];
|
|
1648
|
+
const styleLayerIds = new Set(styleLayers.map(({ id }) => String(id)));
|
|
1649
|
+
const anchors = input.style.metadata?.[placementMetadataKey]?.anchors;
|
|
1650
|
+
const diagnostics = [];
|
|
1651
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1652
|
+
const freeLayers = [];
|
|
1653
|
+
const entry = (id) => entries.get(id);
|
|
1654
|
+
const addRoles = (sourceId, layer) => {
|
|
1655
|
+
const target = entry(sourceId);
|
|
1656
|
+
const cluster = layer.metadata?.[clusterMetadataKey];
|
|
1657
|
+
if (!target || !cluster) return;
|
|
1658
|
+
if (cluster.role === "cluster") target.clusterLayers.push(String(layer.id));
|
|
1659
|
+
if (cluster.role === "point") target.pointLayers.push(String(layer.id));
|
|
1660
|
+
if (cluster.expandOnClick === false) target.expandOnClick = false;
|
|
1661
|
+
};
|
|
1662
|
+
for (const [id, source] of Object.entries(input.dataSources ?? {}).sort(compare)) {
|
|
1663
|
+
const compiled2 = styleSources[id];
|
|
1664
|
+
if (source.kind !== "geojson" || compiled2 && compiled2.type !== "geojson") {
|
|
1665
|
+
diagnostics.push({ message: `Source "${id}" is not GeoJSON.`, path: `/dataSources/${id}` });
|
|
1666
|
+
continue;
|
|
1667
|
+
}
|
|
1668
|
+
const { data, kind: _kind, ...definition } = source;
|
|
1669
|
+
entries.set(id, {
|
|
1670
|
+
adopted: compiled2 !== void 0,
|
|
1671
|
+
clusterLayers: [],
|
|
1672
|
+
data,
|
|
1673
|
+
// A reused source keeps its compiled cluster options.
|
|
1674
|
+
definition: compiled2 ? {} : definition,
|
|
1675
|
+
expandOnClick: true,
|
|
1676
|
+
layers: [],
|
|
1677
|
+
pointLayers: []
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
for (const layer of styleLayers) {
|
|
1681
|
+
const sourceId = typeof layer.source === "string" ? layer.source : void 0;
|
|
1682
|
+
const cluster = layer.metadata?.[clusterMetadataKey];
|
|
1683
|
+
if (!sourceId || !cluster || entries.has(sourceId)) continue;
|
|
1684
|
+
const compiled2 = styleSources[sourceId];
|
|
1685
|
+
if (compiled2?.type !== "geojson") continue;
|
|
1686
|
+
entries.set(sourceId, {
|
|
1687
|
+
adopted: true,
|
|
1688
|
+
clusterLayers: [],
|
|
1689
|
+
data: compiled2.data,
|
|
1690
|
+
definition: {},
|
|
1691
|
+
expandOnClick: true,
|
|
1692
|
+
layers: [],
|
|
1693
|
+
pointLayers: []
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
for (const layer of styleLayers) {
|
|
1697
|
+
if (typeof layer.source === "string") addRoles(layer.source, layer);
|
|
1698
|
+
}
|
|
1699
|
+
for (const [id, overlay] of Object.entries(input.dataOverlays ?? {}).sort(compare)) {
|
|
1700
|
+
const path = `/dataOverlays/${id}`;
|
|
1701
|
+
if (overlay.kind !== "maplibre-overlay") {
|
|
1702
|
+
diagnostics.push({ message: `Overlay "${id}" is not a Tileflow overlay.`, path });
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1705
|
+
const target = entry(overlay.source);
|
|
1706
|
+
if (!target && !styleSources[overlay.source]) {
|
|
1707
|
+
diagnostics.push({
|
|
1708
|
+
message: `Overlay "${id}" references unknown source "${overlay.source}".`,
|
|
1709
|
+
path: `${path}/source`
|
|
1710
|
+
});
|
|
1711
|
+
continue;
|
|
1712
|
+
}
|
|
1713
|
+
const anchor = anchors?.[overlay.placement];
|
|
1714
|
+
const beforeId = typeof anchor === "string" && styleLayerIds.has(anchor) ? anchor : void 0;
|
|
1715
|
+
for (const layer of overlay.layers) {
|
|
1716
|
+
if (styleLayerIds.has(layer.id)) continue;
|
|
1717
|
+
const prepared = withTileflowClusterLabelFont(layer, styleLayers);
|
|
1718
|
+
if (!prepared) {
|
|
1719
|
+
diagnostics.push({
|
|
1720
|
+
message: `Layer "${layer.id}" needs font: the style has no label font.`,
|
|
1721
|
+
path
|
|
1722
|
+
});
|
|
1723
|
+
continue;
|
|
1724
|
+
}
|
|
1725
|
+
const native = {
|
|
1726
|
+
...prepared,
|
|
1727
|
+
...beforeId ? { beforeId } : {},
|
|
1728
|
+
id: layer.id,
|
|
1729
|
+
source: overlay.source
|
|
1730
|
+
};
|
|
1731
|
+
if (target) {
|
|
1732
|
+
target.layers.push(native);
|
|
1733
|
+
addRoles(overlay.source, layer);
|
|
1734
|
+
} else {
|
|
1735
|
+
freeLayers.push(native);
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
return Object.freeze({
|
|
1740
|
+
diagnostics: Object.freeze(diagnostics),
|
|
1741
|
+
layers: Object.freeze(freeLayers),
|
|
1742
|
+
sources: Object.freeze([...entries].map(([id, value]) => Object.freeze({ id, ...value })))
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
function compare([left], [right]) {
|
|
1746
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1504
1749
|
// src/native-marker.tsx
|
|
1505
1750
|
import { Marker as NativeMarker } from "@maplibre/maplibre-react-native";
|
|
1506
1751
|
import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo2 } from "react";
|
|
1507
|
-
import { Pressable, processColor, View } from "react-native";
|
|
1752
|
+
import { Pressable as Pressable2, processColor, View } from "react-native";
|
|
1508
1753
|
|
|
1509
1754
|
// src/native-marker-model.ts
|
|
1510
1755
|
import { isValidElement } from "react";
|
|
@@ -1550,7 +1795,7 @@ function resolveNativeMarkerContent(context, render) {
|
|
|
1550
1795
|
}
|
|
1551
1796
|
|
|
1552
1797
|
// src/native-marker.tsx
|
|
1553
|
-
import { jsx as
|
|
1798
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1554
1799
|
var button = Object.freeze({
|
|
1555
1800
|
minWidth: 44,
|
|
1556
1801
|
minHeight: 44,
|
|
@@ -1593,7 +1838,7 @@ function NativeAnnotationMarker({
|
|
|
1593
1838
|
event?.stopPropagation();
|
|
1594
1839
|
lifecycle.markerPress(sceneKey, annotation);
|
|
1595
1840
|
};
|
|
1596
|
-
return /* @__PURE__ */
|
|
1841
|
+
return /* @__PURE__ */ jsx3(
|
|
1597
1842
|
NativeMarker,
|
|
1598
1843
|
{
|
|
1599
1844
|
id: `tileflow-annotation-${model.key}`,
|
|
@@ -1604,8 +1849,8 @@ function NativeAnnotationMarker({
|
|
|
1604
1849
|
lifecycle.beginTouch(sceneKey);
|
|
1605
1850
|
press();
|
|
1606
1851
|
},
|
|
1607
|
-
children: /* @__PURE__ */
|
|
1608
|
-
|
|
1852
|
+
children: /* @__PURE__ */ jsx3(
|
|
1853
|
+
Pressable2,
|
|
1609
1854
|
{
|
|
1610
1855
|
accessible: false,
|
|
1611
1856
|
disabled: !enabled,
|
|
@@ -1615,14 +1860,14 @@ function NativeAnnotationMarker({
|
|
|
1615
1860
|
event.stopPropagation();
|
|
1616
1861
|
},
|
|
1617
1862
|
onPress: press,
|
|
1618
|
-
children: /* @__PURE__ */
|
|
1863
|
+
children: /* @__PURE__ */ jsx3(
|
|
1619
1864
|
View,
|
|
1620
1865
|
{
|
|
1621
1866
|
pointerEvents: "none",
|
|
1622
1867
|
accessible: false,
|
|
1623
1868
|
accessibilityElementsHidden: true,
|
|
1624
1869
|
importantForAccessibility: "no-hide-descendants",
|
|
1625
|
-
children: rendered.content ?? /* @__PURE__ */
|
|
1870
|
+
children: rendered.content ?? /* @__PURE__ */ jsx3(View, { style: [dot, { backgroundColor: color }] })
|
|
1626
1871
|
}
|
|
1627
1872
|
)
|
|
1628
1873
|
}
|
|
@@ -1965,6 +2210,8 @@ var RETRY_LIMIT_MS = 6e4;
|
|
|
1965
2210
|
var RETRY_AFTER_LIMIT_MS = 15 * 60 * 1e3;
|
|
1966
2211
|
var RETRY_AFTER_SECONDS = /^\d{1,10}$/u;
|
|
1967
2212
|
var QUOTA_CODES = /* @__PURE__ */ new Set(["COMMERCIAL_MAP_LIMIT_REACHED", "COMMERCIAL_SPENDING_LIMIT_REACHED"]);
|
|
2213
|
+
var SERVICE_CODE = /^[A-Z][A-Z0-9_]{0,63}$/u;
|
|
2214
|
+
var SERVICE_CODE_BODY_LIMIT = 4096;
|
|
1968
2215
|
var MOBILE_CREDENTIAL = /^tf_public_[0-9a-f]{48}$/u;
|
|
1969
2216
|
var MAP_ID = /^map_[A-Za-z0-9_-]{16}$/u;
|
|
1970
2217
|
var CREDENTIAL_ID = /^key_[A-Za-z0-9_-]{8,80}$/u;
|
|
@@ -2008,7 +2255,8 @@ var TERMINAL_CODES = /* @__PURE__ */ new Set([
|
|
|
2008
2255
|
"NATIVE_SESSION_CREDENTIAL_REJECTED",
|
|
2009
2256
|
"NATIVE_SESSION_MAP_MISMATCH",
|
|
2010
2257
|
"NATIVE_SESSION_MAP_NOT_FOUND",
|
|
2011
|
-
"NATIVE_SESSION_QUOTA_EXCEEDED"
|
|
2258
|
+
"NATIVE_SESSION_QUOTA_EXCEEDED",
|
|
2259
|
+
"NATIVE_SESSION_REJECTED"
|
|
2012
2260
|
]);
|
|
2013
2261
|
var ERROR_MESSAGES = {
|
|
2014
2262
|
NATIVE_SESSION_INPUT_INVALID: "Native session configuration is invalid.",
|
|
@@ -2027,13 +2275,16 @@ var ERROR_MESSAGES = {
|
|
|
2027
2275
|
NATIVE_SESSION_DISPOSED: "Native session controller is disposed."
|
|
2028
2276
|
};
|
|
2029
2277
|
var HostedNativeSessionError = class extends Error {
|
|
2030
|
-
constructor(code) {
|
|
2278
|
+
constructor(code, reason) {
|
|
2031
2279
|
super(ERROR_MESSAGES[code]);
|
|
2032
2280
|
__publicField(this, "code");
|
|
2033
2281
|
__publicField(this, "kind");
|
|
2034
2282
|
this.name = "HostedNativeSessionError";
|
|
2035
2283
|
this.code = code;
|
|
2036
2284
|
this.kind = errorKind(code);
|
|
2285
|
+
if (code === "NATIVE_SESSION_REJECTED" && typeof reason === "string" && SERVICE_CODE.test(reason)) {
|
|
2286
|
+
this.reason = reason;
|
|
2287
|
+
}
|
|
2037
2288
|
}
|
|
2038
2289
|
};
|
|
2039
2290
|
function createHostedNativeSessionController(input) {
|
|
@@ -2162,10 +2413,10 @@ function createHostedNativeSessionController(input) {
|
|
|
2162
2413
|
if (retryAt === null || at >= retryAt) failures = Math.min(failures + 1, 16);
|
|
2163
2414
|
const backoff = Math.min(RETRY_INITIAL_MS * 2 ** (failures - 1), RETRY_LIMIT_MS);
|
|
2164
2415
|
retryAt = Math.max(retryAt ?? at, at + Math.max(backoff, retryAfterDelays.get(error) ?? 0));
|
|
2165
|
-
retryError =
|
|
2416
|
+
retryError = safeError(error);
|
|
2166
2417
|
}
|
|
2167
2418
|
function rotateIfRequired(at) {
|
|
2168
|
-
if (terminal) throw
|
|
2419
|
+
if (terminal) throw errorFrom(terminal);
|
|
2169
2420
|
if (!activeSession || binding.kind !== "hosted") return;
|
|
2170
2421
|
if (at - activeSession.startedAt < ROTATION_AGE_MS && activeSession.requestCount < ROTATION_REQUEST_LIMIT) {
|
|
2171
2422
|
return;
|
|
@@ -2199,7 +2450,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2199
2450
|
return current;
|
|
2200
2451
|
}
|
|
2201
2452
|
async function ensureAuthority(session, at) {
|
|
2202
|
-
if (terminal) throw
|
|
2453
|
+
if (terminal) throw errorFrom(terminal);
|
|
2203
2454
|
if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil - at > REFRESH_MARGIN_MS) {
|
|
2204
2455
|
return { authority: session.authority, session };
|
|
2205
2456
|
}
|
|
@@ -2211,7 +2462,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2211
2462
|
if (session.authority && session.authority.clockEpoch === clock.epoch && session.authority.validUntil > at) {
|
|
2212
2463
|
return { authority: session.authority, session };
|
|
2213
2464
|
}
|
|
2214
|
-
throw
|
|
2465
|
+
throw errorFrom(retryError);
|
|
2215
2466
|
}
|
|
2216
2467
|
const operationBinding = binding;
|
|
2217
2468
|
const abort = new SessionAbortController();
|
|
@@ -2238,14 +2489,16 @@ function createHostedNativeSessionController(input) {
|
|
|
2238
2489
|
const normalized = abort.signal.aborted ? abort.error() : normalizeError(error);
|
|
2239
2490
|
const target = latestSession(session);
|
|
2240
2491
|
if (normalized.kind === "terminal" && binding === operationBinding && !terminal) {
|
|
2241
|
-
const failure3 =
|
|
2492
|
+
const failure3 = safeError(normalized);
|
|
2242
2493
|
terminal = failure3;
|
|
2243
2494
|
const rejectedSession = activeSession;
|
|
2244
2495
|
if (rejectedSession) {
|
|
2245
2496
|
rejectedSession.authority = null;
|
|
2246
2497
|
rejectedSession.error = failure3;
|
|
2247
2498
|
}
|
|
2248
|
-
for (const pending of [...operations])
|
|
2499
|
+
for (const pending of [...operations]) {
|
|
2500
|
+
pending.abort(failure3.code, failure3.reason);
|
|
2501
|
+
}
|
|
2249
2502
|
if (binding === operationBinding && rejectedSession) {
|
|
2250
2503
|
publishSession(rejectedSession, "error", failure3);
|
|
2251
2504
|
}
|
|
@@ -2254,7 +2507,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2254
2507
|
delayRetry(normalized);
|
|
2255
2508
|
}
|
|
2256
2509
|
if (normalized.code !== "NATIVE_SESSION_REPLACED" && normalized.code !== "NATIVE_SESSION_DISPOSED") {
|
|
2257
|
-
target.error =
|
|
2510
|
+
target.error = safeError(normalized);
|
|
2258
2511
|
publishSession(target, "error", target.error);
|
|
2259
2512
|
}
|
|
2260
2513
|
throw normalized;
|
|
@@ -2280,7 +2533,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2280
2533
|
if (abort.signal.aborted) throw abort.error();
|
|
2281
2534
|
const expectedSurfaceId = session.authority?.public.surfaceId ?? session.requestedSurfaceId;
|
|
2282
2535
|
const response = await fetchResponse(hostedBinding, session, expectedSurfaceId, abort);
|
|
2283
|
-
const source = await readBoundedResponse(response, abort);
|
|
2536
|
+
const { source, size } = await readBoundedResponse(response, abort);
|
|
2284
2537
|
let body;
|
|
2285
2538
|
try {
|
|
2286
2539
|
body = source.length ? JSON.parse(source) : null;
|
|
@@ -2290,14 +2543,15 @@ function createHostedNativeSessionController(input) {
|
|
|
2290
2543
|
}
|
|
2291
2544
|
body = null;
|
|
2292
2545
|
}
|
|
2293
|
-
if (response.status === 409 &&
|
|
2546
|
+
if (response.status === 409 && isExactRestart(body, session.sessionId)) {
|
|
2547
|
+
if (!allowRestart) throw new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
|
|
2294
2548
|
assertCurrentSession(session, hostedBinding);
|
|
2295
2549
|
const replacement = redirectSession(session, readClock());
|
|
2296
2550
|
if (abort.signal.aborted) throw abort.error();
|
|
2297
2551
|
return bootstrap(replacement, hostedBinding, abort, false, false);
|
|
2298
2552
|
}
|
|
2299
2553
|
if (response.status !== 201) {
|
|
2300
|
-
const failure3 = statusError(response.status, body);
|
|
2554
|
+
const failure3 = statusError(response.status, body, size);
|
|
2301
2555
|
const delay = retryAfterMs(response.headers, now);
|
|
2302
2556
|
if (delay !== null) retryAfterDelays.set(failure3, delay);
|
|
2303
2557
|
throw failure3;
|
|
@@ -2435,7 +2689,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2435
2689
|
if (bindingGeneration !== expectedGeneration) {
|
|
2436
2690
|
throw new HostedNativeSessionError("NATIVE_SESSION_REPLACED");
|
|
2437
2691
|
}
|
|
2438
|
-
if (terminal) throw
|
|
2692
|
+
if (terminal) throw errorFrom(terminal);
|
|
2439
2693
|
checkedAt = readClock();
|
|
2440
2694
|
if (resolved.authority.clockEpoch === clock.epoch && resolved.authority.validUntil > checkedAt) {
|
|
2441
2695
|
admittedAuthorities.set(resolved.authority.public, resolved.authority);
|
|
@@ -2510,7 +2764,7 @@ function createHostedNativeSessionController(input) {
|
|
|
2510
2764
|
if (disposed) throw new HostedNativeSessionError("NATIVE_SESSION_DISPOSED");
|
|
2511
2765
|
lifecycle = "foreground";
|
|
2512
2766
|
if (terminal) {
|
|
2513
|
-
const error =
|
|
2767
|
+
const error = errorFrom(terminal);
|
|
2514
2768
|
publish(currentSnapshot());
|
|
2515
2769
|
throw error;
|
|
2516
2770
|
}
|
|
@@ -2783,7 +3037,7 @@ async function readBoundedResponse(response, abort) {
|
|
|
2783
3037
|
bytes.set(chunk, offset);
|
|
2784
3038
|
offset += chunk.byteLength;
|
|
2785
3039
|
}
|
|
2786
|
-
return decodeUtf8(bytes);
|
|
3040
|
+
return { source: decodeUtf8(bytes), size };
|
|
2787
3041
|
}
|
|
2788
3042
|
function decodeUtf8(bytes) {
|
|
2789
3043
|
let result = "";
|
|
@@ -2814,7 +3068,7 @@ function decodeUtf8(bytes) {
|
|
|
2814
3068
|
if (index + remaining > bytes.length) {
|
|
2815
3069
|
throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_UTF8_INVALID");
|
|
2816
3070
|
}
|
|
2817
|
-
for (let
|
|
3071
|
+
for (let count2 = 0; count2 < remaining; count2 += 1) {
|
|
2818
3072
|
const byte = bytes[index++];
|
|
2819
3073
|
if ((byte & 192) !== 128) {
|
|
2820
3074
|
throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_UTF8_INVALID");
|
|
@@ -2831,7 +3085,7 @@ function decodeUtf8(bytes) {
|
|
|
2831
3085
|
function hasNoStore(value) {
|
|
2832
3086
|
return typeof value === "string" && value.split(",").some((part) => part.trim().toLowerCase() === "no-store");
|
|
2833
3087
|
}
|
|
2834
|
-
function statusError(status, body) {
|
|
3088
|
+
function statusError(status, body, size) {
|
|
2835
3089
|
if (status === 401) return new HostedNativeSessionError("NATIVE_SESSION_CREDENTIAL_REJECTED");
|
|
2836
3090
|
if (status === 403) return new HostedNativeSessionError("NATIVE_SESSION_MAP_MISMATCH");
|
|
2837
3091
|
if (status === 404) return new HostedNativeSessionError("NATIVE_SESSION_MAP_NOT_FOUND");
|
|
@@ -2843,7 +3097,21 @@ function statusError(status, body) {
|
|
|
2843
3097
|
if (status === 408 || status >= 500 && status <= 599) {
|
|
2844
3098
|
return new HostedNativeSessionError("NATIVE_SESSION_UNAVAILABLE");
|
|
2845
3099
|
}
|
|
2846
|
-
|
|
3100
|
+
if (status >= 400 && status <= 499) {
|
|
3101
|
+
return new HostedNativeSessionError(
|
|
3102
|
+
"NATIVE_SESSION_REJECTED",
|
|
3103
|
+
size <= SERVICE_CODE_BODY_LIMIT && isRecord(body) && typeof body.code === "string" ? body.code : void 0
|
|
3104
|
+
);
|
|
3105
|
+
}
|
|
3106
|
+
return new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
|
|
3107
|
+
}
|
|
3108
|
+
function safeError(error) {
|
|
3109
|
+
return Object.freeze(
|
|
3110
|
+
error.reason === void 0 ? { code: error.code, kind: error.kind } : { code: error.code, kind: error.kind, reason: error.reason }
|
|
3111
|
+
);
|
|
3112
|
+
}
|
|
3113
|
+
function errorFrom(error) {
|
|
3114
|
+
return new HostedNativeSessionError(error.code, error.reason);
|
|
2847
3115
|
}
|
|
2848
3116
|
var retryAfterDelays = /* @__PURE__ */ new WeakMap();
|
|
2849
3117
|
function retryAfterMs(headers, now) {
|
|
@@ -2893,12 +3161,13 @@ async function cancelResponse(response) {
|
|
|
2893
3161
|
} catch {
|
|
2894
3162
|
}
|
|
2895
3163
|
}
|
|
2896
|
-
var _aborted, _code, _listeners;
|
|
3164
|
+
var _aborted, _code, _reason, _listeners;
|
|
2897
3165
|
var SessionAbortController = class {
|
|
2898
3166
|
constructor() {
|
|
2899
3167
|
__publicField(this, "signal");
|
|
2900
3168
|
__privateAdd(this, _aborted, false);
|
|
2901
3169
|
__privateAdd(this, _code, "NATIVE_SESSION_REPLACED");
|
|
3170
|
+
__privateAdd(this, _reason);
|
|
2902
3171
|
__privateAdd(this, _listeners, /* @__PURE__ */ new Set());
|
|
2903
3172
|
const isAborted = () => __privateGet(this, _aborted);
|
|
2904
3173
|
this.signal = Object.freeze({
|
|
@@ -2913,9 +3182,10 @@ var SessionAbortController = class {
|
|
|
2913
3182
|
}
|
|
2914
3183
|
});
|
|
2915
3184
|
}
|
|
2916
|
-
abort(code) {
|
|
3185
|
+
abort(code, reason) {
|
|
2917
3186
|
if (__privateGet(this, _aborted)) return;
|
|
2918
3187
|
__privateSet(this, _code, code);
|
|
3188
|
+
__privateSet(this, _reason, reason);
|
|
2919
3189
|
__privateSet(this, _aborted, true);
|
|
2920
3190
|
for (const listener of [...__privateGet(this, _listeners)]) {
|
|
2921
3191
|
try {
|
|
@@ -2926,11 +3196,12 @@ var SessionAbortController = class {
|
|
|
2926
3196
|
__privateGet(this, _listeners).clear();
|
|
2927
3197
|
}
|
|
2928
3198
|
error() {
|
|
2929
|
-
return new HostedNativeSessionError(__privateGet(this, _code));
|
|
3199
|
+
return new HostedNativeSessionError(__privateGet(this, _code), __privateGet(this, _reason));
|
|
2930
3200
|
}
|
|
2931
3201
|
};
|
|
2932
3202
|
_aborted = new WeakMap();
|
|
2933
3203
|
_code = new WeakMap();
|
|
3204
|
+
_reason = new WeakMap();
|
|
2934
3205
|
_listeners = new WeakMap();
|
|
2935
3206
|
function raceWithAbort(promise, controller) {
|
|
2936
3207
|
if (controller.signal.aborted) return Promise.reject(controller.error());
|
|
@@ -3238,7 +3509,7 @@ function createNativeAdmissionOwner(options) {
|
|
|
3238
3509
|
reported = code;
|
|
3239
3510
|
if (state.status !== "error") return;
|
|
3240
3511
|
try {
|
|
3241
|
-
input.onSessionError?.(Object.freeze({
|
|
3512
|
+
input.onSessionError?.(Object.freeze({ ...state.error }));
|
|
3242
3513
|
} catch {
|
|
3243
3514
|
}
|
|
3244
3515
|
});
|
|
@@ -3864,27 +4135,27 @@ function decode(bytes) {
|
|
|
3864
4135
|
for (let index = 0; index < bytes.length; ) {
|
|
3865
4136
|
const first = bytes[index++];
|
|
3866
4137
|
let code;
|
|
3867
|
-
let
|
|
4138
|
+
let count2;
|
|
3868
4139
|
let minimum;
|
|
3869
4140
|
if (first <= 127) {
|
|
3870
4141
|
code = first;
|
|
3871
|
-
|
|
4142
|
+
count2 = 0;
|
|
3872
4143
|
minimum = 0;
|
|
3873
4144
|
} else if (first >= 194 && first <= 223) {
|
|
3874
4145
|
code = first & 31;
|
|
3875
|
-
|
|
4146
|
+
count2 = 1;
|
|
3876
4147
|
minimum = 128;
|
|
3877
4148
|
} else if (first >= 224 && first <= 239) {
|
|
3878
4149
|
code = first & 15;
|
|
3879
|
-
|
|
4150
|
+
count2 = 2;
|
|
3880
4151
|
minimum = 2048;
|
|
3881
4152
|
} else if (first >= 240 && first <= 244) {
|
|
3882
4153
|
code = first & 7;
|
|
3883
|
-
|
|
4154
|
+
count2 = 3;
|
|
3884
4155
|
minimum = 65536;
|
|
3885
4156
|
} else throw new NativePreparationError();
|
|
3886
|
-
if (index +
|
|
3887
|
-
for (let part = 0; part <
|
|
4157
|
+
if (index + count2 > bytes.length) throw new NativePreparationError();
|
|
4158
|
+
for (let part = 0; part < count2; part++) {
|
|
3888
4159
|
const next = bytes[index++];
|
|
3889
4160
|
if ((next & 192) !== 128) throw new NativePreparationError();
|
|
3890
4161
|
code = code * 64 + (next & 63);
|
|
@@ -5568,7 +5839,7 @@ function fontMetadata(input, developmentOrigin) {
|
|
|
5568
5839
|
}
|
|
5569
5840
|
function validateFontFaces(faces, documentUrl, metadata, add, rewrites, policy, discriminate, developmentOrigin) {
|
|
5570
5841
|
if (Object.keys(faces).length > nativePreparationLimits.fontFaces) throw invalid3();
|
|
5571
|
-
let
|
|
5842
|
+
let count2 = 0;
|
|
5572
5843
|
const matched = /* @__PURE__ */ new Set();
|
|
5573
5844
|
for (const name3 of Object.keys(faces).sort()) {
|
|
5574
5845
|
if (name3.length === 0 || name3.length > 256 || name3 !== name3.trim()) throw invalid3();
|
|
@@ -5576,7 +5847,7 @@ function validateFontFaces(faces, documentUrl, metadata, add, rewrites, policy,
|
|
|
5576
5847
|
if (!Array.isArray(definitions) || definitions.length === 0) throw invalid3();
|
|
5577
5848
|
const rewritten = [];
|
|
5578
5849
|
for (const definition of definitions) {
|
|
5579
|
-
if (++
|
|
5850
|
+
if (++count2 > nativePreparationLimits.fontFaces || !record2(definition)) throw invalid3();
|
|
5580
5851
|
const keys = Object.keys(definition).sort();
|
|
5581
5852
|
if (keys.length !== 4 || !["font-family", "font-style", "font-weight", "url"].every((key2) => keys.includes(key2)))
|
|
5582
5853
|
throw invalid3();
|
|
@@ -5824,8 +6095,10 @@ var sessionErrorCodes = /* @__PURE__ */ new Set([
|
|
|
5824
6095
|
"NATIVE_SESSION_MAP_MISMATCH",
|
|
5825
6096
|
"NATIVE_SESSION_MAP_NOT_FOUND",
|
|
5826
6097
|
"NATIVE_SESSION_QUOTA_EXCEEDED",
|
|
6098
|
+
"NATIVE_SESSION_REJECTED",
|
|
5827
6099
|
"NATIVE_SESSION_INPUT_INVALID"
|
|
5828
6100
|
]);
|
|
6101
|
+
var SERVICE_CODE2 = /^[A-Z][A-Z0-9_]{0,63}$/u;
|
|
5829
6102
|
function themeSource(source, name3) {
|
|
5830
6103
|
const theme = Object.hasOwn(source.map.themes, name3) ? source.map.themes[name3] : void 0;
|
|
5831
6104
|
if (!theme) throw new NativePreparationError();
|
|
@@ -6085,9 +6358,14 @@ function createMountedMapOwner(ports2) {
|
|
|
6085
6358
|
reopenings += 1;
|
|
6086
6359
|
restart(epoch);
|
|
6087
6360
|
}
|
|
6088
|
-
function sessionError(epoch, code) {
|
|
6361
|
+
function sessionError(epoch, code, reason) {
|
|
6089
6362
|
if (disposed || current !== epoch || !epoch.live || !sessionErrorCodes.has(code)) return;
|
|
6090
|
-
const
|
|
6363
|
+
const detail = code === "NATIVE_SESSION_REJECTED" && typeof reason === "string" && SERVICE_CODE2.test(reason) ? { reason } : {};
|
|
6364
|
+
const error = Object.freeze({
|
|
6365
|
+
code,
|
|
6366
|
+
kind: "terminal",
|
|
6367
|
+
...detail
|
|
6368
|
+
});
|
|
6091
6369
|
emit({ type: "session-error", generation: generation(), error });
|
|
6092
6370
|
}
|
|
6093
6371
|
function createEpoch(developmentOrigin) {
|
|
@@ -6125,7 +6403,7 @@ function createMountedMapOwner(ports2) {
|
|
|
6125
6403
|
onRetired: () => void Promise.resolve().then(() => reopen(epoch)),
|
|
6126
6404
|
onSessionError: (error) => {
|
|
6127
6405
|
if (error.kind !== "terminal") return;
|
|
6128
|
-
void Promise.resolve().then(() => sessionError(epoch, error.code));
|
|
6406
|
+
void Promise.resolve().then(() => sessionError(epoch, error.code, error.reason));
|
|
6129
6407
|
}
|
|
6130
6408
|
});
|
|
6131
6409
|
const map = await epoch.lease.ready;
|
|
@@ -7670,7 +7948,7 @@ function createNativeMapOwner() {
|
|
|
7670
7948
|
}
|
|
7671
7949
|
|
|
7672
7950
|
// src/map.tsx
|
|
7673
|
-
import { jsx as
|
|
7951
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7674
7952
|
var fill = Object.freeze({ flex: 1 });
|
|
7675
7953
|
function NativeScene({
|
|
7676
7954
|
scene,
|
|
@@ -7680,17 +7958,18 @@ function NativeScene({
|
|
|
7680
7958
|
interactions,
|
|
7681
7959
|
interactionEnabled,
|
|
7682
7960
|
renderMarker,
|
|
7683
|
-
boundaryFeatureState
|
|
7961
|
+
boundaryFeatureState,
|
|
7962
|
+
data
|
|
7684
7963
|
}) {
|
|
7685
|
-
const view =
|
|
7686
|
-
const camera =
|
|
7687
|
-
const nativeMap =
|
|
7688
|
-
const committedHost =
|
|
7689
|
-
const tag =
|
|
7690
|
-
const laidOut =
|
|
7691
|
-
const styleLoaded =
|
|
7692
|
-
const attachRequested =
|
|
7693
|
-
const latestStyle =
|
|
7964
|
+
const view = useRef2(null);
|
|
7965
|
+
const camera = useRef2(null);
|
|
7966
|
+
const nativeMap = useRef2(null);
|
|
7967
|
+
const committedHost = useRef2(void 0);
|
|
7968
|
+
const tag = useRef2(null);
|
|
7969
|
+
const laidOut = useRef2(false);
|
|
7970
|
+
const styleLoaded = useRef2(false);
|
|
7971
|
+
const attachRequested = useRef2(false);
|
|
7972
|
+
const latestStyle = useRef2(scene.style);
|
|
7694
7973
|
latestStyle.current = scene.style;
|
|
7695
7974
|
const [loadedStyle, setLoadedStyle] = useState2(void 0);
|
|
7696
7975
|
const host = useMemo3(() => {
|
|
@@ -7745,7 +8024,42 @@ function NativeScene({
|
|
|
7745
8024
|
};
|
|
7746
8025
|
const annotations = interactions?.annotations;
|
|
7747
8026
|
const byId = new globalThis.Map(annotations?.map((annotation) => [annotation.id, annotation]));
|
|
7748
|
-
|
|
8027
|
+
const [zoomLevel, setZoomLevel] = useState2(() => Math.floor(scene.initialView.zoom));
|
|
8028
|
+
const followZoom = (event) => {
|
|
8029
|
+
if (Number.isFinite(event.nativeEvent.zoom)) setZoomLevel(Math.floor(event.nativeEvent.zoom));
|
|
8030
|
+
};
|
|
8031
|
+
const clusterSettings = data.annotationClusters;
|
|
8032
|
+
const clusterKey = JSON.stringify(clusterSettings ?? null);
|
|
8033
|
+
const clusterIndex = useMemo3(
|
|
8034
|
+
() => clusterSettings && annotations ? createNativeAnnotationClusters(annotations, clusterSettings) : void 0,
|
|
8035
|
+
// Options written inline are new objects each render; only a real change rebuilds groups.
|
|
8036
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8037
|
+
[annotations, clusterKey]
|
|
8038
|
+
);
|
|
8039
|
+
const clusterView = clusterIndex?.at(zoomLevel);
|
|
8040
|
+
const styleReady = loadedStyle === scene.style;
|
|
8041
|
+
const dataPlan = useMemo3(
|
|
8042
|
+
() => planNativeDataLayers({
|
|
8043
|
+
dataOverlays: data.dataOverlays,
|
|
8044
|
+
dataSources: data.dataSources,
|
|
8045
|
+
style: scene.style
|
|
8046
|
+
}),
|
|
8047
|
+
[data.dataOverlays, data.dataSources, scene.style]
|
|
8048
|
+
);
|
|
8049
|
+
const reportedPlan = useRef2(void 0);
|
|
8050
|
+
useLayoutEffect3(() => {
|
|
8051
|
+
if (reportedPlan.current === dataPlan) return;
|
|
8052
|
+
reportedPlan.current = dataPlan;
|
|
8053
|
+
for (const { message, path } of dataPlan.diagnostics)
|
|
8054
|
+
data.onDiagnostic({ code: "INVALID_DATA_LAYER", level: "error", message, path });
|
|
8055
|
+
}, [data, dataPlan]);
|
|
8056
|
+
const activate = (target) => data.onActivate({
|
|
8057
|
+
coordinate: target.coordinate,
|
|
8058
|
+
inputModality: "touch",
|
|
8059
|
+
target,
|
|
8060
|
+
type: "target:activate"
|
|
8061
|
+
});
|
|
8062
|
+
return /* @__PURE__ */ jsx4(
|
|
7749
8063
|
View2,
|
|
7750
8064
|
{
|
|
7751
8065
|
ref: bind2,
|
|
@@ -7762,13 +8076,15 @@ function NativeScene({
|
|
|
7762
8076
|
lifecycle.layoutChanged(scene.key);
|
|
7763
8077
|
attach();
|
|
7764
8078
|
},
|
|
7765
|
-
children: /* @__PURE__ */
|
|
8079
|
+
children: /* @__PURE__ */ jsxs2(
|
|
7766
8080
|
NativeMap,
|
|
7767
8081
|
{
|
|
7768
8082
|
...mapOptions,
|
|
7769
8083
|
ref: nativeMap,
|
|
7770
8084
|
style: fill,
|
|
7771
8085
|
mapStyle,
|
|
8086
|
+
onRegionIsChanging: followZoom,
|
|
8087
|
+
onRegionDidChange: followZoom,
|
|
7772
8088
|
onPress: (event) => {
|
|
7773
8089
|
if (!host.current()) return;
|
|
7774
8090
|
try {
|
|
@@ -7787,7 +8103,7 @@ function NativeScene({
|
|
|
7787
8103
|
attach();
|
|
7788
8104
|
},
|
|
7789
8105
|
children: [
|
|
7790
|
-
/* @__PURE__ */
|
|
8106
|
+
/* @__PURE__ */ jsx4(
|
|
7791
8107
|
NativeCamera,
|
|
7792
8108
|
{
|
|
7793
8109
|
ref: camera,
|
|
@@ -7797,21 +8113,57 @@ function NativeScene({
|
|
|
7797
8113
|
},
|
|
7798
8114
|
"tileflow-camera"
|
|
7799
8115
|
),
|
|
7800
|
-
/* @__PURE__ */
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
8116
|
+
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
8117
|
+
interactions?.plan.order.map((id) => {
|
|
8118
|
+
const annotation = byId.get(id);
|
|
8119
|
+
return annotation && !clusterView?.hiddenAnnotationIds.has(id) ? /* @__PURE__ */ jsx4(
|
|
8120
|
+
NativeAnnotationMarker,
|
|
8121
|
+
{
|
|
8122
|
+
annotation,
|
|
8123
|
+
enabled: interactionEnabled,
|
|
8124
|
+
sceneKey: scene.key,
|
|
8125
|
+
lifecycle,
|
|
8126
|
+
renderMarker
|
|
8127
|
+
},
|
|
8128
|
+
annotation.id
|
|
8129
|
+
) : null;
|
|
8130
|
+
}),
|
|
8131
|
+
clusterView?.clusters.map((cluster) => /* @__PURE__ */ jsx4(
|
|
8132
|
+
NativeClusterMarker,
|
|
7804
8133
|
{
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
8134
|
+
cluster,
|
|
8135
|
+
label: clusterSettings?.formatAriaLabel?.(cluster.pointCount) ?? `${cluster.pointCount} places`,
|
|
8136
|
+
onPress: () => {
|
|
8137
|
+
activate({
|
|
8138
|
+
annotationIds: cluster.annotationIds,
|
|
8139
|
+
clusterId: cluster.clusterId,
|
|
8140
|
+
coordinate: cluster.coordinate,
|
|
8141
|
+
kind: "cluster",
|
|
8142
|
+
pointCount: cluster.pointCount,
|
|
8143
|
+
properties: { point_count: cluster.pointCount }
|
|
8144
|
+
});
|
|
8145
|
+
if (data.expand && clusterSettings?.expandOnClick !== false)
|
|
8146
|
+
camera.current?.easeTo({
|
|
8147
|
+
center: [cluster.coordinate[0], cluster.coordinate[1]],
|
|
8148
|
+
duration: 400,
|
|
8149
|
+
zoom: cluster.expansionZoom
|
|
8150
|
+
});
|
|
8151
|
+
}
|
|
7810
8152
|
},
|
|
7811
|
-
|
|
7812
|
-
)
|
|
7813
|
-
|
|
7814
|
-
|
|
8153
|
+
`cluster-${cluster.clusterId}`
|
|
8154
|
+
))
|
|
8155
|
+
] }, "tileflow-annotations"),
|
|
8156
|
+
styleReady ? /* @__PURE__ */ jsx4(
|
|
8157
|
+
NativeDataLayers,
|
|
8158
|
+
{
|
|
8159
|
+
camera,
|
|
8160
|
+
expand: data.expand,
|
|
8161
|
+
onActivate: activate,
|
|
8162
|
+
plan: dataPlan
|
|
8163
|
+
},
|
|
8164
|
+
"tileflow-data-layers"
|
|
8165
|
+
) : null,
|
|
8166
|
+
boundaryFeatureState ? /* @__PURE__ */ jsx4(
|
|
7815
8167
|
NativeBoundaryFeatureState,
|
|
7816
8168
|
{
|
|
7817
8169
|
input: boundaryFeatureState,
|
|
@@ -7836,6 +8188,22 @@ function Map2(props) {
|
|
|
7836
8188
|
lifecycle.getSnapshot,
|
|
7837
8189
|
lifecycle.getSnapshot
|
|
7838
8190
|
);
|
|
8191
|
+
const latestProps = useRef2(props);
|
|
8192
|
+
latestProps.current = props;
|
|
8193
|
+
const [callbacks] = useState2(() => ({
|
|
8194
|
+
onActivate: (event) => latestProps.current.onInteractionEvent?.({ ...event, type: "target:activate" }),
|
|
8195
|
+
onDiagnostic: (diagnostic) => latestProps.current.onInteractionDiagnostic?.(diagnostic)
|
|
8196
|
+
}));
|
|
8197
|
+
const data = useMemo3(
|
|
8198
|
+
() => ({
|
|
8199
|
+
annotationClusters: props.annotationClusters,
|
|
8200
|
+
dataOverlays: props.dataOverlays,
|
|
8201
|
+
dataSources: props.dataSources,
|
|
8202
|
+
expand: props.view === void 0,
|
|
8203
|
+
...callbacks
|
|
8204
|
+
}),
|
|
8205
|
+
[callbacks, props.annotationClusters, props.dataOverlays, props.dataSources, props.view]
|
|
8206
|
+
);
|
|
7839
8207
|
useImperativeHandle(
|
|
7840
8208
|
props.ref,
|
|
7841
8209
|
() => Object.freeze({ getSourceState: lifecycle.getSourceState, retry: lifecycle.retry }),
|
|
@@ -7856,7 +8224,7 @@ function Map2(props) {
|
|
|
7856
8224
|
useLayoutEffect3(() => {
|
|
7857
8225
|
lifecycle.update(props);
|
|
7858
8226
|
});
|
|
7859
|
-
return /* @__PURE__ */
|
|
8227
|
+
return /* @__PURE__ */ jsx4(View2, { style: props.style, testID: props.testID, children: snapshot.renderer ? /* @__PURE__ */ jsx4(
|
|
7860
8228
|
NativeScene,
|
|
7861
8229
|
{
|
|
7862
8230
|
scene: snapshot.renderer,
|
|
@@ -7866,6 +8234,7 @@ function Map2(props) {
|
|
|
7866
8234
|
interactionEnabled: snapshot.interactionEnabled === true,
|
|
7867
8235
|
renderMarker: props.renderMarker,
|
|
7868
8236
|
boundaryFeatureState: props.boundaryFeatureState,
|
|
8237
|
+
data,
|
|
7869
8238
|
children: props.children
|
|
7870
8239
|
},
|
|
7871
8240
|
snapshot.renderer.key
|