@usefillo/react 0.10.0 → 0.12.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.ts +93 -14
- package/dist/index.js +798 -339
- package/dist/styles.css +257 -57
- package/dist/styles.unlayered.css +257 -57
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
useEffect as useEffect8,
|
|
7
7
|
useId as useId2,
|
|
8
8
|
useMemo as useMemo5,
|
|
9
|
-
useRef as
|
|
9
|
+
useRef as useRef8,
|
|
10
10
|
useState as useState6,
|
|
11
11
|
useSyncExternalStore as useSyncExternalStore2
|
|
12
12
|
} from "react";
|
|
@@ -15,15 +15,17 @@ import {
|
|
|
15
15
|
createClient,
|
|
16
16
|
formSchemasEqual,
|
|
17
17
|
isBuildTimeDevEnv as isBuildTimeDevEnv2,
|
|
18
|
+
isField as isField2,
|
|
18
19
|
isFilloError as isFilloError2,
|
|
19
20
|
isLikelyDevEnv,
|
|
20
21
|
needsExplicitSubmit,
|
|
21
22
|
normalizeFormSchema,
|
|
22
23
|
normalizeFormTheme,
|
|
23
24
|
reachableFields,
|
|
24
|
-
reachablePageSequence
|
|
25
|
+
reachablePageSequence,
|
|
26
|
+
resolveThemeAppearance
|
|
25
27
|
} from "@usefillo/core";
|
|
26
|
-
import { resolveStrings, slotClass as slotClass3 } from "@usefillo/core";
|
|
28
|
+
import { REQUIRED_FIELD_MESSAGE as REQUIRED_FIELD_MESSAGE2, resolveStrings, slotClass as slotClass3 } from "@usefillo/core";
|
|
27
29
|
|
|
28
30
|
// src/appearance.tsx
|
|
29
31
|
import { createContext, useContext } from "react";
|
|
@@ -155,6 +157,12 @@ var FilloChromeContext = createContext2(null);
|
|
|
155
157
|
function useFilloChrome() {
|
|
156
158
|
return useContext2(FilloChromeContext);
|
|
157
159
|
}
|
|
160
|
+
var noopAnnounce = () => {
|
|
161
|
+
};
|
|
162
|
+
var FilloAnnounceContext = createContext2(noopAnnounce);
|
|
163
|
+
function useFilloAnnounce() {
|
|
164
|
+
return useContext2(FilloAnnounceContext);
|
|
165
|
+
}
|
|
158
166
|
function useFilloInstanceId() {
|
|
159
167
|
const instanceId = useContext2(FilloInstanceIdContext);
|
|
160
168
|
const fallbackId = useId().replace(/:/g, "");
|
|
@@ -328,6 +336,7 @@ function useCodeFormSync(form, client, onError, options) {
|
|
|
328
336
|
accepting: void 0,
|
|
329
337
|
acceptingReason: void 0,
|
|
330
338
|
uploadsAvailable: void 0,
|
|
339
|
+
uploadFileSizeLimitMb: void 0,
|
|
331
340
|
resolvedSchema: void 0,
|
|
332
341
|
resolvedTheme: void 0,
|
|
333
342
|
warning: void 0,
|
|
@@ -390,6 +399,7 @@ function useCodeFormSync(form, client, onError, options) {
|
|
|
390
399
|
accepting: r.accepting,
|
|
391
400
|
acceptingReason: r.acceptingReason,
|
|
392
401
|
uploadsAvailable: r.uploadsAvailable,
|
|
402
|
+
uploadFileSizeLimitMb: r.uploadFileSizeLimitMb,
|
|
393
403
|
resolvedSchema: r.resolvedSchema,
|
|
394
404
|
resolvedTheme: r.resolvedTheme,
|
|
395
405
|
warning: r.warning,
|
|
@@ -451,6 +461,7 @@ function useCodeFormSync(form, client, onError, options) {
|
|
|
451
461
|
accepting: synced.accepting,
|
|
452
462
|
acceptingReason: synced.acceptingReason,
|
|
453
463
|
uploadsAvailable: synced.uploadsAvailable,
|
|
464
|
+
uploadFileSizeLimitMb: synced.uploadFileSizeLimitMb,
|
|
454
465
|
resolvedSchema: synced.resolvedSchema,
|
|
455
466
|
resolvedTheme: synced.resolvedTheme,
|
|
456
467
|
warning: synced.warning,
|
|
@@ -467,12 +478,26 @@ function useCodeFormSync(form, client, onError, options) {
|
|
|
467
478
|
}
|
|
468
479
|
|
|
469
480
|
// src/fields.tsx
|
|
470
|
-
import {
|
|
471
|
-
|
|
481
|
+
import {
|
|
482
|
+
formatAnswer,
|
|
483
|
+
formatGroupedNumber,
|
|
484
|
+
isField,
|
|
485
|
+
isValidPartialNumberText,
|
|
486
|
+
localeForNotation,
|
|
487
|
+
parseGroupedNumber,
|
|
488
|
+
pipeBlock,
|
|
489
|
+
radioGroupStep,
|
|
490
|
+
REQUIRED_FIELD_MESSAGE,
|
|
491
|
+
shouldAutoSubmit,
|
|
492
|
+
slotClass as slotClass2,
|
|
493
|
+
visibleFields
|
|
494
|
+
} from "@usefillo/core";
|
|
495
|
+
import { memo, useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef6, useState as useState5 } from "react";
|
|
472
496
|
|
|
473
497
|
// src/phone.tsx
|
|
474
498
|
import {
|
|
475
499
|
PHONE_COUNTRIES,
|
|
500
|
+
PHONE_PICKER_COUNTRIES,
|
|
476
501
|
countryByIso,
|
|
477
502
|
countryByTimeZone,
|
|
478
503
|
digitsOnly,
|
|
@@ -524,8 +549,9 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
524
549
|
const guess = countryByTimeZone(browserTimeZone()) ?? countryByIso(localeCountry());
|
|
525
550
|
if (guess) setCountry(guess);
|
|
526
551
|
}, []);
|
|
552
|
+
const [pendingRaw, setPendingRaw] = useState2(null);
|
|
527
553
|
const national = nationalFor(stored, country);
|
|
528
|
-
const display = formatNational(country, national);
|
|
554
|
+
const display = pendingRaw ?? formatNational(country, national);
|
|
529
555
|
const inputRef = useRef3(null);
|
|
530
556
|
const caretDigits = useRef3(null);
|
|
531
557
|
useLayoutEffect(() => {
|
|
@@ -552,15 +578,23 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
552
578
|
const caret = el.selectionStart ?? raw.length;
|
|
553
579
|
caretDigits.current = digitsOnly(raw.slice(0, caret)).length;
|
|
554
580
|
if (raw.trimStart().startsWith("+")) {
|
|
555
|
-
const p = parsePhone(raw);
|
|
581
|
+
const p = parsePhone(raw, country, { previousDigits: national });
|
|
582
|
+
if (p.pending) {
|
|
583
|
+
setPendingRaw(p.raw ?? raw);
|
|
584
|
+
setValue(p.raw ?? raw);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
setPendingRaw(null);
|
|
556
588
|
if (p.country) setCountry(p.country);
|
|
557
589
|
commit(p.country ?? country, p.country ? p.national : digitsOnly(raw));
|
|
558
590
|
return;
|
|
559
591
|
}
|
|
592
|
+
setPendingRaw(null);
|
|
560
593
|
commit(country, digitsOnly(raw));
|
|
561
594
|
}
|
|
562
595
|
function pickCountry(c) {
|
|
563
596
|
touched.current = true;
|
|
597
|
+
setPendingRaw(null);
|
|
564
598
|
setCountry(c);
|
|
565
599
|
commit(c, national);
|
|
566
600
|
inputRef.current?.focus();
|
|
@@ -593,7 +627,7 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
593
627
|
}
|
|
594
628
|
)
|
|
595
629
|
] }),
|
|
596
|
-
error && /* @__PURE__ */ jsx2("p", { className: slots.error, "data-fillo": "error", id: ids.errorId,
|
|
630
|
+
error && /* @__PURE__ */ jsx2("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
597
631
|
] });
|
|
598
632
|
}
|
|
599
633
|
function CountrySelect({
|
|
@@ -601,6 +635,8 @@ function CountrySelect({
|
|
|
601
635
|
onPick,
|
|
602
636
|
labelledBy
|
|
603
637
|
}) {
|
|
638
|
+
const strings = useStrings();
|
|
639
|
+
const announce = useFilloAnnounce();
|
|
604
640
|
const [open, setOpen] = useState2(false);
|
|
605
641
|
const [query, setQuery] = useState2("");
|
|
606
642
|
const [active, setActive] = useState2(0);
|
|
@@ -609,19 +645,22 @@ function CountrySelect({
|
|
|
609
645
|
const triggerRef = useRef3(null);
|
|
610
646
|
const popoverRef = useRef3(null);
|
|
611
647
|
const searchRef = useRef3(null);
|
|
648
|
+
const seedRef = useRef3(null);
|
|
612
649
|
const listId = `${labelledBy}-countries`;
|
|
613
650
|
const matches = useMemo3(() => {
|
|
614
651
|
const q = query.trim().toLowerCase();
|
|
615
|
-
if (!q) return
|
|
652
|
+
if (!q) return PHONE_PICKER_COUNTRIES;
|
|
616
653
|
const qDigits = q.replace(/[^\d]/g, "");
|
|
617
|
-
return
|
|
654
|
+
return PHONE_PICKER_COUNTRIES.filter(
|
|
618
655
|
(c) => c.name.toLowerCase().includes(q) || c.iso2.toLowerCase() === q || qDigits.length > 0 && c.dialCode.startsWith(qDigits)
|
|
619
656
|
);
|
|
620
657
|
}, [query]);
|
|
621
658
|
useEffect3(() => {
|
|
622
659
|
if (!open) return;
|
|
623
|
-
|
|
624
|
-
|
|
660
|
+
const seed = seedRef.current ?? "";
|
|
661
|
+
seedRef.current = null;
|
|
662
|
+
setQuery(seed);
|
|
663
|
+
setActive(seed ? 0 : Math.max(0, PHONE_PICKER_COUNTRIES.indexOf(country)));
|
|
625
664
|
const id = requestAnimationFrame(() => searchRef.current?.focus());
|
|
626
665
|
return () => cancelAnimationFrame(id);
|
|
627
666
|
}, [open, country]);
|
|
@@ -648,8 +687,15 @@ function CountrySelect({
|
|
|
648
687
|
if (!open) return;
|
|
649
688
|
document.getElementById(`${listId}-opt-${active}`)?.scrollIntoView({ block: "nearest" });
|
|
650
689
|
}, [active, open, listId]);
|
|
690
|
+
const resultsAnnouncement = strings.phoneResultsCount(matches.length);
|
|
691
|
+
useEffect3(() => {
|
|
692
|
+
if (!open || !query.trim()) return;
|
|
693
|
+
const id = setTimeout(() => announce(resultsAnnouncement), 300);
|
|
694
|
+
return () => clearTimeout(id);
|
|
695
|
+
}, [open, query, resultsAnnouncement, announce]);
|
|
651
696
|
function choose(c) {
|
|
652
697
|
if (!c) return;
|
|
698
|
+
announce(strings.phoneCountrySelected(c.name));
|
|
653
699
|
onPick(c);
|
|
654
700
|
setOpen(false);
|
|
655
701
|
}
|
|
@@ -669,7 +715,30 @@ function CountrySelect({
|
|
|
669
715
|
triggerRef.current?.focus();
|
|
670
716
|
}
|
|
671
717
|
}
|
|
672
|
-
|
|
718
|
+
function onTriggerKeyDown(e) {
|
|
719
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
720
|
+
e.preventDefault();
|
|
721
|
+
setOpen(true);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
if (e.key.length === 1 && e.key !== " " && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
|
725
|
+
e.preventDefault();
|
|
726
|
+
seedRef.current = e.key;
|
|
727
|
+
setOpen(true);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function onCompositeBlur(e) {
|
|
731
|
+
if (!open) return;
|
|
732
|
+
const next = e.relatedTarget;
|
|
733
|
+
if (next) {
|
|
734
|
+
if (!rootRef.current?.contains(next)) setOpen(false);
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
queueMicrotask(() => {
|
|
738
|
+
if (!rootRef.current?.contains(document.activeElement)) setOpen(false);
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
return /* @__PURE__ */ jsxs2("div", { className: "fillo-phone-country", ref: rootRef, onBlur: onCompositeBlur, children: [
|
|
673
742
|
/* @__PURE__ */ jsxs2(
|
|
674
743
|
"button",
|
|
675
744
|
{
|
|
@@ -681,6 +750,7 @@ function CountrySelect({
|
|
|
681
750
|
"aria-controls": open ? listId : void 0,
|
|
682
751
|
"aria-label": `Country: ${country.name} (+${country.dialCode})`,
|
|
683
752
|
onClick: () => setOpen((o) => !o),
|
|
753
|
+
onKeyDown: onTriggerKeyDown,
|
|
684
754
|
children: [
|
|
685
755
|
/* @__PURE__ */ jsx2("span", { className: "fillo-phone-flag-emoji", "aria-hidden": "true", children: flagEmoji(country.iso2) }),
|
|
686
756
|
/* @__PURE__ */ jsxs2("span", { className: "fillo-phone-dial", children: [
|
|
@@ -737,7 +807,7 @@ function CountrySelect({
|
|
|
737
807
|
},
|
|
738
808
|
c.iso2
|
|
739
809
|
)),
|
|
740
|
-
matches.length === 0 && /* @__PURE__ */ jsx2("li", { className: "fillo-phone-empty", children: "No matches" })
|
|
810
|
+
matches.length === 0 && /* @__PURE__ */ jsx2("li", { className: "fillo-phone-empty", role: "option", "aria-disabled": "true", children: "No matches" })
|
|
741
811
|
] })
|
|
742
812
|
] })
|
|
743
813
|
] });
|
|
@@ -752,6 +822,7 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
752
822
|
const strings = useStrings();
|
|
753
823
|
const typedInputId = `${ids.inputId}-typed`;
|
|
754
824
|
const canvasRef = useRef4(null);
|
|
825
|
+
const typedInputRef = useRef4(null);
|
|
755
826
|
const drawing = useRef4(false);
|
|
756
827
|
const [hasInk, setHasInk] = useState3(Boolean(value));
|
|
757
828
|
const [typedName, setTypedName] = useState3("");
|
|
@@ -848,6 +919,7 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
848
919
|
setHasInk(false);
|
|
849
920
|
setTypedName("");
|
|
850
921
|
setValue(null);
|
|
922
|
+
typedInputRef.current?.focus();
|
|
851
923
|
}
|
|
852
924
|
const describedBy = [field.description ? ids.descriptionId : null, error ? ids.errorId : null].filter(Boolean).join(" ") || void 0;
|
|
853
925
|
return /* @__PURE__ */ jsxs3("div", { ...slots.wrapperProps(`fillo-field fillo-field--signature${error ? " fillo-field--error" : ""}`), children: [
|
|
@@ -869,7 +941,8 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
869
941
|
{
|
|
870
942
|
ref: canvasRef,
|
|
871
943
|
className: "fillo-signature-canvas",
|
|
872
|
-
|
|
944
|
+
role: "img",
|
|
945
|
+
"aria-label": hasInk ? strings.signatureSigned : strings.signatureEmpty,
|
|
873
946
|
onPointerDown: start,
|
|
874
947
|
onPointerMove: move,
|
|
875
948
|
onPointerUp: end,
|
|
@@ -886,6 +959,7 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
886
959
|
"input",
|
|
887
960
|
{
|
|
888
961
|
id: typedInputId,
|
|
962
|
+
ref: typedInputRef,
|
|
889
963
|
type: "text",
|
|
890
964
|
className: "fillo-input fillo-signature-type-input",
|
|
891
965
|
autoComplete: "name",
|
|
@@ -904,7 +978,7 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
904
978
|
]
|
|
905
979
|
}
|
|
906
980
|
),
|
|
907
|
-
error && /* @__PURE__ */ jsx3("p", { className: slots.error, "data-fillo": "error", id: ids.errorId,
|
|
981
|
+
error && /* @__PURE__ */ jsx3("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
908
982
|
] });
|
|
909
983
|
}
|
|
910
984
|
|
|
@@ -926,7 +1000,22 @@ function formatBytes(bytes) {
|
|
|
926
1000
|
if (bytes < 1024 ** 3) return `${(bytes / 1024 ** 2).toFixed(1)} MB`;
|
|
927
1001
|
return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
|
|
928
1002
|
}
|
|
929
|
-
function
|
|
1003
|
+
function uploadFailureMessage(error, strings) {
|
|
1004
|
+
if (error instanceof Error && error.name === "FilloError") {
|
|
1005
|
+
const status = error.status;
|
|
1006
|
+
if (status !== void 0 && status >= 500) return strings.uploadUnavailable;
|
|
1007
|
+
return error.message || strings.uploadFailed;
|
|
1008
|
+
}
|
|
1009
|
+
return strings.uploadFailed;
|
|
1010
|
+
}
|
|
1011
|
+
function FileUploadField({
|
|
1012
|
+
field,
|
|
1013
|
+
value,
|
|
1014
|
+
error,
|
|
1015
|
+
setValue,
|
|
1016
|
+
api,
|
|
1017
|
+
ids: providedIds
|
|
1018
|
+
}) {
|
|
930
1019
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
931
1020
|
const slots = useFieldSlots(field, error);
|
|
932
1021
|
const strings = useStrings();
|
|
@@ -952,11 +1041,13 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
952
1041
|
const filesRef = useRef5(files);
|
|
953
1042
|
filesRef.current = files;
|
|
954
1043
|
const maxFiles = schema.maxFiles ?? 1;
|
|
955
|
-
const
|
|
1044
|
+
const configuredMaxMb = schema.maxFileSizeMb ?? 500;
|
|
1045
|
+
const maxMb = chrome?.uploadFileSizeLimitMb ? Math.min(configuredMaxMb, chrome.uploadFileSizeLimitMb) : configuredMaxMb;
|
|
956
1046
|
const maxBytes = maxMb * 1024 * 1024;
|
|
1047
|
+
const renderOnly = chrome?.renderOnly === true;
|
|
957
1048
|
const storageBlocked = chrome?.uploadsAvailable === false;
|
|
958
1049
|
const storageUrl = storageBlocked && chrome?.devChrome ? safeHttpUrl(chrome.warningUrl) : null;
|
|
959
|
-
const canUpload = Boolean(api.client && api.formId) && !storageBlocked;
|
|
1050
|
+
const canUpload = !renderOnly && Boolean(api.client && api.formId) && !storageBlocked;
|
|
960
1051
|
const activeInFlight = inFlight.filter((f) => !f.error).length;
|
|
961
1052
|
const remaining = maxFiles - files.length - activeInFlight;
|
|
962
1053
|
async function startUpload(file) {
|
|
@@ -965,7 +1056,15 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
965
1056
|
if (file.size > maxBytes) {
|
|
966
1057
|
setInFlight((prev) => [
|
|
967
1058
|
...prev,
|
|
968
|
-
{
|
|
1059
|
+
{
|
|
1060
|
+
key,
|
|
1061
|
+
name: file.name,
|
|
1062
|
+
size: file.size,
|
|
1063
|
+
fraction: 0,
|
|
1064
|
+
file,
|
|
1065
|
+
tooLarge: true,
|
|
1066
|
+
error: strings.fileTooLarge(maxMb)
|
|
1067
|
+
}
|
|
969
1068
|
]);
|
|
970
1069
|
return;
|
|
971
1070
|
}
|
|
@@ -991,10 +1090,8 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
991
1090
|
setValue(next);
|
|
992
1091
|
} catch (err) {
|
|
993
1092
|
if (mountedRef.current) {
|
|
994
|
-
const message = err
|
|
995
|
-
setInFlight(
|
|
996
|
-
(prev) => prev.map((f) => f.key === key ? { ...f, error: message } : f)
|
|
997
|
-
);
|
|
1093
|
+
const message = uploadFailureMessage(err, strings);
|
|
1094
|
+
setInFlight((prev) => prev.map((f) => f.key === key ? { ...f, error: message } : f));
|
|
998
1095
|
}
|
|
999
1096
|
} finally {
|
|
1000
1097
|
controllers.current.delete(key);
|
|
@@ -1018,171 +1115,190 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
1018
1115
|
setValue(next);
|
|
1019
1116
|
}
|
|
1020
1117
|
const describedBy = [field.description ? ids.descriptionId : null, error ? ids.errorId : null].filter(Boolean).join(" ") || void 0;
|
|
1021
|
-
return /* @__PURE__ */ jsxs4(
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
className: slots.
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1118
|
+
return /* @__PURE__ */ jsxs4(
|
|
1119
|
+
"div",
|
|
1120
|
+
{
|
|
1121
|
+
...slots.wrapperProps(
|
|
1122
|
+
`fillo-field fillo-field--file_upload${error ? " fillo-field--error" : ""}`
|
|
1123
|
+
),
|
|
1124
|
+
children: [
|
|
1125
|
+
/* @__PURE__ */ jsxs4("label", { className: slots.label, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: [
|
|
1126
|
+
field.label,
|
|
1127
|
+
!field.required && /* @__PURE__ */ jsx4("span", { className: "fillo-optional", children: strings.optional })
|
|
1128
|
+
] }),
|
|
1129
|
+
field.description && /* @__PURE__ */ jsx4("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1130
|
+
remaining > 0 && /* @__PURE__ */ jsxs4(
|
|
1131
|
+
"div",
|
|
1132
|
+
{
|
|
1133
|
+
"data-fillo": "control",
|
|
1134
|
+
"data-drag-over": dragOver ? "" : void 0,
|
|
1135
|
+
className: slots.control(
|
|
1136
|
+
`fillo-dropzone${dragOver ? " fillo-dropzone--over" : ""}${canUpload ? "" : " fillo-dropzone--disabled"}`
|
|
1137
|
+
),
|
|
1138
|
+
onDragOver: (e) => {
|
|
1139
|
+
e.preventDefault();
|
|
1140
|
+
setDragOver(true);
|
|
1141
|
+
},
|
|
1142
|
+
onDragLeave: () => setDragOver(false),
|
|
1143
|
+
onDrop: (e) => {
|
|
1144
|
+
e.preventDefault();
|
|
1145
|
+
setDragOver(false);
|
|
1146
|
+
if (canUpload) handleFiles(e.dataTransfer.files);
|
|
1147
|
+
},
|
|
1148
|
+
onClick: () => canUpload && inputRef.current?.click(),
|
|
1149
|
+
role: "button",
|
|
1150
|
+
tabIndex: 0,
|
|
1151
|
+
"aria-disabled": !canUpload || void 0,
|
|
1152
|
+
"aria-labelledby": ids.labelId,
|
|
1153
|
+
"aria-invalid": error ? true : void 0,
|
|
1154
|
+
"aria-describedby": describedBy,
|
|
1155
|
+
onKeyDown: (e) => {
|
|
1156
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1157
|
+
e.preventDefault();
|
|
1158
|
+
if (canUpload) inputRef.current?.click();
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1161
|
+
children: [
|
|
1162
|
+
/* @__PURE__ */ jsx4(
|
|
1163
|
+
"input",
|
|
1164
|
+
{
|
|
1165
|
+
ref: inputRef,
|
|
1166
|
+
id: ids.inputId,
|
|
1167
|
+
type: "file",
|
|
1168
|
+
hidden: true,
|
|
1169
|
+
disabled: !canUpload,
|
|
1170
|
+
multiple: maxFiles > 1,
|
|
1171
|
+
accept: schema.accept?.join(","),
|
|
1172
|
+
onChange: (e) => canUpload && handleFiles(e.target.files)
|
|
1173
|
+
}
|
|
1174
|
+
),
|
|
1175
|
+
canUpload ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1176
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-title", children: strings.dropzoneTitle(maxFiles > 1) }),
|
|
1177
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-hint", children: strings.dropzoneHint(maxMb) })
|
|
1178
|
+
] }) : storageBlocked && chrome?.devChrome ? /* @__PURE__ */ jsxs4("span", { className: "fillo-dropzone-hint", children: [
|
|
1179
|
+
"Connect file storage to enable uploads",
|
|
1180
|
+
storageUrl && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1181
|
+
" \u2014 ",
|
|
1182
|
+
/* @__PURE__ */ jsx4("a", { href: storageUrl, target: "_blank", rel: "noopener noreferrer", children: storageUrl })
|
|
1183
|
+
] })
|
|
1184
|
+
] }) : /* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-hint", children: renderOnly ? strings.uploadsRenderOnly : storageBlocked ? strings.uploadsUnavailable : strings.uploadsDisabled })
|
|
1185
|
+
]
|
|
1055
1186
|
}
|
|
1056
|
-
|
|
1057
|
-
children: [
|
|
1058
|
-
/* @__PURE__ */ jsx4(
|
|
1059
|
-
"input",
|
|
1060
|
-
{
|
|
1061
|
-
ref: inputRef,
|
|
1062
|
-
id: ids.inputId,
|
|
1063
|
-
type: "file",
|
|
1064
|
-
hidden: true,
|
|
1065
|
-
disabled: !canUpload,
|
|
1066
|
-
multiple: maxFiles > 1,
|
|
1067
|
-
accept: schema.accept?.join(","),
|
|
1068
|
-
onChange: (e) => canUpload && handleFiles(e.target.files)
|
|
1069
|
-
}
|
|
1070
|
-
),
|
|
1071
|
-
canUpload ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1072
|
-
/* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-title", children: strings.dropzoneTitle(maxFiles > 1) }),
|
|
1073
|
-
/* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-hint", children: strings.dropzoneHint(maxMb) })
|
|
1074
|
-
] }) : storageBlocked && chrome?.devChrome ? /* @__PURE__ */ jsxs4("span", { className: "fillo-dropzone-hint", children: [
|
|
1075
|
-
"Connect file storage to enable uploads",
|
|
1076
|
-
storageUrl && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1077
|
-
" \u2014 ",
|
|
1078
|
-
/* @__PURE__ */ jsx4("a", { href: storageUrl, target: "_blank", rel: "noopener noreferrer", children: storageUrl })
|
|
1079
|
-
] })
|
|
1080
|
-
] }) : /* @__PURE__ */ jsx4("span", { className: "fillo-dropzone-hint", children: storageBlocked ? strings.uploadsUnavailable : strings.uploadsDisabled })
|
|
1081
|
-
]
|
|
1082
|
-
}
|
|
1083
|
-
),
|
|
1084
|
-
/* @__PURE__ */ jsx4(
|
|
1085
|
-
"div",
|
|
1086
|
-
{
|
|
1087
|
-
role: "status",
|
|
1088
|
-
"aria-live": "polite",
|
|
1089
|
-
className: "fillo-sr-only",
|
|
1090
|
-
style: { position: "absolute", left: "-9999px", width: 1, height: 1, overflow: "hidden" },
|
|
1091
|
-
children: uploadStatus(inFlight, files.length, strings)
|
|
1092
|
-
}
|
|
1093
|
-
),
|
|
1094
|
-
(inFlight.length > 0 || files.length > 0) && /* @__PURE__ */ jsxs4("ul", { className: "fillo-files", children: [
|
|
1095
|
-
files.map((f) => /* @__PURE__ */ jsxs4("li", { className: "fillo-file fillo-file--done", children: [
|
|
1096
|
-
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1097
|
-
/* @__PURE__ */ jsx4("span", { className: "fillo-file-meta", children: formatBytes(f.size) }),
|
|
1187
|
+
),
|
|
1098
1188
|
/* @__PURE__ */ jsx4(
|
|
1099
|
-
"
|
|
1189
|
+
"div",
|
|
1100
1190
|
{
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
"
|
|
1104
|
-
|
|
1105
|
-
children:
|
|
1191
|
+
role: "status",
|
|
1192
|
+
"aria-live": "polite",
|
|
1193
|
+
className: "fillo-sr-only",
|
|
1194
|
+
style: { position: "absolute", left: "-9999px", width: 1, height: 1, overflow: "hidden" },
|
|
1195
|
+
children: uploadStatus(inFlight, files.length, strings)
|
|
1106
1196
|
}
|
|
1107
|
-
)
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
"li",
|
|
1111
|
-
{
|
|
1112
|
-
className: `fillo-file${f.error ? " fillo-file--failed" : ""}`,
|
|
1113
|
-
...f.error ? {} : {
|
|
1114
|
-
role: "progressbar",
|
|
1115
|
-
"aria-label": `Uploading ${f.name}`,
|
|
1116
|
-
"aria-valuemin": 0,
|
|
1117
|
-
"aria-valuemax": 100,
|
|
1118
|
-
"aria-valuenow": Math.round(f.fraction * 100)
|
|
1119
|
-
},
|
|
1120
|
-
children: [
|
|
1197
|
+
),
|
|
1198
|
+
(inFlight.length > 0 || files.length > 0) && /* @__PURE__ */ jsxs4("ul", { className: "fillo-files", children: [
|
|
1199
|
+
files.map((f) => /* @__PURE__ */ jsxs4("li", { className: "fillo-file fillo-file--done", children: [
|
|
1121
1200
|
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
"
|
|
1141
|
-
{
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1201
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-meta", children: formatBytes(f.size) }),
|
|
1202
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-sr-only", children: "Uploaded" }),
|
|
1203
|
+
/* @__PURE__ */ jsx4(
|
|
1204
|
+
"button",
|
|
1205
|
+
{
|
|
1206
|
+
type: "button",
|
|
1207
|
+
className: "fillo-file-remove",
|
|
1208
|
+
"aria-label": `Remove ${f.name}`,
|
|
1209
|
+
onClick: () => removeFile(f.fileId),
|
|
1210
|
+
children: "\xD7"
|
|
1211
|
+
}
|
|
1212
|
+
)
|
|
1213
|
+
] }, f.fileId)),
|
|
1214
|
+
inFlight.map((f) => /* @__PURE__ */ jsxs4(
|
|
1215
|
+
"li",
|
|
1216
|
+
{
|
|
1217
|
+
className: `fillo-file${f.error ? " fillo-file--failed" : ""}`,
|
|
1218
|
+
...f.error ? {} : {
|
|
1219
|
+
role: "progressbar",
|
|
1220
|
+
"aria-label": `Uploading ${f.name}`,
|
|
1221
|
+
"aria-valuemin": 0,
|
|
1222
|
+
"aria-valuemax": 100,
|
|
1223
|
+
"aria-valuenow": Math.round(f.fraction * 100)
|
|
1224
|
+
},
|
|
1225
|
+
children: [
|
|
1226
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-name", children: f.name }),
|
|
1227
|
+
f.error ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1228
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-actions", children: [
|
|
1229
|
+
f.file && !f.tooLarge && remaining > 0 && /* @__PURE__ */ jsx4(
|
|
1230
|
+
"button",
|
|
1231
|
+
{
|
|
1232
|
+
type: "button",
|
|
1233
|
+
className: "fillo-file-retry",
|
|
1234
|
+
"aria-label": `${strings.uploadRetry} ${f.name}`,
|
|
1235
|
+
onClick: () => {
|
|
1236
|
+
const retryFile = f.file;
|
|
1237
|
+
if (!retryFile) return;
|
|
1238
|
+
setInFlight((prev) => prev.filter((x) => x.key !== f.key));
|
|
1239
|
+
void startUpload(retryFile);
|
|
1240
|
+
},
|
|
1241
|
+
children: strings.uploadRetry
|
|
1242
|
+
}
|
|
1243
|
+
),
|
|
1244
|
+
/* @__PURE__ */ jsx4(
|
|
1245
|
+
"button",
|
|
1246
|
+
{
|
|
1247
|
+
type: "button",
|
|
1248
|
+
className: "fillo-file-remove",
|
|
1249
|
+
"aria-label": "Dismiss",
|
|
1250
|
+
onClick: () => setInFlight((prev) => prev.filter((x) => x.key !== f.key)),
|
|
1251
|
+
children: "\xD7"
|
|
1252
|
+
}
|
|
1253
|
+
)
|
|
1254
|
+
] }),
|
|
1255
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-file-error", role: "alert", children: f.error })
|
|
1256
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1257
|
+
/* @__PURE__ */ jsxs4("span", { className: "fillo-file-meta", children: [
|
|
1258
|
+
Math.round(f.fraction * 100),
|
|
1259
|
+
"% of ",
|
|
1260
|
+
formatBytes(f.size)
|
|
1261
|
+
] }),
|
|
1262
|
+
/* @__PURE__ */ jsx4(
|
|
1263
|
+
"button",
|
|
1264
|
+
{
|
|
1265
|
+
type: "button",
|
|
1266
|
+
className: "fillo-file-remove",
|
|
1267
|
+
"aria-label": `Cancel ${f.name}`,
|
|
1268
|
+
onClick: () => cancelUpload(f.key),
|
|
1269
|
+
children: "\xD7"
|
|
1270
|
+
}
|
|
1271
|
+
),
|
|
1272
|
+
/* @__PURE__ */ jsx4("span", { className: "fillo-progress", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
|
|
1273
|
+
"span",
|
|
1274
|
+
{
|
|
1275
|
+
className: "fillo-progress-bar",
|
|
1276
|
+
style: { width: `${f.fraction * 100}%` }
|
|
1277
|
+
}
|
|
1278
|
+
) })
|
|
1279
|
+
] })
|
|
1280
|
+
]
|
|
1281
|
+
},
|
|
1282
|
+
f.key
|
|
1283
|
+
))
|
|
1284
|
+
] }),
|
|
1285
|
+
error && /* @__PURE__ */ jsx4("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1286
|
+
]
|
|
1287
|
+
}
|
|
1288
|
+
);
|
|
1174
1289
|
}
|
|
1175
1290
|
|
|
1176
1291
|
// src/fields.tsx
|
|
1177
1292
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1178
|
-
function fieldAria(field, error, ids) {
|
|
1293
|
+
function fieldAria(field, error, ids, opts = {}) {
|
|
1179
1294
|
const describedBy = [
|
|
1180
1295
|
field.description ? ids.descriptionId : null,
|
|
1181
1296
|
error ? ids.errorId : null
|
|
1182
1297
|
].filter(Boolean);
|
|
1298
|
+
const requiredSupported = opts.required ?? true;
|
|
1183
1299
|
return {
|
|
1184
1300
|
"aria-invalid": error ? true : void 0,
|
|
1185
|
-
"aria-required": field.required ? true : void 0,
|
|
1301
|
+
"aria-required": requiredSupported && field.required ? true : void 0,
|
|
1186
1302
|
"aria-describedby": describedBy.length ? describedBy.join(" ") : void 0
|
|
1187
1303
|
};
|
|
1188
1304
|
}
|
|
@@ -1198,9 +1314,6 @@ function useControl(base, field, error) {
|
|
|
1198
1314
|
"data-fillo": "control"
|
|
1199
1315
|
};
|
|
1200
1316
|
}
|
|
1201
|
-
function isNativeControlTarget(target) {
|
|
1202
|
-
return target instanceof HTMLElement && Boolean(target.closest("input, textarea, select, button"));
|
|
1203
|
-
}
|
|
1204
1317
|
function FieldShell({
|
|
1205
1318
|
field,
|
|
1206
1319
|
error,
|
|
@@ -1237,7 +1350,7 @@ function FieldShell({
|
|
|
1237
1350
|
] }),
|
|
1238
1351
|
field.description && /* @__PURE__ */ jsx5("p", { className: descriptionCls, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1239
1352
|
children,
|
|
1240
|
-
error && /* @__PURE__ */ jsx5("p", { className: errorCls, "data-fillo": "error", id: ids.errorId,
|
|
1353
|
+
error && /* @__PURE__ */ jsx5("p", { className: errorCls, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1241
1354
|
]
|
|
1242
1355
|
}
|
|
1243
1356
|
);
|
|
@@ -1245,6 +1358,7 @@ function FieldShell({
|
|
|
1245
1358
|
function TextInput({ field, value, error, setValue, ids: providedIds }) {
|
|
1246
1359
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1247
1360
|
const type = field.kind === "email" ? "email" : field.kind === "url" ? "url" : field.kind === "number" ? "number" : field.kind === "date" ? "date" : "text";
|
|
1361
|
+
const autoComplete = field.kind === "email" ? "email" : field.kind === "url" ? "url" : void 0;
|
|
1248
1362
|
const control = useControl("fillo-input", field, error);
|
|
1249
1363
|
return /* @__PURE__ */ jsx5(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx5(
|
|
1250
1364
|
"input",
|
|
@@ -1252,6 +1366,7 @@ function TextInput({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1252
1366
|
id: ids.inputId,
|
|
1253
1367
|
...control,
|
|
1254
1368
|
type,
|
|
1369
|
+
autoComplete,
|
|
1255
1370
|
value: typeof value === "string" || typeof value === "number" ? String(value) : "",
|
|
1256
1371
|
placeholder: field.placeholder,
|
|
1257
1372
|
maxLength: "maxLength" in field ? field.maxLength : void 0,
|
|
@@ -1262,6 +1377,72 @@ function TextInput({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1262
1377
|
}
|
|
1263
1378
|
) });
|
|
1264
1379
|
}
|
|
1380
|
+
function NumberInput({ field, value, error, setValue, api, ids: providedIds }) {
|
|
1381
|
+
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1382
|
+
const control = useControl("fillo-input", field, error);
|
|
1383
|
+
const [draft, setDraft] = useState5(null);
|
|
1384
|
+
const inputRef = useRef6(null);
|
|
1385
|
+
const pendingCaret = useRef6(null);
|
|
1386
|
+
const [, setRevertTick] = useState5(0);
|
|
1387
|
+
useLayoutEffect2(() => {
|
|
1388
|
+
if (pendingCaret.current === null) return;
|
|
1389
|
+
const pos = pendingCaret.current;
|
|
1390
|
+
pendingCaret.current = null;
|
|
1391
|
+
inputRef.current?.setSelectionRange(pos, pos);
|
|
1392
|
+
});
|
|
1393
|
+
const num = field;
|
|
1394
|
+
const grouped = num.notation !== void 0;
|
|
1395
|
+
const locale = localeForNotation(num.notation);
|
|
1396
|
+
const hasAffix = Boolean(num.prefix) || Boolean(num.suffix);
|
|
1397
|
+
if (!grouped && !hasAffix) {
|
|
1398
|
+
return /* @__PURE__ */ jsx5(
|
|
1399
|
+
TextInput,
|
|
1400
|
+
{
|
|
1401
|
+
field,
|
|
1402
|
+
value,
|
|
1403
|
+
error,
|
|
1404
|
+
setValue,
|
|
1405
|
+
api,
|
|
1406
|
+
ids: providedIds
|
|
1407
|
+
}
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
const stored = typeof value === "string" || typeof value === "number" ? String(value) : "";
|
|
1411
|
+
const n = Number(stored);
|
|
1412
|
+
const display = draft !== null ? draft : grouped && stored !== "" && Number.isFinite(n) ? formatGroupedNumber(n, { locale, decimals: num.decimals }) : stored;
|
|
1413
|
+
const input = /* @__PURE__ */ jsx5(
|
|
1414
|
+
"input",
|
|
1415
|
+
{
|
|
1416
|
+
ref: inputRef,
|
|
1417
|
+
id: ids.inputId,
|
|
1418
|
+
...control,
|
|
1419
|
+
type: "text",
|
|
1420
|
+
inputMode: "decimal",
|
|
1421
|
+
value: display,
|
|
1422
|
+
placeholder: field.placeholder,
|
|
1423
|
+
onBlur: grouped ? () => setDraft(null) : void 0,
|
|
1424
|
+
onChange: (e) => {
|
|
1425
|
+
if (!isValidPartialNumberText(e.target.value, locale)) {
|
|
1426
|
+
pendingCaret.current = e.target.selectionStart ?? e.target.value.length;
|
|
1427
|
+
setRevertTick((t) => t + 1);
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
if (grouped) {
|
|
1431
|
+
setDraft(e.target.value);
|
|
1432
|
+
setValue(parseGroupedNumber(e.target.value, locale));
|
|
1433
|
+
} else {
|
|
1434
|
+
setValue(e.target.value);
|
|
1435
|
+
}
|
|
1436
|
+
},
|
|
1437
|
+
...fieldAria(field, error, ids)
|
|
1438
|
+
}
|
|
1439
|
+
);
|
|
1440
|
+
return /* @__PURE__ */ jsx5(FieldShell, { field, error, ids, children: hasAffix ? /* @__PURE__ */ jsxs5("div", { className: "fillo-number", children: [
|
|
1441
|
+
num.prefix && /* @__PURE__ */ jsx5("span", { className: "fillo-number-prefix", children: num.prefix }),
|
|
1442
|
+
input,
|
|
1443
|
+
num.suffix && /* @__PURE__ */ jsx5("span", { className: "fillo-number-suffix", children: num.suffix })
|
|
1444
|
+
] }) : input });
|
|
1445
|
+
}
|
|
1265
1446
|
function LongText({ field, value, error, setValue, ids: providedIds }) {
|
|
1266
1447
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1267
1448
|
const control = useControl("fillo-input fillo-textarea", field, error);
|
|
@@ -1347,12 +1528,6 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1347
1528
|
opt.id,
|
|
1348
1529
|
value === opt.id
|
|
1349
1530
|
),
|
|
1350
|
-
onClick: (event) => {
|
|
1351
|
-
if (isNativeControlTarget(event.target)) return;
|
|
1352
|
-
event.preventDefault();
|
|
1353
|
-
setOtherOn(false);
|
|
1354
|
-
setValue(opt.id);
|
|
1355
|
-
},
|
|
1356
1531
|
children: [
|
|
1357
1532
|
/* @__PURE__ */ jsx5(
|
|
1358
1533
|
"input",
|
|
@@ -1368,15 +1543,21 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1368
1543
|
}
|
|
1369
1544
|
),
|
|
1370
1545
|
/* @__PURE__ */ jsx5(ChoiceIcon, { icon: opt.icon }),
|
|
1546
|
+
opt.icon && value === opt.id && // Icon-mode hides the native input, so its check state is
|
|
1547
|
+
// otherwise color-only (forfeits forced-colors' own indicator).
|
|
1548
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-option-check", "aria-hidden": "true", children: "\u2713" }),
|
|
1371
1549
|
/* @__PURE__ */ jsx5("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: opt.label })
|
|
1372
1550
|
]
|
|
1373
1551
|
},
|
|
1374
1552
|
opt.id
|
|
1375
1553
|
)),
|
|
1376
|
-
choice.allowOther && //
|
|
1377
|
-
//
|
|
1554
|
+
choice.allowOther && // The outer element is a <label> so the whole row is a pointer
|
|
1555
|
+
// target (native label click-forwarding), same as every other
|
|
1556
|
+
// option row above. The free-text input below is its own labelable
|
|
1557
|
+
// descendant, so it handles its own clicks without re-toggling the
|
|
1558
|
+
// radio (dom's proven pattern).
|
|
1378
1559
|
/* @__PURE__ */ jsxs5(
|
|
1379
|
-
"
|
|
1560
|
+
"label",
|
|
1380
1561
|
{
|
|
1381
1562
|
"data-fillo": "option",
|
|
1382
1563
|
"data-selected": otherActive ? "" : void 0,
|
|
@@ -1386,7 +1567,7 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1386
1567
|
otherActive
|
|
1387
1568
|
),
|
|
1388
1569
|
children: [
|
|
1389
|
-
/* @__PURE__ */ jsxs5("
|
|
1570
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-option-main", children: [
|
|
1390
1571
|
/* @__PURE__ */ jsx5(
|
|
1391
1572
|
"input",
|
|
1392
1573
|
{
|
|
@@ -1441,7 +1622,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1441
1622
|
"data-fillo": "options",
|
|
1442
1623
|
role: "group",
|
|
1443
1624
|
"aria-labelledby": ids.labelId,
|
|
1444
|
-
...fieldAria(field, error, ids),
|
|
1625
|
+
...fieldAria(field, error, ids, { required: false }),
|
|
1445
1626
|
children: [
|
|
1446
1627
|
options.map((opt) => /* @__PURE__ */ jsxs5(
|
|
1447
1628
|
"label",
|
|
@@ -1454,11 +1635,6 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1454
1635
|
opt.id,
|
|
1455
1636
|
selected.includes(opt.id)
|
|
1456
1637
|
),
|
|
1457
|
-
onClick: (event) => {
|
|
1458
|
-
if (isNativeControlTarget(event.target)) return;
|
|
1459
|
-
event.preventDefault();
|
|
1460
|
-
toggle(opt.id);
|
|
1461
|
-
},
|
|
1462
1638
|
children: [
|
|
1463
1639
|
/* @__PURE__ */ jsx5(
|
|
1464
1640
|
"input",
|
|
@@ -1470,15 +1646,21 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1470
1646
|
}
|
|
1471
1647
|
),
|
|
1472
1648
|
/* @__PURE__ */ jsx5(ChoiceIcon, { icon: opt.icon }),
|
|
1649
|
+
opt.icon && selected.includes(opt.id) && // Icon-mode hides the native input, so its check state is
|
|
1650
|
+
// otherwise color-only (forfeits forced-colors' own indicator).
|
|
1651
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-option-check", "aria-hidden": "true", children: "\u2713" }),
|
|
1473
1652
|
/* @__PURE__ */ jsx5("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: opt.label })
|
|
1474
1653
|
]
|
|
1475
1654
|
},
|
|
1476
1655
|
opt.id
|
|
1477
1656
|
)),
|
|
1478
|
-
choice.allowOther && //
|
|
1479
|
-
//
|
|
1657
|
+
choice.allowOther && // The outer element is a <label> so the whole row is a pointer
|
|
1658
|
+
// target (native label click-forwarding), same as every other
|
|
1659
|
+
// option row above. The free-text input below is its own labelable
|
|
1660
|
+
// descendant, so it handles its own clicks without re-toggling the
|
|
1661
|
+
// checkbox (dom's proven pattern).
|
|
1480
1662
|
/* @__PURE__ */ jsxs5(
|
|
1481
|
-
"
|
|
1663
|
+
"label",
|
|
1482
1664
|
{
|
|
1483
1665
|
"data-fillo": "option",
|
|
1484
1666
|
"data-selected": otherActive ? "" : void 0,
|
|
@@ -1488,7 +1670,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1488
1670
|
otherActive
|
|
1489
1671
|
),
|
|
1490
1672
|
children: [
|
|
1491
|
-
/* @__PURE__ */ jsxs5("
|
|
1673
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-option-main", children: [
|
|
1492
1674
|
/* @__PURE__ */ jsx5(
|
|
1493
1675
|
"input",
|
|
1494
1676
|
{
|
|
@@ -1610,18 +1792,16 @@ function Checkbox({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1610
1792
|
{
|
|
1611
1793
|
id: ids.inputId,
|
|
1612
1794
|
type: "checkbox",
|
|
1613
|
-
role: "switch",
|
|
1614
1795
|
className: "fillo-toggle-input",
|
|
1615
1796
|
checked: value === true,
|
|
1616
1797
|
onChange: (e) => setValue(e.target.checked),
|
|
1617
|
-
"aria-checked": value === true,
|
|
1618
1798
|
...fieldAria(field, error, ids)
|
|
1619
1799
|
}
|
|
1620
1800
|
),
|
|
1621
1801
|
/* @__PURE__ */ jsx5("span", { className: "fillo-toggle-track", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("span", { className: "fillo-toggle-thumb" }) })
|
|
1622
1802
|
] }),
|
|
1623
1803
|
field.description && /* @__PURE__ */ jsx5("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1624
|
-
error && /* @__PURE__ */ jsx5("p", { className: slots.error, "data-fillo": "error", id: ids.errorId,
|
|
1804
|
+
error && /* @__PURE__ */ jsx5("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1625
1805
|
]
|
|
1626
1806
|
}
|
|
1627
1807
|
);
|
|
@@ -1651,28 +1831,21 @@ function Checkbox({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1651
1831
|
] })
|
|
1652
1832
|
] }),
|
|
1653
1833
|
field.description && /* @__PURE__ */ jsx5("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1654
|
-
error && /* @__PURE__ */ jsx5("p", { className: slots.error, "data-fillo": "error", id: ids.errorId,
|
|
1834
|
+
error && /* @__PURE__ */ jsx5("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1655
1835
|
]
|
|
1656
1836
|
}
|
|
1657
1837
|
);
|
|
1658
1838
|
}
|
|
1659
1839
|
function radiogroupKeyDown(e, steps, current, setValue) {
|
|
1660
|
-
const
|
|
1661
|
-
const
|
|
1662
|
-
|
|
1840
|
+
const group = e.currentTarget;
|
|
1841
|
+
const rtl = getComputedStyle(group).direction === "rtl";
|
|
1842
|
+
const index = rovingIndex(steps, current);
|
|
1843
|
+
const next = radioGroupStep(e.key, index, steps.length, { rtl });
|
|
1844
|
+
if (next == null) return;
|
|
1663
1845
|
e.preventDefault();
|
|
1664
|
-
const index = current == null ? -1 : steps.indexOf(current);
|
|
1665
|
-
let next;
|
|
1666
|
-
if (index === -1) {
|
|
1667
|
-
next = forward ? 0 : steps.length - 1;
|
|
1668
|
-
} else {
|
|
1669
|
-
next = forward ? index + 1 : index - 1;
|
|
1670
|
-
next = (next + steps.length) % steps.length;
|
|
1671
|
-
}
|
|
1672
1846
|
const value = steps[next];
|
|
1673
1847
|
if (value === void 0) return;
|
|
1674
1848
|
setValue(value);
|
|
1675
|
-
const group = e.currentTarget;
|
|
1676
1849
|
const buttons = group.querySelectorAll('[role="radio"]');
|
|
1677
1850
|
buttons[next]?.focus();
|
|
1678
1851
|
}
|
|
@@ -1693,6 +1866,7 @@ function Rating({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1693
1866
|
return /* @__PURE__ */ jsx5(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx5(
|
|
1694
1867
|
"div",
|
|
1695
1868
|
{
|
|
1869
|
+
id: ids.inputId,
|
|
1696
1870
|
...control,
|
|
1697
1871
|
role: "radiogroup",
|
|
1698
1872
|
"aria-labelledby": ids.labelId,
|
|
@@ -1714,8 +1888,11 @@ function Rating({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1714
1888
|
"aria-label": `${n} of ${max}`,
|
|
1715
1889
|
"aria-checked": n === current,
|
|
1716
1890
|
tabIndex: i === tabbable ? 0 : -1,
|
|
1717
|
-
onClick: () =>
|
|
1718
|
-
|
|
1891
|
+
onClick: (event) => {
|
|
1892
|
+
if (event.detail === 0 && n === current) return;
|
|
1893
|
+
setValue(n === current ? null : n);
|
|
1894
|
+
},
|
|
1895
|
+
children: n <= current ? "\u2605" : "\u2606"
|
|
1719
1896
|
},
|
|
1720
1897
|
n
|
|
1721
1898
|
))
|
|
@@ -1745,6 +1922,7 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1745
1922
|
/* @__PURE__ */ jsx5(
|
|
1746
1923
|
"div",
|
|
1747
1924
|
{
|
|
1925
|
+
id: ids.inputId,
|
|
1748
1926
|
...control,
|
|
1749
1927
|
role: "radiogroup",
|
|
1750
1928
|
"aria-labelledby": ids.labelId,
|
|
@@ -1768,7 +1946,10 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1768
1946
|
"aria-label": String(n),
|
|
1769
1947
|
"aria-checked": value === n,
|
|
1770
1948
|
tabIndex: i === tabbable ? 0 : -1,
|
|
1771
|
-
onClick: () =>
|
|
1949
|
+
onClick: (event) => {
|
|
1950
|
+
if (event.detail === 0 && n === current) return;
|
|
1951
|
+
setValue(value === n ? null : n);
|
|
1952
|
+
},
|
|
1772
1953
|
children: n
|
|
1773
1954
|
},
|
|
1774
1955
|
n
|
|
@@ -1783,19 +1964,34 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1783
1964
|
}
|
|
1784
1965
|
function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
1785
1966
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1967
|
+
const strings = useStrings();
|
|
1968
|
+
const announce = useFilloAnnounce();
|
|
1786
1969
|
const ranking = field;
|
|
1787
1970
|
const answered = Array.isArray(value) ? value : [];
|
|
1788
1971
|
const order = [
|
|
1789
1972
|
...answered.filter((id) => ranking.options.some((o) => o.id === id)),
|
|
1790
1973
|
...ranking.options.map((o) => o.id).filter((id) => !answered.includes(id))
|
|
1791
1974
|
];
|
|
1792
|
-
|
|
1975
|
+
const pressedRef = useRef6(null);
|
|
1976
|
+
useEffect6(() => {
|
|
1977
|
+
const pressed = pressedRef.current;
|
|
1978
|
+
pressedRef.current = null;
|
|
1979
|
+
if (!pressed || !pressed.disabled) return;
|
|
1980
|
+
const sibling = pressed.parentElement?.querySelector(
|
|
1981
|
+
".fillo-ranking-move:not(:disabled)"
|
|
1982
|
+
);
|
|
1983
|
+
sibling?.focus();
|
|
1984
|
+
}, [value]);
|
|
1985
|
+
function move(id, delta, button) {
|
|
1793
1986
|
const index = order.indexOf(id);
|
|
1794
1987
|
const target = index + delta;
|
|
1795
1988
|
if (target < 0 || target >= order.length) return;
|
|
1989
|
+
pressedRef.current = button;
|
|
1796
1990
|
const next = [...order];
|
|
1797
1991
|
[next[index], next[target]] = [next[target], next[index]];
|
|
1798
1992
|
setValue(next);
|
|
1993
|
+
const moved = ranking.options.find((o) => o.id === id);
|
|
1994
|
+
if (moved) announce(strings.rankingPosition(moved.label, target + 1, order.length));
|
|
1799
1995
|
}
|
|
1800
1996
|
return /* @__PURE__ */ jsx5(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx5(
|
|
1801
1997
|
"div",
|
|
@@ -1803,7 +1999,7 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1803
1999
|
id: ids.inputId,
|
|
1804
2000
|
role: "group",
|
|
1805
2001
|
"aria-labelledby": ids.labelId,
|
|
1806
|
-
...fieldAria(field, error, ids),
|
|
2002
|
+
...fieldAria(field, error, ids, { required: false }),
|
|
1807
2003
|
children: /* @__PURE__ */ jsx5("ol", { className: "fillo-ranking", children: order.map((id, index) => {
|
|
1808
2004
|
const option = ranking.options.find((o) => o.id === id);
|
|
1809
2005
|
if (!option) return null;
|
|
@@ -1818,7 +2014,7 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1818
2014
|
className: "fillo-ranking-move",
|
|
1819
2015
|
"aria-label": `Move ${option.label} up`,
|
|
1820
2016
|
disabled: index === 0,
|
|
1821
|
-
onClick: () => move(id, -1),
|
|
2017
|
+
onClick: (e) => move(id, -1, e.currentTarget),
|
|
1822
2018
|
children: "\u2191"
|
|
1823
2019
|
}
|
|
1824
2020
|
),
|
|
@@ -1829,7 +2025,7 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1829
2025
|
className: "fillo-ranking-move",
|
|
1830
2026
|
"aria-label": `Move ${option.label} down`,
|
|
1831
2027
|
disabled: index === order.length - 1,
|
|
1832
|
-
onClick: () => move(id, 1),
|
|
2028
|
+
onClick: (e) => move(id, 1, e.currentTarget),
|
|
1833
2029
|
children: "\u2193"
|
|
1834
2030
|
}
|
|
1835
2031
|
)
|
|
@@ -1850,10 +2046,10 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1850
2046
|
className: "fillo-matrix-wrap",
|
|
1851
2047
|
role: "group",
|
|
1852
2048
|
"aria-labelledby": ids.labelId,
|
|
1853
|
-
...fieldAria(field, error, ids),
|
|
2049
|
+
...fieldAria(field, error, ids, { required: false }),
|
|
1854
2050
|
children: /* @__PURE__ */ jsxs5("table", { className: "fillo-matrix", children: [
|
|
1855
2051
|
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1856
|
-
/* @__PURE__ */ jsx5("
|
|
2052
|
+
/* @__PURE__ */ jsx5("td", {}),
|
|
1857
2053
|
matrix.columns.map((col) => /* @__PURE__ */ jsx5("th", { scope: "col", children: col.label }, col.id))
|
|
1858
2054
|
] }) }),
|
|
1859
2055
|
/* @__PURE__ */ jsx5("tbody", { children: matrix.rows.map((row) => {
|
|
@@ -1872,12 +2068,12 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1872
2068
|
"div",
|
|
1873
2069
|
{
|
|
1874
2070
|
role: "radiogroup",
|
|
1875
|
-
"aria-labelledby": rowLabelId
|
|
2071
|
+
"aria-labelledby": `${ids.labelId} ${rowLabelId}`,
|
|
1876
2072
|
"aria-owns": matrix.columns.map(radioId).join(" "),
|
|
1877
2073
|
children: /* @__PURE__ */ jsx5("span", { id: rowLabelId, children: row.label })
|
|
1878
2074
|
}
|
|
1879
2075
|
) }),
|
|
1880
|
-
matrix.columns.map((col) => /* @__PURE__ */ jsx5("td", { children: /* @__PURE__ */ jsx5(
|
|
2076
|
+
matrix.columns.map((col) => /* @__PURE__ */ jsx5("td", { "data-label": col.label, children: /* @__PURE__ */ jsx5("label", { className: "fillo-matrix-cell", children: /* @__PURE__ */ jsx5(
|
|
1881
2077
|
"input",
|
|
1882
2078
|
{
|
|
1883
2079
|
id: radioId(col),
|
|
@@ -1890,7 +2086,7 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1890
2086
|
checked: answers[row.id] === col.id,
|
|
1891
2087
|
onChange: () => setValue({ ...answers, [row.id]: col.id })
|
|
1892
2088
|
}
|
|
1893
|
-
) }, col.id))
|
|
2089
|
+
) }) }, col.id))
|
|
1894
2090
|
] }, row.id)
|
|
1895
2091
|
);
|
|
1896
2092
|
}) })
|
|
@@ -1901,12 +2097,45 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1901
2097
|
function Hidden() {
|
|
1902
2098
|
return null;
|
|
1903
2099
|
}
|
|
2100
|
+
function Calculated({ field, value, ids: providedIds }) {
|
|
2101
|
+
const ids = useFilloFieldIds(field.id, providedIds);
|
|
2102
|
+
const state = { kind: field.kind, fieldId: field.id, invalid: false, required: false };
|
|
2103
|
+
const rootCls = useSlotClass("fillo-field fillo-field--calculated fillo-calculated", {
|
|
2104
|
+
slot: "calculated",
|
|
2105
|
+
...state
|
|
2106
|
+
});
|
|
2107
|
+
const labelCls = useSlotClass("fillo-label", { slot: "label", ...state });
|
|
2108
|
+
const descriptionCls = useSlotClass("fillo-description", { slot: "fieldDescription", ...state });
|
|
2109
|
+
const answered = value !== void 0 && value !== null && value !== "";
|
|
2110
|
+
return /* @__PURE__ */ jsxs5(
|
|
2111
|
+
"div",
|
|
2112
|
+
{
|
|
2113
|
+
className: rootCls,
|
|
2114
|
+
"data-fillo": "calculated",
|
|
2115
|
+
"data-field": field.id,
|
|
2116
|
+
"data-kind": field.kind,
|
|
2117
|
+
children: [
|
|
2118
|
+
/* @__PURE__ */ jsx5("label", { className: labelCls, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: field.label }),
|
|
2119
|
+
field.description && /* @__PURE__ */ jsx5("p", { className: descriptionCls, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
2120
|
+
/* @__PURE__ */ jsx5(
|
|
2121
|
+
"output",
|
|
2122
|
+
{
|
|
2123
|
+
id: ids.inputId,
|
|
2124
|
+
className: `fillo-calculated-value${answered ? "" : " fillo-calculated-value--empty"}`,
|
|
2125
|
+
"aria-describedby": field.description ? ids.descriptionId : void 0,
|
|
2126
|
+
children: answered ? formatAnswer(field, value) : "\u2014"
|
|
2127
|
+
}
|
|
2128
|
+
)
|
|
2129
|
+
]
|
|
2130
|
+
}
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
1904
2133
|
var DEFAULT_COMPONENTS = {
|
|
1905
2134
|
short_text: TextInput,
|
|
1906
2135
|
email: TextInput,
|
|
1907
2136
|
url: TextInput,
|
|
1908
2137
|
phone: PhoneField,
|
|
1909
|
-
number:
|
|
2138
|
+
number: NumberInput,
|
|
1910
2139
|
date: TextInput,
|
|
1911
2140
|
long_text: LongText,
|
|
1912
2141
|
select: SingleChoice,
|
|
@@ -1919,7 +2148,8 @@ var DEFAULT_COMPONENTS = {
|
|
|
1919
2148
|
matrix: Matrix,
|
|
1920
2149
|
signature: SignatureField,
|
|
1921
2150
|
file_upload: FileUploadField,
|
|
1922
|
-
hidden: Hidden
|
|
2151
|
+
hidden: Hidden,
|
|
2152
|
+
calculated: Calculated
|
|
1923
2153
|
};
|
|
1924
2154
|
function ContentRenderer({ block }) {
|
|
1925
2155
|
switch (block.kind) {
|
|
@@ -2034,7 +2264,7 @@ function FormField({
|
|
|
2034
2264
|
}
|
|
2035
2265
|
|
|
2036
2266
|
// src/turnstile.tsx
|
|
2037
|
-
import { useEffect as useEffect7, useRef as
|
|
2267
|
+
import { useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
2038
2268
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2039
2269
|
var SCRIPT_SRC = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
|
2040
2270
|
var SCRIPT_ID = "fillo-turnstile-script";
|
|
@@ -2093,13 +2323,13 @@ function TurnstileWidget({
|
|
|
2093
2323
|
registerReset,
|
|
2094
2324
|
className
|
|
2095
2325
|
}) {
|
|
2096
|
-
const containerRef =
|
|
2097
|
-
const widgetIdRef =
|
|
2098
|
-
const onTokenRef =
|
|
2326
|
+
const containerRef = useRef7(null);
|
|
2327
|
+
const widgetIdRef = useRef7(null);
|
|
2328
|
+
const onTokenRef = useRef7(onToken);
|
|
2099
2329
|
onTokenRef.current = onToken;
|
|
2100
|
-
const onErrorRef =
|
|
2330
|
+
const onErrorRef = useRef7(onError);
|
|
2101
2331
|
onErrorRef.current = onError;
|
|
2102
|
-
const registerResetRef =
|
|
2332
|
+
const registerResetRef = useRef7(registerReset);
|
|
2103
2333
|
registerResetRef.current = registerReset;
|
|
2104
2334
|
useEffect7(() => {
|
|
2105
2335
|
let cancelled = false;
|
|
@@ -2155,7 +2385,7 @@ function TurnstileWidget({
|
|
|
2155
2385
|
// src/FilloForm.tsx
|
|
2156
2386
|
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2157
2387
|
function themeProps(theme) {
|
|
2158
|
-
const safeTheme = normalizeFormTheme(theme);
|
|
2388
|
+
const safeTheme = resolveThemeAppearance(normalizeFormTheme(theme));
|
|
2159
2389
|
if (!safeTheme) return {};
|
|
2160
2390
|
const style = {};
|
|
2161
2391
|
if (safeTheme.primary) style["--fillo-primary"] = safeTheme.primary;
|
|
@@ -2175,17 +2405,25 @@ function badgeUrl(href) {
|
|
|
2175
2405
|
url.searchParams.set("utm_source", "form_badge");
|
|
2176
2406
|
return url.toString();
|
|
2177
2407
|
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
target?.focus?.();
|
|
2185
|
-
};
|
|
2408
|
+
var FOCUSABLE_SELECTOR = 'input:not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
2409
|
+
function resolveFocusable(el) {
|
|
2410
|
+
if (!el) return null;
|
|
2411
|
+
return el.matches(FOCUSABLE_SELECTOR) ? el : el.querySelector(FOCUSABLE_SELECTOR);
|
|
2412
|
+
}
|
|
2413
|
+
function nextFrame(run) {
|
|
2186
2414
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
2187
2415
|
else setTimeout(run, 0);
|
|
2188
2416
|
}
|
|
2417
|
+
function focusErrorSummary(formEl) {
|
|
2418
|
+
if (!formEl || typeof window === "undefined") return;
|
|
2419
|
+
nextFrame(() => {
|
|
2420
|
+
formEl.querySelector(".fillo-error-summary")?.focus();
|
|
2421
|
+
});
|
|
2422
|
+
}
|
|
2423
|
+
function focusField(inputId) {
|
|
2424
|
+
if (typeof document === "undefined") return;
|
|
2425
|
+
resolveFocusable(document.getElementById(inputId))?.focus();
|
|
2426
|
+
}
|
|
2189
2427
|
var HP_STYLE = {
|
|
2190
2428
|
position: "absolute",
|
|
2191
2429
|
left: "-9999px",
|
|
@@ -2204,12 +2442,15 @@ function assertHpHidden(el) {
|
|
|
2204
2442
|
}
|
|
2205
2443
|
function FilloForm(props) {
|
|
2206
2444
|
const { form, formId } = props;
|
|
2445
|
+
const renderOnly = props.renderOnly === true || props.skipValidation === true;
|
|
2207
2446
|
const client = useMemo5(
|
|
2208
|
-
() => props.client ?? (formId ? createClient() : void 0),
|
|
2209
|
-
[props.client, formId]
|
|
2447
|
+
() => renderOnly ? void 0 : props.client ?? (formId ? createClient() : void 0),
|
|
2448
|
+
[renderOnly, props.client, formId]
|
|
2210
2449
|
);
|
|
2211
2450
|
const [loaded, setLoaded] = useState6(null);
|
|
2212
|
-
const [loadFailure, setLoadFailure] = useState6(
|
|
2451
|
+
const [loadFailure, setLoadFailure] = useState6(
|
|
2452
|
+
null
|
|
2453
|
+
);
|
|
2213
2454
|
const devEnv = useIsDevEnv();
|
|
2214
2455
|
const devChrome = props.preview === true || devEnv;
|
|
2215
2456
|
if (props.preview === true) warnPreviewInProduction();
|
|
@@ -2227,6 +2468,7 @@ function FilloForm(props) {
|
|
|
2227
2468
|
accepting: syncedAccepting,
|
|
2228
2469
|
acceptingReason: syncedAcceptingReason,
|
|
2229
2470
|
uploadsAvailable: syncedUploadsAvailable,
|
|
2471
|
+
uploadFileSizeLimitMb: syncedUploadFileSizeLimitMb,
|
|
2230
2472
|
resolvedSchema,
|
|
2231
2473
|
resolvedTheme,
|
|
2232
2474
|
warningCode: syncedWarningCode,
|
|
@@ -2238,10 +2480,22 @@ function FilloForm(props) {
|
|
|
2238
2480
|
});
|
|
2239
2481
|
const renderResolvedSnapshot = Boolean(resolvedSchema && !devChrome);
|
|
2240
2482
|
const inlineSchema = codeForm ? renderResolvedSnapshot ? resolvedSchema : codeForm.schema : form;
|
|
2241
|
-
const onErrorRef =
|
|
2483
|
+
const onErrorRef = useRef8(onError);
|
|
2242
2484
|
useEffect8(() => {
|
|
2243
2485
|
onErrorRef.current = onError;
|
|
2244
2486
|
});
|
|
2487
|
+
const targetError = useMemo5(
|
|
2488
|
+
() => form && !formId && !renderOnly && (!isCodeForm2(form) || !props.client) ? new FilloError2(
|
|
2489
|
+
"This form has no Fillo target. Pass formId with the schema, use a defineForm() value with client, or set renderOnly for a non-submitting preview.",
|
|
2490
|
+
422,
|
|
2491
|
+
void 0,
|
|
2492
|
+
"form_target_required"
|
|
2493
|
+
) : null,
|
|
2494
|
+
[form, formId, props.client, renderOnly]
|
|
2495
|
+
);
|
|
2496
|
+
useEffect8(() => {
|
|
2497
|
+
if (targetError) onErrorRef.current?.(targetError);
|
|
2498
|
+
}, [targetError]);
|
|
2245
2499
|
const needsFetch = !inlineSchema && Boolean(client && formId);
|
|
2246
2500
|
useEffect8(() => {
|
|
2247
2501
|
if (!needsFetch || !client || !formId) {
|
|
@@ -2262,6 +2516,7 @@ function FilloForm(props) {
|
|
|
2262
2516
|
accepting: published.accepting,
|
|
2263
2517
|
acceptingReason: published.acceptingReason,
|
|
2264
2518
|
uploadsAvailable: published.uploadsAvailable,
|
|
2519
|
+
uploadFileSizeLimitMb: published.uploadFileSizeLimitMb,
|
|
2265
2520
|
branding: published.branding ?? null,
|
|
2266
2521
|
challenge: published.challenge ?? null
|
|
2267
2522
|
});
|
|
@@ -2279,10 +2534,28 @@ function FilloForm(props) {
|
|
|
2279
2534
|
const currentLoaded = needsFetch && loaded?.formId === formId ? loaded : null;
|
|
2280
2535
|
const loadError = needsFetch && loadFailure && loadFailure.formId === formId ? loadFailure.error : null;
|
|
2281
2536
|
const rawSchema = inlineSchema ?? currentLoaded?.schema ?? null;
|
|
2282
|
-
const normalized = useMemo5(
|
|
2537
|
+
const normalized = useMemo5(
|
|
2538
|
+
() => rawSchema ? normalizeFormSchema(rawSchema) : null,
|
|
2539
|
+
[rawSchema]
|
|
2540
|
+
);
|
|
2283
2541
|
const schema = normalized?.ok ? normalized.schema : null;
|
|
2284
2542
|
const resolvedCodeTheme = renderResolvedSnapshot ? resolvedTheme ?? void 0 : codeForm?.theme;
|
|
2285
2543
|
const theme = props.appearance?.theme ?? props.theme ?? resolvedCodeTheme ?? currentLoaded?.theme ?? void 0;
|
|
2544
|
+
if (targetError) {
|
|
2545
|
+
if (props.renderError) return /* @__PURE__ */ jsx7(Fragment3, { children: props.renderError(targetError) });
|
|
2546
|
+
return /* @__PURE__ */ jsx7(
|
|
2547
|
+
"div",
|
|
2548
|
+
{
|
|
2549
|
+
className: `fillo-form fillo-form--error ${props.className ?? ""}`,
|
|
2550
|
+
role: "alert",
|
|
2551
|
+
"data-fillo": "root",
|
|
2552
|
+
"data-state": "error",
|
|
2553
|
+
"data-error-code": "form_target_required",
|
|
2554
|
+
...themeProps(theme),
|
|
2555
|
+
children: devChrome ? `${targetError.message} (${targetError.code})` : strings.loadFailed
|
|
2556
|
+
}
|
|
2557
|
+
);
|
|
2558
|
+
}
|
|
2286
2559
|
if (normalized && !normalized.ok) {
|
|
2287
2560
|
const error = new FilloError2(`This form could not be rendered: ${normalized.error}`, 422);
|
|
2288
2561
|
if (props.renderError) return /* @__PURE__ */ jsx7(Fragment3, { children: props.renderError(error) });
|
|
@@ -2323,7 +2596,14 @@ function FilloForm(props) {
|
|
|
2323
2596
|
);
|
|
2324
2597
|
}
|
|
2325
2598
|
if (currentLoaded?.closed) {
|
|
2326
|
-
return /* @__PURE__ */ jsx7(
|
|
2599
|
+
return /* @__PURE__ */ jsx7(
|
|
2600
|
+
"div",
|
|
2601
|
+
{
|
|
2602
|
+
className: `fillo-form fillo-form--closed ${props.className ?? ""}`,
|
|
2603
|
+
...themeProps(theme),
|
|
2604
|
+
children: /* @__PURE__ */ jsx7("p", { className: "fillo-closed", children: strings.closed })
|
|
2605
|
+
}
|
|
2606
|
+
);
|
|
2327
2607
|
}
|
|
2328
2608
|
const canonicalSyncError = codeForm && syncError && !props.skipValidation ? syncError : null;
|
|
2329
2609
|
if (canonicalSyncError && props.renderError) {
|
|
@@ -2365,7 +2645,14 @@ function FilloForm(props) {
|
|
|
2365
2645
|
}
|
|
2366
2646
|
);
|
|
2367
2647
|
}
|
|
2368
|
-
return /* @__PURE__ */ jsx7(
|
|
2648
|
+
return /* @__PURE__ */ jsx7(
|
|
2649
|
+
"div",
|
|
2650
|
+
{
|
|
2651
|
+
className: `fillo-form fillo-form--closed ${props.className ?? ""}`,
|
|
2652
|
+
...themeProps(theme),
|
|
2653
|
+
children: /* @__PURE__ */ jsx7("p", { className: "fillo-closed", children: variant === "closed" ? strings.closed : strings.notLive })
|
|
2654
|
+
}
|
|
2655
|
+
);
|
|
2369
2656
|
}
|
|
2370
2657
|
const awaitingCanonical = Boolean(codeForm && codeFormSyncing && !props.skipValidation);
|
|
2371
2658
|
if (!devChrome && awaitingCanonical || !schema) {
|
|
@@ -2390,10 +2677,12 @@ function FilloForm(props) {
|
|
|
2390
2677
|
ResolvedForm,
|
|
2391
2678
|
{
|
|
2392
2679
|
...props,
|
|
2393
|
-
client,
|
|
2680
|
+
client: renderOnly ? void 0 : client,
|
|
2394
2681
|
schema,
|
|
2395
2682
|
theme,
|
|
2396
|
-
formId: syncedFormId ?? formId,
|
|
2683
|
+
formId: renderOnly ? void 0 : syncedFormId ?? formId,
|
|
2684
|
+
renderOnly,
|
|
2685
|
+
skipValidation: renderOnly ? true : props.skipValidation,
|
|
2397
2686
|
poweredBy,
|
|
2398
2687
|
brandLabel: branding?.label,
|
|
2399
2688
|
brandHref: branding?.href,
|
|
@@ -2401,6 +2690,7 @@ function FilloForm(props) {
|
|
|
2401
2690
|
stagedNotice: codeChangesStaged,
|
|
2402
2691
|
syncErrorNotice: syncError ?? syncNoticeError ?? void 0,
|
|
2403
2692
|
uploadsAvailable: codeForm ? syncedUploadsAvailable : currentLoaded?.uploadsAvailable,
|
|
2693
|
+
uploadFileSizeLimitMb: codeForm ? syncedUploadFileSizeLimitMb : currentLoaded?.uploadFileSizeLimitMb ?? props.uploadFileSizeLimitMb,
|
|
2404
2694
|
syncWarningCode: codeForm ? syncedWarningCode : void 0,
|
|
2405
2695
|
syncWarningUrl: syncedWarningUrl,
|
|
2406
2696
|
challenge
|
|
@@ -2463,20 +2753,21 @@ function useIsDevEnv() {
|
|
|
2463
2753
|
function ResolvedForm(props) {
|
|
2464
2754
|
const { schema, theme } = props;
|
|
2465
2755
|
const displayOnly = props.displayOnly === true;
|
|
2756
|
+
const renderOnly = props.renderOnly === true;
|
|
2466
2757
|
const instanceId = useId2().replace(/:/g, "");
|
|
2467
2758
|
const devEnv = useIsDevEnv();
|
|
2468
2759
|
const devChrome = !displayOnly && (props.preview === true || devEnv);
|
|
2469
|
-
const hpRef =
|
|
2760
|
+
const hpRef = useRef8(null);
|
|
2470
2761
|
const codeForm = isCodeForm2(props.form) ? props.form : null;
|
|
2471
2762
|
const client = props.client;
|
|
2472
|
-
const challenge = props.challenge;
|
|
2763
|
+
const challenge = renderOnly ? void 0 : props.challenge;
|
|
2473
2764
|
const challengeRequired = Boolean(challenge);
|
|
2474
|
-
const challengeTokenRef =
|
|
2765
|
+
const challengeTokenRef = useRef8(void 0);
|
|
2475
2766
|
const [resyncWarning, setResyncWarning] = useState6(null);
|
|
2476
2767
|
const [resolutionFailureCode, setResolutionFailureCode] = useState6(null);
|
|
2477
2768
|
const [challengeToken, setChallengeToken] = useState6(void 0);
|
|
2478
2769
|
const [challengeError, setChallengeError] = useState6(false);
|
|
2479
|
-
const resetChallengeRef =
|
|
2770
|
+
const resetChallengeRef = useRef8(void 0);
|
|
2480
2771
|
const handleChallengeToken = useCallback((token) => {
|
|
2481
2772
|
challengeTokenRef.current = token;
|
|
2482
2773
|
setChallengeToken(token);
|
|
@@ -2494,7 +2785,8 @@ function ResolvedForm(props) {
|
|
|
2494
2785
|
setResyncWarning({
|
|
2495
2786
|
code: result.warningCode,
|
|
2496
2787
|
url: result.warningUrl,
|
|
2497
|
-
uploadsAvailable: result.uploadsAvailable
|
|
2788
|
+
uploadsAvailable: result.uploadsAvailable,
|
|
2789
|
+
uploadFileSizeLimitMb: result.uploadFileSizeLimitMb
|
|
2498
2790
|
});
|
|
2499
2791
|
if (result.status === "draft") {
|
|
2500
2792
|
throw new FilloError2(
|
|
@@ -2580,19 +2872,44 @@ function ResolvedForm(props) {
|
|
|
2580
2872
|
resetChallengeRef.current?.();
|
|
2581
2873
|
}
|
|
2582
2874
|
});
|
|
2583
|
-
useDraftFlush(api, !displayOnly);
|
|
2875
|
+
useDraftFlush(api, !displayOnly && !renderOnly);
|
|
2876
|
+
const strings = resolveStrings(props.strings);
|
|
2877
|
+
const announceRef = useRef8(null);
|
|
2878
|
+
const announce = useCallback((text) => {
|
|
2879
|
+
const el = announceRef.current;
|
|
2880
|
+
if (!el) return;
|
|
2881
|
+
if (el.textContent === text) {
|
|
2882
|
+
el.textContent = "";
|
|
2883
|
+
nextFrame(() => {
|
|
2884
|
+
if (announceRef.current) announceRef.current.textContent = text;
|
|
2885
|
+
});
|
|
2886
|
+
return;
|
|
2887
|
+
}
|
|
2888
|
+
el.textContent = text;
|
|
2889
|
+
}, []);
|
|
2890
|
+
useEffect8(() => {
|
|
2891
|
+
if (api.status === "submitting") announce(strings.submittingAnnouncement);
|
|
2892
|
+
}, [api.status, announce, strings.submittingAnnouncement]);
|
|
2893
|
+
const resuming = api.resumedDraft || api.editingPrevious;
|
|
2894
|
+
const resumeAnnouncement = api.editingPrevious ? strings.editNotice : strings.resumeNotice;
|
|
2895
|
+
useEffect8(() => {
|
|
2896
|
+
if (resuming) announce(resumeAnnouncement);
|
|
2897
|
+
}, [resuming, resumeAnnouncement, announce]);
|
|
2584
2898
|
const themed = useMemo5(() => themeProps(theme), [theme]);
|
|
2585
2899
|
const warningCode = resyncWarning ? resyncWarning.code : props.syncWarningCode;
|
|
2586
2900
|
const warningUrl = resyncWarning ? resyncWarning.url : props.syncWarningUrl;
|
|
2587
2901
|
const uploadsAvailable = resyncWarning ? resyncWarning.uploadsAvailable : props.uploadsAvailable;
|
|
2902
|
+
const uploadFileSizeLimitMb = resyncWarning ? resyncWarning.uploadFileSizeLimitMb : props.uploadFileSizeLimitMb;
|
|
2588
2903
|
const chromeValue = useMemo5(
|
|
2589
2904
|
() => ({
|
|
2590
2905
|
devChrome,
|
|
2906
|
+
renderOnly,
|
|
2591
2907
|
uploadsAvailable,
|
|
2908
|
+
uploadFileSizeLimitMb,
|
|
2592
2909
|
warningCode,
|
|
2593
2910
|
warningUrl
|
|
2594
2911
|
}),
|
|
2595
|
-
[devChrome, uploadsAvailable, warningCode, warningUrl]
|
|
2912
|
+
[devChrome, renderOnly, uploadsAvailable, uploadFileSizeLimitMb, warningCode, warningUrl]
|
|
2596
2913
|
);
|
|
2597
2914
|
const settings = schema.settings;
|
|
2598
2915
|
const submitted = api.status === "submitted";
|
|
@@ -2602,19 +2919,23 @@ function ResolvedForm(props) {
|
|
|
2602
2919
|
const url = safeHttpUrl(settings.redirectUrl);
|
|
2603
2920
|
if (url) window.location.assign(url);
|
|
2604
2921
|
}, [liveSubmit, settings.redirectUrl]);
|
|
2605
|
-
const successRef =
|
|
2922
|
+
const successRef = useRef8(null);
|
|
2606
2923
|
useEffect8(() => {
|
|
2607
2924
|
if (liveSubmit) successRef.current?.focus();
|
|
2608
2925
|
}, [liveSubmit]);
|
|
2609
|
-
const blocksRef =
|
|
2610
|
-
const prevPageIndex =
|
|
2926
|
+
const blocksRef = useRef8(null);
|
|
2927
|
+
const prevPageIndex = useRef8(api.pageIndex);
|
|
2611
2928
|
useEffect8(() => {
|
|
2612
2929
|
if (prevPageIndex.current === api.pageIndex) return;
|
|
2613
2930
|
prevPageIndex.current = api.pageIndex;
|
|
2614
|
-
blocksRef.current?.
|
|
2931
|
+
const container = blocksRef.current?.parentElement;
|
|
2932
|
+
const heading = container?.querySelector(".fillo-page-title, .fillo-title");
|
|
2933
|
+
const target = heading ?? blocksRef.current;
|
|
2934
|
+
if (!target) return;
|
|
2935
|
+
if (!target.hasAttribute("tabindex")) target.setAttribute("tabindex", "-1");
|
|
2936
|
+
target.focus();
|
|
2615
2937
|
}, [api.pageIndex]);
|
|
2616
2938
|
const appearance = props.appearance;
|
|
2617
|
-
const strings = resolveStrings(props.strings);
|
|
2618
2939
|
if (api.status === "submitted") {
|
|
2619
2940
|
return /* @__PURE__ */ jsxs6(
|
|
2620
2941
|
"div",
|
|
@@ -2629,16 +2950,20 @@ function ResolvedForm(props) {
|
|
|
2629
2950
|
{ slot: "root", status: "submitted" }
|
|
2630
2951
|
),
|
|
2631
2952
|
"data-fillo": "root",
|
|
2953
|
+
"data-fillo-form-id": props.formId,
|
|
2632
2954
|
"data-state": "submitted",
|
|
2633
2955
|
...themed,
|
|
2634
2956
|
children: [
|
|
2635
2957
|
props.renderSuccess ? props.renderSuccess() : /* @__PURE__ */ jsxs6(
|
|
2636
2958
|
"div",
|
|
2637
2959
|
{
|
|
2638
|
-
className: slotClass3("fillo-success", appearance, {
|
|
2960
|
+
className: slotClass3("fillo-success", appearance, {
|
|
2961
|
+
slot: "success",
|
|
2962
|
+
status: "submitted"
|
|
2963
|
+
}),
|
|
2639
2964
|
"data-fillo": "success",
|
|
2640
2965
|
children: [
|
|
2641
|
-
/* @__PURE__ */ jsx7("div", { className: "fillo-success-mark", "aria-hidden": "true"
|
|
2966
|
+
/* @__PURE__ */ jsx7("div", { className: "fillo-success-mark", "aria-hidden": "true" }),
|
|
2642
2967
|
/* @__PURE__ */ jsx7("h2", { className: "fillo-success-title", children: settings.successTitle ?? strings.successTitle }),
|
|
2643
2968
|
/* @__PURE__ */ jsx7("p", { className: "fillo-success-message", children: api.duplicateSubmission ? strings.alreadyAnswered : settings.successMessage ?? strings.successMessage })
|
|
2644
2969
|
]
|
|
@@ -2661,11 +2986,32 @@ function ResolvedForm(props) {
|
|
|
2661
2986
|
const progressPos = progressSeq.indexOf(api.page.id);
|
|
2662
2987
|
const progressStep = progressPos >= 0 ? progressPos + 1 : Math.min(api.pageIndex + 1, progressTotal);
|
|
2663
2988
|
const submitFixUrl = devChrome && resolutionFailureCode === "form_not_published" && warningCode === "storage_required" ? safeHttpUrl(warningUrl) : null;
|
|
2989
|
+
const invalidFields = [];
|
|
2990
|
+
for (const block of api.blocks) {
|
|
2991
|
+
if (!isField2(block)) continue;
|
|
2992
|
+
const raw = api.errors[block.id];
|
|
2993
|
+
if (!raw) continue;
|
|
2994
|
+
invalidFields.push({
|
|
2995
|
+
field: block,
|
|
2996
|
+
error: raw === REQUIRED_FIELD_MESSAGE2 ? strings.required : raw,
|
|
2997
|
+
inputId: createFilloFieldIds(instanceId, block.id).inputId
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
2664
3000
|
const rootClass = slotClass3(`fillo-form ${props.className ?? ""}`, appearance, {
|
|
2665
3001
|
slot: "root",
|
|
2666
3002
|
status: api.status
|
|
2667
3003
|
});
|
|
2668
3004
|
const formBody = /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
3005
|
+
/* @__PURE__ */ jsx7(
|
|
3006
|
+
"span",
|
|
3007
|
+
{
|
|
3008
|
+
ref: announceRef,
|
|
3009
|
+
className: "fillo-sr-only",
|
|
3010
|
+
role: "status",
|
|
3011
|
+
"aria-live": "polite",
|
|
3012
|
+
"data-fillo": "announce"
|
|
3013
|
+
}
|
|
3014
|
+
),
|
|
2669
3015
|
devChrome && /* @__PURE__ */ jsx7(
|
|
2670
3016
|
DevChrome,
|
|
2671
3017
|
{
|
|
@@ -2675,15 +3021,14 @@ function ResolvedForm(props) {
|
|
|
2675
3021
|
staged: props.stagedNotice,
|
|
2676
3022
|
draft: props.draftNotice,
|
|
2677
3023
|
warningUrl: props.syncWarningUrl,
|
|
2678
|
-
noClient: !props.client && !props.skipValidation
|
|
3024
|
+
noClient: !props.client && !props.skipValidation && !renderOnly
|
|
2679
3025
|
}
|
|
2680
3026
|
),
|
|
2681
|
-
|
|
3027
|
+
resuming && /* @__PURE__ */ jsxs6(
|
|
2682
3028
|
"div",
|
|
2683
3029
|
{
|
|
2684
3030
|
className: slotClass3("fillo-resume", appearance, { slot: "resume" }),
|
|
2685
3031
|
"data-fillo": "resume",
|
|
2686
|
-
role: "status",
|
|
2687
3032
|
children: [
|
|
2688
3033
|
/* @__PURE__ */ jsx7("span", { className: "fillo-resume-text", children: api.editingPrevious ? strings.editNotice : strings.resumeNotice }),
|
|
2689
3034
|
/* @__PURE__ */ jsx7("button", { type: "button", className: "fillo-resume-clear", onClick: api.resetDraft, children: strings.resumeStartOver })
|
|
@@ -2693,7 +3038,9 @@ function ResolvedForm(props) {
|
|
|
2693
3038
|
api.resumeLinkFailed && !api.resumedDraft && !api.editingPrevious && /* @__PURE__ */ jsx7(
|
|
2694
3039
|
"div",
|
|
2695
3040
|
{
|
|
2696
|
-
className: slotClass3("fillo-resume fillo-resume--expired", appearance, {
|
|
3041
|
+
className: slotClass3("fillo-resume fillo-resume--expired", appearance, {
|
|
3042
|
+
slot: "resume"
|
|
3043
|
+
}),
|
|
2697
3044
|
"data-fillo": "resume",
|
|
2698
3045
|
role: "status",
|
|
2699
3046
|
children: /* @__PURE__ */ jsx7("span", { className: "fillo-resume-text", children: strings.resumeLinkExpired })
|
|
@@ -2714,33 +3061,83 @@ function ResolvedForm(props) {
|
|
|
2714
3061
|
{
|
|
2715
3062
|
className: slotClass3("fillo-progress-fill", appearance, { slot: "progressFill" }),
|
|
2716
3063
|
"data-fillo": "progressFill",
|
|
2717
|
-
style: {
|
|
3064
|
+
style: {
|
|
3065
|
+
"--fillo-progress-value": `${progressStep / progressTotal * 100}%`
|
|
3066
|
+
}
|
|
2718
3067
|
}
|
|
2719
3068
|
)
|
|
2720
3069
|
}
|
|
2721
3070
|
),
|
|
2722
|
-
api.pageIndex === 0 && props.showTitle !== false && /* @__PURE__ */ jsxs6(
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
"
|
|
3071
|
+
api.pageIndex === 0 && props.showTitle !== false && /* @__PURE__ */ jsxs6(
|
|
3072
|
+
"header",
|
|
3073
|
+
{
|
|
3074
|
+
className: slotClass3("fillo-header", appearance, { slot: "header" }),
|
|
3075
|
+
"data-fillo": "header",
|
|
3076
|
+
children: [
|
|
3077
|
+
schema.title && /* @__PURE__ */ jsx7(
|
|
3078
|
+
"h1",
|
|
3079
|
+
{
|
|
3080
|
+
className: slotClass3("fillo-title", appearance, { slot: "title" }),
|
|
3081
|
+
"data-fillo": "title",
|
|
3082
|
+
children: schema.title
|
|
3083
|
+
}
|
|
3084
|
+
),
|
|
3085
|
+
schema.description && /* @__PURE__ */ jsx7(
|
|
3086
|
+
"p",
|
|
3087
|
+
{
|
|
3088
|
+
className: slotClass3("fillo-form-description", appearance, { slot: "description" }),
|
|
3089
|
+
"data-fillo": "description",
|
|
3090
|
+
children: schema.description
|
|
3091
|
+
}
|
|
3092
|
+
)
|
|
3093
|
+
]
|
|
3094
|
+
}
|
|
3095
|
+
),
|
|
3096
|
+
multiPage && api.page.title && api.pageIndex > 0 && /* @__PURE__ */ jsx7(
|
|
3097
|
+
"h2",
|
|
3098
|
+
{
|
|
3099
|
+
className: slotClass3("fillo-page-title", appearance, { slot: "pageTitle" }),
|
|
3100
|
+
"data-fillo": "pageTitle",
|
|
3101
|
+
children: api.page.title
|
|
3102
|
+
}
|
|
3103
|
+
),
|
|
3104
|
+
invalidFields.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "fillo-error-summary", role: "alert", tabIndex: -1, "data-fillo": "error-summary", children: [
|
|
3105
|
+
/* @__PURE__ */ jsx7("p", { className: "fillo-error-summary-title", children: strings.errorSummaryTitle }),
|
|
3106
|
+
/* @__PURE__ */ jsx7("ul", { children: invalidFields.map(({ field, error, inputId }) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsxs6(
|
|
3107
|
+
"a",
|
|
2726
3108
|
{
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
3109
|
+
href: `#${inputId}`,
|
|
3110
|
+
onClick: (e) => {
|
|
3111
|
+
e.preventDefault();
|
|
3112
|
+
focusField(inputId);
|
|
3113
|
+
},
|
|
3114
|
+
children: [
|
|
3115
|
+
field.label,
|
|
3116
|
+
": ",
|
|
3117
|
+
error
|
|
3118
|
+
]
|
|
2730
3119
|
}
|
|
2731
|
-
)
|
|
3120
|
+
) }, field.id)) })
|
|
2732
3121
|
] }),
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
BlockRenderer,
|
|
3122
|
+
/* @__PURE__ */ jsx7(
|
|
3123
|
+
"div",
|
|
2736
3124
|
{
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
3125
|
+
className: slotClass3("fillo-blocks", appearance, { slot: "blocks" }),
|
|
3126
|
+
"data-fillo": "blocks",
|
|
3127
|
+
ref: blocksRef,
|
|
3128
|
+
tabIndex: -1,
|
|
3129
|
+
children: api.blocks.map((block) => /* @__PURE__ */ jsx7(
|
|
3130
|
+
BlockRenderer,
|
|
3131
|
+
{
|
|
3132
|
+
block,
|
|
3133
|
+
api,
|
|
3134
|
+
components: props.components,
|
|
3135
|
+
customComponents: props.customComponents
|
|
3136
|
+
},
|
|
3137
|
+
block.id
|
|
3138
|
+
))
|
|
3139
|
+
}
|
|
3140
|
+
),
|
|
2744
3141
|
!displayOnly && /* @__PURE__ */ jsx7(
|
|
2745
3142
|
"input",
|
|
2746
3143
|
{
|
|
@@ -2780,43 +3177,66 @@ function ResolvedForm(props) {
|
|
|
2780
3177
|
/* @__PURE__ */ jsx7("a", { href: submitFixUrl, target: "_blank", rel: "noopener noreferrer", children: submitFixUrl })
|
|
2781
3178
|
] })
|
|
2782
3179
|
] }),
|
|
2783
|
-
showFooter && /* @__PURE__ */ jsxs6(
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
{
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
3180
|
+
showFooter && /* @__PURE__ */ jsxs6(
|
|
3181
|
+
"footer",
|
|
3182
|
+
{
|
|
3183
|
+
className: slotClass3("fillo-footer", appearance, { slot: "footer" }),
|
|
3184
|
+
"data-fillo": "footer",
|
|
3185
|
+
children: [
|
|
3186
|
+
multiPage && !api.isFirstPage && /* @__PURE__ */ jsx7(
|
|
3187
|
+
"button",
|
|
3188
|
+
{
|
|
3189
|
+
type: "button",
|
|
3190
|
+
className: slotClass3("fillo-button fillo-button--ghost", appearance, {
|
|
3191
|
+
slot: "button",
|
|
3192
|
+
variant: "ghost"
|
|
3193
|
+
}),
|
|
3194
|
+
"data-fillo": "button",
|
|
3195
|
+
onClick: api.back,
|
|
3196
|
+
children: strings.back
|
|
3197
|
+
}
|
|
3198
|
+
),
|
|
3199
|
+
showPrimaryButton && /* @__PURE__ */ jsx7(
|
|
3200
|
+
"button",
|
|
3201
|
+
{
|
|
3202
|
+
type: "submit",
|
|
3203
|
+
className: slotClass3("fillo-button fillo-button--primary", appearance, {
|
|
3204
|
+
slot: "button",
|
|
3205
|
+
variant: "primary"
|
|
3206
|
+
}),
|
|
3207
|
+
"data-fillo": "button",
|
|
3208
|
+
disabled: api.status === "submitting" || api.uploading || // Wait for the human check before enabling submit (never
|
|
3209
|
+
// "Next"). The server rejects a tokenless submit regardless —
|
|
3210
|
+
// this is UX only.
|
|
3211
|
+
showChallenge && !challengeToken,
|
|
3212
|
+
children: api.uploading ? strings.uploading : api.status === "submitting" ? strings.submitting : api.isLastPage ? settings.submitLabel ?? strings.submit : strings.next
|
|
3213
|
+
}
|
|
3214
|
+
)
|
|
3215
|
+
]
|
|
3216
|
+
}
|
|
3217
|
+
),
|
|
2808
3218
|
props.poweredBy && /* @__PURE__ */ jsx7(PoweredBy, { label: props.brandLabel, href: props.brandHref })
|
|
2809
3219
|
] });
|
|
2810
|
-
return /* @__PURE__ */ jsx7(FilloContext.Provider, { value: api, children: /* @__PURE__ */ jsx7(FilloChromeContext.Provider, { value: chromeValue, children: /* @__PURE__ */ jsx7(FilloStringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx7(FilloAppearanceContext.Provider, { value: appearance, children: /* @__PURE__ */ jsx7(FilloInstanceIdContext.Provider, { value: instanceId, children: displayOnly ? (
|
|
3220
|
+
return /* @__PURE__ */ jsx7(FilloContext.Provider, { value: api, children: /* @__PURE__ */ jsx7(FilloChromeContext.Provider, { value: chromeValue, children: /* @__PURE__ */ jsx7(FilloAnnounceContext.Provider, { value: announce, children: /* @__PURE__ */ jsx7(FilloStringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx7(FilloAppearanceContext.Provider, { value: appearance, children: /* @__PURE__ */ jsx7(FilloInstanceIdContext.Provider, { value: instanceId, children: displayOnly ? (
|
|
2811
3221
|
// Display-only preview: a plain div (no form element to submit) with
|
|
2812
3222
|
// every control inside a natively disabled fieldset — unfocusable
|
|
2813
3223
|
// and unfillable even without the stylesheet or inert support.
|
|
2814
|
-
/* @__PURE__ */ jsx7(
|
|
3224
|
+
/* @__PURE__ */ jsx7(
|
|
3225
|
+
"div",
|
|
3226
|
+
{
|
|
3227
|
+
className: rootClass,
|
|
3228
|
+
"data-fillo": "preview-form",
|
|
3229
|
+
"data-state": "preview",
|
|
3230
|
+
...themed,
|
|
3231
|
+
children: /* @__PURE__ */ jsx7("fieldset", { disabled: true, className: "fillo-not-open-fields", children: formBody })
|
|
3232
|
+
}
|
|
3233
|
+
)
|
|
2815
3234
|
) : /* @__PURE__ */ jsx7(
|
|
2816
3235
|
"form",
|
|
2817
3236
|
{
|
|
2818
3237
|
className: rootClass,
|
|
2819
3238
|
"data-fillo": "root",
|
|
3239
|
+
"data-fillo-form-id": props.formId,
|
|
2820
3240
|
"data-state": api.status,
|
|
2821
3241
|
"data-page": api.pageIndex + 1,
|
|
2822
3242
|
"data-last-page": api.isLastPage ? "" : void 0,
|
|
@@ -2826,20 +3246,20 @@ function ResolvedForm(props) {
|
|
|
2826
3246
|
e.preventDefault();
|
|
2827
3247
|
const formEl = e.currentTarget;
|
|
2828
3248
|
if (api.isLastPage) {
|
|
2829
|
-
void api.submit().then(() =>
|
|
3249
|
+
void api.submit().then(() => focusErrorSummary(formEl)).catch(() => {
|
|
2830
3250
|
});
|
|
2831
3251
|
} else {
|
|
2832
3252
|
api.next();
|
|
2833
|
-
|
|
3253
|
+
focusErrorSummary(formEl);
|
|
2834
3254
|
}
|
|
2835
3255
|
},
|
|
2836
3256
|
children: formBody
|
|
2837
3257
|
}
|
|
2838
|
-
) }) }) }) }) });
|
|
3258
|
+
) }) }) }) }) }) });
|
|
2839
3259
|
}
|
|
2840
3260
|
|
|
2841
3261
|
// src/jsx.tsx
|
|
2842
|
-
import { useRef as
|
|
3262
|
+
import { useRef as useRef9 } from "react";
|
|
2843
3263
|
import {
|
|
2844
3264
|
codeFormFromJsx,
|
|
2845
3265
|
FilloJsxError,
|
|
@@ -2853,7 +3273,7 @@ function JsxForm(props) {
|
|
|
2853
3273
|
const { id, title, description, settings, theme, client, children, ...rest } = props;
|
|
2854
3274
|
const compiled = codeFormFromJsx({ id, title, description, settings, theme }, children);
|
|
2855
3275
|
const json = JSON.stringify(compiled.schema) + JSON.stringify(compiled.theme ?? null);
|
|
2856
|
-
const memo2 =
|
|
3276
|
+
const memo2 = useRef9(null);
|
|
2857
3277
|
if (memo2.current && memo2.current.json !== json && isDevEnv()) {
|
|
2858
3278
|
console.warn(
|
|
2859
3279
|
`[fillo] "${id}": form structure changed between renders. If you just edited the form, ignore this. Otherwise: conditional questions are visibleIf={when(\u2026)\u2026}, never {cond && <Fillo.\u2026/>} \u2014 a per-visitor schema churns drafts in your workspace.`
|
|
@@ -2862,7 +3282,7 @@ function JsxForm(props) {
|
|
|
2862
3282
|
if (!memo2.current || memo2.current.json !== json) {
|
|
2863
3283
|
memo2.current = { json, form: compiled };
|
|
2864
3284
|
}
|
|
2865
|
-
return /* @__PURE__ */ jsx8(FilloForm, { form: memo2.current.form, client, ...rest });
|
|
3285
|
+
return /* @__PURE__ */ jsx8(FilloForm, { ...{ form: memo2.current.form, client, ...rest } });
|
|
2866
3286
|
}
|
|
2867
3287
|
function defineFormFromJsx(element) {
|
|
2868
3288
|
if (!element || element.type !== JsxForm) {
|
|
@@ -2897,6 +3317,7 @@ var Fillo = {
|
|
|
2897
3317
|
Date: B.Date,
|
|
2898
3318
|
FileUpload: B.FileUpload,
|
|
2899
3319
|
Hidden: B.Hidden,
|
|
3320
|
+
Calculated: B.Calculated,
|
|
2900
3321
|
Custom: B.Custom,
|
|
2901
3322
|
Heading: B.Heading,
|
|
2902
3323
|
Paragraph: B.Paragraph,
|
|
@@ -2906,9 +3327,10 @@ var Fillo = {
|
|
|
2906
3327
|
};
|
|
2907
3328
|
|
|
2908
3329
|
// src/provider.tsx
|
|
2909
|
-
import { useId as useId3, useMemo as useMemo6, useState as useState7 } from "react";
|
|
3330
|
+
import { useEffect as useEffect9, useId as useId3, useMemo as useMemo6, useState as useState7 } from "react";
|
|
2910
3331
|
import {
|
|
2911
3332
|
FilloError as FilloError3,
|
|
3333
|
+
createClient as createClient2,
|
|
2912
3334
|
formSchemasEqual as formSchemasEqual2,
|
|
2913
3335
|
isFilloError as isFilloError3,
|
|
2914
3336
|
normalizeFormSchema as normalizeFormSchema2,
|
|
@@ -2926,13 +3348,33 @@ function FilloProvider({
|
|
|
2926
3348
|
onError,
|
|
2927
3349
|
renderError,
|
|
2928
3350
|
preview,
|
|
3351
|
+
renderOnly,
|
|
3352
|
+
skipValidation,
|
|
2929
3353
|
...options
|
|
2930
3354
|
}) {
|
|
3355
|
+
const localPreview = renderOnly === true || skipValidation === true;
|
|
3356
|
+
const activeClient = useMemo6(
|
|
3357
|
+
() => localPreview ? void 0 : client ?? (formId ? createClient2() : void 0),
|
|
3358
|
+
[client, formId, localPreview]
|
|
3359
|
+
);
|
|
3360
|
+
const activeFormId = localPreview ? void 0 : formId;
|
|
2931
3361
|
const instanceId = useId3().replace(/:/g, "");
|
|
2932
3362
|
const devEnv = useIsDevEnv();
|
|
2933
3363
|
const devChrome = preview === true || devEnv;
|
|
2934
3364
|
if (preview === true) warnPreviewInProduction();
|
|
2935
3365
|
const codeForm = isCodeForm2(form) ? form : null;
|
|
3366
|
+
const targetError = useMemo6(
|
|
3367
|
+
() => !formId && !localPreview && (!codeForm || !client) ? new FilloError3(
|
|
3368
|
+
"This form has no Fillo target. Pass formId with the schema, use a defineForm() value with client, or set renderOnly for a non-submitting preview.",
|
|
3369
|
+
422,
|
|
3370
|
+
void 0,
|
|
3371
|
+
"form_target_required"
|
|
3372
|
+
) : null,
|
|
3373
|
+
[client, codeForm, formId, localPreview]
|
|
3374
|
+
);
|
|
3375
|
+
useEffect9(() => {
|
|
3376
|
+
if (targetError) onError?.(targetError);
|
|
3377
|
+
}, [onError, targetError]);
|
|
2936
3378
|
const {
|
|
2937
3379
|
formId: syncedFormId,
|
|
2938
3380
|
status: syncedStatus,
|
|
@@ -2942,10 +3384,11 @@ function FilloProvider({
|
|
|
2942
3384
|
accepting: syncedAccepting,
|
|
2943
3385
|
acceptingReason: syncedAcceptingReason,
|
|
2944
3386
|
uploadsAvailable,
|
|
3387
|
+
uploadFileSizeLimitMb,
|
|
2945
3388
|
warningCode,
|
|
2946
3389
|
warningUrl
|
|
2947
|
-
} = useCodeFormSync(form,
|
|
2948
|
-
allowUnsynced: Boolean(!
|
|
3390
|
+
} = useCodeFormSync(form, activeClient, onError, {
|
|
3391
|
+
allowUnsynced: Boolean(!activeClient || activeFormId || localPreview)
|
|
2949
3392
|
});
|
|
2950
3393
|
const [resyncWarning, setResyncWarning] = useState7(null);
|
|
2951
3394
|
const rawSchema = codeForm ? resolvedSchema && !devChrome ? resolvedSchema : codeForm.schema : form;
|
|
@@ -2955,13 +3398,14 @@ function FilloProvider({
|
|
|
2955
3398
|
}
|
|
2956
3399
|
const schema = normalized.schema;
|
|
2957
3400
|
const resolveFormId = useMemo6(
|
|
2958
|
-
() => codeForm &&
|
|
3401
|
+
() => codeForm && activeClient?.key ? async () => {
|
|
2959
3402
|
try {
|
|
2960
|
-
const result = await syncCodeForm3(
|
|
3403
|
+
const result = await syncCodeForm3(activeClient, codeForm, { bypassCache: true });
|
|
2961
3404
|
setResyncWarning({
|
|
2962
3405
|
code: result.warningCode,
|
|
2963
3406
|
url: result.warningUrl,
|
|
2964
|
-
uploadsAvailable: result.uploadsAvailable
|
|
3407
|
+
uploadsAvailable: result.uploadsAvailable,
|
|
3408
|
+
uploadFileSizeLimitMb: result.uploadFileSizeLimitMb
|
|
2965
3409
|
});
|
|
2966
3410
|
if (result.status === "draft") {
|
|
2967
3411
|
throw new FilloError3(
|
|
@@ -3018,13 +3462,14 @@ function FilloProvider({
|
|
|
3018
3462
|
throw failure;
|
|
3019
3463
|
}
|
|
3020
3464
|
} : void 0,
|
|
3021
|
-
[
|
|
3465
|
+
[activeClient, codeForm, onError, schema]
|
|
3022
3466
|
);
|
|
3023
3467
|
const api = useFilloController({
|
|
3024
3468
|
...options,
|
|
3025
|
-
client,
|
|
3469
|
+
client: activeClient,
|
|
3026
3470
|
form: schema,
|
|
3027
|
-
formId: syncedFormId ??
|
|
3471
|
+
formId: syncedFormId ?? activeFormId ?? void 0,
|
|
3472
|
+
skipValidation: localPreview,
|
|
3028
3473
|
resolveFormId,
|
|
3029
3474
|
// Dev chrome (preview or dev env) surfaces the developer-grade resolution
|
|
3030
3475
|
// failure (message + code); an explicit option wins.
|
|
@@ -3033,26 +3478,40 @@ function FilloProvider({
|
|
|
3033
3478
|
// method; recorded per response so usage stays measurable.
|
|
3034
3479
|
surface: "headless"
|
|
3035
3480
|
});
|
|
3036
|
-
useDraftFlush(api);
|
|
3481
|
+
useDraftFlush(api, !localPreview);
|
|
3037
3482
|
const freshWarningCode = resyncWarning ? resyncWarning.code : warningCode;
|
|
3038
3483
|
const freshWarningUrl = resyncWarning ? resyncWarning.url : warningUrl;
|
|
3039
3484
|
const freshUploadsAvailable = resyncWarning ? resyncWarning.uploadsAvailable : uploadsAvailable;
|
|
3485
|
+
const freshUploadFileSizeLimitMb = resyncWarning ? resyncWarning.uploadFileSizeLimitMb : uploadFileSizeLimitMb;
|
|
3040
3486
|
const chromeValue = useMemo6(
|
|
3041
3487
|
() => ({
|
|
3042
3488
|
devChrome,
|
|
3489
|
+
renderOnly: localPreview,
|
|
3043
3490
|
uploadsAvailable: freshUploadsAvailable,
|
|
3491
|
+
uploadFileSizeLimitMb: freshUploadFileSizeLimitMb,
|
|
3044
3492
|
warningCode: freshWarningCode,
|
|
3045
3493
|
warningUrl: freshWarningUrl
|
|
3046
3494
|
}),
|
|
3047
|
-
[
|
|
3495
|
+
[
|
|
3496
|
+
devChrome,
|
|
3497
|
+
localPreview,
|
|
3498
|
+
freshUploadsAvailable,
|
|
3499
|
+
freshUploadFileSizeLimitMb,
|
|
3500
|
+
freshWarningCode,
|
|
3501
|
+
freshWarningUrl
|
|
3502
|
+
]
|
|
3048
3503
|
);
|
|
3049
3504
|
const resolvedStrings = resolveStrings2(strings);
|
|
3050
|
-
|
|
3505
|
+
if (targetError) {
|
|
3506
|
+
if (renderError) return /* @__PURE__ */ jsx9(Fragment4, { children: renderError(targetError) });
|
|
3507
|
+
throw targetError;
|
|
3508
|
+
}
|
|
3509
|
+
const canonicalSyncError = syncError && !localPreview ? syncError : null;
|
|
3051
3510
|
if (canonicalSyncError && renderError) return /* @__PURE__ */ jsx9(Fragment4, { children: renderError(canonicalSyncError) });
|
|
3052
3511
|
if (canonicalSyncError && !devChrome) return null;
|
|
3053
|
-
if (codeFormSyncing && !
|
|
3054
|
-
const notPublished = Boolean(codeForm) && syncedStatus === "draft" && !
|
|
3055
|
-
const notAccepting = Boolean(codeForm) && syncedStatus === "published" && syncedAccepting === false && !
|
|
3512
|
+
if (codeFormSyncing && !localPreview && !devChrome) return null;
|
|
3513
|
+
const notPublished = Boolean(codeForm) && syncedStatus === "draft" && !localPreview;
|
|
3514
|
+
const notAccepting = Boolean(codeForm) && syncedStatus === "published" && syncedAccepting === false && !localPreview;
|
|
3056
3515
|
if ((notPublished || notAccepting) && !devChrome) {
|
|
3057
3516
|
const error = notPublished ? new FilloError3("This form isn't published yet.", 403, void 0, "form_not_published") : new FilloError3(
|
|
3058
3517
|
"This form is no longer accepting responses.",
|
|
@@ -3067,7 +3526,7 @@ function FilloProvider({
|
|
|
3067
3526
|
|
|
3068
3527
|
// src/index.ts
|
|
3069
3528
|
import {
|
|
3070
|
-
createClient as
|
|
3529
|
+
createClient as createClient3,
|
|
3071
3530
|
provisionWorkspace,
|
|
3072
3531
|
when,
|
|
3073
3532
|
FilloJsxError as FilloJsxError2,
|
|
@@ -3094,7 +3553,7 @@ export {
|
|
|
3094
3553
|
FilloJsxError2 as FilloJsxError,
|
|
3095
3554
|
FilloProvider,
|
|
3096
3555
|
FormField,
|
|
3097
|
-
|
|
3556
|
+
createClient3 as createClient,
|
|
3098
3557
|
defineForm,
|
|
3099
3558
|
provisionWorkspace,
|
|
3100
3559
|
useField,
|