@georeferencing/react 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +400 -2
- package/dist/Georeferencer.d.ts +71 -0
- package/dist/Georeferencer.js +220 -0
- package/dist/components/accuracy.d.ts +15 -0
- package/dist/components/accuracy.js +39 -0
- package/dist/components/exports.d.ts +32 -0
- package/dist/components/exports.js +152 -0
- package/dist/components/fields.d.ts +17 -0
- package/dist/components/fields.js +35 -0
- package/dist/controls.d.ts +40 -0
- package/dist/controls.js +28 -0
- package/dist/hooks/useGeoreferencer.d.ts +6 -0
- package/dist/hooks/useGeoreferencer.js +8 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +16 -0
- package/dist/licenses/APACHE-2.0.txt +202 -0
- package/dist/licenses/GDAL-NOTICE.txt +24 -0
- package/dist/licenses/inventory.json +1 -0
- package/dist/localization.d.ts +6 -0
- package/dist/localization.js +1 -0
- package/dist/panels/AlignmentPanel.d.ts +19 -0
- package/dist/panels/AlignmentPanel.js +27 -0
- package/dist/panels/FeaturePanel.d.ts +28 -0
- package/dist/panels/FeaturePanel.js +43 -0
- package/dist/panels/GcpPanel.d.ts +35 -0
- package/dist/panels/GcpPanel.js +81 -0
- package/dist/panels/ImagePanel.d.ts +30 -0
- package/dist/panels/ImagePanel.js +279 -0
- package/dist/panels/PreviewControls.d.ts +17 -0
- package/dist/panels/PreviewControls.js +37 -0
- package/dist/panels/ReferencePanel.d.ts +17 -0
- package/dist/panels/ReferencePanel.js +24 -0
- package/dist/styles.css +594 -0
- package/dist/utils/downloadBlob.d.ts +5 -0
- package/dist/utils/downloadBlob.js +11 -0
- package/package.json +57 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TobiLG <github@tobilg.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,401 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @georeferencing/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React 19 components and hooks for georeferencing local images on an existing
|
|
4
|
+
OpenLayers map. This package provides the ready-made editor, composable panels,
|
|
5
|
+
subscription hook, unsaved-work dialog and scoped styles.
|
|
6
|
+
|
|
7
|
+
The authoritative session and processing engine live in
|
|
8
|
+
[`@georeferencing/core`](https://github.com/tobilg/georeferencing/tree/main/packages/core).
|
|
9
|
+
Optional exports come from
|
|
10
|
+
[`@georeferencing/plugins`](https://github.com/tobilg/georeferencing/tree/main/packages/plugins).
|
|
11
|
+
React has no runtime dependency on plugins or pdf-lib: it displays formats
|
|
12
|
+
configured on the controller.
|
|
13
|
+
|
|
14
|
+
## Installation and compatibility
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pnpm add @georeferencing/core @georeferencing/react react@19 react-dom@19 ol@10
|
|
18
|
+
# Optional output formats:
|
|
19
|
+
pnpm add @georeferencing/plugins
|
|
20
|
+
# TypeScript React applications also need the React declarations:
|
|
21
|
+
pnpm add -D @types/react@19 @types/react-dom@19
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Verified peer ranges are React/React DOM `>=19.3.0 <20` and OpenLayers
|
|
25
|
+
`>=10.10.0 <11`. The host owns these libraries and its map. Packages ship ESM and
|
|
26
|
+
TypeDoc-bearing TypeScript declarations. Node.js 22.12+ is the declared tooling
|
|
27
|
+
requirement; the repository uses pnpm 12.x.
|
|
28
|
+
|
|
29
|
+
Importing the package is SSR-safe. Create maps and start browser processing only
|
|
30
|
+
on the client.
|
|
31
|
+
|
|
32
|
+
**Install the same version of `@georeferencing/react`, `@georeferencing/core` and
|
|
33
|
+
`@georeferencing/plugins`**, and upgrade them together. React depends on core and
|
|
34
|
+
re-exports its controller; a mismatched version can install a second copy of core
|
|
35
|
+
with a separate projection registry. See
|
|
36
|
+
[keep package versions aligned](https://georeferencing-api-docs.gh.tobilg.com/Getting_started/#keep-package-versions-aligned).
|
|
37
|
+
|
|
38
|
+
## Integrate with a host-owned map
|
|
39
|
+
|
|
40
|
+
The map must already have a visible target, dimensions and initialized view. Make
|
|
41
|
+
one stable controller/engine per session, and inject your real save service.
|
|
42
|
+
This example needs no export plugin and sends geographic features to the host.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import type { ControllerOptions } from "@georeferencing/core";
|
|
46
|
+
import { GeoreferencerController } from "@georeferencing/core";
|
|
47
|
+
import { createWorkerEngine } from "@georeferencing/core/engine";
|
|
48
|
+
import { Georeferencer } from "@georeferencing/react";
|
|
49
|
+
import type OLMap from "ol/Map.js";
|
|
50
|
+
import "ol/ol.css";
|
|
51
|
+
import "@georeferencing/react/styles.css";
|
|
52
|
+
|
|
53
|
+
export function createEditorSession(
|
|
54
|
+
workingCrs: string,
|
|
55
|
+
persistFeatures: NonNullable<ControllerOptions["onSave"]>,
|
|
56
|
+
persistDraft?: ControllerOptions["onSaveDraft"],
|
|
57
|
+
) {
|
|
58
|
+
const engine = createWorkerEngine();
|
|
59
|
+
const controller = new GeoreferencerController({
|
|
60
|
+
workingCrs,
|
|
61
|
+
engine,
|
|
62
|
+
digitizing: true,
|
|
63
|
+
onSave: persistFeatures,
|
|
64
|
+
onSaveDraft: persistDraft,
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
controller,
|
|
68
|
+
dispose() {
|
|
69
|
+
controller.dispose();
|
|
70
|
+
engine.dispose();
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function ImageEditor({
|
|
76
|
+
map,
|
|
77
|
+
session,
|
|
78
|
+
}: {
|
|
79
|
+
map: OLMap;
|
|
80
|
+
session: ReturnType<typeof createEditorSession>;
|
|
81
|
+
}) {
|
|
82
|
+
return <Georeferencer controller={session.controller} referenceMap={map} />;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The host calls `createEditorSession` once, for example when opening an editor,
|
|
87
|
+
and retains it across renders. Render `ImageEditor` only after the host map exists.
|
|
88
|
+
On permanent close, resolve unsaved work, unmount the editor, then dispose the
|
|
89
|
+
session. A temporary detach/remount must retain the same controller.
|
|
90
|
+
|
|
91
|
+
With Vite, use ES module workers:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
export default { worker: { format: "es" } };
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The stylesheet is optional. It uses `rg-` classes; the host controls map layout
|
|
98
|
+
and dimensions. Core's engine and each optional codec support explicit worker
|
|
99
|
+
URLs/factories for deployments that do not preserve default bundled asset paths.
|
|
100
|
+
|
|
101
|
+
## Ready-made editor props
|
|
102
|
+
|
|
103
|
+
| Prop | Contract |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `controller` | Required stable authoritative session controller |
|
|
106
|
+
| `referenceMap` | Required initialized, host-owned OpenLayers map |
|
|
107
|
+
| `bindingOptions` | Stable reference providers, projections, snapping and optional initial map framing |
|
|
108
|
+
| `t` | Translate default English text, including configured format labels |
|
|
109
|
+
| `formatError` | Format structured errors by code/message/operation ID |
|
|
110
|
+
| `className` | Additional editor root class |
|
|
111
|
+
| `propertyEditor` | Host feature-property form; update replacement JSON properties |
|
|
112
|
+
| `onExport` | Receive any configured format's artifacts instead of automatic downloads |
|
|
113
|
+
|
|
114
|
+
Memoize `bindingOptions` or construct it outside rendering. Changing its identity
|
|
115
|
+
reattaches the binding. The ready-made component owns its attachment; do not also
|
|
116
|
+
call `attachReferenceMap` for the same controller and map.
|
|
117
|
+
|
|
118
|
+
## Select exports on demand
|
|
119
|
+
|
|
120
|
+
No format is enabled implicitly. Configure the controller at creation or replace
|
|
121
|
+
its registry at runtime:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import type { GeoreferencerController } from "@georeferencing/core";
|
|
125
|
+
import { geoTiff } from "@georeferencing/plugins/geotiff";
|
|
126
|
+
import { jpeg } from "@georeferencing/plugins/jpeg";
|
|
127
|
+
import { pdf, type ReportMap } from "@georeferencing/plugins/pdf";
|
|
128
|
+
|
|
129
|
+
export function enableExports(
|
|
130
|
+
controller: GeoreferencerController,
|
|
131
|
+
currentMap: () => ReportMap | undefined,
|
|
132
|
+
) {
|
|
133
|
+
controller.setExportFormats([
|
|
134
|
+
geoTiff(),
|
|
135
|
+
jpeg({ quality: 0.92 }),
|
|
136
|
+
pdf({ map: currentMap }),
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The UI shows only these actions. `setExportFormats` replaces the registry and
|
|
142
|
+
cancels active export work. Import a subset to exclude unused implementations
|
|
143
|
+
from the browser bundle; heavy format code loads on request.
|
|
144
|
+
|
|
145
|
+
The default UI downloads every artifact. `onExport(result)` can handle them in
|
|
146
|
+
host code; inspect `result.format`, `result.document` and each `{ name, blob }`
|
|
147
|
+
in `result.files`. JPEG and world-file exports include required CRS/placement
|
|
148
|
+
sidecars. Export completion never acknowledges host persistence. See the
|
|
149
|
+
[plugins README](https://github.com/tobilg/georeferencing/blob/main/packages/plugins/README.md)
|
|
150
|
+
for format settings, cancellation and limits.
|
|
151
|
+
|
|
152
|
+
## Guided four-step layout
|
|
153
|
+
|
|
154
|
+
Supply `referenceView` to `Georeferencer` to use the guided layout. It is a React
|
|
155
|
+
node containing the host's map target and optional map controls; the host still
|
|
156
|
+
owns the map and must attach its target before editor effects run (a React
|
|
157
|
+
callback ref is suitable). Without this prop, the classic workbench with every
|
|
158
|
+
control remains. See the
|
|
159
|
+
[complete demo host](https://github.com/tobilg/georeferencing/blob/main/packages/demo/main.tsx)
|
|
160
|
+
for a typed integration with target attachment and cleanup.
|
|
161
|
+
|
|
162
|
+
The guided layout leads users through four steps, each with one main action in a
|
|
163
|
+
sticky bar:
|
|
164
|
+
|
|
165
|
+
1. **Load image**: drop zone with **Choose image** and any `emptyImageActions`
|
|
166
|
+
(for example a sample-image button).
|
|
167
|
+
2. **Match points**: click a spot in the image, then the same spot on the map.
|
|
168
|
+
Progress shows how many points the model needs; **Run alignment** fits them.
|
|
169
|
+
3. **Check alignment**: the overlay on the map, a plain-language accuracy summary
|
|
170
|
+
(average residual in image pixels, or a hint to add a point when the fit is
|
|
171
|
+
exact) and the point list. **Adjust points** goes back; **Looks good, continue**
|
|
172
|
+
confirms the alignment.
|
|
173
|
+
4. **Export or draw**: download buttons for the configured formats and, with
|
|
174
|
+
`digitizing`, drawing tools and **Save features**. **Back to check** returns.
|
|
175
|
+
|
|
176
|
+
Completed steps in the step bar are clickable. Desktop keeps both views side by
|
|
177
|
+
side; below 720 px, Image/Map buttons switch panes and follow pending points.
|
|
178
|
+
In both views, dragging pans and scrolling zooms; a click without dragging places
|
|
179
|
+
a point.
|
|
180
|
+
|
|
181
|
+
OpenLayers' `Map` creates its default interactions with `onFocusOnly: true`. If
|
|
182
|
+
the map target has a `tabindex` (for keyboard navigation), mouse panning and wheel
|
|
183
|
+
zoom then only work after the map has focus. Create the host map with
|
|
184
|
+
`interactions: defaults({ onFocusOnly: false })` from `ol/interaction/defaults.js`,
|
|
185
|
+
as the demo does, so both work immediately.
|
|
186
|
+
|
|
187
|
+
### Choose the controls
|
|
188
|
+
|
|
189
|
+
The guided layout starts minimal. Add expert controls individually with
|
|
190
|
+
`controls`; omitted flags fall back to `MINIMAL_CONTROLS`:
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { ALL_CONTROLS, Georeferencer } from "@georeferencing/react";
|
|
194
|
+
|
|
195
|
+
<Georeferencer
|
|
196
|
+
controller={controller}
|
|
197
|
+
referenceMap={map}
|
|
198
|
+
referenceView={mapView}
|
|
199
|
+
controls={{ transformation: true, outputSettings: true }}
|
|
200
|
+
/>;
|
|
201
|
+
// Every control: controls={ALL_CONTROLS}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Flag | Default | Adds |
|
|
205
|
+
| --- | --- | --- |
|
|
206
|
+
| `history` | on | Undo and redo |
|
|
207
|
+
| `previewMode` | off | Manual/automatic preview selector (otherwise the controller's `previewMode` applies) |
|
|
208
|
+
| `transformation` | off | Transformation model selector while matching |
|
|
209
|
+
| `pointTable` | off | Full point table with editable coordinates, CRS and residuals (otherwise a compact list) |
|
|
210
|
+
| `manualEntry` | off | Add a point pair by typing coordinates, the keyboard alternative to clicking |
|
|
211
|
+
| `navigation` | off | Previous/next image and map views, linked navigation |
|
|
212
|
+
| `displayAdjustment` | off | Brightness, contrast and histogram stretch |
|
|
213
|
+
| `referenceStatus` | off | Load status of reference providers |
|
|
214
|
+
| `outputSettings` | off | Raster output CRS, resampling, compression, no-data, pixel size and bounds |
|
|
215
|
+
| `sessionFiles` | off | Restore session, import `.points`, save draft and early session downloads |
|
|
216
|
+
| `unsavedIndicator` | off | Unsaved-changes indicator |
|
|
217
|
+
|
|
218
|
+
Enable `manualEntry` when keyboard-only point entry is required.
|
|
219
|
+
|
|
220
|
+
### Preview policy and panels
|
|
221
|
+
|
|
222
|
+
`previewMode: "manual"` on the controller waits for **Run alignment**;
|
|
223
|
+
`"automatic"` updates eligible previews after committed edits without advancing
|
|
224
|
+
the user's step. Worker validation reports singular or unusable arrangements when
|
|
225
|
+
a run is requested.
|
|
226
|
+
|
|
227
|
+
The composable panels keep every control by default and accept the same opt-outs:
|
|
228
|
+
`GcpPanel` takes `variant` (`"table"` or `"compact"`), `manualEntry` and `tools`;
|
|
229
|
+
`ImagePanel` takes `navigation`, `displayAdjustment` and `emptyActions`;
|
|
230
|
+
`PreviewControls` takes `modeSelector` and calls `onReview` only for a successful
|
|
231
|
+
preview matching the requested revision. `AlignmentPanel` accepts
|
|
232
|
+
`controls={false}` when transformation and preview controls are rendered
|
|
233
|
+
elsewhere. These panels never take map or engine ownership.
|
|
234
|
+
|
|
235
|
+
## References, projections and snapping
|
|
236
|
+
|
|
237
|
+
Pass core's `BindingOptions` as `bindingOptions`. Providers include bounded
|
|
238
|
+
viewport WFS, static GeoJSON, custom abortable loaders and borrowed vector layers.
|
|
239
|
+
A borrowed layer retains its host loading and ownership. Reference errors and
|
|
240
|
+
partial results appear in the UI without disabling manual target entry.
|
|
241
|
+
|
|
242
|
+
Configure real endpoint/type names, request/response CRSs and axis conventions.
|
|
243
|
+
Preserve AbortSignal when injecting authentication. Query bounds limit reference
|
|
244
|
+
loading; `initialView` only frames the map. Neither georeferences the image.
|
|
245
|
+
Drawing bounds and raster bounds are independent.
|
|
246
|
+
|
|
247
|
+
Register the same custom projection definitions and NTv2 grids with the engine
|
|
248
|
+
and binding. Image GCPs use original-resolution, orientation-normalized pixels;
|
|
249
|
+
feature drafts/save payloads use longitude/latitude regardless of the map view.
|
|
250
|
+
Supplying provider `snapping` opts into GCP snapping. Drawing snapping is separately
|
|
251
|
+
controlled by `digitizingSnapping.references` and `.drafts`. The
|
|
252
|
+
[reference guide](https://github.com/tobilg/georeferencing/blob/main/packages/documentation/guides/reference-data.md)
|
|
253
|
+
contains typed provider examples.
|
|
254
|
+
|
|
255
|
+
## Image lifecycle, confirmation and saving
|
|
256
|
+
|
|
257
|
+
The image picker and drop zone use controller lifecycle methods. Selection supports
|
|
258
|
+
files up to 25 MiB, subject to decoded-pixel and memory budgets. Replacing/removing
|
|
259
|
+
an image invokes the ready-made Save/Discard/Cancel dialog when needed, cancels
|
|
260
|
+
old processing and preserves the host map view. Original bytes stay outside the
|
|
261
|
+
serializable document. Restoring a JSON session requires the matching source file.
|
|
262
|
+
|
|
263
|
+
Digitizing is opt-in through `digitizing: true`. A valid current alignment must be
|
|
264
|
+
explicitly confirmed before drawing multiple points, lines or polygons. Features
|
|
265
|
+
can be modified, deleted and undone/redone. Returning to alignment leaves them
|
|
266
|
+
geographically anchored; subsequent alignment changes require confirmation and
|
|
267
|
+
explicit feature review before saving accepted features again.
|
|
268
|
+
|
|
269
|
+
`onChange` mirrors draft state. `onSave` receives an immutable accepted-feature
|
|
270
|
+
envelope with stable IDs, source fingerprint, alignment and provenance.
|
|
271
|
+
`onSaveDraft` can persist unfinished sessions separately. A save callback resolves
|
|
272
|
+
after actual storage success and rejects on failure; a failed draft remains
|
|
273
|
+
retryable. Older save completion does not acknowledge newer edits. Feature saving
|
|
274
|
+
never requires raster export. Hosts must separately persist source bytes and
|
|
275
|
+
protect route/window closure; the image-transition dialog is not a general router
|
|
276
|
+
or browser-close guard.
|
|
277
|
+
|
|
278
|
+
## React Strict Mode and ownership
|
|
279
|
+
|
|
280
|
+
The editor resumes the controller during setup and suspends it during cleanup.
|
|
281
|
+
It adds/removes only package-owned map layers/interactions. It does not dispose
|
|
282
|
+
the host map, borrowed layers, controller or engine on unmount. This permits
|
|
283
|
+
React 19 Strict Mode setup/cleanup cycles and later remounts.
|
|
284
|
+
|
|
285
|
+
Use permanent `dispose()` only after the host has finished with the session;
|
|
286
|
+
do not put it in an effect cleanup that Strict Mode uses for temporary teardown.
|
|
287
|
+
Host interactions remain host-owned. Use `onActiveToolChange` in controller options
|
|
288
|
+
to coordinate conflicting host drawing tools explicitly. Pending host saves are
|
|
289
|
+
revision-safe but are not cancelled by UI suspension.
|
|
290
|
+
|
|
291
|
+
## Compose a custom UI
|
|
292
|
+
|
|
293
|
+
| Export | Purpose |
|
|
294
|
+
| --- | --- |
|
|
295
|
+
| `Georeferencer` | Complete editor, map attachment, guard dialog and output controls |
|
|
296
|
+
| `useGeoreferencer(controller)` | Subscribe to the authoritative snapshot |
|
|
297
|
+
| `ImagePanel` | Image selection, image view and image-side GCP interaction |
|
|
298
|
+
| `GcpPanel` | Paired-point table, numeric editing and diagnostics |
|
|
299
|
+
| `PreviewControls` | Manual/automatic preview policy, readiness and explicit run/review |
|
|
300
|
+
| `AlignmentPanel` | Transformation selection, confirmation and alignment controls |
|
|
301
|
+
| `ReferencePanel` | Reference loading/error/incomplete-result feedback |
|
|
302
|
+
| `FeaturePanel` | Drawing tools, features/properties, review and save controls |
|
|
303
|
+
|
|
304
|
+
Composable panels do not install a map binding or unsaved-work dialog. Supply a
|
|
305
|
+
controller with a host `guard`, attach the map once and manage suspension yourself:
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
import type { GeoreferencerController } from "@georeferencing/core";
|
|
309
|
+
import { attachReferenceMap, type BindingOptions } from "@georeferencing/core/openlayers";
|
|
310
|
+
import {
|
|
311
|
+
AlignmentPanel, FeaturePanel, GcpPanel, ImagePanel,
|
|
312
|
+
ReferencePanel, useGeoreferencer,
|
|
313
|
+
} from "@georeferencing/react";
|
|
314
|
+
import type OLMap from "ol/Map.js";
|
|
315
|
+
import { useEffect } from "react";
|
|
316
|
+
|
|
317
|
+
export function CustomEditor({ map, controller, options }: {
|
|
318
|
+
map: OLMap;
|
|
319
|
+
controller: GeoreferencerController;
|
|
320
|
+
options: BindingOptions;
|
|
321
|
+
}) {
|
|
322
|
+
const state = useGeoreferencer(controller);
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
controller.start();
|
|
325
|
+
const binding = attachReferenceMap(map, controller, options);
|
|
326
|
+
return () => {
|
|
327
|
+
binding.detach();
|
|
328
|
+
controller.suspend();
|
|
329
|
+
};
|
|
330
|
+
}, [map, controller, options]);
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<div className="rg-editor">
|
|
334
|
+
<ImagePanel controller={controller} />
|
|
335
|
+
<GcpPanel controller={controller} />
|
|
336
|
+
<AlignmentPanel controller={controller} />
|
|
337
|
+
<ReferencePanel controller={controller} />
|
|
338
|
+
<FeaturePanel controller={controller} />
|
|
339
|
+
<p role="status">{state.error ?? `Document revision ${state.document.documentRevision}`}</p>
|
|
340
|
+
</div>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Custom layouts provide their own export/session actions through controller APIs.
|
|
346
|
+
Keep the `options` object stable. Omitting a headless guard safely cancels dirty
|
|
347
|
+
image transitions instead of silently discarding them.
|
|
348
|
+
|
|
349
|
+
## Localization and property forms
|
|
350
|
+
|
|
351
|
+
Use `t` for UI messages and `formatError` for structured dynamic errors. Business
|
|
352
|
+
properties remain host-defined JSON. Never mutate the frozen feature passed to
|
|
353
|
+
a property renderer; call its update callback with replacement properties.
|
|
354
|
+
|
|
355
|
+
```tsx
|
|
356
|
+
import type { GeoreferencerProps } from "@georeferencing/react";
|
|
357
|
+
|
|
358
|
+
export const propertyEditor: GeoreferencerProps["propertyEditor"] = (feature, update) => (
|
|
359
|
+
<label>
|
|
360
|
+
Name
|
|
361
|
+
<input
|
|
362
|
+
value={String(feature.properties.name ?? "")}
|
|
363
|
+
onChange={(event) => update({ ...feature.properties, name: event.target.value })}
|
|
364
|
+
/>
|
|
365
|
+
</label>
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
export const translate: NonNullable<GeoreferencerProps["t"]> = (message) => {
|
|
369
|
+
const messages: Record<string, string> = { "Choose image": "Bild auswählen" };
|
|
370
|
+
return messages[message] ?? message;
|
|
371
|
+
};
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Pass these functions as props to `Georeferencer`, or to the relevant composable
|
|
375
|
+
panels. The package includes focusable map/image controls, labeled inputs and
|
|
376
|
+
status feedback; hosts remain responsible for accessible custom property editors,
|
|
377
|
+
layout, translations and their application's overall keyboard behavior.
|
|
378
|
+
|
|
379
|
+
## Source organization
|
|
380
|
+
|
|
381
|
+
`src/index.ts` defines the public exports. The editor lives in `Georeferencer.tsx`,
|
|
382
|
+
composable panels in `panels/`, the subscription hook in `hooks/`, shared fields
|
|
383
|
+
in `components/`, and download handling in `utils/`. Translation types/defaults
|
|
384
|
+
live in `localization.ts`. These internal modules preserve the public API; consumers
|
|
385
|
+
continue importing from `@georeferencing/react` and its `styles.css` entry.
|
|
386
|
+
|
|
387
|
+
## Troubleshooting and license
|
|
388
|
+
|
|
389
|
+
`@georeferencing/react` exposes `.` and `/styles.css`. Declarations carry TypeDoc
|
|
390
|
+
comments for editor help; the same comments are published as the
|
|
391
|
+
[API documentation](https://georeferencing-api-docs.gh.tobilg.com). Source, issues and contribution notes are in the
|
|
392
|
+
[GitHub repository](https://github.com/tobilg/georeferencing). MIT licensed.
|
|
393
|
+
|
|
394
|
+
| Symptom | Check |
|
|
395
|
+
| --- | --- |
|
|
396
|
+
| Blank map or missing overlay | Host map target/size, valid current fit and overlay visibility |
|
|
397
|
+
| Repeated reference loads / lost map interaction state | Stable controller, map and memoized binding options |
|
|
398
|
+
| Duplicate editor layers/interactions | Only one attachment per controller/map; avoid manual binding alongside `Georeferencer` |
|
|
399
|
+
| Drawing/save controls unavailable | Opt-in digitizing, valid confirmation, feature review and configured save handler |
|
|
400
|
+
| Export controls absent | Register the desired optional plugins |
|
|
401
|
+
| Worker or map-capture error | Worker URLs/CSP, supported browser APIs and CORS-safe map layers |
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { ExportResult, GeoreferencerController } from "@georeferencing/core";
|
|
2
|
+
import type { BindingOptions } from "@georeferencing/core/openlayers";
|
|
3
|
+
import type OLMap from "ol/Map.js";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import type { GeoreferencerControls } from "./controls.js";
|
|
6
|
+
import type { Translate } from "./localization.js";
|
|
7
|
+
import { FeaturePanel } from "./panels/FeaturePanel.js";
|
|
8
|
+
/**
|
|
9
|
+
* Integration props for the ready-made editor. Keep controller, map and binding
|
|
10
|
+
* configuration stable across React renders.
|
|
11
|
+
*/
|
|
12
|
+
export interface GeoreferencerProps {
|
|
13
|
+
/**
|
|
14
|
+
* Opt into the guided four-step layout (load, match, check, export/draw) by supplying
|
|
15
|
+
* the host map's rendered target and controls. The host still creates, targets and
|
|
16
|
+
* disposes the map. This slot stays mounted across all steps and responsive
|
|
17
|
+
* image/map tabs.
|
|
18
|
+
*/
|
|
19
|
+
referenceView?: ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* Optional controls of the guided layout. Omitted flags use {@link MINIMAL_CONTROLS};
|
|
22
|
+
* pass {@link ALL_CONTROLS} for every expert control. The classic layout always shows
|
|
23
|
+
* all controls.
|
|
24
|
+
*/
|
|
25
|
+
controls?: Partial<GeoreferencerControls>;
|
|
26
|
+
/**
|
|
27
|
+
* Extra actions shown in the empty image drop zone next to "Choose image", for example
|
|
28
|
+
* a button that loads a sample image.
|
|
29
|
+
*/
|
|
30
|
+
emptyImageActions?: ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Host-owned authoritative controller; the component resumes/suspends it but does not
|
|
33
|
+
* permanently dispose it.
|
|
34
|
+
*/
|
|
35
|
+
controller: GeoreferencerController;
|
|
36
|
+
/**
|
|
37
|
+
* Existing host-owned OpenLayers map. The component attaches owned layers/interactions
|
|
38
|
+
* and leaves the map alive on unmount.
|
|
39
|
+
*/
|
|
40
|
+
referenceMap: OLMap;
|
|
41
|
+
/**
|
|
42
|
+
* Reference providers, projections, snapping and optional initial map framing. Memoize
|
|
43
|
+
* this object to avoid reattachment.
|
|
44
|
+
*/
|
|
45
|
+
bindingOptions?: BindingOptions;
|
|
46
|
+
/** Translation function for default English messages; identity when omitted. */
|
|
47
|
+
t?: Translate;
|
|
48
|
+
/**
|
|
49
|
+
* Additional class on the editor root; built-in styles are scoped beneath rg-prefixed
|
|
50
|
+
* classes.
|
|
51
|
+
*/
|
|
52
|
+
className?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Optional structured-error formatter, allowing localization by error code instead of
|
|
55
|
+
* parsing English strings.
|
|
56
|
+
*/
|
|
57
|
+
formatError?: (error: NonNullable<ReturnType<GeoreferencerController["getSnapshot"]>["errorDetail"]>) => string;
|
|
58
|
+
/**
|
|
59
|
+
* Render a host-specific property form. Call the provided update callback with a
|
|
60
|
+
* replacement JSON properties object; do not mutate the frozen feature.
|
|
61
|
+
*/
|
|
62
|
+
propertyEditor?: Parameters<typeof FeaturePanel>[0]["propertyEditor"];
|
|
63
|
+
/** Receive any configured format's revisioned artifacts instead of default downloads. */
|
|
64
|
+
onExport?: (result: ExportResult) => void | Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Ready-made React editor for an existing OpenLayers map. Composes image, GCP, alignment, reference, output and optional drawing controls.
|
|
68
|
+
*
|
|
69
|
+
* Supplying `referenceView` selects the guided four-step layout, whose optional controls are chosen with `controls`; otherwise the classic workbench shows every control. Its effects attach/detach owned map resources and resume/suspend the controller for React Strict Mode. It installs a Save/Discard/Cancel guard and cancels pending dialogs on cleanup. The host retains final ownership of map, controller and engine. Import the optional scoped stylesheet from `@georeferencing/react/styles.css`.
|
|
70
|
+
*/
|
|
71
|
+
export declare function Georeferencer({ controller, referenceMap, bindingOptions, t, className, propertyEditor, onExport, formatError, referenceView, controls: controlOverrides, emptyImageActions, }: GeoreferencerProps): import("react/jsx-runtime").JSX.Element;
|