@formancy/react 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +22 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +213 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Fragment, createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
|
-
import { cancelUploads, fieldUploads, formatPath, parsePath, thumbnailSize } from "@formancy/core";
|
|
2
|
+
import { cancelUploads, fieldUploads, formatPath, parsePath, placedGroup, placedPage, thumbnailSize } from "@formancy/core";
|
|
3
|
+
import { createFormText } from "@formancy/core/words";
|
|
4
|
+
import { LAYOUT_LEAF_KINDS, acceptRemoteOptions, answerFromText, applyRichCommand, capRemoteOptions, datagridColumns, editMasked, formatMasked, isImageSource, layoutChildren, layoutNodeShows, maskIsNumeric, maskPlaceholder, narrowOptionsByLabel, parseRichText, resolveText, resolvedLocale } from "@formancy/spec";
|
|
3
5
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { LAYOUT_LEAF_KINDS, acceptRemoteOptions, answerFromText, applyRichCommand, capRemoteOptions, datagridColumns, editMasked, formatMasked, isImageSource, layoutChildren, layoutNodeShows, maskIsNumeric, maskPlaceholder, narrowOptionsByLabel, parseRichText, resolveText } from "@formancy/spec";
|
|
5
6
|
import { flushSync } from "react-dom";
|
|
6
7
|
import { encode } from "uqr";
|
|
7
8
|
//#region src/context.tsx
|
|
@@ -12,11 +13,23 @@ import { encode } from "uqr";
|
|
|
12
13
|
* use prop getters.
|
|
13
14
|
*/
|
|
14
15
|
const FormancyContext = createContext(null);
|
|
15
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The form's own words, in the language its questions are read in (0171). Beside the engine
|
|
18
|
+
* rather than on it, because the engine has no buttons — the server runs the same one.
|
|
19
|
+
*/
|
|
20
|
+
const FormancyTextContext = createContext(null);
|
|
21
|
+
function FormancyProvider({ engine, words, children }) {
|
|
16
22
|
useEffect(() => () => cancelUploads(engine), [engine]);
|
|
23
|
+
const text = useMemo(() => createFormText({
|
|
24
|
+
locale: resolvedLocale(engine.schema(), engine.locale()),
|
|
25
|
+
...words === void 0 ? {} : { words }
|
|
26
|
+
}), [engine, words]);
|
|
17
27
|
return /* @__PURE__ */ jsx(FormancyContext.Provider, {
|
|
18
28
|
value: engine,
|
|
19
|
-
children
|
|
29
|
+
children: /* @__PURE__ */ jsx(FormancyTextContext.Provider, {
|
|
30
|
+
value: text,
|
|
31
|
+
children
|
|
32
|
+
})
|
|
20
33
|
});
|
|
21
34
|
}
|
|
22
35
|
function useFormEngine() {
|
|
@@ -24,6 +37,21 @@ function useFormEngine() {
|
|
|
24
37
|
if (!engine) throw new Error("formancy hooks need a <FormancyProvider engine={...}> above them in the tree");
|
|
25
38
|
return engine;
|
|
26
39
|
}
|
|
40
|
+
let english;
|
|
41
|
+
/**
|
|
42
|
+
* The form's words, in the language the reader chose for it.
|
|
43
|
+
*
|
|
44
|
+
* English outside a `FormancyProvider`, which has no engine to take a language from — a
|
|
45
|
+
* resume notice a host draws beside the form rather than inside its provider. Never the
|
|
46
|
+
* browser's language: the form's is the one the reader chose, and the browser's is the
|
|
47
|
+
* one their machine came with.
|
|
48
|
+
*/
|
|
49
|
+
function useFormText() {
|
|
50
|
+
const text = useContext(FormancyTextContext);
|
|
51
|
+
if (text !== null) return text;
|
|
52
|
+
english ??= createFormText({ locale: "" });
|
|
53
|
+
return english;
|
|
54
|
+
}
|
|
27
55
|
//#endregion
|
|
28
56
|
//#region src/use-field.ts
|
|
29
57
|
/**
|
|
@@ -267,6 +295,7 @@ function LayoutNodeView({ schema, node, locale, renderField, at, shows }) {
|
|
|
267
295
|
*/
|
|
268
296
|
function Tabs({ schema, node, locale, renderField, at, here, shows }) {
|
|
269
297
|
const base = useId();
|
|
298
|
+
const text = useFormText();
|
|
270
299
|
const shown = node.children.flatMap((child, index) => shows === void 0 || layoutNodeShows(child, shows) ? [{
|
|
271
300
|
child,
|
|
272
301
|
index
|
|
@@ -325,7 +354,7 @@ function Tabs({ schema, node, locale, renderField, at, here, shows }) {
|
|
|
325
354
|
tabIndex: index === open ? 0 : -1,
|
|
326
355
|
"data-formancy-part": "tab",
|
|
327
356
|
onClick: () => setOpen(index),
|
|
328
|
-
children: names[index] ??
|
|
357
|
+
children: names[index] ?? text("tabs.unnamed", { position: index + 1 })
|
|
329
358
|
}, position))
|
|
330
359
|
}), shown.map(({ child, index: position }, index) => /* @__PURE__ */ jsx("div", {
|
|
331
360
|
ref: (element) => {
|
|
@@ -520,6 +549,7 @@ const MIN_QUERY = 0;
|
|
|
520
549
|
const MAX_ROWS = 50;
|
|
521
550
|
function useSourcedOptions(field, query, enabled = true) {
|
|
522
551
|
const engine = useFormEngine();
|
|
552
|
+
const text = useFormText();
|
|
523
553
|
const sources = useOptionsSources();
|
|
524
554
|
const name = field.def.optionsSource;
|
|
525
555
|
const source = name === void 0 ? void 0 : sources?.[name];
|
|
@@ -645,8 +675,9 @@ function useSourcedOptions(field, query, enabled = true) {
|
|
|
645
675
|
remote: {
|
|
646
676
|
unavailable: source === void 0,
|
|
647
677
|
busy,
|
|
678
|
+
failed,
|
|
648
679
|
needs: minQueryLength,
|
|
649
|
-
status: statusFor({
|
|
680
|
+
status: statusFor(text, {
|
|
650
681
|
failed,
|
|
651
682
|
busy,
|
|
652
683
|
needs: minQueryLength,
|
|
@@ -663,11 +694,14 @@ function useSourcedOptions(field, query, enabled = true) {
|
|
|
663
694
|
* feedback, and a region that spoke on every successful keystroke would talk over
|
|
664
695
|
* them. A failure is a sentence somebody can act on rather than a code.
|
|
665
696
|
*/
|
|
666
|
-
function statusFor({ failed, busy, needs, query, capped }) {
|
|
667
|
-
if (failed) return "
|
|
668
|
-
if (query.trim().length < needs) return
|
|
669
|
-
if (busy) return "
|
|
670
|
-
if (capped !== null) return
|
|
697
|
+
function statusFor(text, { failed, busy, needs, query, capped }) {
|
|
698
|
+
if (failed) return text("options.failed");
|
|
699
|
+
if (query.trim().length < needs) return text("options.tooShort", { count: needs });
|
|
700
|
+
if (busy) return text("options.searching");
|
|
701
|
+
if (capped !== null) return text("options.capped", {
|
|
702
|
+
shown: capped.shown,
|
|
703
|
+
total: capped.total
|
|
704
|
+
});
|
|
671
705
|
return "";
|
|
672
706
|
}
|
|
673
707
|
//#endregion
|
|
@@ -753,7 +787,7 @@ function FieldShell({ path, field, label, children }) {
|
|
|
753
787
|
function statusState({ sourced, open, matches }) {
|
|
754
788
|
if (sourced.remote === null) return open && matches === 0 ? "empty" : void 0;
|
|
755
789
|
if (sourced.remote.busy) return "busy";
|
|
756
|
-
if (sourced.remote.
|
|
790
|
+
if (sourced.remote.failed) return "failed";
|
|
757
791
|
if (sourced.remote.status !== "") return "hint";
|
|
758
792
|
return open && matches === 0 ? "empty" : void 0;
|
|
759
793
|
}
|
|
@@ -769,11 +803,12 @@ function statusState({ sourced, open, matches }) {
|
|
|
769
803
|
* a red asterisk is a requirement some people cannot perceive.
|
|
770
804
|
*/
|
|
771
805
|
function RequiredHint({ field }) {
|
|
806
|
+
const text = useFormText();
|
|
772
807
|
if (!field.required) return null;
|
|
773
808
|
return /* @__PURE__ */ jsx("span", {
|
|
774
809
|
"data-formancy-part": "required-hint",
|
|
775
810
|
id: field.props.hint.id,
|
|
776
|
-
children: "required"
|
|
811
|
+
children: text("form.required")
|
|
777
812
|
});
|
|
778
813
|
}
|
|
779
814
|
/** One option's element id, in the shape the radio group already uses, so a
|
|
@@ -822,6 +857,7 @@ function OptionPicture({ option }) {
|
|
|
822
857
|
* These were one 2,154-line file — the largest in the repository.
|
|
823
858
|
*/
|
|
824
859
|
function TypeaheadSelectField({ path, label, field }) {
|
|
860
|
+
const text = useFormText();
|
|
825
861
|
/**
|
|
826
862
|
* What is in the box while somebody types, or null when the box is simply
|
|
827
863
|
* showing the answer.
|
|
@@ -933,7 +969,7 @@ function TypeaheadSelectField({ path, label, field }) {
|
|
|
933
969
|
}), /* @__PURE__ */ jsx("ul", {
|
|
934
970
|
id: listboxId,
|
|
935
971
|
role: "listbox",
|
|
936
|
-
"aria-label":
|
|
972
|
+
"aria-label": text("options.suggestions", { label }),
|
|
937
973
|
"data-formancy-part": "typeahead-listbox",
|
|
938
974
|
hidden: !expanded,
|
|
939
975
|
children: matches.map((option) => /* @__PURE__ */ jsx("li", {
|
|
@@ -959,7 +995,7 @@ function TypeaheadSelectField({ path, label, field }) {
|
|
|
959
995
|
open,
|
|
960
996
|
matches: matches.length
|
|
961
997
|
}) },
|
|
962
|
-
children: sourced.remote !== null && sourced.remote.status !== "" ? sourced.remote.status : open && matches.length === 0 && sourced.remote?.busy !== true ? "
|
|
998
|
+
children: sourced.remote !== null && sourced.remote.status !== "" ? sourced.remote.status : open && matches.length === 0 && sourced.remote?.busy !== true ? text("options.noMatch") : ""
|
|
963
999
|
})]
|
|
964
1000
|
});
|
|
965
1001
|
}
|
|
@@ -989,6 +1025,7 @@ function CheckboxField({ path, label }) {
|
|
|
989
1025
|
}
|
|
990
1026
|
function SelectField({ path, label }) {
|
|
991
1027
|
const field = useField(path);
|
|
1028
|
+
const text = useFormText();
|
|
992
1029
|
const sourced = useSourcedOptions({
|
|
993
1030
|
...field,
|
|
994
1031
|
path
|
|
@@ -1000,7 +1037,7 @@ function SelectField({ path, label }) {
|
|
|
1000
1037
|
label,
|
|
1001
1038
|
children: /* @__PURE__ */ jsx("p", {
|
|
1002
1039
|
"data-formancy-part": "options-unavailable",
|
|
1003
|
-
children:
|
|
1040
|
+
children: text("options.unavailable", { source: field.def.optionsSource ?? "" })
|
|
1004
1041
|
})
|
|
1005
1042
|
});
|
|
1006
1043
|
if (field.def.widget === "typeahead") return /* @__PURE__ */ jsx(TypeaheadSelectField, {
|
|
@@ -1096,6 +1133,7 @@ function RadioGroupField({ path, label }) {
|
|
|
1096
1133
|
*/
|
|
1097
1134
|
function FileField({ path, label }) {
|
|
1098
1135
|
const field = useField(path);
|
|
1136
|
+
const text = useFormText();
|
|
1099
1137
|
const upload = useUploader();
|
|
1100
1138
|
const queue = useUploadQueue(path, upload);
|
|
1101
1139
|
const pending = useSyncExternalStore(queue.subscribe, queue.pending, queue.pending);
|
|
@@ -1122,7 +1160,7 @@ function FileField({ path, label }) {
|
|
|
1122
1160
|
children: [
|
|
1123
1161
|
upload === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
1124
1162
|
"data-formancy-part": "file-unavailable",
|
|
1125
|
-
children: "
|
|
1163
|
+
children: text("file.unavailable")
|
|
1126
1164
|
}) : /* @__PURE__ */ jsx("div", {
|
|
1127
1165
|
"data-formancy-part": "file-dropzone",
|
|
1128
1166
|
...over ? { "data-state": "over" } : {},
|
|
@@ -1166,16 +1204,24 @@ function FileField({ path, label }) {
|
|
|
1166
1204
|
"data-formancy-part": "file-up",
|
|
1167
1205
|
disabled: field.disabled,
|
|
1168
1206
|
onClick: () => field.setValue(moved(files, index, index - 1)),
|
|
1169
|
-
children:
|
|
1207
|
+
children: text("file.up", {
|
|
1208
|
+
name: file.name,
|
|
1209
|
+
position: index + 1,
|
|
1210
|
+
count: files.length
|
|
1211
|
+
})
|
|
1170
1212
|
}) : null,
|
|
1171
1213
|
index < files.length - 1 ? /* @__PURE__ */ jsx("button", {
|
|
1172
1214
|
type: "button",
|
|
1173
1215
|
"data-formancy-part": "file-down",
|
|
1174
1216
|
disabled: field.disabled,
|
|
1175
1217
|
onClick: () => field.setValue(moved(files, index, index + 1)),
|
|
1176
|
-
children:
|
|
1218
|
+
children: text("file.down", {
|
|
1219
|
+
name: file.name,
|
|
1220
|
+
position: index + 1,
|
|
1221
|
+
count: files.length
|
|
1222
|
+
})
|
|
1177
1223
|
}) : null,
|
|
1178
|
-
/* @__PURE__ */
|
|
1224
|
+
/* @__PURE__ */ jsx("button", {
|
|
1179
1225
|
type: "button",
|
|
1180
1226
|
disabled: field.disabled,
|
|
1181
1227
|
onClick: () => {
|
|
@@ -1185,14 +1231,15 @@ function FileField({ path, label }) {
|
|
|
1185
1231
|
}]);
|
|
1186
1232
|
field.setValue(files.filter((other) => other.id !== file.id));
|
|
1187
1233
|
},
|
|
1188
|
-
children:
|
|
1234
|
+
children: text("file.remove", { name: file.name })
|
|
1189
1235
|
})
|
|
1190
1236
|
]
|
|
1191
1237
|
}, file.id)),
|
|
1192
1238
|
pending.map((entry) => /* @__PURE__ */ jsx(PendingRow, {
|
|
1193
1239
|
entry,
|
|
1194
1240
|
queue,
|
|
1195
|
-
disabled: field.disabled
|
|
1241
|
+
disabled: field.disabled,
|
|
1242
|
+
text
|
|
1196
1243
|
}, entry.key)),
|
|
1197
1244
|
removed.map(({ at, file }) => /* @__PURE__ */ jsxs("li", {
|
|
1198
1245
|
"data-formancy-part": "file-item",
|
|
@@ -1200,7 +1247,7 @@ function FileField({ path, label }) {
|
|
|
1200
1247
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1201
1248
|
"data-formancy-part": "file-name",
|
|
1202
1249
|
children: file.name
|
|
1203
|
-
}), /* @__PURE__ */
|
|
1250
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
1204
1251
|
type: "button",
|
|
1205
1252
|
disabled: field.disabled,
|
|
1206
1253
|
onClick: () => {
|
|
@@ -1209,7 +1256,7 @@ function FileField({ path, label }) {
|
|
|
1209
1256
|
next.splice(Math.min(at, next.length), 0, file);
|
|
1210
1257
|
field.setValue(next);
|
|
1211
1258
|
},
|
|
1212
|
-
children:
|
|
1259
|
+
children: text("file.undo", { name: file.name })
|
|
1213
1260
|
})]
|
|
1214
1261
|
}, file.id))
|
|
1215
1262
|
]
|
|
@@ -1217,7 +1264,7 @@ function FileField({ path, label }) {
|
|
|
1217
1264
|
/* @__PURE__ */ jsx("p", {
|
|
1218
1265
|
role: "status",
|
|
1219
1266
|
"data-formancy-part": "file-status",
|
|
1220
|
-
children: statusOf(pending)
|
|
1267
|
+
children: statusOf(pending, text)
|
|
1221
1268
|
})
|
|
1222
1269
|
]
|
|
1223
1270
|
});
|
|
@@ -1229,7 +1276,7 @@ function moved(files, from, to) {
|
|
|
1229
1276
|
return next;
|
|
1230
1277
|
}
|
|
1231
1278
|
/** A file not yet in the answer: waiting, being sent, or refused. */
|
|
1232
|
-
function PendingRow({ entry, queue, disabled }) {
|
|
1279
|
+
function PendingRow({ entry, queue, disabled, text }) {
|
|
1233
1280
|
const failed = entry.state === "failed";
|
|
1234
1281
|
return /* @__PURE__ */ jsxs("li", {
|
|
1235
1282
|
"data-formancy-part": "file-item",
|
|
@@ -1241,46 +1288,51 @@ function PendingRow({ entry, queue, disabled }) {
|
|
|
1241
1288
|
}),
|
|
1242
1289
|
entry.state === "waiting" ? /* @__PURE__ */ jsx("span", {
|
|
1243
1290
|
"data-formancy-part": "file-waiting",
|
|
1244
|
-
children: "
|
|
1291
|
+
children: text("file.waiting")
|
|
1245
1292
|
}) : null,
|
|
1246
1293
|
entry.state === "uploading" ? /* @__PURE__ */ jsx("progress", {
|
|
1247
1294
|
"data-formancy-part": "file-progress",
|
|
1248
|
-
"aria-label":
|
|
1295
|
+
"aria-label": text("file.uploading", { name: entry.name }),
|
|
1249
1296
|
...entry.total === void 0 ? {} : {
|
|
1250
1297
|
value: entry.sent,
|
|
1251
1298
|
max: entry.total
|
|
1252
1299
|
}
|
|
1253
1300
|
}) : null,
|
|
1254
|
-
failed ? /* @__PURE__ */
|
|
1301
|
+
failed ? /* @__PURE__ */ jsx("span", {
|
|
1255
1302
|
"data-formancy-part": "file-error",
|
|
1256
|
-
children:
|
|
1303
|
+
children: text("file.notAttached", { reason: entry.reason ?? "" })
|
|
1257
1304
|
}) : null,
|
|
1258
|
-
failed ? /* @__PURE__ */
|
|
1305
|
+
failed ? /* @__PURE__ */ jsx("button", {
|
|
1259
1306
|
type: "button",
|
|
1260
1307
|
disabled,
|
|
1261
1308
|
onClick: () => queue.retry(entry.key),
|
|
1262
|
-
children:
|
|
1263
|
-
"Try ",
|
|
1264
|
-
entry.name,
|
|
1265
|
-
" again"
|
|
1266
|
-
]
|
|
1309
|
+
children: text("file.retry", { name: entry.name })
|
|
1267
1310
|
}) : null,
|
|
1268
1311
|
/* @__PURE__ */ jsx("button", {
|
|
1269
1312
|
type: "button",
|
|
1270
1313
|
disabled,
|
|
1271
1314
|
onClick: () => queue.cancel(entry.key),
|
|
1272
|
-
children: failed ?
|
|
1315
|
+
children: failed ? text("file.dismiss", { name: entry.name }) : text("file.cancel", { name: entry.name })
|
|
1273
1316
|
})
|
|
1274
1317
|
]
|
|
1275
1318
|
});
|
|
1276
1319
|
}
|
|
1277
1320
|
/** What the status region says: the file being sent, or the files refused, by name. */
|
|
1278
|
-
function statusOf(pending) {
|
|
1321
|
+
function statusOf(pending, text) {
|
|
1279
1322
|
const sending = pending.find((entry) => entry.state === "uploading");
|
|
1280
|
-
if (sending !== void 0) return
|
|
1323
|
+
if (sending !== void 0) return text("file.status.uploading", { name: sending.name });
|
|
1281
1324
|
const failed = pending.filter((entry) => entry.state === "failed");
|
|
1282
|
-
if (failed.length === 1) return
|
|
1283
|
-
|
|
1325
|
+
if (failed.length === 1) return text("file.status.failed", {
|
|
1326
|
+
name: failed[0].name,
|
|
1327
|
+
reason: failed[0].reason ?? ""
|
|
1328
|
+
});
|
|
1329
|
+
if (failed.length > 1) {
|
|
1330
|
+
const names = failed.map((entry) => entry.name);
|
|
1331
|
+
return text("file.status.failedSeveral", {
|
|
1332
|
+
count: failed.length,
|
|
1333
|
+
names
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1284
1336
|
return "";
|
|
1285
1337
|
}
|
|
1286
1338
|
/**
|
|
@@ -1384,30 +1436,26 @@ function FileThumbnail({ source }) {
|
|
|
1384
1436
|
function RichTextToolbar({ disabled, label, onCommand }) {
|
|
1385
1437
|
const buttons = useRef([]);
|
|
1386
1438
|
const [active, setActive] = useState(0);
|
|
1439
|
+
const text = useFormText();
|
|
1387
1440
|
const commands = [
|
|
1388
1441
|
{
|
|
1389
1442
|
command: "strong",
|
|
1390
|
-
name: "Bold",
|
|
1391
1443
|
glyph: "B"
|
|
1392
1444
|
},
|
|
1393
1445
|
{
|
|
1394
1446
|
command: "emphasis",
|
|
1395
|
-
name: "Italic",
|
|
1396
1447
|
glyph: "I"
|
|
1397
1448
|
},
|
|
1398
1449
|
{
|
|
1399
1450
|
command: "link",
|
|
1400
|
-
name: "Link",
|
|
1401
1451
|
glyph: "↗"
|
|
1402
1452
|
},
|
|
1403
1453
|
{
|
|
1404
1454
|
command: "bulletList",
|
|
1405
|
-
name: "Bulleted list",
|
|
1406
1455
|
glyph: "•"
|
|
1407
1456
|
},
|
|
1408
1457
|
{
|
|
1409
1458
|
command: "orderedList",
|
|
1410
|
-
name: "Numbered list",
|
|
1411
1459
|
glyph: "1."
|
|
1412
1460
|
}
|
|
1413
1461
|
];
|
|
@@ -1418,7 +1466,7 @@ function RichTextToolbar({ disabled, label, onCommand }) {
|
|
|
1418
1466
|
};
|
|
1419
1467
|
return /* @__PURE__ */ jsx("div", {
|
|
1420
1468
|
role: "toolbar",
|
|
1421
|
-
"aria-label":
|
|
1469
|
+
"aria-label": text("richtext.toolbar", { label }),
|
|
1422
1470
|
"data-formancy-part": "richtext-toolbar",
|
|
1423
1471
|
onKeyDown: (event) => {
|
|
1424
1472
|
if (event.key === "ArrowRight") {
|
|
@@ -1446,7 +1494,7 @@ function RichTextToolbar({ disabled, label, onCommand }) {
|
|
|
1446
1494
|
onFocus: () => setActive(index),
|
|
1447
1495
|
onClick: () => {
|
|
1448
1496
|
if (entry.command === "link") {
|
|
1449
|
-
const href = window.prompt("
|
|
1497
|
+
const href = window.prompt(text("richtext.linkAddress"));
|
|
1450
1498
|
if (href === null || href === "") return;
|
|
1451
1499
|
onCommand("link", href);
|
|
1452
1500
|
return;
|
|
@@ -1458,7 +1506,7 @@ function RichTextToolbar({ disabled, label, onCommand }) {
|
|
|
1458
1506
|
children: entry.glyph
|
|
1459
1507
|
}), /* @__PURE__ */ jsx("span", {
|
|
1460
1508
|
"data-formancy-part": "visually-hidden",
|
|
1461
|
-
children: entry.
|
|
1509
|
+
children: text(`richtext.${entry.command}`)
|
|
1462
1510
|
})]
|
|
1463
1511
|
}, entry.command))
|
|
1464
1512
|
});
|
|
@@ -1644,6 +1692,7 @@ function SelectBoxesSwitch(props) {
|
|
|
1644
1692
|
*/
|
|
1645
1693
|
function TagPickerField({ path, label }) {
|
|
1646
1694
|
const field = useField(path);
|
|
1695
|
+
const text = useFormText();
|
|
1647
1696
|
const options = useResolvedOptions(field);
|
|
1648
1697
|
const chosen = Array.isArray(field.value) ? field.value.map(String) : [];
|
|
1649
1698
|
const [query, setQuery] = useState("");
|
|
@@ -1670,13 +1719,13 @@ function TagPickerField({ path, label }) {
|
|
|
1670
1719
|
"data-formancy-part": "tagpicker",
|
|
1671
1720
|
children: [chosen.length === 0 ? null : /* @__PURE__ */ jsx("ul", {
|
|
1672
1721
|
"data-formancy-part": "tagpicker-chips",
|
|
1673
|
-
"aria-label":
|
|
1722
|
+
"aria-label": text("tagpicker.chosen", { label }),
|
|
1674
1723
|
children: chosen.map((value) => /* @__PURE__ */ jsxs("li", {
|
|
1675
1724
|
"data-formancy-part": "tagpicker-chip",
|
|
1676
1725
|
children: [labelFor(value), /* @__PURE__ */ jsx("button", {
|
|
1677
1726
|
type: "button",
|
|
1678
1727
|
"data-formancy-part": "tagpicker-remove",
|
|
1679
|
-
"aria-label":
|
|
1728
|
+
"aria-label": text("tagpicker.remove", { option: labelFor(value) }),
|
|
1680
1729
|
onClick: () => remove(value),
|
|
1681
1730
|
children: "×"
|
|
1682
1731
|
})]
|
|
@@ -1717,7 +1766,7 @@ function TagPickerField({ path, label }) {
|
|
|
1717
1766
|
}), /* @__PURE__ */ jsx("ul", {
|
|
1718
1767
|
id: listboxId,
|
|
1719
1768
|
role: "listbox",
|
|
1720
|
-
"aria-label":
|
|
1769
|
+
"aria-label": text("options.suggestions", { label }),
|
|
1721
1770
|
"data-formancy-part": "tagpicker-listbox",
|
|
1722
1771
|
hidden: !expanded,
|
|
1723
1772
|
children: matches.map((option) => /* @__PURE__ */ jsx("li", {
|
|
@@ -1803,6 +1852,7 @@ function SelectBoxesField({ path, label }) {
|
|
|
1803
1852
|
*/
|
|
1804
1853
|
function RankingField({ path, label }) {
|
|
1805
1854
|
const field = useField(path);
|
|
1855
|
+
const text = useFormText();
|
|
1806
1856
|
const options = useResolvedOptions(field);
|
|
1807
1857
|
const showError = field.touched && field.errors.length > 0;
|
|
1808
1858
|
const order = Array.isArray(field.value) ? field.value.map(String) : [];
|
|
@@ -1849,7 +1899,7 @@ function RankingField({ path, label }) {
|
|
|
1849
1899
|
/* @__PURE__ */ jsx(RequiredHint, { field }),
|
|
1850
1900
|
ranked.length === 0 ? null : /* @__PURE__ */ jsx("ol", {
|
|
1851
1901
|
"data-formancy-part": "ranking-order",
|
|
1852
|
-
"aria-label":
|
|
1902
|
+
"aria-label": text("ranking.order", { label }),
|
|
1853
1903
|
children: ranked.map((option, index) => /* @__PURE__ */ jsxs("li", {
|
|
1854
1904
|
"data-formancy-part": "ranking-item",
|
|
1855
1905
|
children: [
|
|
@@ -1861,7 +1911,7 @@ function RankingField({ path, label }) {
|
|
|
1861
1911
|
type: "button",
|
|
1862
1912
|
id: buttonId("up", option.value),
|
|
1863
1913
|
"data-formancy-part": "ranking-up",
|
|
1864
|
-
"aria-label":
|
|
1914
|
+
"aria-label": text("ranking.up", { option: option.label }),
|
|
1865
1915
|
"aria-disabled": index === 0 ? true : void 0,
|
|
1866
1916
|
onClick: () => move(option.value, -1),
|
|
1867
1917
|
onBlur: () => field.touch(),
|
|
@@ -1871,7 +1921,7 @@ function RankingField({ path, label }) {
|
|
|
1871
1921
|
type: "button",
|
|
1872
1922
|
id: buttonId("down", option.value),
|
|
1873
1923
|
"data-formancy-part": "ranking-down",
|
|
1874
|
-
"aria-label":
|
|
1924
|
+
"aria-label": text("ranking.down", { option: option.label }),
|
|
1875
1925
|
"aria-disabled": index === ranked.length - 1 ? true : void 0,
|
|
1876
1926
|
onClick: () => move(option.value, 1),
|
|
1877
1927
|
onBlur: () => field.touch(),
|
|
@@ -1881,7 +1931,7 @@ function RankingField({ path, label }) {
|
|
|
1881
1931
|
type: "button",
|
|
1882
1932
|
id: buttonId("remove", option.value),
|
|
1883
1933
|
"data-formancy-part": "ranking-remove",
|
|
1884
|
-
"aria-label":
|
|
1934
|
+
"aria-label": text("ranking.remove", { option: option.label }),
|
|
1885
1935
|
onClick: () => reorder(order.filter((value) => value !== option.value), buttonId("rank", option.value)),
|
|
1886
1936
|
onBlur: () => field.touch(),
|
|
1887
1937
|
children: "×"
|
|
@@ -1891,14 +1941,14 @@ function RankingField({ path, label }) {
|
|
|
1891
1941
|
}),
|
|
1892
1942
|
unranked.length === 0 ? null : /* @__PURE__ */ jsx("ul", {
|
|
1893
1943
|
"data-formancy-part": "ranking-pool",
|
|
1894
|
-
"aria-label":
|
|
1944
|
+
"aria-label": text("ranking.pool", { label }),
|
|
1895
1945
|
children: unranked.map((option) => /* @__PURE__ */ jsx("li", {
|
|
1896
1946
|
"data-formancy-part": "ranking-candidate",
|
|
1897
1947
|
children: /* @__PURE__ */ jsx("button", {
|
|
1898
1948
|
type: "button",
|
|
1899
1949
|
id: buttonId("rank", option.value),
|
|
1900
1950
|
"data-formancy-part": "ranking-add",
|
|
1901
|
-
"aria-label":
|
|
1951
|
+
"aria-label": text("ranking.rank", { option: option.label }),
|
|
1902
1952
|
onClick: () => rank(option.value),
|
|
1903
1953
|
onBlur: () => field.touch(),
|
|
1904
1954
|
children: option.label
|
|
@@ -2166,6 +2216,7 @@ function NumberFallback({ path, label }) {
|
|
|
2166
2216
|
*/
|
|
2167
2217
|
function SignatureField({ path, label }) {
|
|
2168
2218
|
const field = useField(path);
|
|
2219
|
+
const text = useFormText();
|
|
2169
2220
|
const answer = typeof field.value === "object" && field.value !== null ? field.value : {};
|
|
2170
2221
|
const drawn = answer.drawn ?? [];
|
|
2171
2222
|
const [width, height] = field.def?.box ?? [600, 200];
|
|
@@ -2259,7 +2310,7 @@ function SignatureField({ path, label }) {
|
|
|
2259
2310
|
"data-formancy-part": "signature-typed",
|
|
2260
2311
|
type: "text",
|
|
2261
2312
|
value: answer.typed ?? "",
|
|
2262
|
-
"aria-label": "
|
|
2313
|
+
"aria-label": text("signature.typed"),
|
|
2263
2314
|
onChange: (event) => {
|
|
2264
2315
|
const typed = event.target.value;
|
|
2265
2316
|
field.setValue(typed === "" ? null : { typed });
|
|
@@ -2274,7 +2325,7 @@ function SignatureField({ path, label }) {
|
|
|
2274
2325
|
before.current = [];
|
|
2275
2326
|
field.setValue(null);
|
|
2276
2327
|
},
|
|
2277
|
-
children: "
|
|
2328
|
+
children: text("signature.clear")
|
|
2278
2329
|
})
|
|
2279
2330
|
]
|
|
2280
2331
|
})
|
|
@@ -2297,9 +2348,10 @@ function SignatureField({ path, label }) {
|
|
|
2297
2348
|
* heading element either: the spec does not say what level it would be, and
|
|
2298
2349
|
* guessing produces a document outline that skips levels.
|
|
2299
2350
|
*/
|
|
2300
|
-
function StaticField({ label }) {
|
|
2351
|
+
function StaticField({ path, label }) {
|
|
2301
2352
|
return /* @__PURE__ */ jsx("p", {
|
|
2302
2353
|
"data-formancy-part": "static",
|
|
2354
|
+
"data-formancy-field-path": path,
|
|
2303
2355
|
children: label
|
|
2304
2356
|
});
|
|
2305
2357
|
}
|
|
@@ -2429,8 +2481,12 @@ function DateTimeField({ path, label }) {
|
|
|
2429
2481
|
function TextField({ path, label }) {
|
|
2430
2482
|
const field = useField(path);
|
|
2431
2483
|
const scan = useScanner();
|
|
2484
|
+
const words = useFormText();
|
|
2432
2485
|
const [scanning, setScanning] = useState(false);
|
|
2433
|
-
/**
|
|
2486
|
+
/**
|
|
2487
|
+
* A device failure, held here rather than in the field's errors. See below. What went
|
|
2488
|
+
* wrong rather than a sentence about it, so the sentence is the form's language's.
|
|
2489
|
+
*/
|
|
2434
2490
|
const [trouble, setTrouble] = useState(void 0);
|
|
2435
2491
|
/**
|
|
2436
2492
|
* The ONE place a text field's answer is written, typed or scanned.
|
|
@@ -2455,13 +2511,13 @@ function TextField({ path, label }) {
|
|
|
2455
2511
|
});
|
|
2456
2512
|
if (text === null) return;
|
|
2457
2513
|
if (typeof text !== "string") {
|
|
2458
|
-
setTrouble(
|
|
2514
|
+
setTrouble({});
|
|
2459
2515
|
return;
|
|
2460
2516
|
}
|
|
2461
2517
|
commit(mask === void 0 ? text : answerFromText(mask, text));
|
|
2462
2518
|
field.touch();
|
|
2463
2519
|
} catch (error) {
|
|
2464
|
-
setTrouble(
|
|
2520
|
+
setTrouble({ reason: error instanceof Error ? error.message : String(error) });
|
|
2465
2521
|
} finally {
|
|
2466
2522
|
setScanning(false);
|
|
2467
2523
|
}
|
|
@@ -2500,14 +2556,18 @@ function TextField({ path, label }) {
|
|
|
2500
2556
|
onClick: () => {
|
|
2501
2557
|
read();
|
|
2502
2558
|
},
|
|
2503
|
-
children: [
|
|
2504
|
-
"
|
|
2505
|
-
|
|
2506
|
-
|
|
2559
|
+
children: [
|
|
2560
|
+
words("scanner.scan"),
|
|
2561
|
+
" ",
|
|
2562
|
+
/* @__PURE__ */ jsx("span", {
|
|
2563
|
+
"data-formancy-part": "visually-hidden",
|
|
2564
|
+
children: label
|
|
2565
|
+
})
|
|
2566
|
+
]
|
|
2507
2567
|
}), /* @__PURE__ */ jsx("p", {
|
|
2508
2568
|
role: "status",
|
|
2509
2569
|
"data-formancy-part": "scanner-status",
|
|
2510
|
-
children: scanning ? "
|
|
2570
|
+
children: scanning ? words("scanner.scanning") : trouble === void 0 ? "" : trouble.reason === void 0 ? words("scanner.noText") : words("scanner.failed", { reason: trouble.reason })
|
|
2511
2571
|
})] }) : null]
|
|
2512
2572
|
});
|
|
2513
2573
|
}
|
|
@@ -2553,6 +2613,7 @@ function FormancyForm(props) {
|
|
|
2553
2613
|
}
|
|
2554
2614
|
function SubmitButton({ submitLabel, onSubmit, onFailedNavigate }) {
|
|
2555
2615
|
const engine = useFormEngine();
|
|
2616
|
+
const text = useFormText();
|
|
2556
2617
|
const submit = useSubmit();
|
|
2557
2618
|
return /* @__PURE__ */ jsx("button", {
|
|
2558
2619
|
type: "button",
|
|
@@ -2572,7 +2633,7 @@ function SubmitButton({ submitLabel, onSubmit, onFailedNavigate }) {
|
|
|
2572
2633
|
errors: outcome.errors
|
|
2573
2634
|
});
|
|
2574
2635
|
},
|
|
2575
|
-
children: submitLabel ?? "
|
|
2636
|
+
children: submitLabel ?? text("form.submit")
|
|
2576
2637
|
});
|
|
2577
2638
|
}
|
|
2578
2639
|
function FlatForm(props) {
|
|
@@ -2580,6 +2641,7 @@ function FlatForm(props) {
|
|
|
2580
2641
|
}
|
|
2581
2642
|
function PagedForm(props) {
|
|
2582
2643
|
const engine = useFormEngine();
|
|
2644
|
+
const text = useFormText();
|
|
2583
2645
|
const wizard = useWizard();
|
|
2584
2646
|
const pages = engine.pages().map((page, index) => ({
|
|
2585
2647
|
...page,
|
|
@@ -2588,7 +2650,7 @@ function PagedForm(props) {
|
|
|
2588
2650
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2589
2651
|
/* @__PURE__ */ jsx("nav", {
|
|
2590
2652
|
"data-formancy-part": "stepper",
|
|
2591
|
-
"aria-label": "
|
|
2653
|
+
"aria-label": text("form.progress"),
|
|
2592
2654
|
children: /* @__PURE__ */ jsx("ol", { children: pages.map((page) => /* @__PURE__ */ jsx("li", {
|
|
2593
2655
|
"aria-current": page.index === wizard.page ? "step" : void 0,
|
|
2594
2656
|
children: engine.text(page.def.label) ?? page.key
|
|
@@ -2603,11 +2665,11 @@ function PagedForm(props) {
|
|
|
2603
2665
|
children: [wizard.canGoBack ? /* @__PURE__ */ jsx("button", {
|
|
2604
2666
|
type: "button",
|
|
2605
2667
|
onClick: () => wizard.back(),
|
|
2606
|
-
children: "
|
|
2668
|
+
children: text("form.back")
|
|
2607
2669
|
}) : null, wizard.canGoNext ? /* @__PURE__ */ jsx("button", {
|
|
2608
2670
|
type: "button",
|
|
2609
2671
|
onClick: () => void wizard.next(),
|
|
2610
|
-
children: "
|
|
2672
|
+
children: text("form.next")
|
|
2611
2673
|
}) : /* @__PURE__ */ jsx(SubmitButton, {
|
|
2612
2674
|
...props,
|
|
2613
2675
|
onFailedNavigate: (page) => wizard.goTo(page)
|
|
@@ -2626,13 +2688,20 @@ function FieldList({ labels, registry, page, layout }) {
|
|
|
2626
2688
|
schema,
|
|
2627
2689
|
nodes: arrangement.nodes,
|
|
2628
2690
|
locale: engine.locale(),
|
|
2629
|
-
shows: page === void 0 ? void 0 : (path) => engine
|
|
2691
|
+
shows: page === void 0 ? void 0 : (path) => placedPage(engine, path) === page,
|
|
2630
2692
|
renderField: (path) => {
|
|
2631
2693
|
if (repeaterWires.includes(path)) return /* @__PURE__ */ jsx(RepeaterSection, {
|
|
2632
2694
|
wire: path,
|
|
2633
2695
|
labels,
|
|
2634
2696
|
registry
|
|
2635
2697
|
}, path);
|
|
2698
|
+
const group = placedGroup(engine, path);
|
|
2699
|
+
if (group !== void 0) return /* @__PURE__ */ jsx(GroupSection, {
|
|
2700
|
+
path,
|
|
2701
|
+
group,
|
|
2702
|
+
labels,
|
|
2703
|
+
registry
|
|
2704
|
+
}, path);
|
|
2636
2705
|
return /* @__PURE__ */ jsx(FieldSlot, {
|
|
2637
2706
|
path,
|
|
2638
2707
|
fallbackLabel: labels?.[path],
|
|
@@ -2664,13 +2733,49 @@ function FieldSlot({ path, fallbackLabel, registry }) {
|
|
|
2664
2733
|
label
|
|
2665
2734
|
});
|
|
2666
2735
|
}
|
|
2736
|
+
/**
|
|
2737
|
+
* A group an arrangement places whole: its fields, under its label, the way a labelled
|
|
2738
|
+
* section is drawn — a real group when it has a name, a box when it has none. What it holds
|
|
2739
|
+
* and in which order is `@formancy/core`'s, shared with the Angular renderer (0151).
|
|
2740
|
+
*/
|
|
2741
|
+
function GroupSection({ path, group, labels, registry }) {
|
|
2742
|
+
const engine = useFormEngine();
|
|
2743
|
+
const headingId = useId();
|
|
2744
|
+
const label = resolveText(engine.schema(), group.def.label, engine.locale());
|
|
2745
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2746
|
+
"data-formancy-part": "group",
|
|
2747
|
+
"data-formancy-field-path": path,
|
|
2748
|
+
...label === void 0 ? {} : {
|
|
2749
|
+
role: "group",
|
|
2750
|
+
"aria-labelledby": headingId
|
|
2751
|
+
},
|
|
2752
|
+
children: [
|
|
2753
|
+
label === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
2754
|
+
id: headingId,
|
|
2755
|
+
"data-formancy-part": "group-heading",
|
|
2756
|
+
children: label
|
|
2757
|
+
}),
|
|
2758
|
+
group.fields.map((wire) => /* @__PURE__ */ jsx(FieldSlot, {
|
|
2759
|
+
path: wire,
|
|
2760
|
+
fallbackLabel: labels?.[wire],
|
|
2761
|
+
registry
|
|
2762
|
+
}, wire)),
|
|
2763
|
+
group.repeaters.map((wire) => /* @__PURE__ */ jsx(RepeaterSection, {
|
|
2764
|
+
wire,
|
|
2765
|
+
labels,
|
|
2766
|
+
registry
|
|
2767
|
+
}, wire))
|
|
2768
|
+
]
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2667
2771
|
function RepeaterSection({ wire, labels, registry }) {
|
|
2668
2772
|
const engine = useFormEngine();
|
|
2773
|
+
const text = useFormText();
|
|
2669
2774
|
const repeater = useRepeater(wire);
|
|
2670
2775
|
const def = engine.repeaters().find((candidate) => candidate.wire === wire)?.def;
|
|
2671
2776
|
const label = engine.text(def?.label) ?? labels?.[wire] ?? wire;
|
|
2672
|
-
const addLabel = def?.addLabel ??
|
|
2673
|
-
const removeLabel = def?.removeLabel ??
|
|
2777
|
+
const addLabel = def?.addLabel ?? text("repeater.add", { label });
|
|
2778
|
+
const removeLabel = def?.removeLabel ?? text("repeater.remove", { label });
|
|
2674
2779
|
const fallbackFor = (instanceWire) => {
|
|
2675
2780
|
const template = instanceWire.replace(/\[\d+\]/, "[]");
|
|
2676
2781
|
return labels?.[template] ?? labels?.[instanceWire];
|
|
@@ -2724,7 +2829,11 @@ function RepeaterSection({ wire, labels, registry }) {
|
|
|
2724
2829
|
onClick: () => repeater.removeRow(index),
|
|
2725
2830
|
children: /* @__PURE__ */ jsx("span", {
|
|
2726
2831
|
"data-formancy-part": "row-action-text",
|
|
2727
|
-
children:
|
|
2832
|
+
children: text("repeater.removeRow", {
|
|
2833
|
+
remove: removeLabel,
|
|
2834
|
+
position: index + 1,
|
|
2835
|
+
count: repeater.rowCount
|
|
2836
|
+
})
|
|
2728
2837
|
})
|
|
2729
2838
|
}),
|
|
2730
2839
|
index > 0 ? /* @__PURE__ */ jsx("button", {
|
|
@@ -2733,7 +2842,11 @@ function RepeaterSection({ wire, labels, registry }) {
|
|
|
2733
2842
|
onClick: () => repeater.moveRow(index, index - 1),
|
|
2734
2843
|
children: /* @__PURE__ */ jsx("span", {
|
|
2735
2844
|
"data-formancy-part": "row-action-text",
|
|
2736
|
-
children:
|
|
2845
|
+
children: text("repeater.moveUp", {
|
|
2846
|
+
label,
|
|
2847
|
+
position: index + 1,
|
|
2848
|
+
count: repeater.rowCount
|
|
2849
|
+
})
|
|
2737
2850
|
})
|
|
2738
2851
|
}) : null,
|
|
2739
2852
|
index < repeater.rowCount - 1 ? /* @__PURE__ */ jsx("button", {
|
|
@@ -2742,7 +2855,11 @@ function RepeaterSection({ wire, labels, registry }) {
|
|
|
2742
2855
|
onClick: () => repeater.moveRow(index, index + 1),
|
|
2743
2856
|
children: /* @__PURE__ */ jsx("span", {
|
|
2744
2857
|
"data-formancy-part": "row-action-text",
|
|
2745
|
-
children:
|
|
2858
|
+
children: text("repeater.moveDown", {
|
|
2859
|
+
label,
|
|
2860
|
+
position: index + 1,
|
|
2861
|
+
count: repeater.rowCount
|
|
2862
|
+
})
|
|
2746
2863
|
})
|
|
2747
2864
|
}) : null
|
|
2748
2865
|
] });
|
|
@@ -2777,6 +2894,7 @@ function RepeaterSection({ wire, labels, registry }) {
|
|
|
2777
2894
|
}, rowId));
|
|
2778
2895
|
return /* @__PURE__ */ jsxs("fieldset", {
|
|
2779
2896
|
"data-formancy-part": "repeater",
|
|
2897
|
+
"data-formancy-field-path": wire,
|
|
2780
2898
|
children: [
|
|
2781
2899
|
/* @__PURE__ */ jsx("legend", {
|
|
2782
2900
|
"data-formancy-part": "repeater-legend",
|
|
@@ -2844,6 +2962,7 @@ const DEFAULT_COMPONENTS = {
|
|
|
2844
2962
|
*/
|
|
2845
2963
|
function ErrorSummary({ labels }) {
|
|
2846
2964
|
const engine = useFormEngine();
|
|
2965
|
+
const text = useFormText();
|
|
2847
2966
|
const subscribe = useCallback((onChange) => engine.subscribe(onChange), [engine]);
|
|
2848
2967
|
const getErrors = useCallback(() => engine.visibleErrors(), [engine]);
|
|
2849
2968
|
const errors = useSyncExternalStore(subscribe, getErrors, getErrors);
|
|
@@ -2861,7 +2980,7 @@ function ErrorSummary({ labels }) {
|
|
|
2861
2980
|
ref: region,
|
|
2862
2981
|
children: [/* @__PURE__ */ jsx("h2", {
|
|
2863
2982
|
"data-formancy-part": "error-summary-heading",
|
|
2864
|
-
children: errors.
|
|
2983
|
+
children: text("errors.heading", { count: errors.length })
|
|
2865
2984
|
}), /* @__PURE__ */ jsx("ul", { children: errors.map(({ path, codes }) => {
|
|
2866
2985
|
const controlId = engine.getFieldSnapshot(parsePath(path)).ids.control;
|
|
2867
2986
|
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
|
|
@@ -2870,7 +2989,10 @@ function ErrorSummary({ labels }) {
|
|
|
2870
2989
|
event.preventDefault();
|
|
2871
2990
|
focusControl(document.getElementById(controlId));
|
|
2872
2991
|
},
|
|
2873
|
-
children:
|
|
2992
|
+
children: text("errors.entry", {
|
|
2993
|
+
label: labelFor(path),
|
|
2994
|
+
codes: codes.join(", ")
|
|
2995
|
+
})
|
|
2874
2996
|
}) }, path);
|
|
2875
2997
|
}) })]
|
|
2876
2998
|
});
|
|
@@ -2879,6 +3001,7 @@ function ErrorSummary({ labels }) {
|
|
|
2879
3001
|
//#region src/resume-notice.tsx
|
|
2880
3002
|
function ResumeNotice({ migration, labels }) {
|
|
2881
3003
|
const region = useRef(null);
|
|
3004
|
+
const text = useFormText();
|
|
2882
3005
|
useEffect(() => {
|
|
2883
3006
|
if (migration !== void 0) region.current?.focus();
|
|
2884
3007
|
}, [migration]);
|
|
@@ -2886,25 +3009,27 @@ function ResumeNotice({ migration, labels }) {
|
|
|
2886
3009
|
const setAside = migration.changes.map((change) => change.path).filter((path) => path !== void 0);
|
|
2887
3010
|
return /* @__PURE__ */ jsxs("div", {
|
|
2888
3011
|
role: "region",
|
|
2889
|
-
"aria-label": "
|
|
3012
|
+
"aria-label": text("resume.heading"),
|
|
2890
3013
|
"data-formancy-part": "resume-notice",
|
|
2891
3014
|
"data-state": migration.severity,
|
|
2892
3015
|
tabIndex: -1,
|
|
2893
3016
|
ref: region,
|
|
2894
3017
|
children: [/* @__PURE__ */ jsx("h2", {
|
|
2895
3018
|
"data-formancy-part": "resume-notice-heading",
|
|
2896
|
-
children: "
|
|
3019
|
+
children: text("resume.heading")
|
|
2897
3020
|
}), migration.severity === "breaking" ? /* @__PURE__ */ jsxs("p", { children: [
|
|
2898
|
-
"
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
3021
|
+
text("resume.breaking.kept"),
|
|
3022
|
+
" ",
|
|
3023
|
+
/* @__PURE__ */ jsx("strong", { children: text("resume.breaking.cannotSubmit") }),
|
|
3024
|
+
" ",
|
|
3025
|
+
text("resume.breaking.restart")
|
|
3026
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", { children: text("resume.setAside", { count: setAside.length }) }), setAside.length === 0 ? null : /* @__PURE__ */ jsx("ul", {
|
|
2902
3027
|
"data-formancy-part": "resume-notice-list",
|
|
2903
3028
|
children: setAside.map((path) => /* @__PURE__ */ jsx("li", { children: labels?.[path] ?? path }, path))
|
|
2904
3029
|
})] })]
|
|
2905
3030
|
});
|
|
2906
3031
|
}
|
|
2907
3032
|
//#endregion
|
|
2908
|
-
export { ErrorSummary, FormancyForm, FormancyProvider, OptionsSourcesProvider, ResumeNotice, RichText, RichTextEditorProvider, ScannerProvider, UploaderProvider, useField, useFormEngine, useOptionsSources, useRepeater, useRichTextEditorFactory, useScanner, useSubmit, useUploader, useWizard };
|
|
3033
|
+
export { ErrorSummary, FormancyForm, FormancyProvider, OptionsSourcesProvider, ResumeNotice, RichText, RichTextEditorProvider, ScannerProvider, UploaderProvider, useField, useFormEngine, useFormText, useOptionsSources, useRepeater, useRichTextEditorFactory, useScanner, useSubmit, useUploader, useWizard };
|
|
2909
3034
|
|
|
2910
3035
|
//# sourceMappingURL=index.mjs.map
|