@panneau/fields 5.0.0-alpha.1 → 5.0.0-alpha.11

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 (243) hide show
  1. package/README.md +101 -20
  2. package/dist/boolean/BooleanField.d.ts +1 -1
  3. package/dist/boolean/BooleanField.js +78 -17
  4. package/dist/boolean/BooleanField.js.map +1 -1
  5. package/dist/boolean/index.d.ts +1 -1
  6. package/dist/color/ColorField.css +5 -5
  7. package/dist/color/ColorField.d.ts +2 -2
  8. package/dist/color/ColorField.js.map +1 -1
  9. package/dist/color/ColorField.module.js +3 -3
  10. package/dist/color/index.d.ts +1 -1
  11. package/dist/date/DateField.d.ts +1 -1
  12. package/dist/date/DateField.js.map +1 -1
  13. package/dist/date/index.d.ts +1 -1
  14. package/dist/datetime/DateTimeField.d.ts +1 -1
  15. package/dist/datetime/DateTimeField.js +107 -20
  16. package/dist/datetime/DateTimeField.js.map +1 -1
  17. package/dist/datetime/index.d.ts +1 -1
  18. package/dist/duration/DurationField.css +11 -0
  19. package/dist/duration/DurationField.d.ts +26 -0
  20. package/dist/duration/DurationField.d.ts.map +1 -0
  21. package/dist/duration/DurationField.js +214 -0
  22. package/dist/duration/DurationField.js.map +1 -0
  23. package/dist/duration/DurationField.module.js +12 -0
  24. package/dist/duration/DurationField.module.js.map +1 -0
  25. package/dist/duration/index.d.ts +2 -0
  26. package/dist/duration/index.d.ts.map +1 -0
  27. package/dist/duration/index.js +1 -0
  28. package/dist/email/EmailField.d.ts +2 -2
  29. package/dist/email/EmailField.js.map +1 -1
  30. package/dist/email/index.d.ts +1 -1
  31. package/dist/embed/EmbedField.css +60 -0
  32. package/dist/embed/EmbedField.d.ts +20 -0
  33. package/dist/embed/EmbedField.d.ts.map +1 -0
  34. package/dist/embed/EmbedField.js +246 -0
  35. package/dist/embed/EmbedField.js.map +1 -0
  36. package/dist/embed/EmbedField.module.js +22 -0
  37. package/dist/embed/EmbedField.module.js.map +1 -0
  38. package/dist/embed/index.d.ts +3 -0
  39. package/dist/embed/index.d.ts.map +1 -0
  40. package/dist/embed/index.js +3 -0
  41. package/dist/file/FileField.css +54 -0
  42. package/dist/file/FileField.d.ts +50 -0
  43. package/dist/file/FileField.d.ts.map +1 -0
  44. package/dist/file/FileField.js +288 -0
  45. package/dist/file/FileField.js.map +1 -0
  46. package/dist/file/FileField.module.js +22 -0
  47. package/dist/file/FileField.module.js.map +1 -0
  48. package/dist/file/index.d.ts +3 -0
  49. package/dist/file/index.d.ts.map +1 -0
  50. package/dist/file/index.js +1 -0
  51. package/dist/group/GroupField.css +2 -2
  52. package/dist/group/GroupField.d.ts +1 -1
  53. package/dist/group/GroupField.js.map +1 -1
  54. package/dist/group/GroupField.module.js +1 -1
  55. package/dist/group/index.d.ts +1 -1
  56. package/dist/index.d.ts +18 -7
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +11 -2
  59. package/dist/json/JsonField.css +7 -0
  60. package/dist/json/JsonField.d.ts +22 -0
  61. package/dist/json/JsonField.d.ts.map +1 -0
  62. package/dist/json/JsonField.js +207 -0
  63. package/dist/json/JsonField.js.map +1 -0
  64. package/dist/json/JsonField.module.js +8 -0
  65. package/dist/json/JsonField.module.js.map +1 -0
  66. package/dist/json/index.d.ts +2 -0
  67. package/dist/json/index.d.ts.map +1 -0
  68. package/dist/json/index.js +1 -0
  69. package/dist/locales/index.js.map +1 -1
  70. package/dist/localized/LocalizedField.css +2 -2
  71. package/dist/localized/LocalizedField.d.ts +1 -1
  72. package/dist/localized/LocalizedField.d.ts.map +1 -1
  73. package/dist/localized/LocalizedField.js +1 -0
  74. package/dist/localized/LocalizedField.js.map +1 -1
  75. package/dist/localized/LocalizedField.module.js +2 -2
  76. package/dist/localized/index.d.ts +1 -1
  77. package/dist/location/LocationField.css +54 -0
  78. package/dist/location/LocationField.d.ts +31 -0
  79. package/dist/location/LocationField.d.ts.map +1 -0
  80. package/dist/location/LocationField.js +563 -0
  81. package/dist/location/LocationField.js.map +1 -0
  82. package/dist/location/LocationField.module.js +22 -0
  83. package/dist/location/LocationField.module.js.map +1 -0
  84. package/dist/location/LocationMap.d.ts +25 -0
  85. package/dist/location/LocationMap.d.ts.map +1 -0
  86. package/dist/location/LocationMap.js +205 -0
  87. package/dist/location/LocationMap.js.map +1 -0
  88. package/dist/location/index.d.ts +5 -0
  89. package/dist/location/index.d.ts.map +1 -0
  90. package/dist/location/index.js +4 -0
  91. package/dist/location/leafletCss.d.ts +2 -0
  92. package/dist/location/leafletCss.d.ts.map +1 -0
  93. package/dist/location/leafletCss.js +6 -0
  94. package/dist/location/leafletCss.js.map +1 -0
  95. package/dist/location/nominatim.d.ts +17 -0
  96. package/dist/location/nominatim.d.ts.map +1 -0
  97. package/dist/location/nominatim.js +50 -0
  98. package/dist/location/nominatim.js.map +1 -0
  99. package/dist/location/types.d.ts +40 -0
  100. package/dist/location/types.d.ts.map +1 -0
  101. package/dist/missing/MissingField.css +4 -3
  102. package/dist/missing/MissingField.d.ts +4 -3
  103. package/dist/missing/MissingField.d.ts.map +1 -1
  104. package/dist/missing/MissingField.js +3 -2
  105. package/dist/missing/MissingField.js.map +1 -1
  106. package/dist/missing/MissingField.module.js +3 -3
  107. package/dist/missing/MissingField.module.js.map +1 -1
  108. package/dist/number/NumberField.d.ts +1 -1
  109. package/dist/number/NumberField.js.map +1 -1
  110. package/dist/number/index.d.ts +1 -1
  111. package/dist/range/RangeField.d.ts +22 -0
  112. package/dist/range/RangeField.d.ts.map +1 -0
  113. package/dist/range/RangeField.js +203 -0
  114. package/dist/range/RangeField.js.map +1 -0
  115. package/dist/range/index.d.ts +2 -0
  116. package/dist/range/index.d.ts.map +1 -0
  117. package/dist/range/index.js +1 -0
  118. package/dist/relation/RelationField.css +7 -7
  119. package/dist/relation/RelationField.d.ts +2 -2
  120. package/dist/relation/RelationField.d.ts.map +1 -1
  121. package/dist/relation/RelationField.js +509 -169
  122. package/dist/relation/RelationField.js.map +1 -1
  123. package/dist/relation/RelationField.module.js +6 -6
  124. package/dist/relation/index.d.ts +2 -2
  125. package/dist/repeater/RepeaterField.css +12 -11
  126. package/dist/repeater/RepeaterField.d.ts +1 -1
  127. package/dist/repeater/RepeaterField.js +118 -34
  128. package/dist/repeater/RepeaterField.js.map +1 -1
  129. package/dist/repeater/RepeaterField.module.js +9 -9
  130. package/dist/repeater/RepeaterField.module.js.map +1 -1
  131. package/dist/repeater/index.d.ts +1 -1
  132. package/dist/select/SelectField.css +1 -1
  133. package/dist/select/SelectField.d.ts +1 -1
  134. package/dist/select/SelectField.js.map +1 -1
  135. package/dist/select/SelectField.module.js +1 -1
  136. package/dist/select/index.d.ts +1 -1
  137. package/dist/shared/DefinitionField.d.ts +4 -2
  138. package/dist/shared/DefinitionField.d.ts.map +1 -1
  139. package/dist/shared/DefinitionField.js +80 -72
  140. package/dist/shared/DefinitionField.js.map +1 -1
  141. package/dist/shared/builtIn.d.ts +5 -3
  142. package/dist/shared/builtIn.d.ts.map +1 -1
  143. package/dist/shared/builtIn.js +21 -3
  144. package/dist/shared/builtIn.js.map +1 -1
  145. package/dist/shared/check.d.ts +27 -0
  146. package/dist/shared/check.d.ts.map +1 -0
  147. package/dist/shared/check.js +18 -0
  148. package/dist/shared/check.js.map +1 -0
  149. package/dist/shared/context.d.ts +28 -5
  150. package/dist/shared/context.d.ts.map +1 -1
  151. package/dist/shared/context.js +35 -19
  152. package/dist/shared/context.js.map +1 -1
  153. package/dist/shared/cx.js.map +1 -1
  154. package/dist/shared/dates.js.map +1 -1
  155. package/dist/shared/embed.d.ts +19 -0
  156. package/dist/shared/embed.d.ts.map +1 -0
  157. package/dist/shared/embed.js +14 -0
  158. package/dist/shared/embed.js.map +1 -0
  159. package/dist/shared/entry.d.ts +11 -2
  160. package/dist/shared/entry.d.ts.map +1 -1
  161. package/dist/shared/entry.js +19 -3
  162. package/dist/shared/entry.js.map +1 -1
  163. package/dist/shared/relation.js.map +1 -1
  164. package/dist/shared/types.d.ts +2 -0
  165. package/dist/shared/types.d.ts.map +1 -1
  166. package/dist/slug/SlugField.css +18 -0
  167. package/dist/slug/SlugField.d.ts +33 -5
  168. package/dist/slug/SlugField.d.ts.map +1 -1
  169. package/dist/slug/SlugField.js +346 -126
  170. package/dist/slug/SlugField.js.map +1 -1
  171. package/dist/slug/SlugField.module.js +14 -0
  172. package/dist/slug/SlugField.module.js.map +1 -0
  173. package/dist/slug/index.d.ts +1 -1
  174. package/dist/slug/index.d.ts.map +1 -1
  175. package/dist/slug/index.js +1 -1
  176. package/dist/tags/TagsField.d.ts +17 -0
  177. package/dist/tags/TagsField.d.ts.map +1 -0
  178. package/dist/tags/TagsField.js +120 -0
  179. package/dist/tags/TagsField.js.map +1 -0
  180. package/dist/tags/index.d.ts +2 -0
  181. package/dist/tags/index.d.ts.map +1 -0
  182. package/dist/tags/index.js +1 -0
  183. package/dist/tel/TelField.d.ts +11 -0
  184. package/dist/tel/TelField.d.ts.map +1 -0
  185. package/dist/tel/TelField.js +87 -0
  186. package/dist/tel/TelField.js.map +1 -0
  187. package/dist/tel/index.d.ts +2 -0
  188. package/dist/tel/index.d.ts.map +1 -0
  189. package/dist/tel/index.js +1 -0
  190. package/dist/text/TextField.d.ts +12 -4
  191. package/dist/text/TextField.d.ts.map +1 -1
  192. package/dist/text/TextField.js +104 -60
  193. package/dist/text/TextField.js.map +1 -1
  194. package/dist/text/index.d.ts +1 -1
  195. package/dist/textarea/TextAreaField.d.ts +1 -1
  196. package/dist/textarea/TextAreaField.js.map +1 -1
  197. package/dist/textarea/index.d.ts +1 -1
  198. package/dist/time/TimeField.d.ts +1 -1
  199. package/dist/time/TimeField.js +64 -10
  200. package/dist/time/TimeField.js.map +1 -1
  201. package/dist/time/index.d.ts +1 -1
  202. package/dist/upload/FilePicker.css +24 -0
  203. package/dist/upload/FilePicker.d.ts +14 -0
  204. package/dist/upload/FilePicker.d.ts.map +1 -0
  205. package/dist/upload/FilePicker.js +130 -0
  206. package/dist/upload/FilePicker.js.map +1 -0
  207. package/dist/upload/FilePicker.module.js +12 -0
  208. package/dist/upload/FilePicker.module.js.map +1 -0
  209. package/dist/upload/UploadList.css +93 -0
  210. package/dist/upload/UploadList.d.ts +18 -0
  211. package/dist/upload/UploadList.d.ts.map +1 -0
  212. package/dist/upload/UploadList.js +144 -0
  213. package/dist/upload/UploadList.js.map +1 -0
  214. package/dist/upload/UploadList.module.js +32 -0
  215. package/dist/upload/UploadList.module.js.map +1 -0
  216. package/dist/upload/files.d.ts +5 -0
  217. package/dist/upload/files.d.ts.map +1 -0
  218. package/dist/upload/files.js +26 -0
  219. package/dist/upload/files.js.map +1 -0
  220. package/dist/upload/types.d.ts +58 -0
  221. package/dist/upload/types.d.ts.map +1 -0
  222. package/dist/upload/useRejectionMessage.d.ts +4 -0
  223. package/dist/upload/useRejectionMessage.d.ts.map +1 -0
  224. package/dist/upload/useRejectionMessage.js +25 -0
  225. package/dist/upload/useRejectionMessage.js.map +1 -0
  226. package/dist/upload/useUploads.d.ts +30 -0
  227. package/dist/upload/useUploads.d.ts.map +1 -0
  228. package/dist/upload/useUploads.js +115 -0
  229. package/dist/upload/useUploads.js.map +1 -0
  230. package/dist/uppy/index.d.ts +3 -0
  231. package/dist/uppy/index.d.ts.map +1 -0
  232. package/dist/uppy/index.js +1 -0
  233. package/dist/uppy/uploader.d.ts +44 -0
  234. package/dist/uppy/uploader.d.ts.map +1 -0
  235. package/dist/uppy/uploader.js +139 -0
  236. package/dist/uppy/uploader.js.map +1 -0
  237. package/dist/url/UrlField.css +2 -2
  238. package/dist/url/UrlField.d.ts +2 -2
  239. package/dist/url/UrlField.js +69 -14
  240. package/dist/url/UrlField.js.map +1 -1
  241. package/dist/url/UrlField.module.js +1 -1
  242. package/dist/url/index.d.ts +1 -1
  243. package/package.json +69 -7
@@ -1,12 +1,15 @@
1
+ import { useFieldsContext } from "../shared/context.js";
1
2
  import { getFieldProps, getSetting, isString } from "../shared/entry.js";
2
3
  import { messages } from "../shared/messages.js";
3
4
  import { TextField } from "../text/TextField.js";
5
+ import SlugField_module_default from "./SlugField.module.js";
4
6
  import { c } from "react/compiler-runtime";
5
- import { IconButton, usePanneauIntl } from "@panneau/ui";
6
- import { useEffect, useRef } from "react";
7
- import { jsx } from "react/jsx-runtime";
7
+ import { Button, IconButton, usePanneauIntl } from "@panneau/ui";
8
+ import { useEffect, useRef, useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
8
10
  import { WandSparkles } from "lucide-react";
9
11
  //#region src/slug/SlugField.tsx
12
+ var suggestionMessage = messages.useSuggestion;
10
13
  /**
11
14
  * Turns a text into a slug: lowercase ASCII letters and digits separated by dashes, without
12
15
  * accents (`Été à Montréal` gives `ete-a-montreal`).
@@ -15,47 +18,131 @@ function slugify(text) {
15
18
  return text.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
16
19
  }
17
20
  /**
21
+ * Checks a slug after a pause in typing, and keeps the latest answer for it. A check that
22
+ * fails leaves the field as it is: saving still validates the slug.
23
+ */
24
+ function useSlugCheck(value, onCheck, delay, key) {
25
+ const $ = c(11);
26
+ const [result, setResult] = useState(null);
27
+ const latest = useRef(onCheck);
28
+ let t0;
29
+ if ($[0] !== onCheck) {
30
+ t0 = () => {
31
+ latest.current = onCheck;
32
+ };
33
+ $[0] = onCheck;
34
+ $[1] = t0;
35
+ } else t0 = $[1];
36
+ useEffect(t0);
37
+ const enabled = onCheck !== null && onCheck !== void 0;
38
+ let t1;
39
+ if ($[2] !== delay || $[3] !== enabled || $[4] !== value) {
40
+ t1 = () => {
41
+ if (!enabled || value === "") return;
42
+ const controller = new AbortController();
43
+ const timer = setTimeout(() => {
44
+ const check = latest.current;
45
+ if (check === null || check === void 0) return;
46
+ check(value, { signal: controller.signal }).then((check_0) => {
47
+ if (!controller.signal.aborted) setResult({
48
+ value,
49
+ check: check_0
50
+ });
51
+ }).catch(_temp);
52
+ }, delay);
53
+ return () => {
54
+ clearTimeout(timer);
55
+ controller.abort();
56
+ };
57
+ };
58
+ $[2] = delay;
59
+ $[3] = enabled;
60
+ $[4] = value;
61
+ $[5] = t1;
62
+ } else t1 = $[5];
63
+ let t2;
64
+ if ($[6] !== delay || $[7] !== enabled || $[8] !== key || $[9] !== value) {
65
+ t2 = [
66
+ value,
67
+ enabled,
68
+ delay,
69
+ key
70
+ ];
71
+ $[6] = delay;
72
+ $[7] = enabled;
73
+ $[8] = key;
74
+ $[9] = value;
75
+ $[10] = t2;
76
+ } else t2 = $[10];
77
+ useEffect(t1, t2);
78
+ return result !== null && result.value === value ? result.check : null;
79
+ }
80
+ /**
18
81
  * A slug for URLs. Typed text is cleaned up on blur. With a `source`, the slug follows it until
19
- * it is edited, and a button generates it again.
82
+ * it is edited, and a button generates it again. With `onCheck`, the backend says whether the
83
+ * slug is taken, and gives its URL.
20
84
  */
85
+ function _temp() {}
21
86
  function SlugField(t0) {
22
- const $ = c(37);
87
+ const $ = c(65);
88
+ let description;
23
89
  let disabled;
90
+ let errors;
24
91
  let onBlur;
25
92
  let onChange;
93
+ let onCheck;
94
+ let prefix;
26
95
  let props;
27
96
  let readOnly;
28
97
  let source;
29
98
  let sourceLabel;
99
+ let t1;
100
+ let t2;
30
101
  let value;
31
102
  if ($[0] !== t0) {
32
- ({value, onChange, onBlur, source, sourceLabel, disabled, readOnly, ...props} = t0);
103
+ ({value, onChange, onBlur, source, sourceLabel, onCheck, checkDelay: t1, checkKey: t2, disabled, readOnly, prefix, errors, description, ...props} = t0);
33
104
  $[0] = t0;
34
- $[1] = disabled;
35
- $[2] = onBlur;
36
- $[3] = onChange;
37
- $[4] = props;
38
- $[5] = readOnly;
39
- $[6] = source;
40
- $[7] = sourceLabel;
41
- $[8] = value;
105
+ $[1] = description;
106
+ $[2] = disabled;
107
+ $[3] = errors;
108
+ $[4] = onBlur;
109
+ $[5] = onChange;
110
+ $[6] = onCheck;
111
+ $[7] = prefix;
112
+ $[8] = props;
113
+ $[9] = readOnly;
114
+ $[10] = source;
115
+ $[11] = sourceLabel;
116
+ $[12] = t1;
117
+ $[13] = t2;
118
+ $[14] = value;
42
119
  } else {
43
- disabled = $[1];
44
- onBlur = $[2];
45
- onChange = $[3];
46
- props = $[4];
47
- readOnly = $[5];
48
- source = $[6];
49
- sourceLabel = $[7];
50
- value = $[8];
120
+ description = $[1];
121
+ disabled = $[2];
122
+ errors = $[3];
123
+ onBlur = $[4];
124
+ onChange = $[5];
125
+ onCheck = $[6];
126
+ prefix = $[7];
127
+ props = $[8];
128
+ readOnly = $[9];
129
+ source = $[10];
130
+ sourceLabel = $[11];
131
+ t1 = $[12];
132
+ t2 = $[13];
133
+ value = $[14];
51
134
  }
135
+ const checkDelay = t1 === void 0 ? 300 : t1;
136
+ const checkKey = t2 === void 0 ? "" : t2;
52
137
  const intl = usePanneauIntl();
53
138
  const previousSource = useRef(source);
54
- const editable = disabled !== true && readOnly !== true;
55
- let t1;
56
- let t2;
57
- if ($[9] !== editable || $[10] !== onChange || $[11] !== source || $[12] !== value) {
58
- t1 = () => {
139
+ const check = useSlugCheck(value ?? "", onCheck, checkDelay, checkKey);
140
+ const disabledByBackend = check?.disabled === true;
141
+ const editable = disabled !== true && readOnly !== true && !disabledByBackend;
142
+ let t3;
143
+ let t4;
144
+ if ($[15] !== editable || $[16] !== onChange || $[17] !== source || $[18] !== value) {
145
+ t3 = () => {
59
146
  const previous = previousSource.current;
60
147
  previousSource.current = source;
61
148
  if (!editable || source === previous || source === void 0) return;
@@ -65,95 +152,193 @@ function SlugField(t0) {
65
152
  if (next !== current) onChange?.(next === "" ? null : next);
66
153
  }
67
154
  };
68
- t2 = [
155
+ t4 = [
69
156
  source,
70
157
  value,
71
158
  onChange,
72
159
  editable
73
160
  ];
74
- $[9] = editable;
75
- $[10] = onChange;
76
- $[11] = source;
77
- $[12] = value;
78
- $[13] = t1;
79
- $[14] = t2;
161
+ $[15] = editable;
162
+ $[16] = onChange;
163
+ $[17] = source;
164
+ $[18] = value;
165
+ $[19] = t3;
166
+ $[20] = t4;
80
167
  } else {
81
- t1 = $[13];
82
- t2 = $[14];
168
+ t3 = $[19];
169
+ t4 = $[20];
83
170
  }
84
- useEffect(t1, t2);
85
- const t3 = source ?? "";
86
- let t4;
87
- if ($[15] !== t3) {
88
- t4 = slugify(t3);
89
- $[15] = t3;
90
- $[16] = t4;
91
- } else t4 = $[16];
92
- const generated = t4;
93
- let t5;
94
- if ($[17] !== onBlur || $[18] !== onChange || $[19] !== value) {
95
- t5 = () => {
171
+ useEffect(t3, t4);
172
+ const t5 = source ?? "";
173
+ let t6;
174
+ if ($[21] !== t5) {
175
+ t6 = slugify(t5);
176
+ $[21] = t5;
177
+ $[22] = t6;
178
+ } else t6 = $[22];
179
+ const generated = t6;
180
+ const taken = check !== null && !check.available;
181
+ let t7;
182
+ if ($[23] !== check || $[24] !== taken) {
183
+ t7 = taken && isString(check.suggestion) ? check.suggestion : null;
184
+ $[23] = check;
185
+ $[24] = taken;
186
+ $[25] = t7;
187
+ } else t7 = $[25];
188
+ const suggestion = t7;
189
+ let t8;
190
+ if ($[26] !== check || $[27] !== taken) {
191
+ t8 = check !== null && isString(check.url) && !taken ? check.url : null;
192
+ $[26] = check;
193
+ $[27] = taken;
194
+ $[28] = t8;
195
+ } else t8 = $[28];
196
+ const url = t8;
197
+ const t9 = readOnly === true || disabledByBackend;
198
+ let t10;
199
+ if ($[29] !== check || $[30] !== prefix) {
200
+ t10 = check !== null && isString(check.prefix) ? { prefix: check.prefix } : prefix !== void 0 ? { prefix } : {};
201
+ $[29] = check;
202
+ $[30] = prefix;
203
+ $[31] = t10;
204
+ } else t10 = $[31];
205
+ let t11;
206
+ if ($[32] !== errors) {
207
+ t11 = errors !== void 0 ? { errors } : {};
208
+ $[32] = errors;
209
+ $[33] = t11;
210
+ } else t11 = $[33];
211
+ let t12;
212
+ if ($[34] !== description || $[35] !== editable || $[36] !== intl || $[37] !== onChange || $[38] !== suggestion || $[39] !== taken || $[40] !== url) {
213
+ t12 = taken || url !== null || description !== void 0 ? /* @__PURE__ */ jsxs("span", {
214
+ className: SlugField_module_default.description,
215
+ children: [
216
+ description !== void 0 ? /* @__PURE__ */ jsx("span", { children: description }) : null,
217
+ url !== null ? /* @__PURE__ */ jsx("a", {
218
+ href: url,
219
+ target: "_blank",
220
+ rel: "noreferrer",
221
+ className: SlugField_module_default.url,
222
+ children: url
223
+ }) : null,
224
+ taken ? /* @__PURE__ */ jsxs("span", {
225
+ className: SlugField_module_default.taken,
226
+ role: "status",
227
+ children: [intl.formatMessage(messages.slugTaken), suggestion !== null && editable ? /* @__PURE__ */ jsx(Button, {
228
+ size: "sm",
229
+ appearance: "ghost",
230
+ onPress: () => onChange?.(suggestion),
231
+ children: intl.formatMessage(suggestionMessage, { suggestion })
232
+ }) : null]
233
+ }) : null
234
+ ]
235
+ }) : void 0;
236
+ $[34] = description;
237
+ $[35] = editable;
238
+ $[36] = intl;
239
+ $[37] = onChange;
240
+ $[38] = suggestion;
241
+ $[39] = taken;
242
+ $[40] = url;
243
+ $[41] = t12;
244
+ } else t12 = $[41];
245
+ let t13;
246
+ if ($[42] !== onBlur || $[43] !== onChange || $[44] !== value) {
247
+ t13 = () => {
96
248
  if (value !== null && value !== void 0) {
97
249
  const next_0 = slugify(value);
98
250
  if (next_0 !== value) onChange?.(next_0 === "" ? null : next_0);
99
251
  }
100
252
  onBlur?.();
101
253
  };
102
- $[17] = onBlur;
103
- $[18] = onChange;
104
- $[19] = value;
105
- $[20] = t5;
106
- } else t5 = $[20];
107
- let t6;
108
- if ($[21] !== editable || $[22] !== generated || $[23] !== intl || $[24] !== onChange || $[25] !== source || $[26] !== sourceLabel || $[27] !== value) {
109
- t6 = source !== void 0 && editable ? /* @__PURE__ */ jsx(IconButton, {
254
+ $[42] = onBlur;
255
+ $[43] = onChange;
256
+ $[44] = value;
257
+ $[45] = t13;
258
+ } else t13 = $[45];
259
+ let t14;
260
+ if ($[46] !== editable || $[47] !== generated || $[48] !== intl || $[49] !== onChange || $[50] !== source || $[51] !== sourceLabel || $[52] !== value) {
261
+ t14 = source !== void 0 && editable ? /* @__PURE__ */ jsx(IconButton, {
110
262
  icon: WandSparkles,
111
263
  size: "sm",
112
264
  label: intl.formatMessage(messages.generateSlug, { field: sourceLabel ?? "" }),
113
265
  isDisabled: generated === "" || generated === value,
114
266
  onPress: () => onChange?.(generated === "" ? null : generated)
115
267
  }) : void 0;
116
- $[21] = editable;
117
- $[22] = generated;
118
- $[23] = intl;
119
- $[24] = onChange;
120
- $[25] = source;
121
- $[26] = sourceLabel;
122
- $[27] = value;
123
- $[28] = t6;
124
- } else t6 = $[28];
125
- let t7;
126
- if ($[29] !== disabled || $[30] !== onChange || $[31] !== props || $[32] !== readOnly || $[33] !== t5 || $[34] !== t6 || $[35] !== value) {
127
- t7 = /* @__PURE__ */ jsx(TextField, {
268
+ $[46] = editable;
269
+ $[47] = generated;
270
+ $[48] = intl;
271
+ $[49] = onChange;
272
+ $[50] = source;
273
+ $[51] = sourceLabel;
274
+ $[52] = value;
275
+ $[53] = t14;
276
+ } else t14 = $[53];
277
+ let t15;
278
+ if ($[54] !== disabled || $[55] !== onChange || $[56] !== props || $[57] !== t10 || $[58] !== t11 || $[59] !== t12 || $[60] !== t13 || $[61] !== t14 || $[62] !== t9 || $[63] !== value) {
279
+ t15 = /* @__PURE__ */ jsx(TextField, {
128
280
  autoComplete: "off",
129
281
  ...props,
130
282
  value,
131
283
  onChange,
132
284
  disabled,
133
- readOnly,
134
- onBlur: t5,
135
- suffix: t6
285
+ readOnly: t9,
286
+ ...t10,
287
+ ...t11,
288
+ description: t12,
289
+ onBlur: t13,
290
+ suffix: t14
136
291
  });
137
- $[29] = disabled;
138
- $[30] = onChange;
139
- $[31] = props;
140
- $[32] = readOnly;
141
- $[33] = t5;
142
- $[34] = t6;
143
- $[35] = value;
144
- $[36] = t7;
145
- } else t7 = $[36];
146
- return t7;
292
+ $[54] = disabled;
293
+ $[55] = onChange;
294
+ $[56] = props;
295
+ $[57] = t10;
296
+ $[58] = t11;
297
+ $[59] = t12;
298
+ $[60] = t13;
299
+ $[61] = t14;
300
+ $[62] = t9;
301
+ $[63] = value;
302
+ $[64] = t15;
303
+ } else t15 = $[64];
304
+ return t15;
147
305
  }
148
- function sourceText(value) {
306
+ /**
307
+ * The text of a source value: the value itself, or for a localized value, its value in `locale`.
308
+ * Without a locale, the first locale that has a value.
309
+ */
310
+ function sourceText(value, locale) {
149
311
  if (typeof value === "string") return value;
150
- if (value !== null && typeof value === "object") return Object.values(value).find(isString) ?? null;
312
+ if (value !== null && typeof value === "object") {
313
+ const record = value;
314
+ if (locale !== void 0) {
315
+ const text = record[locale];
316
+ return isString(text) ? text : null;
317
+ }
318
+ return Object.values(record).find(isString) ?? null;
319
+ }
151
320
  return null;
152
321
  }
153
- /** The `slug` type: `from` names the field it follows, and setting `prefix` shows a URL prefix. */
322
+ /** The form's values that a check depends on: all but the slug itself. */
323
+ function checkKeyOf(values, name) {
324
+ if (values === null) return "";
325
+ const { [name]: _slug, ...others } = values;
326
+ try {
327
+ return JSON.stringify(others);
328
+ } catch {
329
+ return "";
330
+ }
331
+ }
332
+ /**
333
+ * The `slug` type: `from` names the field it follows, in the slug's own locale, or in the default
334
+ * locale (the first of the fields context) for a slug that isn't localized. Setting `prefix`
335
+ * shows a URL prefix. With `check`, the fields context's check source checks the slug of a field
336
+ * at the top of the resource, with the form's values.
337
+ */
154
338
  function SlugFieldEntry(props) {
155
- const $ = c(18);
156
- const { field, parentValue } = props;
339
+ const $ = c(33);
340
+ const { field, parentValue, locale, path } = props;
341
+ const { locales, checkSource } = useFieldsContext();
157
342
  let t0;
158
343
  if ($[0] !== field) {
159
344
  t0 = getSetting(field, "prefix", isString);
@@ -161,56 +346,91 @@ function SlugFieldEntry(props) {
161
346
  $[1] = t0;
162
347
  } else t0 = $[1];
163
348
  const prefix = t0;
349
+ const values = parentValue !== null && typeof parentValue === "object" ? parentValue : null;
164
350
  let t1;
165
- if ($[2] !== field.from || $[3] !== parentValue) {
166
- t1 = field.from !== void 0 && parentValue !== null && typeof parentValue === "object" ? sourceText(parentValue[field.from]) : void 0;
351
+ if ($[2] !== field.from || $[3] !== locale || $[4] !== locales || $[5] !== values) {
352
+ t1 = field.from !== void 0 && values !== null ? sourceText(values[field.from], locale ?? locales[0]) : void 0;
167
353
  $[2] = field.from;
168
- $[3] = parentValue;
169
- $[4] = t1;
170
- } else t1 = $[4];
354
+ $[3] = locale;
355
+ $[4] = locales;
356
+ $[5] = values;
357
+ $[6] = t1;
358
+ } else t1 = $[6];
171
359
  const source = t1;
360
+ const topLevel = path === field.name || path === `${field.name}.${locale ?? ""}`;
172
361
  let t2;
173
- if ($[5] !== props) {
174
- t2 = getFieldProps(props);
175
- $[5] = props;
176
- $[6] = t2;
177
- } else t2 = $[6];
178
- const t3 = isString(props.value) ? props.value : null;
179
- let t4;
180
- if ($[7] !== field.from || $[8] !== source) {
181
- t4 = source !== void 0 ? {
362
+ if ($[7] !== checkSource || $[8] !== field.check || $[9] !== field.name || $[10] !== locale || $[11] !== topLevel || $[12] !== values) {
363
+ t2 = field.check === true && checkSource !== null && topLevel ? (value, t3) => {
364
+ const { signal } = t3;
365
+ return checkSource.check(field.name, {
366
+ value,
367
+ ...locale !== void 0 ? { locale } : {},
368
+ values: values ?? {}
369
+ }, { signal });
370
+ } : null;
371
+ $[7] = checkSource;
372
+ $[8] = field.check;
373
+ $[9] = field.name;
374
+ $[10] = locale;
375
+ $[11] = topLevel;
376
+ $[12] = values;
377
+ $[13] = t2;
378
+ } else t2 = $[13];
379
+ const onCheck = t2;
380
+ let t3;
381
+ if ($[14] !== props) {
382
+ t3 = getFieldProps(props);
383
+ $[14] = props;
384
+ $[15] = t3;
385
+ } else t3 = $[15];
386
+ const t4 = isString(props.value) ? props.value : null;
387
+ let t5;
388
+ if ($[16] !== field.name || $[17] !== onCheck || $[18] !== values) {
389
+ t5 = onCheck !== null ? checkKeyOf(values, field.name) : "";
390
+ $[16] = field.name;
391
+ $[17] = onCheck;
392
+ $[18] = values;
393
+ $[19] = t5;
394
+ } else t5 = $[19];
395
+ let t6;
396
+ if ($[20] !== field.from || $[21] !== source) {
397
+ t6 = source !== void 0 ? {
182
398
  source,
183
399
  sourceLabel: field.from ?? ""
184
400
  } : {};
185
- $[7] = field.from;
186
- $[8] = source;
187
- $[9] = t4;
188
- } else t4 = $[9];
189
- let t5;
190
- if ($[10] !== prefix) {
191
- t5 = prefix !== void 0 ? { prefix } : {};
192
- $[10] = prefix;
193
- $[11] = t5;
194
- } else t5 = $[11];
195
- let t6;
196
- if ($[12] !== props.onChange || $[13] !== t2 || $[14] !== t3 || $[15] !== t4 || $[16] !== t5) {
197
- t6 = /* @__PURE__ */ jsx(SlugField, {
198
- ...t2,
199
- value: t3,
401
+ $[20] = field.from;
402
+ $[21] = source;
403
+ $[22] = t6;
404
+ } else t6 = $[22];
405
+ let t7;
406
+ if ($[23] !== prefix) {
407
+ t7 = prefix !== void 0 ? { prefix } : {};
408
+ $[23] = prefix;
409
+ $[24] = t7;
410
+ } else t7 = $[24];
411
+ let t8;
412
+ if ($[25] !== onCheck || $[26] !== props.onChange || $[27] !== t3 || $[28] !== t4 || $[29] !== t5 || $[30] !== t6 || $[31] !== t7) {
413
+ t8 = /* @__PURE__ */ jsx(SlugField, {
414
+ ...t3,
415
+ value: t4,
200
416
  onChange: props.onChange,
201
- ...t4,
202
- ...t5
417
+ onCheck,
418
+ checkKey: t5,
419
+ ...t6,
420
+ ...t7
203
421
  });
204
- $[12] = props.onChange;
205
- $[13] = t2;
206
- $[14] = t3;
207
- $[15] = t4;
208
- $[16] = t5;
209
- $[17] = t6;
210
- } else t6 = $[17];
211
- return t6;
422
+ $[25] = onCheck;
423
+ $[26] = props.onChange;
424
+ $[27] = t3;
425
+ $[28] = t4;
426
+ $[29] = t5;
427
+ $[30] = t6;
428
+ $[31] = t7;
429
+ $[32] = t8;
430
+ } else t8 = $[32];
431
+ return t8;
212
432
  }
213
433
  //#endregion
214
- export { SlugField, SlugFieldEntry, slugify };
434
+ export { SlugField, SlugFieldEntry, slugify, sourceText };
215
435
 
216
436
  //# sourceMappingURL=SlugField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SlugField.js","names":["next","WandSparkles","value","onChange","disabled","readOnly","_c"],"sources":["../../src/slug/SlugField.tsx"],"sourcesContent":["import { WandSparkles } from 'lucide-react';\nimport { useEffect, useRef } from 'react';\n\nimport { IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { getFieldProps, getSetting, isString } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps } from '../shared/types';\nimport { TextField, type TextFieldProps } from '../text/TextField';\n\n/**\n * Turns a text into a slug: lowercase ASCII letters and digits separated by dashes, without\n * accents (`Été à Montréal` gives `ete-a-montreal`).\n */\nexport function slugify(text: string): string {\n return text\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nexport interface SlugFieldProps extends Omit<TextFieldProps, 'type' | 'suffix'> {\n /**\n * The text the slug is made from (a title). While the slug is empty or still matches it, the\n * slug follows it.\n */\n source?: string | null;\n /** Name of the source, for the button that generates the slug from it. */\n sourceLabel?: string;\n}\n\n/**\n * A slug for URLs. Typed text is cleaned up on blur. With a `source`, the slug follows it until\n * it is edited, and a button generates it again.\n */\nexport function SlugField({\n value,\n onChange,\n onBlur,\n source,\n sourceLabel,\n disabled,\n readOnly,\n ...props\n}: SlugFieldProps) {\n const intl = usePanneauIntl();\n const previousSource = useRef(source);\n const editable = disabled !== true && readOnly !== true;\n\n useEffect(() => {\n const previous = previousSource.current;\n previousSource.current = source;\n if (!editable || source === previous || source === undefined) {\n return;\n }\n const current = value ?? '';\n if (current === '' || current === slugify(previous ?? '')) {\n const next = slugify(source ?? '');\n if (next !== current) {\n onChange?.(next === '' ? null : next);\n }\n }\n }, [source, value, onChange, editable]);\n\n const generated = slugify(source ?? '');\n return (\n <TextField\n autoComplete=\"off\"\n {...props}\n value={value}\n onChange={onChange}\n disabled={disabled}\n readOnly={readOnly}\n onBlur={() => {\n if (value !== null && value !== undefined) {\n const next = slugify(value);\n if (next !== value) {\n onChange?.(next === '' ? null : next);\n }\n }\n onBlur?.();\n }}\n suffix={\n source !== undefined && editable ? (\n <IconButton\n icon={WandSparkles}\n size=\"sm\"\n label={intl.formatMessage(messages.generateSlug, {\n field: sourceLabel ?? '',\n })}\n isDisabled={generated === '' || generated === value}\n onPress={() => onChange?.(generated === '' ? null : generated)}\n />\n ) : undefined\n }\n />\n );\n}\n\nfunction sourceText(value: unknown): string | null {\n if (typeof value === 'string') {\n return value;\n }\n // A localized source: its first locale.\n if (value !== null && typeof value === 'object') {\n const first = Object.values(value as Record<string, unknown>).find(isString);\n return first ?? null;\n }\n return null;\n}\n\n/** The `slug` type: `from` names the field it follows, and setting `prefix` shows a URL prefix. */\nexport function SlugFieldEntry(props: FieldEntryProps) {\n const { field, parentValue } = props;\n const prefix = getSetting(field, 'prefix', isString);\n const source =\n field.from !== undefined && parentValue !== null && typeof parentValue === 'object'\n ? sourceText((parentValue as Record<string, unknown>)[field.from])\n : undefined;\n return (\n <SlugField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(source !== undefined ? { source, sourceLabel: field.from ?? '' } : {})}\n {...(prefix !== undefined ? { prefix } : {})}\n />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SlugField.js","names":["WandSparkles","useEffect","useRef","useState","FieldCheckResponse","Button","IconButton","usePanneauIntl","useFieldsContext","getFieldProps","getSetting","isString","messages","FieldEntryProps","TextField","TextFieldProps","styles","suggestionMessage","useSuggestion","slugify","text","normalize","replace","toLowerCase","SlugCheck","value","options","signal","AbortSignal","Promise","SlugFieldProps","Omit","source","sourceLabel","onCheck","checkDelay","checkKey","useSlugCheck","delay","key","$","_c","result","setResult","latest","t0","current","enabled","undefined","t1","controller","AbortController","timer","setTimeout","check","then","check_0","aborted","catch","_temp","clearTimeout","abort","t2","SlugField","description","disabled","errors","onBlur","onChange","prefix","props","readOnly","intl","previousSource","disabledByBackend","editable","t3","t4","previous","next","t5","t6","generated","taken","available","t7","suggestion","t8","url","t9","t10","t11","t12","formatMessage","slugTaken","t13","next_0","t14","generateSlug","field","t15","sourceText","locale","record","Record","Object","values","find","checkKeyOf","name","_slug","others","JSON","stringify","SlugFieldEntry","parentValue","path","locales","checkSource","from","topLevel","_c","styles"],"sources":["../../src/slug/SlugField.tsx"],"sourcesContent":["import { WandSparkles } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport type { FieldCheckResponse } from '@panneau/protocol';\nimport { Button, IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { useFieldsContext } from '../shared/context';\nimport { getFieldProps, getSetting, isString } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps } from '../shared/types';\nimport { TextField, type TextFieldProps } from '../text/TextField';\nimport styles from './SlugField.module.css';\n\n// Read outside the component: the React Compiler takes any `use…` name for a hook.\nconst suggestionMessage = messages.useSuggestion;\n\n/**\n * Turns a text into a slug: lowercase ASCII letters and digits separated by dashes, without\n * accents (`Été à Montréal` gives `ete-a-montreal`).\n */\nexport function slugify(text: string): string {\n return text\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/** Checks a slug with the backend: whether it is available, and its URL. */\nexport type SlugCheck = (\n value: string,\n options: { signal: AbortSignal },\n) => Promise<FieldCheckResponse>;\n\nexport interface SlugFieldProps extends Omit<TextFieldProps, 'type' | 'suffix'> {\n /**\n * The text the slug is made from (a title). While the slug is empty or still matches it, the\n * slug follows it.\n */\n source?: string | null;\n /** Name of the source, for the button that generates the slug from it. */\n sourceLabel?: string;\n /**\n * Checks the slug as it is typed, and once when the field shows: the field then shows the\n * URL the backend gives, and says when the slug is taken, with a free one to use instead.\n */\n onCheck?: SlugCheck | null;\n /** How long typing must pause before a check, in milliseconds. Defaults to 300. */\n checkDelay?: number;\n /**\n * What the check depends on besides the slug, such as the form's values: the slug is checked\n * again when it changes. `onCheck` itself can change on every render.\n */\n checkKey?: string;\n}\n\n/**\n * Checks a slug after a pause in typing, and keeps the latest answer for it. A check that\n * fails leaves the field as it is: saving still validates the slug.\n */\nfunction useSlugCheck(\n value: string,\n onCheck: SlugCheck | null | undefined,\n delay: number,\n key: string,\n): FieldCheckResponse | null {\n const [result, setResult] = useState<{ value: string; check: FieldCheckResponse } | null>(null);\n const latest = useRef(onCheck);\n useEffect(() => {\n latest.current = onCheck;\n });\n const enabled = onCheck !== null && onCheck !== undefined;\n useEffect(() => {\n if (!enabled || value === '') {\n return undefined;\n }\n const controller = new AbortController();\n const timer = setTimeout(() => {\n const check = latest.current;\n if (check === null || check === undefined) {\n return;\n }\n check(value, { signal: controller.signal })\n .then((check) => {\n if (!controller.signal.aborted) {\n setResult({ value, check });\n }\n })\n .catch(() => undefined);\n }, delay);\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [value, enabled, delay, key]);\n return result !== null && result.value === value ? result.check : null;\n}\n\n/**\n * A slug for URLs. Typed text is cleaned up on blur. With a `source`, the slug follows it until\n * it is edited, and a button generates it again. With `onCheck`, the backend says whether the\n * slug is taken, and gives its URL.\n */\nexport function SlugField({\n value,\n onChange,\n onBlur,\n source,\n sourceLabel,\n onCheck,\n checkDelay = 300,\n checkKey = '',\n disabled,\n readOnly,\n prefix,\n errors,\n description,\n ...props\n}: SlugFieldProps) {\n const intl = usePanneauIntl();\n const previousSource = useRef(source);\n const check = useSlugCheck(value ?? '', onCheck, checkDelay, checkKey);\n const disabledByBackend = check?.disabled === true;\n const editable = disabled !== true && readOnly !== true && !disabledByBackend;\n\n useEffect(() => {\n const previous = previousSource.current;\n previousSource.current = source;\n if (!editable || source === previous || source === undefined) {\n return;\n }\n const current = value ?? '';\n if (current === '' || current === slugify(previous ?? '')) {\n const next = slugify(source ?? '');\n if (next !== current) {\n onChange?.(next === '' ? null : next);\n }\n }\n }, [source, value, onChange, editable]);\n\n const generated = slugify(source ?? '');\n const taken = check !== null && !check.available;\n const suggestion = taken && isString(check.suggestion) ? check.suggestion : null;\n const url = check !== null && isString(check.url) && !taken ? check.url : null;\n return (\n <TextField\n autoComplete=\"off\"\n {...props}\n value={value}\n onChange={onChange}\n disabled={disabled}\n readOnly={readOnly === true || disabledByBackend}\n {...(check !== null && isString(check.prefix)\n ? { prefix: check.prefix }\n : prefix !== undefined\n ? { prefix }\n : {})}\n {...(errors !== undefined ? { errors } : {})}\n description={\n taken || url !== null || description !== undefined ? (\n <span className={styles.description}>\n {description !== undefined ? <span>{description}</span> : null}\n {url !== null ? (\n <a href={url} target=\"_blank\" rel=\"noreferrer\" className={styles.url}>\n {url}\n </a>\n ) : null}\n {taken ? (\n <span className={styles.taken} role=\"status\">\n {intl.formatMessage(messages.slugTaken)}\n {suggestion !== null && editable ? (\n <Button\n size=\"sm\"\n appearance=\"ghost\"\n onPress={() => onChange?.(suggestion)}\n >\n {intl.formatMessage(suggestionMessage, {\n suggestion,\n })}\n </Button>\n ) : null}\n </span>\n ) : null}\n </span>\n ) : undefined\n }\n onBlur={() => {\n if (value !== null && value !== undefined) {\n const next = slugify(value);\n if (next !== value) {\n onChange?.(next === '' ? null : next);\n }\n }\n onBlur?.();\n }}\n suffix={\n source !== undefined && editable ? (\n <IconButton\n icon={WandSparkles}\n size=\"sm\"\n label={intl.formatMessage(messages.generateSlug, {\n field: sourceLabel ?? '',\n })}\n isDisabled={generated === '' || generated === value}\n onPress={() => onChange?.(generated === '' ? null : generated)}\n />\n ) : undefined\n }\n />\n );\n}\n\n/**\n * The text of a source value: the value itself, or for a localized value, its value in `locale`.\n * Without a locale, the first locale that has a value.\n */\nexport function sourceText(value: unknown, locale?: string): string | null {\n if (typeof value === 'string') {\n return value;\n }\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n if (locale !== undefined) {\n const text = record[locale];\n return isString(text) ? text : null;\n }\n return Object.values(record).find(isString) ?? null;\n }\n return null;\n}\n\n/** The form's values that a check depends on: all but the slug itself. */\nfunction checkKeyOf(values: Record<string, unknown> | null, name: string): string {\n if (values === null) {\n return '';\n }\n const { [name]: _slug, ...others } = values;\n try {\n return JSON.stringify(others);\n } catch {\n return '';\n }\n}\n\n/**\n * The `slug` type: `from` names the field it follows, in the slug's own locale, or in the default\n * locale (the first of the fields context) for a slug that isn't localized. Setting `prefix`\n * shows a URL prefix. With `check`, the fields context's check source checks the slug of a field\n * at the top of the resource, with the form's values.\n */\nexport function SlugFieldEntry(props: FieldEntryProps) {\n const { field, parentValue, locale, path } = props;\n const { locales, checkSource } = useFieldsContext();\n const prefix = getSetting(field, 'prefix', isString);\n const values =\n parentValue !== null && typeof parentValue === 'object'\n ? (parentValue as Record<string, unknown>)\n : null;\n const source =\n field.from !== undefined && values !== null\n ? sourceText(values[field.from], locale ?? locales[0])\n : undefined;\n const topLevel = path === field.name || path === `${field.name}.${locale ?? ''}`;\n const onCheck: SlugCheck | null =\n field.check === true && checkSource !== null && topLevel\n ? (value, { signal }) =>\n checkSource.check(\n field.name,\n {\n value,\n ...(locale !== undefined ? { locale } : {}),\n values: values ?? {},\n },\n { signal },\n )\n : null;\n return (\n <SlugField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n onCheck={onCheck}\n checkKey={onCheck !== null ? checkKeyOf(values, field.name) : ''}\n {...(source !== undefined ? { source, sourceLabel: field.from ?? '' } : {})}\n {...(prefix !== undefined ? { prefix } : {})}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import "./SlugField.css";
2
+ //#region src/slug/SlugField.module.css
3
+ var description = "panneau-slug-field-description";
4
+ var url = "panneau-slug-field-url";
5
+ var taken = "panneau-slug-field-taken";
6
+ var SlugField_module_default = {
7
+ description,
8
+ url,
9
+ taken
10
+ };
11
+ //#endregion
12
+ export { SlugField_module_default as default, description, taken, url };
13
+
14
+ //# sourceMappingURL=SlugField.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlugField.module.js","names":[],"sources":["../../src/slug/SlugField.module.css"],"sourcesContent":[".description {\n display: flex;\n flex-direction: column;\n gap: var(--panneau-space-1);\n}\n\n.url {\n overflow-wrap: anywhere;\n color: var(--panneau-color-link);\n}\n\n.taken {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--panneau-space-2);\n color: var(--panneau-color-warning);\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- export { SlugField, SlugFieldEntry, type SlugFieldProps, slugify } from './SlugField';
1
+ export { SlugField, SlugFieldEntry, type SlugCheck, type SlugFieldProps, slugify, sourceText, } from './SlugField.js';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slug/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slug/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,SAAS,EACT,cAAc,EACd,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,OAAO,EACP,UAAU,GACb,MAAM,aAAa,CAAC"}