@chelone/core 0.6.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 (242) hide show
  1. package/dist/assistant/assistant-session.d.ts +6 -0
  2. package/dist/assistant/assistant-session.js +204 -181
  3. package/dist/assistant/echo-transport.js +26 -29
  4. package/dist/assistant/http-transport.d.ts +10 -0
  5. package/dist/assistant/http-transport.js +98 -0
  6. package/dist/assistant/types.d.ts +1 -7
  7. package/dist/auth/access-control.d.ts +13 -5
  8. package/dist/auth/access-control.js +25 -21
  9. package/dist/auth/auth-options.d.ts +21 -17
  10. package/dist/auth/auth-options.js +80 -48
  11. package/dist/auth/permission-matrix.d.ts +12 -0
  12. package/dist/auth/permission-matrix.js +67 -0
  13. package/dist/auth/types.d.ts +14 -4
  14. package/dist/block-editor/block-document.d.ts +60 -0
  15. package/dist/block-editor/block-document.js +143 -0
  16. package/dist/block-editor/data-blocks.d.ts +63 -0
  17. package/dist/block-editor/data-blocks.js +117 -0
  18. package/dist/chart/chart-data.js +46 -44
  19. package/dist/command-menu/hotkey.js +58 -47
  20. package/dist/command-menu/recents.js +8 -11
  21. package/dist/command-menu/registry.d.ts +9 -5
  22. package/dist/command-menu/registry.js +36 -46
  23. package/dist/controller/calendar-dates.js +82 -113
  24. package/dist/controller/calendar-events.js +93 -88
  25. package/dist/controller/client-list-controller.d.ts +2 -2
  26. package/dist/controller/client-list-controller.js +251 -254
  27. package/dist/controller/data-table-columns.d.ts +2 -0
  28. package/dist/controller/data-table-columns.js +50 -56
  29. package/dist/controller/deep-equal.d.ts +1 -0
  30. package/dist/controller/deep-equal.js +14 -0
  31. package/dist/controller/filter-toggle.js +36 -44
  32. package/dist/controller/in-place-editor.d.ts +42 -0
  33. package/dist/controller/in-place-editor.js +42 -0
  34. package/dist/controller/infinite-list-controller.js +219 -189
  35. package/dist/controller/inspector.d.ts +49 -0
  36. package/dist/controller/inspector.js +64 -0
  37. package/dist/controller/job-monitor.d.ts +3 -4
  38. package/dist/controller/job-monitor.js +37 -47
  39. package/dist/controller/kanban-board.d.ts +2 -3
  40. package/dist/controller/kanban-board.js +43 -24
  41. package/dist/controller/list-controller.d.ts +5 -5
  42. package/dist/controller/list-controller.js +444 -400
  43. package/dist/controller/list-params.js +96 -87
  44. package/dist/controller/pivot-grid.js +89 -95
  45. package/dist/controller/prev-next.d.ts +2 -2
  46. package/dist/controller/prev-next.js +74 -54
  47. package/dist/controller/record-controllers.d.ts +14 -6
  48. package/dist/controller/record-controllers.js +288 -257
  49. package/dist/controller/record-diff.d.ts +21 -0
  50. package/dist/controller/record-diff.js +50 -0
  51. package/dist/controller/record-timeline.js +42 -30
  52. package/dist/controller/record-tree.js +57 -47
  53. package/dist/controller/record-workflow.d.ts +38 -16
  54. package/dist/controller/record-workflow.js +85 -64
  55. package/dist/controller/reference-many-controller.js +198 -192
  56. package/dist/controller/reference-one-controller.d.ts +1 -1
  57. package/dist/controller/reference-one-controller.js +63 -56
  58. package/dist/controller/saved-queries.js +104 -91
  59. package/dist/controller/translate-fallback.js +10 -6
  60. package/dist/csv/export.d.ts +2 -1
  61. package/dist/csv/export.js +43 -40
  62. package/dist/csv/import-controller.js +185 -169
  63. package/dist/csv/match-headers.js +29 -22
  64. package/dist/csv/parse-with.js +60 -54
  65. package/dist/csv/run-import.js +69 -72
  66. package/dist/csv/validate-rows.d.ts +1 -1
  67. package/dist/csv/validate-rows.js +65 -52
  68. package/dist/data/cache-ops.d.ts +5 -4
  69. package/dist/data/cache-ops.js +208 -188
  70. package/dist/data/combine-data-providers.js +25 -23
  71. package/dist/data/data-provider-log.d.ts +45 -0
  72. package/dist/data/data-provider-log.js +93 -0
  73. package/dist/data/errors.js +14 -10
  74. package/dist/data/fake-provider.d.ts +6 -3
  75. package/dist/data/fake-provider.js +129 -114
  76. package/dist/data/fetch-utils.js +61 -44
  77. package/dist/data/filter-branch.d.ts +5 -0
  78. package/dist/data/filter-branch.js +10 -0
  79. package/dist/data/get-many-aggregate.js +84 -76
  80. package/dist/data/http-error.js +17 -12
  81. package/dist/data/keys.js +50 -36
  82. package/dist/data/mutation-options.d.ts +14 -9
  83. package/dist/data/mutation-options.js +93 -109
  84. package/dist/data/query-options.js +73 -68
  85. package/dist/data/remove-empty.d.ts +3 -0
  86. package/dist/data/remove-empty.js +11 -0
  87. package/dist/data/undoable.d.ts +2 -2
  88. package/dist/data/undoable.js +190 -174
  89. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  90. package/dist/data/with-lifecycle-callbacks.js +66 -52
  91. package/dist/environment/application-update-store.js +58 -55
  92. package/dist/environment/offline-store.js +21 -21
  93. package/dist/form/array-binding.d.ts +30 -11
  94. package/dist/form/array-binding.js +184 -166
  95. package/dist/form/choice-ids.d.ts +7 -0
  96. package/dist/form/choice-ids.js +11 -0
  97. package/dist/form/choices-controller.d.ts +3 -2
  98. package/dist/form/choices-controller.js +302 -275
  99. package/dist/form/date-format.d.ts +38 -0
  100. package/dist/form/date-format.js +89 -0
  101. package/dist/form/dirty-values.d.ts +2 -2
  102. package/dist/form/dirty-values.js +22 -11
  103. package/dist/form/duration.d.ts +22 -0
  104. package/dist/form/duration.js +49 -0
  105. package/dist/form/edit-create-form.d.ts +12 -5
  106. package/dist/form/edit-create-form.js +243 -188
  107. package/dist/form/event-value.d.ts +6 -0
  108. package/dist/form/event-value.js +17 -0
  109. package/dist/form/field-error.d.ts +14 -0
  110. package/dist/form/field-error.js +28 -0
  111. package/dist/form/field-name.d.ts +20 -0
  112. package/dist/form/field-name.js +6 -0
  113. package/dist/form/filter-form-values.js +63 -49
  114. package/dist/form/form-controller.d.ts +9 -1
  115. package/dist/form/form-controller.js +165 -160
  116. package/dist/form/form-groups.d.ts +4 -3
  117. package/dist/form/form-groups.js +79 -79
  118. package/dist/form/form-handle.d.ts +175 -0
  119. package/dist/form/form-handle.js +68 -0
  120. package/dist/form/input-binding.d.ts +56 -31
  121. package/dist/form/input-binding.js +169 -118
  122. package/dist/form/input-values.d.ts +130 -0
  123. package/dist/form/input-values.js +177 -0
  124. package/dist/form/json-text.js +51 -37
  125. package/dist/form/save-pipeline.d.ts +6 -8
  126. package/dist/form/save-pipeline.js +91 -82
  127. package/dist/form/set-form-values.d.ts +6 -0
  128. package/dist/form/set-form-values.js +10 -0
  129. package/dist/form/source.js +97 -65
  130. package/dist/form/text-of.d.ts +2 -0
  131. package/dist/form/text-of.js +7 -0
  132. package/dist/form/validators.d.ts +58 -19
  133. package/dist/form/validators.js +97 -71
  134. package/dist/geo/bbox.d.ts +5 -4
  135. package/dist/geo/bbox.js +69 -48
  136. package/dist/geo/bounds.d.ts +14 -3
  137. package/dist/geo/bounds.js +98 -68
  138. package/dist/geo/constraints.js +88 -93
  139. package/dist/geo/coordinates.js +31 -23
  140. package/dist/geo/editor.d.ts +13 -13
  141. package/dist/geo/editor.js +176 -153
  142. package/dist/geo/geocoding.d.ts +4 -4
  143. package/dist/geo/geocoding.js +38 -41
  144. package/dist/geo/geojson.d.ts +12 -74
  145. package/dist/geo/geojson.js +52 -40
  146. package/dist/geo/geometry-math.d.ts +4 -4
  147. package/dist/geo/geometry-math.js +100 -93
  148. package/dist/geo/index.d.ts +7 -6
  149. package/dist/geo/map-layers.d.ts +42 -7
  150. package/dist/geo/map-layers.js +88 -62
  151. package/dist/geo/map-style.js +31 -32
  152. package/dist/geo/messages.js +48 -45
  153. package/dist/geo/nominatim.js +88 -80
  154. package/dist/geo/osm-presets.d.ts +4 -3
  155. package/dist/geo/osm-presets.js +108 -86
  156. package/dist/geo/osm-tags.js +14 -12
  157. package/dist/geo/overpass.d.ts +14 -2
  158. package/dist/geo/overpass.js +83 -90
  159. package/dist/geo/shape-value.d.ts +9 -5
  160. package/dist/geo/shape-value.js +169 -146
  161. package/dist/geo/snap-to-roads.d.ts +3 -3
  162. package/dist/geo/snap-to-roads.js +55 -50
  163. package/dist/geo/throttle.js +36 -39
  164. package/dist/guards.d.ts +37 -0
  165. package/dist/guards.js +62 -0
  166. package/dist/i18n/default-messages.js +34 -29
  167. package/dist/i18n/english-messages.js +187 -189
  168. package/dist/i18n/i18n.d.ts +2 -2
  169. package/dist/i18n/i18n.js +47 -60
  170. package/dist/i18n/inflection.d.ts +34 -0
  171. package/dist/i18n/inflection.js +82 -0
  172. package/dist/i18n/messages.d.ts +10 -2
  173. package/dist/i18n/messages.js +17 -4
  174. package/dist/i18n/missing-keys.js +66 -62
  175. package/dist/i18n/translatable.d.ts +16 -1
  176. package/dist/i18n/translatable.js +40 -47
  177. package/dist/index.d.ts +71 -24
  178. package/dist/index.js +40 -288
  179. package/dist/json/deep-equal.d.ts +8 -0
  180. package/dist/json/deep-equal.js +24 -0
  181. package/dist/json/strip-json-comments.js +38 -42
  182. package/dist/noop.d.ts +2 -0
  183. package/dist/noop.js +4 -0
  184. package/dist/notification/error-message.d.ts +2 -0
  185. package/dist/notification/error-message.js +10 -0
  186. package/dist/notification/notification-store.d.ts +3 -2
  187. package/dist/notification/notification-store.js +41 -45
  188. package/dist/onboarding-tour/placement.js +63 -78
  189. package/dist/onboarding-tour/tour-controller.js +46 -54
  190. package/dist/realtime/add-events-for-mutations.js +75 -81
  191. package/dist/realtime/announce-lock.js +16 -13
  192. package/dist/realtime/broadcast-channel-transport.js +65 -59
  193. package/dist/realtime/copy-members.js +22 -14
  194. package/dist/realtime/in-memory-lock-provider.js +40 -48
  195. package/dist/realtime/live.js +95 -101
  196. package/dist/realtime/lock-options.js +16 -16
  197. package/dist/realtime/lock-session.js +91 -78
  198. package/dist/realtime/memory-transport.js +25 -25
  199. package/dist/realtime/presence.js +120 -122
  200. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  201. package/dist/realtime/realtime-data-provider.js +45 -42
  202. package/dist/realtime/reconnect-backoff.js +17 -0
  203. package/dist/realtime/sse-transport.d.ts +31 -0
  204. package/dist/realtime/sse-transport.js +235 -0
  205. package/dist/realtime/status-store.js +23 -28
  206. package/dist/realtime/topic-hub.js +62 -71
  207. package/dist/realtime/topics.js +10 -12
  208. package/dist/realtime/types.js +10 -12
  209. package/dist/realtime/unread-count.js +21 -21
  210. package/dist/realtime/websocket-transport.d.ts +32 -0
  211. package/dist/realtime/websocket-transport.js +306 -0
  212. package/dist/resource/describe-resource.d.ts +2 -0
  213. package/dist/resource/describe-resource.js +232 -219
  214. package/dist/resource/get-at-path.js +29 -14
  215. package/dist/resource/identifier.d.ts +18 -0
  216. package/dist/resource/identifier.js +27 -0
  217. package/dist/resource/record.d.ts +4 -0
  218. package/dist/resource/record.js +10 -0
  219. package/dist/resource/register.d.ts +7 -0
  220. package/dist/resource/registry-store.d.ts +45 -15
  221. package/dist/resource/registry-store.js +67 -60
  222. package/dist/resource/registry.d.ts +10 -0
  223. package/dist/resource/registry.js +8 -4
  224. package/dist/resource/source-path.d.ts +16 -1
  225. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  226. package/dist/rich-text/rich-text-extras.js +179 -0
  227. package/dist/rich-text/rich-text-image.d.ts +124 -0
  228. package/dist/rich-text/rich-text-image.js +163 -0
  229. package/dist/rich-text/rich-text.d.ts +6 -0
  230. package/dist/rich-text/rich-text.js +125 -88
  231. package/dist/router/location.d.ts +22 -4
  232. package/dist/router/location.js +41 -18
  233. package/dist/router/match.js +47 -39
  234. package/dist/router/paths.js +40 -34
  235. package/dist/router/record-from-location.d.ts +1 -1
  236. package/dist/router/record-from-location.js +25 -17
  237. package/dist/store/adapters.js +51 -55
  238. package/dist/store/micro-store.js +57 -59
  239. package/dist/store/shallow-equal.d.ts +12 -0
  240. package/dist/store/shallow-equal.js +20 -0
  241. package/dist/store/store.js +54 -57
  242. 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 };