@10x-media/form-builder 0.1.0-beta.0 → 0.1.0-beta.1
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/CHANGELOG.md +52 -0
- package/README.md +43 -1402
- package/dist/actions/buildActionBlocks.js +19 -0
- package/dist/actions/buildActionBlocks.js.map +1 -0
- package/dist/actions/builtin/confirmation.js +49 -0
- package/dist/actions/builtin/confirmation.js.map +1 -0
- package/dist/actions/builtin/emailTeam.js +46 -0
- package/dist/actions/builtin/emailTeam.js.map +1 -0
- package/dist/actions/builtin/index.d.ts +7 -0
- package/dist/actions/builtin/index.js +13 -0
- package/dist/actions/builtin/index.js.map +1 -0
- package/dist/actions/builtin/signedWebhook.js +49 -0
- package/dist/actions/builtin/signedWebhook.js.map +1 -0
- package/dist/actions/defineAction.d.ts +36 -0
- package/dist/actions/defineAction.js +6 -0
- package/dist/actions/defineAction.js.map +1 -0
- package/dist/actions/dispatch.js +48 -0
- package/dist/actions/dispatch.js.map +1 -0
- package/dist/actions/registry.d.ts +16 -0
- package/dist/actions/registry.js +16 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/actions/runActions.d.ts +9 -0
- package/dist/actions/runActions.js +34 -0
- package/dist/actions/runActions.js.map +1 -0
- package/dist/actions/sign.d.ts +7 -0
- package/dist/actions/sign.js +9 -0
- package/dist/actions/sign.js.map +1 -0
- package/dist/actions/task.js +82 -0
- package/dist/actions/task.js.map +1 -0
- package/dist/aggregation/aggregateResponses.d.ts +31 -0
- package/dist/aggregation/aggregateResponses.js +86 -0
- package/dist/aggregation/aggregateResponses.js.map +1 -0
- package/dist/aggregation/aggregateRows.d.ts +10 -0
- package/dist/aggregation/aggregateRows.js +64 -0
- package/dist/aggregation/aggregateRows.js.map +1 -0
- package/dist/aggregation/resolveResultsRequest.d.ts +32 -0
- package/dist/aggregation/resolveResultsRequest.js +56 -0
- package/dist/aggregation/resolveResultsRequest.js.map +1 -0
- package/dist/aggregation/types.d.ts +39 -0
- package/dist/calc/computeCalcFields.d.ts +15 -0
- package/dist/calc/computeCalcFields.js +27 -0
- package/dist/calc/computeCalcFields.js.map +1 -0
- package/dist/calc/evaluate.d.ts +8 -0
- package/dist/calc/evaluate.js +59 -0
- package/dist/calc/evaluate.js.map +1 -0
- package/dist/calc/normalizeCalc.d.ts +8 -0
- package/dist/calc/normalizeCalc.js +100 -0
- package/dist/calc/normalizeCalc.js.map +1 -0
- package/dist/calc/types.d.ts +28 -0
- package/dist/client/ConditionBuilder.js +121 -0
- package/dist/client/ConditionBuilder.js.map +1 -0
- package/dist/client/ConditionRow.js +150 -0
- package/dist/client/ConditionRow.js.map +1 -0
- package/dist/client/FlowBuilder.d.ts +15 -0
- package/dist/client/FlowBuilder.js +408 -0
- package/dist/client/FlowBuilder.js.map +1 -0
- package/dist/client/FormConditionField.d.ts +21 -0
- package/dist/client/FormConditionField.js +33 -0
- package/dist/client/FormConditionField.js.map +1 -0
- package/dist/client/synthesizeClientField.js +46 -0
- package/dist/client/synthesizeClientField.js.map +1 -0
- package/dist/collections/formSubmissions.js +138 -0
- package/dist/collections/formSubmissions.js.map +1 -0
- package/dist/collections/forms.js +187 -0
- package/dist/collections/forms.js.map +1 -0
- package/dist/collections/uploads.d.ts +29 -0
- package/dist/collections/uploads.js +46 -0
- package/dist/collections/uploads.js.map +1 -0
- package/dist/conditions/conditionType.js +14 -0
- package/dist/conditions/conditionType.js.map +1 -0
- package/dist/conditions/evaluate.d.ts +17 -0
- package/dist/conditions/evaluate.js +94 -0
- package/dist/conditions/evaluate.js.map +1 -0
- package/dist/conditions/fieldTypes.d.ts +9 -0
- package/dist/{fieldTypes-CzhhJXjg.js → conditions/fieldTypes.js} +2 -2
- package/dist/conditions/fieldTypes.js.map +1 -0
- package/dist/conditions/normalizeConditions.js +47 -0
- package/dist/conditions/normalizeConditions.js.map +1 -0
- package/dist/conditions/types.d.ts +8 -0
- package/dist/consent/buildConsentSourceConfig.js +49 -0
- package/dist/consent/buildConsentSourceConfig.js.map +1 -0
- package/dist/consent/builtin/index.d.ts +7 -0
- package/dist/consent/builtin/index.js +11 -0
- package/dist/consent/builtin/index.js.map +1 -0
- package/dist/consent/builtin/pageReference.js +75 -0
- package/dist/consent/builtin/pageReference.js.map +1 -0
- package/dist/consent/builtin/static.js +44 -0
- package/dist/consent/builtin/static.js.map +1 -0
- package/dist/consent/captureConsent.d.ts +28 -0
- package/dist/consent/captureConsent.js +26 -0
- package/dist/consent/captureConsent.js.map +1 -0
- package/dist/consent/defineConsentSource.d.ts +35 -0
- package/dist/consent/defineConsentSource.js +6 -0
- package/dist/consent/defineConsentSource.js.map +1 -0
- package/dist/consent/registry.d.ts +16 -0
- package/dist/consent/registry.js +16 -0
- package/dist/consent/registry.js.map +1 -0
- package/dist/consent/resolveConsentLinks.d.ts +19 -0
- package/dist/consent/resolveConsentLinks.js +26 -0
- package/dist/consent/resolveConsentLinks.js.map +1 -0
- package/dist/consent/resolvePublishedVersionRef.d.ts +17 -0
- package/dist/consent/resolvePublishedVersionRef.js +27 -0
- package/dist/consent/resolvePublishedVersionRef.js.map +1 -0
- package/dist/events/noopSink.js +6 -0
- package/dist/events/noopSink.js.map +1 -0
- package/dist/events/resolveEventSink.js +8 -0
- package/dist/events/resolveEventSink.js.map +1 -0
- package/dist/events/types.d.ts +31 -0
- package/dist/exports/client.d.ts +3 -21
- package/dist/exports/client.js +3 -319
- package/dist/exports/i18n.d.ts +3 -138
- package/dist/exports/i18n.js +2 -2
- package/dist/exports/react.d.ts +45 -550
- package/dist/exports/react.js +39 -1563
- package/dist/exports/rsc.d.ts +2 -16
- package/dist/exports/rsc.js +1 -54
- package/dist/exports/types.d.ts +27 -5
- package/dist/fields/buildFieldBlocks.js +46 -0
- package/dist/fields/buildFieldBlocks.js.map +1 -0
- package/dist/fields/builtin/calculation.js +24 -0
- package/dist/fields/builtin/calculation.js.map +1 -0
- package/dist/fields/builtin/checkbox.js +13 -0
- package/dist/fields/builtin/checkbox.js.map +1 -0
- package/dist/fields/builtin/consent.js +32 -0
- package/dist/fields/builtin/consent.js.map +1 -0
- package/dist/fields/builtin/email.js +18 -0
- package/dist/fields/builtin/email.js.map +1 -0
- package/dist/fields/builtin/file.js +40 -0
- package/dist/fields/builtin/file.js.map +1 -0
- package/dist/fields/builtin/index.js +25 -0
- package/dist/fields/builtin/index.js.map +1 -0
- package/dist/fields/builtin/number.js +17 -0
- package/dist/fields/builtin/number.js.map +1 -0
- package/dist/fields/builtin/select.js +44 -0
- package/dist/fields/builtin/select.js.map +1 -0
- package/dist/fields/builtin/text.js +13 -0
- package/dist/fields/builtin/text.js.map +1 -0
- package/dist/fields/builtin/textarea.js +13 -0
- package/dist/fields/builtin/textarea.js.map +1 -0
- package/dist/fields/defineFormField.d.ts +13 -0
- package/dist/fields/defineFormField.js +12 -0
- package/dist/fields/defineFormField.js.map +1 -0
- package/dist/fields/registry.d.ts +10 -0
- package/dist/fields/registry.js +24 -0
- package/dist/fields/registry.js.map +1 -0
- package/dist/fields/sharedConfig.js +89 -0
- package/dist/fields/sharedConfig.js.map +1 -0
- package/dist/fields/types.d.ts +88 -0
- package/dist/flow/engine.d.ts +17 -0
- package/dist/flow/engine.js +24 -0
- package/dist/flow/engine.js.map +1 -0
- package/dist/flow/normalizeFlow.js +35 -0
- package/dist/flow/normalizeFlow.js.map +1 -0
- package/dist/{types-DsJ_6kGJ.d.ts → flow/types.d.ts} +2 -2
- package/dist/index.d.ts +74 -4
- package/dist/index.js +40 -1889
- package/dist/index.js.map +1 -1
- package/dist/plugin/access.js +12 -0
- package/dist/plugin/access.js.map +1 -0
- package/dist/plugin/registerCollections.js +40 -0
- package/dist/plugin/registerCollections.js.map +1 -0
- package/dist/plugin/registerTranslations.js +19 -0
- package/dist/plugin/registerTranslations.js.map +1 -0
- package/dist/prefill/valuesFromSearchParams.d.ts +18 -0
- package/dist/prefill/valuesFromSearchParams.js +45 -0
- package/dist/prefill/valuesFromSearchParams.js.map +1 -0
- package/dist/presentations/defaults.d.ts +33 -0
- package/dist/presentations/defaults.js +35 -0
- package/dist/presentations/defaults.js.map +1 -0
- package/dist/presentations/registry.d.ts +15 -0
- package/dist/presentations/registry.js +15 -0
- package/dist/presentations/registry.js.map +1 -0
- package/dist/presentations/types.d.ts +18 -0
- package/dist/react/Form.d.ts +81 -0
- package/dist/react/Form.js +457 -0
- package/dist/react/Form.js.map +1 -0
- package/dist/react/FormContext.d.ts +16 -0
- package/dist/react/FormContext.js +14 -0
- package/dist/react/FormContext.js.map +1 -0
- package/dist/react/FormLayout.d.ts +20 -0
- package/dist/react/FormLayout.js +14 -0
- package/dist/react/FormLayout.js.map +1 -0
- package/dist/react/FormResults.d.ts +25 -0
- package/dist/react/FormResults.js +85 -0
- package/dist/react/FormResults.js.map +1 -0
- package/dist/react/Honeypot.d.ts +22 -0
- package/dist/react/Honeypot.js +38 -0
- package/dist/react/Honeypot.js.map +1 -0
- package/dist/react/Poll.d.ts +32 -0
- package/dist/react/Poll.js +77 -0
- package/dist/react/Poll.js.map +1 -0
- package/dist/react/cn.d.ts +6 -0
- package/dist/react/cn.js +8 -0
- package/dist/react/cn.js.map +1 -0
- package/dist/react/contract.d.ts +32 -0
- package/dist/react/contract.js +7 -0
- package/dist/react/contract.js.map +1 -0
- package/dist/react/events.js +14 -0
- package/dist/react/events.js.map +1 -0
- package/dist/react/fetchResults.d.ts +25 -0
- package/dist/react/fetchResults.js +31 -0
- package/dist/react/fetchResults.js.map +1 -0
- package/dist/react/presentation/Backdrop.d.ts +18 -0
- package/dist/react/presentation/Backdrop.js +14 -0
- package/dist/react/presentation/Backdrop.js.map +1 -0
- package/dist/react/presentation/DialogSurface.d.ts +35 -0
- package/dist/react/presentation/DialogSurface.js +56 -0
- package/dist/react/presentation/DialogSurface.js.map +1 -0
- package/dist/react/presentation/presentations.d.ts +7 -0
- package/dist/react/presentation/presentations.js +32 -0
- package/dist/react/presentation/presentations.js.map +1 -0
- package/dist/react/presentation/registry.d.ts +11 -0
- package/dist/react/presentation/registry.js +12 -0
- package/dist/react/presentation/registry.js.map +1 -0
- package/dist/react/presentation/types.d.ts +19 -0
- package/dist/react/presentation/useDismiss.d.ts +19 -0
- package/dist/react/presentation/useDismiss.js +33 -0
- package/dist/react/presentation/useDismiss.js.map +1 -0
- package/dist/react/presentation/useFocusTrap.d.ts +8 -0
- package/dist/react/presentation/useFocusTrap.js +35 -0
- package/dist/react/presentation/useFocusTrap.js.map +1 -0
- package/dist/react/presentation/useScrollLock.d.ts +6 -0
- package/dist/react/presentation/useScrollLock.js +18 -0
- package/dist/react/presentation/useScrollLock.js.map +1 -0
- package/dist/react/primitives/Checkbox.d.ts +26 -0
- package/dist/react/primitives/Checkbox.js +20 -0
- package/dist/react/primitives/Checkbox.js.map +1 -0
- package/dist/react/primitives/FieldShell.d.ts +31 -0
- package/dist/react/primitives/FieldShell.js +51 -0
- package/dist/react/primitives/FieldShell.js.map +1 -0
- package/dist/react/primitives/Input.d.ts +30 -0
- package/dist/react/primitives/Input.js +21 -0
- package/dist/react/primitives/Input.js.map +1 -0
- package/dist/react/primitives/Select.d.ts +34 -0
- package/dist/react/primitives/Select.js +26 -0
- package/dist/react/primitives/Select.js.map +1 -0
- package/dist/react/primitives/Textarea.d.ts +28 -0
- package/dist/react/primitives/Textarea.js +20 -0
- package/dist/react/primitives/Textarea.js.map +1 -0
- package/dist/react/recall.js +20 -0
- package/dist/react/recall.js.map +1 -0
- package/dist/react/registry.d.ts +16 -0
- package/dist/react/registry.js +16 -0
- package/dist/react/registry.js.map +1 -0
- package/dist/react/renderers/calculation.js +30 -0
- package/dist/react/renderers/calculation.js.map +1 -0
- package/dist/react/renderers/checkbox.js +35 -0
- package/dist/react/renderers/checkbox.js.map +1 -0
- package/dist/react/renderers/consent.js +54 -0
- package/dist/react/renderers/consent.js.map +1 -0
- package/dist/react/renderers/email.js +37 -0
- package/dist/react/renderers/email.js.map +1 -0
- package/dist/react/renderers/file.js +92 -0
- package/dist/react/renderers/file.js.map +1 -0
- package/dist/react/renderers/index.d.ts +8 -0
- package/dist/react/renderers/index.js +26 -0
- package/dist/react/renderers/index.js.map +1 -0
- package/dist/react/renderers/number.js +40 -0
- package/dist/react/renderers/number.js.map +1 -0
- package/dist/react/renderers/select.js +38 -0
- package/dist/react/renderers/select.js.map +1 -0
- package/dist/react/renderers/text.js +37 -0
- package/dist/react/renderers/text.js.map +1 -0
- package/dist/react/renderers/textarea.js +36 -0
- package/dist/react/renderers/textarea.js.map +1 -0
- package/dist/react/resolveForm.js +16 -0
- package/dist/react/resolveForm.js.map +1 -0
- package/dist/react/state.d.ts +15 -0
- package/dist/react/state.js +70 -0
- package/dist/react/state.js.map +1 -0
- package/dist/react/submitForm.d.ts +31 -0
- package/dist/react/submitForm.js +58 -0
- package/dist/react/submitForm.js.map +1 -0
- package/dist/react/toFormDocument.d.ts +24 -0
- package/dist/react/toFormDocument.js +22 -0
- package/dist/react/toFormDocument.js.map +1 -0
- package/dist/react/uploadFile.d.ts +23 -0
- package/dist/react/uploadFile.js +39 -0
- package/dist/react/uploadFile.js.map +1 -0
- package/dist/react/useField.d.ts +14 -0
- package/dist/react/useField.js +49 -0
- package/dist/react/useField.js.map +1 -0
- package/dist/react/useFormState.d.ts +8 -0
- package/dist/react/useFormState.js +9 -0
- package/dist/react/useFormState.js.map +1 -0
- package/dist/react/useFormStep.d.ts +8 -0
- package/dist/react/useFormStep.js +9 -0
- package/dist/react/useFormStep.js.map +1 -0
- package/dist/react/validateField.js +30 -0
- package/dist/react/validateField.js.map +1 -0
- package/dist/recall/interpolate.d.ts +10 -0
- package/dist/recall/interpolate.js +16 -0
- package/dist/recall/interpolate.js.map +1 -0
- package/dist/recall/resolver.d.ts +22 -0
- package/dist/recall/resolver.js +36 -0
- package/dist/recall/resolver.js.map +1 -0
- package/dist/spam/captcha.d.ts +12 -0
- package/dist/spam/captcha.js +11 -0
- package/dist/spam/captcha.js.map +1 -0
- package/dist/spam/constants.d.ts +12 -0
- package/dist/spam/constants.js +15 -0
- package/dist/spam/constants.js.map +1 -0
- package/dist/spam/identify.d.ts +12 -0
- package/dist/spam/identify.js +20 -0
- package/dist/spam/identify.js.map +1 -0
- package/dist/spam/rateLimiter.d.ts +18 -0
- package/dist/spam/rateLimiter.js +41 -0
- package/dist/spam/rateLimiter.js.map +1 -0
- package/dist/spam/reserved.js +30 -0
- package/dist/spam/reserved.js.map +1 -0
- package/dist/spam/resolveSpam.d.ts +12 -0
- package/dist/spam/resolveSpam.js +42 -0
- package/dist/spam/resolveSpam.js.map +1 -0
- package/dist/spam/spamGuard.js +68 -0
- package/dist/spam/spamGuard.js.map +1 -0
- package/dist/spam/types.d.ts +73 -0
- package/dist/spam/uploadHooks.js +33 -0
- package/dist/spam/uploadHooks.js.map +1 -0
- package/dist/submissions/SubmissionAnswers.d.ts +16 -0
- package/dist/submissions/SubmissionAnswers.js +57 -0
- package/dist/submissions/SubmissionAnswers.js.map +1 -0
- package/dist/submissions/runSubmission.js +205 -0
- package/dist/submissions/runSubmission.js.map +1 -0
- package/dist/submissions/types.d.ts +33 -0
- package/dist/submissions/validateSubmission.js +59 -0
- package/dist/submissions/validateSubmission.js.map +1 -0
- package/dist/translations/en.d.ts +12 -0
- package/dist/{translations-edMqq_2e.js → translations/en.js} +3 -22
- package/dist/translations/en.js.map +1 -0
- package/dist/translations/index.d.ts +14 -0
- package/dist/translations/index.js +26 -0
- package/dist/translations/index.js.map +1 -0
- package/dist/translations/keys.d.ts +132 -0
- package/dist/{keys-N5xGiUsh.js → translations/keys.js} +2 -2
- package/dist/translations/keys.js.map +1 -0
- package/dist/translations/makeTranslate.d.ts +11 -0
- package/dist/translations/makeTranslate.js +11 -0
- package/dist/translations/makeTranslate.js.map +1 -0
- package/dist/translations/server.js +25 -0
- package/dist/translations/server.js.map +1 -0
- package/dist/translations/useTranslation.js +12 -0
- package/dist/translations/useTranslation.js.map +1 -0
- package/dist/uploads/captureFileRef.d.ts +27 -0
- package/dist/uploads/captureFileRef.js +34 -0
- package/dist/uploads/captureFileRef.js.map +1 -0
- package/dist/uploads/resolveFileRef.d.ts +26 -0
- package/dist/uploads/resolveFileRef.js +44 -0
- package/dist/uploads/resolveFileRef.js.map +1 -0
- package/dist/uploads/types.d.ts +20 -0
- package/dist/validation/buildRuleBlocks.js +46 -0
- package/dist/validation/buildRuleBlocks.js.map +1 -0
- package/dist/validation/builtin/email.js +19 -0
- package/dist/validation/builtin/email.js.map +1 -0
- package/dist/validation/builtin/index.js +27 -0
- package/dist/validation/builtin/index.js.map +1 -0
- package/dist/validation/builtin/matchesField.js +20 -0
- package/dist/validation/builtin/matchesField.js.map +1 -0
- package/dist/validation/builtin/max.js +21 -0
- package/dist/validation/builtin/max.js.map +1 -0
- package/dist/validation/builtin/maxLength.js +26 -0
- package/dist/validation/builtin/maxLength.js.map +1 -0
- package/dist/validation/builtin/min.js +21 -0
- package/dist/validation/builtin/min.js.map +1 -0
- package/dist/validation/builtin/minLength.js +26 -0
- package/dist/validation/builtin/minLength.js.map +1 -0
- package/dist/validation/builtin/notAlreadySubmitted.js +32 -0
- package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -0
- package/dist/validation/builtin/oneOf.js +34 -0
- package/dist/validation/builtin/oneOf.js.map +1 -0
- package/dist/validation/builtin/pattern.js +41 -0
- package/dist/validation/builtin/pattern.js.map +1 -0
- package/dist/validation/builtin/url.js +22 -0
- package/dist/validation/builtin/url.js.map +1 -0
- package/dist/validation/defineValidationRule.d.ts +12 -0
- package/dist/validation/defineValidationRule.js +11 -0
- package/dist/validation/defineValidationRule.js.map +1 -0
- package/dist/validation/message.js +14 -0
- package/dist/validation/message.js.map +1 -0
- package/dist/validation/registry.d.ts +10 -0
- package/dist/validation/registry.js +20 -0
- package/dist/validation/registry.js.map +1 -0
- package/dist/validation/runValidation.js +111 -0
- package/dist/validation/runValidation.js.map +1 -0
- package/dist/validation/types.d.ts +76 -0
- package/package.json +8 -5
- package/styles/form-builder.css +201 -11
- package/dist/constants-B-BUfetP.d.ts +0 -288
- package/dist/exports/client.js.map +0 -1
- package/dist/exports/react.js.map +0 -1
- package/dist/exports/rsc.js.map +0 -1
- package/dist/fieldTypes-B8jkNRob.d.ts +0 -188
- package/dist/fieldTypes-CzhhJXjg.js.map +0 -1
- package/dist/index-DfFYGbVF.d.ts +0 -481
- package/dist/keys-N5xGiUsh.js.map +0 -1
- package/dist/registry-CoCyhtvB.js +0 -282
- package/dist/registry-CoCyhtvB.js.map +0 -1
- package/dist/resolver-OeQyVH2N.js +0 -665
- package/dist/resolver-OeQyVH2N.js.map +0 -1
- package/dist/translations-edMqq_2e.js.map +0 -1
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import { n as AnyFormFieldDefinition } from "./fieldTypes-B8jkNRob.js";
|
|
2
|
-
import { Field, Payload, PayloadRequest, Where } from "payload";
|
|
3
|
-
|
|
4
|
-
//#region src/submissions/types.d.ts
|
|
5
|
-
/** A single answered field: the field's machine name and its typed value. */
|
|
6
|
-
type SubmissionValue = {
|
|
7
|
-
field: string;
|
|
8
|
-
value: unknown;
|
|
9
|
-
};
|
|
10
|
-
/** A localized, self-describing snapshot of an answered field, taken at submit time. */
|
|
11
|
-
type SubmissionDescriptor = {
|
|
12
|
-
field: string;
|
|
13
|
-
label: string;
|
|
14
|
-
fieldType: string;
|
|
15
|
-
optionLabels?: Record<string, string>;
|
|
16
|
-
};
|
|
17
|
-
/** A per-field validation failure (`path` is the field name, for renderer error mapping). */
|
|
18
|
-
type SubmissionFieldError = {
|
|
19
|
-
path: string;
|
|
20
|
-
message: string;
|
|
21
|
-
};
|
|
22
|
-
/** A field instance as stored in a form's `fields` blocks array (shared config plus type-specific keys). */
|
|
23
|
-
type FormFieldInstance = {
|
|
24
|
-
blockType: string;
|
|
25
|
-
name: string;
|
|
26
|
-
label?: string;
|
|
27
|
-
required?: boolean;
|
|
28
|
-
visibleWhen?: Where;
|
|
29
|
-
validateWhen?: Where;
|
|
30
|
-
[key: string]: unknown;
|
|
31
|
-
};
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/aggregation/types.d.ts
|
|
34
|
-
/** Which submission statuses to count. `complete` (default) excludes partials; `all` counts everything. */
|
|
35
|
-
type SubmissionStatusFilter = 'complete' | 'partial' | 'all';
|
|
36
|
-
/** One answer option (or distinct value) with its tally. */
|
|
37
|
-
type AggregationBucket = {
|
|
38
|
-
/** The answer value, stringified (the grouping key). */value: string; /** Display label: current option label, else the submitted snapshot label, else the raw value. */
|
|
39
|
-
label: string;
|
|
40
|
-
count: number; /** Share of respondents, 0-100, rounded to one decimal. Can sum past 100 for multi-value fields. */
|
|
41
|
-
percentage: number;
|
|
42
|
-
};
|
|
43
|
-
/** Aggregated responses for one field across a form's submissions. */
|
|
44
|
-
type FieldAggregation = {
|
|
45
|
-
field: string;
|
|
46
|
-
label?: string;
|
|
47
|
-
fieldType?: string; /** Respondents: submissions with a non-empty answer for this field. The percentage denominator. */
|
|
48
|
-
total: number;
|
|
49
|
-
buckets: AggregationBucket[]; /** True when the `maxSubmissions` cap was hit, so the tallies are a (large) sample, not the full set. */
|
|
50
|
-
truncated: boolean;
|
|
51
|
-
};
|
|
52
|
-
/** The slice of a submission the reducer reads. */
|
|
53
|
-
type AggregationRow = {
|
|
54
|
-
values?: SubmissionValue[];
|
|
55
|
-
descriptors?: SubmissionDescriptor[];
|
|
56
|
-
};
|
|
57
|
-
/** Field metadata the reducer needs to label and order buckets, derived from the live form definition. */
|
|
58
|
-
type FieldMeta = {
|
|
59
|
-
field: string;
|
|
60
|
-
label?: string;
|
|
61
|
-
fieldType?: string; /** Ordered known options with current labels; drives bucket order and label resolution. */
|
|
62
|
-
options?: {
|
|
63
|
-
value: string;
|
|
64
|
-
label: string;
|
|
65
|
-
}[];
|
|
66
|
-
};
|
|
67
|
-
//#endregion
|
|
68
|
-
//#region src/calc/types.d.ts
|
|
69
|
-
/** A serializable, safe-by-construction calculation expression. No strings are parsed; the evaluator tree-walks this closed node set (never `eval`). */
|
|
70
|
-
type CalcExpression = {
|
|
71
|
-
type: 'lit';
|
|
72
|
-
value: number;
|
|
73
|
-
} | {
|
|
74
|
-
type: 'ref';
|
|
75
|
-
field: string;
|
|
76
|
-
} | {
|
|
77
|
-
type: 'op';
|
|
78
|
-
op: '+' | '-' | '*' | '/' | '%';
|
|
79
|
-
left: CalcExpression;
|
|
80
|
-
right: CalcExpression;
|
|
81
|
-
} | {
|
|
82
|
-
type: 'neg';
|
|
83
|
-
operand: CalcExpression;
|
|
84
|
-
} | {
|
|
85
|
-
type: 'fn';
|
|
86
|
-
fn: 'min' | 'max' | 'round' | 'abs' | 'ceil' | 'floor';
|
|
87
|
-
args: CalcExpression[];
|
|
88
|
-
} | {
|
|
89
|
-
type: 'weight';
|
|
90
|
-
field: string;
|
|
91
|
-
weights: Record<string, number>;
|
|
92
|
-
};
|
|
93
|
-
//#endregion
|
|
94
|
-
//#region src/calc/computeCalcFields.d.ts
|
|
95
|
-
/** Returns the calc expression if the field carries one (non-null object), otherwise undefined. */
|
|
96
|
-
declare const calcExpressionOf: (field: FormFieldInstance) => CalcExpression | undefined;
|
|
97
|
-
/**
|
|
98
|
-
* Returns answers with every calc field's value derived from its expression,
|
|
99
|
-
* folded in declaration order so a calc may reference an earlier calc's result.
|
|
100
|
-
* Identity when no field carries an expression.
|
|
101
|
-
*/
|
|
102
|
-
declare const computeCalcFields: (fields: FormFieldInstance[], answers: Record<string, unknown>) => Record<string, unknown>;
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/calc/evaluate.d.ts
|
|
105
|
-
/** Evaluate a calc expression against form answers. Total + safe: no `eval`, always finite, div/mod by zero -> 0, missing ref -> 0, depth-guarded. Isomorphic (client + server). */
|
|
106
|
-
declare const evaluateCalc: (expr: CalcExpression | null | undefined, answers: Record<string, unknown>) => number;
|
|
107
|
-
//#endregion
|
|
108
|
-
//#region src/conditions/evaluate.d.ts
|
|
109
|
-
/**
|
|
110
|
-
* Evaluate a serializable `Where`-shaped condition against a flat map of (already coerced) form answers.
|
|
111
|
-
* An absent or empty condition matches (returns true). Operator semantics mirror Payload's query
|
|
112
|
-
* adapters: coerce then compare; `not_equals`/`not_in` are null-inclusive; `exists` treats `''`/absent
|
|
113
|
-
* as not-existing; `like` is case-insensitive and space-splits (every word must be a substring), and
|
|
114
|
-
* `not_like` is its logical negation (at least one word absent); `contains` is a single case-insensitive
|
|
115
|
-
* substring; comma-delimited `in`/`not_in` string values are split and trimmed. Geo (`near`/`within`/
|
|
116
|
-
* `intersects`) and `all` are out of scope and evaluate to false. Isomorphic: no `req`/DB access, so the
|
|
117
|
-
* renderer reuses it client-side.
|
|
118
|
-
*/
|
|
119
|
-
declare const evaluateCondition: (where: Where | null | undefined, answers: Record<string, unknown>) => boolean;
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/fields/registry.d.ts
|
|
122
|
-
type FieldTypeRegistry = Map<string, AnyFormFieldDefinition>;
|
|
123
|
-
/** Per-type opt-in: `false` removes a built-in, `true` keeps it, an object adds a new type or replaces one. */
|
|
124
|
-
type FieldTypeOption = boolean | AnyFormFieldDefinition;
|
|
125
|
-
type FieldTypesConfig = Record<string, FieldTypeOption>;
|
|
126
|
-
//#endregion
|
|
127
|
-
//#region src/prefill/valuesFromSearchParams.d.ts
|
|
128
|
-
type PrefillOptions = {
|
|
129
|
-
/** Map a query-param name to a field name. Unmapped params use their own name. */map?: Record<string, string>; /** If set, only these field names may be prefilled. */
|
|
130
|
-
allow?: string[]; /** These field names may never be prefilled. */
|
|
131
|
-
deny?: string[];
|
|
132
|
-
};
|
|
133
|
-
/**
|
|
134
|
-
* Map URL/query params to typed initial values for KNOWN fields only, coerced by each field's value
|
|
135
|
-
* kind. Unknown, denied, or un-allowed params are ignored; invalid numbers are dropped. Prefilled
|
|
136
|
-
* values are never trusted -- they still validate on submit. Pass the result to `<Form initialValues>`.
|
|
137
|
-
*/
|
|
138
|
-
declare const valuesFromSearchParams: (params: URLSearchParams | Record<string, string>, fields: FormFieldInstance[], registry: FieldTypeRegistry, options?: PrefillOptions) => Record<string, unknown>;
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/events/types.d.ts
|
|
141
|
-
type FormEventBase = {
|
|
142
|
-
formId: string;
|
|
143
|
-
at: string;
|
|
144
|
-
};
|
|
145
|
-
type FormEvent = (FormEventBase & {
|
|
146
|
-
type: 'form.viewed';
|
|
147
|
-
}) | (FormEventBase & {
|
|
148
|
-
type: 'form.started';
|
|
149
|
-
}) | (FormEventBase & {
|
|
150
|
-
type: 'step.viewed';
|
|
151
|
-
stepId: string;
|
|
152
|
-
}) | (FormEventBase & {
|
|
153
|
-
type: 'step.completed';
|
|
154
|
-
stepId: string;
|
|
155
|
-
}) | (FormEventBase & {
|
|
156
|
-
type: 'field.errored';
|
|
157
|
-
field: string;
|
|
158
|
-
message: string;
|
|
159
|
-
}) | (FormEventBase & {
|
|
160
|
-
type: 'form.abandoned';
|
|
161
|
-
}) | (FormEventBase & {
|
|
162
|
-
type: 'submission.created';
|
|
163
|
-
submissionId?: string;
|
|
164
|
-
});
|
|
165
|
-
type FormEventSink = {
|
|
166
|
-
emit: (event: FormEvent) => Promise<void> | void;
|
|
167
|
-
};
|
|
168
|
-
//#endregion
|
|
169
|
-
//#region src/validation/types.d.ts
|
|
170
|
-
type ValidationSeverity = 'error' | 'warning';
|
|
171
|
-
/** A rule outcome: pass, a plain error string, or an explicit message + severity. */
|
|
172
|
-
type ValidationRuleResult = true | string | {
|
|
173
|
-
message: string;
|
|
174
|
-
severity?: ValidationSeverity;
|
|
175
|
-
};
|
|
176
|
-
/** Resolves this rule instance's message (custom override or localized default) with `{var}` interpolation. */
|
|
177
|
-
type MessageFn = (vars?: Record<string, unknown>) => string;
|
|
178
|
-
/** Resolved per-instance rule params (loose at the DB boundary, narrowed by the author's generic). */
|
|
179
|
-
type ValidationParams = Record<string, unknown>;
|
|
180
|
-
type ValidationRuleValidateArgs<TParams extends ValidationParams, TValue, TData extends Record<string, unknown> = Record<string, unknown>> = {
|
|
181
|
-
value: TValue | null | undefined;
|
|
182
|
-
params: TParams;
|
|
183
|
-
siblingData: TData;
|
|
184
|
-
data: TData;
|
|
185
|
-
field: FormFieldInstance;
|
|
186
|
-
fieldType: string;
|
|
187
|
-
operation: 'create' | 'update';
|
|
188
|
-
event: 'onChange' | 'submit';
|
|
189
|
-
locale: string;
|
|
190
|
-
message: MessageFn; /** Server only. Absent in the client (req-less) context, so a server-only rule cannot run there. */
|
|
191
|
-
req?: PayloadRequest;
|
|
192
|
-
payload?: Payload; /** Server only. The form being submitted, for form-scoped lookups (e.g. notAlreadySubmitted). */
|
|
193
|
-
formId?: number | string;
|
|
194
|
-
};
|
|
195
|
-
type ValidationRuleValidate<TParams extends ValidationParams, TValue, TData extends Record<string, unknown> = Record<string, unknown>> = (args: ValidationRuleValidateArgs<TParams, TValue, TData>) => Promise<ValidationRuleResult> | ValidationRuleResult;
|
|
196
|
-
/**
|
|
197
|
-
* A validation rule type, authored once. `params` is a Payload `Field[]` rendered in the per-field
|
|
198
|
-
* constraint list; `validate` returns `true | string | { message, severity }`. `client` defaults from
|
|
199
|
-
* whether the rule is pure (a rule that is async or uses `req`/`payload` must set `client: false`).
|
|
200
|
-
*/
|
|
201
|
-
type ValidationRuleDefinition<TParams extends ValidationParams = ValidationParams, TValue = unknown, TData extends Record<string, unknown> = Record<string, unknown>> = {
|
|
202
|
-
type: string;
|
|
203
|
-
label: string;
|
|
204
|
-
description?: string; /** Field type slugs this rule may be added to. Omit for all field types. */
|
|
205
|
-
appliesTo?: string[];
|
|
206
|
-
params?: Field[];
|
|
207
|
-
defaultMessage: string; /** Runs client-side too. Defaults to `true`; set `false` for async or `req`/`payload`-using rules. */
|
|
208
|
-
client?: boolean; /** Default severity when `validate` returns a bare string. Defaults to `error`. */
|
|
209
|
-
severity?: ValidationSeverity;
|
|
210
|
-
validate: ValidationRuleValidate<TParams, TValue, TData>;
|
|
211
|
-
};
|
|
212
|
-
/** Erased shape stored in the heterogeneous registry; params re-narrow per matched rule at execution. */
|
|
213
|
-
type AnyValidationRuleValidate = (args: {
|
|
214
|
-
value: unknown;
|
|
215
|
-
params: ValidationParams;
|
|
216
|
-
siblingData: Record<string, unknown>;
|
|
217
|
-
data: Record<string, unknown>;
|
|
218
|
-
field: FormFieldInstance;
|
|
219
|
-
fieldType: string;
|
|
220
|
-
operation: 'create' | 'update';
|
|
221
|
-
event: 'onChange' | 'submit';
|
|
222
|
-
locale: string;
|
|
223
|
-
message: MessageFn;
|
|
224
|
-
req?: PayloadRequest;
|
|
225
|
-
payload?: Payload;
|
|
226
|
-
formId?: number | string;
|
|
227
|
-
}) => Promise<ValidationRuleResult> | ValidationRuleResult;
|
|
228
|
-
type AnyValidationRuleDefinition = {
|
|
229
|
-
type: string;
|
|
230
|
-
label: string;
|
|
231
|
-
description?: string;
|
|
232
|
-
appliesTo?: string[];
|
|
233
|
-
params?: Field[];
|
|
234
|
-
defaultMessage: string;
|
|
235
|
-
client?: boolean;
|
|
236
|
-
severity?: ValidationSeverity;
|
|
237
|
-
validate: AnyValidationRuleValidate;
|
|
238
|
-
};
|
|
239
|
-
//#endregion
|
|
240
|
-
//#region src/presentations/types.d.ts
|
|
241
|
-
/** How a presentation surfaces the form. Drives wrapper selection and CSS. */
|
|
242
|
-
type PresentationSurface = 'inline' | 'page' | 'overlay';
|
|
243
|
-
type PresentationDensity = 'comfortable' | 'compact';
|
|
244
|
-
/**
|
|
245
|
-
* Serializable, framework-agnostic description of a presentation. The admin select and the
|
|
246
|
-
* stored `defaultPresentation` use only this; the React `Wrapper` is added in `./react`. No React here.
|
|
247
|
-
*/
|
|
248
|
-
type PresentationDescriptor = {
|
|
249
|
-
name: string; /** i18n key or literal shown in the admin select. */
|
|
250
|
-
label: string;
|
|
251
|
-
surface: PresentationSurface;
|
|
252
|
-
density: PresentationDensity; /** Overlay surfaces request dismissal after a successful submit. */
|
|
253
|
-
dismissOnSuccess?: boolean;
|
|
254
|
-
};
|
|
255
|
-
//#endregion
|
|
256
|
-
//#region src/recall/interpolate.d.ts
|
|
257
|
-
/**
|
|
258
|
-
* Replace `{{ name }}` and `{{ name|fallback }}` tokens. `resolve` returns the recalled value (''
|
|
259
|
-
* when absent); the fallback (or '') is substituted when `resolve` yields ''. Token-free input is
|
|
260
|
-
* returned unchanged, so this is a no-op for ordinary text.
|
|
261
|
-
*/
|
|
262
|
-
declare const interpolate: (template: string, resolve: (name: string) => string) => string;
|
|
263
|
-
//#endregion
|
|
264
|
-
//#region src/recall/resolver.d.ts
|
|
265
|
-
type RecallResolver = (name: string) => string;
|
|
266
|
-
/** Derive a value->label map from a select-like field instance's `options`. */
|
|
267
|
-
declare const optionLabelsFor: (field: FormFieldInstance) => Record<string, string> | undefined;
|
|
268
|
-
/**
|
|
269
|
-
* Build a recall resolver: `{{name}}` -> the field's current value, formatted via its type's `format`
|
|
270
|
-
* (so a select shows its option label, a checkbox Yes/No, a date localized). Missing field or empty
|
|
271
|
-
* value -> ''. Pure and isomorphic; the renderer and server templates share it.
|
|
272
|
-
*/
|
|
273
|
-
declare const buildRecallResolver: (args: {
|
|
274
|
-
fields: FormFieldInstance[];
|
|
275
|
-
values: Record<string, unknown>;
|
|
276
|
-
registry: Map<string, AnyFormFieldDefinition>;
|
|
277
|
-
locale: string;
|
|
278
|
-
t: (key: string) => string;
|
|
279
|
-
}) => RecallResolver;
|
|
280
|
-
//#endregion
|
|
281
|
-
//#region src/spam/constants.d.ts
|
|
282
|
-
/** Default honeypot decoy field name. Plausible to bots, unlikely to collide with a real field name. */
|
|
283
|
-
declare const DEFAULT_HONEYPOT_FIELD = "confirm_email";
|
|
284
|
-
/** Reserved `values` entry carrying a captcha token from the client. */
|
|
285
|
-
declare const CAPTCHA_TOKEN_KEY = "__fb_captcha";
|
|
286
|
-
//#endregion
|
|
287
|
-
export { FieldMeta as A, evaluateCalc as C, AggregationBucket as D, CalcExpression as E, SubmissionValue as F, FormFieldInstance as M, SubmissionDescriptor as N, AggregationRow as O, SubmissionFieldError as P, evaluateCondition as S, computeCalcFields as T, PrefillOptions as _, optionLabelsFor as a, FieldTypeRegistry as b, PresentationDescriptor as c, ValidationParams as d, ValidationRuleDefinition as f, FormEventSink as g, FormEvent as h, buildRecallResolver as i, SubmissionStatusFilter as j, FieldAggregation as k, PresentationSurface as l, ValidationSeverity as m, DEFAULT_HONEYPOT_FIELD as n, interpolate as o, ValidationRuleResult as p, RecallResolver as r, PresentationDensity as s, CAPTCHA_TOKEN_KEY as t, AnyValidationRuleDefinition as u, valuesFromSearchParams as v, calcExpressionOf as w, FieldTypesConfig as x, FieldTypeOption as y };
|
|
288
|
-
//# sourceMappingURL=constants-B-BUfetP.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["useTranslation","usePayloadTranslation","useTranslation","useTranslation"],"sources":["../../src/translations/useTranslation.ts","../../src/client/synthesizeClientField.ts","../../src/client/ConditionRow.tsx","../../src/client/ConditionBuilder.tsx","../../src/client/FormConditionField.tsx"],"sourcesContent":["'use client'\n\nimport { useTranslation as usePayloadTranslation } from '@payloadcms/ui'\n\nimport type { TranslationKey } from './keys'\n\n/**\n * `useTranslation` bound to this plugin's keys, so `t(keys.X)` typechecks without\n * a per-call `@ts-expect-error`. Returns Payload's `{ t, i18n }` unchanged.\n */\nexport const useTranslation = () => usePayloadTranslation<Record<string, never>, TranslationKey>()\n","import type {\n\tDateFieldClient,\n\tNumberFieldClient,\n\tOption,\n\tSelectFieldClient,\n\tTextFieldClient,\n} from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\n\n/** A field row as stored in the form's `fields` blocks array (only the keys the builder reads). */\nexport type FieldRow = {\n\tblockType: string\n\tname?: string\n\tlabel?: string\n\toptions?: Option[]\n\t[key: string]: unknown\n}\n\n/** A condition operand: a selectable form field the builder can compare against. */\nexport type ConditionOperand = {\n\tname: string\n\tlabel: string\n\tconditionType: ConditionFieldType\n\toptions?: Option[]\n}\n\n/** Project a stored field row into a condition operand, or `null` when the row has no usable name. */\nexport const operandFromRow = (\n\trow: FieldRow,\n\tconditionTypes: Record<string, ConditionFieldType>\n): ConditionOperand | null => {\n\tconst name = typeof row.name === 'string' ? row.name.trim() : ''\n\tif (name.length === 0) {\n\t\treturn null\n\t}\n\tconst conditionType = conditionTypes[row.blockType] ?? 'text'\n\treturn {\n\t\tname,\n\t\tlabel: typeof row.label === 'string' && row.label.length > 0 ? row.label : name,\n\t\tconditionType,\n\t\toptions: Array.isArray(row.options) ? row.options : undefined,\n\t}\n}\n\n/**\n * Build the minimal `*FieldClient` a Payload leaf condition input requires for a given operand. Casts\n * are localized to these four synths and nowhere else: `FieldBaseClient` requires only `name`, and each\n * leaf is `FieldBaseClient & Pick<…, 'type' | …>` where every picked member but `type` (and `select`'s\n * required `options`) is optional, so the literals are structurally complete. `dateClientField` omits\n * `admin.date`, so `DateCondition` falls back to its default date format. Each synth returns a single\n * concrete client type so leaf `field` props need no narrowing.\n */\nexport const textClientField = (operand: ConditionOperand): TextFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'text' }) as TextFieldClient\n\nexport const numberClientField = (operand: ConditionOperand): NumberFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'number' }) as NumberFieldClient\n\nexport const dateClientField = (operand: ConditionOperand): DateFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'date' }) as DateFieldClient\n\nexport const selectClientField = (operand: ConditionOperand): SelectFieldClient =>\n\t({\n\t\tname: operand.name,\n\t\tlabel: operand.label,\n\t\ttype: 'select',\n\t\toptions: operand.options ?? [],\n\t}) as SelectFieldClient\n","'use client'\n\nimport {\n\tDateCondition,\n\tNumberCondition,\n\tReactSelect,\n\ttype ReactSelectOption,\n\tSelectCondition,\n\tTextCondition,\n} from '@payloadcms/ui'\nimport type { Operator } from 'payload'\nimport {\n\tconditionOperators,\n\tfirstOperatorFor,\n\toperatorLabelKey,\n\toperatorValueShape,\n} from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport {\n\ttype ConditionOperand,\n\tdateClientField,\n\tnumberClientField,\n\tselectClientField,\n\ttextClientField,\n} from './synthesizeClientField'\n\nexport type RowCondition = { field: string; operator: Operator; value: unknown }\n\nexport type ConditionRowProps = {\n\tcondition: RowCondition\n\toperands: ConditionOperand[]\n\tonChange: (next: RowCondition) => void\n\tonRemove: () => void\n}\n\n/** ReactSelect's `onChange` hands back `Option | Option[]`; narrow it to the single chosen option. */\nconst singleOption = (\n\tselected: ReactSelectOption | ReactSelectOption[]\n): ReactSelectOption | undefined => (Array.isArray(selected) ? selected[0] : selected)\n\nexport const ConditionRow = ({ condition, operands, onChange, onRemove }: ConditionRowProps) => {\n\tconst { t, i18n } = useTranslation()\n\tconst operand = operands.find((entry) => entry.name === condition.field)\n\tconst conditionType = operand?.conditionType ?? 'text'\n\tconst operators = conditionOperators[conditionType]\n\n\tconst fieldOptions: ReactSelectOption[] = operands.map((entry) => ({\n\t\tlabel: entry.label,\n\t\tvalue: entry.name,\n\t}))\n\tconst operatorOptions: ReactSelectOption[] = operators.map((operator) => ({\n\t\tlabel: i18n.t(operatorLabelKey(operator)),\n\t\tvalue: operator,\n\t}))\n\n\tconst handleFieldChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = singleOption(selected)\n\t\tconst next = operands.find((entry) => entry.name === chosen?.value)\n\t\tif (!next) {\n\t\t\treturn\n\t\t}\n\t\tonChange({\n\t\t\tfield: next.name,\n\t\t\toperator: firstOperatorFor(next.conditionType),\n\t\t\tvalue: undefined,\n\t\t})\n\t}\n\n\tconst handleOperatorChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = singleOption(selected)\n\t\tif (!chosen) {\n\t\t\treturn\n\t\t}\n\t\tconst operator = chosen.value as Operator\n\t\tconst keepValue = operatorValueShape(condition.operator) === operatorValueShape(operator)\n\t\tonChange({ ...condition, operator, value: keepValue ? condition.value : undefined })\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"form-builder-condition-row\"\n\t\t\tstyle={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}\n\t\t>\n\t\t\t<div style={{ minWidth: 160 }}>\n\t\t\t\t<ReactSelect\n\t\t\t\t\toptions={fieldOptions}\n\t\t\t\t\tvalue={fieldOptions.find((option) => option.value === condition.field)}\n\t\t\t\t\tplaceholder={t(keys.conditionSelectField)}\n\t\t\t\t\tisClearable={false}\n\t\t\t\t\tonChange={handleFieldChange}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div style={{ minWidth: 140 }}>\n\t\t\t\t<ReactSelect\n\t\t\t\t\toptions={operatorOptions}\n\t\t\t\t\tvalue={operatorOptions.find((option) => option.value === condition.operator)}\n\t\t\t\t\tdisabled={!operand}\n\t\t\t\t\tisClearable={false}\n\t\t\t\t\tonChange={handleOperatorChange}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div style={{ flex: 1 }}>\n\t\t\t\t<ConditionValue\n\t\t\t\t\tconditionType={conditionType}\n\t\t\t\t\toperand={operand}\n\t\t\t\t\toperator={condition.operator}\n\t\t\t\t\tvalue={condition.value}\n\t\t\t\t\tonChange={(value) => onChange({ ...condition, value })}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<button type=\"button\" onClick={onRemove} aria-label={t(keys.conditionRemove)}>\n\t\t\t\t{t(keys.conditionRemove)}\n\t\t\t</button>\n\t\t</div>\n\t)\n}\n\ntype ConditionValueProps = {\n\tconditionType: ConditionOperand['conditionType']\n\toperand?: ConditionOperand\n\toperator: Operator\n\tvalue: unknown\n\tonChange: (value: unknown) => void\n}\n\nconst ConditionValue = ({\n\tconditionType,\n\toperand,\n\toperator,\n\tvalue,\n\tonChange,\n}: ConditionValueProps) => {\n\tconst { t } = useTranslation()\n\tif (conditionType === 'checkbox' || operatorValueShape(operator) === 'boolean') {\n\t\tconst options: ReactSelectOption[] = [\n\t\t\t{ label: t(keys.conditionTrue), value: 'true' },\n\t\t\t{ label: t(keys.conditionFalse), value: 'false' },\n\t\t]\n\t\tconst handleBooleanChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\t\tconst chosen = singleOption(selected)\n\t\t\tonChange(chosen?.value === 'true')\n\t\t}\n\t\treturn (\n\t\t\t<ReactSelect\n\t\t\t\toptions={options}\n\t\t\t\tvalue={options.find((option) => String(option.value) === String(value)) ?? options[0]}\n\t\t\t\tisClearable={false}\n\t\t\t\tonChange={handleBooleanChange}\n\t\t\t/>\n\t\t)\n\t}\n\tif (!operand) {\n\t\treturn null\n\t}\n\tswitch (conditionType) {\n\t\tcase 'number':\n\t\t\treturn (\n\t\t\t\t<NumberCondition\n\t\t\t\t\tdisabled={false}\n\t\t\t\t\tfield={numberClientField(operand)}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\tvalue={value as number | number[]}\n\t\t\t\t\tonChange={(next: string) => onChange(next)}\n\t\t\t\t/>\n\t\t\t)\n\t\tcase 'date':\n\t\t\treturn (\n\t\t\t\t<DateCondition\n\t\t\t\t\tdisabled={false}\n\t\t\t\t\tfield={dateClientField(operand)}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\tvalue={value as Date | string}\n\t\t\t\t\tonChange={(next: Date | string) => onChange(next)}\n\t\t\t\t/>\n\t\t\t)\n\t\tcase 'select':\n\t\t\treturn (\n\t\t\t\t<SelectCondition\n\t\t\t\t\tdisabled={false}\n\t\t\t\t\tfield={selectClientField(operand)}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\toptions={operand.options ?? []}\n\t\t\t\t\tvalue={value as string}\n\t\t\t\t\tonChange={(next: string) => onChange(next)}\n\t\t\t\t/>\n\t\t\t)\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\t<TextCondition\n\t\t\t\t\tdisabled={false}\n\t\t\t\t\tfield={textClientField(operand)}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\tvalue={value as string | string[]}\n\t\t\t\t\tonChange={(next: string) => onChange(next)}\n\t\t\t\t/>\n\t\t\t)\n\t}\n}\n","'use client'\n\nimport { useFormFields } from '@payloadcms/ui'\nimport type { Operator, Where } from 'payload'\nimport { reduceFieldsToValues, transformWhereQuery } from 'payload/shared'\nimport { useMemo } from 'react'\nimport { type ConditionFieldType, firstOperatorFor } from '../conditions/fieldTypes'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { ConditionRow, type RowCondition } from './ConditionRow'\nimport { type ConditionOperand, type FieldRow, operandFromRow } from './synthesizeClientField'\n\nexport type ConditionBuilderProps = {\n\tvalue?: Where\n\tonChange: (next: Where) => void\n\tconditionTypes: Record<string, ConditionFieldType>\n\t/** This field's own machine name, excluded from the operand list (a field cannot condition on itself). */\n\tselfName?: string\n}\n\nconst toRow = (constraint: Record<string, unknown>): RowCondition | null => {\n\tconst field = Object.keys(constraint)[0]\n\tif (!field) {\n\t\treturn null\n\t}\n\tconst ops = constraint[field] as Record<string, unknown>\n\tconst operator = Object.keys(ops)[0] as Operator | undefined\n\tif (!operator) {\n\t\treturn null\n\t}\n\treturn { field, operator, value: ops[operator] }\n}\n\nconst fromRow = (row: RowCondition): Where => ({ [row.field]: { [row.operator]: row.value } })\n\nconst readGroups = (value: Where | undefined): RowCondition[][] => {\n\tif (!value || Object.keys(value).length === 0) {\n\t\treturn []\n\t}\n\tconst canonical = transformWhereQuery(value)\n\tconst or = Array.isArray(canonical.or) ? canonical.or : []\n\treturn or.map((group) => {\n\t\tconst and = Array.isArray((group as Where).and) ? ((group as Where).and as Where[]) : []\n\t\treturn and\n\t\t\t.map((constraint) => toRow(constraint as Record<string, unknown>))\n\t\t\t.filter((row): row is RowCondition => row !== null)\n\t})\n}\n\nconst writeGroups = (groups: RowCondition[][]): Where => ({\n\tor: groups.filter((group) => group.length > 0).map((group) => ({ and: group.map(fromRow) })),\n})\n\nconst operandsFromData = (\n\tdata: Record<string, unknown>,\n\tconditionTypes: Record<string, ConditionFieldType>,\n\tselfName: string | undefined\n): ConditionOperand[] => {\n\tconst rows = Array.isArray(data.fields) ? (data.fields as FieldRow[]) : []\n\treturn rows\n\t\t.map((row) => operandFromRow(row, conditionTypes))\n\t\t.filter((operand): operand is ConditionOperand => operand !== null && operand.name !== selfName)\n}\n\nexport const ConditionBuilder = ({\n\tvalue,\n\tonChange,\n\tconditionTypes,\n\tselfName,\n}: ConditionBuilderProps) => {\n\tconst { t } = useTranslation()\n\t// Serialize the operand list so the builder re-renders only when operands actually change (a field\n\t// added, renamed, retyped, or its options edited), not on every unrelated form-state update.\n\tconst operandsJson = useFormFields(([fields]) =>\n\t\tJSON.stringify(operandsFromData(reduceFieldsToValues(fields, true), conditionTypes, selfName))\n\t)\n\tconst operands = useMemo(() => JSON.parse(operandsJson) as ConditionOperand[], [operandsJson])\n\n\tconst groups = readGroups(value)\n\tconst emit = (next: RowCondition[][]) => onChange(writeGroups(next))\n\n\tconst addCondition = (groupIndex: number) => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\tconst row: RowCondition = {\n\t\t\tfield: first.name,\n\t\t\toperator: firstOperatorFor(first.conditionType),\n\t\t\tvalue: undefined,\n\t\t}\n\t\temit(\n\t\t\tgroups.length === 0\n\t\t\t\t? [[row]]\n\t\t\t\t: groups.map((group, index) => (index === groupIndex ? [...group, row] : group))\n\t\t)\n\t}\n\n\tconst addOrGroup = () => {\n\t\tconst first = operands[0]\n\t\tif (!first) {\n\t\t\treturn\n\t\t}\n\t\temit([\n\t\t\t...groups,\n\t\t\t[{ field: first.name, operator: firstOperatorFor(first.conditionType), value: undefined }],\n\t\t])\n\t}\n\n\tconst updateRow = (groupIndex: number, rowIndex: number, row: RowCondition) =>\n\t\temit(\n\t\t\tgroups.map((group, index) =>\n\t\t\t\tindex === groupIndex\n\t\t\t\t\t? group.map((existing, position) => (position === rowIndex ? row : existing))\n\t\t\t\t\t: group\n\t\t\t)\n\t\t)\n\n\tconst removeRow = (groupIndex: number, rowIndex: number) =>\n\t\temit(\n\t\t\tgroups\n\t\t\t\t.map((group, index) =>\n\t\t\t\t\tindex === groupIndex ? group.filter((_, position) => position !== rowIndex) : group\n\t\t\t\t)\n\t\t\t\t.filter((group) => group.length > 0)\n\t\t)\n\n\tif (operands.length === 0) {\n\t\treturn <p className=\"form-builder-condition__hint\">{t(keys.conditionNoFields)}</p>\n\t}\n\n\treturn (\n\t\t<div className=\"form-builder-condition\">\n\t\t\t{groups.length === 0 ? (\n\t\t\t\t<p className=\"form-builder-condition__hint\">{t(keys.conditionEmpty)}</p>\n\t\t\t) : (\n\t\t\t\tgroups.map((group, groupIndex) => (\n\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: groups are positional and never reordered\n\t\t\t\t\t<div key={groupIndex} className=\"form-builder-condition__group\">\n\t\t\t\t\t\t{groupIndex > 0 ? (\n\t\t\t\t\t\t\t<div className=\"form-builder-condition__or\">{t(keys.conditionOr)}</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t{group.map((row, rowIndex) => (\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and never reordered\n\t\t\t\t\t\t\t<div key={rowIndex} className=\"form-builder-condition__and\">\n\t\t\t\t\t\t\t\t{rowIndex > 0 ? <span>{t(keys.conditionAnd)}</span> : null}\n\t\t\t\t\t\t\t\t<ConditionRow\n\t\t\t\t\t\t\t\t\tcondition={row}\n\t\t\t\t\t\t\t\t\toperands={operands}\n\t\t\t\t\t\t\t\t\tonChange={(next) => updateRow(groupIndex, rowIndex, next)}\n\t\t\t\t\t\t\t\t\tonRemove={() => removeRow(groupIndex, rowIndex)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<button type=\"button\" onClick={() => addCondition(groupIndex)}>\n\t\t\t\t\t\t\t{t(keys.conditionAddCondition)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t))\n\t\t\t)}\n\t\t\t<div className=\"form-builder-condition__actions\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => (groups.length === 0 ? addCondition(0) : addOrGroup())}\n\t\t\t\t>\n\t\t\t\t\t{groups.length === 0 ? t(keys.conditionAddCondition) : t(keys.conditionAddOr)}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n","'use client'\n\nimport { FieldLabel, useField } from '@payloadcms/ui'\nimport type { StaticLabel, Where } from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\nimport { ConditionBuilder } from './ConditionBuilder'\n\n/** Props: standard JSON field client props plus the `conditionTypes` map we pass via clientProps. */\nexport type FormConditionFieldProps = {\n\tpath?: string\n\tfield?: { label?: unknown; name?: string }\n\tlabel?: unknown\n\tconditionTypes: Record<string, ConditionFieldType>\n}\n\nconst toStaticLabel = (label: unknown): StaticLabel | undefined => {\n\tif (typeof label === 'string') {\n\t\treturn label\n\t}\n\tif (label && typeof label === 'object') {\n\t\treturn label as Record<string, string>\n\t}\n\treturn undefined\n}\n\n/**\n * The `Field` mounted on a form field's `visibleWhen`/`validateWhen` json column. Binds the field's own\n * path with `useField<Where>()` (the QueryPresetsWhereField precedent) and renders the native builder.\n */\nexport const FormConditionField = (props: FormConditionFieldProps) => {\n\tconst { path, setValue, value } = useField<Where>()\n\tconst label = toStaticLabel(props.field?.label ?? props.label)\n\treturn (\n\t\t<div className=\"field-type form-builder-condition-field\">\n\t\t\t<FieldLabel label={label} path={path} />\n\t\t\t<ConditionBuilder\n\t\t\t\tvalue={value ?? undefined}\n\t\t\t\tonChange={setValue}\n\t\t\t\tconditionTypes={props.conditionTypes}\n\t\t\t\tselfName={props.field?.name}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":[],"sources":["../../src/flow/engine.ts","../../src/react/contract.ts","../../src/react/events.ts","../../src/react/FormContext.ts","../../src/react/FormLayout.tsx","../../src/react/Honeypot.tsx","../../src/react/presentation/Backdrop.tsx","../../src/react/presentation/useDismiss.ts","../../src/react/presentation/useFocusTrap.ts","../../src/react/presentation/useScrollLock.ts","../../src/react/presentation/DialogSurface.tsx","../../src/react/presentation/presentations.tsx","../../src/react/presentation/registry.ts","../../src/react/recall.ts","../../src/react/registry.ts","../../src/react/primitives/FieldShell.tsx","../../src/react/renderers/calculation.tsx","../../src/react/primitives/Checkbox.tsx","../../src/react/renderers/checkbox.tsx","../../src/react/renderers/consent.tsx","../../src/react/primitives/Input.tsx","../../src/react/renderers/email.tsx","../../src/react/uploadFile.ts","../../src/react/renderers/file.tsx","../../src/react/renderers/number.tsx","../../src/react/primitives/Select.tsx","../../src/react/renderers/select.tsx","../../src/react/renderers/text.tsx","../../src/react/primitives/Textarea.tsx","../../src/react/renderers/textarea.tsx","../../src/react/renderers/index.ts","../../src/react/resolveForm.ts","../../src/react/state.ts","../../src/react/submitForm.ts","../../src/react/useField.ts","../../src/react/validateField.ts","../../src/react/Form.tsx","../../src/react/FormResults.tsx","../../src/react/fetchResults.ts","../../src/react/Poll.tsx","../../src/react/useFormState.ts","../../src/react/useFormStep.ts"],"sourcesContent":["import { evaluateCondition } from '../conditions/evaluate'\nimport type { FlowStep, FormFlow } from './types'\n\n/** The entry step id (the first step), or `undefined` for an empty flow. */\nexport const firstStepId = (flow: FormFlow): string | undefined => flow.steps[0]?.id\n\n/** The step with the given id, or `undefined`. */\nexport const getStep = (flow: FormFlow, id: string): FlowStep | undefined =>\n\tflow.steps.find((step) => step.id === id)\n\n/** The field machine names a step renders (empty for an unknown step). */\nexport const stepFieldNames = (flow: FormFlow, id: string): string[] =>\n\tgetStep(flow, id)?.fields ?? []\n\n/**\n * Resolve the next step id from the current step + answers: the first transition whose `when` matches\n * (via `evaluateCondition`), else the default `next`, else `undefined` (terminal). Pure + isomorphic.\n */\nexport const resolveNextStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): string | undefined => {\n\tconst step = getStep(flow, currentId)\n\tif (!step) {\n\t\treturn undefined\n\t}\n\tfor (const transition of step.transitions ?? []) {\n\t\tif (evaluateCondition(transition.when, answers)) {\n\t\t\treturn transition.to\n\t\t}\n\t}\n\treturn step.next\n}\n\n/** Whether the current step is terminal (no matching transition + no default next). */\nexport const isTerminalStepId = (\n\tflow: FormFlow,\n\tcurrentId: string,\n\tanswers: Record<string, unknown>\n): boolean => resolveNextStepId(flow, currentId, answers) === undefined\n","import type { ReactNode } from 'react'\nimport type { FormFieldInstance } from '../submissions/types'\n\n/** A localized translator the renderer uses for built-in copy. `(key) => string`; unknown keys return the key. */\nexport type RendererTranslate = (key: string) => string\n\n/**\n * The props every field renderer receives. The renderer turns one field instance plus its current value\n * into an accessible control. Supplied by `<Form>` or directly in tests. Generic over the\n * value type so custom renderers can narrow it.\n */\nexport type FieldRendererProps<TValue = unknown> = {\n\t/** The stored field instance (name, label, blockType, required, placeholder, description, options, ...). */\n\tfield: FormFieldInstance\n\t/** The control's stable id, for label/aria wiring. */\n\tid: string\n\t/** The field machine name (form value key). */\n\tname: string\n\tvalue: TValue | undefined\n\tonChange: (value: TValue) => void\n\tonBlur: () => void\n\t/** Blocking error messages for this field (already filtered to error severity). */\n\terrors: string[]\n\t/** Advisory messages (warning severity). */\n\twarnings?: string[]\n\trequired: boolean\n\tdisabled?: boolean\n\tlocale: string\n\tt: RendererTranslate\n}\n\n/** A field renderer: maps `FieldRendererProps` to React output. */\nexport type FieldRenderer<TValue = unknown> = (props: FieldRendererProps<TValue>) => ReactNode\n\n/** Identity helper that pins a renderer to the `FieldRenderer` type so authors get prop inference. */\nexport const defineFieldRenderer = <TValue = unknown>(\n\trenderer: FieldRenderer<TValue>\n): FieldRenderer<TValue> => renderer\n","'use client'\n\nimport type { FormEvent, FormEventSink } from '../events/types'\n\n/** Distribute `Omit` across the event union so each variant keeps its discriminated extras. */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/** Emit a lifecycle event through the sink, stamping `formId` + an ISO `at`. */\nexport const emitFormEvent = (\n\tsink: FormEventSink,\n\tformId: string,\n\tevent: DistributiveOmit<FormEvent, 'formId' | 'at'>\n): void => {\n\tvoid sink.emit({ ...event, formId, at: new Date().toISOString() } as FormEvent)\n}\n","'use client'\n\nimport type { Dispatch } from 'react'\nimport { createContext, useContext } from 'react'\nimport type { FormFlow } from '../flow/types'\nimport type { FormAction, FormState } from './state'\n\n/** Multi-step navigation state. Defaults to a single terminal step when the form has no flow. */\nexport type FormStepInfo = {\n\tflow?: FormFlow\n\tcurrentStepId?: string\n\tstepIndex: number\n\tstepCount: number\n\tisFirst: boolean\n\tisTerminal: boolean\n\tgoNext: () => void\n\tgoBack: () => void\n}\n\nexport type FormContextValue = {\n\tstate: FormState\n\tdispatch: Dispatch<FormAction>\n\t/** Validate one field now (client mode) against the supplied value and store its issues. */\n\tvalidateField: (name: string, value: unknown) => void\n\tlocale: string\n\tstep: FormStepInfo\n}\n\nexport const FormContext = createContext<FormContextValue | null>(null)\n\n/** Read the form controller context. Throws if used outside `<Form>`. */\nexport const useFormContext = (): FormContextValue => {\n\tconst context = useContext(FormContext)\n\tif (!context) {\n\t\tthrow new Error('useFormContext must be used within a <Form>')\n\t}\n\treturn context\n}\n","'use client'\n\nimport type { ReactNode } from 'react'\n\nexport type FieldWidth = 'full' | 'half' | 'third' | 'twoThirds'\n\nexport type FormLayoutProps = {\n\tchildren: ReactNode\n\t/** When false, render a plain container with no grid class (document-order layout). */\n\tenabled?: boolean\n}\n\n/** Establishes the layout container. With the stylesheet imported, children with `data-width` flow into a grid. */\nexport const FormLayout = ({ children, enabled = true }: FormLayoutProps) => (\n\t<div className={enabled ? 'fb-form fb-form--grid' : 'fb-form'}>{children}</div>\n)\n\n/** Props to spread onto a field wrapper to declare its grid width. */\nexport const widthProps = (width: FieldWidth | undefined) => ({ 'data-width': width ?? 'full' })\n","'use client'\n\nimport type { CSSProperties, Ref } from 'react'\n\nconst HIDDEN: CSSProperties = {\n\tposition: 'absolute',\n\twidth: 1,\n\theight: 1,\n\tpadding: 0,\n\tmargin: -1,\n\toverflow: 'hidden',\n\tclip: 'rect(0, 0, 0, 0)',\n\twhiteSpace: 'nowrap',\n\tborder: 0,\n}\n\nexport type HoneypotProps = {\n\tname: string\n\tinputRef?: Ref<HTMLInputElement>\n}\n\n/**\n * A visually hidden honeypot decoy. Real users never see or tab to it; bots that fill every input trip it,\n * and the server rejects the submission. Off-screen + aria-hidden + tabIndex -1 + autoComplete off.\n */\nexport const Honeypot = ({ name, inputRef }: HoneypotProps) => (\n\t<div aria-hidden=\"true\" style={HIDDEN}>\n\t\t<label>\n\t\t\tLeave this field empty\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\ttype=\"text\"\n\t\t\t\tname={name}\n\t\t\t\ttabIndex={-1}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tdefaultValue=\"\"\n\t\t\t/>\n\t\t</label>\n\t</div>\n)\n","'use client'\n\nimport { createElement } from 'react'\n\nexport type BackdropProps = {\n\tonClick?: () => void\n\tclassName?: string\n}\n\n/** A full-viewport backdrop behind an overlay surface. Styling comes from the `data-fb-backdrop` hook. */\nexport const Backdrop = ({ onClick, className }: BackdropProps) =>\n\tcreateElement('div', { 'data-fb-backdrop': '', className, onClick, 'aria-hidden': true })\n","'use client'\n\nimport { type RefObject, useEffect } from 'react'\n\nexport type UseDismissOptions = {\n\tactive: boolean\n\tonDismiss: () => void\n\tcloseOnEscape?: boolean\n\tcloseOnOutsideClick?: boolean\n}\n\n/** Dismiss-on-Escape and dismiss-on-outside-pointerdown for an overlay surface. */\nexport const useDismiss = (\n\t{ active, onDismiss, closeOnEscape = true, closeOnOutsideClick = true }: UseDismissOptions,\n\tref: RefObject<HTMLElement | null>\n): void => {\n\tuseEffect(() => {\n\t\tif (!active) {\n\t\t\treturn\n\t\t}\n\t\tconst onKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (closeOnEscape && event.key === 'Escape') {\n\t\t\t\tonDismiss()\n\t\t\t}\n\t\t}\n\t\tconst onPointerDown = (event: Event) => {\n\t\t\tif (!closeOnOutsideClick) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst node = ref.current\n\t\t\tif (node && event.target instanceof Node && !node.contains(event.target)) {\n\t\t\t\tonDismiss()\n\t\t\t}\n\t\t}\n\t\tdocument.addEventListener('keydown', onKeyDown)\n\t\tdocument.addEventListener('pointerdown', onPointerDown)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', onKeyDown)\n\t\t\tdocument.removeEventListener('pointerdown', onPointerDown)\n\t\t}\n\t}, [active, onDismiss, closeOnEscape, closeOnOutsideClick, ref])\n}\n","'use client'\n\nimport { type RefObject, useEffect } from 'react'\n\nconst FOCUSABLE =\n\t'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex=\"-1\"])'\n\n/** Trap Tab focus within the container while active. */\nexport const useFocusTrap = (ref: RefObject<HTMLElement | null>, active: boolean): void => {\n\tuseEffect(() => {\n\t\tif (!active) {\n\t\t\treturn\n\t\t}\n\t\tconst node = ref.current\n\t\tif (!node) {\n\t\t\treturn\n\t\t}\n\t\tconst onKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (event.key !== 'Tab') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst focusable = Array.from(node.querySelectorAll<HTMLElement>(FOCUSABLE))\n\t\t\tif (focusable.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst first = focusable[0] as HTMLElement\n\t\t\tconst last = focusable[focusable.length - 1] as HTMLElement\n\t\t\tconst activeEl = document.activeElement\n\t\t\tif (event.shiftKey && activeEl === first) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tlast.focus()\n\t\t\t} else if (!event.shiftKey && activeEl === last) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tfirst.focus()\n\t\t\t}\n\t\t}\n\t\tnode.addEventListener('keydown', onKeyDown)\n\t\treturn () => {\n\t\t\tnode.removeEventListener('keydown', onKeyDown)\n\t\t}\n\t}, [ref, active])\n}\n","'use client'\n\nimport { useEffect } from 'react'\n\n/** Lock body scroll while active; restores the prior value on cleanup. */\nexport const useScrollLock = (active: boolean): void => {\n\tuseEffect(() => {\n\t\tif (!active) {\n\t\t\treturn\n\t\t}\n\t\tconst previous = document.body.style.overflow\n\t\tdocument.body.style.overflow = 'hidden'\n\t\treturn () => {\n\t\t\tdocument.body.style.overflow = previous\n\t\t}\n\t}, [active])\n}\n","'use client'\n\nimport { createElement, type ReactNode, useEffect, useRef } from 'react'\nimport { Backdrop } from './Backdrop'\nimport { useDismiss } from './useDismiss'\nimport { useFocusTrap } from './useFocusTrap'\nimport { useScrollLock } from './useScrollLock'\n\nexport type DialogSurfaceProps = {\n\topen: boolean\n\tonClose: () => void\n\t/** Accessible name; pass either label or labelledBy. */\n\tlabel?: string\n\tlabelledBy?: string\n\t/** CSS data hook, e.g. 'modal' | 'drawer'. */\n\tsurface?: string\n\tcloseLabel?: string\n\tcloseOnEscape?: boolean\n\tcloseOnOutsideClick?: boolean\n\tchildren?: ReactNode\n}\n\n/**\n * Accessible, dependency-free overlay surface: backdrop + role=dialog/aria-modal, focus-trap,\n * scroll-lock, Escape/outside-click dismiss, initial focus, and focus restore on close. Composes the\n * exported primitives so a consumer can rebuild it from the same parts.\n */\nexport const DialogSurface = ({\n\topen,\n\tonClose,\n\tlabel,\n\tlabelledBy,\n\tsurface,\n\tcloseLabel = 'Close',\n\tcloseOnEscape,\n\tcloseOnOutsideClick,\n\tchildren,\n}: DialogSurfaceProps) => {\n\tconst ref = useRef<HTMLDivElement>(null)\n\tconst restoreRef = useRef<HTMLElement | null>(null)\n\n\tuseScrollLock(open)\n\tuseFocusTrap(ref, open)\n\tuseDismiss({ active: open, onDismiss: onClose, closeOnEscape, closeOnOutsideClick }, ref)\n\n\tuseEffect(() => {\n\t\tif (!open) {\n\t\t\treturn\n\t\t}\n\t\trestoreRef.current =\n\t\t\tdocument.activeElement instanceof HTMLElement ? document.activeElement : null\n\t\tref.current?.focus()\n\t\treturn () => {\n\t\t\trestoreRef.current?.focus()\n\t\t}\n\t}, [open])\n\n\tif (!open) {\n\t\treturn null\n\t}\n\n\treturn createElement('div', { 'data-fb-overlay': surface ?? '' }, [\n\t\tcreateElement(Backdrop, { key: 'backdrop', onClick: onClose }),\n\t\tcreateElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tkey: 'surface',\n\t\t\t\tref,\n\t\t\t\trole: 'dialog',\n\t\t\t\t'aria-modal': true,\n\t\t\t\t'aria-label': labelledBy ? undefined : label,\n\t\t\t\t'aria-labelledby': labelledBy,\n\t\t\t\t'data-fb-dialog': surface ?? '',\n\t\t\t\ttabIndex: -1,\n\t\t\t},\n\t\t\t[\n\t\t\t\tcreateElement(\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: 'close',\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t'data-fb-dialog-close': '',\n\t\t\t\t\t\t'aria-label': closeLabel,\n\t\t\t\t\t\tonClick: onClose,\n\t\t\t\t\t},\n\t\t\t\t\t'\\xd7'\n\t\t\t\t),\n\t\t\t\tcreateElement('div', { key: 'body' }, children),\n\t\t\t]\n\t\t),\n\t])\n}\n","'use client'\n\nimport { createElement } from 'react'\nimport { defaultPresentationDescriptors } from '../../presentations/defaults'\nimport { DialogSurface } from './DialogSurface'\nimport type { FormPresentation, PresentationWrapperProps } from './types'\n\nconst overlayWrapper = (surface: 'modal' | 'drawer') => {\n\tconst Wrapper = ({ open, onClose, title, closeLabel, children }: PresentationWrapperProps) =>\n\t\tcreateElement(DialogSurface, { open, onClose, label: title, surface, closeLabel }, children)\n\tWrapper.displayName = `${surface}Wrapper`\n\treturn Wrapper\n}\n\nexport const defaultPresentations: Record<string, FormPresentation> = {\n\tpage: defaultPresentationDescriptors.page,\n\tinline: defaultPresentationDescriptors.inline,\n\tmodal: { ...defaultPresentationDescriptors.modal, Wrapper: overlayWrapper('modal') },\n\tdrawer: { ...defaultPresentationDescriptors.drawer, Wrapper: overlayWrapper('drawer') },\n}\n","import { defaultPresentations } from './presentations'\nimport type { FormPresentation } from './types'\n\nexport type PresentationRegistry = Map<string, FormPresentation>\n\n/** `false` removes, `true` keeps the default, a presentation adds or replaces one. */\nexport type PresentationOption = boolean | FormPresentation\n\nexport type PresentationsConfig = Record<string, PresentationOption>\n\nexport const resolvePresentations = (\n\tdefaults: Record<string, FormPresentation> = defaultPresentations,\n\tconfig: PresentationsConfig = {}\n): PresentationRegistry => {\n\tconst registry: PresentationRegistry = new Map(Object.entries(defaults))\n\tfor (const [name, option] of Object.entries(config)) {\n\t\tif (option === false) {\n\t\t\tregistry.delete(name)\n\t\t} else if (option === true) {\n\t\t\t// keep the default\n\t\t} else {\n\t\t\tregistry.set(name, option)\n\t\t}\n\t}\n\treturn registry\n}\n","import { interpolate } from '../recall/interpolate'\nimport type { RecallResolver } from '../recall/resolver'\nimport type { FormFieldInstance } from '../submissions/types'\n\ntype Option = { label?: string; value?: string }\n\n/**\n * Return a copy of the field with recall tokens interpolated in its label, description, and option\n * labels. Never alters `name` (identity for React keys and state lookups must stay stable).\n */\nexport const applyRecall = (\n\tfield: FormFieldInstance,\n\tresolve: RecallResolver\n): FormFieldInstance => {\n\tconst next: FormFieldInstance = { ...field }\n\tif (typeof field.label === 'string') {\n\t\tnext.label = interpolate(field.label, resolve)\n\t}\n\tif (typeof field.description === 'string') {\n\t\tnext.description = interpolate(field.description, resolve)\n\t}\n\tif (Array.isArray(field.options)) {\n\t\tnext.options = (field.options as Option[]).map((option) =>\n\t\t\toption && typeof option.label === 'string'\n\t\t\t\t? { ...option, label: interpolate(option.label, resolve) }\n\t\t\t\t: option\n\t\t)\n\t}\n\treturn next\n}\n","import type { FieldRenderer } from './contract'\n\nexport type RendererRegistry = Map<string, FieldRenderer>\n\n/** Per-type renderer override: `false` removes, `true` keeps the default, a renderer adds or replaces one. */\nexport type RendererOption = boolean | FieldRenderer\n\nexport type RenderersConfig = Record<string, RendererOption>\n\n/**\n * Resolve the active renderer registry from the defaults and a consumer override map. `false` removes a\n * type, `true` keeps the default (no-op when none exists), a renderer adds a new type or replaces one.\n * Mirrors the field-type and validation-rule registry convention.\n */\nexport const resolveRenderers = (\n\tdefaults: Record<string, FieldRenderer>,\n\tconfig: RenderersConfig = {}\n): RendererRegistry => {\n\tconst registry: RendererRegistry = new Map(Object.entries(defaults))\n\tfor (const [type, option] of Object.entries(config)) {\n\t\tif (option === false) {\n\t\t\tregistry.delete(type)\n\t\t} else if (option === true) {\n\t\t\t// keep the default; no-op when no default exists for this key\n\t\t} else {\n\t\t\tregistry.set(type, option)\n\t\t}\n\t}\n\treturn registry\n}\n","'use client'\n\nimport type { ReactNode } from 'react'\n\nexport type FieldShellProps = {\n\t/** The control id this shell labels and describes. */\n\tid: string\n\tlabel?: string\n\tdescription?: string\n\trequired?: boolean\n\terrors?: string[]\n\twarnings?: string[]\n\t/** id used for aria-describedby on the control; the shell renders description + messages under it. */\n\tdescribedById: string\n\tchildren: ReactNode\n}\n\n/**\n * Accessible wrapper for a single field: a `<label>` bound to the control, the control slot, an optional\n * description, and error/warning messages. The control inside must set `aria-describedby={describedById}`\n * and `aria-invalid` when errors exist; this shell renders the matching `id={describedById}` region.\n */\nexport const FieldShell = ({\n\tid,\n\tlabel,\n\tdescription,\n\trequired,\n\terrors = [],\n\twarnings = [],\n\tdescribedById,\n\tchildren,\n}: FieldShellProps) => (\n\t<div className=\"fb-field\" data-invalid={errors.length > 0 ? '' : undefined}>\n\t\t{label ? (\n\t\t\t<label className=\"fb-field__label\" htmlFor={id}>\n\t\t\t\t{label}\n\t\t\t\t{required ? (\n\t\t\t\t\t<span className=\"fb-field__required\" aria-hidden=\"true\">\n\t\t\t\t\t\t{' *'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</label>\n\t\t) : null}\n\t\t{children}\n\t\t<div id={describedById} className=\"fb-field__messages\">\n\t\t\t{description ? <p className=\"fb-field__description\">{description}</p> : null}\n\t\t\t{errors.length > 0 ? (\n\t\t\t\t<div role=\"alert\" aria-atomic=\"true\" className=\"fb-field__errors\">\n\t\t\t\t\t{errors.map((message) => (\n\t\t\t\t\t\t<p key={message} className=\"fb-field__error\">\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t{warnings.map((message) => (\n\t\t\t\t<p key={message} className=\"fb-field__warning\">\n\t\t\t\t\t{message}\n\t\t\t\t</p>\n\t\t\t))}\n\t\t</div>\n\t</div>\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\n\n/** Read-only renderer for a calculation field: the value is derived, never user-editable, so it shows in an `<output>` rather than an input. */\nexport const calculationRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, value, errors, warnings, required }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<output id={id} className=\"fb-field__calc\" aria-describedby={describedById}>\n\t\t\t\t\t{value == null ? '' : String(value)}\n\t\t\t\t</output>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nexport type CheckboxProps = {\n\tid: string\n\tname: string\n\tchecked: boolean\n\tonChange: (checked: boolean) => void\n\tonBlur?: () => void\n\trequired?: boolean\n\tdisabled?: boolean\n\tinvalid?: boolean\n\tdescribedById?: string\n}\n\nexport const Checkbox = ({\n\tid,\n\tname,\n\tchecked,\n\tonChange,\n\tonBlur,\n\trequired,\n\tdisabled,\n\tinvalid,\n\tdescribedById,\n}: CheckboxProps) => (\n\t<input\n\t\ttype=\"checkbox\"\n\t\tclassName=\"fb-checkbox\"\n\t\tid={id}\n\t\tname={name}\n\t\tchecked={checked}\n\t\trequired={required}\n\t\tdisabled={disabled}\n\t\taria-invalid={invalid || undefined}\n\t\taria-describedby={describedById}\n\t\tonChange={(e) => onChange(e.target.checked)}\n\t\tonBlur={onBlur}\n\t/>\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\nexport const checkboxRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nimport { useId } from 'react'\nimport type { ConsentLink } from '../../consent/defineConsentSource'\nimport { defineFieldRenderer } from '../contract'\nimport { Checkbox } from '../primitives/Checkbox'\nimport { FieldShell } from '../primitives/FieldShell'\n\nexport const consentRenderer = defineFieldRenderer<boolean>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\t// The visible agreement text labels the checkbox. Prefer the explicit `statement`; fall back to the\n\t\t// field `label` so a consent field authored with only a label (or a blank statement) is never an\n\t\t// unlabelled control (a11y). A blank or whitespace-only value counts as absent.\n\t\tconst text = (raw: unknown): string | undefined =>\n\t\t\ttypeof raw === 'string' && raw.trim() !== '' ? raw : undefined\n\t\tconst statement = text(field.statement) ?? text(field.label)\n\n\t\tconst links: ConsentLink[] = Array.isArray(field.consentLinks)\n\t\t\t? (field.consentLinks as ConsentLink[])\n\t\t\t: (() => {\n\t\t\t\t\tconst sc = field.sourceConfig as Record<string, unknown> | undefined\n\t\t\t\t\tif (sc && typeof sc.url === 'string' && sc.url) {\n\t\t\t\t\t\treturn [{ label: typeof sc.label === 'string' ? sc.label : 'Policy', url: sc.url }]\n\t\t\t\t\t}\n\t\t\t\t\treturn []\n\t\t\t\t})()\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={statement}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Checkbox\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tchecked={value ?? false}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t\t{links.length > 0 ? (\n\t\t\t\t\t<span className=\"fb-consent__links\">\n\t\t\t\t\t\t{links.map((link) => (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tkey={link.url}\n\t\t\t\t\t\t\t\thref={link.url}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"fb-consent__link\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{link.label}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nexport type InputProps = {\n\tid: string\n\tname: string\n\ttype?: 'text' | 'email' | 'number'\n\tvalue: string\n\tonChange: (value: string) => void\n\tonBlur?: () => void\n\tplaceholder?: string\n\trequired?: boolean\n\tdisabled?: boolean\n\tinvalid?: boolean\n\tdescribedById?: string\n}\n\nexport const Input = ({\n\tid,\n\tname,\n\ttype = 'text',\n\tvalue,\n\tonChange,\n\tonBlur,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tinvalid,\n\tdescribedById,\n}: InputProps) => (\n\t<input\n\t\tid={id}\n\t\tname={name}\n\t\ttype={type}\n\t\tclassName=\"fb-input\"\n\t\tvalue={value}\n\t\tplaceholder={placeholder}\n\t\trequired={required}\n\t\tdisabled={disabled}\n\t\taria-invalid={invalid || undefined}\n\t\taria-describedby={describedById}\n\t\tonChange={(event) => onChange(event.target.value)}\n\t\tonBlur={onBlur}\n\t/>\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const emailRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","export type UploadFileInput = {\n\tfile: File\n\t/** Upload collection slug. Defaults to `form-uploads`. */\n\tcollection?: string\n\tapiRoute?: string\n\tfetchImpl?: typeof fetch\n}\n\nexport type UploadFileResult = { ok: true; id: string | number } | { ok: false; message?: string }\n\n/**\n * Upload one file to a Payload upload collection (`POST {apiRoute}/{collection}`, multipart) and return its\n * id, which the file field stores as its value. The server re-derives the file metadata from the stored doc\n * at submit, so the client is never trusted for it. Pure: inject `fetchImpl` in tests.\n */\nexport const uploadFile = async (input: UploadFileInput): Promise<UploadFileResult> => {\n\tconst { file, collection = 'form-uploads', apiRoute = '/api', fetchImpl = fetch } = input\n\tconst body = new FormData()\n\tbody.append('file', file)\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetchImpl(`${apiRoute}/${collection}`, { method: 'POST', body })\n\t} catch (error) {\n\t\treturn { ok: false, message: error instanceof Error ? error.message : 'Network error' }\n\t}\n\tif (!response.ok) {\n\t\treturn { ok: false, message: `Upload failed (${response.status})` }\n\t}\n\tconst data = (await response.json().catch(() => ({}))) as { doc?: { id?: string | number } }\n\tconst id = data.doc?.id\n\treturn id == null ? { ok: false, message: 'No id returned' } : { ok: true, id }\n}\n","'use client'\n\nimport { type ChangeEvent, useId, useState } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { uploadFile } from '../uploadFile'\n\nconst acceptOf = (mimeTypes: unknown): string | undefined => {\n\tif (!Array.isArray(mimeTypes)) {\n\t\treturn undefined\n\t}\n\tconst types = mimeTypes.filter((entry): entry is string => typeof entry === 'string')\n\treturn types.length > 0 ? types.join(',') : undefined\n}\n\n/**\n * Headless file renderer: a native file input that uploads the chosen file to the upload collection and\n * stores the returned id as the field value. The server re-derives filename/mimeType/filesize from the\n * stored doc at submit, so the client value is only the id. Shows the uploaded filename with a clear\n * control and surfaces upload errors. Single file (v1); the upload posts to the default `/api` route.\n */\nexport const fileRenderer = defineFieldRenderer<string | number>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\tconst [uploading, setUploading] = useState(false)\n\t\tconst [filename, setFilename] = useState<string | undefined>(undefined)\n\t\tconst [localError, setLocalError] = useState<string | undefined>(undefined)\n\n\t\tconst collection = typeof field.relationTo === 'string' ? field.relationTo : 'form-uploads'\n\t\tconst accept = acceptOf(field.mimeTypes)\n\t\tconst allErrors = localError ? [...errors, localError] : errors\n\t\t// Show the just-uploaded filename, or a generic indicator when the field already holds an id (recall/prefill): the filename is not part of the client value.\n\t\tconst hasValue = value !== undefined && value !== null && value !== ''\n\t\tconst displayName = filename ?? (hasValue ? 'Uploaded file' : undefined)\n\n\t\tconst handleChange = async (event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst selected = event.target.files?.[0]\n\t\t\tif (!selected) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetUploading(true)\n\t\t\tsetLocalError(undefined)\n\t\t\tconst result = await uploadFile({ file: selected, collection })\n\t\t\tsetUploading(false)\n\t\t\tif (result.ok) {\n\t\t\t\tsetFilename(selected.name)\n\t\t\t\tonChange(result.id)\n\t\t\t} else {\n\t\t\t\tsetLocalError(result.message ?? 'Upload failed')\n\t\t\t}\n\t\t}\n\n\t\tconst clear = () => {\n\t\t\tsetFilename(undefined)\n\t\t\tsetLocalError(undefined)\n\t\t\tonChange('')\n\t\t}\n\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={allErrors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tdisabled={disabled || uploading}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tvoid handleChange(event)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\taria-invalid={allErrors.length > 0}\n\t\t\t\t\taria-describedby={describedById}\n\t\t\t\t/>\n\t\t\t\t{uploading ? (\n\t\t\t\t\t<p className=\"fb-field__file-status\" aria-live=\"polite\">\n\t\t\t\t\t\tUploading\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t\t{displayName ? (\n\t\t\t\t\t<p className=\"fb-field__file-name\">\n\t\t\t\t\t\t<span>{displayName}</span>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"fb-field__file-clear\"\n\t\t\t\t\t\t\tonClick={clear}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</p>\n\t\t\t\t) : null}\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const numberRenderer = defineFieldRenderer<number | undefined>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tvalue={value == null ? '' : String(value)}\n\t\t\t\t\tonChange={(raw) => {\n\t\t\t\t\t\tconst next = Number(raw)\n\t\t\t\t\t\tonChange(raw === '' || Number.isNaN(next) ? undefined : next)\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nexport type SelectOption = { label: string; value: string }\n\nexport type SelectProps = {\n\tid: string\n\tname: string\n\tvalue: string\n\toptions: SelectOption[]\n\tonChange: (value: string) => void\n\tonBlur?: () => void\n\trequired?: boolean\n\tdisabled?: boolean\n\tinvalid?: boolean\n\tdescribedById?: string\n\tplaceholder?: string\n}\n\nexport const Select = ({\n\tid,\n\tname,\n\tvalue,\n\toptions,\n\tonChange,\n\tonBlur,\n\trequired,\n\tdisabled,\n\tinvalid,\n\tdescribedById,\n\tplaceholder,\n}: SelectProps) => (\n\t<select\n\t\tid={id}\n\t\tname={name}\n\t\tclassName=\"fb-select\"\n\t\tvalue={value}\n\t\trequired={required}\n\t\tdisabled={disabled}\n\t\taria-invalid={invalid || undefined}\n\t\taria-describedby={describedById}\n\t\tonChange={(event) => onChange(event.target.value)}\n\t\tonBlur={onBlur}\n\t>\n\t\t{placeholder !== undefined ? <option value=\"\">{placeholder}</option> : null}\n\t\t{options.map((option) => (\n\t\t\t<option key={option.value} value={option.value}>\n\t\t\t\t{option.label}\n\t\t\t</option>\n\t\t))}\n\t</select>\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Select } from '../primitives/Select'\n\nexport const selectRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\tconst options = Array.isArray(field.options)\n\t\t\t? (field.options as { label: string; value: string }[])\n\t\t\t: []\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Select\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\toptions={options}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Input } from '../primitives/Input'\n\nexport const textRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\ttype=\"text\"\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","'use client'\n\nexport type TextareaProps = {\n\tid: string\n\tname: string\n\tvalue: string\n\tonChange: (value: string) => void\n\tonBlur?: () => void\n\tplaceholder?: string\n\trequired?: boolean\n\tdisabled?: boolean\n\tinvalid?: boolean\n\tdescribedById?: string\n}\n\nexport const Textarea = ({\n\tid,\n\tname,\n\tvalue,\n\tonChange,\n\tonBlur,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tinvalid,\n\tdescribedById,\n}: TextareaProps) => (\n\t<textarea\n\t\tid={id}\n\t\tname={name}\n\t\tclassName=\"fb-textarea\"\n\t\tvalue={value}\n\t\tplaceholder={placeholder}\n\t\trequired={required}\n\t\tdisabled={disabled}\n\t\taria-invalid={invalid || undefined}\n\t\taria-describedby={describedById}\n\t\tonChange={(e) => onChange(e.target.value)}\n\t\tonBlur={onBlur}\n\t/>\n)\n","'use client'\n\nimport { useId } from 'react'\nimport { defineFieldRenderer } from '../contract'\nimport { FieldShell } from '../primitives/FieldShell'\nimport { Textarea } from '../primitives/Textarea'\n\nexport const textareaRenderer = defineFieldRenderer<string>(\n\t({ field, name, value, onChange, onBlur, errors, warnings, required, disabled }) => {\n\t\tconst id = useId()\n\t\tconst describedById = `${id}-desc`\n\t\treturn (\n\t\t\t<FieldShell\n\t\t\t\tid={id}\n\t\t\t\tlabel={field.label}\n\t\t\t\tdescription={typeof field.description === 'string' ? field.description : undefined}\n\t\t\t\trequired={required}\n\t\t\t\terrors={errors}\n\t\t\t\twarnings={warnings}\n\t\t\t\tdescribedById={describedById}\n\t\t\t>\n\t\t\t\t<Textarea\n\t\t\t\t\tid={id}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={value ?? ''}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\tplaceholder={typeof field.placeholder === 'string' ? field.placeholder : undefined}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={errors.length > 0}\n\t\t\t\t\tdescribedById={describedById}\n\t\t\t\t/>\n\t\t\t</FieldShell>\n\t\t)\n\t}\n)\n","import type { FieldRenderer } from '../contract'\nimport { calculationRenderer } from './calculation'\nimport { checkboxRenderer } from './checkbox'\nimport { consentRenderer } from './consent'\nimport { emailRenderer } from './email'\nimport { fileRenderer } from './file'\nimport { numberRenderer } from './number'\nimport { selectRenderer } from './select'\nimport { textRenderer } from './text'\nimport { textareaRenderer } from './textarea'\n\n/** The built-in field renderers, keyed by field-type slug. Override via the renderer registry. */\nexport const defaultRenderers: Record<string, FieldRenderer> = {\n\tcalculation: calculationRenderer as FieldRenderer,\n\tcheckbox: checkboxRenderer as FieldRenderer,\n\tconsent: consentRenderer as FieldRenderer,\n\temail: emailRenderer as FieldRenderer,\n\tfile: fileRenderer as FieldRenderer,\n\tnumber: numberRenderer as FieldRenderer,\n\tselect: selectRenderer as FieldRenderer,\n\ttext: textRenderer as FieldRenderer,\n\ttextarea: textareaRenderer as FieldRenderer,\n}\n","import { evaluateCondition } from '../conditions/evaluate'\nimport { defaultFieldDefinitions } from '../fields/builtin'\nimport { buildRegistry, type FieldTypeRegistry } from '../fields/registry'\nimport type { AnyFormFieldDefinition } from '../fields/types'\nimport type { FormFieldInstance } from '../submissions/types'\nimport { defaultValidationRules } from '../validation/builtin'\nimport { buildRuleRegistry, type ValidationRuleRegistry } from '../validation/registry'\nimport type { AnyValidationRuleDefinition } from '../validation/types'\n\n/** Build the field-type registry from the bundled defaults plus any consumer-supplied extra definitions. */\nexport const buildFieldTypeRegistry = (extra: AnyFormFieldDefinition[] = []): FieldTypeRegistry =>\n\tbuildRegistry([...defaultFieldDefinitions, ...extra])\n\n/** Build the validation-rule registry from the bundled defaults plus consumer extras. */\nexport const buildValidationRuleRegistry = (\n\textra: AnyValidationRuleDefinition[] = []\n): ValidationRuleRegistry => buildRuleRegistry([...defaultValidationRules, ...extra])\n\n/** The subset of fields currently visible, evaluating each field's `visibleWhen` against the answers. */\nexport const visibleFields = (\n\tfields: FormFieldInstance[],\n\tvalues: Record<string, unknown>\n): FormFieldInstance[] => fields.filter((field) => evaluateCondition(field.visibleWhen, values))\n","export type FieldErrors = Record<string, string[]>\n\nexport type FormState = {\n\tvalues: Record<string, unknown>\n\terrors: FieldErrors\n\twarnings: FieldErrors\n\ttouched: Record<string, boolean>\n\tsubmitting: boolean\n\tsubmitted: boolean\n\tsubmitAttempted: boolean\n\tsubmitError?: string\n}\n\nexport type FormAction =\n\t| { type: 'SET_VALUE'; name: string; value: unknown }\n\t| { type: 'TOUCH'; name: string }\n\t| { type: 'SET_FIELD_ISSUES'; name: string; errors: string[]; warnings: string[] }\n\t| { type: 'SET_ALL_ISSUES'; errors: FieldErrors; warnings: FieldErrors }\n\t| { type: 'SUBMIT_START' }\n\t| { type: 'SUBMIT_SUCCESS' }\n\t| { type: 'SUBMIT_ERROR'; message: string }\n\nexport const initialFormState = (values: Record<string, unknown>): FormState => ({\n\tvalues,\n\terrors: {},\n\twarnings: {},\n\ttouched: {},\n\tsubmitting: false,\n\tsubmitted: false,\n\tsubmitAttempted: false,\n})\n\n/** Changing a value clears that field's prior errors (re-validated by the caller). */\nexport const formReducer = (state: FormState, action: FormAction): FormState => {\n\tswitch (action.type) {\n\t\tcase 'SET_VALUE': {\n\t\t\tconst { [action.name]: _removed, ...restErrors } = state.errors\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tvalues: { ...state.values, [action.name]: action.value },\n\t\t\t\terrors: restErrors,\n\t\t\t}\n\t\t}\n\t\tcase 'TOUCH':\n\t\t\treturn state.touched[action.name]\n\t\t\t\t? state\n\t\t\t\t: { ...state, touched: { ...state.touched, [action.name]: true } }\n\t\tcase 'SET_FIELD_ISSUES':\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\terrors: { ...state.errors, [action.name]: action.errors },\n\t\t\t\twarnings: { ...state.warnings, [action.name]: action.warnings },\n\t\t\t}\n\t\tcase 'SET_ALL_ISSUES':\n\t\t\treturn { ...state, errors: action.errors, warnings: action.warnings, submitAttempted: true }\n\t\tcase 'SUBMIT_START':\n\t\t\treturn { ...state, submitting: true, submitError: undefined }\n\t\tcase 'SUBMIT_SUCCESS':\n\t\t\treturn { ...state, submitting: false, submitted: true }\n\t\tcase 'SUBMIT_ERROR':\n\t\t\treturn { ...state, submitting: false, submitError: action.message }\n\t\tdefault:\n\t\t\treturn state\n\t}\n}\n","import type { SubmissionValue } from '../submissions/types'\n\nexport type SubmitFormInput = {\n\tformId: number | string\n\tvalues: SubmissionValue[]\n\t/** Payload API route prefix; defaults to `/api`. */\n\tapiRoute?: string\n\t/** Injectable for testing; defaults to global `fetch`. */\n\tfetchImpl?: typeof fetch\n}\n\nexport type SubmitFormResult =\n\t| { ok: true; submissionId?: string }\n\t| { ok: false; fieldErrors?: Record<string, string[]>; message?: string }\n\ntype ValidationErrorBody = {\n\terrors?: Array<{\n\t\tmessage?: string\n\t\tdata?: { errors?: Array<{ path?: string; message?: string }> }\n\t}>\n}\n\nconst toFieldErrors = (body: ValidationErrorBody): Record<string, string[]> => {\n\tconst nested = body.errors?.[0]?.data?.errors ?? []\n\tconst map: Record<string, string[]> = {}\n\tfor (const entry of nested) {\n\t\tif (typeof entry.path === 'string' && typeof entry.message === 'string') {\n\t\t\tmap[entry.path] = [...(map[entry.path] ?? []), entry.message]\n\t\t}\n\t}\n\treturn map\n}\n\n/**\n * The default submission transport: POST `{apiRoute}/form-submissions` with `{ form, values }`. On 201\n * returns the created submission id; on a 400 Payload `ValidationError` maps `data.errors[].path` to\n * per-field messages; otherwise returns a generic message. Pure: inject `fetchImpl` in tests.\n */\nexport const submitForm = async (input: SubmitFormInput): Promise<SubmitFormResult> => {\n\tconst { formId, values, apiRoute = '/api', fetchImpl = fetch } = input\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetchImpl(`${apiRoute}/form-submissions`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ form: formId, values }),\n\t\t})\n\t} catch (error) {\n\t\treturn { ok: false, message: error instanceof Error ? error.message : 'Network error' }\n\t}\n\tif (response.ok) {\n\t\tconst data = (await response.json().catch(() => ({}))) as { doc?: { id?: number | string } }\n\t\tconst id = data.doc?.id\n\t\treturn { ok: true, submissionId: id === undefined ? undefined : String(id) }\n\t}\n\tif (response.status === 400) {\n\t\tconst body = (await response.json().catch(() => ({}))) as ValidationErrorBody\n\t\tconst fieldErrors = toFieldErrors(body)\n\t\tif (Object.keys(fieldErrors).length > 0) {\n\t\t\treturn { ok: false, fieldErrors }\n\t\t}\n\t\treturn { ok: false, message: body.errors?.[0]?.message ?? 'Validation failed' }\n\t}\n\treturn { ok: false, message: `Request failed (${response.status})` }\n}\n\n/** A consumer override for the transport: given the form id + values, resolve to a submit result. */\nexport type SubmitHandler = (input: {\n\tformId: number | string\n\tvalues: SubmissionValue[]\n}) => Promise<SubmitFormResult>\n","'use client'\n\nimport { useCallback } from 'react'\nimport { useFormContext } from './FormContext'\n\nexport type UseFieldResult<TValue = unknown> = {\n\tvalue: TValue | undefined\n\terrors: string[]\n\twarnings: string[]\n\ttouched: boolean\n\tsetValue: (value: TValue) => void\n\t/** Mark touched and validate now (call on blur). */\n\tonBlur: () => void\n}\n\n/** Bind one field by name to the form controller: its value, issues, and change/blur handlers. */\nexport const useField = <TValue = unknown>(name: string): UseFieldResult<TValue> => {\n\tconst { state, dispatch, validateField } = useFormContext()\n\tconst touched = state.touched[name] ?? false\n\tconst showIssues = touched || state.submitAttempted\n\tconst value = state.values[name] as TValue | undefined\n\n\tconst setValue = useCallback(\n\t\t(next: TValue) => {\n\t\t\tdispatch({ type: 'SET_VALUE', name, value: next })\n\t\t\tif (touched || state.submitAttempted) {\n\t\t\t\tvalidateField(name, next)\n\t\t\t}\n\t\t},\n\t\t[dispatch, name, touched, state.submitAttempted, validateField]\n\t)\n\n\tconst onBlur = useCallback(() => {\n\t\tdispatch({ type: 'TOUCH', name })\n\t\tvalidateField(name, value)\n\t}, [dispatch, name, validateField, value])\n\n\treturn {\n\t\tvalue,\n\t\terrors: showIssues ? (state.errors[name] ?? []) : [],\n\t\twarnings: showIssues ? (state.warnings[name] ?? []) : [],\n\t\ttouched,\n\t\tsetValue,\n\t\tonBlur,\n\t}\n}\n","import type { FieldTypeRegistry } from '../fields/registry'\nimport type { Translate } from '../fields/types'\nimport type { FormFieldInstance } from '../submissions/types'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport { runValidation } from '../validation/runValidation'\n\nexport type ValidateFieldInput = {\n\tfield: FormFieldInstance\n\tvalue: unknown\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tanswers: Record<string, unknown>\n\tlocale: string\n\tt: Translate\n}\n\nexport type ValidateFieldResult = { errors: string[]; warnings: string[] }\n\n/**\n * Run client-side validation for one field, reusing the shared engine in `mode: 'client'` (server-only\n * rules are skipped, no `req`/`payload`). Splits issues into blocking errors and advisory warnings.\n */\nexport const validateFieldValue = async (\n\tinput: ValidateFieldInput\n): Promise<ValidateFieldResult> => {\n\tconst { field, value, registry, ruleRegistry, answers, locale, t } = input\n\tconst { errors: issues } = await runValidation({\n\t\tfield,\n\t\tfieldDefinition: registry.get(field.blockType),\n\t\tvalue,\n\t\tfieldType: field.blockType,\n\t\truleRegistry,\n\t\tanswers,\n\t\tlocale,\n\t\tt,\n\t\toperation: 'create',\n\t\tevent: 'onChange',\n\t\tmode: 'client',\n\t})\n\treturn {\n\t\terrors: issues.filter((issue) => issue.severity === 'error').map((issue) => issue.message),\n\t\twarnings: issues.filter((issue) => issue.severity === 'warning').map((issue) => issue.message),\n\t}\n}\n","'use client'\n\nimport {\n\tcreateElement,\n\ttype FormEvent as ReactFormEvent,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { calcExpressionOf, computeCalcFields } from '../calc/computeCalcFields'\nimport { evaluateCondition } from '../conditions/evaluate'\nimport { noopEventSink } from '../events/noopSink'\nimport type { FormEventSink } from '../events/types'\nimport type { AnyFormFieldDefinition } from '../fields/types'\nimport { firstStepId, isTerminalStepId, resolveNextStepId, stepFieldNames } from '../flow/engine'\nimport type { FormFlow } from '../flow/types'\nimport { defaultPresentationDescriptors } from '../presentations/defaults'\nimport { interpolate } from '../recall/interpolate'\nimport { buildRecallResolver } from '../recall/resolver'\nimport { CAPTCHA_TOKEN_KEY, DEFAULT_HONEYPOT_FIELD } from '../spam/constants'\nimport type { FormFieldInstance, SubmissionValue } from '../submissions/types'\nimport type { AnyValidationRuleDefinition } from '../validation/types'\nimport type { FieldRenderer, RendererTranslate } from './contract'\nimport { emitFormEvent } from './events'\nimport { FormContext, type FormStepInfo } from './FormContext'\nimport { type FieldWidth, FormLayout, widthProps } from './FormLayout'\nimport { Honeypot } from './Honeypot'\nimport { defaultPresentations } from './presentation/presentations'\nimport { type PresentationsConfig, resolvePresentations } from './presentation/registry'\nimport type { FormPresentation } from './presentation/types'\nimport { applyRecall } from './recall'\nimport { type RenderersConfig, resolveRenderers } from './registry'\nimport { defaultRenderers } from './renderers'\nimport { buildFieldTypeRegistry, buildValidationRuleRegistry, visibleFields } from './resolveForm'\nimport { type FieldErrors, type FormAction, formReducer, initialFormState } from './state'\nimport { type SubmitFormResult, type SubmitHandler, submitForm } from './submitForm'\nimport { useField } from './useField'\nimport { validateFieldValue } from './validateField'\n\nexport type FormDocument = {\n\tid: number | string\n\tfields: FormFieldInstance[]\n\tflow?: FormFlow\n\t/** Stored presentation name; overridden by the `presentation` prop. */\n\tdefaultPresentation?: string\n}\n\nexport type FormProps = {\n\tform: FormDocument\n\tfieldTypes?: AnyFormFieldDefinition[]\n\trules?: AnyValidationRuleDefinition[]\n\trenderers?: RenderersConfig\n\tapiRoute?: string\n\tonSubmit?: SubmitHandler\n\tonSuccess?: (submissionId?: string) => void\n\tonError?: (message: string) => void\n\tevents?: FormEventSink\n\tt?: RendererTranslate\n\tlocale?: string\n\tlayout?: boolean\n\tsubmitLabel?: string\n\tnextLabel?: string\n\tbackLabel?: string\n\t/** Label for the overlay close control (modal/drawer). */\n\tcloseLabel?: string\n\tsuccessMessage?: string\n\t/** Active presentation: a name into the registry or an inline presentation. Overrides the form's stored default. */\n\tpresentation?: string | FormPresentation\n\t/** Per-render presentation overrides merged onto the defaults (add, replace, or `false` to remove). */\n\tpresentations?: PresentationsConfig\n\t/** Invoked when an overlay presentation dismisses (close button, Escape, outside click, or `dismissOnSuccess`). */\n\tonClose?: () => void\n\t/** Accessible name for an overlay surface. */\n\ttitle?: string\n\t/** Seed initial field values (e.g. from `valuesFromSearchParams`). Still validated on submit. */\n\tinitialValues?: Record<string, unknown>\n\t/** Honeypot decoy (on by default). `false` removes it; `{ name }` matches a customized server `spam.honeypot.fieldName`. */\n\thoneypot?: false | { name?: string }\n\t/** A token from your captcha widget; verified server-side when a captcha provider is configured. */\n\tcaptchaToken?: string\n\t/** Custom layout: render fields with `useField`/`useFormState` instead of the auto-rendered field loop. */\n\tchildren?: ReactNode\n}\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\nconst FIELD_WIDTHS = new Set<string>(['full', 'half', 'third', 'twoThirds'])\n\ntype FieldHostProps = {\n\tfield: FormFieldInstance\n\trenderer: FieldRenderer\n\tlocale: string\n\tt: RendererTranslate\n}\n\nconst FieldHost = ({ field, renderer, locale, t }: FieldHostProps) => {\n\tconst id = useId()\n\tconst { value, errors, warnings, setValue, onBlur } = useField(field.name)\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: setValue,\n\t\tonBlur,\n\t\terrors,\n\t\twarnings,\n\t\trequired: Boolean(field.required),\n\t\tlocale,\n\t\tt,\n\t})\n}\n\ntype CalcFieldHostProps = FieldHostProps & { value: unknown }\n\n/** Hosts a derived (calc) field: read-only, value supplied from `effectiveValues`, never bound via `useField`. */\nconst CalcFieldHost = ({ field, renderer, value, locale, t }: CalcFieldHostProps) => {\n\tconst id = useId()\n\treturn createElement(renderer, {\n\t\tfield,\n\t\tid,\n\t\tname: field.name,\n\t\tvalue,\n\t\tonChange: () => {},\n\t\tonBlur: () => {},\n\t\terrors: [],\n\t\twarnings: [],\n\t\trequired: false,\n\t\tdisabled: true,\n\t\tlocale,\n\t\tt,\n\t})\n}\n\n/** The headless form controller: state, progressive client validation, conditional visibility, submission, events. */\nexport const Form = ({\n\tform,\n\tfieldTypes,\n\trules,\n\trenderers,\n\tapiRoute,\n\tonSubmit,\n\tonSuccess,\n\tonError,\n\tevents,\n\tt,\n\tlocale = 'en',\n\tlayout,\n\tsubmitLabel = 'Submit',\n\tnextLabel = 'Next',\n\tbackLabel = 'Back',\n\tcloseLabel = 'Close',\n\tsuccessMessage = 'Thank you.',\n\tpresentation,\n\tpresentations,\n\tonClose,\n\ttitle,\n\tinitialValues,\n\thoneypot,\n\tcaptchaToken,\n\tchildren,\n}: FormProps) => {\n\tconst honeypotName = honeypot === false ? null : (honeypot?.name ?? DEFAULT_HONEYPOT_FIELD)\n\tconst honeypotRef = useRef<HTMLInputElement>(null)\n\tconst registry = useMemo(() => buildFieldTypeRegistry(fieldTypes), [fieldTypes])\n\tconst ruleRegistry = useMemo(() => buildValidationRuleRegistry(rules), [rules])\n\tconst rendererRegistry = useMemo(() => resolveRenderers(defaultRenderers, renderers), [renderers])\n\tconst presentationRegistry = useMemo(\n\t\t() => resolvePresentations(defaultPresentations, presentations),\n\t\t[presentations]\n\t)\n\tconst activePresentation: FormPresentation =\n\t\ttypeof presentation === 'object'\n\t\t\t? presentation\n\t\t\t: (presentationRegistry.get(presentation ?? form.defaultPresentation ?? 'page') ??\n\t\t\t\tpresentationRegistry.get('page') ??\n\t\t\t\tdefaultPresentationDescriptors.page)\n\tconst fieldsByName = useMemo(\n\t\t() => new Map(form.fields.map((field) => [field.name, field])),\n\t\t[form.fields]\n\t)\n\tconst translate = useMemo<RendererTranslate>(() => t ?? ((key) => key), [t])\n\n\t// Latest-value refs so event emission and the mount/unmount effect tolerate an inline `events` prop or a changing form id.\n\tconst sinkRef = useRef<FormEventSink>(noopEventSink)\n\tsinkRef.current = events ?? noopEventSink\n\tconst formIdRef = useRef('')\n\tformIdRef.current = String(form.id)\n\n\tconst [state, rawDispatch] = useReducer(formReducer, form.fields, (fields) =>\n\t\tinitialFormState({\n\t\t\t...Object.fromEntries(fields.map((field) => [field.name, undefined])),\n\t\t\t...(initialValues ?? {}),\n\t\t})\n\t)\n\n\t// Authoritative values for derived (calc) fields, recomputed from user answers on every change. The\n\t// server recomputes these too at submit; the client copy drives the live calc renderer, recall, and submit.\n\tconst effectiveValues = useMemo(\n\t\t() => computeCalcFields(form.fields, state.values),\n\t\t[form.fields, state.values]\n\t)\n\n\tconst recall = useMemo(\n\t\t() =>\n\t\t\tbuildRecallResolver({\n\t\t\t\tfields: form.fields,\n\t\t\t\tvalues: effectiveValues,\n\t\t\t\tregistry,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}),\n\t\t[form.fields, effectiveValues, registry, locale, translate]\n\t)\n\n\t// Multi-step is active only when a flow declares two or more steps; otherwise this is an ordinary single-step form.\n\tconst flow = form.flow && form.flow.steps.length >= 2 ? form.flow : undefined\n\tconst [currentStepId, setCurrentStepId] = useState<string | undefined>(() =>\n\t\tflow ? firstStepId(flow) : undefined\n\t)\n\tconst [history, setHistory] = useState<string[]>([])\n\n\tconst startedRef = useRef(false)\n\tconst submittedRef = useRef(false)\n\tconst submittingRef = useRef(false)\n\tconst flowRef = useRef(flow)\n\tflowRef.current = flow\n\n\tconst dispatch = useCallback((action: FormAction) => {\n\t\tif (action.type === 'SET_VALUE' && !startedRef.current) {\n\t\t\tstartedRef.current = true\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.started' })\n\t\t}\n\t\trawDispatch(action)\n\t}, [])\n\n\tconst validateField = useCallback(\n\t\t(name: string, value: unknown) => {\n\t\t\tconst field = fieldsByName.get(name)\n\t\t\tif (!field) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst answers = { ...effectiveValues, [name]: value }\n\t\t\t// Mirror the server: a field whose `validateWhen` is unmet is not validated; clear any stale error.\n\t\t\tif (!evaluateCondition(field.validateWhen, answers)) {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors: [], warnings: [] })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvoid validateFieldValue({\n\t\t\t\tfield,\n\t\t\t\tvalue,\n\t\t\t\tregistry,\n\t\t\t\truleRegistry,\n\t\t\t\tanswers,\n\t\t\t\tlocale,\n\t\t\t\tt: translate,\n\t\t\t}).then(({ errors, warnings }) => {\n\t\t\t\trawDispatch({ type: 'SET_FIELD_ISSUES', name, errors, warnings })\n\t\t\t\tconst [firstError] = errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t\t[fieldsByName, effectiveValues, registry, ruleRegistry, locale, translate]\n\t)\n\n\tconst visible = visibleFields(form.fields, effectiveValues)\n\tconst stepNames = flow && currentStepId ? stepFieldNames(flow, currentStepId) : []\n\tconst stepVisible: FormFieldInstance[] = stepNames\n\t\t.map((name) => visible.find((field) => field.name === name))\n\t\t.filter((field): field is FormFieldInstance => Boolean(field))\n\n\tconst goNext = async () => {\n\t\tif (!flow || !currentStepId) {\n\t\t\treturn\n\t\t}\n\t\tconst results = await Promise.all(\n\t\t\tstepVisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tlet hasError = false\n\t\tfor (const result of results) {\n\t\t\trawDispatch({ type: 'TOUCH', name: result.field.name })\n\t\t\trawDispatch({\n\t\t\t\ttype: 'SET_FIELD_ISSUES',\n\t\t\t\tname: result.field.name,\n\t\t\t\terrors: result.errors,\n\t\t\t\twarnings: result.warnings,\n\t\t\t})\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\thasError = true\n\t\t\t}\n\t\t}\n\t\tif (hasError) {\n\t\t\treturn\n\t\t}\n\t\tconst next = resolveNextStepId(flow, currentStepId, state.values)\n\t\tif (!next) {\n\t\t\treturn\n\t\t}\n\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\ttype: 'step.completed',\n\t\t\tstepId: currentStepId,\n\t\t})\n\t\tsetHistory((prev) => [...prev, currentStepId])\n\t\tsetCurrentStepId(next)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: next })\n\t}\n\n\tconst goBack = () => {\n\t\tconst prev = history[history.length - 1]\n\t\tif (prev === undefined) {\n\t\t\treturn\n\t\t}\n\t\tsetHistory((entries) => entries.slice(0, -1))\n\t\tsetCurrentStepId(prev)\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: prev })\n\t}\n\n\tuseEffect(() => {\n\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.viewed' })\n\t\tconst mountFlow = flowRef.current\n\t\tif (mountFlow) {\n\t\t\tconst first = firstStepId(mountFlow)\n\t\t\tif (first) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'step.viewed', stepId: first })\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\tif (!submittedRef.current && !submittingRef.current) {\n\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, { type: 'form.abandoned' })\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst handleClose = useCallback(() => {\n\t\tonClose?.()\n\t}, [onClose])\n\n\tconst handleSubmit = async (event: ReactFormEvent<HTMLFormElement>) => {\n\t\tevent.preventDefault()\n\t\t// Re-entrancy guard: claim the in-flight slot before the async validation window so a fast second\n\t\t// activation (double-click, Enter + click) cannot reach the transport and POST the submission twice.\n\t\tif (submittingRef.current) {\n\t\t\treturn\n\t\t}\n\t\tsubmittingRef.current = true\n\t\tconst visible = visibleFields(form.fields, effectiveValues)\n\t\tconst results = await Promise.all(\n\t\t\t// Calc fields carry no rules and have no input; they are always satisfied, so skip validating them.\n\t\t\t// A field whose `validateWhen` is unmet is skipped too, mirroring the server (no client/server divergence).\n\t\t\tvisible\n\t\t\t\t.filter((field) => !calcExpressionOf(field))\n\t\t\t\t.filter((field) => evaluateCondition(field.validateWhen, effectiveValues))\n\t\t\t\t.map(async (field) => ({\n\t\t\t\t\tfield,\n\t\t\t\t\t...(await validateFieldValue({\n\t\t\t\t\t\tfield,\n\t\t\t\t\t\tvalue: effectiveValues[field.name],\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: effectiveValues,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt: translate,\n\t\t\t\t\t})),\n\t\t\t\t}))\n\t\t)\n\t\tconst errors: FieldErrors = {}\n\t\tconst warnings: FieldErrors = {}\n\t\tfor (const result of results) {\n\t\t\tif (result.errors.length > 0) {\n\t\t\t\terrors[result.field.name] = result.errors\n\t\t\t\tconst [firstError] = result.errors\n\t\t\t\tif (firstError !== undefined) {\n\t\t\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\t\t\ttype: 'field.errored',\n\t\t\t\t\t\tfield: result.field.name,\n\t\t\t\t\t\tmessage: firstError,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.warnings.length > 0) {\n\t\t\t\twarnings[result.field.name] = result.warnings\n\t\t\t}\n\t\t}\n\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors, warnings })\n\t\tif (Object.keys(errors).length > 0) {\n\t\t\tsubmittingRef.current = false\n\t\t\treturn\n\t\t}\n\t\trawDispatch({ type: 'SUBMIT_START' })\n\t\tconst values: SubmissionValue[] = visible\n\t\t\t.filter((field) => !isEmpty(effectiveValues[field.name]))\n\t\t\t.map((field) => ({ field: field.name, value: effectiveValues[field.name] }))\n\t\tif (honeypotName) {\n\t\t\tconst decoy = honeypotRef.current?.value ?? ''\n\t\t\tif (decoy !== '') {\n\t\t\t\tvalues.push({ field: honeypotName, value: decoy })\n\t\t\t}\n\t\t}\n\t\tif (captchaToken) {\n\t\t\tvalues.push({ field: CAPTCHA_TOKEN_KEY, value: captchaToken })\n\t\t}\n\t\tconst result: SubmitFormResult = onSubmit\n\t\t\t? await onSubmit({ formId: form.id, values })\n\t\t\t: await submitForm({ formId: form.id, values, apiRoute })\n\t\tsubmittingRef.current = false\n\t\tif (result.ok) {\n\t\t\tsubmittedRef.current = true\n\t\t\trawDispatch({ type: 'SUBMIT_SUCCESS' })\n\t\t\temitFormEvent(sinkRef.current, formIdRef.current, {\n\t\t\t\ttype: 'submission.created',\n\t\t\t\tsubmissionId: result.submissionId,\n\t\t\t})\n\t\t\tonSuccess?.(result.submissionId)\n\t\t\tif (activePresentation.dismissOnSuccess) {\n\t\t\t\thandleClose()\n\t\t\t}\n\t\t} else {\n\t\t\tif (result.fieldErrors) {\n\t\t\t\trawDispatch({ type: 'SET_ALL_ISSUES', errors: result.fieldErrors, warnings: {} })\n\t\t\t}\n\t\t\tconst message = result.message ?? 'Submission failed'\n\t\t\trawDispatch({ type: 'SUBMIT_ERROR', message })\n\t\t\tonError?.(message)\n\t\t}\n\t}\n\n\tconst step: FormStepInfo = flow\n\t\t? {\n\t\t\t\tflow,\n\t\t\t\tcurrentStepId,\n\t\t\t\tstepIndex: flow.steps.findIndex((s) => s.id === currentStepId),\n\t\t\t\tstepCount: flow.steps.length,\n\t\t\t\tisFirst: history.length === 0,\n\t\t\t\tisTerminal: currentStepId ? isTerminalStepId(flow, currentStepId, state.values) : true,\n\t\t\t\tgoNext: () => {\n\t\t\t\t\tvoid goNext()\n\t\t\t\t},\n\t\t\t\tgoBack,\n\t\t\t}\n\t\t: {\n\t\t\t\tstepIndex: 0,\n\t\t\t\tstepCount: 1,\n\t\t\t\tisFirst: true,\n\t\t\t\tisTerminal: true,\n\t\t\t\tgoNext: () => {},\n\t\t\t\tgoBack: () => {},\n\t\t\t}\n\n\tconst contextValue = { state, dispatch, validateField, locale, step }\n\n\tconst PresentationWrapper = activePresentation.Wrapper\n\tconst wrap = (content: ReactNode): ReactNode =>\n\t\tPresentationWrapper ? (\n\t\t\t<PresentationWrapper\n\t\t\t\tpresentation={activePresentation}\n\t\t\t\topen\n\t\t\t\tonClose={handleClose}\n\t\t\t\ttitle={title}\n\t\t\t\tcloseLabel={closeLabel}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</PresentationWrapper>\n\t\t) : (\n\t\t\tcontent\n\t\t)\n\n\tif (children !== undefined) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<form\n\t\t\t\t\t\tclassName=\"fb-form-root\"\n\t\t\t\t\t\tnoValidate\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</form>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tif (state.submitted) {\n\t\treturn (\n\t\t\t<FormContext.Provider value={contextValue}>\n\t\t\t\t{wrap(\n\t\t\t\t\t<p\n\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\tclassName=\"fb-form__success\"\n\t\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t\t>\n\t\t\t\t\t\t{interpolate(successMessage, recall)}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</FormContext.Provider>\n\t\t)\n\t}\n\n\tconst rendered = (flow ? stepVisible : visible).filter(\n\t\t(field) => field.hidden !== true && field.calcDisplay !== false\n\t)\n\n\treturn (\n\t\t<FormContext.Provider value={contextValue}>\n\t\t\t{wrap(\n\t\t\t\t<form\n\t\t\t\t\tclassName=\"fb-form-root\"\n\t\t\t\t\tnoValidate\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tdata-fb-presentation={activePresentation.name}\n\t\t\t\t\tdata-fb-density={activePresentation.density}\n\t\t\t\t>\n\t\t\t\t\t{honeypotName ? <Honeypot name={honeypotName} inputRef={honeypotRef} /> : null}\n\t\t\t\t\t<FormLayout enabled={layout !== false}>\n\t\t\t\t\t\t{rendered.map((field) => {\n\t\t\t\t\t\t\tconst renderer = rendererRegistry.get(field.blockType)\n\t\t\t\t\t\t\tif (!renderer) {\n\t\t\t\t\t\t\t\treturn null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst width: FieldWidth | undefined =\n\t\t\t\t\t\t\t\ttypeof field.width === 'string' && FIELD_WIDTHS.has(field.width)\n\t\t\t\t\t\t\t\t\t? (field.width as FieldWidth)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\tconst recalledField = applyRecall(field, recall)\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={field.name} {...widthProps(width)}>\n\t\t\t\t\t\t\t\t\t{calcExpressionOf(field) ? (\n\t\t\t\t\t\t\t\t\t\t<CalcFieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tvalue={effectiveValues[field.name]}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<FieldHost\n\t\t\t\t\t\t\t\t\t\t\tfield={recalledField}\n\t\t\t\t\t\t\t\t\t\t\trenderer={renderer}\n\t\t\t\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\t\t\t\tt={translate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\n\t\t\t\t\t</FormLayout>\n\t\t\t\t\t{state.submitError ? (\n\t\t\t\t\t\t<p role=\"alert\" className=\"fb-form__submit-error\">\n\t\t\t\t\t\t\t{state.submitError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{flow ? (\n\t\t\t\t\t\t<div className=\"fb-form__controls\">\n\t\t\t\t\t\t\t{!step.isFirst ? (\n\t\t\t\t\t\t\t\t<button type=\"button\" onClick={goBack} disabled={state.submitting}>\n\t\t\t\t\t\t\t\t\t{backLabel}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{step.isTerminal ? (\n\t\t\t\t\t\t\t\t<button type=\"submit\" disabled={state.submitting}>\n\t\t\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={state.submitting}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tvoid goNext()\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{nextLabel}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<button type=\"submit\" disabled={state.submitting}>\n\t\t\t\t\t\t\t{submitLabel}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t)}\n\t\t\t\t</form>\n\t\t\t)}\n\t\t</FormContext.Provider>\n\t)\n}\n","'use client'\n\nimport type { ReactNode } from 'react'\nimport type { FieldAggregation } from '../aggregation/types'\nimport { keys } from '../translations/keys'\nimport type { RendererTranslate } from './contract'\n\nexport type FormResultsProps = {\n\t/** One field aggregation or several (a survey summary), resolved server-side and passed in. */\n\tresults: FieldAggregation | FieldAggregation[]\n\t/** Localized translator for built-in copy. Defaults to identity (returns the key). */\n\tt?: RendererTranslate\n\tlocale?: string\n\t/** Show the raw count beside each option. Default true. */\n\tshowCounts?: boolean\n}\n\nconst OneResult = ({\n\tresult,\n\tt,\n\tshowCounts,\n}: {\n\tresult: FieldAggregation\n\tt: RendererTranslate\n\tshowCounts: boolean\n}): ReactNode => {\n\tif (result.total === 0) {\n\t\treturn (\n\t\t\t<section className=\"fb-results__field\">\n\t\t\t\t{result.label ? <h3 className=\"fb-results__label\">{result.label}</h3> : null}\n\t\t\t\t<p className=\"fb-results__empty\">{t(keys.resultsNoResponses)}</p>\n\t\t\t</section>\n\t\t)\n\t}\n\treturn (\n\t\t<section className=\"fb-results__field\">\n\t\t\t{result.label ? <h3 className=\"fb-results__label\">{result.label}</h3> : null}\n\t\t\t<ul className=\"fb-results__list\">\n\t\t\t\t{result.buckets.map((bucket) => (\n\t\t\t\t\t<li key={bucket.value} className=\"fb-results__row\">\n\t\t\t\t\t\t<span className=\"fb-results__option\">{bucket.label}</span>\n\t\t\t\t\t\t<span className=\"fb-results__bar\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName=\"fb-results__bar-fill\"\n\t\t\t\t\t\t\t\tstyle={{ width: `${bucket.percentage}%` }}\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"fb-results__pct\">{bucket.percentage}%</span>\n\t\t\t\t\t\t{showCounts ? <span className=\"fb-results__count\">{bucket.count}</span> : null}\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t\t<p className=\"fb-results__total\">\n\t\t\t\t{result.total} {t(keys.resultsResponses)}\n\t\t\t\t{result.truncated ? ` (${t(keys.resultsTruncated)})` : ''}\n\t\t\t</p>\n\t\t</section>\n\t)\n}\n\n/**\n * Presentational results view for polls and survey summaries: per-option bars with percentages. Headless,\n * data resolved server-side via `aggregateFieldResponses`/`aggregateFormResponses` and passed in (it never\n * fetches). The option label, count, and percentage are real text (the accessible content); the bar fill\n * is `aria-hidden` visual sugar sized by inline width.\n */\nexport const FormResults = ({ results, t, showCounts = true }: FormResultsProps): ReactNode => {\n\tconst translate: RendererTranslate = t ?? ((key) => key)\n\tconst list = Array.isArray(results) ? results : [results]\n\treturn (\n\t\t<div className=\"fb-results\">\n\t\t\t{list.map((result) => (\n\t\t\t\t<OneResult key={result.field} result={result} t={translate} showCounts={showCounts} />\n\t\t\t))}\n\t\t</div>\n\t)\n}\n","import type { FieldAggregation } from '../aggregation/types'\n\nexport type FetchResultsInput = {\n\tformId: number | string\n\t/** Restrict to one field. Omit to get every public/enumerable field. */\n\tfield?: string\n\t/** Payload API route prefix; defaults to `/api`. */\n\tapiRoute?: string\n\t/** Injectable for testing; defaults to global `fetch`. */\n\tfetchImpl?: typeof fetch\n}\n\nexport type FetchResultsResult =\n\t| { ok: true; results: FieldAggregation[] }\n\t| { ok: false; message?: string }\n\n/**\n * Fetch aggregate poll/survey results from the form-builder results endpoint\n * (`GET {apiRoute}/forms/:id/results`). Returns the server-resolved aggregations; the endpoint gates public\n * access by the form's `showResults` opt-in. Pure: inject `fetchImpl` in tests.\n */\nexport const fetchFormResults = async (input: FetchResultsInput): Promise<FetchResultsResult> => {\n\tconst { formId, field, apiRoute = '/api', fetchImpl = fetch } = input\n\tconst query = field ? `?field=${encodeURIComponent(field)}` : ''\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetchImpl(`${apiRoute}/forms/${formId}/results${query}`, { method: 'GET' })\n\t} catch (error) {\n\t\treturn { ok: false, message: error instanceof Error ? error.message : 'Network error' }\n\t}\n\tif (!response.ok) {\n\t\treturn { ok: false, message: `Request failed (${response.status})` }\n\t}\n\tconst body = (await response.json().catch(() => ({}))) as { results?: FieldAggregation[] }\n\treturn { ok: true, results: body.results ?? [] }\n}\n","'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\nimport type { FieldAggregation } from '../aggregation/types'\nimport { Form, type FormProps } from './Form'\nimport { FormResults } from './FormResults'\nimport { type FetchResultsResult, fetchFormResults } from './fetchResults'\n\nexport type PollProps = FormProps & {\n\t/** The choice field whose results are shown after voting (should match the form's public `resultsField`). */\n\tresultsField: string\n\t/** localStorage key for the per-browser voted guard. Default `fb-poll-{form.id}`. */\n\tstorageKey?: string\n\t/** Force the voted state (controlled). Omit to use the localStorage guard. */\n\thasVoted?: boolean\n\t/**\n\t * Injectable results fetch (testing); defaults to `fetchFormResults`. Pass a stable reference (module\n\t * scope, `useCallback`, or `useMemo`): an inline function re-runs the load effect and double-fetches.\n\t */\n\tfetchResultsImpl?: typeof fetchFormResults\n}\n\nconst readVoted = (key: string): boolean => {\n\ttry {\n\t\treturn window.localStorage.getItem(key) != null\n\t} catch {\n\t\treturn false\n\t}\n}\n\nconst writeVoted = (key: string): void => {\n\ttry {\n\t\twindow.localStorage.setItem(key, '1')\n\t} catch {\n\t\t// Private mode / storage disabled: the guard is best-effort UX, never integrity.\n\t}\n}\n\n/**\n * A poll: renders `<Form>` until the visitor votes, then fetches the aggregate results and shows\n * `<FormResults>`. A per-browser localStorage flag (`storageKey`) skips straight to results on revisit. The\n * guard is UX, not integrity (bypassable): server-enforced one-per-identity dedup composes via `req.user`\n * (authed forms) or a `notAlreadySubmitted` rule, with cookie/IP identity deferred to the spam phase.\n */\nexport const Poll = ({\n\tresultsField,\n\tstorageKey,\n\thasVoted,\n\tfetchResultsImpl = fetchFormResults,\n\tapiRoute,\n\tonSuccess,\n\t...formProps\n}: PollProps) => {\n\tconst key = storageKey ?? `fb-poll-${formProps.form.id}`\n\tconst [voted, setVoted] = useState(false)\n\tconst [results, setResults] = useState<FieldAggregation[] | null>(null)\n\n\tconst loadResults = useCallback(async () => {\n\t\tconst result: FetchResultsResult = await fetchResultsImpl({\n\t\t\tformId: formProps.form.id,\n\t\t\tfield: resultsField,\n\t\t\tapiRoute,\n\t\t})\n\t\tsetResults(result.ok ? result.results : [])\n\t}, [fetchResultsImpl, formProps.form.id, resultsField, apiRoute])\n\n\tuseEffect(() => {\n\t\tconst already = hasVoted ?? readVoted(key)\n\t\tif (already) {\n\t\t\tsetVoted(true)\n\t\t\tvoid loadResults()\n\t\t}\n\t}, [hasVoted, key, loadResults])\n\n\tconst handleSuccess = useCallback(\n\t\t(submissionId?: string) => {\n\t\t\twriteVoted(key)\n\t\t\tsetVoted(true)\n\t\t\tvoid loadResults()\n\t\t\tonSuccess?.(submissionId)\n\t\t},\n\t\t[key, loadResults, onSuccess]\n\t)\n\n\tif (voted) {\n\t\treturn results ? (\n\t\t\t<FormResults results={results} t={formProps.t} locale={formProps.locale} />\n\t\t) : null\n\t}\n\n\treturn <Form {...formProps} apiRoute={apiRoute} onSuccess={handleSuccess} />\n}\n","'use client'\n\nimport { useFormContext } from './FormContext'\nimport type { FormState } from './state'\n\n/** The whole form state (values, errors, warnings, touched, submitting, submitted, submitError). */\nexport const useFormState = (): FormState => useFormContext().state\n","'use client'\n\nimport type { FormStepInfo } from './FormContext'\nimport { useFormContext } from './FormContext'\n\n/** Multi-step navigation state for the current form (single-step default when the form has no flow). */\nexport const useFormStep = (): FormStepInfo => useFormContext().step\n"],"mappings":"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"}
|
package/dist/exports/rsc.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rsc.js","names":[],"sources":["../../src/submissions/SubmissionAnswers.tsx"],"sourcesContent":["import type { UIFieldServerProps } from 'payload'\nimport { defaultFieldDefinitions } from '../fields/builtin'\nimport { buildRegistry } from '../fields/registry'\nimport { keys } from '../translations/keys'\nimport { asFieldTranslate } from '../translations/server'\nimport type { SubmissionDescriptor, SubmissionValue } from './types'\n\nconst registry = buildRegistry(defaultFieldDefinitions)\n\ntype SubmissionDoc = {\n\tvalues?: SubmissionValue[]\n\tdescriptors?: SubmissionDescriptor[]\n\tlocale?: string\n}\n\n/** A stored file answer's link, when the captured `FileRef` carries a url; null otherwise. */\nconst fileHref = (raw: unknown): { url: string; filename: string } | null => {\n\tif (raw && typeof raw === 'object' && 'url' in raw) {\n\t\tconst ref = raw as { url?: unknown; filename?: unknown }\n\t\tif (typeof ref.url === 'string' && ref.url.length > 0) {\n\t\t\treturn { url: ref.url, filename: typeof ref.filename === 'string' ? ref.filename : ref.url }\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Read-only, localized submission view (server component). Renders each answered field's snapshot\n * label next to its type-aware formatted value via the field type's `format`, using the request\n * locale and i18n, with no client bundle. The built-in field types are formatted directly; threading\n * the full resolved registry (custom types) to the view is a future enhancement.\n */\nexport const SubmissionAnswers = ({ data, req }: UIFieldServerProps) => {\n\tconst doc = (data ?? {}) as SubmissionDoc\n\tconst descriptors = doc.descriptors ?? []\n\tconst values = doc.values ?? []\n\tconst locale = doc.locale ?? req.locale ?? 'en'\n\tconst t = asFieldTranslate(req.i18n.t)\n\n\tif (descriptors.length === 0) {\n\t\treturn <p>{t(keys.submissionNoAnswers)}</p>\n\t}\n\n\tconst valueByField = new Map(values.map((entry) => [entry.field, entry.value]))\n\n\treturn (\n\t\t<div className=\"form-builder-submission-answers\">\n\t\t\t<h4>{t(keys.submissionAnswers)}</h4>\n\t\t\t<dl>\n\t\t\t\t{descriptors.map((descriptor) => {\n\t\t\t\t\tconst definition = registry.get(descriptor.fieldType)\n\t\t\t\t\tconst raw = valueByField.get(descriptor.field)\n\t\t\t\t\tconst formatted = definition?.format\n\t\t\t\t\t\t? definition.format({\n\t\t\t\t\t\t\t\tvalue: raw,\n\t\t\t\t\t\t\t\tconfig: {},\n\t\t\t\t\t\t\t\toptionLabels: descriptor.optionLabels,\n\t\t\t\t\t\t\t\tlocale,\n\t\t\t\t\t\t\t\tt,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: raw == null\n\t\t\t\t\t\t\t? ''\n\t\t\t\t\t\t\t: String(raw)\n\t\t\t\t\tconst href = descriptor.fieldType === 'file' ? fileHref(raw) : null\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={descriptor.field}>\n\t\t\t\t\t\t\t<dt>{descriptor.label}</dt>\n\t\t\t\t\t\t\t<dd>\n\t\t\t\t\t\t\t\t{href ? (\n\t\t\t\t\t\t\t\t\t<a href={href.url} rel=\"noreferrer\">\n\t\t\t\t\t\t\t\t\t\t{href.filename}\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\tformatted\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</dd>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)\n\t\t\t\t})}\n\t\t\t</dl>\n\t\t</div>\n\t)\n}\n"],"mappings":";;;;AAOA,MAAM,WAAW,cAAc,uBAAuB;;AAStD,MAAM,YAAY,QAA2D;CAC5E,IAAI,OAAO,OAAO,QAAQ,YAAY,SAAS,KAAK;EACnD,MAAM,MAAM;EACZ,IAAI,OAAO,IAAI,QAAQ,YAAY,IAAI,IAAI,SAAS,GACnD,OAAO;GAAE,KAAK,IAAI;GAAK,UAAU,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW,IAAI;EAAI;CAE7F;CACA,OAAO;AACR;;;;;;;AAQA,MAAa,qBAAqB,EAAE,MAAM,UAA8B;CACvE,MAAM,MAAO,QAAQ,CAAC;CACtB,MAAM,cAAc,IAAI,eAAe,CAAC;CACxC,MAAM,SAAS,IAAI,UAAU,CAAC;CAC9B,MAAM,SAAS,IAAI,UAAU,IAAI,UAAU;CAC3C,MAAM,IAAI,iBAAiB,IAAI,KAAK,CAAC;CAErC,IAAI,YAAY,WAAW,GAC1B,OAAO,oBAAC,KAAD,EAAA,UAAI,EAAE,KAAK,mBAAmB,EAAK,CAAA;CAG3C,MAAM,eAAe,IAAI,IAAI,OAAO,KAAK,UAAU,CAAC,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC;CAE9E,OACC,qBAAC,OAAD;EAAK,WAAU;YAAf,CACC,oBAAC,MAAD,EAAA,UAAK,EAAE,KAAK,iBAAiB,EAAM,CAAA,GACnC,oBAAC,MAAD,EAAA,UACE,YAAY,KAAK,eAAe;GAChC,MAAM,aAAa,SAAS,IAAI,WAAW,SAAS;GACpD,MAAM,MAAM,aAAa,IAAI,WAAW,KAAK;GAC7C,MAAM,YAAY,YAAY,SAC3B,WAAW,OAAO;IAClB,OAAO;IACP,QAAQ,CAAC;IACT,cAAc,WAAW;IACzB;IACA;GACD,CAAC,IACA,OAAO,OACN,KACA,OAAO,GAAG;GACd,MAAM,OAAO,WAAW,cAAc,SAAS,SAAS,GAAG,IAAI;GAC/D,OACC,qBAAC,OAAD,EAAA,UAAA,CACC,oBAAC,MAAD,EAAA,UAAK,WAAW,MAAU,CAAA,GAC1B,oBAAC,MAAD,EAAA,UACE,OACA,oBAAC,KAAD;IAAG,MAAM,KAAK;IAAK,KAAI;cACrB,KAAK;GACJ,CAAA,IAEH,UAEE,CAAA,CACA,EAAA,GAXK,WAAW,KAWhB;EAEP,CAAC,EACE,CAAA,CACA;;AAEP"}
|