@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.
Files changed (118) hide show
  1. package/README.md +67 -21
  2. package/dist/duration/DurationField.css +11 -0
  3. package/dist/duration/DurationField.d.ts +26 -0
  4. package/dist/duration/DurationField.d.ts.map +1 -0
  5. package/dist/duration/DurationField.js +129 -0
  6. package/dist/duration/DurationField.js.map +1 -0
  7. package/dist/duration/DurationField.module.js +12 -0
  8. package/dist/duration/DurationField.module.js.map +1 -0
  9. package/dist/duration/index.d.ts +2 -0
  10. package/dist/duration/index.d.ts.map +1 -0
  11. package/dist/duration/index.js +1 -0
  12. package/dist/embed/EmbedField.css +60 -0
  13. package/dist/embed/EmbedField.d.ts +20 -0
  14. package/dist/embed/EmbedField.d.ts.map +1 -0
  15. package/dist/embed/EmbedField.js +130 -0
  16. package/dist/embed/EmbedField.js.map +1 -0
  17. package/dist/embed/EmbedField.module.js +22 -0
  18. package/dist/embed/EmbedField.module.js.map +1 -0
  19. package/dist/embed/index.d.ts +3 -0
  20. package/dist/embed/index.d.ts.map +1 -0
  21. package/dist/embed/index.js +3 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +4 -1
  25. package/dist/json/JsonField.css +7 -0
  26. package/dist/json/JsonField.d.ts +22 -0
  27. package/dist/json/JsonField.d.ts.map +1 -0
  28. package/dist/json/JsonField.js +125 -0
  29. package/dist/json/JsonField.js.map +1 -0
  30. package/dist/json/JsonField.module.js +8 -0
  31. package/dist/json/JsonField.module.js.map +1 -0
  32. package/dist/json/index.d.ts +2 -0
  33. package/dist/json/index.d.ts.map +1 -0
  34. package/dist/json/index.js +1 -0
  35. package/dist/localized/LocalizedField.d.ts.map +1 -1
  36. package/dist/localized/LocalizedField.js +1 -0
  37. package/dist/localized/LocalizedField.js.map +1 -1
  38. package/dist/location/LocationField.css +54 -0
  39. package/dist/location/LocationField.d.ts +31 -0
  40. package/dist/location/LocationField.d.ts.map +1 -0
  41. package/dist/location/LocationField.js +350 -0
  42. package/dist/location/LocationField.js.map +1 -0
  43. package/dist/location/LocationField.module.js +22 -0
  44. package/dist/location/LocationField.module.js.map +1 -0
  45. package/dist/location/LocationMap.d.ts +25 -0
  46. package/dist/location/LocationMap.d.ts.map +1 -0
  47. package/dist/location/LocationMap.js +115 -0
  48. package/dist/location/LocationMap.js.map +1 -0
  49. package/dist/location/index.d.ts +5 -0
  50. package/dist/location/index.d.ts.map +1 -0
  51. package/dist/location/index.js +4 -0
  52. package/dist/location/leafletCss.d.ts +2 -0
  53. package/dist/location/leafletCss.d.ts.map +1 -0
  54. package/dist/location/leafletCss.js +6 -0
  55. package/dist/location/leafletCss.js.map +1 -0
  56. package/dist/location/nominatim.d.ts +17 -0
  57. package/dist/location/nominatim.d.ts.map +1 -0
  58. package/dist/location/nominatim.js +50 -0
  59. package/dist/location/nominatim.js.map +1 -0
  60. package/dist/location/types.d.ts +40 -0
  61. package/dist/location/types.d.ts.map +1 -0
  62. package/dist/range/RangeField.d.ts +22 -0
  63. package/dist/range/RangeField.d.ts.map +1 -0
  64. package/dist/range/RangeField.js +132 -0
  65. package/dist/range/RangeField.js.map +1 -0
  66. package/dist/range/index.d.ts +2 -0
  67. package/dist/range/index.d.ts.map +1 -0
  68. package/dist/range/index.js +1 -0
  69. package/dist/relation/RelationField.d.ts.map +1 -1
  70. package/dist/relation/RelationField.js +24 -24
  71. package/dist/relation/RelationField.js.map +1 -1
  72. package/dist/shared/DefinitionField.d.ts +3 -1
  73. package/dist/shared/DefinitionField.d.ts.map +1 -1
  74. package/dist/shared/DefinitionField.js +80 -72
  75. package/dist/shared/DefinitionField.js.map +1 -1
  76. package/dist/shared/builtIn.d.ts +1 -0
  77. package/dist/shared/builtIn.d.ts.map +1 -1
  78. package/dist/shared/builtIn.js +16 -1
  79. package/dist/shared/builtIn.js.map +1 -1
  80. package/dist/shared/check.d.ts +27 -0
  81. package/dist/shared/check.d.ts.map +1 -0
  82. package/dist/shared/check.js +18 -0
  83. package/dist/shared/check.js.map +1 -0
  84. package/dist/shared/context.d.ts +18 -3
  85. package/dist/shared/context.d.ts.map +1 -1
  86. package/dist/shared/context.js +31 -19
  87. package/dist/shared/context.js.map +1 -1
  88. package/dist/shared/embed.d.ts +19 -0
  89. package/dist/shared/embed.d.ts.map +1 -0
  90. package/dist/shared/embed.js +14 -0
  91. package/dist/shared/embed.js.map +1 -0
  92. package/dist/shared/types.d.ts +2 -0
  93. package/dist/shared/types.d.ts.map +1 -1
  94. package/dist/slug/SlugField.css +18 -0
  95. package/dist/slug/SlugField.d.ts +31 -3
  96. package/dist/slug/SlugField.d.ts.map +1 -1
  97. package/dist/slug/SlugField.js +231 -159
  98. package/dist/slug/SlugField.js.map +1 -1
  99. package/dist/slug/SlugField.module.js +14 -0
  100. package/dist/slug/SlugField.module.js.map +1 -0
  101. package/dist/slug/index.d.ts +1 -1
  102. package/dist/slug/index.d.ts.map +1 -1
  103. package/dist/slug/index.js +1 -1
  104. package/dist/tags/TagsField.d.ts +17 -0
  105. package/dist/tags/TagsField.d.ts.map +1 -0
  106. package/dist/tags/TagsField.js +120 -0
  107. package/dist/tags/TagsField.js.map +1 -0
  108. package/dist/tags/index.d.ts +2 -0
  109. package/dist/tags/index.d.ts.map +1 -0
  110. package/dist/tags/index.js +1 -0
  111. package/dist/tel/TelField.d.ts +11 -0
  112. package/dist/tel/TelField.d.ts.map +1 -0
  113. package/dist/tel/TelField.js +87 -0
  114. package/dist/tel/TelField.js.map +1 -0
  115. package/dist/tel/index.d.ts +2 -0
  116. package/dist/tel/index.d.ts.map +1 -0
  117. package/dist/tel/index.js +1 -0
  118. package/package.json +41 -4
package/dist/index.js CHANGED
@@ -10,4 +10,7 @@ import { FileField, FileFieldEntry, isFileValue, toFiles } from "./file/FileFiel
10
10
  import { createRelationSource, toReferences, useRelationReferences } from "./shared/relation.js";
11
11
  import { builtInFields, fieldsPlugin } from "./shared/builtIn.js";
12
12
  import { DefinitionField, NestedField } from "./shared/DefinitionField.js";
13
- export { DefinitionField, FieldsProvider, FileField, FileFieldEntry, FilePicker, MissingFieldEntry, NestedField, UploadList, builtInFields, createRelationSource, fieldsPlugin, findRule, formatSize, getAccept, getFieldProps, getMaxSize, getParentPath, getRuleNumber, isFileValue, isRequired, matchesMime, toFiles, toReferences, useFieldsContext, useRejectionMessage, useRelationReferences, useUploads };
13
+ import { createFieldCheckSource } from "./shared/check.js";
14
+ import { createEmbedSource } from "./shared/embed.js";
15
+ import { createNominatimSource } from "./location/nominatim.js";
16
+ export { DefinitionField, FieldsProvider, FileField, FileFieldEntry, FilePicker, MissingFieldEntry, NestedField, UploadList, builtInFields, createEmbedSource, createFieldCheckSource, createNominatimSource, createRelationSource, fieldsPlugin, findRule, formatSize, getAccept, getFieldProps, getMaxSize, getParentPath, getRuleNumber, isFileValue, isRequired, matchesMime, toFiles, toReferences, useFieldsContext, useRejectionMessage, useRelationReferences, useUploads };
@@ -0,0 +1,7 @@
1
+ /* JSON reads in a monospace font, without wrapping long lines. */
2
+ .panneau-json-field-code {
3
+ font-family: var(--panneau-font-family-mono);
4
+ font-size: var(--panneau-font-size-sm);
5
+ white-space: pre;
6
+ tab-size: 2;
7
+ }
@@ -0,0 +1,22 @@
1
+ import type { FieldEntryProps, FieldProps } from '../shared/types';
2
+ /** The value of a `json` field: an object or an array, or the text while it doesn't parse. */
3
+ export type JsonValue = Record<string, unknown> | unknown[] | string;
4
+ export interface JsonFieldProps extends FieldProps<JsonValue> {
5
+ placeholder?: string;
6
+ /** Visible lines. Defaults to 8. */
7
+ rows?: number;
8
+ }
9
+ /** The value of a text: what it parses to when it is an object or an array, or the text itself. */
10
+ export declare function parseJson(text: string): {
11
+ value: JsonValue | null;
12
+ error: string | null;
13
+ };
14
+ /**
15
+ * Structured data edited as JSON: an object or an array. While the text doesn't parse, the value
16
+ * is the text itself, which the `json` rule refuses, so the form can't be saved with it. The text
17
+ * is indented again on blur once it parses.
18
+ */
19
+ export declare function JsonField({ value, onChange, onBlur, errors, rows, disabled, readOnly, required, ...props }: JsonFieldProps): import("react").JSX.Element;
20
+ /** The `json` type: an object or an array, with setting `rows`. */
21
+ export declare function JsonFieldEntry(props: FieldEntryProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=JsonField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonField.d.ts","sourceRoot":"","sources":["../../src/json/JsonField.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGnE,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,cAAe,SAAQ,UAAU,CAAC,SAAS,CAAC;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAUD,mGAAmG;AACnG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAazF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EACtB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAW,EACX,IAAQ,EACR,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACX,EAAE,cAAc,+BAwChB;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,+BAepD"}
@@ -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,2 @@
1
+ export { JsonField, JsonFieldEntry, type JsonFieldProps, type JsonValue, parseJson, } from './JsonField';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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";
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizedField.d.ts","sourceRoot":"","sources":["../../src/localized/LocalizedField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGnE,6EAA6E;AAC7E,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAElE,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACzE,yBAAyB;IACzB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,sFAAsF;AACtF,wBAAgB,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAY1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAC9B,OAAO,EACP,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,eAAe,GAClB,EAAE,mBAAmB,CAAC,CAAC,CAAC,+BAsCxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,+BA8BzD"}
1
+ {"version":3,"file":"LocalizedField.d.ts","sourceRoot":"","sources":["../../src/localized/LocalizedField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGnE,6EAA6E;AAC7E,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAElE,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACzE,yBAAyB;IACzB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,sFAAsF;AACtF,wBAAgB,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAY1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAC9B,OAAO,EACP,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,eAAe,GAClB,EAAE,mBAAmB,CAAC,CAAC,CAAC,+BAsCxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,+BA+BzD"}
@@ -172,6 +172,7 @@ function LocalizedFieldEntry(props) {
172
172
  onChange: input.onChange,
173
173
  ...props.onBlur !== void 0 ? { onBlur: props.onBlur } : {},
174
174
  parentValue: props.parentValue,
175
+ locale: input.locale,
175
176
  ...props.disabled !== void 0 ? { disabled: props.disabled } : {},
176
177
  ...props.readOnly !== void 0 ? { readOnly: props.readOnly } : {}
177
178
  });
@@ -1 +1 @@
1
- {"version":3,"file":"LocalizedField.js","names":["name","locale","label","description","errors","required","className","labelClassName","descriptionClassName","errorsClassName","locales","record","_c","styles"],"sources":["../../src/localized/LocalizedField.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { Fieldset, usePanneauIntl } from '@panneau/ui';\n\nimport { NestedField } from '../shared/DefinitionField';\nimport { useFieldsContext } from '../shared/context';\nimport { cx } from '../shared/cx';\nimport { getFieldProps } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport styles from './LocalizedField.module.css';\n\n/** A localized value: a value per locale (`{ fr: 'Été', en: 'Summer' }`). */\nexport type LocalizedValue<V> = Partial<Record<string, V | null>>;\n\n/** What `LocalizedField` gives the input of each locale. */\nexport interface LocalizedInputProps<V> {\n locale: string;\n /** Name of the locale in the UI's language, as the input's label. */\n label: string;\n value: V | null;\n onChange: (value: V | null) => void;\n onBlur?: () => void;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n}\n\nexport interface LocalizedFieldProps<V> extends FieldProps<LocalizedValue<V>> {\n /** Locales, in order. */\n locales: readonly string[];\n /** Renders the input of a locale. */\n children: (props: LocalizedInputProps<V>) => ReactNode;\n localeClassName?: string;\n}\n\n/** The name of a locale in the UI's language, capitalized (`Français`, `English`). */\nexport function useLocaleName(): (locale: string) => string {\n const intl = usePanneauIntl();\n return (locale) => {\n let name: string | undefined;\n try {\n name = intl.formatDisplayName(locale, { type: 'language' });\n } catch {\n name = undefined;\n }\n const text = name ?? locale.toUpperCase();\n return text.charAt(0).toLocaleUpperCase(intl.locale) + text.slice(1);\n };\n}\n\n/**\n * A value per locale, with an input for each locale under one legend. A value without any locale\n * filled is `null`.\n */\nexport function LocalizedField<V>({\n locales,\n children,\n value,\n onChange,\n onBlur,\n label,\n description,\n errors,\n disabled,\n readOnly,\n required,\n className,\n labelClassName,\n descriptionClassName,\n errorsClassName,\n localeClassName,\n}: LocalizedFieldProps<V>) {\n const localeName = useLocaleName();\n return (\n <Fieldset\n legend={label}\n description={description}\n errors={errors}\n isRequired={required}\n className={className}\n legendClassName={labelClassName}\n descriptionClassName={descriptionClassName}\n errorsClassName={errorsClassName}\n >\n <div className={styles.locales}>\n {locales.map((locale) => (\n <div key={locale} className={cx(styles.locale, localeClassName)}>\n {children({\n locale,\n label: localeName(locale),\n value: value?.[locale] ?? null,\n onChange: (next) => {\n const updated = { ...value, [locale]: next };\n const filled = Object.values(updated).some(\n (entry) =>\n entry !== null && entry !== undefined && entry !== '',\n );\n onChange?.(filled ? updated : null);\n },\n ...(onBlur !== undefined ? { onBlur } : {}),\n ...(disabled !== undefined ? { disabled } : {}),\n ...(readOnly !== undefined ? { readOnly } : {}),\n ...(required !== undefined ? { required } : {}),\n })}\n </div>\n ))}\n </div>\n </Fieldset>\n );\n}\n\n/**\n * A field of the definition with `localized: true`: the field of its type for each locale of the\n * fields context, each at its own path (`title.fr`).\n */\nexport function LocalizedFieldEntry(props: FieldEntryProps) {\n const { locales: contextLocales } = useFieldsContext();\n const { field, path, value } = props;\n const record =\n value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n const locales = contextLocales.length > 0 ? contextLocales : Object.keys(record);\n const { name: _name, onBlur: _onBlur, ...chrome } = getFieldProps(props);\n return (\n <LocalizedField<unknown>\n {...chrome}\n locales={locales}\n value={record}\n onChange={props.onChange}\n >\n {(input) => (\n <NestedField\n field={{ ...field, localized: false, label: input.label, help: undefined }}\n path={`${path}.${input.locale}`}\n value={input.value}\n onChange={input.onChange}\n {...(props.onBlur !== undefined ? { onBlur: props.onBlur } : {})}\n parentValue={props.parentValue}\n {...(props.disabled !== undefined ? { disabled: props.disabled } : {})}\n {...(props.readOnly !== undefined ? { readOnly: props.readOnly } : {})}\n />\n )}\n </LocalizedField>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LocalizedField.js","names":["name","locale","label","description","errors","required","className","labelClassName","descriptionClassName","errorsClassName","locales","record","_c","styles"],"sources":["../../src/localized/LocalizedField.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { Fieldset, usePanneauIntl } from '@panneau/ui';\n\nimport { NestedField } from '../shared/DefinitionField';\nimport { useFieldsContext } from '../shared/context';\nimport { cx } from '../shared/cx';\nimport { getFieldProps } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport styles from './LocalizedField.module.css';\n\n/** A localized value: a value per locale (`{ fr: 'Été', en: 'Summer' }`). */\nexport type LocalizedValue<V> = Partial<Record<string, V | null>>;\n\n/** What `LocalizedField` gives the input of each locale. */\nexport interface LocalizedInputProps<V> {\n locale: string;\n /** Name of the locale in the UI's language, as the input's label. */\n label: string;\n value: V | null;\n onChange: (value: V | null) => void;\n onBlur?: () => void;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n}\n\nexport interface LocalizedFieldProps<V> extends FieldProps<LocalizedValue<V>> {\n /** Locales, in order. */\n locales: readonly string[];\n /** Renders the input of a locale. */\n children: (props: LocalizedInputProps<V>) => ReactNode;\n localeClassName?: string;\n}\n\n/** The name of a locale in the UI's language, capitalized (`Français`, `English`). */\nexport function useLocaleName(): (locale: string) => string {\n const intl = usePanneauIntl();\n return (locale) => {\n let name: string | undefined;\n try {\n name = intl.formatDisplayName(locale, { type: 'language' });\n } catch {\n name = undefined;\n }\n const text = name ?? locale.toUpperCase();\n return text.charAt(0).toLocaleUpperCase(intl.locale) + text.slice(1);\n };\n}\n\n/**\n * A value per locale, with an input for each locale under one legend. A value without any locale\n * filled is `null`.\n */\nexport function LocalizedField<V>({\n locales,\n children,\n value,\n onChange,\n onBlur,\n label,\n description,\n errors,\n disabled,\n readOnly,\n required,\n className,\n labelClassName,\n descriptionClassName,\n errorsClassName,\n localeClassName,\n}: LocalizedFieldProps<V>) {\n const localeName = useLocaleName();\n return (\n <Fieldset\n legend={label}\n description={description}\n errors={errors}\n isRequired={required}\n className={className}\n legendClassName={labelClassName}\n descriptionClassName={descriptionClassName}\n errorsClassName={errorsClassName}\n >\n <div className={styles.locales}>\n {locales.map((locale) => (\n <div key={locale} className={cx(styles.locale, localeClassName)}>\n {children({\n locale,\n label: localeName(locale),\n value: value?.[locale] ?? null,\n onChange: (next) => {\n const updated = { ...value, [locale]: next };\n const filled = Object.values(updated).some(\n (entry) =>\n entry !== null && entry !== undefined && entry !== '',\n );\n onChange?.(filled ? updated : null);\n },\n ...(onBlur !== undefined ? { onBlur } : {}),\n ...(disabled !== undefined ? { disabled } : {}),\n ...(readOnly !== undefined ? { readOnly } : {}),\n ...(required !== undefined ? { required } : {}),\n })}\n </div>\n ))}\n </div>\n </Fieldset>\n );\n}\n\n/**\n * A field of the definition with `localized: true`: the field of its type for each locale of the\n * fields context, each at its own path (`title.fr`).\n */\nexport function LocalizedFieldEntry(props: FieldEntryProps) {\n const { locales: contextLocales } = useFieldsContext();\n const { field, path, value } = props;\n const record =\n value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n const locales = contextLocales.length > 0 ? contextLocales : Object.keys(record);\n const { name: _name, onBlur: _onBlur, ...chrome } = getFieldProps(props);\n return (\n <LocalizedField<unknown>\n {...chrome}\n locales={locales}\n value={record}\n onChange={props.onChange}\n >\n {(input) => (\n <NestedField\n field={{ ...field, localized: false, label: input.label, help: undefined }}\n path={`${path}.${input.locale}`}\n value={input.value}\n onChange={input.onChange}\n {...(props.onBlur !== undefined ? { onBlur: props.onBlur } : {})}\n parentValue={props.parentValue}\n locale={input.locale}\n {...(props.disabled !== undefined ? { disabled: props.disabled } : {})}\n {...(props.readOnly !== undefined ? { readOnly: props.readOnly } : {})}\n />\n )}\n </LocalizedField>\n );\n}\n"],"mappings":";;;;;;;;;;AAoCA,SAAO,gBAAA;CAAA,MAAA,IAAAY,EAAA,CAAA;CACH,MAAA,OAAa,eAAe;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,MAAA;EACvB,MAAA,WAAA;GACCZ,IAAA;GACJ,IAAA;IACI,OAAO,KAAI,kBAAmB,QAAQ,EAAA,MAAQ,WAAW,CAAC;GAAtD,QAAA;IAEJ,OAAO,KAAA;GAAH;GAER,MAAA,OAAa,QAAQ,OAAM,YAAa;GAAE,OACnC,KAAI,OAAQ,CAAC,CAAC,CAAA,kBAAmB,KAAI,MAAO,IAAI,KAAI,MAAO,CAAC;EAAC;EACvE,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OATM;AASN;;;;;AAOL,SAAO,eAAA,IAAA;CAAA,MAAA,IAAAY,EAAA,EAAA;CAA2B,MAAA,EAAA,SAAA,UAAA,OAAA,UAAA,QAAA,OAAA,aAAA,QAAA,UAAA,UAAA,UAAA,WAAA,gBAAA,sBAAA,iBAAA,oBAAA;CAkB9B,MAAA,aAAmB,cAAc;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,YAAA,EAAA,OAAA,YAAA,EAAA,OAAA,mBAAA,EAAA,OAAA,cAAA,EAAA,OAAA,WAAA,EAAA,OAAA,UAAA,EAAA,OAAA,YAAA,EAAA,OAAA,YAAA,EAAA,OAAA,YAAA,EAAA,OAAA,OAAA;EAAA,IAAA;EAAA,IAAA,EAAA,QAAA,YAAA,EAAA,QAAA,YAAA,EAAA,QAAA,mBAAA,EAAA,QAAA,cAAA,EAAA,QAAA,UAAA,EAAA,QAAA,YAAA,EAAA,QAAA,YAAA,EAAA,QAAA,YAAA,EAAA,QAAA,OAAA;GAaV,MAAA,WACT,oBAAA,OAAA;IAA6B,WAAA,GAAGC,8BAAM,QAAS,eAAe;IACzD,UAAA,SAAS;KAAA;KAAA,OAEC,WAAW,MAAM;KAAC,OAClB,QAAQ,WAAR;KAAuB,WACpB,SAAA;MACN,MAAA,UAAgB;OAAA,GAAK;QAAQ,SAAS;MAAK;MAC3C,MAAA,SAAe,OAAM,OAAQ,OAAO,CAAC,CAAA,KACjC,KAEJ;MACA,WAAW,SAAA,UAAA,IAAuB;KAAC;KACtC,GACG,WAAW,KAAA,IAAX,EAAA,OAAqC,IAArC,CAAqC;KAAC,GACtC,aAAa,KAAA,IAAb,EAAA,SAAyC,IAAzC,CAAyC;KAAC,GAC1C,aAAa,KAAA,IAAb,EAAA,SAAyC,IAAzC,CAAyC;KAAC,GAC1C,aAAa,KAAA,IAAb,EAAA,SAAyC,IAAzC,CAAyC;IACjD,CAAC;GACC,GAlBI,MAkBJ;GACT,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;EAAA,OAAA,KAAA,EAAA;EApBA,KAAA,QAAO,IAAK,EAoBZ;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,IAAA;EArBN,KAAA,oBAAA,OAAA;GAAgB,WAAAA,8BAAM;GACjB,UAAA;EAqBC,CAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,aAAA,EAAA,QAAA,eAAA,EAAA,QAAA,wBAAA,EAAA,QAAA,UAAA,EAAA,QAAA,mBAAA,EAAA,QAAA,SAAA,EAAA,QAAA,kBAAA,EAAA,QAAA,YAAA,EAAA,QAAA,IAAA;EAhCV,KAAA,oBAAC,UAAD;GACYX,QAAA;GACK;GACL;GACIG,YAAA;GACD;GACME,iBAAA;GACK;GACL;GAEjB,UAAA;EAVK,CAAA;EAiCE,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAjCX;AAiCW;;;;;AArDZ,SAAA,MAAA,OAAA;CAAA,OAyCiC,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU;AAAE;AAoB7F,SAAO,oBAAA,OAAA;CAAA,MAAA,IAAAK,EAAA,EAAA;CACH,MAAA,EAAA,SAAA,mBAAoC,iBAAiB;CACrD,MAAA,EAAA,OAAA,MAAA,UAA+B;CAAM,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EAEjC,KAAA,UAAU,QAAQ,OAAO,UAAU,YAAnC,CAAgD,MAAK,QAAS,KAAK,IAC5D,QADP,CAEO;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAHZ,MAAA,SACI;CAES,IAAA;CAAA,IAAA,EAAA,OAAA,kBAAA,EAAA,OAAA,QAAA;EACG,KAAA,eAAc,SAAU,IAAxB,iBAA6C,OAAM,KAAM,MAAM;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAhF,MAAA,UAAgB;CAAiE,IAAA;CAAA,IAAA,EAAA,OAAA,OAAA;EAC7B,KAAA,cAAc,KAAK;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,IAAA;EAAxE,MAAA,EAAA,MAAA,OAAA,QAAA,SAAA,GAAA,OAAoD;EAApD,SAAA;EAAyE,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,SAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,SAAA,EAAA,QAAA,QAAA,EAAA,QAAA,MAAA,YAAA,EAAA,QAAA,MAAA,UAAA,EAAA,QAAA,MAAA,eAAA,EAAA,QAAA,MAAA,UAAA;EAQhE,MAAA,UACG,oBAAC,aAAD;GACW,OAAA;IAAA,GAAK;IAAK,WAAa;IAAK,OAAS,MAAK;IAAM,MAAQ,KAAA;GAAU;GACnE,MAAA,GAAG,KAAI,GAAI,MAAK;GACf,OAAA,MAAK;GACF,UAAA,MAAK;GAAS,GACnB,MAAK,WAAY,KAAA,IAAjB,EAAA,QAAuC,MAAK,OAAa,IAAzD,CAAyD;GACjD,aAAA,MAAK;GACV,QAAA,MAAK;GAAO,GACf,MAAK,aAAc,KAAA,IAAnB,EAAA,UAA2C,MAAK,SAAe,IAA/D,CAA+D;GAAC,GAChE,MAAK,aAAc,KAAA,IAAnB,EAAA,UAA2C,MAAK,SAAe,IAA/D,CAA+D;EAAC,CAAA;EAE5E,EAAA,KAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,IAAA;CAAA,IAAA,EAAA,QAAA,UAAA,EAAA,QAAA,WAAA,EAAA,QAAA,MAAA,YAAA,EAAA,QAAA,UAAA,EAAA,QAAA,IAAA;EAlBL,KAAA,oBAAC,gBAAD;GAAe,GACP;GACK;GACFD,OAAA;GACG,UAAA,MAAK;GAEd,UAAA;EANU,CAAA;EAmBE,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAnBjB;AAmBiB"}
@@ -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"}