@object-ui/plugin-map 17.5.0 → 17.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.
package/README.md CHANGED
@@ -1,15 +1,28 @@
1
1
  # @object-ui/plugin-map
2
2
 
3
- Map visualization plugin for Object UI - Display geographic data with interactive maps.
4
-
5
- ## Features
6
-
7
- - **Interactive Maps** - Zoomable, pannable map visualization
8
- - **Markers** - Add markers with custom icons and popups
9
- - **Layers** - Multiple map layers support
10
- - **Geolocation** - User location detection
11
- - **Customizable** - Tailwind CSS styling support
12
- - **Responsive** - Mobile-friendly map controls
3
+ Map view plugin for Object UI.
4
+
5
+ Renders the records of an **ObjectQL query** as markers on a MapLibre map: every
6
+ marker comes from a record's own coordinate fields, and the first paint frames the
7
+ records that were fetched. It is a *view over data* — there is no authored marker
8
+ list, and no pin you place by hand.
9
+
10
+ Importing the package registers one component type on the `ComponentRegistry`:
11
+ `object-map`, the object-bound renderer. Inside an `ObjectView`, a stored `map`
12
+ view is compiled to an `object-map` node, so a saved map view ends at the same
13
+ component.
14
+
15
+ > **The bare `map` node type key is retired** (objectui#10393, following the
16
+ > objectui#8008 ruling that retired `gantt`). The registry used to accept a node
17
+ > authored `"type": "map"` (and its namespaced twin `view:map`) while the
18
+ > published declaration refused it — `ObjectMapSchema.type` is the literal
19
+ > `'object-map'` and no schema arm names `map` — so a validated document could not
20
+ > use the key the registry took. Write `"type": "object-map"`.
21
+ >
22
+ > ⚠️ The **stored view type** `"map"` — what a saved `listViews[].type` or
23
+ > `defaultViewType` holds — is a **different layer and is unchanged**. Do not
24
+ > rewrite it: `ObjectView` maps a stored `map` view onto the `object-map` node
25
+ > type, so no saved view moves.
13
26
 
14
27
  ## Installation
15
28
 
@@ -17,263 +30,246 @@ Map visualization plugin for Object UI - Display geographic data with interactiv
17
30
  pnpm add @object-ui/plugin-map
18
31
  ```
19
32
 
20
- ## Usage
21
-
22
- ### Automatic Registration (Side-Effect Import)
23
-
24
- ```typescript
25
- // In your app entry point (e.g., App.tsx or main.tsx)
26
- import '@object-ui/plugin-map';
27
-
28
- // Now you can use map types in your schemas
29
- const schema = {
30
- type: 'map',
31
- center: { lat: 37.7749, lng: -122.4194 },
32
- zoom: 12,
33
- markers: [
34
- { lat: 37.7749, lng: -122.4194, label: 'San Francisco' }
35
- ]
36
- };
37
- ```
38
-
39
- ### Manual Registration
33
+ ## Requires a bundler — plain Node cannot import this package
40
34
 
41
- ```typescript
42
- import { mapComponents } from '@object-ui/plugin-map';
43
- import { ComponentRegistry } from '@object-ui/core';
35
+ `ObjectMap` imports MapLibre's stylesheet at module scope
36
+ (`import 'maplibre-gl/dist/maplibre-gl.css'`), and Node has no loader for `.css` at all.
37
+ Importing the published entry from plain Node ESM — no bundler, no loader hooks — therefore
38
+ resolves and then fails during evaluation:
44
39
 
45
- // Register map components
46
- Object.entries(mapComponents).forEach(([type, component]) => {
47
- ComponentRegistry.register(type, component);
48
- });
40
+ ```text
41
+ TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".css"
42
+ for .../maplibre-gl/dist/maplibre-gl.css
49
43
  ```
50
44
 
51
- ## Schema API
45
+ **This is a supported-configuration statement, not a bug to report.** Unbundled Node
46
+ consumption is not supported for style-carrying plugin packages. It was ruled that way on
47
+ [objectui#5384](https://github.com/objectstack-ai/objectui/issues/5384) — deliberately, over
48
+ the alternative of moving the stylesheet out of module scope — because a MapLibre canvas
49
+ without its stylesheet is not a map, and no unbundled-Node consumer exists to serve.
52
50
 
53
- ### Map
51
+ Consume it through a host that handles CSS imports, which every supported host does: Vite,
52
+ webpack, or Next with the package listed in `transpilePackages`. If you have a real need to
53
+ import it under plain Node — SSR with no bundler, a Node-side script — please open an issue.
54
+ That reopens the question as a design decision rather than a defect, and the shape of your
55
+ consumer is the missing input.
54
56
 
55
- Display an interactive map:
57
+ ## Usage
56
58
 
57
- ```typescript
58
- {
59
- type: 'map',
60
- center: { lat: number, lng: number },
61
- zoom?: number, // Default: 10
62
- markers?: MapMarker[],
63
- layers?: MapLayer[],
64
- height?: number | string,
65
- onMarkerClick?: (marker) => void,
66
- className?: string
67
- }
68
- ```
59
+ Registration is a side effect of the import. There is no manual-registration
60
+ export to iterate over — the import *is* the registration.
69
61
 
70
- ### Map Marker
71
-
72
- ```typescript
73
- interface MapMarker {
74
- lat: number;
75
- lng: number;
76
- label?: string;
77
- icon?: string; // Icon URL or name
78
- popup?: string | ReactNode;
79
- color?: string; // Marker color
80
- }
81
- ```
62
+ An authored `object-map` node takes its props in its `properties` bag, whose
63
+ members are `@objectstack/spec`'s `ComponentPropsMap['object-map']` row.
64
+ `objectui validate` refuses a prop written flat on the node by name, naming its
65
+ bag member, as the spec's own page component does (objectui#10859).
66
+ `SchemaRenderer` hoists the bag onto the node before `ObjectMap` runs, so
67
+ `ObjectMapSchema` (`@object-ui/types`) is the node as the component reads it.
82
68
 
83
- ## Examples
84
-
85
- ### Basic Map
86
-
87
- ```typescript
88
- const schema = {
89
- type: 'map',
90
- center: { lat: 40.7128, lng: -74.0060 },
91
- zoom: 13,
92
- height: 500,
93
- markers: [
94
- {
95
- lat: 40.7128,
96
- lng: -74.0060,
97
- label: 'New York City',
98
- popup: 'The Big Apple'
99
- }
100
- ]
101
- };
102
- ```
69
+ ```ts
70
+ import '@object-ui/plugin-map';
71
+ import type { ObjectMapBlockNode } from '@object-ui/types';
103
72
 
104
- ### Multiple Markers
105
-
106
- ```typescript
107
- const schema = {
108
- type: 'map',
109
- center: { lat: 37.7749, lng: -122.4194 },
110
- zoom: 10,
111
- markers: [
112
- {
113
- lat: 37.7749,
114
- lng: -122.4194,
115
- label: 'San Francisco',
116
- color: 'red',
117
- popup: 'Golden Gate Bridge'
118
- },
119
- {
120
- lat: 37.8044,
121
- lng: -122.2712,
122
- label: 'Oakland',
123
- color: 'blue',
124
- popup: 'Port of Oakland'
73
+ // Object-bound: the markers are the records the query returns.
74
+ const schema: ObjectMapBlockNode = {
75
+ type: 'object-map',
76
+ properties: {
77
+ objectName: 'stores',
78
+ map: {
79
+ latitudeField: 'lat',
80
+ longitudeField: 'lng',
81
+ titleField: 'name',
82
+ descriptionField: 'address',
125
83
  },
126
- {
127
- lat: 37.3382,
128
- lng: -121.8863,
129
- label: 'San Jose',
130
- color: 'green',
131
- popup: 'Silicon Valley'
132
- }
133
- ]
134
- };
135
- ```
136
-
137
- ### Interactive Map
138
-
139
- ```typescript
140
- const schema = {
141
- type: 'map',
142
- center: { lat: 51.5074, lng: -0.1278 },
143
- zoom: 12,
144
- markers: [/* markers */],
145
- onMarkerClick: (marker) => {
146
- console.log('Marker clicked:', marker);
147
- // Show marker details
148
84
  },
149
- onMapClick: (coordinates) => {
150
- console.log('Map clicked at:', coordinates);
151
- // Add new marker
152
- }
153
- };
154
- ```
155
-
156
- ### Map with Data Binding
157
-
158
- ```typescript
159
- const schema = {
160
- type: 'map',
161
- center: { lat: 37.7749, lng: -122.4194 },
162
- zoom: 10,
163
- markers: '${data.locations.map(loc => ({ lat: loc.latitude, lng: loc.longitude, label: loc.name }))}',
164
- onMarkerClick: (marker) => {
165
- // Handle marker click
166
- }
167
85
  };
168
86
  ```
169
87
 
170
- ## Integration with ObjectQL
88
+ A literal record array instead of a query, with the same `map` block:
171
89
 
172
- Connect map to ObjectStack data sources:
90
+ ```ts
91
+ import type { ObjectMapBlockNode } from '@object-ui/types';
173
92
 
174
- ```typescript
175
- import { createObjectStackAdapter } from '@object-ui/data-objectstack';
176
-
177
- const dataSource = createObjectStackAdapter({
178
- baseUrl: 'https://api.example.com',
179
- token: 'your-auth-token'
180
- });
181
-
182
- const schema = {
93
+ const schema: ObjectMapBlockNode = {
183
94
  type: 'object-map',
184
- dataSource,
185
- object: 'locations',
186
- latField: 'latitude',
187
- lngField: 'longitude',
188
- labelField: 'name',
189
- popupField: 'description',
190
- center: { lat: 37.7749, lng: -122.4194 },
191
- zoom: 10
192
- };
193
- ```
194
-
195
- ## Map Features
196
-
197
- ### Custom Markers
198
-
199
- ```typescript
200
- const schema = {
201
- type: 'map',
202
- markers: [
203
- {
204
- lat: 40.7128,
205
- lng: -74.0060,
206
- icon: '/custom-marker.png',
207
- popup: {
208
- type: 'card',
209
- title: 'Location Details',
210
- body: 'Custom popup content'
211
- }
212
- }
213
- ]
214
- };
215
- ```
216
-
217
- ### Geolocation
218
-
219
- ```typescript
220
- const schema = {
221
- type: 'map',
222
- useGeolocation: true, // Center map on user's location
223
- zoom: 15,
224
- markers: []
225
- };
226
- ```
227
-
228
- ### Map Layers
229
-
230
- ```typescript
231
- const schema = {
232
- type: 'map',
233
- center: { lat: 37.7749, lng: -122.4194 },
234
- layers: [
235
- { type: 'heatmap', data: [/* heatmap data */] },
236
- { type: 'polygon', coordinates: [/* polygon coordinates */], color: 'rgba(255, 0, 0, 0.3)' }
237
- ]
95
+ properties: {
96
+ staticData: [
97
+ { id: 1, name: 'San Francisco HQ', lat: 37.7749, lng: -122.4194 },
98
+ { id: 2, name: 'Oakland Office', lat: 37.8044, lng: -122.2711 },
99
+ ],
100
+ map: { latitudeField: 'lat', longitudeField: 'lng', titleField: 'name' },
101
+ },
238
102
  };
239
103
  ```
240
104
 
241
- ## TypeScript Support
242
-
243
- ```typescript
244
- import type { MapSchema, MapMarker } from '@object-ui/plugin-map';
245
-
246
- const marker: MapMarker = {
247
- lat: 37.7749,
248
- lng: -122.4194,
249
- label: 'San Francisco',
250
- color: 'red'
251
- };
252
-
253
- const map: MapSchema = {
254
- type: 'map',
255
- center: { lat: 37.7749, lng: -122.4194 },
256
- zoom: 12,
257
- markers: [marker]
258
- };
105
+ `filter` and `sort` are the **query's** filter and order — they reach the data
106
+ source as `$filter` / `$orderby`, and the spec's per-element `dataSource` binding
107
+ is honoured as well.
108
+
109
+ **The provider does not change which query keys apply** (objectui#9061, the port
110
+ of objectui#8769). An authored `filter` and `sort` narrow and order the rows on
111
+ **every** provider, inline ones included — `staticData` and
112
+ `data: { provider: 'value', items }` both reach the same in-memory adapter the
113
+ other providers go through, so `filter` is evaluated with the same matcher. A
114
+ bare array under `data` is not a record source on this map (objectui#8348): the
115
+ ladder falls through to `staticData`, then `objectName`, so inline rows belong
116
+ under `staticData`. Before objectui#9061 the inline provider skipped that query
117
+ and plotted every authored row with an authored `filter` silently dropped. The
118
+ platform row ceiling (2,000 drawn rows, with a footnote naming both numbers — objectui#7210,
119
+ ruling a′) applies to inline rows too, and it is applied to the **filtered** set,
120
+ never to the raw one: a large inline array that a `filter` cuts below the ceiling
121
+ plots every matching row and shows no footnote.
122
+
123
+ ⚠️ Two consequences of routing inline rows through the adapter. They reach the
124
+ map as that adapter's own deep copy rather than as the authored array's object
125
+ identities, so code comparing a record handed to `onMarkerClick` against the
126
+ authored array with `===` needs `id` equality instead; and the copy is a JSON
127
+ round-trip, so inline rows must be JSON-serializable.
128
+
129
+ ## The `map` block
130
+
131
+ The declared configuration input. Every key is optional, and the block is
132
+ **closed** (objectui#5157): a key outside this table — a typo such as
133
+ `latitudeFieId` — is refused by `objectui validate` with an `unrecognized_keys`
134
+ issue at `properties.map` that names it (on a root node; a nested node reports under
135
+ `invalid_union` at `children`, with the key in the arm detail). At runtime
136
+ `ObjectMap` does not throw: it renders from the declared keys and warns
137
+ `[ObjectMap] Invalid map configuration` in the console, naming the same key; the
138
+ undeclared key is never read. A typo that leaves the block with no coordinate
139
+ binding, as `latitudeFieId` does, therefore draws the "Map configuration
140
+ required" refusal below rather than a map.
141
+
142
+ | Key | Description |
143
+ | --- | --- |
144
+ | `latitudeField` | Record field holding the latitude. Needs `longitudeField` alongside it; both values must be numbers. |
145
+ | `longitudeField` | Record field holding the longitude. |
146
+ | `locationField` | Single field holding both coordinates — see the formats below. Used when the lat/lng pair yields nothing. |
147
+ | `titleField` | Field shown as the marker title. Omitted, the title is resolved by the object's own record-title precedence (`@object-ui/core`'s `getRecordDisplayName`, ADR-0079): the declared `nameField`, its deprecated `displayNameField` alias, the legacy `titleFormat` template, a type-aware pick from the object's fields, then name-ish keys read straight off the record — the rung that answers when no object definition reached the view, as `staticData` and an inline `data: { provider: 'value', items }` configuration never fetch one. `Record #<id>` is the floor; `Marker` is reached only by a record carrying no id at all. |
148
+ | `descriptionField` | Field shown under the title in the marker popup. |
149
+ | `zoom` | Zoom level. Declaring it opts this view out of the auto-fit (see below). |
150
+ | `center` | `[latitude, longitude]` — a two-number **tuple**, latitude first. Declaring it opts this view out of the auto-fit. |
151
+ | `style` | MapLibre style URL/spec, replacing the default public demo style. The node-level `mapStyle` is read before it, so it applies when `mapStyle` is absent. |
152
+
153
+ **Nothing is guessed — an unbound map REFUSES.** A map with no coordinate binding
154
+ renders
155
+
156
+ > Map configuration required — declare `map.locationField` or `map.latitudeField` + `map.longitudeField`
157
+
158
+ in place of the map, rather than painting an empty one (objectui#8169, ruled
159
+ 2026-09-07). *Unbound* is a property of the resolved config, not of the spelling
160
+ that produced it — an absent `map` block, a block naming only `titleField`, and a
161
+ `latitudeField` with no `longitudeField` beside it all refuse alike.
162
+
163
+ The four field-name defaults this component used to fall back to — `latitude` /
164
+ `longitude` / `location` / `description` — are gone, and so are the
165
+ `locationField: … || 'location'` floors that `plugin-list` and `plugin-view` used
166
+ to add on the way in. ⚠️ **Behaviour change for existing metadata**: a record set
167
+ that happens to carry `latitude` / `longitude` columns no longer plots on a view
168
+ that declared no binding — it refuses, and the fix is to declare the binding.
169
+ A title field is still never guessed (objectui#5953): an unconfigured marker
170
+ takes its title from the record-title precedence above.
171
+
172
+ ## Node-level keys beside the block
173
+
174
+ | Key | Description |
175
+ | --- | --- |
176
+ | `mapStyle` | MapLibre style URL or spec, replacing the demo tiles. Read before `map.style`, so it wins when both are written. Not the node's base `style`, which is an inline CSS record. |
177
+ | `enableClustering` | `true` groups nearby markers into numbered clusters. Absent, the map clusters only above 100 markers; `false` turns clustering off at any count. |
178
+ | `navigation` | What a marker click opens — the spec's `NavigationConfig`. `drawer`, `modal` and `popover` open the marker's record; `new_window` (or `openNewTab: true`, which outranks every mode except `none`) opens the record page in a new tab; `preventNavigation: true` opens nothing. An absent key, `none` and `split` open nothing (the map hands the split shell no main panel). `page`, and a block without `mode` (the spec's `page` default), open the record page of the map's `objectName` through the record navigator the host publishes (the console publishes one on its custom pages, record pages and list views); under a host that publishes none, or on a map that names no `objectName`, the click opens nothing. A parent view's click handler outranks the whole key. |
179
+
180
+ ## Initial camera
181
+
182
+ There is no default zoom and no default centre. With records to show and no
183
+ camera declared, the map **fits the records**: their bounding box, measured along
184
+ the shortest arc that contains them (so a set straddling the antimeridian is
185
+ framed across the line, not around the far side of the planet), with 48px of
186
+ padding and a city-scale zoom ceiling of 12 — a single record does not become a
187
+ rooftop view.
188
+
189
+ Two cases sit outside the fit:
190
+
191
+ - **Nothing placeable** (empty result, or no record yielding coordinates): the
192
+ whole world, centred on `0, 0`.
193
+ - **A declared camera**: `zoom` or `center` in the `map` block wins and the fit is
194
+ skipped. Declaring one half keeps the other derived — `zoom` alone is applied at
195
+ the centre of the records, `center` alone at a continental zoom.
196
+
197
+ A `center` that is not a two-number tuple (the `{ lat, lng }` object form, say) is
198
+ rejected by the config schema, warned about in the console, and **not** adapted —
199
+ and it does not cost the view its fit.
200
+
201
+ ## Coordinate formats
202
+
203
+ `locationField` names one record field, and the value in it is read at RUNTIME:
204
+ `extractCoordinates()` in `packages/plugin-map/src/ObjectMap.tsx` tests the value's
205
+ shape per record and takes the first of these three that answers. So this is a
206
+ reference read of what that parser accepts, not a value you author — which is why
207
+ it is a table rather than a snippet:
208
+
209
+ | Shape of `record[locationField]` | Example value | What the parser accepts |
210
+ | --- | --- | --- |
211
+ | Object | `{ lat: 37.7749, lng: -122.4194 }` | `lat` or `latitude` for the latitude; `lng`, `lon` or `longitude` for the longitude. Both must already be numbers — an object form is not string-parsed. |
212
+ | String | `'37.7749,-122.4194'` | `"lat,lng"`: split on the comma, each half trimmed and `parseFloat`-ed. |
213
+ | Array | `[37.7749, -122.4194]` | `[lat, lng]`, exactly two elements, each `parseFloat`-ed. |
214
+
215
+ The lat/lng PAIR (`latitudeField` + `longitudeField`) is tried first and is
216
+ stricter: both values must already be numbers, with no parsing step at all.
217
+
218
+ A record whose coordinates are missing, unparseable, or out of range (latitude
219
+ beyond ±90, longitude beyond ±180) is left off the map and counted in a notice
220
+ above it, rather than being silently dropped or rescued. The range test and the
221
+ notice live in that same file, alongside the parser.
222
+
223
+ ## What this component does not read
224
+
225
+ Keys that look plausible on a map schema but have no read site here: `markers`
226
+ (markers are records), `layers`, `height` (the container is a fixed responsive
227
+ height, 300px through 600px), `useGeolocation` (the map carries a
228
+ user-initiated "show my location" button instead), and per-marker `icon` /
229
+ `color` / `popup` styling. A `map` configuration stashed under `filter.map` — a
230
+ shape predating the `map` input — is no longer read either, and says so in the
231
+ console.
232
+
233
+ ## Using `ObjectMap` directly
234
+
235
+ `ObjectMap` (the component), `ObjectMapRenderer` (the registered wrapper, for a
236
+ host that registers types itself) and the `ObjectMapProps` type are the package's
237
+ exports. A component mounted directly is not behind `SchemaRenderer`, so nothing
238
+ hoists a `properties` bag: its `schema` prop takes the node as the component
239
+ reads it, with the keys flat:
240
+
241
+ ```tsx
242
+ import { ObjectMap, type ObjectMapProps } from '@object-ui/plugin-map';
243
+
244
+ declare const dataSource: ObjectMapProps['dataSource'];
245
+
246
+ <ObjectMap
247
+ schema={{ type: 'object-map', objectName: 'stores', map: { latitudeField: 'lat', longitudeField: 'lng' } }}
248
+ dataSource={dataSource}
249
+ onMarkerClick={(record) => console.log(record)}
250
+ />;
259
251
  ```
260
252
 
261
- ## Customization
262
-
263
- Style the map with Tailwind classes:
264
-
265
- ```typescript
266
- const schema = {
267
- type: 'map',
268
- className: 'rounded-lg shadow-xl border-2 border-gray-200',
269
- height: '600px',
270
- center: { lat: 37.7749, lng: -122.4194 }
271
- };
272
- ```
253
+ | Prop | Description |
254
+ | --- | --- |
255
+ | `schema` | The map schema — the keys above. |
256
+ | `dataSource` | Resolves the `object` provider. Not needed for `staticData` or an inline `data: { provider: 'value', items }` configuration. |
257
+ | `className` | Classes for the wrapper around the map. |
258
+ | `data` | Records to render directly, bypassing the component's own fetch — the shape `ListView` passes when it already holds the rows. Tracked live: passing a new array after mount (e.g. once a host's own in-flight query resolves) updates the map. |
259
+ | `onMarkerClick` | Called with the clicked record. |
260
+ | `onRowClick` | Record click handler; takes priority over the `navigation` overlay. |
261
+ | `onEdit` / `onDelete` | Passing either adds that button to the marker popup (and to the mobile record sheet). |
262
+ | `enableClustering` | Forces clustering on; without it, clustering starts above 100 visible markers. |
263
+ | `clusterRadius` | Clustering granularity (default `50`): the grid cell is `clusterRadius / 2 ** zoom`, so a larger value groups more aggressively. |
264
+
265
+ In a schema-driven page these handlers may equally be authored on the node
266
+ itself: `SchemaRenderer` spreads a node's non-metadata properties onto the
267
+ component.
273
268
 
274
269
  ## Links
275
270
 
276
- - 📚 [Documentation](https://www.objectui.org/docs/plugins/plugin-map)
271
+ - 📚 [Documentation](https://www.objectui.org/docs/plugins/plugin-map) — the full
272
+ authoring reference for the schema and the `map` block
277
273
  - 📦 [npm package](https://www.npmjs.com/package/@object-ui/plugin-map)
278
274
  - 📝 [Changelog](./CHANGELOG.md)
279
275
  - 🐛 [Report an issue](https://github.com/objectstack-ai/objectui/issues)
@@ -1,16 +1,45 @@
1
1
  import { default as React } from 'react';
2
- import { ObjectGridSchema, DataSource } from '@object-ui/types';
2
+ import { ObjectMapSchema, DataSource } from '@object-ui/types';
3
3
  export interface ObjectMapProps {
4
- schema: ObjectGridSchema;
4
+ schema: ObjectMapSchema;
5
5
  dataSource?: DataSource;
6
6
  className?: string;
7
+ /**
8
+ * Records to render directly, bypassing this component's own fetch — the
9
+ * shape `ListView` passes when it already holds the rows. Declared as its
10
+ * own prop (not read off the `rest` spread) so the fetch effect can depend
11
+ * on this one value: naming the whole `rest` object in that effect's deps
12
+ * instead would refetch on every render, since `rest` is a fresh object
13
+ * each render (objectui#5003).
14
+ */
15
+ data?: any[];
7
16
  onMarkerClick?: (record: any) => void;
8
- onRowClick?: (record: any) => void;
17
+ /**
18
+ * TWO parameters since objectui#9357, and the second is not decoration: this
19
+ * prop reaches `useNavigationOverlay` as its `onRowClick`, and `handleClick`
20
+ * invokes it as `onRowClick(record, event)` — the modifier payload a host
21
+ * needs to implement Cmd/Ctrl/middle-click for itself. Declaring one
22
+ * parameter hid the second on the ONE line a host reads. Spelled `any` and
23
+ * not `HandleClickModifiers` for the reason objectui#9341 measured on
24
+ * `ObjectKanbanSchema.onCardClick`: that interface lives in
25
+ * `@object-ui/react`, the published twins in `@object-ui/types` may not name
26
+ * it, and a host that discovered the payload from the implementation
27
+ * annotated it `React.MouseEvent` — which a narrower declaration refuses
28
+ * contravariantly. `BaseSchema`'s own `onClick` / `onChange` / `onSubmit`
29
+ * already use this spelling for exactly this situation.
30
+ */
31
+ onRowClick?: (record: any, event?: any) => void;
9
32
  onEdit?: (record: any) => void;
10
33
  onDelete?: (record: any) => void;
11
34
  /** Enable marker clustering for dense data */
12
35
  enableClustering?: boolean;
13
- /** Cluster radius in pixels (default: 50) */
36
+ /**
37
+ * Clustering grid granularity (default: 50). NOT screen pixels — the grid
38
+ * cell edge is `clusterRadius / 2 ** zoom`, in coordinate DEGREES (the
39
+ * marker's `[lng, lat]`), so a larger value groups more aggressively and
40
+ * the effective granularity shrinks exponentially as zoom increases. See
41
+ * `clusterMarkers` below.
42
+ */
14
43
  clusterRadius?: number;
15
44
  }
16
45
  export declare const ObjectMap: React.FC<ObjectMapProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectMap.d.ts","sourceRoot":"","sources":["../src/ObjectMap.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAY,MAAM,kBAAkB,CAAC;AAO/E,OAAO,kCAAkC,CAAC;AAqB1C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACjC,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA+SD,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA4d9C,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ObjectMap.d.ts","sourceRoot":"","sources":["../src/ObjectMap.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAmB,UAAU,EAAY,MAAM,kBAAkB,CAAC;AA0B/F,OAAO,kCAAkC,CAAC;AAkB1C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACtC;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACjC,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAqfD,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAq6B9C,CAAC;AAEF,eAAe,SAAS,CAAC"}