@panneau/fields 5.0.0-alpha.4 → 5.0.0-alpha.6
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 +67 -21
- package/dist/duration/DurationField.css +11 -0
- package/dist/duration/DurationField.d.ts +26 -0
- package/dist/duration/DurationField.d.ts.map +1 -0
- package/dist/duration/DurationField.js +129 -0
- package/dist/duration/DurationField.js.map +1 -0
- package/dist/duration/DurationField.module.js +12 -0
- package/dist/duration/DurationField.module.js.map +1 -0
- package/dist/duration/index.d.ts +2 -0
- package/dist/duration/index.d.ts.map +1 -0
- package/dist/duration/index.js +1 -0
- package/dist/embed/EmbedField.css +60 -0
- package/dist/embed/EmbedField.d.ts +20 -0
- package/dist/embed/EmbedField.d.ts.map +1 -0
- package/dist/embed/EmbedField.js +130 -0
- package/dist/embed/EmbedField.js.map +1 -0
- package/dist/embed/EmbedField.module.js +22 -0
- package/dist/embed/EmbedField.module.js.map +1 -0
- package/dist/embed/index.d.ts +3 -0
- package/dist/embed/index.d.ts.map +1 -0
- package/dist/embed/index.js +3 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/json/JsonField.css +7 -0
- package/dist/json/JsonField.d.ts +22 -0
- package/dist/json/JsonField.d.ts.map +1 -0
- package/dist/json/JsonField.js +125 -0
- package/dist/json/JsonField.js.map +1 -0
- package/dist/json/JsonField.module.js +8 -0
- package/dist/json/JsonField.module.js.map +1 -0
- package/dist/json/index.d.ts +2 -0
- package/dist/json/index.d.ts.map +1 -0
- package/dist/json/index.js +1 -0
- package/dist/localized/LocalizedField.d.ts.map +1 -1
- package/dist/localized/LocalizedField.js +1 -0
- package/dist/localized/LocalizedField.js.map +1 -1
- package/dist/location/LocationField.css +54 -0
- package/dist/location/LocationField.d.ts +31 -0
- package/dist/location/LocationField.d.ts.map +1 -0
- package/dist/location/LocationField.js +350 -0
- package/dist/location/LocationField.js.map +1 -0
- package/dist/location/LocationField.module.js +22 -0
- package/dist/location/LocationField.module.js.map +1 -0
- package/dist/location/LocationMap.d.ts +25 -0
- package/dist/location/LocationMap.d.ts.map +1 -0
- package/dist/location/LocationMap.js +115 -0
- package/dist/location/LocationMap.js.map +1 -0
- package/dist/location/index.d.ts +5 -0
- package/dist/location/index.d.ts.map +1 -0
- package/dist/location/index.js +4 -0
- package/dist/location/leafletCss.d.ts +2 -0
- package/dist/location/leafletCss.d.ts.map +1 -0
- package/dist/location/leafletCss.js +6 -0
- package/dist/location/leafletCss.js.map +1 -0
- package/dist/location/nominatim.d.ts +17 -0
- package/dist/location/nominatim.d.ts.map +1 -0
- package/dist/location/nominatim.js +50 -0
- package/dist/location/nominatim.js.map +1 -0
- package/dist/location/types.d.ts +40 -0
- package/dist/location/types.d.ts.map +1 -0
- package/dist/range/RangeField.d.ts +22 -0
- package/dist/range/RangeField.d.ts.map +1 -0
- package/dist/range/RangeField.js +132 -0
- package/dist/range/RangeField.js.map +1 -0
- package/dist/range/index.d.ts +2 -0
- package/dist/range/index.d.ts.map +1 -0
- package/dist/range/index.js +1 -0
- package/dist/relation/RelationField.d.ts.map +1 -1
- package/dist/relation/RelationField.js +24 -24
- package/dist/relation/RelationField.js.map +1 -1
- package/dist/shared/DefinitionField.d.ts +3 -1
- package/dist/shared/DefinitionField.d.ts.map +1 -1
- package/dist/shared/DefinitionField.js +80 -72
- package/dist/shared/DefinitionField.js.map +1 -1
- package/dist/shared/builtIn.d.ts +1 -0
- package/dist/shared/builtIn.d.ts.map +1 -1
- package/dist/shared/builtIn.js +16 -1
- package/dist/shared/builtIn.js.map +1 -1
- package/dist/shared/check.d.ts +27 -0
- package/dist/shared/check.d.ts.map +1 -0
- package/dist/shared/check.js +18 -0
- package/dist/shared/check.js.map +1 -0
- package/dist/shared/context.d.ts +18 -3
- package/dist/shared/context.d.ts.map +1 -1
- package/dist/shared/context.js +31 -19
- package/dist/shared/context.js.map +1 -1
- package/dist/shared/embed.d.ts +19 -0
- package/dist/shared/embed.d.ts.map +1 -0
- package/dist/shared/embed.js +14 -0
- package/dist/shared/embed.js.map +1 -0
- package/dist/shared/types.d.ts +2 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/slug/SlugField.css +18 -0
- package/dist/slug/SlugField.d.ts +31 -3
- package/dist/slug/SlugField.d.ts.map +1 -1
- package/dist/slug/SlugField.js +231 -159
- package/dist/slug/SlugField.js.map +1 -1
- package/dist/slug/SlugField.module.js +14 -0
- package/dist/slug/SlugField.module.js.map +1 -0
- package/dist/slug/index.d.ts +1 -1
- package/dist/slug/index.d.ts.map +1 -1
- package/dist/slug/index.js +1 -1
- package/dist/tags/TagsField.d.ts +17 -0
- package/dist/tags/TagsField.d.ts.map +1 -0
- package/dist/tags/TagsField.js +120 -0
- package/dist/tags/TagsField.js.map +1 -0
- package/dist/tags/index.d.ts +2 -0
- package/dist/tags/index.d.ts.map +1 -0
- package/dist/tags/index.js +1 -0
- package/dist/tel/TelField.d.ts +11 -0
- package/dist/tel/TelField.d.ts.map +1 -0
- package/dist/tel/TelField.js +87 -0
- package/dist/tel/TelField.js.map +1 -0
- package/dist/tel/index.d.ts +2 -0
- package/dist/tel/index.d.ts.map +1 -0
- package/dist/tel/index.js +1 -0
- package/package.json +41 -4
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { useFieldsContext } from "../shared/context.js";
|
|
2
|
+
import { getFieldProps, getSetting, isNumber, isString } from "../shared/entry.js";
|
|
3
|
+
import { messages } from "../shared/messages.js";
|
|
4
|
+
import LocationField_module_default from "./LocationField.module.js";
|
|
5
|
+
import { LocationMap } from "./LocationMap.js";
|
|
6
|
+
import { c } from "react/compiler-runtime";
|
|
7
|
+
import { ComboBox, Fieldset, IconButton, NumberInput, TextInput, usePanneauIntl } from "@panneau/ui";
|
|
8
|
+
import { useEffect, useRef, useState } from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { X } from "lucide-react";
|
|
11
|
+
//#region src/location/LocationField.tsx
|
|
12
|
+
/** OpenStreetMap's standard tiles: fine for an admin panel, with their credit. */
|
|
13
|
+
var OPEN_STREET_MAP_TILES = {
|
|
14
|
+
url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
15
|
+
attribution: "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors",
|
|
16
|
+
maxZoom: 19
|
|
17
|
+
};
|
|
18
|
+
var SEARCH_DELAY = 400;
|
|
19
|
+
var SEARCH_MIN_LENGTH = 3;
|
|
20
|
+
/** Whether a value is a point. */
|
|
21
|
+
function isLocation(value) {
|
|
22
|
+
return value !== null && typeof value === "object" && isNumber(value.lat) && isNumber(value.lng);
|
|
23
|
+
}
|
|
24
|
+
/** The search of addresses: results of the text typed, after a pause. */
|
|
25
|
+
function useAddressSearch(geocoding, query, locale) {
|
|
26
|
+
const $ = c(9);
|
|
27
|
+
let t0;
|
|
28
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
29
|
+
t0 = {
|
|
30
|
+
query: "",
|
|
31
|
+
results: [],
|
|
32
|
+
loading: false
|
|
33
|
+
};
|
|
34
|
+
$[0] = t0;
|
|
35
|
+
} else t0 = $[0];
|
|
36
|
+
const [state, setState] = useState(t0);
|
|
37
|
+
let t1;
|
|
38
|
+
let t2;
|
|
39
|
+
if ($[1] !== geocoding || $[2] !== locale || $[3] !== query) {
|
|
40
|
+
t1 = () => {
|
|
41
|
+
const text = query.trim();
|
|
42
|
+
if (geocoding === null || text.length < SEARCH_MIN_LENGTH) return;
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
const timeout = window.setTimeout(() => {
|
|
45
|
+
setState(_temp);
|
|
46
|
+
geocoding.search(text, {
|
|
47
|
+
signal: controller.signal,
|
|
48
|
+
locale
|
|
49
|
+
}).then((results) => setState({
|
|
50
|
+
query: text,
|
|
51
|
+
results,
|
|
52
|
+
loading: false
|
|
53
|
+
})).catch(() => {
|
|
54
|
+
if (!controller.signal.aborted) setState({
|
|
55
|
+
query: text,
|
|
56
|
+
results: [],
|
|
57
|
+
loading: false
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}, SEARCH_DELAY);
|
|
61
|
+
return () => {
|
|
62
|
+
window.clearTimeout(timeout);
|
|
63
|
+
controller.abort();
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
t2 = [
|
|
67
|
+
geocoding,
|
|
68
|
+
query,
|
|
69
|
+
locale
|
|
70
|
+
];
|
|
71
|
+
$[1] = geocoding;
|
|
72
|
+
$[2] = locale;
|
|
73
|
+
$[3] = query;
|
|
74
|
+
$[4] = t1;
|
|
75
|
+
$[5] = t2;
|
|
76
|
+
} else {
|
|
77
|
+
t1 = $[4];
|
|
78
|
+
t2 = $[5];
|
|
79
|
+
}
|
|
80
|
+
useEffect(t1, t2);
|
|
81
|
+
let t3;
|
|
82
|
+
if ($[6] !== query || $[7] !== state) {
|
|
83
|
+
t3 = query.trim().length >= SEARCH_MIN_LENGTH ? state : {
|
|
84
|
+
...state,
|
|
85
|
+
results: []
|
|
86
|
+
};
|
|
87
|
+
$[6] = query;
|
|
88
|
+
$[7] = state;
|
|
89
|
+
$[8] = t3;
|
|
90
|
+
} else t3 = $[8];
|
|
91
|
+
return t3;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A point on a map, and its address. Clicking the map or dragging the marker places the point,
|
|
95
|
+
* and its latitude and longitude can be typed. With an address search, a place found sets the
|
|
96
|
+
* point and the address; with a reverse search, placing a point fills an empty address.
|
|
97
|
+
*/
|
|
98
|
+
function _temp(current) {
|
|
99
|
+
return {
|
|
100
|
+
...current,
|
|
101
|
+
loading: true
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function LocationField({ value, onChange, onBlur, geocoding: geocodingProp, tiles: tilesProp, center = {
|
|
105
|
+
lat: 20,
|
|
106
|
+
lng: 0
|
|
107
|
+
}, zoom = 15, label, description, errors, disabled, readOnly, required, className }) {
|
|
108
|
+
const intl = usePanneauIntl();
|
|
109
|
+
const { maps } = useFieldsContext();
|
|
110
|
+
const geocoding = geocodingProp === void 0 ? maps?.geocoding ?? null : geocodingProp;
|
|
111
|
+
const tiles = tilesProp ?? maps?.tiles ?? OPEN_STREET_MAP_TILES;
|
|
112
|
+
const editable = disabled !== true && readOnly !== true;
|
|
113
|
+
const [query, setQuery] = useState("");
|
|
114
|
+
const [chosen, setChosen] = useState(null);
|
|
115
|
+
const search = useAddressSearch(editable && query !== chosen?.label ? geocoding : null, query, intl.locale);
|
|
116
|
+
const places = chosen !== null && query === chosen.label ? [chosen] : search.results;
|
|
117
|
+
const addressRef = useRef(null);
|
|
118
|
+
const focusAddress = () => window.requestAnimationFrame(() => addressRef.current?.querySelector("input")?.focus());
|
|
119
|
+
const [draft, setDraft] = useState({
|
|
120
|
+
source: value,
|
|
121
|
+
lat: value?.lat ?? null,
|
|
122
|
+
lng: value?.lng ?? null
|
|
123
|
+
});
|
|
124
|
+
if (draft.source !== value) setDraft({
|
|
125
|
+
source: value,
|
|
126
|
+
lat: value?.lat ?? null,
|
|
127
|
+
lng: value?.lng ?? null
|
|
128
|
+
});
|
|
129
|
+
const setPoint = (point, address = value?.address) => {
|
|
130
|
+
const next = {
|
|
131
|
+
lat: Number(point.lat.toFixed(6)),
|
|
132
|
+
lng: Number(point.lng.toFixed(6)),
|
|
133
|
+
...address !== void 0 && address !== "" ? { address } : {}
|
|
134
|
+
};
|
|
135
|
+
onChange?.(next);
|
|
136
|
+
if ((address === void 0 || address === "") && geocoding?.reverse !== void 0) {
|
|
137
|
+
const controller = new AbortController();
|
|
138
|
+
geocoding.reverse(point, {
|
|
139
|
+
signal: controller.signal,
|
|
140
|
+
locale: intl.locale
|
|
141
|
+
}).then((place) => {
|
|
142
|
+
if (place !== null) onChange?.({
|
|
143
|
+
...next,
|
|
144
|
+
address: place.label
|
|
145
|
+
});
|
|
146
|
+
}).catch(() => void 0);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const setCoordinate = (key, number) => {
|
|
150
|
+
const next_0 = {
|
|
151
|
+
...draft,
|
|
152
|
+
[key]: number
|
|
153
|
+
};
|
|
154
|
+
setDraft(next_0);
|
|
155
|
+
if (next_0.lat !== null && next_0.lng !== null) setPoint({
|
|
156
|
+
lat: next_0.lat,
|
|
157
|
+
lng: next_0.lng
|
|
158
|
+
});
|
|
159
|
+
else if (next_0.lat === null && next_0.lng === null) onChange?.(null);
|
|
160
|
+
};
|
|
161
|
+
const point_0 = isLocation(value) ? {
|
|
162
|
+
lat: value.lat,
|
|
163
|
+
lng: value.lng
|
|
164
|
+
} : null;
|
|
165
|
+
return /* @__PURE__ */ jsx(Fieldset, {
|
|
166
|
+
legend: label,
|
|
167
|
+
description,
|
|
168
|
+
errors,
|
|
169
|
+
isRequired: required,
|
|
170
|
+
isDisabled: disabled,
|
|
171
|
+
className,
|
|
172
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
173
|
+
className: LocationField_module_default.location,
|
|
174
|
+
children: [
|
|
175
|
+
editable && geocoding !== null ? /* @__PURE__ */ jsx(ComboBox, {
|
|
176
|
+
"aria-label": intl.formatMessage(messages.searchAddress),
|
|
177
|
+
placeholder: intl.formatMessage(messages.searchAddress),
|
|
178
|
+
onInputChange: setQuery,
|
|
179
|
+
items: places.map((result, index) => ({
|
|
180
|
+
id: String(index),
|
|
181
|
+
label: result.label
|
|
182
|
+
})),
|
|
183
|
+
isLoading: search.loading,
|
|
184
|
+
menuTrigger: "input",
|
|
185
|
+
emptyMessage: query.trim().length < SEARCH_MIN_LENGTH ? intl.formatMessage(messages.searchAddressHint, { count: SEARCH_MIN_LENGTH }) : intl.formatMessage(messages.noPlaces),
|
|
186
|
+
value: chosen !== null && query === chosen.label ? "0" : null,
|
|
187
|
+
onChange: (id) => {
|
|
188
|
+
const result_0 = id !== null ? places[Number(id)] : void 0;
|
|
189
|
+
if (result_0 !== void 0) {
|
|
190
|
+
setChosen(result_0);
|
|
191
|
+
setPoint(result_0, result_0.label);
|
|
192
|
+
focusAddress();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}) : null,
|
|
196
|
+
/* @__PURE__ */ jsx(LocationMap, {
|
|
197
|
+
point: point_0,
|
|
198
|
+
onChange: (next_1) => setPoint(next_1),
|
|
199
|
+
tiles,
|
|
200
|
+
center,
|
|
201
|
+
zoom,
|
|
202
|
+
readOnly: !editable,
|
|
203
|
+
label: intl.formatMessage(messages.map, { label: typeof label === "string" ? label : "" })
|
|
204
|
+
}),
|
|
205
|
+
/* @__PURE__ */ jsxs("div", {
|
|
206
|
+
className: LocationField_module_default.coordinates,
|
|
207
|
+
children: [
|
|
208
|
+
/* @__PURE__ */ jsx(NumberInput, {
|
|
209
|
+
label: intl.formatMessage(messages.latitude),
|
|
210
|
+
value: draft.lat,
|
|
211
|
+
onChange: (next_2) => setCoordinate("lat", next_2),
|
|
212
|
+
onBlur: () => onBlur?.(),
|
|
213
|
+
minValue: -90,
|
|
214
|
+
maxValue: 90,
|
|
215
|
+
step: 1e-6,
|
|
216
|
+
formatOptions: { maximumFractionDigits: 6 },
|
|
217
|
+
isDisabled: disabled,
|
|
218
|
+
isReadOnly: readOnly,
|
|
219
|
+
className: LocationField_module_default.coordinate
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ jsx(NumberInput, {
|
|
222
|
+
label: intl.formatMessage(messages.longitude),
|
|
223
|
+
value: draft.lng,
|
|
224
|
+
onChange: (next_3) => setCoordinate("lng", next_3),
|
|
225
|
+
onBlur: () => onBlur?.(),
|
|
226
|
+
minValue: -180,
|
|
227
|
+
maxValue: 180,
|
|
228
|
+
step: 1e-6,
|
|
229
|
+
formatOptions: { maximumFractionDigits: 6 },
|
|
230
|
+
isDisabled: disabled,
|
|
231
|
+
isReadOnly: readOnly,
|
|
232
|
+
className: LocationField_module_default.coordinate
|
|
233
|
+
}),
|
|
234
|
+
editable && point_0 !== null ? /* @__PURE__ */ jsx(IconButton, {
|
|
235
|
+
icon: X,
|
|
236
|
+
label: intl.formatMessage(messages.removePoint),
|
|
237
|
+
className: LocationField_module_default.remove,
|
|
238
|
+
onPress: () => onChange?.(null)
|
|
239
|
+
}) : null
|
|
240
|
+
]
|
|
241
|
+
}),
|
|
242
|
+
point_0 !== null ? /* @__PURE__ */ jsx("div", {
|
|
243
|
+
ref: addressRef,
|
|
244
|
+
children: /* @__PURE__ */ jsx(TextInput, {
|
|
245
|
+
label: intl.formatMessage(messages.address),
|
|
246
|
+
value: value?.address ?? "",
|
|
247
|
+
onChange: (address_0) => onChange?.({
|
|
248
|
+
lat: point_0.lat,
|
|
249
|
+
lng: point_0.lng,
|
|
250
|
+
...address_0 !== "" ? { address: address_0 } : {}
|
|
251
|
+
}),
|
|
252
|
+
onBlur: () => onBlur?.(),
|
|
253
|
+
isDisabled: disabled,
|
|
254
|
+
isReadOnly: readOnly
|
|
255
|
+
})
|
|
256
|
+
}) : null
|
|
257
|
+
]
|
|
258
|
+
})
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function isPoint(value) {
|
|
262
|
+
return isLocation(value);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The `location` type: settings `zoom`, `center` (`{ "lat", "lng" }`, where the map opens without
|
|
266
|
+
* a point) and `tiles` (`{ "url", "attribution" }`), over the maps of the `FieldsProvider`.
|
|
267
|
+
*/
|
|
268
|
+
function LocationFieldEntry(props) {
|
|
269
|
+
const $ = c(23);
|
|
270
|
+
const { field } = props;
|
|
271
|
+
let t0;
|
|
272
|
+
if ($[0] !== field) {
|
|
273
|
+
t0 = getSetting(field, "zoom", isNumber);
|
|
274
|
+
$[0] = field;
|
|
275
|
+
$[1] = t0;
|
|
276
|
+
} else t0 = $[1];
|
|
277
|
+
const zoom = t0;
|
|
278
|
+
let t1;
|
|
279
|
+
if ($[2] !== field) {
|
|
280
|
+
t1 = getSetting(field, "center", isPoint);
|
|
281
|
+
$[2] = field;
|
|
282
|
+
$[3] = t1;
|
|
283
|
+
} else t1 = $[3];
|
|
284
|
+
const center = t1;
|
|
285
|
+
let t2;
|
|
286
|
+
if ($[4] !== field) {
|
|
287
|
+
t2 = getSetting(field, "tiles", _temp2);
|
|
288
|
+
$[4] = field;
|
|
289
|
+
$[5] = t2;
|
|
290
|
+
} else t2 = $[5];
|
|
291
|
+
const tiles = t2;
|
|
292
|
+
let t3;
|
|
293
|
+
if ($[6] !== props) {
|
|
294
|
+
t3 = getFieldProps(props);
|
|
295
|
+
$[6] = props;
|
|
296
|
+
$[7] = t3;
|
|
297
|
+
} else t3 = $[7];
|
|
298
|
+
let fieldProps;
|
|
299
|
+
if ($[8] !== t3) {
|
|
300
|
+
const { placeholder: _placeholder, ...t4 } = t3;
|
|
301
|
+
fieldProps = t4;
|
|
302
|
+
$[8] = t3;
|
|
303
|
+
$[9] = fieldProps;
|
|
304
|
+
} else fieldProps = $[9];
|
|
305
|
+
const t4 = isLocation(props.value) ? props.value : null;
|
|
306
|
+
let t5;
|
|
307
|
+
if ($[10] !== zoom) {
|
|
308
|
+
t5 = zoom !== void 0 ? { zoom } : {};
|
|
309
|
+
$[10] = zoom;
|
|
310
|
+
$[11] = t5;
|
|
311
|
+
} else t5 = $[11];
|
|
312
|
+
let t6;
|
|
313
|
+
if ($[12] !== center) {
|
|
314
|
+
t6 = center !== void 0 ? { center } : {};
|
|
315
|
+
$[12] = center;
|
|
316
|
+
$[13] = t6;
|
|
317
|
+
} else t6 = $[13];
|
|
318
|
+
let t7;
|
|
319
|
+
if ($[14] !== tiles) {
|
|
320
|
+
t7 = tiles !== void 0 ? { tiles } : {};
|
|
321
|
+
$[14] = tiles;
|
|
322
|
+
$[15] = t7;
|
|
323
|
+
} else t7 = $[15];
|
|
324
|
+
let t8;
|
|
325
|
+
if ($[16] !== fieldProps || $[17] !== props.onChange || $[18] !== t4 || $[19] !== t5 || $[20] !== t6 || $[21] !== t7) {
|
|
326
|
+
t8 = /* @__PURE__ */ jsx(LocationField, {
|
|
327
|
+
...fieldProps,
|
|
328
|
+
value: t4,
|
|
329
|
+
onChange: props.onChange,
|
|
330
|
+
...t5,
|
|
331
|
+
...t6,
|
|
332
|
+
...t7
|
|
333
|
+
});
|
|
334
|
+
$[16] = fieldProps;
|
|
335
|
+
$[17] = props.onChange;
|
|
336
|
+
$[18] = t4;
|
|
337
|
+
$[19] = t5;
|
|
338
|
+
$[20] = t6;
|
|
339
|
+
$[21] = t7;
|
|
340
|
+
$[22] = t8;
|
|
341
|
+
} else t8 = $[22];
|
|
342
|
+
return t8;
|
|
343
|
+
}
|
|
344
|
+
function _temp2(value) {
|
|
345
|
+
return value !== null && typeof value === "object" && isString(value.url) && isString(value.attribution);
|
|
346
|
+
}
|
|
347
|
+
//#endregion
|
|
348
|
+
export { LocationField, LocationFieldEntry, OPEN_STREET_MAP_TILES, isLocation };
|
|
349
|
+
|
|
350
|
+
//# sourceMappingURL=LocationField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocationField.js","names":["next","point","result","address","_c","styles"],"sources":["../../src/location/LocationField.tsx"],"sourcesContent":["import { X } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { LocationValue } from '@panneau/protocol';\nimport {\n ComboBox,\n Fieldset,\n IconButton,\n NumberInput,\n TextInput,\n usePanneauIntl,\n} from '@panneau/ui';\n\nimport { useFieldsContext } from '../shared/context';\nimport { getFieldProps, getSetting, isNumber, isString } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport styles from './LocationField.module.css';\nimport { LocationMap, type Point } from './LocationMap';\nimport type { GeocodingResult, GeocodingSource, MapTiles } from './types';\n\nexport type { LocationValue };\n\n/** OpenStreetMap's standard tiles: fine for an admin panel, with their credit. */\nexport const OPEN_STREET_MAP_TILES: MapTiles = {\n url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution:\n '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n maxZoom: 19,\n};\n\nconst SEARCH_DELAY = 400;\nconst SEARCH_MIN_LENGTH = 3;\n\nexport interface LocationFieldProps extends FieldProps<LocationValue> {\n /** The address search. Defaults to that of the `FieldsProvider`; without one, there is none. */\n geocoding?: GeocodingSource | null;\n /** The tiles of the map. Defaults to those of the `FieldsProvider`, or OpenStreetMap's. */\n tiles?: MapTiles;\n /** Where the map opens without a point. Defaults to the whole world. */\n center?: Point;\n /** Zoom of the map on a point. Defaults to 15. */\n zoom?: number;\n}\n\n/** Whether a value is a point. */\nexport function isLocation(value: unknown): value is LocationValue {\n return (\n value !== null &&\n typeof value === 'object' &&\n isNumber((value as Record<string, unknown>).lat) &&\n isNumber((value as Record<string, unknown>).lng)\n );\n}\n\n/** The search of addresses: results of the text typed, after a pause. */\nfunction useAddressSearch(geocoding: GeocodingSource | null, query: string, locale: string) {\n const [state, setState] = useState<{\n query: string;\n results: GeocodingResult[];\n loading: boolean;\n }>({ query: '', results: [], loading: false });\n useEffect(() => {\n const text = query.trim();\n if (geocoding === null || text.length < SEARCH_MIN_LENGTH) {\n return undefined;\n }\n const controller = new AbortController();\n const timeout = window.setTimeout(() => {\n setState((current) => ({ ...current, loading: true }));\n geocoding\n .search(text, { signal: controller.signal, locale })\n .then((results) => setState({ query: text, results, loading: false }))\n .catch(() => {\n if (!controller.signal.aborted) {\n setState({ query: text, results: [], loading: false });\n }\n });\n }, SEARCH_DELAY);\n return () => {\n window.clearTimeout(timeout);\n controller.abort();\n };\n }, [geocoding, query, locale]);\n return query.trim().length >= SEARCH_MIN_LENGTH ? state : { ...state, results: [] };\n}\n\n/**\n * A point on a map, and its address. Clicking the map or dragging the marker places the point,\n * and its latitude and longitude can be typed. With an address search, a place found sets the\n * point and the address; with a reverse search, placing a point fills an empty address.\n */\nexport function LocationField({\n value,\n onChange,\n onBlur,\n geocoding: geocodingProp,\n tiles: tilesProp,\n center = { lat: 20, lng: 0 },\n zoom = 15,\n label,\n description,\n errors,\n disabled,\n readOnly,\n required,\n className,\n}: LocationFieldProps) {\n const intl = usePanneauIntl();\n const { maps } = useFieldsContext();\n const geocoding = geocodingProp === undefined ? (maps?.geocoding ?? null) : geocodingProp;\n const tiles = tilesProp ?? maps?.tiles ?? OPEN_STREET_MAP_TILES;\n const editable = disabled !== true && readOnly !== true;\n const [query, setQuery] = useState('');\n // The place chosen: the search shows its label until something else is typed\n const [chosen, setChosen] = useState<GeocodingResult | null>(null);\n const search = useAddressSearch(\n editable && query !== chosen?.label ? geocoding : null,\n query,\n intl.locale,\n );\n const places = chosen !== null && query === chosen.label ? [chosen] : search.results;\n // A place chosen moves focus to its address, which closes the results\n const addressRef = useRef<HTMLDivElement>(null);\n const focusAddress = () =>\n window.requestAnimationFrame(() =>\n addressRef.current?.querySelector<HTMLInputElement>('input')?.focus(),\n );\n\n // The coordinates as typed: a value needs both\n const [draft, setDraft] = useState<{ source: unknown; lat: number | null; lng: number | null }>(\n { source: value, lat: value?.lat ?? null, lng: value?.lng ?? null },\n );\n if (draft.source !== value) {\n setDraft({ source: value, lat: value?.lat ?? null, lng: value?.lng ?? null });\n }\n\n const setPoint = (point: Point, address = value?.address) => {\n const next: LocationValue = {\n lat: Number(point.lat.toFixed(6)),\n lng: Number(point.lng.toFixed(6)),\n ...(address !== undefined && address !== '' ? { address } : {}),\n };\n onChange?.(next);\n // Fills an empty address from the point\n if ((address === undefined || address === '') && geocoding?.reverse !== undefined) {\n const controller = new AbortController();\n void geocoding\n .reverse(point, { signal: controller.signal, locale: intl.locale })\n .then((place) => {\n if (place !== null) {\n onChange?.({ ...next, address: place.label });\n }\n })\n .catch(() => undefined);\n }\n };\n\n const setCoordinate = (key: 'lat' | 'lng', number: number | null) => {\n const next = { ...draft, [key]: number };\n setDraft(next);\n if (next.lat !== null && next.lng !== null) {\n setPoint({ lat: next.lat, lng: next.lng });\n } else if (next.lat === null && next.lng === null) {\n onChange?.(null);\n }\n };\n\n const point = isLocation(value) ? { lat: value.lat, lng: value.lng } : null;\n return (\n <Fieldset\n legend={label}\n description={description}\n errors={errors}\n isRequired={required}\n isDisabled={disabled}\n className={className}\n >\n <div className={styles.location}>\n {editable && geocoding !== null ? (\n <ComboBox\n aria-label={intl.formatMessage(messages.searchAddress)}\n placeholder={intl.formatMessage(messages.searchAddress)}\n onInputChange={setQuery}\n items={places.map((result, index) => ({\n id: String(index),\n label: result.label,\n }))}\n isLoading={search.loading}\n menuTrigger=\"input\"\n emptyMessage={\n query.trim().length < SEARCH_MIN_LENGTH\n ? intl.formatMessage(messages.searchAddressHint, {\n count: SEARCH_MIN_LENGTH,\n })\n : intl.formatMessage(messages.noPlaces)\n }\n value={chosen !== null && query === chosen.label ? '0' : null}\n onChange={(id) => {\n const result = id !== null ? places[Number(id)] : undefined;\n if (result !== undefined) {\n setChosen(result);\n setPoint(result, result.label);\n focusAddress();\n }\n }}\n />\n ) : null}\n <LocationMap\n point={point}\n onChange={(next) => setPoint(next)}\n tiles={tiles}\n center={center}\n zoom={zoom}\n readOnly={!editable}\n label={intl.formatMessage(messages.map, {\n label: typeof label === 'string' ? label : '',\n })}\n />\n <div className={styles.coordinates}>\n <NumberInput\n label={intl.formatMessage(messages.latitude)}\n value={draft.lat}\n onChange={(next) => setCoordinate('lat', next)}\n onBlur={() => onBlur?.()}\n minValue={-90}\n maxValue={90}\n step={0.000001}\n formatOptions={{ maximumFractionDigits: 6 }}\n isDisabled={disabled}\n isReadOnly={readOnly}\n className={styles.coordinate}\n />\n <NumberInput\n label={intl.formatMessage(messages.longitude)}\n value={draft.lng}\n onChange={(next) => setCoordinate('lng', next)}\n onBlur={() => onBlur?.()}\n minValue={-180}\n maxValue={180}\n step={0.000001}\n formatOptions={{ maximumFractionDigits: 6 }}\n isDisabled={disabled}\n isReadOnly={readOnly}\n className={styles.coordinate}\n />\n {editable && point !== null ? (\n <IconButton\n icon={X}\n label={intl.formatMessage(messages.removePoint)}\n className={styles.remove}\n onPress={() => onChange?.(null)}\n />\n ) : null}\n </div>\n {point !== null ? (\n <div ref={addressRef}>\n <TextInput\n label={intl.formatMessage(messages.address)}\n value={value?.address ?? ''}\n onChange={(address) =>\n onChange?.({\n lat: point.lat,\n lng: point.lng,\n ...(address !== '' ? { address } : {}),\n })\n }\n onBlur={() => onBlur?.()}\n isDisabled={disabled}\n isReadOnly={readOnly}\n />\n </div>\n ) : null}\n </div>\n </Fieldset>\n );\n}\n\nfunction isPoint(value: unknown): value is Point {\n return isLocation(value);\n}\n\n/**\n * The `location` type: settings `zoom`, `center` (`{ \"lat\", \"lng\" }`, where the map opens without\n * a point) and `tiles` (`{ \"url\", \"attribution\" }`), over the maps of the `FieldsProvider`.\n */\nexport function LocationFieldEntry(props: FieldEntryProps) {\n const { field } = props;\n const zoom = getSetting(field, 'zoom', isNumber);\n const center = getSetting(field, 'center', isPoint);\n const tiles = getSetting(\n field,\n 'tiles',\n (value): value is MapTiles =>\n value !== null &&\n typeof value === 'object' &&\n isString((value as Record<string, unknown>).url) &&\n isString((value as Record<string, unknown>).attribution),\n );\n const { placeholder: _placeholder, ...fieldProps } = getFieldProps(props);\n return (\n <LocationField\n {...fieldProps}\n value={isLocation(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(zoom !== undefined ? { zoom } : {})}\n {...(center !== undefined ? { center } : {})}\n {...(tiles !== undefined ? { tiles } : {})}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;AAwBA,IAAa,wBAAkC;CAC3C,KAAK;CACL,aACI;CACJ,SAAS;AACb;AAEA,IAAM,eAAe;AACrB,IAAM,oBAAoB;;AAc1B,SAAgB,WAAW,OAAwC;CAC/D,OACI,UAAU,QACV,OAAO,UAAU,YACjB,SAAU,MAAkC,GAAG,KAC/C,SAAU,MAAkC,GAAG;AAEvD;;AAGA,SAAA,iBAAA,WAAA,OAAA,QAAA;CAAA,MAAA,IAAAI,EAAA,CAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA,IAAA,2BAAA,GAAA;EAKO,KAAA;GAAA,OAAS;GAAE,SAAW,CAAA;GAAE,SAAW;EAAM;EAAC,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAJ7C,MAAA,CAAA,OAAA,YAA0B,SAIvB,EAA0C;CAAE,IAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,aAAA,EAAA,OAAA,UAAA,EAAA,OAAA,OAAA;EACrC,WAAA;GACN,MAAA,OAAa,MAAK,KAAM;GACxB,IAAI,cAAc,QAAQ,KAAI,SAAU,mBAAiB;GAGzD,MAAA,aAAmB,IAAI,gBAAgB;GACvC,MAAA,UAAgB,OAAM,iBAAY;IAC9B,SAAS,KAA4C;IACrD,UAAS,OACG,MAAM;KAAA,QAAU,WAAU;KAAO;IAAS,CAAC,CAAC,CAAA,MAC9C,YAAa,SAAS;KAAA,OAAS;KAAI;KAAA,SAAoB;IAAM,CAAC,CAAC,CAAC,CAAA,YAC/D;KACH,IAAI,CAAC,WAAU,OAAO,SAClB,SAAS;MAAA,OAAS;MAAI,SAAW,CAAA;MAAE,SAAW;KAAM,CAAC;IACxD,CACJ;GAAC,GACP,YAAY;GAAE,aACV;IACH,OAAM,aAAc,OAAO;IAC3B,WAAU,MAAO;GAAC;EACrB;EACF,KAAA;GAAC;GAAW;GAAO;EAAM;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA;EAAA,KAAA,EAAA;EAAA,KAAA,EAAA;CAAA;CArB7B,UAAU,IAqBP,EAA0B;CAAC,IAAA;CAAA,IAAA,EAAA,OAAA,SAAA,EAAA,OAAA,OAAA;EACvB,KAAA,MAAK,KAAM,CAAC,CAAA,UAAW,oBAAvB,QAAA;GAAA,GAAwD;GAAK,SAAW,CAAA;EAAG;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAA5E;AAA4E;;;;;;AA5BvF,SAAA,MAAA,SAAA;CAAA,OAamC;EAAA,GAAK;EAAO,SAAW;CAAK;AAAC;AAuBhE,SAAgB,cAAc,EAC1B,OACA,UACA,QACA,WAAW,eACX,OAAO,WACP,SAAS;CAAE,KAAK;CAAI,KAAK;AAAE,GAC3B,OAAO,IACP,OACA,aACA,QACA,UACA,UACA,UACA,aACmB;CACnB,MAAM,OAAO,eAAe;CAC5B,MAAM,EAAE,SAAS,iBAAiB;CAClC,MAAM,YAAY,kBAAkB,KAAA,IAAa,MAAM,aAAa,OAAQ;CAC5E,MAAM,QAAQ,aAAa,MAAM,SAAS;CAC1C,MAAM,WAAW,aAAa,QAAQ,aAAa;CACnD,MAAM,CAAC,OAAO,YAAY,SAAS,EAAE;CAErC,MAAM,CAAC,QAAQ,aAAa,SAAiC,IAAI;CACjE,MAAM,SAAS,iBACX,YAAY,UAAU,QAAQ,QAAQ,YAAY,MAClD,OACA,KAAK,MACT;CACA,MAAM,SAAS,WAAW,QAAQ,UAAU,OAAO,QAAQ,CAAC,MAAM,IAAI,OAAO;CAE7E,MAAM,aAAa,OAAuB,IAAI;CAC9C,MAAM,qBACF,OAAO,4BACH,WAAW,SAAS,cAAgC,OAAO,CAAC,EAAE,MAAM,CACxE;CAGJ,MAAM,CAAC,OAAO,YAAY,SACtB;EAAE,QAAQ;EAAO,KAAK,OAAO,OAAO;EAAM,KAAK,OAAO,OAAO;CAAK,CACtE;CACA,IAAI,MAAM,WAAW,OACjB,SAAS;EAAE,QAAQ;EAAO,KAAK,OAAO,OAAO;EAAM,KAAK,OAAO,OAAO;CAAK,CAAC;CAGhF,MAAM,YAAY,OAAc,UAAU,OAAO,YAAY;EACzD,MAAM,OAAsB;GACxB,KAAK,OAAO,MAAM,IAAI,QAAQ,CAAC,CAAC;GAChC,KAAK,OAAO,MAAM,IAAI,QAAQ,CAAC,CAAC;GAChC,GAAI,YAAY,KAAA,KAAa,YAAY,KAAK,EAAE,QAAQ,IAAI,CAAC;EACjE;EACA,WAAW,IAAI;EAEf,KAAK,YAAY,KAAA,KAAa,YAAY,OAAO,WAAW,YAAY,KAAA,GAAW;GAC/E,MAAM,aAAa,IAAI,gBAAgB;GACvC,UACK,QAAQ,OAAO;IAAE,QAAQ,WAAW;IAAQ,QAAQ,KAAK;GAAO,CAAC,CAAC,CAClE,MAAM,UAAU;IACb,IAAI,UAAU,MACV,WAAW;KAAE,GAAG;KAAM,SAAS,MAAM;IAAM,CAAC;GAEpD,CAAC,CAAC,CACD,YAAY,KAAA,CAAS;EAC9B;CACJ;CAEA,MAAM,iBAAiB,KAAoB,WAA0B;EACjE,MAAMJ,SAAO;GAAE,GAAG;IAAQ,MAAM;EAAO;EACvC,SAASA,MAAI;EACb,IAAIA,OAAK,QAAQ,QAAQA,OAAK,QAAQ,MAClC,SAAS;GAAE,KAAKA,OAAK;GAAK,KAAKA,OAAK;EAAI,CAAC;OACtC,IAAIA,OAAK,QAAQ,QAAQA,OAAK,QAAQ,MACzC,WAAW,IAAI;CAEvB;CAEA,MAAMC,UAAQ,WAAW,KAAK,IAAI;EAAE,KAAK,MAAM;EAAK,KAAK,MAAM;CAAI,IAAI;CACvE,OACI,oBAAC,UAAD;EACI,QAAQ;EACK;EACL;EACR,YAAY;EACZ,YAAY;EACD;EAEX,UAAA,qBAAC,OAAD;GAAK,WAAWI,6BAAO;GAAvB,UAAA;IACK,YAAY,cAAc,OACvB,oBAAC,UAAD;KACI,cAAY,KAAK,cAAc,SAAS,aAAa;KACrD,aAAa,KAAK,cAAc,SAAS,aAAa;KACtD,eAAe;KACf,OAAO,OAAO,KAAK,QAAQ,WAAW;MAClC,IAAI,OAAO,KAAK;MAChB,OAAO,OAAO;KAClB,EAAE;KACF,WAAW,OAAO;KAClB,aAAY;KACZ,cACI,MAAM,KAAK,CAAC,CAAC,SAAS,oBAChB,KAAK,cAAc,SAAS,mBAAmB,EAC3C,OAAO,kBACX,CAAC,IACD,KAAK,cAAc,SAAS,QAAQ;KAE9C,OAAO,WAAW,QAAQ,UAAU,OAAO,QAAQ,MAAM;KACzD,WAAW,OAAO;MACd,MAAMH,WAAS,OAAO,OAAO,OAAO,OAAO,EAAE,KAAK,KAAA;MAClD,IAAIA,aAAW,KAAA,GAAW;OACtB,UAAUA,QAAM;OAChB,SAASA,UAAQA,SAAO,KAAK;OAC7B,aAAa;MACjB;KACJ;IAAE,CAAA,IAEN;IACJ,oBAAC,aAAD;KACI,OAAOD;KACP,WAAWD,WAAS,SAASA,MAAI;KAC1B;KACC;KACF;KACN,UAAU,CAAC;KACX,OAAO,KAAK,cAAc,SAAS,KAAK,EACpC,OAAO,OAAO,UAAU,WAAW,QAAQ,GAC/C,CAAC;IAAE,CAAA;IAEP,qBAAC,OAAD;KAAK,WAAWK,6BAAO;KAAvB,UAAA;MACI,oBAAC,aAAD;OACI,OAAO,KAAK,cAAc,SAAS,QAAQ;OAC3C,OAAO,MAAM;OACb,WAAWL,WAAS,cAAc,OAAOA,MAAI;OAC7C,cAAc,SAAS;OACvB,UAAU;OACV,UAAU;OACV,MAAM;OACN,eAAe,EAAE,uBAAuB,EAAE;OAC1C,YAAY;OACZ,YAAY;OACZ,WAAWK,6BAAO;MAAW,CAAA;MAEjC,oBAAC,aAAD;OACI,OAAO,KAAK,cAAc,SAAS,SAAS;OAC5C,OAAO,MAAM;OACb,WAAWL,WAAS,cAAc,OAAOA,MAAI;OAC7C,cAAc,SAAS;OACvB,UAAU;OACV,UAAU;OACV,MAAM;OACN,eAAe,EAAE,uBAAuB,EAAE;OAC1C,YAAY;OACZ,YAAY;OACZ,WAAWK,6BAAO;MAAW,CAAA;MAEhC,YAAYJ,YAAU,OACnB,oBAAC,YAAD;OACI,MAAM;OACN,OAAO,KAAK,cAAc,SAAS,WAAW;OAC9C,WAAWI,6BAAO;OAClB,eAAe,WAAW,IAAI;MAAE,CAAA,IAEpC;KACH;;IACJJ,YAAU,OACP,oBAAC,OAAD;KAAK,KAAK;KACN,UAAA,oBAAC,WAAD;MACI,OAAO,KAAK,cAAc,SAAS,OAAO;MAC1C,OAAO,OAAO,WAAW;MACzB,WAAWE,cACP,WAAW;OACP,KAAKF,QAAM;OACX,KAAKA,QAAM;OACX,GAAIE,cAAY,KAAK,EAAE,SAAAA,UAAQ,IAAI,CAAC;MACxC,CAAC;MAEL,cAAc,SAAS;MACvB,YAAY;MACZ,YAAY;KAAS,CAAA;IAExB,CAAA,IACL;GACH;;CACC,CAAA;AAElB;AAEA,SAAS,QAAQ,OAAgC;CAC7C,OAAO,WAAW,KAAK;AAC3B;;;;;AAMA,SAAO,mBAAA,OAAA;CAAA,MAAA,IAAAC,EAAA,EAAA;CACH,MAAA,EAAA,UAAkB;CAAM,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EACX,KAAA,WAAW,OAAO,QAAQ,QAAQ;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAhD,MAAA,OAAa;CAAoC,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EAClC,KAAA,WAAW,OAAO,UAAU,OAAO;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAnD,MAAA,SAAe;CAAqC,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EACtC,KAAA,WACV,OACA,SACA,MAKJ;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CARD,MAAA,QAAc;CAQZ,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EACmD,KAAA,cAAc,KAAK;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,IAAA;EAAzE,MAAA,EAAA,aAAA,cAAA,GAAA,OAAqD;EAArD,aAAA;EAA0E,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,aAAA,EAAA;CAI3D,MAAA,KAAA,WAAW,MAAK,KAA2B,IAAjB,MAAK,QAA/B;CAA4C,IAAA;CAAA,IAAA,EAAA,QAAA,MAAA;EAE9C,KAAA,SAAS,KAAA,IAAT,EAAA,KAAiC,IAAjC,CAAiC;EAAC,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,QAAA;EAClC,KAAA,WAAW,KAAA,IAAX,EAAA,OAAqC,IAArC,CAAqC;EAAC,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,OAAA;EACtC,KAAA,UAAU,KAAA,IAAV,EAAA,MAAmC,IAAnC,CAAmC;EAAC,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,cAAA,EAAA,QAAA,MAAA,YAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,MAAA,EAAA,QAAA,IAAA;EAN7C,KAAA,oBAAC,eAAD;GAAc,GACN;GACG,OAAA;GACG,UAAA,MAAK;GAAS,GACnB;GAAkC,GAClC;GAAsC,GACtC;EAAoC,CAAA;EAC3C,EAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAPF;AAOE;AAtBH,SAAA,OAAA,OAAA;CAAA,OAQK,UAAU,QACV,OAAO,UAAU,YACjB,SAAU,MAAgC,GAAK,KAC/C,SAAU,MAAgC,WAAa;AAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "./LocationField.css";
|
|
2
|
+
//#region src/location/LocationField.module.css
|
|
3
|
+
var location = "panneau-location-field-location";
|
|
4
|
+
var map = "panneau-location-field-map";
|
|
5
|
+
var marker = "panneau-location-field-marker";
|
|
6
|
+
var pin = "panneau-location-field-pin";
|
|
7
|
+
var coordinates = "panneau-location-field-coordinates";
|
|
8
|
+
var coordinate = "panneau-location-field-coordinate";
|
|
9
|
+
var remove = "panneau-location-field-remove";
|
|
10
|
+
var LocationField_module_default = {
|
|
11
|
+
location,
|
|
12
|
+
map,
|
|
13
|
+
marker,
|
|
14
|
+
pin,
|
|
15
|
+
coordinates,
|
|
16
|
+
coordinate,
|
|
17
|
+
remove
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { coordinate, coordinates, LocationField_module_default as default, location, map, marker, pin, remove };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=LocationField.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocationField.module.js","names":[],"sources":["../../src/location/LocationField.module.css"],"sourcesContent":["/* The search, the map, then the coordinates and the address. */\n.location {\n display: flex;\n flex-direction: column;\n gap: var(--panneau-space-2);\n}\n\n.map {\n position: relative;\n z-index: 0;\n height: 16rem;\n overflow: hidden;\n background-color: var(--panneau-color-surface-sunken);\n border: var(--panneau-border-width) solid var(--panneau-color-border-control);\n border-radius: var(--panneau-radius-md);\n}\n\n.map:focus-visible {\n outline: var(--panneau-focus-width) solid var(--panneau-color-focus);\n outline-offset: 1px;\n}\n\n/* A pin: a round head pointing down at the point. */\n.marker {\n background: none;\n border: 0;\n}\n\n.pin {\n display: block;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n background-color: var(--panneau-color-accent);\n border: 2px solid var(--panneau-color-surface);\n border-radius: 50% 50% 50% 0;\n box-shadow: var(--panneau-shadow-sm);\n rotate: -45deg;\n}\n\n.coordinates {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-end;\n gap: var(--panneau-space-2);\n}\n\n.coordinate {\n flex: 1 1 8rem;\n}\n\n.remove {\n flex: none;\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MapTiles } from './types';
|
|
2
|
+
export interface Point {
|
|
3
|
+
lat: number;
|
|
4
|
+
lng: number;
|
|
5
|
+
}
|
|
6
|
+
export interface LocationMapProps {
|
|
7
|
+
point: Point | null;
|
|
8
|
+
/** Called with the point clicked, or where the marker was dropped. */
|
|
9
|
+
onChange?: (point: Point) => void;
|
|
10
|
+
tiles: MapTiles;
|
|
11
|
+
/** Where the map opens without a point. */
|
|
12
|
+
center: Point;
|
|
13
|
+
/** Zoom of the map on a point; the map opens wider without one. */
|
|
14
|
+
zoom: number;
|
|
15
|
+
readOnly?: boolean;
|
|
16
|
+
/** Accessible name of the map. */
|
|
17
|
+
label: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A Leaflet map with a marker on the point. Clicking the map or dragging the marker moves the
|
|
22
|
+
* point. Leaflet and its stylesheet load when the map first shows.
|
|
23
|
+
*/
|
|
24
|
+
export declare function LocationMap({ point, onChange, tiles, center, zoom, readOnly, label, className, }: LocationMapProps): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=LocationMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocationMap.d.ts","sourceRoot":"","sources":["../../src/location/LocationMap.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAkBxC,MAAM,WAAW,KAAK;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,QAAQ,CAAC;IAChB,2CAA2C;IAC3C,MAAM,EAAE,KAAK,CAAC;IACd,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAgB,EAChB,KAAK,EACL,SAAS,GACZ,EAAE,gBAAgB,+BAsGlB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import LocationField_module_default from "./LocationField.module.js";
|
|
2
|
+
import { LEAFLET_CSS } from "./leafletCss.js";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/location/LocationMap.tsx
|
|
6
|
+
var STYLE_ID = "panneau-leaflet-css";
|
|
7
|
+
/** Adds Leaflet's stylesheet to the document of the map, once. */
|
|
8
|
+
function injectStyles(document) {
|
|
9
|
+
if (document.getElementById(STYLE_ID) === null) {
|
|
10
|
+
const style = document.createElement("style");
|
|
11
|
+
style.id = STYLE_ID;
|
|
12
|
+
style.textContent = LEAFLET_CSS;
|
|
13
|
+
document.head.append(style);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A Leaflet map with a marker on the point. Clicking the map or dragging the marker moves the
|
|
18
|
+
* point. Leaflet and its stylesheet load when the map first shows.
|
|
19
|
+
*/
|
|
20
|
+
function LocationMap({ point, onChange, tiles, center, zoom, readOnly = false, label, className }) {
|
|
21
|
+
const container = useRef(null);
|
|
22
|
+
const map = useRef(null);
|
|
23
|
+
const latest = useRef({
|
|
24
|
+
onChange,
|
|
25
|
+
readOnly
|
|
26
|
+
});
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
latest.current = {
|
|
29
|
+
onChange,
|
|
30
|
+
readOnly
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const element = container.current;
|
|
35
|
+
if (element === null) return;
|
|
36
|
+
let cancelled = false;
|
|
37
|
+
import("leaflet").then((module) => {
|
|
38
|
+
if (cancelled) return;
|
|
39
|
+
const leaflet = module.default ?? module;
|
|
40
|
+
injectStyles(element.ownerDocument);
|
|
41
|
+
const instance = leaflet.map(element, { attributionControl: true });
|
|
42
|
+
leaflet.tileLayer(tiles.url, {
|
|
43
|
+
attribution: tiles.attribution,
|
|
44
|
+
maxZoom: tiles.maxZoom ?? 19
|
|
45
|
+
}).addTo(instance);
|
|
46
|
+
instance.on("click", (event) => {
|
|
47
|
+
if (!latest.current.readOnly) latest.current.onChange?.({
|
|
48
|
+
lat: event.latlng.lat,
|
|
49
|
+
lng: event.latlng.lng
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
map.current = {
|
|
53
|
+
leaflet,
|
|
54
|
+
map: instance,
|
|
55
|
+
marker: null
|
|
56
|
+
};
|
|
57
|
+
instance.setView(point ?? center, point !== null ? zoom : 2);
|
|
58
|
+
sync(point, false);
|
|
59
|
+
});
|
|
60
|
+
return () => {
|
|
61
|
+
cancelled = true;
|
|
62
|
+
map.current?.map.remove();
|
|
63
|
+
map.current = null;
|
|
64
|
+
};
|
|
65
|
+
}, [tiles.url]);
|
|
66
|
+
/** Puts the marker on the point, and the point in view. */
|
|
67
|
+
function sync(next, pan) {
|
|
68
|
+
const current = map.current;
|
|
69
|
+
if (current === null) return;
|
|
70
|
+
if (next === null) {
|
|
71
|
+
current.marker?.remove();
|
|
72
|
+
current.marker = null;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (current.marker === null) {
|
|
76
|
+
const marker = current.leaflet.marker(next, {
|
|
77
|
+
draggable: !latest.current.readOnly,
|
|
78
|
+
keyboard: false,
|
|
79
|
+
icon: current.leaflet.divIcon({
|
|
80
|
+
className: LocationField_module_default.marker,
|
|
81
|
+
html: `<span class="${LocationField_module_default.pin}"></span>`,
|
|
82
|
+
iconSize: [24, 24],
|
|
83
|
+
iconAnchor: [12, 29]
|
|
84
|
+
})
|
|
85
|
+
}).addTo(current.map);
|
|
86
|
+
marker.on("dragend", () => {
|
|
87
|
+
const position = marker.getLatLng();
|
|
88
|
+
latest.current.onChange?.({
|
|
89
|
+
lat: position.lat,
|
|
90
|
+
lng: position.lng
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
current.marker = marker;
|
|
94
|
+
} else current.marker.setLatLng(next);
|
|
95
|
+
if (pan && !current.map.getBounds().contains(next)) current.map.setView(next, Math.max(current.map.getZoom(), zoom));
|
|
96
|
+
}
|
|
97
|
+
const lat = point?.lat;
|
|
98
|
+
const lng = point?.lng;
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
sync(lat !== void 0 && lng !== void 0 ? {
|
|
101
|
+
lat,
|
|
102
|
+
lng
|
|
103
|
+
} : null, true);
|
|
104
|
+
}, [lat, lng]);
|
|
105
|
+
return /* @__PURE__ */ jsx("div", {
|
|
106
|
+
ref: container,
|
|
107
|
+
className: [LocationField_module_default.map, className].filter(Boolean).join(" "),
|
|
108
|
+
role: "application",
|
|
109
|
+
"aria-label": label
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { LocationMap };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=LocationMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocationMap.js","names":["styles"],"sources":["../../src/location/LocationMap.tsx"],"sourcesContent":["import type * as LeafletModule from 'leaflet';\nimport { useEffect, useRef } from 'react';\n\nimport styles from './LocationField.module.css';\nimport { LEAFLET_CSS } from './leafletCss';\nimport type { MapTiles } from './types';\n\ntype Leaflet = typeof LeafletModule;\ntype LeafletMap = LeafletModule.Map;\ntype LeafletMarker = LeafletModule.Marker;\n\nconst STYLE_ID = 'panneau-leaflet-css';\n\n/** Adds Leaflet's stylesheet to the document of the map, once. */\nfunction injectStyles(document: Document) {\n if (document.getElementById(STYLE_ID) === null) {\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = LEAFLET_CSS;\n document.head.append(style);\n }\n}\n\nexport interface Point {\n lat: number;\n lng: number;\n}\n\nexport interface LocationMapProps {\n point: Point | null;\n /** Called with the point clicked, or where the marker was dropped. */\n onChange?: (point: Point) => void;\n tiles: MapTiles;\n /** Where the map opens without a point. */\n center: Point;\n /** Zoom of the map on a point; the map opens wider without one. */\n zoom: number;\n readOnly?: boolean;\n /** Accessible name of the map. */\n label: string;\n className?: string;\n}\n\n/**\n * A Leaflet map with a marker on the point. Clicking the map or dragging the marker moves the\n * point. Leaflet and its stylesheet load when the map first shows.\n */\nexport function LocationMap({\n point,\n onChange,\n tiles,\n center,\n zoom,\n readOnly = false,\n label,\n className,\n}: LocationMapProps) {\n const container = useRef<HTMLDivElement>(null);\n const map = useRef<{ leaflet: Leaflet; map: LeafletMap; marker: LeafletMarker | null } | null>(\n null,\n );\n // The latest values, for the handlers of the map\n const latest = useRef({ onChange, readOnly });\n useEffect(() => {\n latest.current = { onChange, readOnly };\n });\n\n // Creates the map once Leaflet is loaded\n useEffect(() => {\n const element = container.current;\n if (element === null) {\n return undefined;\n }\n let cancelled = false;\n void import('leaflet').then((module) => {\n if (cancelled) {\n return;\n }\n const leaflet = ((module as { default?: Leaflet }).default ?? module) as Leaflet;\n injectStyles(element.ownerDocument);\n const instance = leaflet.map(element, { attributionControl: true });\n leaflet\n .tileLayer(tiles.url, {\n attribution: tiles.attribution,\n maxZoom: tiles.maxZoom ?? 19,\n })\n .addTo(instance);\n instance.on('click', (event) => {\n if (!latest.current.readOnly) {\n latest.current.onChange?.({ lat: event.latlng.lat, lng: event.latlng.lng });\n }\n });\n map.current = { leaflet, map: instance, marker: null };\n instance.setView(point ?? center, point !== null ? zoom : 2);\n sync(point, false);\n });\n return () => {\n cancelled = true;\n map.current?.map.remove();\n map.current = null;\n };\n // The map is made once; later changes go through the effect below\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tiles.url]);\n\n /** Puts the marker on the point, and the point in view. */\n function sync(next: Point | null, pan: boolean) {\n const current = map.current;\n if (current === null) {\n return;\n }\n if (next === null) {\n current.marker?.remove();\n current.marker = null;\n return;\n }\n if (current.marker === null) {\n const marker = current.leaflet\n .marker(next, {\n draggable: !latest.current.readOnly,\n keyboard: false,\n icon: current.leaflet.divIcon({\n className: styles.marker,\n // Leaflet places the icon with `transform`: the pin turns inside it\n html: `<span class=\"${styles.pin}\"></span>`,\n iconSize: [24, 24],\n iconAnchor: [12, 29],\n }),\n })\n .addTo(current.map);\n marker.on('dragend', () => {\n const position = marker.getLatLng();\n latest.current.onChange?.({ lat: position.lat, lng: position.lng });\n });\n current.marker = marker;\n } else {\n current.marker.setLatLng(next);\n }\n if (pan && !current.map.getBounds().contains(next)) {\n current.map.setView(next, Math.max(current.map.getZoom(), zoom));\n }\n }\n\n const lat = point?.lat;\n const lng = point?.lng;\n useEffect(() => {\n sync(lat !== undefined && lng !== undefined ? { lat, lng } : null, true);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [lat, lng]);\n\n return (\n <div\n ref={container}\n className={[styles.map, className].filter(Boolean).join(' ')}\n role=\"application\"\n aria-label={label}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { LocationField, LocationFieldEntry, type LocationFieldProps, type LocationValue, OPEN_STREET_MAP_TILES, isLocation, } from './LocationField';
|
|
2
|
+
export { LocationMap, type LocationMapProps, type Point } from './LocationMap';
|
|
3
|
+
export { createNominatimSource, type NominatimSourceOptions } from './nominatim';
|
|
4
|
+
export type { GeocodingResult, GeocodingSource, MapTiles, MapsConfig } from './types';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/location/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,aAAa,EACb,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,qBAAqB,EACrB,UAAU,GACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACjF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { LocationMap } from "./LocationMap.js";
|
|
2
|
+
import { LocationField, LocationFieldEntry, OPEN_STREET_MAP_TILES, isLocation } from "./LocationField.js";
|
|
3
|
+
import { createNominatimSource } from "./nominatim.js";
|
|
4
|
+
export { LocationField, LocationFieldEntry, LocationMap, OPEN_STREET_MAP_TILES, createNominatimSource, isLocation };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const LEAFLET_CSS = ".leaflet-pane,\r\n.leaflet-tile,\r\n.leaflet-marker-icon,\r\n.leaflet-marker-shadow,\r\n.leaflet-tile-container,\r\n.leaflet-pane > svg,\r\n.leaflet-pane > canvas,\r\n.leaflet-zoom-box,\r\n.leaflet-image-layer,\r\n.leaflet-layer {\r\n\tposition: absolute;\r\n\tleft: 0;\r\n\ttop: 0;\r\n\t}\r\n.leaflet-container {\r\n\toverflow: hidden;\r\n\t}\r\n.leaflet-tile,\r\n.leaflet-marker-icon,\r\n.leaflet-marker-shadow {\r\n\t-webkit-user-select: none;\r\n\t -moz-user-select: none;\r\n\t user-select: none;\r\n\t -webkit-user-drag: none;\r\n\t}\r\n.leaflet-tile::selection {\r\n\tbackground: transparent;\r\n}\r\n.leaflet-safari .leaflet-tile {\r\n\timage-rendering: -webkit-optimize-contrast;\r\n\t}\r\n.leaflet-safari .leaflet-tile-container {\r\n\twidth: 1600px;\r\n\theight: 1600px;\r\n\t-webkit-transform-origin: 0 0;\r\n\t}\r\n.leaflet-marker-icon,\r\n.leaflet-marker-shadow {\r\n\tdisplay: block;\r\n\t}\r\n.leaflet-container .leaflet-overlay-pane svg {\r\n\tmax-width: none !important;\r\n\tmax-height: none !important;\r\n\t}\r\n.leaflet-container .leaflet-marker-pane img,\r\n.leaflet-container .leaflet-shadow-pane img,\r\n.leaflet-container .leaflet-tile-pane img,\r\n.leaflet-container img.leaflet-image-layer,\r\n.leaflet-container .leaflet-tile {\r\n\tmax-width: none !important;\r\n\tmax-height: none !important;\r\n\twidth: auto;\r\n\tpadding: 0;\r\n\t}\r\n.leaflet-container img.leaflet-tile {\r\n\tmix-blend-mode: plus-lighter;\r\n}\r\n.leaflet-container.leaflet-touch-zoom {\r\n\t-ms-touch-action: pan-x pan-y;\r\n\ttouch-action: pan-x pan-y;\r\n\t}\r\n.leaflet-container.leaflet-touch-drag {\r\n\t-ms-touch-action: pinch-zoom;\r\n\ttouch-action: none;\r\n\ttouch-action: pinch-zoom;\r\n}\r\n.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {\r\n\t-ms-touch-action: none;\r\n\ttouch-action: none;\r\n}\r\n.leaflet-container {\r\n\t-webkit-tap-highlight-color: transparent;\r\n}\r\n.leaflet-container a {\r\n\t-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);\r\n}\r\n.leaflet-tile {\r\n\tfilter: inherit;\r\n\tvisibility: hidden;\r\n\t}\r\n.leaflet-tile-loaded {\r\n\tvisibility: inherit;\r\n\t}\r\n.leaflet-zoom-box {\r\n\twidth: 0;\r\n\theight: 0;\r\n\t-moz-box-sizing: border-box;\r\n\t box-sizing: border-box;\r\n\tz-index: 800;\r\n\t}\r\n.leaflet-overlay-pane svg {\r\n\t-moz-user-select: none;\r\n\t}\r\n.leaflet-pane { z-index: 400; }\r\n.leaflet-tile-pane { z-index: 200; }\r\n.leaflet-overlay-pane { z-index: 400; }\r\n.leaflet-shadow-pane { z-index: 500; }\r\n.leaflet-marker-pane { z-index: 600; }\r\n.leaflet-tooltip-pane { z-index: 650; }\r\n.leaflet-popup-pane { z-index: 700; }\r\n.leaflet-map-pane canvas { z-index: 100; }\r\n.leaflet-map-pane svg { z-index: 200; }\r\n.leaflet-vml-shape {\r\n\twidth: 1px;\r\n\theight: 1px;\r\n\t}\r\n.lvml {\r\n\tbehavior: url(#default#VML);\r\n\tdisplay: inline-block;\r\n\tposition: absolute;\r\n\t}\r\n.leaflet-control {\r\n\tposition: relative;\r\n\tz-index: 800;\r\n\tpointer-events: visiblePainted; \r\n\tpointer-events: auto;\r\n\t}\r\n.leaflet-top,\r\n.leaflet-bottom {\r\n\tposition: absolute;\r\n\tz-index: 1000;\r\n\tpointer-events: none;\r\n\t}\r\n.leaflet-top {\r\n\ttop: 0;\r\n\t}\r\n.leaflet-right {\r\n\tright: 0;\r\n\t}\r\n.leaflet-bottom {\r\n\tbottom: 0;\r\n\t}\r\n.leaflet-left {\r\n\tleft: 0;\r\n\t}\r\n.leaflet-control {\r\n\tfloat: left;\r\n\tclear: both;\r\n\t}\r\n.leaflet-right .leaflet-control {\r\n\tfloat: right;\r\n\t}\r\n.leaflet-top .leaflet-control {\r\n\tmargin-top: 10px;\r\n\t}\r\n.leaflet-bottom .leaflet-control {\r\n\tmargin-bottom: 10px;\r\n\t}\r\n.leaflet-left .leaflet-control {\r\n\tmargin-left: 10px;\r\n\t}\r\n.leaflet-right .leaflet-control {\r\n\tmargin-right: 10px;\r\n\t}\r\n.leaflet-fade-anim .leaflet-popup {\r\n\topacity: 0;\r\n\t-webkit-transition: opacity 0.2s linear;\r\n\t -moz-transition: opacity 0.2s linear;\r\n\t transition: opacity 0.2s linear;\r\n\t}\r\n.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {\r\n\topacity: 1;\r\n\t}\r\n.leaflet-zoom-animated {\r\n\t-webkit-transform-origin: 0 0;\r\n\t -ms-transform-origin: 0 0;\r\n\t transform-origin: 0 0;\r\n\t}\r\nsvg.leaflet-zoom-animated {\r\n\twill-change: transform;\r\n}\r\n.leaflet-zoom-anim .leaflet-zoom-animated {\r\n\t-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);\r\n\t -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);\r\n\t transition: transform 0.25s cubic-bezier(0,0,0.25,1);\r\n\t}\r\n.leaflet-zoom-anim .leaflet-tile,\r\n.leaflet-pan-anim .leaflet-tile {\r\n\t-webkit-transition: none;\r\n\t -moz-transition: none;\r\n\t transition: none;\r\n\t}\r\n.leaflet-zoom-anim .leaflet-zoom-hide {\r\n\tvisibility: hidden;\r\n\t}\r\n.leaflet-interactive {\r\n\tcursor: pointer;\r\n\t}\r\n.leaflet-grab {\r\n\tcursor: -webkit-grab;\r\n\tcursor: -moz-grab;\r\n\tcursor: grab;\r\n\t}\r\n.leaflet-crosshair,\r\n.leaflet-crosshair .leaflet-interactive {\r\n\tcursor: crosshair;\r\n\t}\r\n.leaflet-popup-pane,\r\n.leaflet-control {\r\n\tcursor: auto;\r\n\t}\r\n.leaflet-dragging .leaflet-grab,\r\n.leaflet-dragging .leaflet-grab .leaflet-interactive,\r\n.leaflet-dragging .leaflet-marker-draggable {\r\n\tcursor: move;\r\n\tcursor: -webkit-grabbing;\r\n\tcursor: -moz-grabbing;\r\n\tcursor: grabbing;\r\n\t}\r\n.leaflet-marker-icon,\r\n.leaflet-marker-shadow,\r\n.leaflet-image-layer,\r\n.leaflet-pane > svg path,\r\n.leaflet-tile-container {\r\n\tpointer-events: none;\r\n\t}\r\n.leaflet-marker-icon.leaflet-interactive,\r\n.leaflet-image-layer.leaflet-interactive,\r\n.leaflet-pane > svg path.leaflet-interactive,\r\nsvg.leaflet-image-layer.leaflet-interactive path {\r\n\tpointer-events: visiblePainted; \r\n\tpointer-events: auto;\r\n\t}\r\n.leaflet-container {\r\n\tbackground: #ddd;\r\n\toutline-offset: 1px;\r\n\t}\r\n.leaflet-container a {\r\n\tcolor: #0078A8;\r\n\t}\r\n.leaflet-zoom-box {\r\n\tborder: 2px dotted #38f;\r\n\tbackground: rgba(255,255,255,0.5);\r\n\t}\r\n.leaflet-container {\r\n\tfont-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\r\n\tfont-size: 12px;\r\n\tfont-size: 0.75rem;\r\n\tline-height: 1.5;\r\n\t}\r\n.leaflet-bar {\r\n\tbox-shadow: 0 1px 5px rgba(0,0,0,0.65);\r\n\tborder-radius: 4px;\r\n\t}\r\n.leaflet-bar a {\r\n\tbackground-color: #fff;\r\n\tborder-bottom: 1px solid #ccc;\r\n\twidth: 26px;\r\n\theight: 26px;\r\n\tline-height: 26px;\r\n\tdisplay: block;\r\n\ttext-align: center;\r\n\ttext-decoration: none;\r\n\tcolor: black;\r\n\t}\r\n.leaflet-bar a,\r\n.leaflet-control-layers-toggle {\r\n\tbackground-position: 50% 50%;\r\n\tbackground-repeat: no-repeat;\r\n\tdisplay: block;\r\n\t}\r\n.leaflet-bar a:hover,\r\n.leaflet-bar a:focus {\r\n\tbackground-color: #f4f4f4;\r\n\t}\r\n.leaflet-bar a:first-child {\r\n\tborder-top-left-radius: 4px;\r\n\tborder-top-right-radius: 4px;\r\n\t}\r\n.leaflet-bar a:last-child {\r\n\tborder-bottom-left-radius: 4px;\r\n\tborder-bottom-right-radius: 4px;\r\n\tborder-bottom: none;\r\n\t}\r\n.leaflet-bar a.leaflet-disabled {\r\n\tcursor: default;\r\n\tbackground-color: #f4f4f4;\r\n\tcolor: #bbb;\r\n\t}\r\n.leaflet-touch .leaflet-bar a {\r\n\twidth: 30px;\r\n\theight: 30px;\r\n\tline-height: 30px;\r\n\t}\r\n.leaflet-touch .leaflet-bar a:first-child {\r\n\tborder-top-left-radius: 2px;\r\n\tborder-top-right-radius: 2px;\r\n\t}\r\n.leaflet-touch .leaflet-bar a:last-child {\r\n\tborder-bottom-left-radius: 2px;\r\n\tborder-bottom-right-radius: 2px;\r\n\t}\r\n.leaflet-control-zoom-in,\r\n.leaflet-control-zoom-out {\r\n\tfont: bold 18px 'Lucida Console', Monaco, monospace;\r\n\ttext-indent: 1px;\r\n\t}\r\n.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {\r\n\tfont-size: 22px;\r\n\t}\r\n.leaflet-control-layers {\r\n\tbox-shadow: 0 1px 5px rgba(0,0,0,0.4);\r\n\tbackground: #fff;\r\n\tborder-radius: 5px;\r\n\t}\r\n.leaflet-control-layers-toggle {\r\n\tbackground-image: url(images/layers.png);\r\n\twidth: 36px;\r\n\theight: 36px;\r\n\t}\r\n.leaflet-retina .leaflet-control-layers-toggle {\r\n\tbackground-image: url(images/layers-2x.png);\r\n\tbackground-size: 26px 26px;\r\n\t}\r\n.leaflet-touch .leaflet-control-layers-toggle {\r\n\twidth: 44px;\r\n\theight: 44px;\r\n\t}\r\n.leaflet-control-layers .leaflet-control-layers-list,\r\n.leaflet-control-layers-expanded .leaflet-control-layers-toggle {\r\n\tdisplay: none;\r\n\t}\r\n.leaflet-control-layers-expanded .leaflet-control-layers-list {\r\n\tdisplay: block;\r\n\tposition: relative;\r\n\t}\r\n.leaflet-control-layers-expanded {\r\n\tpadding: 6px 10px 6px 6px;\r\n\tcolor: #333;\r\n\tbackground: #fff;\r\n\t}\r\n.leaflet-control-layers-scrollbar {\r\n\toverflow-y: scroll;\r\n\toverflow-x: hidden;\r\n\tpadding-right: 5px;\r\n\t}\r\n.leaflet-control-layers-selector {\r\n\tmargin-top: 2px;\r\n\tposition: relative;\r\n\ttop: 1px;\r\n\t}\r\n.leaflet-control-layers label {\r\n\tdisplay: block;\r\n\tfont-size: 13px;\r\n\tfont-size: 1.08333em;\r\n\t}\r\n.leaflet-control-layers-separator {\r\n\theight: 0;\r\n\tborder-top: 1px solid #ddd;\r\n\tmargin: 5px -10px 5px -6px;\r\n\t}\r\n.leaflet-default-icon-path { \r\n\tbackground-image: url(images/marker-icon.png);\r\n\t}\r\n.leaflet-container .leaflet-control-attribution {\r\n\tbackground: #fff;\r\n\tbackground: rgba(255, 255, 255, 0.8);\r\n\tmargin: 0;\r\n\t}\r\n.leaflet-control-attribution,\r\n.leaflet-control-scale-line {\r\n\tpadding: 0 5px;\r\n\tcolor: #333;\r\n\tline-height: 1.4;\r\n\t}\r\n.leaflet-control-attribution a {\r\n\ttext-decoration: none;\r\n\t}\r\n.leaflet-control-attribution a:hover,\r\n.leaflet-control-attribution a:focus {\r\n\ttext-decoration: underline;\r\n\t}\r\n.leaflet-attribution-flag {\r\n\tdisplay: inline !important;\r\n\tvertical-align: baseline !important;\r\n\twidth: 1em;\r\n\theight: 0.6669em;\r\n\t}\r\n.leaflet-left .leaflet-control-scale {\r\n\tmargin-left: 5px;\r\n\t}\r\n.leaflet-bottom .leaflet-control-scale {\r\n\tmargin-bottom: 5px;\r\n\t}\r\n.leaflet-control-scale-line {\r\n\tborder: 2px solid #777;\r\n\tborder-top: none;\r\n\tline-height: 1.1;\r\n\tpadding: 2px 5px 1px;\r\n\twhite-space: nowrap;\r\n\t-moz-box-sizing: border-box;\r\n\t box-sizing: border-box;\r\n\tbackground: rgba(255, 255, 255, 0.8);\r\n\ttext-shadow: 1px 1px #fff;\r\n\t}\r\n.leaflet-control-scale-line:not(:first-child) {\r\n\tborder-top: 2px solid #777;\r\n\tborder-bottom: none;\r\n\tmargin-top: -2px;\r\n\t}\r\n.leaflet-control-scale-line:not(:first-child):not(:last-child) {\r\n\tborder-bottom: 2px solid #777;\r\n\t}\r\n.leaflet-touch .leaflet-control-attribution,\r\n.leaflet-touch .leaflet-control-layers,\r\n.leaflet-touch .leaflet-bar {\r\n\tbox-shadow: none;\r\n\t}\r\n.leaflet-touch .leaflet-control-layers,\r\n.leaflet-touch .leaflet-bar {\r\n\tborder: 2px solid rgba(0,0,0,0.2);\r\n\tbackground-clip: padding-box;\r\n\t}\r\n.leaflet-popup {\r\n\tposition: absolute;\r\n\ttext-align: center;\r\n\tmargin-bottom: 20px;\r\n\t}\r\n.leaflet-popup-content-wrapper {\r\n\tpadding: 1px;\r\n\ttext-align: left;\r\n\tborder-radius: 12px;\r\n\t}\r\n.leaflet-popup-content {\r\n\tmargin: 13px 24px 13px 20px;\r\n\tline-height: 1.3;\r\n\tfont-size: 13px;\r\n\tfont-size: 1.08333em;\r\n\tmin-height: 1px;\r\n\t}\r\n.leaflet-popup-content p {\r\n\tmargin: 17px 0;\r\n\tmargin: 1.3em 0;\r\n\t}\r\n.leaflet-popup-tip-container {\r\n\twidth: 40px;\r\n\theight: 20px;\r\n\tposition: absolute;\r\n\tleft: 50%;\r\n\tmargin-top: -1px;\r\n\tmargin-left: -20px;\r\n\toverflow: hidden;\r\n\tpointer-events: none;\r\n\t}\r\n.leaflet-popup-tip {\r\n\twidth: 17px;\r\n\theight: 17px;\r\n\tpadding: 1px;\r\n\tmargin: -10px auto 0;\r\n\tpointer-events: auto;\r\n\t-webkit-transform: rotate(45deg);\r\n\t -moz-transform: rotate(45deg);\r\n\t -ms-transform: rotate(45deg);\r\n\t transform: rotate(45deg);\r\n\t}\r\n.leaflet-popup-content-wrapper,\r\n.leaflet-popup-tip {\r\n\tbackground: white;\r\n\tcolor: #333;\r\n\tbox-shadow: 0 3px 14px rgba(0,0,0,0.4);\r\n\t}\r\n.leaflet-container a.leaflet-popup-close-button {\r\n\tposition: absolute;\r\n\ttop: 0;\r\n\tright: 0;\r\n\tborder: none;\r\n\ttext-align: center;\r\n\twidth: 24px;\r\n\theight: 24px;\r\n\tfont: 16px/24px Tahoma, Verdana, sans-serif;\r\n\tcolor: #757575;\r\n\ttext-decoration: none;\r\n\tbackground: transparent;\r\n\t}\r\n.leaflet-container a.leaflet-popup-close-button:hover,\r\n.leaflet-container a.leaflet-popup-close-button:focus {\r\n\tcolor: #585858;\r\n\t}\r\n.leaflet-popup-scrolled {\r\n\toverflow: auto;\r\n\t}\r\n.leaflet-oldie .leaflet-popup-content-wrapper {\r\n\t-ms-zoom: 1;\r\n\t}\r\n.leaflet-oldie .leaflet-popup-tip {\r\n\twidth: 24px;\r\n\tmargin: 0 auto;\r\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)\";\r\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);\r\n\t}\r\n.leaflet-oldie .leaflet-control-zoom,\r\n.leaflet-oldie .leaflet-control-layers,\r\n.leaflet-oldie .leaflet-popup-content-wrapper,\r\n.leaflet-oldie .leaflet-popup-tip {\r\n\tborder: 1px solid #999;\r\n\t}\r\n.leaflet-div-icon {\r\n\tbackground: #fff;\r\n\tborder: 1px solid #666;\r\n\t}\r\n.leaflet-tooltip {\r\n\tposition: absolute;\r\n\tpadding: 6px;\r\n\tbackground-color: #fff;\r\n\tborder: 1px solid #fff;\r\n\tborder-radius: 3px;\r\n\tcolor: #222;\r\n\twhite-space: nowrap;\r\n\t-webkit-user-select: none;\r\n\t-moz-user-select: none;\r\n\t-ms-user-select: none;\r\n\tuser-select: none;\r\n\tpointer-events: none;\r\n\tbox-shadow: 0 1px 3px rgba(0,0,0,0.4);\r\n\t}\r\n.leaflet-tooltip.leaflet-interactive {\r\n\tcursor: pointer;\r\n\tpointer-events: auto;\r\n\t}\r\n.leaflet-tooltip-top:before,\r\n.leaflet-tooltip-bottom:before,\r\n.leaflet-tooltip-left:before,\r\n.leaflet-tooltip-right:before {\r\n\tposition: absolute;\r\n\tpointer-events: none;\r\n\tborder: 6px solid transparent;\r\n\tbackground: transparent;\r\n\tcontent: \"\";\r\n\t}\r\n.leaflet-tooltip-bottom {\r\n\tmargin-top: 6px;\r\n}\r\n.leaflet-tooltip-top {\r\n\tmargin-top: -6px;\r\n}\r\n.leaflet-tooltip-bottom:before,\r\n.leaflet-tooltip-top:before {\r\n\tleft: 50%;\r\n\tmargin-left: -6px;\r\n\t}\r\n.leaflet-tooltip-top:before {\r\n\tbottom: 0;\r\n\tmargin-bottom: -12px;\r\n\tborder-top-color: #fff;\r\n\t}\r\n.leaflet-tooltip-bottom:before {\r\n\ttop: 0;\r\n\tmargin-top: -12px;\r\n\tmargin-left: -6px;\r\n\tborder-bottom-color: #fff;\r\n\t}\r\n.leaflet-tooltip-left {\r\n\tmargin-left: -6px;\r\n}\r\n.leaflet-tooltip-right {\r\n\tmargin-left: 6px;\r\n}\r\n.leaflet-tooltip-left:before,\r\n.leaflet-tooltip-right:before {\r\n\ttop: 50%;\r\n\tmargin-top: -6px;\r\n\t}\r\n.leaflet-tooltip-left:before {\r\n\tright: 0;\r\n\tmargin-right: -12px;\r\n\tborder-left-color: #fff;\r\n\t}\r\n.leaflet-tooltip-right:before {\r\n\tleft: 0;\r\n\tmargin-left: -12px;\r\n\tborder-right-color: #fff;\r\n\t}\r\n@media print {\r\n\t.leaflet-control {\r\n\t\t-webkit-print-color-adjust: exact;\r\n\t\tprint-color-adjust: exact;\r\n\t\t}\r\n\t}";
|
|
2
|
+
//# sourceMappingURL=leafletCss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leafletCss.d.ts","sourceRoot":"","sources":["../../src/location/leafletCss.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,gqdACqod,CAAC"}
|