@panneau/fields 5.0.0-alpha.5 → 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 +34 -0
- 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 +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -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/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/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/context.d.ts +13 -3
- package/dist/shared/context.d.ts.map +1 -1
- package/dist/shared/context.js +27 -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/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,125 @@
|
|
|
1
|
+
import { getFieldProps, getSetting, isNumber } from "../shared/entry.js";
|
|
2
|
+
import { messages } from "../shared/messages.js";
|
|
3
|
+
import JsonField_module_default from "./JsonField.module.js";
|
|
4
|
+
import { c } from "react/compiler-runtime";
|
|
5
|
+
import { TextArea, usePanneauIntl } from "@panneau/ui";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region src/json/JsonField.tsx
|
|
9
|
+
/** The text of a value: indented JSON, or the text that doesn't parse as it is. */
|
|
10
|
+
function toText(value) {
|
|
11
|
+
if (value === null || value === void 0) return "";
|
|
12
|
+
return typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
13
|
+
}
|
|
14
|
+
/** The value of a text: what it parses to when it is an object or an array, or the text itself. */
|
|
15
|
+
function parseJson(text) {
|
|
16
|
+
if (text.trim() === "") return {
|
|
17
|
+
value: null,
|
|
18
|
+
error: null
|
|
19
|
+
};
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(text);
|
|
22
|
+
if (parsed !== null && typeof parsed === "object") return {
|
|
23
|
+
value: parsed,
|
|
24
|
+
error: null
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
value: text,
|
|
28
|
+
error: "an object or an array"
|
|
29
|
+
};
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return {
|
|
32
|
+
value: text,
|
|
33
|
+
error: error instanceof Error ? error.message : String(error)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Structured data edited as JSON: an object or an array. While the text doesn't parse, the value
|
|
39
|
+
* is the text itself, which the `json` rule refuses, so the form can't be saved with it. The text
|
|
40
|
+
* is indented again on blur once it parses.
|
|
41
|
+
*/
|
|
42
|
+
function JsonField({ value, onChange, onBlur, errors = [], rows = 8, disabled, readOnly, required, ...props }) {
|
|
43
|
+
const intl = usePanneauIntl();
|
|
44
|
+
const [state, setState] = useState(() => ({
|
|
45
|
+
value,
|
|
46
|
+
text: toText(value)
|
|
47
|
+
}));
|
|
48
|
+
if (state.value !== value) setState({
|
|
49
|
+
value,
|
|
50
|
+
text: toText(value)
|
|
51
|
+
});
|
|
52
|
+
const { text } = state;
|
|
53
|
+
const { error } = parseJson(text);
|
|
54
|
+
const shown = error !== null && errors.length === 0 ? [intl.formatMessage(messages.jsonInvalid, { error })] : errors;
|
|
55
|
+
return /* @__PURE__ */ jsx(TextArea, {
|
|
56
|
+
...props,
|
|
57
|
+
value: text,
|
|
58
|
+
onChange: (next) => {
|
|
59
|
+
const parsed = parseJson(next).value;
|
|
60
|
+
setState({
|
|
61
|
+
value: parsed,
|
|
62
|
+
text: next
|
|
63
|
+
});
|
|
64
|
+
onChange?.(parsed);
|
|
65
|
+
},
|
|
66
|
+
onBlur: () => {
|
|
67
|
+
if (value !== null && value !== void 0 && typeof value !== "string") setState({
|
|
68
|
+
value,
|
|
69
|
+
text: toText(value)
|
|
70
|
+
});
|
|
71
|
+
onBlur?.();
|
|
72
|
+
},
|
|
73
|
+
errors: shown,
|
|
74
|
+
rows,
|
|
75
|
+
spellCheck: "false",
|
|
76
|
+
textAreaClassName: JsonField_module_default.code,
|
|
77
|
+
isDisabled: disabled,
|
|
78
|
+
isReadOnly: readOnly,
|
|
79
|
+
isRequired: required
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/** The `json` type: an object or an array, with setting `rows`. */
|
|
83
|
+
function JsonFieldEntry(props) {
|
|
84
|
+
const $ = c(11);
|
|
85
|
+
let t0;
|
|
86
|
+
if ($[0] !== props.field) {
|
|
87
|
+
t0 = getSetting(props.field, "rows", isNumber);
|
|
88
|
+
$[0] = props.field;
|
|
89
|
+
$[1] = t0;
|
|
90
|
+
} else t0 = $[1];
|
|
91
|
+
const rows = t0;
|
|
92
|
+
const { value } = props;
|
|
93
|
+
let t1;
|
|
94
|
+
if ($[2] !== props) {
|
|
95
|
+
t1 = getFieldProps(props);
|
|
96
|
+
$[2] = props;
|
|
97
|
+
$[3] = t1;
|
|
98
|
+
} else t1 = $[3];
|
|
99
|
+
const t2 = typeof value === "string" || value !== null && typeof value === "object" ? value : null;
|
|
100
|
+
let t3;
|
|
101
|
+
if ($[4] !== rows) {
|
|
102
|
+
t3 = rows !== void 0 ? { rows } : {};
|
|
103
|
+
$[4] = rows;
|
|
104
|
+
$[5] = t3;
|
|
105
|
+
} else t3 = $[5];
|
|
106
|
+
let t4;
|
|
107
|
+
if ($[6] !== props.onChange || $[7] !== t1 || $[8] !== t2 || $[9] !== t3) {
|
|
108
|
+
t4 = /* @__PURE__ */ jsx(JsonField, {
|
|
109
|
+
...t1,
|
|
110
|
+
value: t2,
|
|
111
|
+
onChange: props.onChange,
|
|
112
|
+
...t3
|
|
113
|
+
});
|
|
114
|
+
$[6] = props.onChange;
|
|
115
|
+
$[7] = t1;
|
|
116
|
+
$[8] = t2;
|
|
117
|
+
$[9] = t3;
|
|
118
|
+
$[10] = t4;
|
|
119
|
+
} else t4 = $[10];
|
|
120
|
+
return t4;
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
export { JsonField, JsonFieldEntry, parseJson };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=JsonField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonField.js","names":["styles","_c"],"sources":["../../src/json/JsonField.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { TextArea, usePanneauIntl } from '@panneau/ui';\n\nimport { getFieldProps, getSetting, isNumber } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport styles from './JsonField.module.css';\n\n/** The value of a `json` field: an object or an array, or the text while it doesn't parse. */\nexport type JsonValue = Record<string, unknown> | unknown[] | string;\n\nexport interface JsonFieldProps extends FieldProps<JsonValue> {\n placeholder?: string;\n /** Visible lines. Defaults to 8. */\n rows?: number;\n}\n\n/** The text of a value: indented JSON, or the text that doesn't parse as it is. */\nfunction toText(value: JsonValue | null | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n return typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n}\n\n/** The value of a text: what it parses to when it is an object or an array, or the text itself. */\nexport function parseJson(text: string): { value: JsonValue | null; error: string | null } {\n if (text.trim() === '') {\n return { value: null, error: null };\n }\n try {\n const parsed: unknown = JSON.parse(text);\n if (parsed !== null && typeof parsed === 'object') {\n return { value: parsed as JsonValue, error: null };\n }\n return { value: text, error: 'an object or an array' };\n } catch (error) {\n return { value: text, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\n/**\n * Structured data edited as JSON: an object or an array. While the text doesn't parse, the value\n * is the text itself, which the `json` rule refuses, so the form can't be saved with it. The text\n * is indented again on blur once it parses.\n */\nexport function JsonField({\n value,\n onChange,\n onBlur,\n errors = [],\n rows = 8,\n disabled,\n readOnly,\n required,\n ...props\n}: JsonFieldProps) {\n const intl = usePanneauIntl();\n // The text as typed: a value that comes back from the form keeps its text, and a value set\n // from outside (a reset, a reload) shows its JSON\n const [state, setState] = useState(() => ({ value, text: toText(value) }));\n if (state.value !== value) {\n setState({ value, text: toText(value) });\n }\n const { text } = state;\n const { error } = parseJson(text);\n // The parser's message, until the form shows the rule's\n const shown =\n error !== null && errors.length === 0\n ? [intl.formatMessage(messages.jsonInvalid, { error })]\n : errors;\n return (\n <TextArea\n {...props}\n value={text}\n onChange={(next) => {\n const parsed = parseJson(next).value;\n setState({ value: parsed, text: next });\n onChange?.(parsed);\n }}\n onBlur={() => {\n // Indent the text once it parses\n if (value !== null && value !== undefined && typeof value !== 'string') {\n setState({ value, text: toText(value) });\n }\n onBlur?.();\n }}\n errors={shown}\n rows={rows}\n spellCheck=\"false\"\n textAreaClassName={styles.code}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `json` type: an object or an array, with setting `rows`. */\nexport function JsonFieldEntry(props: FieldEntryProps) {\n const rows = getSetting(props.field, 'rows', isNumber);\n const { value } = props;\n return (\n <JsonField\n {...getFieldProps(props)}\n value={\n typeof value === 'string' || (value !== null && typeof value === 'object')\n ? (value as JsonValue)\n : null\n }\n onChange={props.onChange}\n {...(rows !== undefined ? { rows } : {})}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./JsonField.css";
|
|
2
|
+
//#region src/json/JsonField.module.css
|
|
3
|
+
var code = "panneau-json-field-code";
|
|
4
|
+
var JsonField_module_default = { code };
|
|
5
|
+
//#endregion
|
|
6
|
+
export { code, JsonField_module_default as default };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=JsonField.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonField.module.js","names":[],"sources":["../../src/json/JsonField.module.css"],"sourcesContent":["/* JSON reads in a monospace font, without wrapping long lines. */\n.code {\n font-family: var(--panneau-font-family-mono);\n font-size: var(--panneau-font-size-sm);\n white-space: pre;\n tab-size: 2;\n}\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/json/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,SAAS,EACT,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,SAAS,GACZ,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JsonField, JsonFieldEntry, parseJson } from "./JsonField.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* The search, the map, then the coordinates and the address. */
|
|
2
|
+
.panneau-location-field-location {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: var(--panneau-space-2);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.panneau-location-field-map {
|
|
9
|
+
position: relative;
|
|
10
|
+
z-index: 0;
|
|
11
|
+
height: 16rem;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
14
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border-control);
|
|
15
|
+
border-radius: var(--panneau-radius-md);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.panneau-location-field-map:focus-visible {
|
|
19
|
+
outline: var(--panneau-focus-width) solid var(--panneau-color-focus);
|
|
20
|
+
outline-offset: 1px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* A pin: a round head pointing down at the point. */
|
|
24
|
+
.panneau-location-field-marker {
|
|
25
|
+
background: none;
|
|
26
|
+
border: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.panneau-location-field-pin {
|
|
30
|
+
display: block;
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
background-color: var(--panneau-color-accent);
|
|
35
|
+
border: 2px solid var(--panneau-color-surface);
|
|
36
|
+
border-radius: 50% 50% 50% 0;
|
|
37
|
+
box-shadow: var(--panneau-shadow-sm);
|
|
38
|
+
rotate: -45deg;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.panneau-location-field-coordinates {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-wrap: wrap;
|
|
44
|
+
align-items: flex-end;
|
|
45
|
+
gap: var(--panneau-space-2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.panneau-location-field-coordinate {
|
|
49
|
+
flex: 1 1 8rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.panneau-location-field-remove {
|
|
53
|
+
flex: none;
|
|
54
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LocationValue } from '@panneau/protocol';
|
|
2
|
+
import type { FieldEntryProps, FieldProps } from '../shared/types';
|
|
3
|
+
import { type Point } from './LocationMap';
|
|
4
|
+
import type { GeocodingSource, MapTiles } from './types';
|
|
5
|
+
export type { LocationValue };
|
|
6
|
+
/** OpenStreetMap's standard tiles: fine for an admin panel, with their credit. */
|
|
7
|
+
export declare const OPEN_STREET_MAP_TILES: MapTiles;
|
|
8
|
+
export interface LocationFieldProps extends FieldProps<LocationValue> {
|
|
9
|
+
/** The address search. Defaults to that of the `FieldsProvider`; without one, there is none. */
|
|
10
|
+
geocoding?: GeocodingSource | null;
|
|
11
|
+
/** The tiles of the map. Defaults to those of the `FieldsProvider`, or OpenStreetMap's. */
|
|
12
|
+
tiles?: MapTiles;
|
|
13
|
+
/** Where the map opens without a point. Defaults to the whole world. */
|
|
14
|
+
center?: Point;
|
|
15
|
+
/** Zoom of the map on a point. Defaults to 15. */
|
|
16
|
+
zoom?: number;
|
|
17
|
+
}
|
|
18
|
+
/** Whether a value is a point. */
|
|
19
|
+
export declare function isLocation(value: unknown): value is LocationValue;
|
|
20
|
+
/**
|
|
21
|
+
* A point on a map, and its address. Clicking the map or dragging the marker places the point,
|
|
22
|
+
* and its latitude and longitude can be typed. With an address search, a place found sets the
|
|
23
|
+
* point and the address; with a reverse search, placing a point fills an empty address.
|
|
24
|
+
*/
|
|
25
|
+
export declare function LocationField({ value, onChange, onBlur, geocoding: geocodingProp, tiles: tilesProp, center, zoom, label, description, errors, disabled, readOnly, required, className, }: LocationFieldProps): import("react").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* The `location` type: settings `zoom`, `center` (`{ "lat", "lng" }`, where the map opens without
|
|
28
|
+
* a point) and `tiles` (`{ "url", "attribution" }`), over the maps of the `FieldsProvider`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function LocationFieldEntry(props: FieldEntryProps): import("react").JSX.Element;
|
|
31
|
+
//# sourceMappingURL=LocationField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocationField.d.ts","sourceRoot":"","sources":["../../src/location/LocationField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAavD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAmB,eAAe,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE1E,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,EAAE,QAKnC,CAAC;AAKF,MAAM,WAAW,kBAAmB,SAAQ,UAAU,CAAC,aAAa,CAAC;IACjE,gGAAgG;IAChG,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,2FAA2F;IAC3F,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,wEAAwE;IACxE,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kCAAkC;AAClC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAOjE;AAkCD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,SAAS,EAChB,MAA4B,EAC5B,IAAS,EACT,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,GACZ,EAAE,kBAAkB,+BAyKpB;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,+BAwBxD"}
|
|
@@ -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":"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"}
|
|
@@ -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
|