@object-ui/plugin-map 17.5.0 → 17.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,291 @@
1
1
  # @object-ui/plugin-map
2
2
 
3
+ ## 17.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0a73b51: `ObjectView` and `ListView` now flatten a view's `map` block through a
8
+ whitelist instead of spreading the whole (untyped) block to the top level.
9
+
10
+ Both `case 'map'` flatteners used to build the `object-map` schema with
11
+ `...(options.map || {})` — a raw spread of an untyped bag
12
+ (`NamedListView.options?: Record<string, any>`), so any key an author wrote in
13
+ the `map` block reached the top level unfiltered. `ObjectMap`'s own
14
+ `FlatMapConfigKeys = Omit<ObjectMapConfig, 'style'>` declares `style` OUT of
15
+ this flat form (`style` is also `BaseSchema.style`, inline CSS legal on every
16
+ node), so the two disagreed about the same shape. `style` was the live
17
+ specimen: `map: { style: '<url>' }` reached the top level as a CSS-shaped
18
+ `style` key it was never supposed to carry.
19
+
20
+ Behavior narrowing, stated because it changes what reaches the flattened
21
+ schema: a `map` block key that is not one of `ObjectMapConfig`'s declared
22
+ flat keys (`latitudeField` / `longitudeField` / `locationField` / `titleField`
23
+ / `descriptionField` / `zoom` / `center`) — including `style` — no longer
24
+ reaches the top level of the flattened `object-map` schema. This closes a gap
25
+ rather than removing working behavior: the pinned strict spec view schemas
26
+ accept no `map` block at all today, so no author-facing surface could reach
27
+ this path, and `ObjectMap` already stopped reading a top-level `style` as a
28
+ map style (a dev warning names the correct spelling instead).
29
+
30
+ The whitelist is DERIVED from `ObjectMapConfigSchema` (`@object-ui/types/zod`)
31
+ rather than hand-listed, so the flatteners and the declaration cannot drift
32
+ apart again — a key added to (or removed from) the schema reaches both
33
+ flatteners without a second edit. `ObjectMap`'s own `FLAT_MAP_CONFIG_KEYS` is
34
+ derived from the same schema for the same reason.
35
+ - 578e025: `ObjectMapSchema` declares what ObjectMap reads, and the `map` block outranks the flat spelling
36
+
37
+ `object-map` carried three disagreeing shapes for one component. The declared face
38
+ (`ObjectMapSchema`) had four keys — `type`, `objectName`, `locationField`,
39
+ `titleField`, `mapStyle`. The renderer read about fifteen. And `ObjectMapProps.schema`
40
+ was typed `ObjectGridSchema`, so every map-specific read went through
41
+ `(schema as any)`. A TypeScript author could not write the `map` block the docs teach,
42
+ and misspelling `latitudeField` as `latitudeFieId` was caught by nothing: the map
43
+ rendered empty and looked like bad data.
44
+
45
+ Declared now, each with a read site in `ObjectMap.tsx`: `data`, `staticData`, `filter`,
46
+ `sort`, `map`, `enableClustering`, `navigation`. `ObjectMapConfig` (interface) and
47
+ `ObjectMapConfigSchema` (zod) are lifted out of `plugin-map`, where the zod was
48
+ package-private and called `MapConfigSchema`, into `@object-ui/types` and
49
+ `@object-ui/types/zod` — so the declared authoring face and the validation the renderer
50
+ performs are one schema rather than two that can drift. The `Object` prefix is not
51
+ decoration: `@objectstack/spec/automation` already exports `MapConfigSchema` for an
52
+ unrelated concept, and a local declaration under a spec export's name is what
53
+ `check:spec-symbols` exists to refuse. `ObjectMapProps.schema` is `ObjectMapSchema`, and the `as any` map reads
54
+ are gone.
55
+
56
+ Behavior change, ruled by the maintainer on objectui#5018 (2026-08-17): the `map` block
57
+ is the author face and the flat top-level spelling (`schema.latitudeField`, …) is the
58
+ internal form ObjectView / ListView produce when they flatten `options.map`. When a
59
+ schema carries both, **the `map` block now wins** — the reverse of the previous order,
60
+ under which the flatten product silently shadowed an authored block — and a dev-mode
61
+ warning names the top-level keys that were ignored. The flat spelling stays out of the
62
+ declared surface and out of the docs.
63
+
64
+ Nothing changes for views built by ObjectView / ListView: both flatteners emit the flat
65
+ keys and no `map` key at all, so the branch the flip reorders is never reached for their
66
+ output. That property is now pinned rather than assumed
67
+ (`plugin-view/src/__tests__/ObjectView.mapFlatten.test.tsx`).
68
+
69
+ Bound worth stating, because it limits what the typed surface can promise: `BaseSchema`
70
+ carries an index signature (`[key: string]: any`), so a misspelled key at the TOP level
71
+ still type-checks — for every component schema in the repo. The `map` BLOCK is closed,
72
+ which is what makes the card's headline typo a compile error.
73
+
74
+ ### Patch Changes
75
+
76
+ - 5edc0c5: `object-gantt` / `object-map` / `object-calendar` no longer drop a sort entry that omits `order`.
77
+
78
+ The three blocks each inlined a byte-identical private copy of the `sort` →
79
+ `$orderby` conversion. That copy required BOTH `field` and `order` on an array
80
+ entry and silently skipped any entry missing one, so a stored view sorting by
81
+ `[{ field: 'amount' }]` reached the wire with no ordering at all — the authored
82
+ sort key was lost, not applied. The same copy already treated the STRING
83
+ spelling `"amount"` as ascending, so this was an inconsistency between two
84
+ spellings of one thing rather than deliberate strictness.
85
+
86
+ All three now import the shared `convertSortToQueryParams` sink from
87
+ `@object-ui/core` (introduced by objectstack#7137, already used by
88
+ `object-timeline` and `record:line_items`), and the private copies are gone —
89
+ the sink is the repo's only definition. Two behavior changes come with it, both
90
+ of which make the blocks more faithful to what is already declared rather than
91
+ more tolerant:
92
+
93
+ - An array entry that omits `order` now orders ASCENDING instead of vanishing.
94
+ That is what `QueryParams.$orderby`'s own member shape
95
+ (`{ field: string; order?: 'asc' | 'desc' }`) says, and what
96
+ `@object-ui/data-objectstack`'s `serializeOrderBy` already did with a missing
97
+ direction.
98
+ - When nothing orderable was authored, the query now carries no `$orderby` at
99
+ all instead of an empty object. `{}` is truthy and meant "no ordering" only by
100
+ accident of the adapter's serializer.
101
+
102
+ Reachability, so the size of this is not overstated: `SortConfig.order` and
103
+ `ElementDataSourceSort.order` are REQUIRED in objectui's own types, so a typed
104
+ caller could never author the dropped shape. The affected surface is untyped
105
+ stored view metadata (`ElementSavedView` is a loose record by design) — which is
106
+ exactly where an order-less entry can arrive today.
107
+ - 25819c4: A map view now fits its camera to the records it queried, so a view with data never first-paints an empty viewport.
108
+
109
+ The initial camera was never derived from the data. The zoom came from
110
+ `getMapConfig`'s default branch — the branch reached precisely when the author
111
+ declared nothing — which synthesized `zoom: 10` at the origin, and the fabricated
112
+ value was indistinguishable from a declared one at the read site. An unconfigured
113
+ object list view of continent-wide records therefore opened on a ~30km-wide
114
+ viewport centred on the set's midpoint: no markers anywhere on screen, the
115
+ records reachable only by zooming out and panning by hand (objectui#4941, seen on
116
+ the showcase `task` map view, whose ten seeded US-city locations span ~4000km).
117
+
118
+ The camera is now the marker set's bounding box, handed to MapLibre as
119
+ `initialViewState.bounds` so the fit happens against the real container size,
120
+ with padding and a city-scale zoom ceiling (a single record, or several at one
121
+ address, fits a zero-width box — unbounded, that answers with a rooftop view of a
122
+ style whose tiles stop far short of it).
123
+
124
+ The box is measured along the **shortest arc** containing every marker, not
125
+ between the naive longitude extremes. Read as a line rather than a circle, two
126
+ records two degrees apart across the antimeridian (179 and -179) describe a
127
+ 358-degree box whose centre is their antipode; MapLibre then places the markers in
128
+ whichever copy of the world is nearest their previous screen position, which is
129
+ how a fitted-looking camera ends up showing empty ocean with the records sitting
130
+ on a neighbouring copy.
131
+
132
+ Unchanged on purpose: record coordinates are not rescued. The platform's
133
+ `location` value bounds longitude to [-180, 180], so an out-of-range coordinate is
134
+ a producer-side defect — such records keep being rejected and counted in the
135
+ view's "invalid coordinates" notice, and the normalization above is camera
136
+ arithmetic over already-valid values. No new configuration key was added either:
137
+ the documented `zoom` / `center` pair of the `map` block is still the only camera
138
+ declaration, it still wins outright, and declaring one half keeps the other
139
+ derived (`zoom` alone applies at the records' centre; `center` alone at a
140
+ continental zoom). An empty result set is not fitted — it opens on the whole
141
+ world rather than a zoom-10 patch of sea.
142
+ - 072085d: A map node's top-level `style` is inline CSS again, not a MapLibre style URL.
143
+
144
+ `ObjectMap.getMapConfig` resolved the map style from three spellings with the
145
+ top-level `style` FIRST — `schema.style || schema.mapStyle || schema.map?.style`
146
+ — but `style` is `BaseSchema.style`, a record of inline CSS properties that
147
+ every schema node may legally carry. Writing the base face's own
148
+ `style: { height: '400px' }` on a map node therefore handed that object to
149
+ MapGL's `mapStyle` prop: it never passed the config `safeParse` (which only ever
150
+ looked at `schema.map`), so there was no validation and no diagnostic either.
151
+
152
+ `@object-ui/types` had already named the map's key `mapStyle` — explicitly "not
153
+ `style`, to avoid colliding with `BaseSchema.style`" — so the consumer was
154
+ reading, at top priority, the very name the declaration went out of its way to
155
+ avoid. The declaration is now what is enforced: the map style comes from
156
+ `mapStyle` on the schema or `style` inside the declared `map` block, and a
157
+ top-level `style` is not consumed as a map style in any shape.
158
+
159
+ Behaviour change, stated because it is one: a map configured through a top-level
160
+ `style` URL now renders with the default public demo tiles. That spelling was
161
+ never documented (the README teaches `map.style`) and no metadata in this repo
162
+ used it, but it was runtime-reachable one way — `ObjectView` / `ListView`
163
+ flatten `options.map`'s CONTENTS to the top level, so a view authored with
164
+ `map: { style: '<url>' }` arrived here as a top-level string. That shape is not
165
+ spec-authorable (`@objectstack/spec`'s list-view schemas are strict and declare
166
+ no `map` block at all, so such a view fails validation outright), and it now
167
+ gets a dev warning naming both surviving spellings rather than silently painting
168
+ the demo tiles. The object form gets no warning: legal base-face authoring, and
169
+ dropping it is the fix.
170
+ - 687bc0c: Fix two pieces of `ObjectMap` state that stopped tracking their source after mount
171
+ (objectui#5003):
172
+
173
+ - **`data` prop threading**: the fetch effect preferred records passed via `props.data`,
174
+ but `data` was read off the `rest` spread and was not one of the effect's dependencies.
175
+ A host rendering `<ObjectMap data={[]} .../>` while its own query is in flight, then
176
+ re-rendering with the resolved rows, kept showing the empty map — the prop changed, the
177
+ effect never re-ran to notice. `data` is now a declared prop (`data: dataProp`), tracked
178
+ directly in the effect's dependency array; the whole `rest` object is intentionally
179
+ **not** added there (it is a fresh object every render, which would refetch on every
180
+ render instead).
181
+ - **Clustering zoom seed**: `currentZoom` — what `clusterMarkers` uses for its grid cell
182
+ size — was seeded with a nominal `mapConfig.zoom || 3` and updated only by `onZoom`.
183
+ MapLibre applies the initial camera (including a `bounds` fit) via its constructor,
184
+ before react-map-gl attaches React's event handlers, so no `onZoom` ever fired for that
185
+ first camera — the seed stayed nominal until the user's first zoom. It is now also
186
+ seeded from `onLoad`, which fires once the initial camera has settled, so clustering at
187
+ first paint reflects the camera MapLibre actually applied.
188
+
189
+ Both were dormant on the console path (never exercised in the example apps) — see the
190
+ issue for why — so this ships with dedicated tests exercising the prop-update path and
191
+ the pre-`onZoom` clustering state directly.
192
+ - 084155e: Fix the two remaining `object/api/value` claims that objectui#5019 (PR #5162) left
193
+ behind — its dispatch was scoped to only the "API Provider" section of
194
+ `content/docs/plugins/plugin-map.mdx`, so the same false claim survived in the Features
195
+ list and in the `ObjectMap.tsx` file-header JSDoc:
196
+
197
+ - `content/docs/plugins/plugin-map.mdx:24` (Features list): "Works seamlessly with
198
+ object/api/value data providers" → "Works seamlessly with object/value data providers".
199
+ - `packages/plugin-map/src/ObjectMap.tsx:20` (file-header JSDoc): "Works with
200
+ object/api/value data providers" → "Works with object/value data providers".
201
+
202
+ `provider: 'api'` still hits `console.warn('API provider not yet implemented for
203
+ ObjectMap')` and returns an empty record set (`ObjectMap.tsx:584`); `endpoint`/`method`
204
+ have no read point in the package. Implementing the `api` provider is capability
205
+ expansion and is explicitly out of scope here, same as it was for #5019.
206
+
207
+ No runtime behaviour changes — a source comment and a docs line only.
208
+ - Updated dependencies [88085e3]
209
+ - Updated dependencies [516663d]
210
+ - Updated dependencies [460c4d0]
211
+ - Updated dependencies [0ae27f7]
212
+ - Updated dependencies [2533ec5]
213
+ - Updated dependencies [78c0f9a]
214
+ - Updated dependencies [bbe8b86]
215
+ - Updated dependencies [8477be5]
216
+ - Updated dependencies [279fb13]
217
+ - Updated dependencies [2e82ab2]
218
+ - Updated dependencies [ad07b65]
219
+ - Updated dependencies [41f498b]
220
+ - Updated dependencies [e1d4251]
221
+ - Updated dependencies [40d3a33]
222
+ - Updated dependencies [8b9dc62]
223
+ - Updated dependencies [1184192]
224
+ - Updated dependencies [a2a9747]
225
+ - Updated dependencies [a1609a6]
226
+ - Updated dependencies [53f23bc]
227
+ - Updated dependencies [c4533dc]
228
+ - Updated dependencies [be60815]
229
+ - Updated dependencies [37f6844]
230
+ - Updated dependencies [93de4f6]
231
+ - Updated dependencies [2b50261]
232
+ - Updated dependencies [384f30d]
233
+ - Updated dependencies [ac600e5]
234
+ - Updated dependencies [97fba31]
235
+ - Updated dependencies [232f61a]
236
+ - Updated dependencies [d374caf]
237
+ - Updated dependencies [5673576]
238
+ - Updated dependencies [c1ef923]
239
+ - Updated dependencies [911ceaa]
240
+ - Updated dependencies [98eab36]
241
+ - Updated dependencies [af5e292]
242
+ - Updated dependencies [3fbbea1]
243
+ - Updated dependencies [7f96b10]
244
+ - Updated dependencies [167ec42]
245
+ - Updated dependencies [616a2a5]
246
+ - Updated dependencies [0046d8f]
247
+ - Updated dependencies [f1d4748]
248
+ - Updated dependencies [b1119ec]
249
+ - Updated dependencies [9f23d2b]
250
+ - Updated dependencies [578e025]
251
+ - Updated dependencies [af025ee]
252
+ - Updated dependencies [598c89a]
253
+ - Updated dependencies [4a0bd17]
254
+ - Updated dependencies [b8b9af4]
255
+ - Updated dependencies [31676be]
256
+ - Updated dependencies [8c0d52e]
257
+ - Updated dependencies [aff10e2]
258
+ - Updated dependencies [70a774b]
259
+ - Updated dependencies [9ce096f]
260
+ - Updated dependencies [e05db88]
261
+ - Updated dependencies [7458a41]
262
+ - Updated dependencies [5ffcc14]
263
+ - Updated dependencies [d971e51]
264
+ - Updated dependencies [97abb24]
265
+ - Updated dependencies [deb157a]
266
+ - Updated dependencies [d2ce342]
267
+ - Updated dependencies [9695da7]
268
+ - Updated dependencies [75444e3]
269
+ - Updated dependencies [58b8346]
270
+ - Updated dependencies [2d0bd16]
271
+ - Updated dependencies [dad51e5]
272
+ - Updated dependencies [1c9c342]
273
+ - Updated dependencies [787c738]
274
+ - Updated dependencies [8396656]
275
+ - Updated dependencies [dbbd38a]
276
+ - Updated dependencies [93fe362]
277
+ - Updated dependencies [dfc6975]
278
+ - Updated dependencies [3cf4de0]
279
+ - Updated dependencies [c9dc811]
280
+ - Updated dependencies [144ef9b]
281
+ - Updated dependencies [138ab04]
282
+ - Updated dependencies [a0b9e91]
283
+ - Updated dependencies [99bd015]
284
+ - @object-ui/types@17.6.0
285
+ - @object-ui/react@17.6.0
286
+ - @object-ui/components@17.6.0
287
+ - @object-ui/core@17.6.0
288
+
3
289
  ## 17.5.0
4
290
 
5
291
  ### Patch Changes