@usefillo/react 0.12.1 → 0.13.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.js +511 -346
- package/dist/styles.css +45 -2
- package/dist/styles.unlayered.css +45 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
// src/FilloForm.tsx
|
|
4
4
|
import {
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect as
|
|
5
|
+
useCallback as useCallback2,
|
|
6
|
+
useEffect as useEffect9,
|
|
7
7
|
useId as useId2,
|
|
8
|
-
useMemo as
|
|
9
|
-
useRef as
|
|
8
|
+
useMemo as useMemo6,
|
|
9
|
+
useRef as useRef9,
|
|
10
10
|
useState as useState6,
|
|
11
11
|
useSyncExternalStore as useSyncExternalStore2
|
|
12
12
|
} from "react";
|
|
@@ -492,7 +492,171 @@ import {
|
|
|
492
492
|
slotClass as slotClass2,
|
|
493
493
|
visibleFields
|
|
494
494
|
} from "@usefillo/core";
|
|
495
|
-
import { memo, useEffect as
|
|
495
|
+
import { memo, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useMemo as useMemo5, useRef as useRef7, useState as useState5 } from "react";
|
|
496
|
+
|
|
497
|
+
// src/group.tsx
|
|
498
|
+
import { visibleGroupChildren } from "@usefillo/core";
|
|
499
|
+
import { useCallback, useContext as useContext3, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3 } from "react";
|
|
500
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
501
|
+
var EMPTY_INSTANCE = {};
|
|
502
|
+
var FOCUSABLE_SELECTOR = 'input:not(:disabled), select:not(:disabled), textarea:not(:disabled), button:not(:disabled), [tabindex]:not([tabindex="-1"])';
|
|
503
|
+
function firstFieldControl(card) {
|
|
504
|
+
const candidates = card.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
505
|
+
for (const el of candidates) {
|
|
506
|
+
if (!el.classList.contains("fillo-group-remove")) return el;
|
|
507
|
+
}
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
function materializeInstances(value, count) {
|
|
511
|
+
const base = Array.isArray(value) ? value : [];
|
|
512
|
+
const out = base.slice(0, count);
|
|
513
|
+
while (out.length < count) out.push({});
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
516
|
+
function GroupInstance({
|
|
517
|
+
group,
|
|
518
|
+
index,
|
|
519
|
+
count,
|
|
520
|
+
item,
|
|
521
|
+
instanceValue,
|
|
522
|
+
api,
|
|
523
|
+
atFloor,
|
|
524
|
+
onPatch,
|
|
525
|
+
onRemove,
|
|
526
|
+
cardRef
|
|
527
|
+
}) {
|
|
528
|
+
const strings = useStrings();
|
|
529
|
+
const groupId = group.id;
|
|
530
|
+
const n = index + 1;
|
|
531
|
+
const label = strings.groupInstanceLabel(item, n, count);
|
|
532
|
+
const { scopedChildren, data } = useMemo3(() => {
|
|
533
|
+
const prefix = `${groupId}.${index}.`;
|
|
534
|
+
const visible = visibleGroupChildren(group, instanceValue);
|
|
535
|
+
const scoped = [];
|
|
536
|
+
const scopedData = {};
|
|
537
|
+
for (const child of visible) {
|
|
538
|
+
const compoundId = prefix + child.id;
|
|
539
|
+
scoped.push({ ...child, id: compoundId });
|
|
540
|
+
scopedData[compoundId] = instanceValue[child.id];
|
|
541
|
+
}
|
|
542
|
+
return { scopedChildren: scoped, data: scopedData };
|
|
543
|
+
}, [group, instanceValue, groupId, index]);
|
|
544
|
+
const setValue = useCallback(
|
|
545
|
+
(fieldId, v) => {
|
|
546
|
+
const prefix = `${groupId}.${index}.`;
|
|
547
|
+
const childId = fieldId.startsWith(prefix) ? fieldId.slice(prefix.length) : fieldId;
|
|
548
|
+
onPatch(index, childId, v);
|
|
549
|
+
},
|
|
550
|
+
[groupId, index, onPatch]
|
|
551
|
+
);
|
|
552
|
+
const childApi = { ...api, data, errors: api.errors, setValue };
|
|
553
|
+
return /* @__PURE__ */ jsxs2("div", { ref: cardRef, className: "fillo-group-instance", role: "group", "aria-label": label, tabIndex: -1, children: [
|
|
554
|
+
/* @__PURE__ */ jsxs2("div", { className: "fillo-group-instance-header", children: [
|
|
555
|
+
/* @__PURE__ */ jsx2("p", { className: "fillo-group-instance-title", children: label }),
|
|
556
|
+
/* @__PURE__ */ jsx2(
|
|
557
|
+
"button",
|
|
558
|
+
{
|
|
559
|
+
type: "button",
|
|
560
|
+
className: "fillo-group-remove",
|
|
561
|
+
"aria-label": strings.groupRemoveLabel(item, n),
|
|
562
|
+
disabled: atFloor,
|
|
563
|
+
title: atFloor ? `At least ${Math.max(group.minInstances ?? 1, 0)} required` : void 0,
|
|
564
|
+
onClick: () => onRemove(index),
|
|
565
|
+
children: "\xD7"
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
] }),
|
|
569
|
+
scopedChildren.map((child) => /* @__PURE__ */ jsx2(BlockRenderer, { block: child, api: childApi }, child.id))
|
|
570
|
+
] });
|
|
571
|
+
}
|
|
572
|
+
function RepeatingGroup({ field, error, setValue, api, ids: providedIds }) {
|
|
573
|
+
const ids = useFilloFieldIds(field.id, providedIds);
|
|
574
|
+
const strings = useStrings();
|
|
575
|
+
const announce = useFilloAnnounce();
|
|
576
|
+
const group = field;
|
|
577
|
+
const item = group.itemLabel || group.label;
|
|
578
|
+
const liveApi = useContext3(FilloContext) ?? api;
|
|
579
|
+
const value = liveApi.data[field.id];
|
|
580
|
+
const storedInstances = Array.isArray(value) ? value : void 0;
|
|
581
|
+
const floor = Math.max(group.minInstances ?? 1, 0);
|
|
582
|
+
const renderedCount = Math.max(storedInstances?.length ?? 0, floor);
|
|
583
|
+
const atMax = renderedCount >= group.maxInstances;
|
|
584
|
+
const atFloor = renderedCount <= floor;
|
|
585
|
+
const instanceRefs = useRef3([]);
|
|
586
|
+
const addButtonRef = useRef3(null);
|
|
587
|
+
const pendingFocus = useRef3(null);
|
|
588
|
+
useEffect3(() => {
|
|
589
|
+
const pending = pendingFocus.current;
|
|
590
|
+
pendingFocus.current = null;
|
|
591
|
+
if (!pending) return;
|
|
592
|
+
if (pending.target === "add") {
|
|
593
|
+
addButtonRef.current?.focus();
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const card = instanceRefs.current[pending.index];
|
|
597
|
+
if (!card) return;
|
|
598
|
+
if (pending.target === "instance-card") {
|
|
599
|
+
card.focus();
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
(firstFieldControl(card) ?? card).focus();
|
|
603
|
+
}, [value]);
|
|
604
|
+
function patchInstance(index, childId, v) {
|
|
605
|
+
const instances = materializeInstances(value, renderedCount);
|
|
606
|
+
instances[index] = { ...instances[index] ?? {}, [childId]: v };
|
|
607
|
+
setValue(instances);
|
|
608
|
+
}
|
|
609
|
+
function handleAdd() {
|
|
610
|
+
if (atMax) return;
|
|
611
|
+
const instances = materializeInstances(value, renderedCount);
|
|
612
|
+
instances.push({});
|
|
613
|
+
const n = instances.length;
|
|
614
|
+
pendingFocus.current = { target: "instance-control", index: n - 1 };
|
|
615
|
+
setValue(instances);
|
|
616
|
+
announce(strings.groupInstanceAdded(item, n, n));
|
|
617
|
+
}
|
|
618
|
+
function handleRemove(index) {
|
|
619
|
+
if (atFloor) return;
|
|
620
|
+
const instances = materializeInstances(value, renderedCount);
|
|
621
|
+
instances.splice(index, 1);
|
|
622
|
+
pendingFocus.current = index > 0 ? { target: "instance-card", index: index - 1 } : { target: "add" };
|
|
623
|
+
setValue(instances);
|
|
624
|
+
announce(strings.groupInstanceRemoved(item, instances.length));
|
|
625
|
+
}
|
|
626
|
+
return /* @__PURE__ */ jsx2(FieldShell, { field: group, error, ids, children: /* @__PURE__ */ jsxs2("div", { className: "fillo-group", children: [
|
|
627
|
+
Array.from({ length: renderedCount }, (_, index) => /* @__PURE__ */ jsx2(
|
|
628
|
+
GroupInstance,
|
|
629
|
+
{
|
|
630
|
+
group,
|
|
631
|
+
index,
|
|
632
|
+
count: renderedCount,
|
|
633
|
+
item,
|
|
634
|
+
instanceValue: storedInstances?.[index] ?? EMPTY_INSTANCE,
|
|
635
|
+
api: liveApi,
|
|
636
|
+
atFloor,
|
|
637
|
+
onPatch: patchInstance,
|
|
638
|
+
onRemove: handleRemove,
|
|
639
|
+
cardRef: (el) => {
|
|
640
|
+
instanceRefs.current[index] = el;
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
index
|
|
644
|
+
)),
|
|
645
|
+
/* @__PURE__ */ jsx2(
|
|
646
|
+
"button",
|
|
647
|
+
{
|
|
648
|
+
ref: addButtonRef,
|
|
649
|
+
type: "button",
|
|
650
|
+
className: "fillo-group-add",
|
|
651
|
+
disabled: atMax,
|
|
652
|
+
"aria-disabled": atMax ? true : void 0,
|
|
653
|
+
title: atMax ? `Maximum ${group.maxInstances} reached` : void 0,
|
|
654
|
+
onClick: handleAdd,
|
|
655
|
+
children: group.addLabel || strings.groupAdd
|
|
656
|
+
}
|
|
657
|
+
)
|
|
658
|
+
] }) });
|
|
659
|
+
}
|
|
496
660
|
|
|
497
661
|
// src/phone.tsx
|
|
498
662
|
import {
|
|
@@ -507,8 +671,8 @@ import {
|
|
|
507
671
|
positionPhonePopover,
|
|
508
672
|
toE164
|
|
509
673
|
} from "@usefillo/core";
|
|
510
|
-
import { useEffect as
|
|
511
|
-
import { jsx as
|
|
674
|
+
import { useEffect as useEffect4, useLayoutEffect, useMemo as useMemo4, useRef as useRef4, useState as useState2 } from "react";
|
|
675
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
512
676
|
function localeCountry() {
|
|
513
677
|
if (typeof navigator === "undefined") return void 0;
|
|
514
678
|
const tag = navigator.languages?.[0] || navigator.language || "";
|
|
@@ -537,13 +701,13 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
537
701
|
const [country, setCountry] = useState2(
|
|
538
702
|
() => parsePhone(stored).country ?? countryByIso(schema.defaultCountry) ?? PHONE_COUNTRIES[0]
|
|
539
703
|
);
|
|
540
|
-
const touched =
|
|
541
|
-
|
|
704
|
+
const touched = useRef4(false);
|
|
705
|
+
useEffect4(() => {
|
|
542
706
|
if (touched.current || !stored) return;
|
|
543
707
|
const restoredCountry = parsePhone(stored).country;
|
|
544
708
|
if (restoredCountry) setCountry(restoredCountry);
|
|
545
709
|
}, [stored]);
|
|
546
|
-
|
|
710
|
+
useEffect4(() => {
|
|
547
711
|
if (touched.current) return;
|
|
548
712
|
if (parsePhone(stored).country || countryByIso(schema.defaultCountry)) return;
|
|
549
713
|
const guess = countryByTimeZone(browserTimeZone()) ?? countryByIso(localeCountry());
|
|
@@ -552,8 +716,8 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
552
716
|
const [pendingRaw, setPendingRaw] = useState2(null);
|
|
553
717
|
const national = nationalFor(stored, country);
|
|
554
718
|
const display = pendingRaw ?? formatNational(country, national);
|
|
555
|
-
const inputRef =
|
|
556
|
-
const caretDigits =
|
|
719
|
+
const inputRef = useRef4(null);
|
|
720
|
+
const caretDigits = useRef4(null);
|
|
557
721
|
useLayoutEffect(() => {
|
|
558
722
|
const el = inputRef.current;
|
|
559
723
|
if (!el || caretDigits.current == null) return;
|
|
@@ -600,15 +764,15 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
600
764
|
inputRef.current?.focus();
|
|
601
765
|
}
|
|
602
766
|
const describedBy = [field.description ? ids.descriptionId : null, error ? ids.errorId : null].filter(Boolean).join(" ") || void 0;
|
|
603
|
-
return /* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
767
|
+
return /* @__PURE__ */ jsxs3("div", { ...slots.wrapperProps(`fillo-field fillo-field--phone${error ? " fillo-field--error" : ""}`), children: [
|
|
768
|
+
/* @__PURE__ */ jsxs3("label", { className: slots.label, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: [
|
|
605
769
|
field.label,
|
|
606
|
-
!field.required && /* @__PURE__ */
|
|
770
|
+
!field.required && /* @__PURE__ */ jsx3("span", { className: "fillo-optional", children: strings.optional })
|
|
607
771
|
] }),
|
|
608
|
-
field.description && /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
772
|
+
field.description && /* @__PURE__ */ jsx3("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
773
|
+
/* @__PURE__ */ jsxs3("div", { className: "fillo-phone", children: [
|
|
774
|
+
/* @__PURE__ */ jsx3(CountrySelect, { country, onPick: pickCountry, labelledBy: ids.labelId }),
|
|
775
|
+
/* @__PURE__ */ jsx3(
|
|
612
776
|
"input",
|
|
613
777
|
{
|
|
614
778
|
ref: inputRef,
|
|
@@ -627,7 +791,7 @@ function PhoneField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
627
791
|
}
|
|
628
792
|
)
|
|
629
793
|
] }),
|
|
630
|
-
error && /* @__PURE__ */
|
|
794
|
+
error && /* @__PURE__ */ jsx3("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
631
795
|
] });
|
|
632
796
|
}
|
|
633
797
|
function CountrySelect({
|
|
@@ -641,13 +805,13 @@ function CountrySelect({
|
|
|
641
805
|
const [query, setQuery] = useState2("");
|
|
642
806
|
const [active, setActive] = useState2(0);
|
|
643
807
|
const [placement, setPlacement] = useState2("below");
|
|
644
|
-
const rootRef =
|
|
645
|
-
const triggerRef =
|
|
646
|
-
const popoverRef =
|
|
647
|
-
const searchRef =
|
|
648
|
-
const seedRef =
|
|
808
|
+
const rootRef = useRef4(null);
|
|
809
|
+
const triggerRef = useRef4(null);
|
|
810
|
+
const popoverRef = useRef4(null);
|
|
811
|
+
const searchRef = useRef4(null);
|
|
812
|
+
const seedRef = useRef4(null);
|
|
649
813
|
const listId = `${labelledBy}-countries`;
|
|
650
|
-
const matches =
|
|
814
|
+
const matches = useMemo4(() => {
|
|
651
815
|
const q = query.trim().toLowerCase();
|
|
652
816
|
if (!q) return PHONE_PICKER_COUNTRIES;
|
|
653
817
|
const qDigits = q.replace(/[^\d]/g, "");
|
|
@@ -655,7 +819,7 @@ function CountrySelect({
|
|
|
655
819
|
(c) => c.name.toLowerCase().includes(q) || c.iso2.toLowerCase() === q || qDigits.length > 0 && c.dialCode.startsWith(qDigits)
|
|
656
820
|
);
|
|
657
821
|
}, [query]);
|
|
658
|
-
|
|
822
|
+
useEffect4(() => {
|
|
659
823
|
if (!open) return;
|
|
660
824
|
const seed = seedRef.current ?? "";
|
|
661
825
|
seedRef.current = null;
|
|
@@ -664,7 +828,7 @@ function CountrySelect({
|
|
|
664
828
|
const id = requestAnimationFrame(() => searchRef.current?.focus());
|
|
665
829
|
return () => cancelAnimationFrame(id);
|
|
666
830
|
}, [open, country]);
|
|
667
|
-
|
|
831
|
+
useEffect4(() => {
|
|
668
832
|
if (!open) return;
|
|
669
833
|
const onDown = (e) => {
|
|
670
834
|
if (!rootRef.current?.contains(e.target)) setOpen(false);
|
|
@@ -683,12 +847,12 @@ function CountrySelect({
|
|
|
683
847
|
window.removeEventListener("scroll", update, true);
|
|
684
848
|
};
|
|
685
849
|
}, [open, matches.length]);
|
|
686
|
-
|
|
850
|
+
useEffect4(() => {
|
|
687
851
|
if (!open) return;
|
|
688
852
|
document.getElementById(`${listId}-opt-${active}`)?.scrollIntoView({ block: "nearest" });
|
|
689
853
|
}, [active, open, listId]);
|
|
690
854
|
const resultsAnnouncement = strings.phoneResultsCount(matches.length);
|
|
691
|
-
|
|
855
|
+
useEffect4(() => {
|
|
692
856
|
if (!open || !query.trim()) return;
|
|
693
857
|
const id = setTimeout(() => announce(resultsAnnouncement), 300);
|
|
694
858
|
return () => clearTimeout(id);
|
|
@@ -738,8 +902,8 @@ function CountrySelect({
|
|
|
738
902
|
if (!rootRef.current?.contains(document.activeElement)) setOpen(false);
|
|
739
903
|
});
|
|
740
904
|
}
|
|
741
|
-
return /* @__PURE__ */
|
|
742
|
-
/* @__PURE__ */
|
|
905
|
+
return /* @__PURE__ */ jsxs3("div", { className: "fillo-phone-country", ref: rootRef, onBlur: onCompositeBlur, children: [
|
|
906
|
+
/* @__PURE__ */ jsxs3(
|
|
743
907
|
"button",
|
|
744
908
|
{
|
|
745
909
|
ref: triggerRef,
|
|
@@ -752,17 +916,17 @@ function CountrySelect({
|
|
|
752
916
|
onClick: () => setOpen((o) => !o),
|
|
753
917
|
onKeyDown: onTriggerKeyDown,
|
|
754
918
|
children: [
|
|
755
|
-
/* @__PURE__ */
|
|
756
|
-
/* @__PURE__ */
|
|
919
|
+
/* @__PURE__ */ jsx3("span", { className: "fillo-phone-flag-emoji", "aria-hidden": "true", children: flagEmoji(country.iso2) }),
|
|
920
|
+
/* @__PURE__ */ jsxs3("span", { className: "fillo-phone-dial", children: [
|
|
757
921
|
"+",
|
|
758
922
|
country.dialCode
|
|
759
923
|
] }),
|
|
760
|
-
/* @__PURE__ */
|
|
924
|
+
/* @__PURE__ */ jsx3("span", { className: "fillo-phone-caret", "aria-hidden": "true", children: "\u25BE" })
|
|
761
925
|
]
|
|
762
926
|
}
|
|
763
927
|
),
|
|
764
|
-
open && /* @__PURE__ */
|
|
765
|
-
/* @__PURE__ */
|
|
928
|
+
open && /* @__PURE__ */ jsxs3("div", { ref: popoverRef, className: `fillo-phone-popover fillo-phone-popover--${placement}`, children: [
|
|
929
|
+
/* @__PURE__ */ jsx3(
|
|
766
930
|
"input",
|
|
767
931
|
{
|
|
768
932
|
ref: searchRef,
|
|
@@ -783,8 +947,8 @@ function CountrySelect({
|
|
|
783
947
|
onKeyDown: onSearchKey
|
|
784
948
|
}
|
|
785
949
|
),
|
|
786
|
-
/* @__PURE__ */
|
|
787
|
-
matches.map((c, i) => /* @__PURE__ */
|
|
950
|
+
/* @__PURE__ */ jsxs3("ul", { className: "fillo-phone-list", role: "listbox", id: listId, "aria-label": "Country", children: [
|
|
951
|
+
matches.map((c, i) => /* @__PURE__ */ jsxs3(
|
|
788
952
|
"li",
|
|
789
953
|
{
|
|
790
954
|
id: `${listId}-opt-${i}`,
|
|
@@ -797,9 +961,9 @@ function CountrySelect({
|
|
|
797
961
|
choose(c);
|
|
798
962
|
},
|
|
799
963
|
children: [
|
|
800
|
-
/* @__PURE__ */
|
|
801
|
-
/* @__PURE__ */
|
|
802
|
-
/* @__PURE__ */
|
|
964
|
+
/* @__PURE__ */ jsx3("span", { className: "fillo-phone-flag-emoji", "aria-hidden": "true", children: flagEmoji(c.iso2) }),
|
|
965
|
+
/* @__PURE__ */ jsx3("span", { className: "fillo-phone-option-name", children: c.name }),
|
|
966
|
+
/* @__PURE__ */ jsxs3("span", { className: "fillo-phone-option-dial", children: [
|
|
803
967
|
"+",
|
|
804
968
|
c.dialCode
|
|
805
969
|
] })
|
|
@@ -807,26 +971,26 @@ function CountrySelect({
|
|
|
807
971
|
},
|
|
808
972
|
c.iso2
|
|
809
973
|
)),
|
|
810
|
-
matches.length === 0 && /* @__PURE__ */
|
|
974
|
+
matches.length === 0 && /* @__PURE__ */ jsx3("li", { className: "fillo-phone-empty", role: "option", "aria-disabled": "true", children: "No matches" })
|
|
811
975
|
] })
|
|
812
976
|
] })
|
|
813
977
|
] });
|
|
814
978
|
}
|
|
815
979
|
|
|
816
980
|
// src/signature.tsx
|
|
817
|
-
import { useEffect as
|
|
818
|
-
import { jsx as
|
|
981
|
+
import { useEffect as useEffect5, useRef as useRef5, useState as useState3 } from "react";
|
|
982
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
819
983
|
function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
820
984
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
821
985
|
const slots = useFieldSlots(field, error);
|
|
822
986
|
const strings = useStrings();
|
|
823
987
|
const typedInputId = `${ids.inputId}-typed`;
|
|
824
|
-
const canvasRef =
|
|
825
|
-
const typedInputRef =
|
|
826
|
-
const drawing =
|
|
988
|
+
const canvasRef = useRef5(null);
|
|
989
|
+
const typedInputRef = useRef5(null);
|
|
990
|
+
const drawing = useRef5(false);
|
|
827
991
|
const [hasInk, setHasInk] = useState3(Boolean(value));
|
|
828
992
|
const [typedName, setTypedName] = useState3("");
|
|
829
|
-
|
|
993
|
+
useEffect5(() => {
|
|
830
994
|
const canvas = canvasRef.current;
|
|
831
995
|
if (!canvas) return;
|
|
832
996
|
const scale = window.devicePixelRatio || 1;
|
|
@@ -841,7 +1005,7 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
841
1005
|
ctx.lineJoin = "round";
|
|
842
1006
|
ctx.strokeStyle = getComputedStyle(canvas).color;
|
|
843
1007
|
}, []);
|
|
844
|
-
|
|
1008
|
+
useEffect5(() => {
|
|
845
1009
|
const canvas = canvasRef.current;
|
|
846
1010
|
const ctx = canvas?.getContext("2d");
|
|
847
1011
|
if (!canvas || !ctx) return;
|
|
@@ -922,21 +1086,21 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
922
1086
|
typedInputRef.current?.focus();
|
|
923
1087
|
}
|
|
924
1088
|
const describedBy = [field.description ? ids.descriptionId : null, error ? ids.errorId : null].filter(Boolean).join(" ") || void 0;
|
|
925
|
-
return /* @__PURE__ */
|
|
926
|
-
/* @__PURE__ */
|
|
1089
|
+
return /* @__PURE__ */ jsxs4("div", { ...slots.wrapperProps(`fillo-field fillo-field--signature${error ? " fillo-field--error" : ""}`), children: [
|
|
1090
|
+
/* @__PURE__ */ jsxs4("span", { className: slots.label, "data-fillo": "label", id: ids.labelId, children: [
|
|
927
1091
|
field.label,
|
|
928
|
-
!field.required && /* @__PURE__ */
|
|
1092
|
+
!field.required && /* @__PURE__ */ jsx4("span", { className: "fillo-optional", children: strings.optional })
|
|
929
1093
|
] }),
|
|
930
|
-
field.description && /* @__PURE__ */
|
|
931
|
-
/* @__PURE__ */
|
|
1094
|
+
field.description && /* @__PURE__ */ jsx4("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1095
|
+
/* @__PURE__ */ jsxs4(
|
|
932
1096
|
"div",
|
|
933
1097
|
{
|
|
934
1098
|
role: "group",
|
|
935
1099
|
"aria-labelledby": ids.labelId,
|
|
936
1100
|
"aria-describedby": describedBy,
|
|
937
1101
|
children: [
|
|
938
|
-
/* @__PURE__ */
|
|
939
|
-
/* @__PURE__ */
|
|
1102
|
+
/* @__PURE__ */ jsxs4("div", { className: slots.control("fillo-signature"), "data-fillo": "control", children: [
|
|
1103
|
+
/* @__PURE__ */ jsx4(
|
|
940
1104
|
"canvas",
|
|
941
1105
|
{
|
|
942
1106
|
ref: canvasRef,
|
|
@@ -950,12 +1114,12 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
950
1114
|
onPointerLeave: end
|
|
951
1115
|
}
|
|
952
1116
|
),
|
|
953
|
-
hasInk && /* @__PURE__ */
|
|
954
|
-
!hasInk && /* @__PURE__ */
|
|
1117
|
+
hasInk && /* @__PURE__ */ jsx4("button", { type: "button", className: "fillo-signature-clear", onClick: clear, children: "Clear" }),
|
|
1118
|
+
!hasInk && /* @__PURE__ */ jsx4("span", { className: "fillo-signature-hint", "aria-hidden": "true", children: "Sign here" })
|
|
955
1119
|
] }),
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
958
|
-
/* @__PURE__ */
|
|
1120
|
+
/* @__PURE__ */ jsxs4("div", { className: "fillo-signature-type", children: [
|
|
1121
|
+
/* @__PURE__ */ jsx4("label", { className: "fillo-signature-type-label", htmlFor: typedInputId, children: "Or type your full name to sign" }),
|
|
1122
|
+
/* @__PURE__ */ jsx4(
|
|
959
1123
|
"input",
|
|
960
1124
|
{
|
|
961
1125
|
id: typedInputId,
|
|
@@ -978,13 +1142,13 @@ function SignatureField({ field, value, error, setValue, ids: providedIds }) {
|
|
|
978
1142
|
]
|
|
979
1143
|
}
|
|
980
1144
|
),
|
|
981
|
-
error && /* @__PURE__ */
|
|
1145
|
+
error && /* @__PURE__ */ jsx4("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
982
1146
|
] });
|
|
983
1147
|
}
|
|
984
1148
|
|
|
985
1149
|
// src/upload.tsx
|
|
986
|
-
import { useEffect as
|
|
987
|
-
import { Fragment as Fragment2, jsx as
|
|
1150
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState4 } from "react";
|
|
1151
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
988
1152
|
function uploadStatus(inFlight, doneCount, strings) {
|
|
989
1153
|
const failed = inFlight.filter((f) => f.error).length;
|
|
990
1154
|
const active = inFlight.length - failed;
|
|
@@ -1010,7 +1174,7 @@ function uploadFailureMessage(error, strings) {
|
|
|
1010
1174
|
}
|
|
1011
1175
|
function FileStateIcon({ state }) {
|
|
1012
1176
|
if (state === "done") {
|
|
1013
|
-
return /* @__PURE__ */
|
|
1177
|
+
return /* @__PURE__ */ jsx5("span", { className: "fillo-file-state fillo-file-state--done", "aria-hidden": "true", children: /* @__PURE__ */ jsxs5(
|
|
1014
1178
|
"svg",
|
|
1015
1179
|
{
|
|
1016
1180
|
className: "fillo-file-state-icon",
|
|
@@ -1021,14 +1185,14 @@ function FileStateIcon({ state }) {
|
|
|
1021
1185
|
"aria-hidden": "true",
|
|
1022
1186
|
focusable: "false",
|
|
1023
1187
|
children: [
|
|
1024
|
-
/* @__PURE__ */
|
|
1025
|
-
/* @__PURE__ */
|
|
1188
|
+
/* @__PURE__ */ jsx5("path", { d: "M3.75 12a8.25 8.25 0 1 0 16.5 0 8.25 8.25 0 1 0-16.5 0" }),
|
|
1189
|
+
/* @__PURE__ */ jsx5("path", { d: "m8.5 12 2.25 2.25 4.75-5" })
|
|
1026
1190
|
]
|
|
1027
1191
|
}
|
|
1028
1192
|
) });
|
|
1029
1193
|
}
|
|
1030
1194
|
if (state === "failed") {
|
|
1031
|
-
return /* @__PURE__ */
|
|
1195
|
+
return /* @__PURE__ */ jsx5("span", { className: "fillo-file-state fillo-file-state--failed", "aria-hidden": "true", children: /* @__PURE__ */ jsxs5(
|
|
1032
1196
|
"svg",
|
|
1033
1197
|
{
|
|
1034
1198
|
className: "fillo-file-state-icon",
|
|
@@ -1039,14 +1203,14 @@ function FileStateIcon({ state }) {
|
|
|
1039
1203
|
"aria-hidden": "true",
|
|
1040
1204
|
focusable: "false",
|
|
1041
1205
|
children: [
|
|
1042
|
-
/* @__PURE__ */
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
/* @__PURE__ */
|
|
1206
|
+
/* @__PURE__ */ jsx5("path", { d: "M3.75 12a8.25 8.25 0 1 0 16.5 0 8.25 8.25 0 1 0-16.5 0" }),
|
|
1207
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 7.75v5.5" }),
|
|
1208
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 16.5h.01" })
|
|
1045
1209
|
]
|
|
1046
1210
|
}
|
|
1047
1211
|
) });
|
|
1048
1212
|
}
|
|
1049
|
-
return /* @__PURE__ */
|
|
1213
|
+
return /* @__PURE__ */ jsx5("span", { className: "fillo-file-state fillo-file-state--uploading", "aria-hidden": "true", children: /* @__PURE__ */ jsxs5(
|
|
1050
1214
|
"svg",
|
|
1051
1215
|
{
|
|
1052
1216
|
className: "fillo-file-state-icon",
|
|
@@ -1057,14 +1221,14 @@ function FileStateIcon({ state }) {
|
|
|
1057
1221
|
"aria-hidden": "true",
|
|
1058
1222
|
focusable: "false",
|
|
1059
1223
|
children: [
|
|
1060
|
-
/* @__PURE__ */
|
|
1061
|
-
/* @__PURE__ */
|
|
1224
|
+
/* @__PURE__ */ jsx5("path", { d: "M7.25 3.75h6.5l3 3v13.5h-9.5z" }),
|
|
1225
|
+
/* @__PURE__ */ jsx5("path", { d: "M13.75 3.75v3h3" })
|
|
1062
1226
|
]
|
|
1063
1227
|
}
|
|
1064
1228
|
) });
|
|
1065
1229
|
}
|
|
1066
1230
|
function CloseIcon() {
|
|
1067
|
-
return /* @__PURE__ */
|
|
1231
|
+
return /* @__PURE__ */ jsx5(
|
|
1068
1232
|
"svg",
|
|
1069
1233
|
{
|
|
1070
1234
|
className: "fillo-file-action-icon",
|
|
@@ -1074,7 +1238,7 @@ function CloseIcon() {
|
|
|
1074
1238
|
fill: "none",
|
|
1075
1239
|
"aria-hidden": "true",
|
|
1076
1240
|
focusable: "false",
|
|
1077
|
-
children: /* @__PURE__ */
|
|
1241
|
+
children: /* @__PURE__ */ jsx5("path", { d: "m7 7 10 10M17 7 7 17" })
|
|
1078
1242
|
}
|
|
1079
1243
|
);
|
|
1080
1244
|
}
|
|
@@ -1091,15 +1255,15 @@ function FileUploadField({
|
|
|
1091
1255
|
const strings = useStrings();
|
|
1092
1256
|
const chrome = useFilloChrome();
|
|
1093
1257
|
const schema = field;
|
|
1094
|
-
const inputRef =
|
|
1258
|
+
const inputRef = useRef6(null);
|
|
1095
1259
|
const [inFlight, setInFlight] = useState4([]);
|
|
1096
1260
|
const [dragOver, setDragOver] = useState4(false);
|
|
1097
|
-
const mountedRef =
|
|
1098
|
-
const controllers =
|
|
1099
|
-
const inFlightCount =
|
|
1261
|
+
const mountedRef = useRef6(true);
|
|
1262
|
+
const controllers = useRef6(/* @__PURE__ */ new Map());
|
|
1263
|
+
const inFlightCount = useRef6(0);
|
|
1100
1264
|
const setUploading = api.setUploading;
|
|
1101
1265
|
const fieldId = field.id;
|
|
1102
|
-
|
|
1266
|
+
useEffect6(() => {
|
|
1103
1267
|
mountedRef.current = true;
|
|
1104
1268
|
return () => {
|
|
1105
1269
|
mountedRef.current = false;
|
|
@@ -1108,7 +1272,7 @@ function FileUploadField({
|
|
|
1108
1272
|
};
|
|
1109
1273
|
}, [fieldId, setUploading]);
|
|
1110
1274
|
const files = Array.isArray(value) ? value : [];
|
|
1111
|
-
const filesRef =
|
|
1275
|
+
const filesRef = useRef6(files);
|
|
1112
1276
|
filesRef.current = files;
|
|
1113
1277
|
const maxFiles = schema.maxFiles ?? 1;
|
|
1114
1278
|
const configuredMaxMb = schema.maxFileSizeMb ?? 500;
|
|
@@ -1185,19 +1349,19 @@ function FileUploadField({
|
|
|
1185
1349
|
setValue(next);
|
|
1186
1350
|
}
|
|
1187
1351
|
const describedBy = [field.description ? ids.descriptionId : null, error ? ids.errorId : null].filter(Boolean).join(" ") || void 0;
|
|
1188
|
-
return /* @__PURE__ */
|
|
1352
|
+
return /* @__PURE__ */ jsxs5(
|
|
1189
1353
|
"div",
|
|
1190
1354
|
{
|
|
1191
1355
|
...slots.wrapperProps(
|
|
1192
1356
|
`fillo-field fillo-field--file_upload${error ? " fillo-field--error" : ""}`
|
|
1193
1357
|
),
|
|
1194
1358
|
children: [
|
|
1195
|
-
/* @__PURE__ */
|
|
1359
|
+
/* @__PURE__ */ jsxs5("label", { className: slots.label, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: [
|
|
1196
1360
|
field.label,
|
|
1197
|
-
!field.required && /* @__PURE__ */
|
|
1361
|
+
!field.required && /* @__PURE__ */ jsx5("span", { className: "fillo-optional", children: strings.optional })
|
|
1198
1362
|
] }),
|
|
1199
|
-
field.description && /* @__PURE__ */
|
|
1200
|
-
remaining > 0 && /* @__PURE__ */
|
|
1363
|
+
field.description && /* @__PURE__ */ jsx5("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1364
|
+
remaining > 0 && /* @__PURE__ */ jsxs5(
|
|
1201
1365
|
"div",
|
|
1202
1366
|
{
|
|
1203
1367
|
"data-fillo": "control",
|
|
@@ -1229,7 +1393,7 @@ function FileUploadField({
|
|
|
1229
1393
|
}
|
|
1230
1394
|
},
|
|
1231
1395
|
children: [
|
|
1232
|
-
/* @__PURE__ */
|
|
1396
|
+
/* @__PURE__ */ jsx5(
|
|
1233
1397
|
"input",
|
|
1234
1398
|
{
|
|
1235
1399
|
ref: inputRef,
|
|
@@ -1242,20 +1406,20 @@ function FileUploadField({
|
|
|
1242
1406
|
onChange: (e) => canUpload && handleFiles(e.target.files)
|
|
1243
1407
|
}
|
|
1244
1408
|
),
|
|
1245
|
-
canUpload ? /* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
] }) : storageBlocked && chrome?.devChrome ? /* @__PURE__ */
|
|
1409
|
+
canUpload ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1410
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-dropzone-title", children: strings.dropzoneTitle(maxFiles > 1) }),
|
|
1411
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-dropzone-hint", children: strings.dropzoneHint(maxMb) })
|
|
1412
|
+
] }) : storageBlocked && chrome?.devChrome ? /* @__PURE__ */ jsxs5("span", { className: "fillo-dropzone-hint", children: [
|
|
1249
1413
|
"Connect file storage to enable uploads",
|
|
1250
|
-
storageUrl && /* @__PURE__ */
|
|
1414
|
+
storageUrl && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1251
1415
|
" \u2014 ",
|
|
1252
|
-
/* @__PURE__ */
|
|
1416
|
+
/* @__PURE__ */ jsx5("a", { href: storageUrl, target: "_blank", rel: "noopener noreferrer", children: storageUrl })
|
|
1253
1417
|
] })
|
|
1254
|
-
] }) : /* @__PURE__ */
|
|
1418
|
+
] }) : /* @__PURE__ */ jsx5("span", { className: "fillo-dropzone-hint", children: renderOnly ? strings.uploadsRenderOnly : storageBlocked ? strings.uploadsUnavailable : strings.uploadsDisabled })
|
|
1255
1419
|
]
|
|
1256
1420
|
}
|
|
1257
1421
|
),
|
|
1258
|
-
/* @__PURE__ */
|
|
1422
|
+
/* @__PURE__ */ jsx5(
|
|
1259
1423
|
"div",
|
|
1260
1424
|
{
|
|
1261
1425
|
role: "status",
|
|
@@ -1265,33 +1429,33 @@ function FileUploadField({
|
|
|
1265
1429
|
children: uploadStatus(inFlight, files.length, strings)
|
|
1266
1430
|
}
|
|
1267
1431
|
),
|
|
1268
|
-
(inFlight.length > 0 || files.length > 0) && /* @__PURE__ */
|
|
1269
|
-
files.map((f) => /* @__PURE__ */
|
|
1270
|
-
/* @__PURE__ */
|
|
1271
|
-
/* @__PURE__ */
|
|
1272
|
-
/* @__PURE__ */
|
|
1273
|
-
/* @__PURE__ */
|
|
1432
|
+
(inFlight.length > 0 || files.length > 0) && /* @__PURE__ */ jsxs5("ul", { className: "fillo-files", children: [
|
|
1433
|
+
files.map((f) => /* @__PURE__ */ jsxs5("li", { className: "fillo-file fillo-file--done", children: [
|
|
1434
|
+
/* @__PURE__ */ jsx5(FileStateIcon, { state: "done" }),
|
|
1435
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-file-content", children: [
|
|
1436
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-name", children: f.name }),
|
|
1437
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-meta", children: strings.uploadedFile(formatBytes(f.size)) })
|
|
1274
1438
|
] }),
|
|
1275
|
-
/* @__PURE__ */
|
|
1439
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-actions", children: /* @__PURE__ */ jsx5(
|
|
1276
1440
|
"button",
|
|
1277
1441
|
{
|
|
1278
1442
|
type: "button",
|
|
1279
1443
|
className: "fillo-file-remove",
|
|
1280
1444
|
"aria-label": `${strings.uploadRemove} ${f.name}`,
|
|
1281
1445
|
onClick: () => removeFile(f.fileId),
|
|
1282
|
-
children: /* @__PURE__ */
|
|
1446
|
+
children: /* @__PURE__ */ jsx5(CloseIcon, {})
|
|
1283
1447
|
}
|
|
1284
1448
|
) })
|
|
1285
1449
|
] }, f.fileId)),
|
|
1286
|
-
inFlight.map((f) => /* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
f.error ? /* @__PURE__ */
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1450
|
+
inFlight.map((f) => /* @__PURE__ */ jsxs5("li", { className: `fillo-file${f.error ? " fillo-file--failed" : ""}`, children: [
|
|
1451
|
+
/* @__PURE__ */ jsx5(FileStateIcon, { state: f.error ? "failed" : "uploading" }),
|
|
1452
|
+
f.error ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1453
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-file-content", children: [
|
|
1454
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-name", children: f.name }),
|
|
1455
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-error", role: "alert", children: f.error })
|
|
1292
1456
|
] }),
|
|
1293
|
-
/* @__PURE__ */
|
|
1294
|
-
f.file && !f.tooLarge && remaining > 0 && /* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-file-actions", children: [
|
|
1458
|
+
f.file && !f.tooLarge && remaining > 0 && /* @__PURE__ */ jsx5(
|
|
1295
1459
|
"button",
|
|
1296
1460
|
{
|
|
1297
1461
|
type: "button",
|
|
@@ -1306,33 +1470,33 @@ function FileUploadField({
|
|
|
1306
1470
|
children: strings.uploadRetry
|
|
1307
1471
|
}
|
|
1308
1472
|
),
|
|
1309
|
-
/* @__PURE__ */
|
|
1473
|
+
/* @__PURE__ */ jsx5(
|
|
1310
1474
|
"button",
|
|
1311
1475
|
{
|
|
1312
1476
|
type: "button",
|
|
1313
1477
|
className: "fillo-file-remove",
|
|
1314
1478
|
"aria-label": `${strings.uploadDismiss} ${f.name}`,
|
|
1315
1479
|
onClick: () => setInFlight((prev) => prev.filter((x) => x.key !== f.key)),
|
|
1316
|
-
children: /* @__PURE__ */
|
|
1480
|
+
children: /* @__PURE__ */ jsx5(CloseIcon, {})
|
|
1317
1481
|
}
|
|
1318
1482
|
)
|
|
1319
1483
|
] })
|
|
1320
|
-
] }) : /* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1484
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1485
|
+
/* @__PURE__ */ jsxs5("span", { className: "fillo-file-content", children: [
|
|
1486
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-name", children: f.name }),
|
|
1487
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-meta", children: strings.uploadingFile(Math.round(f.fraction * 100), formatBytes(f.size)) })
|
|
1324
1488
|
] }),
|
|
1325
|
-
/* @__PURE__ */
|
|
1489
|
+
/* @__PURE__ */ jsx5("span", { className: "fillo-file-actions", children: /* @__PURE__ */ jsx5(
|
|
1326
1490
|
"button",
|
|
1327
1491
|
{
|
|
1328
1492
|
type: "button",
|
|
1329
1493
|
className: "fillo-file-remove",
|
|
1330
1494
|
"aria-label": `${strings.uploadCancel} ${f.name}`,
|
|
1331
1495
|
onClick: () => cancelUpload(f.key),
|
|
1332
|
-
children: /* @__PURE__ */
|
|
1496
|
+
children: /* @__PURE__ */ jsx5(CloseIcon, {})
|
|
1333
1497
|
}
|
|
1334
1498
|
) }),
|
|
1335
|
-
/* @__PURE__ */
|
|
1499
|
+
/* @__PURE__ */ jsx5(
|
|
1336
1500
|
"span",
|
|
1337
1501
|
{
|
|
1338
1502
|
className: "fillo-progress",
|
|
@@ -1341,7 +1505,7 @@ function FileUploadField({
|
|
|
1341
1505
|
"aria-valuemin": 0,
|
|
1342
1506
|
"aria-valuemax": 100,
|
|
1343
1507
|
"aria-valuenow": Math.round(f.fraction * 100),
|
|
1344
|
-
children: /* @__PURE__ */
|
|
1508
|
+
children: /* @__PURE__ */ jsx5(
|
|
1345
1509
|
"span",
|
|
1346
1510
|
{
|
|
1347
1511
|
className: "fillo-progress-bar",
|
|
@@ -1353,14 +1517,14 @@ function FileUploadField({
|
|
|
1353
1517
|
] })
|
|
1354
1518
|
] }, f.key))
|
|
1355
1519
|
] }),
|
|
1356
|
-
error && /* @__PURE__ */
|
|
1520
|
+
error && /* @__PURE__ */ jsx5("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1357
1521
|
]
|
|
1358
1522
|
}
|
|
1359
1523
|
);
|
|
1360
1524
|
}
|
|
1361
1525
|
|
|
1362
1526
|
// src/fields.tsx
|
|
1363
|
-
import { jsx as
|
|
1527
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1364
1528
|
function fieldAria(field, error, ids, opts = {}) {
|
|
1365
1529
|
const describedBy = [
|
|
1366
1530
|
field.description ? ids.descriptionId : null,
|
|
@@ -1405,7 +1569,7 @@ function FieldShell({
|
|
|
1405
1569
|
const descriptionCls = useSlotClass("fillo-description", { slot: "fieldDescription", ...state });
|
|
1406
1570
|
const errorCls = useSlotClass("fillo-error", { slot: "error", ...state });
|
|
1407
1571
|
const strings = useStrings();
|
|
1408
|
-
return /* @__PURE__ */
|
|
1572
|
+
return /* @__PURE__ */ jsxs6(
|
|
1409
1573
|
"div",
|
|
1410
1574
|
{
|
|
1411
1575
|
className: fieldCls,
|
|
@@ -1415,13 +1579,13 @@ function FieldShell({
|
|
|
1415
1579
|
"data-invalid": error ? "" : void 0,
|
|
1416
1580
|
"data-required": field.required ? "" : void 0,
|
|
1417
1581
|
children: [
|
|
1418
|
-
/* @__PURE__ */
|
|
1582
|
+
/* @__PURE__ */ jsxs6("label", { className: labelCls, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: [
|
|
1419
1583
|
field.label,
|
|
1420
|
-
!field.required && /* @__PURE__ */
|
|
1584
|
+
!field.required && !(field.kind === "repeating_group" && (field.minInstances ?? 1) > 0) && /* @__PURE__ */ jsx6("span", { className: "fillo-optional", children: strings.optional })
|
|
1421
1585
|
] }),
|
|
1422
|
-
field.description && /* @__PURE__ */
|
|
1586
|
+
field.description && /* @__PURE__ */ jsx6("p", { className: descriptionCls, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
1423
1587
|
children,
|
|
1424
|
-
error && /* @__PURE__ */
|
|
1588
|
+
error && /* @__PURE__ */ jsx6("p", { className: errorCls, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1425
1589
|
]
|
|
1426
1590
|
}
|
|
1427
1591
|
);
|
|
@@ -1431,7 +1595,7 @@ function TextInput({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1431
1595
|
const type = field.kind === "email" ? "email" : field.kind === "url" ? "url" : field.kind === "number" ? "number" : field.kind === "date" ? "date" : "text";
|
|
1432
1596
|
const autoComplete = field.kind === "email" ? "email" : field.kind === "url" ? "url" : void 0;
|
|
1433
1597
|
const control = useControl("fillo-input", field, error);
|
|
1434
|
-
return /* @__PURE__ */
|
|
1598
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx6(
|
|
1435
1599
|
"input",
|
|
1436
1600
|
{
|
|
1437
1601
|
id: ids.inputId,
|
|
@@ -1452,8 +1616,8 @@ function NumberInput({ field, value, error, setValue, api, ids: providedIds }) {
|
|
|
1452
1616
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1453
1617
|
const control = useControl("fillo-input", field, error);
|
|
1454
1618
|
const [draft, setDraft] = useState5(null);
|
|
1455
|
-
const inputRef =
|
|
1456
|
-
const pendingCaret =
|
|
1619
|
+
const inputRef = useRef7(null);
|
|
1620
|
+
const pendingCaret = useRef7(null);
|
|
1457
1621
|
const [, setRevertTick] = useState5(0);
|
|
1458
1622
|
useLayoutEffect2(() => {
|
|
1459
1623
|
if (pendingCaret.current === null) return;
|
|
@@ -1466,7 +1630,7 @@ function NumberInput({ field, value, error, setValue, api, ids: providedIds }) {
|
|
|
1466
1630
|
const locale = localeForNotation(num.notation);
|
|
1467
1631
|
const hasAffix = Boolean(num.prefix) || Boolean(num.suffix);
|
|
1468
1632
|
if (!grouped && !hasAffix) {
|
|
1469
|
-
return /* @__PURE__ */
|
|
1633
|
+
return /* @__PURE__ */ jsx6(
|
|
1470
1634
|
TextInput,
|
|
1471
1635
|
{
|
|
1472
1636
|
field,
|
|
@@ -1481,7 +1645,7 @@ function NumberInput({ field, value, error, setValue, api, ids: providedIds }) {
|
|
|
1481
1645
|
const stored = typeof value === "string" || typeof value === "number" ? String(value) : "";
|
|
1482
1646
|
const n = Number(stored);
|
|
1483
1647
|
const display = draft !== null ? draft : grouped && stored !== "" && Number.isFinite(n) ? formatGroupedNumber(n, { locale, decimals: num.decimals }) : stored;
|
|
1484
|
-
const input = /* @__PURE__ */
|
|
1648
|
+
const input = /* @__PURE__ */ jsx6(
|
|
1485
1649
|
"input",
|
|
1486
1650
|
{
|
|
1487
1651
|
ref: inputRef,
|
|
@@ -1508,16 +1672,16 @@ function NumberInput({ field, value, error, setValue, api, ids: providedIds }) {
|
|
|
1508
1672
|
...fieldAria(field, error, ids)
|
|
1509
1673
|
}
|
|
1510
1674
|
);
|
|
1511
|
-
return /* @__PURE__ */
|
|
1512
|
-
num.prefix && /* @__PURE__ */
|
|
1675
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: hasAffix ? /* @__PURE__ */ jsxs6("div", { className: "fillo-number", children: [
|
|
1676
|
+
num.prefix && /* @__PURE__ */ jsx6("span", { className: "fillo-number-prefix", children: num.prefix }),
|
|
1513
1677
|
input,
|
|
1514
|
-
num.suffix && /* @__PURE__ */
|
|
1678
|
+
num.suffix && /* @__PURE__ */ jsx6("span", { className: "fillo-number-suffix", children: num.suffix })
|
|
1515
1679
|
] }) : input });
|
|
1516
1680
|
}
|
|
1517
1681
|
function LongText({ field, value, error, setValue, ids: providedIds }) {
|
|
1518
1682
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
1519
1683
|
const control = useControl("fillo-input fillo-textarea", field, error);
|
|
1520
|
-
return /* @__PURE__ */
|
|
1684
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx6(
|
|
1521
1685
|
"textarea",
|
|
1522
1686
|
{
|
|
1523
1687
|
id: ids.inputId,
|
|
@@ -1534,7 +1698,7 @@ function LongText({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1534
1698
|
function useDisplayOptions(choice) {
|
|
1535
1699
|
const idsKey = choice.options.map((o) => o.id).join("\0");
|
|
1536
1700
|
const [order, setOrder] = useState5(null);
|
|
1537
|
-
|
|
1701
|
+
useEffect7(() => {
|
|
1538
1702
|
if (!choice.shuffleOptions) return;
|
|
1539
1703
|
const ids = idsKey === "" ? [] : idsKey.split("\0");
|
|
1540
1704
|
for (let i = ids.length - 1; i > 0; i--) {
|
|
@@ -1554,7 +1718,7 @@ var OPTION_ICON_PATHS = {
|
|
|
1554
1718
|
};
|
|
1555
1719
|
function ChoiceIcon({ icon }) {
|
|
1556
1720
|
if (!icon) return null;
|
|
1557
|
-
return /* @__PURE__ */
|
|
1721
|
+
return /* @__PURE__ */ jsx6(
|
|
1558
1722
|
"svg",
|
|
1559
1723
|
{
|
|
1560
1724
|
className: "fillo-option-icon",
|
|
@@ -1565,7 +1729,7 @@ function ChoiceIcon({ icon }) {
|
|
|
1565
1729
|
strokeLinecap: "round",
|
|
1566
1730
|
strokeLinejoin: "round",
|
|
1567
1731
|
"aria-hidden": "true",
|
|
1568
|
-
children: /* @__PURE__ */
|
|
1732
|
+
children: /* @__PURE__ */ jsx6("path", { d: OPTION_ICON_PATHS[icon] })
|
|
1569
1733
|
}
|
|
1570
1734
|
);
|
|
1571
1735
|
}
|
|
@@ -1579,7 +1743,7 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1579
1743
|
const isOtherValue = typeof value === "string" && value !== "" && !choice.options.some((o) => o.id === value);
|
|
1580
1744
|
const [otherOn, setOtherOn] = useState5(isOtherValue);
|
|
1581
1745
|
const otherActive = isOtherValue || value === "" && otherOn;
|
|
1582
|
-
return /* @__PURE__ */
|
|
1746
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsxs6(
|
|
1583
1747
|
"div",
|
|
1584
1748
|
{
|
|
1585
1749
|
className: slotClass2("fillo-options", appearance, { slot: "options", kind: field.kind, fieldId: field.id }),
|
|
@@ -1588,7 +1752,7 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1588
1752
|
"aria-labelledby": ids.labelId,
|
|
1589
1753
|
...fieldAria(field, error, ids),
|
|
1590
1754
|
children: [
|
|
1591
|
-
options.map((opt) => /* @__PURE__ */
|
|
1755
|
+
options.map((opt) => /* @__PURE__ */ jsxs6(
|
|
1592
1756
|
"label",
|
|
1593
1757
|
{
|
|
1594
1758
|
"data-option": opt.id,
|
|
@@ -1600,7 +1764,7 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1600
1764
|
value === opt.id
|
|
1601
1765
|
),
|
|
1602
1766
|
children: [
|
|
1603
|
-
/* @__PURE__ */
|
|
1767
|
+
/* @__PURE__ */ jsx6(
|
|
1604
1768
|
"input",
|
|
1605
1769
|
{
|
|
1606
1770
|
type: "radio",
|
|
@@ -1613,11 +1777,11 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1613
1777
|
}
|
|
1614
1778
|
}
|
|
1615
1779
|
),
|
|
1616
|
-
/* @__PURE__ */
|
|
1780
|
+
/* @__PURE__ */ jsx6(ChoiceIcon, { icon: opt.icon }),
|
|
1617
1781
|
opt.icon && value === opt.id && // Icon-mode hides the native input, so its check state is
|
|
1618
1782
|
// otherwise color-only (forfeits forced-colors' own indicator).
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
/* @__PURE__ */
|
|
1783
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-option-check", "aria-hidden": "true", children: "\u2713" }),
|
|
1784
|
+
/* @__PURE__ */ jsx6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: opt.label })
|
|
1621
1785
|
]
|
|
1622
1786
|
},
|
|
1623
1787
|
opt.id
|
|
@@ -1627,7 +1791,7 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1627
1791
|
// option row above. The free-text input below is its own labelable
|
|
1628
1792
|
// descendant, so it handles its own clicks without re-toggling the
|
|
1629
1793
|
// radio (dom's proven pattern).
|
|
1630
|
-
/* @__PURE__ */
|
|
1794
|
+
/* @__PURE__ */ jsxs6(
|
|
1631
1795
|
"label",
|
|
1632
1796
|
{
|
|
1633
1797
|
"data-fillo": "option",
|
|
@@ -1638,8 +1802,8 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1638
1802
|
otherActive
|
|
1639
1803
|
),
|
|
1640
1804
|
children: [
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1805
|
+
/* @__PURE__ */ jsxs6("span", { className: "fillo-option-main", children: [
|
|
1806
|
+
/* @__PURE__ */ jsx6(
|
|
1643
1807
|
"input",
|
|
1644
1808
|
{
|
|
1645
1809
|
type: "radio",
|
|
@@ -1652,9 +1816,9 @@ function SingleChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1652
1816
|
}
|
|
1653
1817
|
}
|
|
1654
1818
|
),
|
|
1655
|
-
/* @__PURE__ */
|
|
1819
|
+
/* @__PURE__ */ jsx6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: strings.other })
|
|
1656
1820
|
] }),
|
|
1657
|
-
otherActive && /* @__PURE__ */
|
|
1821
|
+
otherActive && /* @__PURE__ */ jsx6(
|
|
1658
1822
|
"input",
|
|
1659
1823
|
{
|
|
1660
1824
|
type: "text",
|
|
@@ -1686,7 +1850,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1686
1850
|
const toggle = (id) => setValue(selected.includes(id) ? selected.filter((v) => v !== id) : [...selected, id]);
|
|
1687
1851
|
const appearance = useFilloAppearance();
|
|
1688
1852
|
const optionCls = (base, optionId, isSelected) => slotClass2(base, appearance, { slot: "option", kind: field.kind, fieldId: field.id, optionId, selected: isSelected });
|
|
1689
|
-
return /* @__PURE__ */
|
|
1853
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsxs6(
|
|
1690
1854
|
"div",
|
|
1691
1855
|
{
|
|
1692
1856
|
className: slotClass2("fillo-options", appearance, { slot: "options", kind: field.kind, fieldId: field.id }),
|
|
@@ -1695,7 +1859,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1695
1859
|
"aria-labelledby": ids.labelId,
|
|
1696
1860
|
...fieldAria(field, error, ids, { required: false }),
|
|
1697
1861
|
children: [
|
|
1698
|
-
options.map((opt) => /* @__PURE__ */
|
|
1862
|
+
options.map((opt) => /* @__PURE__ */ jsxs6(
|
|
1699
1863
|
"label",
|
|
1700
1864
|
{
|
|
1701
1865
|
"data-option": opt.id,
|
|
@@ -1707,7 +1871,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1707
1871
|
selected.includes(opt.id)
|
|
1708
1872
|
),
|
|
1709
1873
|
children: [
|
|
1710
|
-
/* @__PURE__ */
|
|
1874
|
+
/* @__PURE__ */ jsx6(
|
|
1711
1875
|
"input",
|
|
1712
1876
|
{
|
|
1713
1877
|
type: "checkbox",
|
|
@@ -1716,11 +1880,11 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1716
1880
|
onChange: () => toggle(opt.id)
|
|
1717
1881
|
}
|
|
1718
1882
|
),
|
|
1719
|
-
/* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ jsx6(ChoiceIcon, { icon: opt.icon }),
|
|
1720
1884
|
opt.icon && selected.includes(opt.id) && // Icon-mode hides the native input, so its check state is
|
|
1721
1885
|
// otherwise color-only (forfeits forced-colors' own indicator).
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1886
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-option-check", "aria-hidden": "true", children: "\u2713" }),
|
|
1887
|
+
/* @__PURE__ */ jsx6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: opt.label })
|
|
1724
1888
|
]
|
|
1725
1889
|
},
|
|
1726
1890
|
opt.id
|
|
@@ -1730,7 +1894,7 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1730
1894
|
// option row above. The free-text input below is its own labelable
|
|
1731
1895
|
// descendant, so it handles its own clicks without re-toggling the
|
|
1732
1896
|
// checkbox (dom's proven pattern).
|
|
1733
|
-
/* @__PURE__ */
|
|
1897
|
+
/* @__PURE__ */ jsxs6(
|
|
1734
1898
|
"label",
|
|
1735
1899
|
{
|
|
1736
1900
|
"data-fillo": "option",
|
|
@@ -1741,8 +1905,8 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1741
1905
|
otherActive
|
|
1742
1906
|
),
|
|
1743
1907
|
children: [
|
|
1744
|
-
/* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1908
|
+
/* @__PURE__ */ jsxs6("span", { className: "fillo-option-main", children: [
|
|
1909
|
+
/* @__PURE__ */ jsx6(
|
|
1746
1910
|
"input",
|
|
1747
1911
|
{
|
|
1748
1912
|
type: "checkbox",
|
|
@@ -1758,9 +1922,9 @@ function MultiChoice({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1758
1922
|
}
|
|
1759
1923
|
}
|
|
1760
1924
|
),
|
|
1761
|
-
/* @__PURE__ */
|
|
1925
|
+
/* @__PURE__ */ jsx6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: strings.other })
|
|
1762
1926
|
] }),
|
|
1763
|
-
otherActive && /* @__PURE__ */
|
|
1927
|
+
otherActive && /* @__PURE__ */ jsx6(
|
|
1764
1928
|
"input",
|
|
1765
1929
|
{
|
|
1766
1930
|
type: "text",
|
|
@@ -1798,9 +1962,9 @@ function Dropdown({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1798
1962
|
const [otherOn, setOtherOn] = useState5(isOtherValue);
|
|
1799
1963
|
const otherActive = isOtherValue || value === "" && otherOn;
|
|
1800
1964
|
const control = useControl("fillo-input fillo-select", field, error);
|
|
1801
|
-
return /* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
1803
|
-
/* @__PURE__ */
|
|
1965
|
+
return /* @__PURE__ */ jsxs6(FieldShell, { field, error, ids, children: [
|
|
1966
|
+
/* @__PURE__ */ jsxs6("div", { className: "fillo-select-wrap", children: [
|
|
1967
|
+
/* @__PURE__ */ jsxs6(
|
|
1804
1968
|
"select",
|
|
1805
1969
|
{
|
|
1806
1970
|
id: ids.inputId,
|
|
@@ -1817,15 +1981,15 @@ function Dropdown({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1817
1981
|
}
|
|
1818
1982
|
},
|
|
1819
1983
|
children: [
|
|
1820
|
-
/* @__PURE__ */
|
|
1821
|
-
options.map((opt) => /* @__PURE__ */
|
|
1822
|
-
choice.allowOther && /* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx6("option", { value: "", children: field.placeholder ?? strings.choosePlaceholder }),
|
|
1985
|
+
options.map((opt) => /* @__PURE__ */ jsx6("option", { value: opt.id, children: opt.label }, opt.id)),
|
|
1986
|
+
choice.allowOther && /* @__PURE__ */ jsx6("option", { value: otherValue, children: `${strings.other}\u2026` })
|
|
1823
1987
|
]
|
|
1824
1988
|
}
|
|
1825
1989
|
),
|
|
1826
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-select-icon", "aria-hidden": "true" })
|
|
1827
1991
|
] }),
|
|
1828
|
-
otherActive && /* @__PURE__ */
|
|
1992
|
+
otherActive && /* @__PURE__ */ jsx6(
|
|
1829
1993
|
"input",
|
|
1830
1994
|
{
|
|
1831
1995
|
type: "text",
|
|
@@ -1846,19 +2010,19 @@ function Checkbox({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1846
2010
|
const slots = useFieldSlots(field, error);
|
|
1847
2011
|
const checkbox = field;
|
|
1848
2012
|
if (checkbox.appearance === "toggle") {
|
|
1849
|
-
return /* @__PURE__ */
|
|
2013
|
+
return /* @__PURE__ */ jsxs6(
|
|
1850
2014
|
"div",
|
|
1851
2015
|
{
|
|
1852
2016
|
...slots.wrapperProps(
|
|
1853
2017
|
`fillo-field fillo-field--checkbox fillo-field--toggle${error ? " fillo-field--error" : ""}`
|
|
1854
2018
|
),
|
|
1855
2019
|
children: [
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
2020
|
+
/* @__PURE__ */ jsxs6("label", { className: "fillo-toggle", "data-fillo": "option", "data-checked": value === true ? "" : void 0, children: [
|
|
2021
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-toggle-copy", children: /* @__PURE__ */ jsxs6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: [
|
|
1858
2022
|
field.label,
|
|
1859
|
-
!field.required && /* @__PURE__ */
|
|
2023
|
+
!field.required && /* @__PURE__ */ jsx6("span", { className: "fillo-optional", children: strings.optional })
|
|
1860
2024
|
] }) }),
|
|
1861
|
-
/* @__PURE__ */
|
|
2025
|
+
/* @__PURE__ */ jsx6(
|
|
1862
2026
|
"input",
|
|
1863
2027
|
{
|
|
1864
2028
|
id: ids.inputId,
|
|
@@ -1869,23 +2033,23 @@ function Checkbox({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1869
2033
|
...fieldAria(field, error, ids)
|
|
1870
2034
|
}
|
|
1871
2035
|
),
|
|
1872
|
-
/* @__PURE__ */
|
|
2036
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-toggle-track", "aria-hidden": "true", children: /* @__PURE__ */ jsx6("span", { className: "fillo-toggle-thumb" }) })
|
|
1873
2037
|
] }),
|
|
1874
|
-
field.description && /* @__PURE__ */
|
|
1875
|
-
error && /* @__PURE__ */
|
|
2038
|
+
field.description && /* @__PURE__ */ jsx6("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
2039
|
+
error && /* @__PURE__ */ jsx6("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1876
2040
|
]
|
|
1877
2041
|
}
|
|
1878
2042
|
);
|
|
1879
2043
|
}
|
|
1880
|
-
return /* @__PURE__ */
|
|
2044
|
+
return /* @__PURE__ */ jsxs6(
|
|
1881
2045
|
"div",
|
|
1882
2046
|
{
|
|
1883
2047
|
...slots.wrapperProps(
|
|
1884
2048
|
`fillo-field fillo-field--checkbox${error ? " fillo-field--error" : ""}`
|
|
1885
2049
|
),
|
|
1886
2050
|
children: [
|
|
1887
|
-
/* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
2051
|
+
/* @__PURE__ */ jsxs6("label", { className: "fillo-option", "data-fillo": "option", "data-checked": value === true ? "" : void 0, children: [
|
|
2052
|
+
/* @__PURE__ */ jsx6(
|
|
1889
2053
|
"input",
|
|
1890
2054
|
{
|
|
1891
2055
|
id: ids.inputId,
|
|
@@ -1896,13 +2060,13 @@ function Checkbox({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1896
2060
|
...fieldAria(field, error, ids)
|
|
1897
2061
|
}
|
|
1898
2062
|
),
|
|
1899
|
-
/* @__PURE__ */
|
|
2063
|
+
/* @__PURE__ */ jsxs6("span", { className: slotClass2("fillo-option-label", appearance, { slot: "optionLabel", kind: field.kind, fieldId: field.id }), "data-fillo": "optionLabel", children: [
|
|
1900
2064
|
field.label,
|
|
1901
|
-
!field.required && /* @__PURE__ */
|
|
2065
|
+
!field.required && /* @__PURE__ */ jsx6("span", { className: "fillo-optional", children: strings.optional })
|
|
1902
2066
|
] })
|
|
1903
2067
|
] }),
|
|
1904
|
-
field.description && /* @__PURE__ */
|
|
1905
|
-
error && /* @__PURE__ */
|
|
2068
|
+
field.description && /* @__PURE__ */ jsx6("p", { className: slots.description, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
2069
|
+
error && /* @__PURE__ */ jsx6("p", { className: slots.error, "data-fillo": "error", id: ids.errorId, children: error })
|
|
1906
2070
|
]
|
|
1907
2071
|
}
|
|
1908
2072
|
);
|
|
@@ -1934,7 +2098,7 @@ function Rating({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1934
2098
|
const tabbable = rovingIndex(steps, selected);
|
|
1935
2099
|
const appearance = useFilloAppearance();
|
|
1936
2100
|
const control = useControl("fillo-rating", field, error);
|
|
1937
|
-
return /* @__PURE__ */
|
|
2101
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx6(
|
|
1938
2102
|
"div",
|
|
1939
2103
|
{
|
|
1940
2104
|
id: ids.inputId,
|
|
@@ -1943,7 +2107,7 @@ function Rating({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1943
2107
|
"aria-labelledby": ids.labelId,
|
|
1944
2108
|
...fieldAria(field, error, ids),
|
|
1945
2109
|
onKeyDown: (e) => radiogroupKeyDown(e, steps, selected, (n) => setValue(n)),
|
|
1946
|
-
children: steps.map((n, i) => /* @__PURE__ */
|
|
2110
|
+
children: steps.map((n, i) => /* @__PURE__ */ jsx6(
|
|
1947
2111
|
"button",
|
|
1948
2112
|
{
|
|
1949
2113
|
type: "button",
|
|
@@ -1989,8 +2153,8 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
1989
2153
|
].filter(Boolean).join(" ") || void 0;
|
|
1990
2154
|
const appearance = useFilloAppearance();
|
|
1991
2155
|
const control = useControl("fillo-scale", field, error);
|
|
1992
|
-
return /* @__PURE__ */
|
|
1993
|
-
/* @__PURE__ */
|
|
2156
|
+
return /* @__PURE__ */ jsxs6(FieldShell, { field, error, ids, children: [
|
|
2157
|
+
/* @__PURE__ */ jsx6(
|
|
1994
2158
|
"div",
|
|
1995
2159
|
{
|
|
1996
2160
|
id: ids.inputId,
|
|
@@ -2001,7 +2165,7 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2001
2165
|
"aria-required": field.required ? true : void 0,
|
|
2002
2166
|
"aria-describedby": describedBy,
|
|
2003
2167
|
onKeyDown: (e) => radiogroupKeyDown(e, steps, current, (n) => setValue(n)),
|
|
2004
|
-
children: steps.map((n, i) => /* @__PURE__ */
|
|
2168
|
+
children: steps.map((n, i) => /* @__PURE__ */ jsx6(
|
|
2005
2169
|
"button",
|
|
2006
2170
|
{
|
|
2007
2171
|
type: "button",
|
|
@@ -2027,9 +2191,9 @@ function LinearScale({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2027
2191
|
))
|
|
2028
2192
|
}
|
|
2029
2193
|
),
|
|
2030
|
-
hasLabels && /* @__PURE__ */
|
|
2031
|
-
/* @__PURE__ */
|
|
2032
|
-
/* @__PURE__ */
|
|
2194
|
+
hasLabels && /* @__PURE__ */ jsxs6("div", { className: "fillo-scale-labels", children: [
|
|
2195
|
+
/* @__PURE__ */ jsx6("span", { id: minLabelId, children: scale.minLabel }),
|
|
2196
|
+
/* @__PURE__ */ jsx6("span", { id: maxLabelId, children: scale.maxLabel })
|
|
2033
2197
|
] })
|
|
2034
2198
|
] });
|
|
2035
2199
|
}
|
|
@@ -2043,8 +2207,8 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2043
2207
|
...answered.filter((id) => ranking.options.some((o) => o.id === id)),
|
|
2044
2208
|
...ranking.options.map((o) => o.id).filter((id) => !answered.includes(id))
|
|
2045
2209
|
];
|
|
2046
|
-
const pressedRef =
|
|
2047
|
-
|
|
2210
|
+
const pressedRef = useRef7(null);
|
|
2211
|
+
useEffect7(() => {
|
|
2048
2212
|
const pressed = pressedRef.current;
|
|
2049
2213
|
pressedRef.current = null;
|
|
2050
2214
|
if (!pressed || !pressed.disabled) return;
|
|
@@ -2064,21 +2228,21 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2064
2228
|
const moved = ranking.options.find((o) => o.id === id);
|
|
2065
2229
|
if (moved) announce(strings.rankingPosition(moved.label, target + 1, order.length));
|
|
2066
2230
|
}
|
|
2067
|
-
return /* @__PURE__ */
|
|
2231
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx6(
|
|
2068
2232
|
"div",
|
|
2069
2233
|
{
|
|
2070
2234
|
id: ids.inputId,
|
|
2071
2235
|
role: "group",
|
|
2072
2236
|
"aria-labelledby": ids.labelId,
|
|
2073
2237
|
...fieldAria(field, error, ids, { required: false }),
|
|
2074
|
-
children: /* @__PURE__ */
|
|
2238
|
+
children: /* @__PURE__ */ jsx6("ol", { className: "fillo-ranking", children: order.map((id, index) => {
|
|
2075
2239
|
const option = ranking.options.find((o) => o.id === id);
|
|
2076
2240
|
if (!option) return null;
|
|
2077
|
-
return /* @__PURE__ */
|
|
2078
|
-
/* @__PURE__ */
|
|
2079
|
-
/* @__PURE__ */
|
|
2080
|
-
/* @__PURE__ */
|
|
2081
|
-
/* @__PURE__ */
|
|
2241
|
+
return /* @__PURE__ */ jsxs6("li", { className: "fillo-ranking-item", children: [
|
|
2242
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-ranking-index", children: index + 1 }),
|
|
2243
|
+
/* @__PURE__ */ jsx6("span", { className: "fillo-ranking-label", children: option.label }),
|
|
2244
|
+
/* @__PURE__ */ jsxs6("span", { className: "fillo-ranking-controls", children: [
|
|
2245
|
+
/* @__PURE__ */ jsx6(
|
|
2082
2246
|
"button",
|
|
2083
2247
|
{
|
|
2084
2248
|
type: "button",
|
|
@@ -2089,7 +2253,7 @@ function Ranking({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2089
2253
|
children: "\u2191"
|
|
2090
2254
|
}
|
|
2091
2255
|
),
|
|
2092
|
-
/* @__PURE__ */
|
|
2256
|
+
/* @__PURE__ */ jsx6(
|
|
2093
2257
|
"button",
|
|
2094
2258
|
{
|
|
2095
2259
|
type: "button",
|
|
@@ -2110,7 +2274,7 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2110
2274
|
const ids = useFilloFieldIds(field.id, providedIds);
|
|
2111
2275
|
const matrix = field;
|
|
2112
2276
|
const answers = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2113
|
-
return /* @__PURE__ */
|
|
2277
|
+
return /* @__PURE__ */ jsx6(FieldShell, { field, error, ids, children: /* @__PURE__ */ jsx6(
|
|
2114
2278
|
"div",
|
|
2115
2279
|
{
|
|
2116
2280
|
id: ids.inputId,
|
|
@@ -2118,12 +2282,12 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2118
2282
|
role: "group",
|
|
2119
2283
|
"aria-labelledby": ids.labelId,
|
|
2120
2284
|
...fieldAria(field, error, ids, { required: false }),
|
|
2121
|
-
children: /* @__PURE__ */
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
matrix.columns.map((col) => /* @__PURE__ */
|
|
2285
|
+
children: /* @__PURE__ */ jsxs6("table", { className: "fillo-matrix", children: [
|
|
2286
|
+
/* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { children: [
|
|
2287
|
+
/* @__PURE__ */ jsx6("td", {}),
|
|
2288
|
+
matrix.columns.map((col) => /* @__PURE__ */ jsx6("th", { scope: "col", children: col.label }, col.id))
|
|
2125
2289
|
] }) }),
|
|
2126
|
-
/* @__PURE__ */
|
|
2290
|
+
/* @__PURE__ */ jsx6("tbody", { children: matrix.rows.map((row) => {
|
|
2127
2291
|
const rowLabelId = `${ids.inputId}-${row.id}`;
|
|
2128
2292
|
const answered = answers[row.id] !== void 0;
|
|
2129
2293
|
const rowInvalid = Boolean(error) && field.required && !answered;
|
|
@@ -2134,17 +2298,17 @@ function Matrix({ field, value, error, setValue, ids: providedIds }) {
|
|
|
2134
2298
|
// radiogroup lives on an inner element that aria-owns the radios
|
|
2135
2299
|
// scattered across the cells (they can't be DOM-nested inside a
|
|
2136
2300
|
// single element within a table row).
|
|
2137
|
-
/* @__PURE__ */
|
|
2138
|
-
/* @__PURE__ */
|
|
2301
|
+
/* @__PURE__ */ jsxs6("tr", { children: [
|
|
2302
|
+
/* @__PURE__ */ jsx6("th", { scope: "row", children: /* @__PURE__ */ jsx6(
|
|
2139
2303
|
"div",
|
|
2140
2304
|
{
|
|
2141
2305
|
role: "radiogroup",
|
|
2142
2306
|
"aria-labelledby": `${ids.labelId} ${rowLabelId}`,
|
|
2143
2307
|
"aria-owns": matrix.columns.map(radioId).join(" "),
|
|
2144
|
-
children: /* @__PURE__ */
|
|
2308
|
+
children: /* @__PURE__ */ jsx6("span", { id: rowLabelId, children: row.label })
|
|
2145
2309
|
}
|
|
2146
2310
|
) }),
|
|
2147
|
-
matrix.columns.map((col) => /* @__PURE__ */
|
|
2311
|
+
matrix.columns.map((col) => /* @__PURE__ */ jsx6("td", { "data-label": col.label, children: /* @__PURE__ */ jsx6("label", { className: "fillo-matrix-cell", children: /* @__PURE__ */ jsx6(
|
|
2148
2312
|
"input",
|
|
2149
2313
|
{
|
|
2150
2314
|
id: radioId(col),
|
|
@@ -2178,7 +2342,7 @@ function Calculated({ field, value, ids: providedIds }) {
|
|
|
2178
2342
|
const labelCls = useSlotClass("fillo-label", { slot: "label", ...state });
|
|
2179
2343
|
const descriptionCls = useSlotClass("fillo-description", { slot: "fieldDescription", ...state });
|
|
2180
2344
|
const answered = value !== void 0 && value !== null && value !== "";
|
|
2181
|
-
return /* @__PURE__ */
|
|
2345
|
+
return /* @__PURE__ */ jsxs6(
|
|
2182
2346
|
"div",
|
|
2183
2347
|
{
|
|
2184
2348
|
className: rootCls,
|
|
@@ -2186,9 +2350,9 @@ function Calculated({ field, value, ids: providedIds }) {
|
|
|
2186
2350
|
"data-field": field.id,
|
|
2187
2351
|
"data-kind": field.kind,
|
|
2188
2352
|
children: [
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
field.description && /* @__PURE__ */
|
|
2191
|
-
/* @__PURE__ */
|
|
2353
|
+
/* @__PURE__ */ jsx6("label", { className: labelCls, "data-fillo": "label", id: ids.labelId, htmlFor: ids.inputId, children: field.label }),
|
|
2354
|
+
field.description && /* @__PURE__ */ jsx6("p", { className: descriptionCls, "data-fillo": "fieldDescription", id: ids.descriptionId, children: field.description }),
|
|
2355
|
+
/* @__PURE__ */ jsx6(
|
|
2192
2356
|
"output",
|
|
2193
2357
|
{
|
|
2194
2358
|
id: ids.inputId,
|
|
@@ -2220,16 +2384,17 @@ var DEFAULT_COMPONENTS = {
|
|
|
2220
2384
|
signature: SignatureField,
|
|
2221
2385
|
file_upload: FileUploadField,
|
|
2222
2386
|
hidden: Hidden,
|
|
2223
|
-
calculated: Calculated
|
|
2387
|
+
calculated: Calculated,
|
|
2388
|
+
repeating_group: RepeatingGroup
|
|
2224
2389
|
};
|
|
2225
2390
|
function ContentRenderer({ block }) {
|
|
2226
2391
|
switch (block.kind) {
|
|
2227
2392
|
case "heading":
|
|
2228
|
-
return /* @__PURE__ */
|
|
2393
|
+
return /* @__PURE__ */ jsx6("h3", { className: "fillo-heading", children: block.text });
|
|
2229
2394
|
case "paragraph":
|
|
2230
|
-
return /* @__PURE__ */
|
|
2395
|
+
return /* @__PURE__ */ jsx6("p", { className: "fillo-paragraph", children: block.text });
|
|
2231
2396
|
case "divider":
|
|
2232
|
-
return /* @__PURE__ */
|
|
2397
|
+
return /* @__PURE__ */ jsx6("hr", { className: "fillo-divider" });
|
|
2233
2398
|
}
|
|
2234
2399
|
}
|
|
2235
2400
|
function blockHasPiping(block) {
|
|
@@ -2268,7 +2433,7 @@ function BlockRendererInner({ block, api, components, customComponents }) {
|
|
|
2268
2433
|
block = pipeBlock(block, api.data, api.form);
|
|
2269
2434
|
const ids = useFilloFieldIds(block.id);
|
|
2270
2435
|
const strings = useStrings();
|
|
2271
|
-
if (!isField(block)) return /* @__PURE__ */
|
|
2436
|
+
if (!isField(block)) return /* @__PURE__ */ jsx6(ContentRenderer, { block });
|
|
2272
2437
|
let Component;
|
|
2273
2438
|
if (block.kind === "custom") {
|
|
2274
2439
|
Component = customComponents?.[block.component] ?? components?.custom;
|
|
@@ -2286,7 +2451,7 @@ function BlockRendererInner({ block, api, components, customComponents }) {
|
|
|
2286
2451
|
}
|
|
2287
2452
|
const rawError = api.errors[block.id];
|
|
2288
2453
|
const error = rawError === REQUIRED_FIELD_MESSAGE ? requiredFieldMessage(block, strings) : rawError;
|
|
2289
|
-
return /* @__PURE__ */
|
|
2454
|
+
return /* @__PURE__ */ jsx6(
|
|
2290
2455
|
Component,
|
|
2291
2456
|
{
|
|
2292
2457
|
field: block,
|
|
@@ -2316,14 +2481,14 @@ function FormField({
|
|
|
2316
2481
|
customComponents
|
|
2317
2482
|
}) {
|
|
2318
2483
|
const api = useFillo();
|
|
2319
|
-
const visibleIds =
|
|
2484
|
+
const visibleIds = useMemo5(
|
|
2320
2485
|
() => new Set(visibleFields(api.form, api.data).map((f) => f.id)),
|
|
2321
2486
|
[api.form, api.data]
|
|
2322
2487
|
);
|
|
2323
2488
|
const block = api.form.pages.flatMap((p) => p.blocks).find((b) => b.id === id);
|
|
2324
2489
|
if (!block) return null;
|
|
2325
2490
|
if (isField(block) && !visibleIds.has(block.id)) return null;
|
|
2326
|
-
return /* @__PURE__ */
|
|
2491
|
+
return /* @__PURE__ */ jsx6(
|
|
2327
2492
|
BlockRenderer,
|
|
2328
2493
|
{
|
|
2329
2494
|
block,
|
|
@@ -2335,8 +2500,8 @@ function FormField({
|
|
|
2335
2500
|
}
|
|
2336
2501
|
|
|
2337
2502
|
// src/turnstile.tsx
|
|
2338
|
-
import { useEffect as
|
|
2339
|
-
import { jsx as
|
|
2503
|
+
import { useEffect as useEffect8, useRef as useRef8 } from "react";
|
|
2504
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2340
2505
|
var SCRIPT_SRC = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
|
2341
2506
|
var SCRIPT_ID = "fillo-turnstile-script";
|
|
2342
2507
|
var scriptPromise = null;
|
|
@@ -2394,15 +2559,15 @@ function TurnstileWidget({
|
|
|
2394
2559
|
registerReset,
|
|
2395
2560
|
className
|
|
2396
2561
|
}) {
|
|
2397
|
-
const containerRef =
|
|
2398
|
-
const widgetIdRef =
|
|
2399
|
-
const onTokenRef =
|
|
2562
|
+
const containerRef = useRef8(null);
|
|
2563
|
+
const widgetIdRef = useRef8(null);
|
|
2564
|
+
const onTokenRef = useRef8(onToken);
|
|
2400
2565
|
onTokenRef.current = onToken;
|
|
2401
|
-
const onErrorRef =
|
|
2566
|
+
const onErrorRef = useRef8(onError);
|
|
2402
2567
|
onErrorRef.current = onError;
|
|
2403
|
-
const registerResetRef =
|
|
2568
|
+
const registerResetRef = useRef8(registerReset);
|
|
2404
2569
|
registerResetRef.current = registerReset;
|
|
2405
|
-
|
|
2570
|
+
useEffect8(() => {
|
|
2406
2571
|
let cancelled = false;
|
|
2407
2572
|
loadTurnstileScript().then(() => {
|
|
2408
2573
|
if (cancelled || !containerRef.current) return;
|
|
@@ -2443,7 +2608,7 @@ function TurnstileWidget({
|
|
|
2443
2608
|
onTokenRef.current(void 0);
|
|
2444
2609
|
};
|
|
2445
2610
|
}, [siteKey]);
|
|
2446
|
-
return /* @__PURE__ */
|
|
2611
|
+
return /* @__PURE__ */ jsx7(
|
|
2447
2612
|
"div",
|
|
2448
2613
|
{
|
|
2449
2614
|
ref: containerRef,
|
|
@@ -2454,7 +2619,7 @@ function TurnstileWidget({
|
|
|
2454
2619
|
}
|
|
2455
2620
|
|
|
2456
2621
|
// src/FilloForm.tsx
|
|
2457
|
-
import { Fragment as Fragment3, jsx as
|
|
2622
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2458
2623
|
function themeProps(theme) {
|
|
2459
2624
|
const safeTheme = resolveThemeAppearance(normalizeFormTheme(theme));
|
|
2460
2625
|
if (!safeTheme) return {};
|
|
@@ -2476,10 +2641,10 @@ function badgeUrl(href) {
|
|
|
2476
2641
|
url.searchParams.set("utm_source", "form_badge");
|
|
2477
2642
|
return url.toString();
|
|
2478
2643
|
}
|
|
2479
|
-
var
|
|
2644
|
+
var FOCUSABLE_SELECTOR2 = 'input:not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
2480
2645
|
function resolveFocusable(el) {
|
|
2481
2646
|
if (!el) return null;
|
|
2482
|
-
return el.matches(
|
|
2647
|
+
return el.matches(FOCUSABLE_SELECTOR2) ? el : el.querySelector(FOCUSABLE_SELECTOR2);
|
|
2483
2648
|
}
|
|
2484
2649
|
function nextFrame(run) {
|
|
2485
2650
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(run);
|
|
@@ -2511,7 +2676,7 @@ function assertHpHidden(el) {
|
|
|
2511
2676
|
function FilloForm(props) {
|
|
2512
2677
|
const { form, formId } = props;
|
|
2513
2678
|
const renderOnly = props.renderOnly === true || props.skipValidation === true;
|
|
2514
|
-
const client =
|
|
2679
|
+
const client = useMemo6(
|
|
2515
2680
|
() => renderOnly ? void 0 : props.client ?? (formId ? createClient() : void 0),
|
|
2516
2681
|
[renderOnly, props.client, formId]
|
|
2517
2682
|
);
|
|
@@ -2548,11 +2713,11 @@ function FilloForm(props) {
|
|
|
2548
2713
|
});
|
|
2549
2714
|
const renderResolvedSnapshot = Boolean(resolvedSchema && !devChrome);
|
|
2550
2715
|
const inlineSchema = codeForm ? renderResolvedSnapshot ? resolvedSchema : codeForm.schema : form;
|
|
2551
|
-
const onErrorRef =
|
|
2552
|
-
|
|
2716
|
+
const onErrorRef = useRef9(onError);
|
|
2717
|
+
useEffect9(() => {
|
|
2553
2718
|
onErrorRef.current = onError;
|
|
2554
2719
|
});
|
|
2555
|
-
const targetError =
|
|
2720
|
+
const targetError = useMemo6(
|
|
2556
2721
|
() => form && !formId && !renderOnly && (!isCodeForm2(form) || !props.client) ? new FilloError2(
|
|
2557
2722
|
"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.",
|
|
2558
2723
|
422,
|
|
@@ -2561,11 +2726,11 @@ function FilloForm(props) {
|
|
|
2561
2726
|
) : null,
|
|
2562
2727
|
[form, formId, props.client, renderOnly]
|
|
2563
2728
|
);
|
|
2564
|
-
|
|
2729
|
+
useEffect9(() => {
|
|
2565
2730
|
if (targetError) onErrorRef.current?.(targetError);
|
|
2566
2731
|
}, [targetError]);
|
|
2567
2732
|
const needsFetch = !inlineSchema && Boolean(client && formId);
|
|
2568
|
-
|
|
2733
|
+
useEffect9(() => {
|
|
2569
2734
|
if (!needsFetch || !client || !formId) {
|
|
2570
2735
|
setLoaded(null);
|
|
2571
2736
|
setLoadFailure(null);
|
|
@@ -2602,7 +2767,7 @@ function FilloForm(props) {
|
|
|
2602
2767
|
const currentLoaded = needsFetch && loaded?.formId === formId ? loaded : null;
|
|
2603
2768
|
const loadError = needsFetch && loadFailure && loadFailure.formId === formId ? loadFailure.error : null;
|
|
2604
2769
|
const rawSchema = inlineSchema ?? currentLoaded?.schema ?? null;
|
|
2605
|
-
const normalized =
|
|
2770
|
+
const normalized = useMemo6(
|
|
2606
2771
|
() => rawSchema ? normalizeFormSchema(rawSchema) : null,
|
|
2607
2772
|
[rawSchema]
|
|
2608
2773
|
);
|
|
@@ -2610,8 +2775,8 @@ function FilloForm(props) {
|
|
|
2610
2775
|
const resolvedCodeTheme = renderResolvedSnapshot ? resolvedTheme ?? void 0 : codeForm?.theme;
|
|
2611
2776
|
const theme = props.appearance?.theme ?? props.theme ?? resolvedCodeTheme ?? currentLoaded?.theme ?? void 0;
|
|
2612
2777
|
if (targetError) {
|
|
2613
|
-
if (props.renderError) return /* @__PURE__ */
|
|
2614
|
-
return /* @__PURE__ */
|
|
2778
|
+
if (props.renderError) return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(targetError) });
|
|
2779
|
+
return /* @__PURE__ */ jsx8(
|
|
2615
2780
|
"div",
|
|
2616
2781
|
{
|
|
2617
2782
|
className: `fillo-form fillo-form--error ${props.className ?? ""}`,
|
|
@@ -2626,15 +2791,15 @@ function FilloForm(props) {
|
|
|
2626
2791
|
}
|
|
2627
2792
|
if (normalized && !normalized.ok) {
|
|
2628
2793
|
const error = new FilloError2(`This form could not be rendered: ${normalized.error}`, 422);
|
|
2629
|
-
if (props.renderError) return /* @__PURE__ */
|
|
2630
|
-
return /* @__PURE__ */
|
|
2794
|
+
if (props.renderError) return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(error) });
|
|
2795
|
+
return /* @__PURE__ */ jsx8("div", { className: `fillo-form fillo-form--error ${props.className ?? ""}`, children: strings.renderFailed });
|
|
2631
2796
|
}
|
|
2632
2797
|
if (loadError) {
|
|
2633
2798
|
if (props.renderError) {
|
|
2634
|
-
return /* @__PURE__ */
|
|
2799
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(loadError) });
|
|
2635
2800
|
}
|
|
2636
2801
|
const message = loadError.status === 404 ? strings.loadFailedNotFound : loadError.status === 0 ? strings.loadFailedNetwork : strings.loadFailed;
|
|
2637
|
-
return /* @__PURE__ */
|
|
2802
|
+
return /* @__PURE__ */ jsx8("div", { className: `fillo-form fillo-form--error ${props.className ?? ""}`, children: message });
|
|
2638
2803
|
}
|
|
2639
2804
|
if (currentLoaded?.accepting === false && schema) {
|
|
2640
2805
|
const variant = overlayVariant(currentLoaded.acceptingReason);
|
|
@@ -2650,9 +2815,9 @@ function FilloForm(props) {
|
|
|
2650
2815
|
void 0,
|
|
2651
2816
|
currentLoaded.acceptingReason
|
|
2652
2817
|
);
|
|
2653
|
-
return /* @__PURE__ */
|
|
2818
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(error) });
|
|
2654
2819
|
}
|
|
2655
|
-
return /* @__PURE__ */
|
|
2820
|
+
return /* @__PURE__ */ jsx8(
|
|
2656
2821
|
NotOpenOverlay,
|
|
2657
2822
|
{
|
|
2658
2823
|
...props,
|
|
@@ -2664,21 +2829,21 @@ function FilloForm(props) {
|
|
|
2664
2829
|
);
|
|
2665
2830
|
}
|
|
2666
2831
|
if (currentLoaded?.closed) {
|
|
2667
|
-
return /* @__PURE__ */
|
|
2832
|
+
return /* @__PURE__ */ jsx8(
|
|
2668
2833
|
"div",
|
|
2669
2834
|
{
|
|
2670
2835
|
className: `fillo-form fillo-form--closed ${props.className ?? ""}`,
|
|
2671
2836
|
...themeProps(theme),
|
|
2672
|
-
children: /* @__PURE__ */
|
|
2837
|
+
children: /* @__PURE__ */ jsx8("p", { className: "fillo-closed", children: strings.closed })
|
|
2673
2838
|
}
|
|
2674
2839
|
);
|
|
2675
2840
|
}
|
|
2676
2841
|
const canonicalSyncError = codeForm && syncError && !props.skipValidation ? syncError : null;
|
|
2677
2842
|
if (canonicalSyncError && props.renderError) {
|
|
2678
|
-
return /* @__PURE__ */
|
|
2843
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(canonicalSyncError) });
|
|
2679
2844
|
}
|
|
2680
2845
|
if (canonicalSyncError && !devChrome) {
|
|
2681
|
-
return /* @__PURE__ */
|
|
2846
|
+
return /* @__PURE__ */ jsx8(
|
|
2682
2847
|
"div",
|
|
2683
2848
|
{
|
|
2684
2849
|
className: `fillo-form fillo-form--error ${props.className ?? ""}`,
|
|
@@ -2700,9 +2865,9 @@ function FilloForm(props) {
|
|
|
2700
2865
|
void 0,
|
|
2701
2866
|
syncedAcceptingReason
|
|
2702
2867
|
) : new FilloError2("This form isn't published yet.", 403);
|
|
2703
|
-
if (props.renderError) return /* @__PURE__ */
|
|
2868
|
+
if (props.renderError) return /* @__PURE__ */ jsx8(Fragment3, { children: props.renderError(error) });
|
|
2704
2869
|
if (schema) {
|
|
2705
|
-
return /* @__PURE__ */
|
|
2870
|
+
return /* @__PURE__ */ jsx8(
|
|
2706
2871
|
NotOpenOverlay,
|
|
2707
2872
|
{
|
|
2708
2873
|
...props,
|
|
@@ -2713,27 +2878,27 @@ function FilloForm(props) {
|
|
|
2713
2878
|
}
|
|
2714
2879
|
);
|
|
2715
2880
|
}
|
|
2716
|
-
return /* @__PURE__ */
|
|
2881
|
+
return /* @__PURE__ */ jsx8(
|
|
2717
2882
|
"div",
|
|
2718
2883
|
{
|
|
2719
2884
|
className: `fillo-form fillo-form--closed ${props.className ?? ""}`,
|
|
2720
2885
|
...themeProps(theme),
|
|
2721
|
-
children: /* @__PURE__ */
|
|
2886
|
+
children: /* @__PURE__ */ jsx8("p", { className: "fillo-closed", children: variant === "closed" ? strings.closed : strings.notLive })
|
|
2722
2887
|
}
|
|
2723
2888
|
);
|
|
2724
2889
|
}
|
|
2725
2890
|
const awaitingCanonical = Boolean(codeForm && codeFormSyncing && !props.skipValidation);
|
|
2726
2891
|
if (!devChrome && awaitingCanonical || !schema) {
|
|
2727
|
-
return /* @__PURE__ */
|
|
2892
|
+
return /* @__PURE__ */ jsxs7(
|
|
2728
2893
|
"div",
|
|
2729
2894
|
{
|
|
2730
2895
|
className: `fillo-form fillo-form--loading ${props.className ?? ""}`,
|
|
2731
2896
|
"aria-busy": "true",
|
|
2732
2897
|
...themeProps(theme),
|
|
2733
2898
|
children: [
|
|
2734
|
-
/* @__PURE__ */
|
|
2735
|
-
/* @__PURE__ */
|
|
2736
|
-
/* @__PURE__ */
|
|
2899
|
+
/* @__PURE__ */ jsx8("div", { className: "fillo-skeleton" }),
|
|
2900
|
+
/* @__PURE__ */ jsx8("div", { className: "fillo-skeleton" }),
|
|
2901
|
+
/* @__PURE__ */ jsx8("div", { className: "fillo-skeleton fillo-skeleton--short" })
|
|
2737
2902
|
]
|
|
2738
2903
|
}
|
|
2739
2904
|
);
|
|
@@ -2741,7 +2906,7 @@ function FilloForm(props) {
|
|
|
2741
2906
|
const branding = codeForm ? syncedBranding : currentLoaded?.branding;
|
|
2742
2907
|
const poweredBy = branding?.poweredBy ?? true;
|
|
2743
2908
|
const challenge = props.challenge ?? (codeForm ? syncedChallenge : currentLoaded?.challenge) ?? void 0;
|
|
2744
|
-
return /* @__PURE__ */
|
|
2909
|
+
return /* @__PURE__ */ jsx8(
|
|
2745
2910
|
ResolvedForm,
|
|
2746
2911
|
{
|
|
2747
2912
|
...props,
|
|
@@ -2766,7 +2931,7 @@ function FilloForm(props) {
|
|
|
2766
2931
|
);
|
|
2767
2932
|
}
|
|
2768
2933
|
function PoweredBy({ label, href }) {
|
|
2769
|
-
return /* @__PURE__ */
|
|
2934
|
+
return /* @__PURE__ */ jsx8("a", { className: "fillo-powered", href: badgeUrl(href), target: "_blank", rel: "noopener noreferrer", children: label ?? "Powered by Fillo" });
|
|
2770
2935
|
}
|
|
2771
2936
|
function overlayVariant(reason) {
|
|
2772
2937
|
return reason === "expired" || reason === "capped" || reason === "storage_full" ? "closed" : "notOpen";
|
|
@@ -2774,7 +2939,7 @@ function overlayVariant(reason) {
|
|
|
2774
2939
|
function NotOpenOverlay(props) {
|
|
2775
2940
|
const strings = resolveStrings(props.strings);
|
|
2776
2941
|
const closedFlavor = props.variant === "closed";
|
|
2777
|
-
return /* @__PURE__ */
|
|
2942
|
+
return /* @__PURE__ */ jsxs7(
|
|
2778
2943
|
"div",
|
|
2779
2944
|
{
|
|
2780
2945
|
className: `fillo-form fillo-form--not-open ${props.className ?? ""}`,
|
|
@@ -2782,13 +2947,13 @@ function NotOpenOverlay(props) {
|
|
|
2782
2947
|
"data-state": "closed",
|
|
2783
2948
|
...themeProps(props.theme),
|
|
2784
2949
|
children: [
|
|
2785
|
-
/* @__PURE__ */
|
|
2950
|
+
/* @__PURE__ */ jsx8(
|
|
2786
2951
|
"div",
|
|
2787
2952
|
{
|
|
2788
2953
|
className: "fillo-not-open-preview",
|
|
2789
2954
|
"aria-hidden": "true",
|
|
2790
2955
|
ref: (node) => node?.setAttribute("inert", ""),
|
|
2791
|
-
children: /* @__PURE__ */
|
|
2956
|
+
children: /* @__PURE__ */ jsx8(
|
|
2792
2957
|
ResolvedForm,
|
|
2793
2958
|
{
|
|
2794
2959
|
schema: props.schema,
|
|
@@ -2804,11 +2969,11 @@ function NotOpenOverlay(props) {
|
|
|
2804
2969
|
)
|
|
2805
2970
|
}
|
|
2806
2971
|
),
|
|
2807
|
-
/* @__PURE__ */
|
|
2808
|
-
/* @__PURE__ */
|
|
2809
|
-
/* @__PURE__ */
|
|
2972
|
+
/* @__PURE__ */ jsxs7("div", { className: "fillo-not-open-card", "data-fillo": "not-open-card", role: "status", children: [
|
|
2973
|
+
/* @__PURE__ */ jsx8("h2", { className: "fillo-not-open-title", children: closedFlavor ? strings.closedTitle : strings.notOpenTitle }),
|
|
2974
|
+
/* @__PURE__ */ jsx8("p", { className: "fillo-not-open-body", children: closedFlavor ? strings.closed : strings.notOpenBody })
|
|
2810
2975
|
] }),
|
|
2811
|
-
(props.branding?.poweredBy ?? true) && /* @__PURE__ */
|
|
2976
|
+
(props.branding?.poweredBy ?? true) && /* @__PURE__ */ jsx8(PoweredBy, { label: props.branding?.label, href: props.branding?.href })
|
|
2812
2977
|
]
|
|
2813
2978
|
}
|
|
2814
2979
|
);
|
|
@@ -2825,26 +2990,26 @@ function ResolvedForm(props) {
|
|
|
2825
2990
|
const instanceId = useId2().replace(/:/g, "");
|
|
2826
2991
|
const devEnv = useIsDevEnv();
|
|
2827
2992
|
const devChrome = !displayOnly && (props.preview === true || devEnv);
|
|
2828
|
-
const hpRef =
|
|
2993
|
+
const hpRef = useRef9(null);
|
|
2829
2994
|
const codeForm = isCodeForm2(props.form) ? props.form : null;
|
|
2830
2995
|
const client = props.client;
|
|
2831
2996
|
const challenge = renderOnly ? void 0 : props.challenge;
|
|
2832
2997
|
const challengeRequired = Boolean(challenge);
|
|
2833
|
-
const challengeTokenRef =
|
|
2998
|
+
const challengeTokenRef = useRef9(void 0);
|
|
2834
2999
|
const [resyncWarning, setResyncWarning] = useState6(null);
|
|
2835
3000
|
const [resolutionFailureCode, setResolutionFailureCode] = useState6(null);
|
|
2836
3001
|
const [challengeToken, setChallengeToken] = useState6(void 0);
|
|
2837
3002
|
const [challengeError, setChallengeError] = useState6(false);
|
|
2838
|
-
const resetChallengeRef =
|
|
2839
|
-
const handleChallengeToken =
|
|
3003
|
+
const resetChallengeRef = useRef9(void 0);
|
|
3004
|
+
const handleChallengeToken = useCallback2((token) => {
|
|
2840
3005
|
challengeTokenRef.current = token;
|
|
2841
3006
|
setChallengeToken(token);
|
|
2842
3007
|
if (token) setChallengeError(false);
|
|
2843
3008
|
}, []);
|
|
2844
|
-
const registerChallengeReset =
|
|
3009
|
+
const registerChallengeReset = useCallback2((reset) => {
|
|
2845
3010
|
resetChallengeRef.current = reset;
|
|
2846
3011
|
}, []);
|
|
2847
|
-
const resolveFormId =
|
|
3012
|
+
const resolveFormId = useMemo6(
|
|
2848
3013
|
() => codeForm && client?.key ? (
|
|
2849
3014
|
// bypassCache: a stale cached formId must not be trusted at submit time.
|
|
2850
3015
|
async () => {
|
|
@@ -2942,8 +3107,8 @@ function ResolvedForm(props) {
|
|
|
2942
3107
|
});
|
|
2943
3108
|
useDraftFlush(api, !displayOnly && !renderOnly);
|
|
2944
3109
|
const strings = resolveStrings(props.strings);
|
|
2945
|
-
const announceRef =
|
|
2946
|
-
const announce =
|
|
3110
|
+
const announceRef = useRef9(null);
|
|
3111
|
+
const announce = useCallback2((text) => {
|
|
2947
3112
|
const el = announceRef.current;
|
|
2948
3113
|
if (!el) return;
|
|
2949
3114
|
if (el.textContent === text) {
|
|
@@ -2955,20 +3120,20 @@ function ResolvedForm(props) {
|
|
|
2955
3120
|
}
|
|
2956
3121
|
el.textContent = text;
|
|
2957
3122
|
}, []);
|
|
2958
|
-
|
|
3123
|
+
useEffect9(() => {
|
|
2959
3124
|
if (api.status === "submitting") announce(strings.submittingAnnouncement);
|
|
2960
3125
|
}, [api.status, announce, strings.submittingAnnouncement]);
|
|
2961
3126
|
const resuming = api.resumedDraft || api.editingPrevious;
|
|
2962
3127
|
const resumeAnnouncement = api.editingPrevious ? strings.editNotice : strings.resumeNotice;
|
|
2963
|
-
|
|
3128
|
+
useEffect9(() => {
|
|
2964
3129
|
if (resuming) announce(resumeAnnouncement);
|
|
2965
3130
|
}, [resuming, resumeAnnouncement, announce]);
|
|
2966
|
-
const themed =
|
|
3131
|
+
const themed = useMemo6(() => themeProps(theme), [theme]);
|
|
2967
3132
|
const warningCode = resyncWarning ? resyncWarning.code : props.syncWarningCode;
|
|
2968
3133
|
const warningUrl = resyncWarning ? resyncWarning.url : props.syncWarningUrl;
|
|
2969
3134
|
const uploadsAvailable = resyncWarning ? resyncWarning.uploadsAvailable : props.uploadsAvailable;
|
|
2970
3135
|
const uploadFileSizeLimitMb = resyncWarning ? resyncWarning.uploadFileSizeLimitMb : props.uploadFileSizeLimitMb;
|
|
2971
|
-
const chromeValue =
|
|
3136
|
+
const chromeValue = useMemo6(
|
|
2972
3137
|
() => ({
|
|
2973
3138
|
devChrome,
|
|
2974
3139
|
renderOnly,
|
|
@@ -2982,18 +3147,18 @@ function ResolvedForm(props) {
|
|
|
2982
3147
|
const settings = schema.settings;
|
|
2983
3148
|
const submitted = api.status === "submitted";
|
|
2984
3149
|
const liveSubmit = submitted && !api.restoredSubmission;
|
|
2985
|
-
|
|
3150
|
+
useEffect9(() => {
|
|
2986
3151
|
if (!liveSubmit || !settings.redirectUrl || typeof window === "undefined") return;
|
|
2987
3152
|
const url = safeHttpUrl(settings.redirectUrl);
|
|
2988
3153
|
if (url) window.location.assign(url);
|
|
2989
3154
|
}, [liveSubmit, settings.redirectUrl]);
|
|
2990
|
-
const successRef =
|
|
2991
|
-
|
|
3155
|
+
const successRef = useRef9(null);
|
|
3156
|
+
useEffect9(() => {
|
|
2992
3157
|
if (liveSubmit) successRef.current?.focus();
|
|
2993
3158
|
}, [liveSubmit]);
|
|
2994
|
-
const blocksRef =
|
|
2995
|
-
const prevPageIndex =
|
|
2996
|
-
|
|
3159
|
+
const blocksRef = useRef9(null);
|
|
3160
|
+
const prevPageIndex = useRef9(api.pageIndex);
|
|
3161
|
+
useEffect9(() => {
|
|
2997
3162
|
if (prevPageIndex.current === api.pageIndex) return;
|
|
2998
3163
|
prevPageIndex.current = api.pageIndex;
|
|
2999
3164
|
const container = blocksRef.current?.parentElement;
|
|
@@ -3005,7 +3170,7 @@ function ResolvedForm(props) {
|
|
|
3005
3170
|
}, [api.pageIndex]);
|
|
3006
3171
|
const appearance = props.appearance;
|
|
3007
3172
|
if (api.status === "submitted") {
|
|
3008
|
-
return /* @__PURE__ */
|
|
3173
|
+
return /* @__PURE__ */ jsxs7(
|
|
3009
3174
|
"div",
|
|
3010
3175
|
{
|
|
3011
3176
|
ref: successRef,
|
|
@@ -3022,7 +3187,7 @@ function ResolvedForm(props) {
|
|
|
3022
3187
|
"data-state": "submitted",
|
|
3023
3188
|
...themed,
|
|
3024
3189
|
children: [
|
|
3025
|
-
props.renderSuccess ? props.renderSuccess() : /* @__PURE__ */
|
|
3190
|
+
props.renderSuccess ? props.renderSuccess() : /* @__PURE__ */ jsxs7(
|
|
3026
3191
|
"div",
|
|
3027
3192
|
{
|
|
3028
3193
|
className: slotClass3("fillo-success", appearance, {
|
|
@@ -3031,13 +3196,13 @@ function ResolvedForm(props) {
|
|
|
3031
3196
|
}),
|
|
3032
3197
|
"data-fillo": "success",
|
|
3033
3198
|
children: [
|
|
3034
|
-
/* @__PURE__ */
|
|
3035
|
-
/* @__PURE__ */
|
|
3036
|
-
/* @__PURE__ */
|
|
3199
|
+
/* @__PURE__ */ jsx8("div", { className: "fillo-success-mark", "aria-hidden": "true" }),
|
|
3200
|
+
/* @__PURE__ */ jsx8("h2", { className: "fillo-success-title", children: settings.successTitle ?? strings.successTitle }),
|
|
3201
|
+
/* @__PURE__ */ jsx8("p", { className: "fillo-success-message", children: api.duplicateSubmission ? strings.alreadyAnswered : settings.successMessage ?? strings.successMessage })
|
|
3037
3202
|
]
|
|
3038
3203
|
}
|
|
3039
3204
|
),
|
|
3040
|
-
props.poweredBy && /* @__PURE__ */
|
|
3205
|
+
props.poweredBy && /* @__PURE__ */ jsx8(PoweredBy, { label: props.brandLabel, href: props.brandHref })
|
|
3041
3206
|
]
|
|
3042
3207
|
}
|
|
3043
3208
|
);
|
|
@@ -3058,8 +3223,8 @@ function ResolvedForm(props) {
|
|
|
3058
3223
|
slot: "root",
|
|
3059
3224
|
status: api.status
|
|
3060
3225
|
});
|
|
3061
|
-
const formBody = /* @__PURE__ */
|
|
3062
|
-
/* @__PURE__ */
|
|
3226
|
+
const formBody = /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
3227
|
+
/* @__PURE__ */ jsx8(
|
|
3063
3228
|
"span",
|
|
3064
3229
|
{
|
|
3065
3230
|
ref: announceRef,
|
|
@@ -3069,7 +3234,7 @@ function ResolvedForm(props) {
|
|
|
3069
3234
|
"data-fillo": "announce"
|
|
3070
3235
|
}
|
|
3071
3236
|
),
|
|
3072
|
-
devChrome && /* @__PURE__ */
|
|
3237
|
+
devChrome && /* @__PURE__ */ jsx8(
|
|
3073
3238
|
DevChrome,
|
|
3074
3239
|
{
|
|
3075
3240
|
preview: props.preview,
|
|
@@ -3081,18 +3246,18 @@ function ResolvedForm(props) {
|
|
|
3081
3246
|
noClient: !props.client && !props.skipValidation && !renderOnly
|
|
3082
3247
|
}
|
|
3083
3248
|
),
|
|
3084
|
-
resuming && /* @__PURE__ */
|
|
3249
|
+
resuming && /* @__PURE__ */ jsxs7(
|
|
3085
3250
|
"div",
|
|
3086
3251
|
{
|
|
3087
3252
|
className: slotClass3("fillo-resume", appearance, { slot: "resume" }),
|
|
3088
3253
|
"data-fillo": "resume",
|
|
3089
3254
|
children: [
|
|
3090
|
-
/* @__PURE__ */
|
|
3091
|
-
/* @__PURE__ */
|
|
3255
|
+
/* @__PURE__ */ jsx8("span", { className: "fillo-resume-text", children: api.editingPrevious ? strings.editNotice : strings.resumeNotice }),
|
|
3256
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "fillo-resume-clear", onClick: api.resetDraft, children: strings.resumeStartOver })
|
|
3092
3257
|
]
|
|
3093
3258
|
}
|
|
3094
3259
|
),
|
|
3095
|
-
api.resumeLinkFailed && !api.resumedDraft && !api.editingPrevious && /* @__PURE__ */
|
|
3260
|
+
api.resumeLinkFailed && !api.resumedDraft && !api.editingPrevious && /* @__PURE__ */ jsx8(
|
|
3096
3261
|
"div",
|
|
3097
3262
|
{
|
|
3098
3263
|
className: slotClass3("fillo-resume fillo-resume--expired", appearance, {
|
|
@@ -3100,10 +3265,10 @@ function ResolvedForm(props) {
|
|
|
3100
3265
|
}),
|
|
3101
3266
|
"data-fillo": "resume",
|
|
3102
3267
|
role: "status",
|
|
3103
|
-
children: /* @__PURE__ */
|
|
3268
|
+
children: /* @__PURE__ */ jsx8("span", { className: "fillo-resume-text", children: strings.resumeLinkExpired })
|
|
3104
3269
|
}
|
|
3105
3270
|
),
|
|
3106
|
-
multiPage && settings.showProgress !== false && /* @__PURE__ */
|
|
3271
|
+
multiPage && settings.showProgress !== false && /* @__PURE__ */ jsx8(
|
|
3107
3272
|
"div",
|
|
3108
3273
|
{
|
|
3109
3274
|
className: slotClass3("fillo-progress-track", appearance, { slot: "progress" }),
|
|
@@ -3113,7 +3278,7 @@ function ResolvedForm(props) {
|
|
|
3113
3278
|
"aria-valuemin": 1,
|
|
3114
3279
|
"aria-valuemax": progressTotal,
|
|
3115
3280
|
"aria-valuenow": progressStep,
|
|
3116
|
-
children: /* @__PURE__ */
|
|
3281
|
+
children: /* @__PURE__ */ jsx8(
|
|
3117
3282
|
"div",
|
|
3118
3283
|
{
|
|
3119
3284
|
className: slotClass3("fillo-progress-fill", appearance, { slot: "progressFill" }),
|
|
@@ -3125,13 +3290,13 @@ function ResolvedForm(props) {
|
|
|
3125
3290
|
)
|
|
3126
3291
|
}
|
|
3127
3292
|
),
|
|
3128
|
-
api.pageIndex === 0 && props.showTitle !== false && /* @__PURE__ */
|
|
3293
|
+
api.pageIndex === 0 && props.showTitle !== false && /* @__PURE__ */ jsxs7(
|
|
3129
3294
|
"header",
|
|
3130
3295
|
{
|
|
3131
3296
|
className: slotClass3("fillo-header", appearance, { slot: "header" }),
|
|
3132
3297
|
"data-fillo": "header",
|
|
3133
3298
|
children: [
|
|
3134
|
-
schema.title && /* @__PURE__ */
|
|
3299
|
+
schema.title && /* @__PURE__ */ jsx8(
|
|
3135
3300
|
"h1",
|
|
3136
3301
|
{
|
|
3137
3302
|
className: slotClass3("fillo-title", appearance, { slot: "title" }),
|
|
@@ -3139,7 +3304,7 @@ function ResolvedForm(props) {
|
|
|
3139
3304
|
children: schema.title
|
|
3140
3305
|
}
|
|
3141
3306
|
),
|
|
3142
|
-
schema.description && /* @__PURE__ */
|
|
3307
|
+
schema.description && /* @__PURE__ */ jsx8(
|
|
3143
3308
|
"p",
|
|
3144
3309
|
{
|
|
3145
3310
|
className: slotClass3("fillo-form-description", appearance, { slot: "description" }),
|
|
@@ -3150,7 +3315,7 @@ function ResolvedForm(props) {
|
|
|
3150
3315
|
]
|
|
3151
3316
|
}
|
|
3152
3317
|
),
|
|
3153
|
-
multiPage && api.page.title && api.pageIndex > 0 && /* @__PURE__ */
|
|
3318
|
+
multiPage && api.page.title && api.pageIndex > 0 && /* @__PURE__ */ jsx8(
|
|
3154
3319
|
"h2",
|
|
3155
3320
|
{
|
|
3156
3321
|
className: slotClass3("fillo-page-title", appearance, { slot: "pageTitle" }),
|
|
@@ -3158,14 +3323,14 @@ function ResolvedForm(props) {
|
|
|
3158
3323
|
children: api.page.title
|
|
3159
3324
|
}
|
|
3160
3325
|
),
|
|
3161
|
-
/* @__PURE__ */
|
|
3326
|
+
/* @__PURE__ */ jsx8(
|
|
3162
3327
|
"div",
|
|
3163
3328
|
{
|
|
3164
3329
|
className: slotClass3("fillo-blocks", appearance, { slot: "blocks" }),
|
|
3165
3330
|
"data-fillo": "blocks",
|
|
3166
3331
|
ref: blocksRef,
|
|
3167
3332
|
tabIndex: -1,
|
|
3168
|
-
children: api.blocks.map((block) => /* @__PURE__ */
|
|
3333
|
+
children: api.blocks.map((block) => /* @__PURE__ */ jsx8(
|
|
3169
3334
|
BlockRenderer,
|
|
3170
3335
|
{
|
|
3171
3336
|
block,
|
|
@@ -3177,7 +3342,7 @@ function ResolvedForm(props) {
|
|
|
3177
3342
|
))
|
|
3178
3343
|
}
|
|
3179
3344
|
),
|
|
3180
|
-
!displayOnly && /* @__PURE__ */
|
|
3345
|
+
!displayOnly && /* @__PURE__ */ jsx8(
|
|
3181
3346
|
"input",
|
|
3182
3347
|
{
|
|
3183
3348
|
type: "text",
|
|
@@ -3194,8 +3359,8 @@ function ResolvedForm(props) {
|
|
|
3194
3359
|
}
|
|
3195
3360
|
}
|
|
3196
3361
|
),
|
|
3197
|
-
challenge && showChallenge && /* @__PURE__ */
|
|
3198
|
-
/* @__PURE__ */
|
|
3362
|
+
challenge && showChallenge && /* @__PURE__ */ jsxs7("div", { className: "fillo-turnstile-slot", "data-fillo": "turnstile-slot", children: [
|
|
3363
|
+
/* @__PURE__ */ jsx8(
|
|
3199
3364
|
TurnstileWidget,
|
|
3200
3365
|
{
|
|
3201
3366
|
siteKey: challenge.siteKey,
|
|
@@ -3205,24 +3370,24 @@ function ResolvedForm(props) {
|
|
|
3205
3370
|
registerReset: registerChallengeReset
|
|
3206
3371
|
}
|
|
3207
3372
|
),
|
|
3208
|
-
challengeError && /* @__PURE__ */
|
|
3373
|
+
challengeError && /* @__PURE__ */ jsx8("p", { className: "fillo-turnstile-error", role: "alert", children: strings.challengeUnavailable })
|
|
3209
3374
|
] }),
|
|
3210
|
-
(api.status === "error" || api.submitError) && /* @__PURE__ */
|
|
3375
|
+
(api.status === "error" || api.submitError) && /* @__PURE__ */ jsxs7("p", { className: "fillo-submit-error", role: "alert", children: [
|
|
3211
3376
|
api.submitError ?? strings.submitFailed,
|
|
3212
|
-
submitFixUrl && /* @__PURE__ */
|
|
3377
|
+
submitFixUrl && /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
3213
3378
|
" ",
|
|
3214
3379
|
"Connect storage:",
|
|
3215
3380
|
" ",
|
|
3216
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsx8("a", { href: submitFixUrl, target: "_blank", rel: "noopener noreferrer", children: submitFixUrl })
|
|
3217
3382
|
] })
|
|
3218
3383
|
] }),
|
|
3219
|
-
showFooter && /* @__PURE__ */
|
|
3384
|
+
showFooter && /* @__PURE__ */ jsxs7(
|
|
3220
3385
|
"footer",
|
|
3221
3386
|
{
|
|
3222
3387
|
className: slotClass3("fillo-footer", appearance, { slot: "footer" }),
|
|
3223
3388
|
"data-fillo": "footer",
|
|
3224
3389
|
children: [
|
|
3225
|
-
multiPage && !api.isFirstPage && /* @__PURE__ */
|
|
3390
|
+
multiPage && !api.isFirstPage && /* @__PURE__ */ jsx8(
|
|
3226
3391
|
"button",
|
|
3227
3392
|
{
|
|
3228
3393
|
type: "button",
|
|
@@ -3235,7 +3400,7 @@ function ResolvedForm(props) {
|
|
|
3235
3400
|
children: strings.back
|
|
3236
3401
|
}
|
|
3237
3402
|
),
|
|
3238
|
-
showPrimaryButton && /* @__PURE__ */
|
|
3403
|
+
showPrimaryButton && /* @__PURE__ */ jsx8(
|
|
3239
3404
|
"button",
|
|
3240
3405
|
{
|
|
3241
3406
|
type: "submit",
|
|
@@ -3254,23 +3419,23 @@ function ResolvedForm(props) {
|
|
|
3254
3419
|
]
|
|
3255
3420
|
}
|
|
3256
3421
|
),
|
|
3257
|
-
props.poweredBy && /* @__PURE__ */
|
|
3422
|
+
props.poweredBy && /* @__PURE__ */ jsx8(PoweredBy, { label: props.brandLabel, href: props.brandHref })
|
|
3258
3423
|
] });
|
|
3259
|
-
return /* @__PURE__ */
|
|
3424
|
+
return /* @__PURE__ */ jsx8(FilloContext.Provider, { value: api, children: /* @__PURE__ */ jsx8(FilloChromeContext.Provider, { value: chromeValue, children: /* @__PURE__ */ jsx8(FilloAnnounceContext.Provider, { value: announce, children: /* @__PURE__ */ jsx8(FilloStringsContext.Provider, { value: strings, children: /* @__PURE__ */ jsx8(FilloAppearanceContext.Provider, { value: appearance, children: /* @__PURE__ */ jsx8(FilloInstanceIdContext.Provider, { value: instanceId, children: displayOnly ? (
|
|
3260
3425
|
// Display-only preview: a plain div (no form element to submit) with
|
|
3261
3426
|
// every control inside a natively disabled fieldset — unfocusable
|
|
3262
3427
|
// and unfillable even without the stylesheet or inert support.
|
|
3263
|
-
/* @__PURE__ */
|
|
3428
|
+
/* @__PURE__ */ jsx8(
|
|
3264
3429
|
"div",
|
|
3265
3430
|
{
|
|
3266
3431
|
className: rootClass,
|
|
3267
3432
|
"data-fillo": "preview-form",
|
|
3268
3433
|
"data-state": "preview",
|
|
3269
3434
|
...themed,
|
|
3270
|
-
children: /* @__PURE__ */
|
|
3435
|
+
children: /* @__PURE__ */ jsx8("fieldset", { disabled: true, className: "fillo-not-open-fields", children: formBody })
|
|
3271
3436
|
}
|
|
3272
3437
|
)
|
|
3273
|
-
) : /* @__PURE__ */
|
|
3438
|
+
) : /* @__PURE__ */ jsx8(
|
|
3274
3439
|
"form",
|
|
3275
3440
|
{
|
|
3276
3441
|
className: rootClass,
|
|
@@ -3298,21 +3463,21 @@ function ResolvedForm(props) {
|
|
|
3298
3463
|
}
|
|
3299
3464
|
|
|
3300
3465
|
// src/jsx.tsx
|
|
3301
|
-
import { useRef as
|
|
3466
|
+
import { useRef as useRef10 } from "react";
|
|
3302
3467
|
import {
|
|
3303
3468
|
codeFormFromJsx,
|
|
3304
3469
|
FilloJsxError,
|
|
3305
3470
|
isLikelyDevEnv as isLikelyDevEnv2,
|
|
3306
3471
|
JSX_BLOCK_COMPONENTS
|
|
3307
3472
|
} from "@usefillo/core";
|
|
3308
|
-
import { jsx as
|
|
3473
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
3309
3474
|
var B = JSX_BLOCK_COMPONENTS;
|
|
3310
3475
|
var isDevEnv = () => isLikelyDevEnv2();
|
|
3311
3476
|
function JsxForm(props) {
|
|
3312
3477
|
const { id, title, description, settings, theme, client, children, ...rest } = props;
|
|
3313
3478
|
const compiled = codeFormFromJsx({ id, title, description, settings, theme }, children);
|
|
3314
3479
|
const json = JSON.stringify(compiled.schema) + JSON.stringify(compiled.theme ?? null);
|
|
3315
|
-
const memo2 =
|
|
3480
|
+
const memo2 = useRef10(null);
|
|
3316
3481
|
if (memo2.current && memo2.current.json !== json && isDevEnv()) {
|
|
3317
3482
|
console.warn(
|
|
3318
3483
|
`[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.`
|
|
@@ -3321,7 +3486,7 @@ function JsxForm(props) {
|
|
|
3321
3486
|
if (!memo2.current || memo2.current.json !== json) {
|
|
3322
3487
|
memo2.current = { json, form: compiled };
|
|
3323
3488
|
}
|
|
3324
|
-
return /* @__PURE__ */
|
|
3489
|
+
return /* @__PURE__ */ jsx9(FilloForm, { ...{ form: memo2.current.form, client, ...rest } });
|
|
3325
3490
|
}
|
|
3326
3491
|
function defineFormFromJsx(element) {
|
|
3327
3492
|
if (!element || element.type !== JsxForm) {
|
|
@@ -3366,7 +3531,7 @@ var Fillo = {
|
|
|
3366
3531
|
};
|
|
3367
3532
|
|
|
3368
3533
|
// src/provider.tsx
|
|
3369
|
-
import { useEffect as
|
|
3534
|
+
import { useEffect as useEffect10, useId as useId3, useMemo as useMemo7, useState as useState7 } from "react";
|
|
3370
3535
|
import {
|
|
3371
3536
|
FilloError as FilloError3,
|
|
3372
3537
|
createClient as createClient2,
|
|
@@ -3376,7 +3541,7 @@ import {
|
|
|
3376
3541
|
resolveStrings as resolveStrings2,
|
|
3377
3542
|
syncCodeForm as syncCodeForm3
|
|
3378
3543
|
} from "@usefillo/core";
|
|
3379
|
-
import { Fragment as Fragment4, jsx as
|
|
3544
|
+
import { Fragment as Fragment4, jsx as jsx10 } from "react/jsx-runtime";
|
|
3380
3545
|
function FilloProvider({
|
|
3381
3546
|
children,
|
|
3382
3547
|
form,
|
|
@@ -3392,7 +3557,7 @@ function FilloProvider({
|
|
|
3392
3557
|
...options
|
|
3393
3558
|
}) {
|
|
3394
3559
|
const localPreview = renderOnly === true || skipValidation === true;
|
|
3395
|
-
const activeClient =
|
|
3560
|
+
const activeClient = useMemo7(
|
|
3396
3561
|
() => localPreview ? void 0 : client ?? (formId ? createClient2() : void 0),
|
|
3397
3562
|
[client, formId, localPreview]
|
|
3398
3563
|
);
|
|
@@ -3402,7 +3567,7 @@ function FilloProvider({
|
|
|
3402
3567
|
const devChrome = preview === true || devEnv;
|
|
3403
3568
|
if (preview === true) warnPreviewInProduction();
|
|
3404
3569
|
const codeForm = isCodeForm2(form) ? form : null;
|
|
3405
|
-
const targetError =
|
|
3570
|
+
const targetError = useMemo7(
|
|
3406
3571
|
() => !formId && !localPreview && (!codeForm || !client) ? new FilloError3(
|
|
3407
3572
|
"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.",
|
|
3408
3573
|
422,
|
|
@@ -3411,7 +3576,7 @@ function FilloProvider({
|
|
|
3411
3576
|
) : null,
|
|
3412
3577
|
[client, codeForm, formId, localPreview]
|
|
3413
3578
|
);
|
|
3414
|
-
|
|
3579
|
+
useEffect10(() => {
|
|
3415
3580
|
if (targetError) onError?.(targetError);
|
|
3416
3581
|
}, [onError, targetError]);
|
|
3417
3582
|
const {
|
|
@@ -3431,12 +3596,12 @@ function FilloProvider({
|
|
|
3431
3596
|
});
|
|
3432
3597
|
const [resyncWarning, setResyncWarning] = useState7(null);
|
|
3433
3598
|
const rawSchema = codeForm ? resolvedSchema && !devChrome ? resolvedSchema : codeForm.schema : form;
|
|
3434
|
-
const normalized =
|
|
3599
|
+
const normalized = useMemo7(() => normalizeFormSchema2(rawSchema), [rawSchema]);
|
|
3435
3600
|
if (!normalized.ok) {
|
|
3436
3601
|
throw new FilloError3(`This form could not be rendered: ${normalized.error}`, 422);
|
|
3437
3602
|
}
|
|
3438
3603
|
const schema = normalized.schema;
|
|
3439
|
-
const resolveFormId =
|
|
3604
|
+
const resolveFormId = useMemo7(
|
|
3440
3605
|
() => codeForm && activeClient?.key ? async () => {
|
|
3441
3606
|
try {
|
|
3442
3607
|
const result = await syncCodeForm3(activeClient, codeForm, { bypassCache: true });
|
|
@@ -3522,7 +3687,7 @@ function FilloProvider({
|
|
|
3522
3687
|
const freshWarningUrl = resyncWarning ? resyncWarning.url : warningUrl;
|
|
3523
3688
|
const freshUploadsAvailable = resyncWarning ? resyncWarning.uploadsAvailable : uploadsAvailable;
|
|
3524
3689
|
const freshUploadFileSizeLimitMb = resyncWarning ? resyncWarning.uploadFileSizeLimitMb : uploadFileSizeLimitMb;
|
|
3525
|
-
const chromeValue =
|
|
3690
|
+
const chromeValue = useMemo7(
|
|
3526
3691
|
() => ({
|
|
3527
3692
|
devChrome,
|
|
3528
3693
|
renderOnly: localPreview,
|
|
@@ -3542,11 +3707,11 @@ function FilloProvider({
|
|
|
3542
3707
|
);
|
|
3543
3708
|
const resolvedStrings = resolveStrings2(strings);
|
|
3544
3709
|
if (targetError) {
|
|
3545
|
-
if (renderError) return /* @__PURE__ */
|
|
3710
|
+
if (renderError) return /* @__PURE__ */ jsx10(Fragment4, { children: renderError(targetError) });
|
|
3546
3711
|
throw targetError;
|
|
3547
3712
|
}
|
|
3548
3713
|
const canonicalSyncError = syncError && !localPreview ? syncError : null;
|
|
3549
|
-
if (canonicalSyncError && renderError) return /* @__PURE__ */
|
|
3714
|
+
if (canonicalSyncError && renderError) return /* @__PURE__ */ jsx10(Fragment4, { children: renderError(canonicalSyncError) });
|
|
3550
3715
|
if (canonicalSyncError && !devChrome) return null;
|
|
3551
3716
|
if (codeFormSyncing && !localPreview && !devChrome) return null;
|
|
3552
3717
|
const notPublished = Boolean(codeForm) && syncedStatus === "draft" && !localPreview;
|
|
@@ -3558,9 +3723,9 @@ function FilloProvider({
|
|
|
3558
3723
|
void 0,
|
|
3559
3724
|
syncedAcceptingReason ?? "form_not_accepting"
|
|
3560
3725
|
);
|
|
3561
|
-
return renderError ? /* @__PURE__ */
|
|
3726
|
+
return renderError ? /* @__PURE__ */ jsx10(Fragment4, { children: renderError(error) }) : null;
|
|
3562
3727
|
}
|
|
3563
|
-
return /* @__PURE__ */
|
|
3728
|
+
return /* @__PURE__ */ jsx10(FilloContext.Provider, { value: api, children: /* @__PURE__ */ jsx10(FilloChromeContext.Provider, { value: chromeValue, children: /* @__PURE__ */ jsx10(FilloStringsContext.Provider, { value: resolvedStrings, children: /* @__PURE__ */ jsx10(FilloAppearanceContext.Provider, { value: appearance, children: /* @__PURE__ */ jsx10(FilloInstanceIdContext.Provider, { value: instanceId, children }) }) }) }) });
|
|
3564
3729
|
}
|
|
3565
3730
|
|
|
3566
3731
|
// src/index.ts
|