@chelone/core 0.5.0 → 0.7.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.
Files changed (253) hide show
  1. package/dist/assistant/assistant-session.d.ts +28 -0
  2. package/dist/assistant/assistant-session.js +208 -0
  3. package/dist/assistant/echo-transport.d.ts +7 -0
  4. package/dist/assistant/echo-transport.js +28 -0
  5. package/dist/assistant/http-transport.d.ts +10 -0
  6. package/dist/assistant/http-transport.js +98 -0
  7. package/dist/assistant/types.d.ts +54 -0
  8. package/dist/auth/access-control.d.ts +13 -5
  9. package/dist/auth/access-control.js +25 -21
  10. package/dist/auth/auth-options.d.ts +21 -17
  11. package/dist/auth/auth-options.js +80 -48
  12. package/dist/auth/permission-matrix.d.ts +12 -0
  13. package/dist/auth/permission-matrix.js +67 -0
  14. package/dist/auth/types.d.ts +14 -4
  15. package/dist/block-editor/block-document.d.ts +60 -0
  16. package/dist/block-editor/block-document.js +143 -0
  17. package/dist/block-editor/data-blocks.d.ts +63 -0
  18. package/dist/block-editor/data-blocks.js +117 -0
  19. package/dist/chart/chart-data.d.ts +25 -0
  20. package/dist/chart/chart-data.js +61 -0
  21. package/dist/command-menu/hotkey.js +58 -47
  22. package/dist/command-menu/recents.js +8 -11
  23. package/dist/command-menu/registry.d.ts +9 -5
  24. package/dist/command-menu/registry.js +36 -46
  25. package/dist/controller/calendar-dates.js +82 -113
  26. package/dist/controller/calendar-events.js +93 -88
  27. package/dist/controller/client-list-controller.d.ts +2 -2
  28. package/dist/controller/client-list-controller.js +251 -254
  29. package/dist/controller/data-table-columns.d.ts +2 -0
  30. package/dist/controller/data-table-columns.js +50 -56
  31. package/dist/controller/deep-equal.d.ts +1 -0
  32. package/dist/controller/deep-equal.js +14 -0
  33. package/dist/controller/filter-toggle.js +36 -44
  34. package/dist/controller/in-place-editor.d.ts +42 -0
  35. package/dist/controller/in-place-editor.js +42 -0
  36. package/dist/controller/infinite-list-controller.js +220 -190
  37. package/dist/controller/inspector.d.ts +49 -0
  38. package/dist/controller/inspector.js +64 -0
  39. package/dist/controller/job-monitor.d.ts +41 -0
  40. package/dist/controller/job-monitor.js +49 -0
  41. package/dist/controller/kanban-board.d.ts +2 -3
  42. package/dist/controller/kanban-board.js +43 -24
  43. package/dist/controller/list-controller.d.ts +5 -5
  44. package/dist/controller/list-controller.js +444 -400
  45. package/dist/controller/list-params.js +96 -87
  46. package/dist/controller/pivot-grid.d.ts +36 -0
  47. package/dist/controller/pivot-grid.js +99 -0
  48. package/dist/controller/prev-next.d.ts +2 -2
  49. package/dist/controller/prev-next.js +74 -54
  50. package/dist/controller/record-controllers.d.ts +14 -6
  51. package/dist/controller/record-controllers.js +288 -257
  52. package/dist/controller/record-diff.d.ts +21 -0
  53. package/dist/controller/record-diff.js +50 -0
  54. package/dist/controller/record-timeline.d.ts +35 -0
  55. package/dist/controller/record-timeline.js +48 -0
  56. package/dist/controller/record-tree.js +57 -47
  57. package/dist/controller/record-workflow.d.ts +38 -16
  58. package/dist/controller/record-workflow.js +85 -64
  59. package/dist/controller/reference-many-controller.js +198 -192
  60. package/dist/controller/reference-one-controller.d.ts +1 -1
  61. package/dist/controller/reference-one-controller.js +63 -56
  62. package/dist/controller/saved-queries.js +104 -91
  63. package/dist/controller/translate-fallback.js +10 -6
  64. package/dist/csv/export.d.ts +2 -1
  65. package/dist/csv/export.js +43 -40
  66. package/dist/csv/import-controller.js +185 -169
  67. package/dist/csv/match-headers.js +29 -22
  68. package/dist/csv/parse-with.js +60 -54
  69. package/dist/csv/run-import.js +69 -72
  70. package/dist/csv/validate-rows.d.ts +1 -1
  71. package/dist/csv/validate-rows.js +65 -52
  72. package/dist/data/cache-ops.d.ts +5 -4
  73. package/dist/data/cache-ops.js +208 -190
  74. package/dist/data/combine-data-providers.js +25 -23
  75. package/dist/data/data-provider-log.d.ts +45 -0
  76. package/dist/data/data-provider-log.js +93 -0
  77. package/dist/data/errors.js +14 -10
  78. package/dist/data/fake-provider.d.ts +6 -3
  79. package/dist/data/fake-provider.js +129 -114
  80. package/dist/data/fetch-utils.js +61 -44
  81. package/dist/data/filter-branch.d.ts +5 -0
  82. package/dist/data/filter-branch.js +10 -0
  83. package/dist/data/get-many-aggregate.js +84 -76
  84. package/dist/data/http-error.js +17 -12
  85. package/dist/data/keys.js +50 -36
  86. package/dist/data/mutation-options.d.ts +14 -9
  87. package/dist/data/mutation-options.js +93 -109
  88. package/dist/data/query-options.js +73 -68
  89. package/dist/data/remove-empty.d.ts +3 -0
  90. package/dist/data/remove-empty.js +11 -0
  91. package/dist/data/undoable.d.ts +2 -2
  92. package/dist/data/undoable.js +190 -174
  93. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  94. package/dist/data/with-lifecycle-callbacks.js +66 -52
  95. package/dist/environment/application-update-store.js +58 -55
  96. package/dist/environment/offline-store.js +21 -21
  97. package/dist/form/array-binding.d.ts +30 -11
  98. package/dist/form/array-binding.js +184 -166
  99. package/dist/form/choice-ids.d.ts +7 -0
  100. package/dist/form/choice-ids.js +11 -0
  101. package/dist/form/choices-controller.d.ts +3 -2
  102. package/dist/form/choices-controller.js +302 -275
  103. package/dist/form/date-format.d.ts +38 -0
  104. package/dist/form/date-format.js +89 -0
  105. package/dist/form/dirty-values.d.ts +2 -2
  106. package/dist/form/dirty-values.js +22 -11
  107. package/dist/form/duration.d.ts +22 -0
  108. package/dist/form/duration.js +49 -0
  109. package/dist/form/edit-create-form.d.ts +12 -5
  110. package/dist/form/edit-create-form.js +243 -188
  111. package/dist/form/event-value.d.ts +6 -0
  112. package/dist/form/event-value.js +17 -0
  113. package/dist/form/field-error.d.ts +14 -0
  114. package/dist/form/field-error.js +28 -0
  115. package/dist/form/field-name.d.ts +20 -0
  116. package/dist/form/field-name.js +6 -0
  117. package/dist/form/filter-form-values.js +63 -49
  118. package/dist/form/form-controller.d.ts +9 -1
  119. package/dist/form/form-controller.js +165 -160
  120. package/dist/form/form-groups.d.ts +4 -3
  121. package/dist/form/form-groups.js +79 -79
  122. package/dist/form/form-handle.d.ts +175 -0
  123. package/dist/form/form-handle.js +68 -0
  124. package/dist/form/input-binding.d.ts +56 -31
  125. package/dist/form/input-binding.js +169 -118
  126. package/dist/form/input-values.d.ts +130 -0
  127. package/dist/form/input-values.js +177 -0
  128. package/dist/form/json-text.js +51 -37
  129. package/dist/form/save-pipeline.d.ts +6 -8
  130. package/dist/form/save-pipeline.js +91 -82
  131. package/dist/form/set-form-values.d.ts +6 -0
  132. package/dist/form/set-form-values.js +10 -0
  133. package/dist/form/source.js +97 -65
  134. package/dist/form/text-of.d.ts +2 -0
  135. package/dist/form/text-of.js +7 -0
  136. package/dist/form/validators.d.ts +58 -19
  137. package/dist/form/validators.js +97 -71
  138. package/dist/geo/bbox.d.ts +5 -4
  139. package/dist/geo/bbox.js +69 -48
  140. package/dist/geo/bounds.d.ts +14 -3
  141. package/dist/geo/bounds.js +98 -68
  142. package/dist/geo/constraints.js +88 -93
  143. package/dist/geo/coordinates.js +31 -23
  144. package/dist/geo/editor.d.ts +13 -13
  145. package/dist/geo/editor.js +176 -153
  146. package/dist/geo/geocoding.d.ts +4 -4
  147. package/dist/geo/geocoding.js +38 -41
  148. package/dist/geo/geojson.d.ts +12 -74
  149. package/dist/geo/geojson.js +52 -40
  150. package/dist/geo/geometry-math.d.ts +4 -4
  151. package/dist/geo/geometry-math.js +100 -93
  152. package/dist/geo/index.d.ts +7 -6
  153. package/dist/geo/map-layers.d.ts +42 -7
  154. package/dist/geo/map-layers.js +88 -62
  155. package/dist/geo/map-style.js +31 -32
  156. package/dist/geo/messages.js +48 -45
  157. package/dist/geo/nominatim.js +88 -80
  158. package/dist/geo/osm-presets.d.ts +4 -3
  159. package/dist/geo/osm-presets.js +108 -86
  160. package/dist/geo/osm-tags.js +14 -12
  161. package/dist/geo/overpass.d.ts +14 -2
  162. package/dist/geo/overpass.js +83 -90
  163. package/dist/geo/shape-value.d.ts +9 -5
  164. package/dist/geo/shape-value.js +169 -146
  165. package/dist/geo/snap-to-roads.d.ts +3 -3
  166. package/dist/geo/snap-to-roads.js +55 -50
  167. package/dist/geo/throttle.js +36 -39
  168. package/dist/guards.d.ts +37 -0
  169. package/dist/guards.js +62 -0
  170. package/dist/i18n/default-messages.js +34 -29
  171. package/dist/i18n/english-messages.js +187 -189
  172. package/dist/i18n/i18n.d.ts +8 -2
  173. package/dist/i18n/i18n.js +47 -48
  174. package/dist/i18n/inflection.d.ts +34 -0
  175. package/dist/i18n/inflection.js +82 -0
  176. package/dist/i18n/messages.d.ts +10 -2
  177. package/dist/i18n/messages.js +17 -4
  178. package/dist/i18n/missing-keys.d.ts +19 -0
  179. package/dist/i18n/missing-keys.js +68 -0
  180. package/dist/i18n/translatable.d.ts +16 -1
  181. package/dist/i18n/translatable.js +40 -47
  182. package/dist/index.d.ts +96 -22
  183. package/dist/index.js +52 -257
  184. package/dist/json/deep-equal.d.ts +8 -0
  185. package/dist/json/deep-equal.js +24 -0
  186. package/dist/json/strip-json-comments.js +38 -42
  187. package/dist/noop.d.ts +2 -0
  188. package/dist/noop.js +4 -0
  189. package/dist/notification/error-message.d.ts +2 -0
  190. package/dist/notification/error-message.js +10 -0
  191. package/dist/notification/notification-store.d.ts +3 -2
  192. package/dist/notification/notification-store.js +41 -45
  193. package/dist/onboarding-tour/placement.d.ts +34 -0
  194. package/dist/onboarding-tour/placement.js +67 -0
  195. package/dist/onboarding-tour/tour-controller.d.ts +25 -0
  196. package/dist/onboarding-tour/tour-controller.js +50 -0
  197. package/dist/realtime/add-events-for-mutations.js +75 -81
  198. package/dist/realtime/announce-lock.d.ts +7 -0
  199. package/dist/realtime/announce-lock.js +18 -0
  200. package/dist/realtime/broadcast-channel-transport.d.ts +14 -0
  201. package/dist/realtime/broadcast-channel-transport.js +69 -0
  202. package/dist/realtime/copy-members.js +22 -14
  203. package/dist/realtime/in-memory-lock-provider.js +41 -60
  204. package/dist/realtime/live.js +95 -101
  205. package/dist/realtime/lock-options.js +16 -16
  206. package/dist/realtime/lock-session.js +91 -78
  207. package/dist/realtime/memory-transport.js +26 -67
  208. package/dist/realtime/presence.js +120 -122
  209. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  210. package/dist/realtime/realtime-data-provider.js +45 -42
  211. package/dist/realtime/reconnect-backoff.d.ts +15 -0
  212. package/dist/realtime/reconnect-backoff.js +17 -0
  213. package/dist/realtime/sse-transport.d.ts +31 -0
  214. package/dist/realtime/sse-transport.js +235 -0
  215. package/dist/realtime/status-store.js +23 -28
  216. package/dist/realtime/topic-hub.d.ts +24 -0
  217. package/dist/realtime/topic-hub.js +66 -0
  218. package/dist/realtime/topics.js +10 -12
  219. package/dist/realtime/types.js +10 -12
  220. package/dist/realtime/unread-count.js +21 -21
  221. package/dist/realtime/websocket-transport.d.ts +32 -0
  222. package/dist/realtime/websocket-transport.js +306 -0
  223. package/dist/resource/describe-resource.d.ts +2 -0
  224. package/dist/resource/describe-resource.js +232 -219
  225. package/dist/resource/get-at-path.js +29 -14
  226. package/dist/resource/identifier.d.ts +18 -0
  227. package/dist/resource/identifier.js +27 -0
  228. package/dist/resource/record.d.ts +4 -0
  229. package/dist/resource/record.js +10 -0
  230. package/dist/resource/register.d.ts +7 -0
  231. package/dist/resource/registry-store.d.ts +45 -15
  232. package/dist/resource/registry-store.js +67 -60
  233. package/dist/resource/registry.d.ts +10 -0
  234. package/dist/resource/registry.js +8 -4
  235. package/dist/resource/source-path.d.ts +16 -1
  236. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  237. package/dist/rich-text/rich-text-extras.js +179 -0
  238. package/dist/rich-text/rich-text-image.d.ts +124 -0
  239. package/dist/rich-text/rich-text-image.js +163 -0
  240. package/dist/rich-text/rich-text.d.ts +62 -0
  241. package/dist/rich-text/rich-text.js +142 -0
  242. package/dist/router/location.d.ts +22 -4
  243. package/dist/router/location.js +41 -18
  244. package/dist/router/match.js +47 -39
  245. package/dist/router/paths.js +40 -34
  246. package/dist/router/record-from-location.d.ts +1 -1
  247. package/dist/router/record-from-location.js +25 -17
  248. package/dist/store/adapters.js +51 -55
  249. package/dist/store/micro-store.js +57 -59
  250. package/dist/store/shallow-equal.d.ts +12 -0
  251. package/dist/store/shallow-equal.js +20 -0
  252. package/dist/store/store.js +54 -57
  253. package/package.json +13 -11
@@ -1,57 +1,69 @@
1
- function isRecord(value) {
2
- return typeof value === "object" && value !== null && !Array.isArray(value);
3
- }
1
+ import { isJsonObject, isRecord } from "../guards.js";
2
+ // src/geo/geojson.ts
4
3
  function isFiniteNumber(value) {
5
- return typeof value === "number" && Number.isFinite(value);
4
+ return typeof value === "number" && Number.isFinite(value);
6
5
  }
7
6
  function isPosition(value) {
8
- return Array.isArray(value) && value.length >= 2 && value.every(isFiniteNumber);
7
+ return Array.isArray(value) && value.length >= 2 && value.every(isFiniteNumber);
9
8
  }
9
+ /** Checks `depth` levels of arrays above the positions (0 is a position). */
10
10
  function isNested(value, depth) {
11
- if (depth === 0) return isPosition(value);
12
- return Array.isArray(value) && value.every((item) => isNested(item, depth - 1));
13
- }
14
- const COORDINATE_DEPTH = {
15
- Point: 0,
16
- MultiPoint: 1,
17
- LineString: 1,
18
- MultiLineString: 2,
19
- Polygon: 2,
20
- MultiPolygon: 3
11
+ if (depth === 0) return isPosition(value);
12
+ return Array.isArray(value) && value.every((item) => isNested(item, depth - 1));
13
+ }
14
+ /** Array depth above the positions, per geometry type. */
15
+ var COORDINATE_DEPTH = {
16
+ Point: 0,
17
+ MultiPoint: 1,
18
+ LineString: 1,
19
+ MultiLineString: 2,
20
+ Polygon: 2,
21
+ MultiPolygon: 3
21
22
  };
23
+ /** True for exactly four finite numbers. */
22
24
  function isGeoBBox(value) {
23
- return Array.isArray(value) && value.length === 4 && value.every(isFiniteNumber);
25
+ return Array.isArray(value) && value.length === 4 && value.every(isFiniteNumber);
24
26
  }
27
+ /** The `bbox` member of an object: 4 numbers, or 6 when it carries altitude. */
25
28
  function hasValidBBox(value) {
26
- const { bbox } = value;
27
- if (bbox === void 0) return true;
28
- return Array.isArray(bbox) && (bbox.length === 4 || bbox.length === 6) && bbox.every(isFiniteNumber);
29
+ const { bbox } = value;
30
+ if (bbox === void 0) return true;
31
+ return Array.isArray(bbox) && (bbox.length === 4 || bbox.length === 6) && bbox.every(isFiniteNumber);
29
32
  }
30
33
  function isGeoGeometry(value) {
31
- if (!isRecord(value) || !hasValidBBox(value)) return false;
32
- if (value.type === "GeometryCollection") {
33
- return Array.isArray(value.geometries) && value.geometries.every(isGeoGeometry);
34
- }
35
- const depth = typeof value.type === "string" && Object.hasOwn(COORDINATE_DEPTH, value.type) ? COORDINATE_DEPTH[value.type] : void 0;
36
- return depth !== void 0 && isNested(value.coordinates, depth);
34
+ if (!isRecord(value) || !hasValidBBox(value)) return false;
35
+ if (value.type === "GeometryCollection") return Array.isArray(value.geometries) && value.geometries.every(isGeoGeometry);
36
+ const depth = typeof value.type === "string" && Object.hasOwn(COORDINATE_DEPTH, value.type) ? COORDINATE_DEPTH[value.type] : void 0;
37
+ return depth !== void 0 && isNested(value.coordinates, depth);
38
+ }
39
+ /** A Polygon or a MultiPolygon, the geometries turf's area operations take. */
40
+ function isGeoArea(value) {
41
+ return isGeoGeometry(value) && (value.type === "Polygon" || value.type === "MultiPolygon");
37
42
  }
38
43
  function isGeoFeature(value) {
39
- if (!isRecord(value) || value.type !== "Feature" || !hasValidBBox(value)) {
40
- return false;
41
- }
42
- if (value.geometry !== null && !isGeoGeometry(value.geometry)) return false;
43
- return value.properties === void 0 || value.properties === null || isRecord(value.properties);
44
+ if (!isRecord(value) || value.type !== "Feature" || !hasValidBBox(value)) return false;
45
+ if (value.geometry !== null && !isGeoGeometry(value.geometry)) return false;
46
+ return value.properties === void 0 || value.properties === null || isJsonObject(value.properties);
44
47
  }
45
48
  function isGeoFeatureCollection(value) {
46
- return isRecord(value) && value.type === "FeatureCollection" && hasValidBBox(value) && Array.isArray(value.features) && value.features.every(isGeoFeature);
49
+ return isRecord(value) && value.type === "FeatureCollection" && hasValidBBox(value) && Array.isArray(value.features) && value.features.every(isGeoFeature);
47
50
  }
48
51
  function isGeoJsonValue(value) {
49
- return isGeoGeometry(value) || isGeoFeature(value) || isGeoFeatureCollection(value);
50
- }
51
- export {
52
- isGeoBBox,
53
- isGeoFeature,
54
- isGeoFeatureCollection,
55
- isGeoGeometry,
56
- isGeoJsonValue
57
- };
52
+ return isGeoGeometry(value) || isGeoFeature(value) || isGeoFeatureCollection(value);
53
+ }
54
+ /** The features MapLibre draws: a feature with a null geometry has nothing to draw. */
55
+ function placedFeatures(collection) {
56
+ const features = [];
57
+ for (const feature of collection.features) {
58
+ const { geometry } = feature;
59
+ if (geometry !== null) features.push({
60
+ ...feature,
61
+ geometry
62
+ });
63
+ }
64
+ return {
65
+ ...collection,
66
+ features
67
+ };
68
+ }
69
+ export { isGeoArea, isGeoBBox, isGeoFeature, isGeoFeatureCollection, isGeoGeometry, isGeoJsonValue, placedFeatures };
@@ -1,17 +1,17 @@
1
- import type { GeoGeometry } from "./geojson.js";
1
+ import type { Geometry } from "geojson";
2
2
  /**
3
3
  * Area in square metres on a sphere of radius 6378137 m, as `@turf/area`
4
4
  * computes it. Holes are subtracted. `0` for every type but Polygon and
5
5
  * MultiPolygon.
6
6
  */
7
- export declare function geoAreaM2(geometry: GeoGeometry): number;
7
+ export declare function geoAreaM2(geometry: Geometry): number;
8
8
  /**
9
9
  * True when two non-adjacent segments of a ring or a line cross or touch.
10
10
  * Rings of one polygon, or polygons of one collection, are not compared with
11
11
  * each other.
12
12
  */
13
- export declare function hasSelfIntersection(geometry: GeoGeometry): boolean;
14
- type Area = Extract<GeoGeometry, {
13
+ export declare function hasSelfIntersection(geometry: Geometry): boolean;
14
+ type Area = Extract<Geometry, {
15
15
  type: "Polygon" | "MultiPolygon";
16
16
  }>;
17
17
  /**
@@ -1,120 +1,127 @@
1
- const EARTH_RADIUS_M = 6378137;
1
+ // src/geo/geometry-math.ts
2
+ var EARTH_RADIUS_M = 6378137;
2
3
  function toRadians(degrees) {
3
- return degrees * Math.PI / 180;
4
+ return degrees * Math.PI / 180;
4
5
  }
6
+ /** An element of an array whose index the caller keeps in range. */
5
7
  function at(positions, index) {
6
- return positions[index];
8
+ const position = positions[index];
9
+ if (!position) throw new RangeError(`No position at index ${index}`);
10
+ return position;
11
+ }
12
+ /** Longitude and latitude; `NaN` for one a short position lacks. */
13
+ function xy([x = NaN, y = NaN]) {
14
+ return [x, y];
7
15
  }
8
16
  function samePosition(a, b) {
9
- return a[0] === b[0] && a[1] === b[1];
17
+ const [ax, ay] = xy(a);
18
+ const [bx, by] = xy(b);
19
+ return ax === bx && ay === by;
10
20
  }
21
+ /** Drops a closing position that repeats the first one. */
11
22
  function openRing(ring) {
12
- const last = ring[ring.length - 1];
13
- return ring.length > 1 && last && samePosition(at(ring, 0), last) ? ring.slice(0, -1) : ring;
23
+ const last = ring[ring.length - 1];
24
+ return ring.length > 1 && last && samePosition(at(ring, 0), last) ? ring.slice(0, -1) : ring;
14
25
  }
26
+ /** Unsigned area of one ring on the sphere. */
15
27
  function ringAreaM2(ring) {
16
- const points = openRing(ring);
17
- const count = points.length;
18
- if (count < 3) return 0;
19
- let sum = 0;
20
- for (let i = 0; i < count; i++) {
21
- const before = at(points, (i + count - 1) % count);
22
- const here = at(points, i);
23
- const after = at(points, (i + 1) % count);
24
- sum += (toRadians(after[0]) - toRadians(before[0])) * Math.sin(toRadians(here[1]));
25
- }
26
- return Math.abs(sum * EARTH_RADIUS_M * EARTH_RADIUS_M / 2);
28
+ const points = openRing(ring);
29
+ const count = points.length;
30
+ if (count < 3) return 0;
31
+ let sum = 0;
32
+ for (let i = 0; i < count; i++) {
33
+ const before = at(points, (i + count - 1) % count);
34
+ const here = at(points, i);
35
+ const after = at(points, (i + 1) % count);
36
+ sum += (toRadians(xy(after)[0]) - toRadians(xy(before)[0])) * Math.sin(toRadians(xy(here)[1]));
37
+ }
38
+ return Math.abs(sum * EARTH_RADIUS_M * EARTH_RADIUS_M / 2);
27
39
  }
28
40
  function polygonAreaM2(rings) {
29
- const [outer, ...holes] = rings;
30
- if (!outer) return 0;
31
- return holes.reduce(
32
- (area, hole) => area - ringAreaM2(hole),
33
- ringAreaM2(outer)
34
- );
41
+ const [outer, ...holes] = rings;
42
+ if (!outer) return 0;
43
+ return holes.reduce((area, hole) => area - ringAreaM2(hole), ringAreaM2(outer));
35
44
  }
45
+ /**
46
+ * Area in square metres on a sphere of radius 6378137 m, as `@turf/area`
47
+ * computes it. Holes are subtracted. `0` for every type but Polygon and
48
+ * MultiPolygon.
49
+ */
36
50
  function geoAreaM2(geometry) {
37
- if (geometry.type === "Polygon") return polygonAreaM2(geometry.coordinates);
38
- if (geometry.type === "MultiPolygon") {
39
- return geometry.coordinates.reduce(
40
- (total, polygon) => total + polygonAreaM2(polygon),
41
- 0
42
- );
43
- }
44
- return 0;
51
+ if (geometry.type === "Polygon") return polygonAreaM2(geometry.coordinates);
52
+ if (geometry.type === "MultiPolygon") return geometry.coordinates.reduce((total, polygon) => total + polygonAreaM2(polygon), 0);
53
+ return 0;
45
54
  }
55
+ /** Twice the signed area of the triangle `a`, `b`, `c`. */
46
56
  function cross(a, b, c) {
47
- return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
57
+ const [ax, ay] = xy(a);
58
+ const [bx, by] = xy(b);
59
+ const [cx, cy] = xy(c);
60
+ return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
48
61
  }
49
62
  function onSegment(a, b, point) {
50
- return point[0] >= Math.min(a[0], b[0]) && point[0] <= Math.max(a[0], b[0]) && point[1] >= Math.min(a[1], b[1]) && point[1] <= Math.max(a[1], b[1]);
63
+ const [ax, ay] = xy(a);
64
+ const [bx, by] = xy(b);
65
+ const [px, py] = xy(point);
66
+ return px >= Math.min(ax, bx) && px <= Math.max(ax, bx) && py >= Math.min(ay, by) && py <= Math.max(ay, by);
51
67
  }
68
+ /** True when the segments share any point, a touch or an overlap included. */
52
69
  function segmentsMeet(a, b, c, d) {
53
- const abc = cross(a, b, c);
54
- const abd = cross(a, b, d);
55
- const cda = cross(c, d, a);
56
- const cdb = cross(c, d, b);
57
- if ((abc > 0 && abd < 0 || abc < 0 && abd > 0) && (cda > 0 && cdb < 0 || cda < 0 && cdb > 0)) {
58
- return true;
59
- }
60
- return abc === 0 && onSegment(a, b, c) || abd === 0 && onSegment(a, b, d) || cda === 0 && onSegment(c, d, a) || cdb === 0 && onSegment(c, d, b);
70
+ const abc = cross(a, b, c);
71
+ const abd = cross(a, b, d);
72
+ const cda = cross(c, d, a);
73
+ const cdb = cross(c, d, b);
74
+ if ((abc > 0 && abd < 0 || abc < 0 && abd > 0) && (cda > 0 && cdb < 0 || cda < 0 && cdb > 0)) return true;
75
+ return abc === 0 && onSegment(a, b, c) || abd === 0 && onSegment(a, b, d) || cda === 0 && onSegment(c, d, a) || cdb === 0 && onSegment(c, d, b);
61
76
  }
77
+ /**
78
+ * True when two segments that do not follow each other share a point.
79
+ * `closed` makes the last segment follow the first.
80
+ */
62
81
  function pathSelfIntersects(positions, closed) {
63
- const points = positions.filter(
64
- (position, index) => index === 0 || !samePosition(position, at(positions, index - 1))
65
- );
66
- const segments = closed ? points.length : points.length - 1;
67
- for (let i = 0; i < segments; i++) {
68
- for (let j = i + 2; j < segments; j++) {
69
- if (closed && i === 0 && j === segments - 1) continue;
70
- if (segmentsMeet(
71
- at(points, i),
72
- at(points, (i + 1) % points.length),
73
- at(points, j),
74
- at(points, (j + 1) % points.length)
75
- )) {
76
- return true;
77
- }
78
- }
79
- }
80
- return false;
82
+ const points = positions.filter((position, index) => index === 0 || !samePosition(position, at(positions, index - 1)));
83
+ const segments = closed ? points.length : points.length - 1;
84
+ for (let i = 0; i < segments; i++) for (let j = i + 2; j < segments; j++) {
85
+ if (closed && i === 0 && j === segments - 1) continue;
86
+ if (segmentsMeet(at(points, i), at(points, (i + 1) % points.length), at(points, j), at(points, (j + 1) % points.length))) return true;
87
+ }
88
+ return false;
81
89
  }
82
90
  function lineSelfIntersects(line) {
83
- const first = line[0];
84
- const last = line[line.length - 1];
85
- const closed = line.length > 3 && first !== void 0 && last !== void 0 && samePosition(first, last);
86
- return pathSelfIntersects(closed ? line.slice(0, -1) : line, closed);
91
+ const first = line[0];
92
+ const last = line[line.length - 1];
93
+ const closed = line.length > 3 && first !== void 0 && last !== void 0 && samePosition(first, last);
94
+ return pathSelfIntersects(closed ? line.slice(0, -1) : line, closed);
87
95
  }
96
+ /**
97
+ * True when two non-adjacent segments of a ring or a line cross or touch.
98
+ * Rings of one polygon, or polygons of one collection, are not compared with
99
+ * each other.
100
+ */
88
101
  function hasSelfIntersection(geometry) {
89
- switch (geometry.type) {
90
- case "LineString":
91
- return lineSelfIntersects(geometry.coordinates);
92
- case "MultiLineString":
93
- return geometry.coordinates.some(lineSelfIntersects);
94
- case "Polygon":
95
- return geometry.coordinates.some(
96
- (ring) => pathSelfIntersects(openRing(ring), true)
97
- );
98
- case "MultiPolygon":
99
- return geometry.coordinates.some(
100
- (polygon) => polygon.some((ring) => pathSelfIntersects(openRing(ring), true))
101
- );
102
- case "GeometryCollection":
103
- return geometry.geometries.some(hasSelfIntersection);
104
- default:
105
- return false;
106
- }
102
+ switch (geometry.type) {
103
+ case "LineString": return lineSelfIntersects(geometry.coordinates);
104
+ case "MultiLineString": return geometry.coordinates.some(lineSelfIntersects);
105
+ case "Polygon": return geometry.coordinates.some((ring) => pathSelfIntersects(openRing(ring), true));
106
+ case "MultiPolygon": return geometry.coordinates.some((polygon) => polygon.some((ring) => pathSelfIntersects(openRing(ring), true)));
107
+ case "GeometryCollection": return geometry.geometries.some(hasSelfIntersection);
108
+ default: return false;
109
+ }
107
110
  }
108
- const areaInTypeOf = (value, result) => {
109
- if (value.type === "MultiPolygon") {
110
- return result.type === "Polygon" ? { type: "MultiPolygon", coordinates: [result.coordinates] } : result;
111
- }
112
- if (result.type === "Polygon") return result;
113
- const [only, ...rest] = result.coordinates;
114
- return only && rest.length === 0 ? { type: "Polygon", coordinates: only } : null;
115
- };
116
- export {
117
- areaInTypeOf,
118
- geoAreaM2,
119
- hasSelfIntersection
111
+ /**
112
+ * `result` in the type of `value`, so it stays editable by the input that owns
113
+ * the field. `null` when a Polygon would have to hold several pieces.
114
+ */
115
+ var areaInTypeOf = (value, result) => {
116
+ if (value.type === "MultiPolygon") return result.type === "Polygon" ? {
117
+ type: "MultiPolygon",
118
+ coordinates: [result.coordinates]
119
+ } : result;
120
+ if (result.type === "Polygon") return result;
121
+ const [only, ...rest] = result.coordinates;
122
+ return only && rest.length === 0 ? {
123
+ type: "Polygon",
124
+ coordinates: only
125
+ } : null;
120
126
  };
127
+ export { areaInTypeOf, geoAreaM2, hasSelfIntersection };
@@ -1,15 +1,16 @@
1
1
  export { aspectLockedBBox, bboxToPolygon, polygonToBBox } from "./bbox.js";
2
+ export type { LngLatBox } from "./bounds.js";
2
3
  export { geoBounds, isLngLatBox } from "./bounds.js";
3
4
  export { countVertices, maxVertices, minAreaM2, minVertices, noSelfIntersection, } from "./constraints.js";
4
5
  export { latitude, longitude, toCoordinate } from "./coordinates.js";
5
- export type { EditorSnapshotFeature, EditorStyles } from "./editor.js";
6
+ export type { EditorFeature, EditorSnapshotFeature, EditorStyles, } from "./editor.js";
6
7
  export { editorStyles, fromEditorFeatures, toEditorFeatures } from "./editor.js";
7
8
  export type { GeocodeQuery, GeocodeQueryOptions, GeocodeRequestOptions, GeocodeResult, GeocodeSearchOptions, GeocodingProvider, ReverseGeocodeQueryOptions, } from "./geocoding.js";
8
9
  export { geocodeQueryOptions, reverseGeocodeQueryOptions } from "./geocoding.js";
9
- export type { GeoBBox, GeoBBox3D, GeoFeature, GeoFeatureCollection, GeoGeometry, GeoGeometryCollection, GeoJsonValue, GeoLineString, GeoMultiLineString, GeoMultiPoint, GeoMultiPolygon, GeoPoint, GeoPolygon, GeoPosition, } from "./geojson.js";
10
- export { isGeoBBox, isGeoFeature, isGeoFeatureCollection, isGeoGeometry, isGeoJsonValue, } from "./geojson.js";
10
+ export type { Feature, FeatureCollection, Geometry } from "./geojson.js";
11
+ export { isGeoArea, isGeoBBox, isGeoFeature, isGeoFeatureCollection, isGeoGeometry, isGeoJsonValue, placedFeatures, } from "./geojson.js";
11
12
  export { areaInTypeOf, geoAreaM2, hasSelfIntersection, } from "./geometry-math.js";
12
- export type { ShapeLayerSpec, ShapeStyle } from "./map-layers.js";
13
+ export type { CircleLayerSpec, FillLayerSpec, LineLayerSpec, ShapeLayerSpec, ShapeStyle, } from "./map-layers.js";
13
14
  export { asFeatureCollection, DEFAULT_SHAPE_STYLE, shapeLayerSpecs, } from "./map-layers.js";
14
15
  export type { MapStyleInput, MapStyleSpec, RasterTileStyleOptions, } from "./map-style.js";
15
16
  export { expandTileUrl, latLngToLngLat, lngLatToLatLng, rasterTileStyle, } from "./map-style.js";
@@ -20,8 +21,8 @@ export type { OsmElementType, OsmPreset, OsmPresetName, OverpassQuerySources, }
20
21
  export { buildOverpassQuery, findPresetForTags, OSM_PRESETS, } from "./osm-presets.js";
21
22
  export type { OsmTagFilter, OsmTagInput } from "./osm-tags.js";
22
23
  export { tagToFilter } from "./osm-tags.js";
23
- export type { OverpassProvider, OverpassProviderOptions, OverpassQuery, OverpassQueryOptions, OverpassRequestOptions, } from "./overpass.js";
24
- export { createOverpassProvider, OverpassError, OverpassRateLimitError, OverpassTimeoutError, overpassQueryOptions, } from "./overpass.js";
24
+ export type { OverpassAnswer, OverpassElement, OverpassProvider, OverpassProviderOptions, OverpassQuery, OverpassQueryOptions, OverpassRequestOptions, } from "./overpass.js";
25
+ export { createOverpassProvider, isOverpassAnswer, OverpassError, OverpassRateLimitError, OverpassTimeoutError, overpassQueryOptions, } from "./overpass.js";
25
26
  export type { FeaturesToShapeOptions, ShapeValue, ShapeValueKind, } from "./shape-value.js";
26
27
  export { featuresToShape, heldFeatures, shapeToFeatures } from "./shape-value.js";
27
28
  export type { OsrmProviderOptions, RoutingProvider } from "./snap-to-roads.js";
@@ -1,4 +1,5 @@
1
- import type { GeoFeatureCollection } from "./geojson.js";
1
+ import type { FeatureCollection, Geometry } from "geojson";
2
+ import type { JsonObject } from "../guards.js";
2
3
  export interface ShapeStyle {
3
4
  color?: string;
4
5
  /** Line width in pixels. */
@@ -19,19 +20,53 @@ export declare const DEFAULT_SHAPE_STYLE: {
19
20
  readonly pointColor: "#3b82f6";
20
21
  readonly pointRadius: 7;
21
22
  };
22
- export interface ShapeLayerSpec {
23
+ /** `["==", ["geometry-type"], type]`: `geometry-type` is the base type for the Multi types. */
24
+ type GeometryTypeTest<TType extends "Polygon" | "LineString" | "Point"> = [
25
+ "==",
26
+ [
27
+ "geometry-type"
28
+ ],
29
+ TType
30
+ ];
31
+ export interface FillLayerSpec {
23
32
  id: string;
24
- type: "fill" | "line" | "circle";
33
+ type: "fill";
25
34
  source: string;
26
- filter: unknown[];
27
- paint: Record<string, string | number>;
35
+ filter: GeometryTypeTest<"Polygon">;
36
+ paint: {
37
+ "fill-color": string;
38
+ "fill-opacity": number;
39
+ };
28
40
  }
41
+ export interface LineLayerSpec {
42
+ id: string;
43
+ type: "line";
44
+ source: string;
45
+ filter: ["any", GeometryTypeTest<"LineString">, GeometryTypeTest<"Polygon">];
46
+ paint: {
47
+ "line-color": string;
48
+ "line-width": number;
49
+ "line-opacity": number;
50
+ };
51
+ }
52
+ export interface CircleLayerSpec {
53
+ id: string;
54
+ type: "circle";
55
+ source: string;
56
+ filter: GeometryTypeTest<"Point">;
57
+ paint: {
58
+ "circle-color": string;
59
+ "circle-radius": number;
60
+ };
61
+ }
62
+ export type ShapeLayerSpec = FillLayerSpec | LineLayerSpec | CircleLayerSpec;
29
63
  /**
30
64
  * Fill, line and point layers for one GeoJSON source. `geometry-type` returns
31
65
  * the base type for the Multi types too, so they need no filter of their own.
32
66
  * The line layer also matches Polygon, so `color`, `weight` and `opacity` give
33
67
  * polygons an outline.
34
68
  */
35
- export declare function shapeLayerSpecs(sourceId: string, style: ShapeStyle): [ShapeLayerSpec, ShapeLayerSpec, ShapeLayerSpec];
69
+ export declare function shapeLayerSpecs(sourceId: string, style: ShapeStyle): [FillLayerSpec, LineLayerSpec, CircleLayerSpec];
36
70
  /** Never throws: anything that is not GeoJSON becomes an empty collection. */
37
- export declare function asFeatureCollection(value: unknown): GeoFeatureCollection;
71
+ export declare function asFeatureCollection(value: unknown): FeatureCollection<Geometry | null, JsonObject | null>;
72
+ export {};
@@ -1,67 +1,93 @@
1
- import { isGeoFeatureCollection, isGeoFeature, isGeoGeometry } from "./geojson.js";
2
- const DEFAULT_SHAPE_STYLE = {
3
- color: "#3388ff",
4
- weight: 3,
5
- opacity: 1,
6
- fillOpacity: 0.2,
7
- pointColor: "#3b82f6",
8
- pointRadius: 7
1
+ import { isGeoFeature, isGeoFeatureCollection, isGeoGeometry } from "./geojson.js";
2
+ // src/geo/map-layers.ts
3
+ var DEFAULT_SHAPE_STYLE = {
4
+ color: "#3388ff",
5
+ weight: 3,
6
+ opacity: 1,
7
+ fillOpacity: .2,
8
+ pointColor: "#3b82f6",
9
+ pointRadius: 7
9
10
  };
11
+ /**
12
+ * Fill, line and point layers for one GeoJSON source. `geometry-type` returns
13
+ * the base type for the Multi types too, so they need no filter of their own.
14
+ * The line layer also matches Polygon, so `color`, `weight` and `opacity` give
15
+ * polygons an outline.
16
+ */
10
17
  function shapeLayerSpecs(sourceId, style) {
11
- const color = style.color ?? DEFAULT_SHAPE_STYLE.color;
12
- return [
13
- {
14
- id: `${sourceId}-fill`,
15
- type: "fill",
16
- source: sourceId,
17
- filter: ["==", ["geometry-type"], "Polygon"],
18
- paint: {
19
- "fill-color": style.fillColor ?? color,
20
- "fill-opacity": style.fillOpacity ?? DEFAULT_SHAPE_STYLE.fillOpacity
21
- }
22
- },
23
- {
24
- id: `${sourceId}-line`,
25
- type: "line",
26
- source: sourceId,
27
- filter: [
28
- "any",
29
- ["==", ["geometry-type"], "LineString"],
30
- ["==", ["geometry-type"], "Polygon"]
31
- ],
32
- paint: {
33
- "line-color": color,
34
- "line-width": style.weight ?? DEFAULT_SHAPE_STYLE.weight,
35
- "line-opacity": style.opacity ?? DEFAULT_SHAPE_STYLE.opacity
36
- }
37
- },
38
- {
39
- id: `${sourceId}-point`,
40
- type: "circle",
41
- source: sourceId,
42
- filter: ["==", ["geometry-type"], "Point"],
43
- paint: {
44
- "circle-color": style.pointColor ?? DEFAULT_SHAPE_STYLE.pointColor,
45
- "circle-radius": style.pointRadius ?? DEFAULT_SHAPE_STYLE.pointRadius
46
- }
47
- }
48
- ];
18
+ const color = style.color ?? DEFAULT_SHAPE_STYLE.color;
19
+ return [
20
+ {
21
+ id: `${sourceId}-fill`,
22
+ type: "fill",
23
+ source: sourceId,
24
+ filter: [
25
+ "==",
26
+ ["geometry-type"],
27
+ "Polygon"
28
+ ],
29
+ paint: {
30
+ "fill-color": style.fillColor ?? color,
31
+ "fill-opacity": style.fillOpacity ?? DEFAULT_SHAPE_STYLE.fillOpacity
32
+ }
33
+ },
34
+ {
35
+ id: `${sourceId}-line`,
36
+ type: "line",
37
+ source: sourceId,
38
+ filter: [
39
+ "any",
40
+ [
41
+ "==",
42
+ ["geometry-type"],
43
+ "LineString"
44
+ ],
45
+ [
46
+ "==",
47
+ ["geometry-type"],
48
+ "Polygon"
49
+ ]
50
+ ],
51
+ paint: {
52
+ "line-color": color,
53
+ "line-width": style.weight ?? DEFAULT_SHAPE_STYLE.weight,
54
+ "line-opacity": style.opacity ?? DEFAULT_SHAPE_STYLE.opacity
55
+ }
56
+ },
57
+ {
58
+ id: `${sourceId}-point`,
59
+ type: "circle",
60
+ source: sourceId,
61
+ filter: [
62
+ "==",
63
+ ["geometry-type"],
64
+ "Point"
65
+ ],
66
+ paint: {
67
+ "circle-color": style.pointColor ?? DEFAULT_SHAPE_STYLE.pointColor,
68
+ "circle-radius": style.pointRadius ?? DEFAULT_SHAPE_STYLE.pointRadius
69
+ }
70
+ }
71
+ ];
49
72
  }
73
+ /** Never throws: anything that is not GeoJSON becomes an empty collection. */
50
74
  function asFeatureCollection(value) {
51
- if (isGeoFeatureCollection(value)) return value;
52
- if (isGeoFeature(value)) {
53
- return { type: "FeatureCollection", features: [value] };
54
- }
55
- if (isGeoGeometry(value)) {
56
- return {
57
- type: "FeatureCollection",
58
- features: [{ type: "Feature", geometry: value, properties: {} }]
59
- };
60
- }
61
- return { type: "FeatureCollection", features: [] };
75
+ if (isGeoFeatureCollection(value)) return value;
76
+ if (isGeoFeature(value)) return {
77
+ type: "FeatureCollection",
78
+ features: [value]
79
+ };
80
+ if (isGeoGeometry(value)) return {
81
+ type: "FeatureCollection",
82
+ features: [{
83
+ type: "Feature",
84
+ geometry: value,
85
+ properties: {}
86
+ }]
87
+ };
88
+ return {
89
+ type: "FeatureCollection",
90
+ features: []
91
+ };
62
92
  }
63
- export {
64
- DEFAULT_SHAPE_STYLE,
65
- asFeatureCollection,
66
- shapeLayerSpecs
67
- };
93
+ export { DEFAULT_SHAPE_STYLE, asFeatureCollection, shapeLayerSpecs };