@usefillo/core 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.d.ts +198 -31
- package/dist/index.js +529 -109
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The framework-agnostic core of [Fillo](https://fillo.so) — forms that render *
|
|
|
4
4
|
|
|
5
5
|
### 📚 Full documentation → **[fillo.so/docs](https://fillo.so/docs)**
|
|
6
6
|
|
|
7
|
-
This package holds the shared foundation: the form schema, validation, the conditional-logic engine, response prefill/piping, and a JS client with
|
|
7
|
+
This package holds the shared foundation: the form schema, validation, the conditional-logic engine, response prefill/piping, and a JS client for provider-aware browser-direct uploads, with resume support where the storage provider offers it. It has **zero framework dependencies**.
|
|
8
8
|
|
|
9
9
|
Most apps don't install this directly — you install a renderer (**[@usefillo/react](https://www.npmjs.com/package/@usefillo/react)** or **[@usefillo/dom](https://www.npmjs.com/package/@usefillo/dom)**), which re-exports everything here you need for embedding. Reach for `@usefillo/core` when you're building your own renderer or working with forms on the server.
|
|
10
10
|
|
|
@@ -15,7 +15,7 @@ npm i @usefillo/core
|
|
|
15
15
|
```ts
|
|
16
16
|
import { createClient, defineForm, validateResponse, visibleBlocks } from "@usefillo/core";
|
|
17
17
|
|
|
18
|
-
const client = createClient({ key: "
|
|
18
|
+
const client = createClient({ key: "pk_…" }); // for syncing code-defined forms
|
|
19
19
|
|
|
20
20
|
const form = defineForm({
|
|
21
21
|
id: "cust-feedback",
|
|
@@ -39,7 +39,7 @@ Key exports: `createClient` / `FilloClient`, `defineForm`, `validateResponse`, `
|
|
|
39
39
|
|
|
40
40
|
MIT licensed.
|
|
41
41
|
|
|
42
|
-
##
|
|
42
|
+
## Additional authoring surface
|
|
43
43
|
|
|
44
44
|
Framework-neutral pieces the renderers share: `defineForm` / `schemaFromJsx`
|
|
45
45
|
(the JSX compiler), `when()` condition builder, the `FilloAppearance` styling
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,8 @@ interface RatingField extends BaseField {
|
|
|
67
67
|
kind: "rating";
|
|
68
68
|
/** Number of steps, default 5. */
|
|
69
69
|
max?: number;
|
|
70
|
+
/** Optional analysis meaning. CSAT requires a 1–5 rating. */
|
|
71
|
+
insightsMetric?: "csat";
|
|
70
72
|
}
|
|
71
73
|
interface DateField extends BaseField {
|
|
72
74
|
kind: "date";
|
|
@@ -79,6 +81,8 @@ interface LinearScaleField extends BaseField {
|
|
|
79
81
|
max?: number;
|
|
80
82
|
minLabel?: string;
|
|
81
83
|
maxLabel?: string;
|
|
84
|
+
/** Optional analysis meaning. NPS requires 0–10; CSAT requires 1–5. */
|
|
85
|
+
insightsMetric?: "csat" | "nps";
|
|
82
86
|
}
|
|
83
87
|
interface RankingField extends BaseField {
|
|
84
88
|
kind: "ranking";
|
|
@@ -291,6 +295,10 @@ type UploadStatus = "pending" | "uploading" | "complete" | "aborted";
|
|
|
291
295
|
* - "gdrive": direct to a Google Drive resumable session URL (Content-Range
|
|
292
296
|
* protocol).
|
|
293
297
|
* - "s3-put": a single PUT to a presigned S3/R2 URL — straight to the bucket.
|
|
298
|
+
* Retained for sessions created by older Fillo servers.
|
|
299
|
+
* - "s3-multipart": resumable S3/R2 multipart upload. The client asks Fillo
|
|
300
|
+
* for one short-lived UploadPart URL at a time; only the server can assemble
|
|
301
|
+
* the parts into an object.
|
|
294
302
|
* - "box": direct to Box with a folder-scoped upload token — small files via a
|
|
295
303
|
* single multipart POST, large files via Box's chunked session (the client
|
|
296
304
|
* computes the SHA-1 digests Box requires). The server commits/verifies in the
|
|
@@ -302,6 +310,8 @@ type UploadTransport = {
|
|
|
302
310
|
} | {
|
|
303
311
|
type: "s3-put";
|
|
304
312
|
uploadUrl: string;
|
|
313
|
+
} | {
|
|
314
|
+
type: "s3-multipart";
|
|
305
315
|
} | {
|
|
306
316
|
type: "box";
|
|
307
317
|
mode: "simple";
|
|
@@ -344,6 +354,19 @@ interface UploadSession {
|
|
|
344
354
|
/** All conditions must hold (AND). No conditions = visible. */
|
|
345
355
|
declare function isBlockVisible(block: Block, data: ResponseData): boolean;
|
|
346
356
|
declare function visibleBlocks(page: FormPage, data: ResponseData): Block[];
|
|
357
|
+
/**
|
|
358
|
+
* Blocks to render on `page`, resolved against the WHOLE-FORM visibility
|
|
359
|
+
* fixpoint rather than just this page's own fields. A field whose `visibleIf`
|
|
360
|
+
* references an answer on another page must appear/validate here exactly when
|
|
361
|
+
* the server would keep that answer — and the server (validateResponse →
|
|
362
|
+
* visibleFields) uses the whole-form fixpoint, hiding any controlling field
|
|
363
|
+
* that is itself logic-hidden. Scoping per page instead reads a stale answer
|
|
364
|
+
* behind a hidden cross-page trigger as still-answered, so the client would
|
|
365
|
+
* render (and validate) a field whose answer the server then silently drops.
|
|
366
|
+
* Use this for anything that must agree with validateResponse; the per-page
|
|
367
|
+
* `visibleBlocks` remains for callers holding only a single page.
|
|
368
|
+
*/
|
|
369
|
+
declare function visiblePageBlocks(form: FormSchema, page: FormPage, data: ResponseData): Block[];
|
|
347
370
|
/** Every field in the form (across pages), in order. */
|
|
348
371
|
declare function allFields(form: FormSchema): Field[];
|
|
349
372
|
/**
|
|
@@ -376,6 +399,16 @@ declare function validateResponse(form: FormSchema, data: ResponseData): Validat
|
|
|
376
399
|
declare const FILLO_SCHEMA_VERSION: 1;
|
|
377
400
|
/** Injected from package.json at build time (tsup define) — never hand-edited. */
|
|
378
401
|
declare const FILLO_SDK_VERSION: string;
|
|
402
|
+
/**
|
|
403
|
+
* The oldest published @usefillo/* SDK that can still render a form the current
|
|
404
|
+
* server serves. This is a DELIBERATE floor — bump it BY HAND only when a
|
|
405
|
+
* genuinely wire-breaking change ships (a new required request/response field an
|
|
406
|
+
* old SDK can't produce or read). It must never be tied to FILLO_SDK_VERSION:
|
|
407
|
+
* the server used to serve its own build version as the min, so every release
|
|
408
|
+
* 426'd every customer still on an older pinned SDK. Field-kind/schema-shape
|
|
409
|
+
* breaks are gated separately by FILLO_SCHEMA_VERSION, so this floor stays low.
|
|
410
|
+
*/
|
|
411
|
+
declare const FILLO_MIN_SDK_VERSION = "0.4.0";
|
|
379
412
|
declare function normalizeSettings(value: unknown): FormSettings;
|
|
380
413
|
interface SchemaValidationResult {
|
|
381
414
|
ok: boolean;
|
|
@@ -457,6 +490,18 @@ declare function parsePhone(value: string, fallback?: PhoneCountry): ParsedPhone
|
|
|
457
490
|
* validation. `country` (when known) tightens the accepted lengths.
|
|
458
491
|
*/
|
|
459
492
|
declare function isPossiblePhone(value: string): boolean;
|
|
493
|
+
/** Whether the country-picker popover opens below or above its trigger. */
|
|
494
|
+
type PhonePopoverPlacement = "below" | "above";
|
|
495
|
+
/** Minimum gap kept between the popover and the viewport edge, in px. */
|
|
496
|
+
declare const PHONE_POPOVER_VIEWPORT_GAP = 8;
|
|
497
|
+
/**
|
|
498
|
+
* Decide whether the country-picker popover should open below or above its
|
|
499
|
+
* anchor and size it to fit the viewport, writing the result to CSS custom
|
|
500
|
+
* properties on the popover. Pure DOM math with no framework assumptions, so
|
|
501
|
+
* the React and vanilla renderers share one implementation instead of drifting
|
|
502
|
+
* copies. Returns "below" when there is nothing to position (SSR / detached).
|
|
503
|
+
*/
|
|
504
|
+
declare function positionPhonePopover(anchor: HTMLElement | null, popover: HTMLElement | null): PhonePopoverPlacement;
|
|
460
505
|
|
|
461
506
|
/** Display metadata for every block kind — drives the builder palette. */
|
|
462
507
|
declare const BLOCK_KIND_META: Record<BlockKind, {
|
|
@@ -491,6 +536,7 @@ interface FieldSpec {
|
|
|
491
536
|
max?: number;
|
|
492
537
|
minLabel?: string;
|
|
493
538
|
maxLabel?: string;
|
|
539
|
+
insightsMetric?: "csat" | "nps";
|
|
494
540
|
rows?: string[];
|
|
495
541
|
columns?: string[];
|
|
496
542
|
placeholder?: string;
|
|
@@ -656,14 +702,23 @@ interface UploadFileOptions {
|
|
|
656
702
|
sessionId?: string;
|
|
657
703
|
/** Ownership token for the resumed session (from the original create call). */
|
|
658
704
|
uploadToken?: string;
|
|
705
|
+
/** Persist this handle if the host wants reload-safe resumability. */
|
|
706
|
+
onSession?: (handle: {
|
|
707
|
+
sessionId: string;
|
|
708
|
+
uploadToken?: string;
|
|
709
|
+
}) => void;
|
|
659
710
|
}
|
|
660
711
|
declare class FilloError extends Error {
|
|
661
712
|
status?: number | undefined;
|
|
662
713
|
/** Server-suggested wait (from a 429's Retry-After header), seconds. */
|
|
663
714
|
retryAfterSec?: number | undefined;
|
|
715
|
+
/** Stable machine-readable API error code, when the server provides one. */
|
|
716
|
+
code?: string | undefined;
|
|
664
717
|
constructor(message: string, status?: number | undefined,
|
|
665
718
|
/** Server-suggested wait (from a 429's Retry-After header), seconds. */
|
|
666
|
-
retryAfterSec?: number | undefined
|
|
719
|
+
retryAfterSec?: number | undefined,
|
|
720
|
+
/** Stable machine-readable API error code, when the server provides one. */
|
|
721
|
+
code?: string | undefined);
|
|
667
722
|
}
|
|
668
723
|
/** Duck-typed — `instanceof` breaks when two SDK copies end up in one bundle. */
|
|
669
724
|
declare function isFilloError(err: unknown): err is FilloError;
|
|
@@ -675,6 +730,17 @@ interface SyncFormResult {
|
|
|
675
730
|
status?: "draft" | "published";
|
|
676
731
|
/** Changes were staged as a draft for a human to publish. */
|
|
677
732
|
staged?: boolean;
|
|
733
|
+
/**
|
|
734
|
+
* Server-authoritative live snapshot. Present when the incoming code schema
|
|
735
|
+
* is not the version respondents may submit against yet.
|
|
736
|
+
*/
|
|
737
|
+
resolvedSchema?: FormSchema;
|
|
738
|
+
resolvedTheme?: FormTheme | null;
|
|
739
|
+
/** Non-fatal integration problem; the resolved live snapshot remains usable. */
|
|
740
|
+
syncError?: {
|
|
741
|
+
code: string;
|
|
742
|
+
message: string;
|
|
743
|
+
};
|
|
678
744
|
warning?: string;
|
|
679
745
|
}
|
|
680
746
|
declare class FilloClient {
|
|
@@ -689,8 +755,10 @@ declare class FilloClient {
|
|
|
689
755
|
/** Fetch a published form definition by id or slug. */
|
|
690
756
|
getForm(idOrSlug: string): Promise<PublishedForm>;
|
|
691
757
|
/**
|
|
692
|
-
*
|
|
693
|
-
* publishable key.
|
|
758
|
+
* Resolve a code-defined form through the workspace identified by the
|
|
759
|
+
* client's publishable key. Depending on workspace policy, changed content
|
|
760
|
+
* may be staged for review or resolved to the authoritative live snapshot.
|
|
761
|
+
* Returns the canonical form id used for submissions.
|
|
694
762
|
*/
|
|
695
763
|
syncForm(handle: string, schema: FormSchema, theme?: FormTheme | null): Promise<SyncFormResult>;
|
|
696
764
|
/** Submit a response. Returns per-field errors instead of throwing on validation failure. */
|
|
@@ -700,8 +768,14 @@ declare class FilloClient {
|
|
|
700
768
|
* used to prefill their answers for editing. Requires a VERIFIED identity
|
|
701
769
|
* ({id, hash}); anything else 404s (returned as null), because an
|
|
702
770
|
* unverified read would hand anyone's answers to any page script.
|
|
771
|
+
*
|
|
772
|
+
* `scopeValue` scopes the lookup for forms whose response limit is keyed to
|
|
773
|
+
* a field (responseLimit.scopeField) — e.g. one response per article. When
|
|
774
|
+
* the form is scoped, the server returns 404 unless the matching scope value
|
|
775
|
+
* is sent, so a page loaded for article B never prefills article A's answers.
|
|
776
|
+
* Optional and back-compatible: omit it for unscoped forms.
|
|
703
777
|
*/
|
|
704
|
-
fetchOwnResponse(formId: string, respondent: FilloRespondent): Promise<{
|
|
778
|
+
fetchOwnResponse(formId: string, respondent: FilloRespondent, scopeValue?: string): Promise<{
|
|
705
779
|
responseId: string;
|
|
706
780
|
data: ResponseData;
|
|
707
781
|
} | null>;
|
|
@@ -743,13 +817,12 @@ declare class FilloClient {
|
|
|
743
817
|
/** Discard a draft (the "Start over" path). */
|
|
744
818
|
deleteDraft(draftId: string, token: string): Promise<void>;
|
|
745
819
|
/** Current state of an upload session — used to resume after interruption. */
|
|
746
|
-
getUploadSession(sessionId: string, token?: string): Promise<UploadSession>;
|
|
820
|
+
getUploadSession(sessionId: string, token?: string, signal?: AbortSignal): Promise<UploadSession>;
|
|
747
821
|
/**
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
* is sent twice or skipped.
|
|
822
|
+
* Provider-aware browser-direct upload. Creates a session, uses the storage
|
|
823
|
+
* transport selected by the server, reports progress, and finalizes into a
|
|
824
|
+
* FileValue. Resumable providers can continue an existing session; one-shot
|
|
825
|
+
* transports are retried according to their own safe semantics.
|
|
753
826
|
*
|
|
754
827
|
* Depending on the form's storage settings the server picks a transport:
|
|
755
828
|
* direct-to-Google-Drive resumable
|
|
@@ -768,7 +841,7 @@ declare class FilloClient {
|
|
|
768
841
|
/**
|
|
769
842
|
* Caller signal (if any) combined with a fresh per-request timeout. Created per
|
|
770
843
|
* fetch so each retry attempt gets its own deadline; the caller's own abort
|
|
771
|
-
* still drives
|
|
844
|
+
* still drives upload cancellation across every provider transport.
|
|
772
845
|
*/
|
|
773
846
|
private uploadSignal;
|
|
774
847
|
/** Retry a request with exponential backoff; never retries an aborted upload. */
|
|
@@ -780,6 +853,13 @@ declare class FilloClient {
|
|
|
780
853
|
* queries Drive for the authoritative offset).
|
|
781
854
|
*/
|
|
782
855
|
private driveUploadLoop;
|
|
856
|
+
/**
|
|
857
|
+
* S3-compatible multipart protocol. Fillo owns the provider upload id and is
|
|
858
|
+
* the only party allowed to complete it; the browser receives only narrowly
|
|
859
|
+
* scoped UploadPart URLs. That keeps uploads resumable and means an old or
|
|
860
|
+
* slow browser request cannot materialize an object after server-side abort.
|
|
861
|
+
*/
|
|
862
|
+
private s3MultipartUploadLoop;
|
|
783
863
|
/**
|
|
784
864
|
* S3-compatible single PUT to a presigned URL — bytes go straight to the
|
|
785
865
|
* bucket. Not resumable (S3 single PUT is atomic), but retried on failure.
|
|
@@ -791,13 +871,13 @@ interface ProvisionWorkspaceResult {
|
|
|
791
871
|
/** Publishable key (pk_…) for the new workspace. Pass to createClient({ key }). */
|
|
792
872
|
key: string;
|
|
793
873
|
organizationId: string;
|
|
794
|
-
/**
|
|
874
|
+
/** The private workspace link is emailed directly; `url` stays null. */
|
|
795
875
|
claim: {
|
|
796
876
|
url: string | null;
|
|
797
877
|
email: string | null;
|
|
798
878
|
sent: boolean;
|
|
799
879
|
};
|
|
800
|
-
/** Caps applied until the workspace is
|
|
880
|
+
/** Caps applied until the workspace is saved to an account. */
|
|
801
881
|
limits: {
|
|
802
882
|
responses: number;
|
|
803
883
|
expiresAt: string;
|
|
@@ -805,9 +885,9 @@ interface ProvisionWorkspaceResult {
|
|
|
805
885
|
}
|
|
806
886
|
/**
|
|
807
887
|
* Provision a Fillo workspace from an email — no signup — and get a publishable
|
|
808
|
-
* key back, so a form can collect real responses immediately. A
|
|
809
|
-
* emailed to `email`; until someone
|
|
810
|
-
* preview (limited responses, for a limited time). Built for setup automation,
|
|
888
|
+
* key back, so a form can collect real responses immediately. A private
|
|
889
|
+
* workspace link is emailed to `email`; until someone saves it to an account,
|
|
890
|
+
* the workspace runs as a capped preview (limited responses, for a limited time). Built for setup automation,
|
|
811
891
|
* e.g. a coding agent wiring Fillo into an app during integration.
|
|
812
892
|
*
|
|
813
893
|
* const { key } = await provisionWorkspace({ email: "you@co.com" });
|
|
@@ -853,10 +933,10 @@ interface FormControllerOptions {
|
|
|
853
933
|
*/
|
|
854
934
|
surface?: "default" | "headless";
|
|
855
935
|
/**
|
|
856
|
-
* Resolve the submission target
|
|
857
|
-
*
|
|
858
|
-
* held (never dropped) while it
|
|
859
|
-
* respondent can retry.
|
|
936
|
+
* Resolve/verify the submission target immediately before submit. Code-form
|
|
937
|
+
* renderers use this to recover a missing target and to detect a live schema
|
|
938
|
+
* change after a cached mount. Answers are held (never dropped) while it
|
|
939
|
+
* runs; failure sets `submitError` and the respondent can retry.
|
|
860
940
|
*/
|
|
861
941
|
resolveFormId?: () => Promise<string>;
|
|
862
942
|
/**
|
|
@@ -904,6 +984,27 @@ interface FormControllerState {
|
|
|
904
984
|
* show an "updating your earlier response" notice.
|
|
905
985
|
*/
|
|
906
986
|
editingPrevious: boolean;
|
|
987
|
+
/**
|
|
988
|
+
* True when the last submit was accepted as an already-recorded response
|
|
989
|
+
* rather than a new one (the server returns this only for a VERIFIED
|
|
990
|
+
* identify() repeat on a keep-mode form). Renderers show an "already
|
|
991
|
+
* answered" message on the success screen instead of implying a fresh
|
|
992
|
+
* submission — otherwise a repeat visitor's new answers look saved when the
|
|
993
|
+
* server kept the original.
|
|
994
|
+
*/
|
|
995
|
+
duplicateSubmission: boolean;
|
|
996
|
+
/**
|
|
997
|
+
* True when the last submit UPDATED the person's existing response in place
|
|
998
|
+
* (responseLimit onRepeat "update"), rather than creating a new one.
|
|
999
|
+
*/
|
|
1000
|
+
updatedSubmission: boolean;
|
|
1001
|
+
/**
|
|
1002
|
+
* True when a resume link (#fillo-draft=…) could not be adopted because it
|
|
1003
|
+
* was expired, already used, or not this browser's — so no progress was
|
|
1004
|
+
* restored. Renderers surface a "that link expired — start again" notice
|
|
1005
|
+
* instead of showing a silently blank form.
|
|
1006
|
+
*/
|
|
1007
|
+
resumeLinkFailed: boolean;
|
|
907
1008
|
}
|
|
908
1009
|
interface FormController {
|
|
909
1010
|
/** Stable snapshot — same reference until something changes (safe for useSyncExternalStore). */
|
|
@@ -1061,10 +1162,23 @@ declare const FILLO_THEME_VARS: readonly [{
|
|
|
1061
1162
|
}];
|
|
1062
1163
|
|
|
1063
1164
|
/**
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1165
|
+
* The default English validation message for a required field left empty.
|
|
1166
|
+
* `validateField` returns this exact sentinel (core has no strings context),
|
|
1167
|
+
* and the React render layer swaps it for `strings.required` so a localized
|
|
1168
|
+
* site can translate it. Keep it identical to `DEFAULT_FIELD_STRINGS.required`.
|
|
1169
|
+
*/
|
|
1170
|
+
declare const REQUIRED_FIELD_MESSAGE = "This field is required";
|
|
1171
|
+
/**
|
|
1172
|
+
* The form-chrome strings the default renderers emit, overridable as a unit so
|
|
1173
|
+
* a localized site never shows stray English at the submit moment.
|
|
1066
1174
|
* Schema-authored text (labels, descriptions, success copy set in settings)
|
|
1067
1175
|
* always wins over these defaults.
|
|
1176
|
+
*
|
|
1177
|
+
* Field-level and validation copy (required message, upload field, duplicate/
|
|
1178
|
+
* resume notices) lives in {@link FilloFieldStrings} — split out so this
|
|
1179
|
+
* documented, all-`string` surface stays stable while parametrized field
|
|
1180
|
+
* strings can be functions. The renderers resolve both together
|
|
1181
|
+
* ({@link FilloRendererStrings}); the `strings` prop overrides either.
|
|
1068
1182
|
*/
|
|
1069
1183
|
interface FilloStrings {
|
|
1070
1184
|
back: string;
|
|
@@ -1099,7 +1213,45 @@ interface FilloStrings {
|
|
|
1099
1213
|
resumeStartOver: string;
|
|
1100
1214
|
}
|
|
1101
1215
|
declare const DEFAULT_STRINGS: FilloStrings;
|
|
1102
|
-
|
|
1216
|
+
/**
|
|
1217
|
+
* Field-level and validation strings the default renderers emit. Kept apart
|
|
1218
|
+
* from {@link FilloStrings} so parametrized entries can be functions (a
|
|
1219
|
+
* translation places the value where its grammar needs it) without widening
|
|
1220
|
+
* the documented all-`string` chrome surface.
|
|
1221
|
+
*/
|
|
1222
|
+
interface FilloFieldStrings {
|
|
1223
|
+
/** Validation: a required field was left empty. Mirrors REQUIRED_FIELD_MESSAGE. */
|
|
1224
|
+
required: string;
|
|
1225
|
+
/** Notice when a spent/expired resume link couldn't restore progress. */
|
|
1226
|
+
resumeLinkExpired: string;
|
|
1227
|
+
/** Success-screen message when a verified identity re-submits and the form
|
|
1228
|
+
* keeps the first answer (a visible duplicate, not a fresh response). */
|
|
1229
|
+
alreadyAnswered: string;
|
|
1230
|
+
/** Retry control on a failed upload row. */
|
|
1231
|
+
uploadRetry: string;
|
|
1232
|
+
/** Dropzone copy when uploads can't run (no client / preview). */
|
|
1233
|
+
uploadsDisabled: string;
|
|
1234
|
+
/** An upload attempt failed with no actionable server message. */
|
|
1235
|
+
uploadFailed: string;
|
|
1236
|
+
/** Dropzone call to action; `multiple` is true when several files are allowed. */
|
|
1237
|
+
dropzoneTitle: (multiple: boolean) => string;
|
|
1238
|
+
/** Dropzone hint stating the per-file size limit in MB. */
|
|
1239
|
+
dropzoneHint: (maxMb: number) => string;
|
|
1240
|
+
/** A file exceeded the per-file MB limit before upload started. */
|
|
1241
|
+
fileTooLarge: (maxMb: number) => string;
|
|
1242
|
+
/** Screen-reader status: N uploads in progress. */
|
|
1243
|
+
filesUploading: (count: number) => string;
|
|
1244
|
+
/** Screen-reader status: N uploads failed. */
|
|
1245
|
+
uploadsFailed: (count: number) => string;
|
|
1246
|
+
/** Screen-reader status: N uploads completed. */
|
|
1247
|
+
filesUploaded: (count: number) => string;
|
|
1248
|
+
}
|
|
1249
|
+
declare const DEFAULT_FIELD_STRINGS: FilloFieldStrings;
|
|
1250
|
+
/** Everything the default renderers can localize — chrome + field/validation. */
|
|
1251
|
+
type FilloRendererStrings = FilloStrings & FilloFieldStrings;
|
|
1252
|
+
/** Merge overrides over the built-in chrome + field defaults. Accepts a partial
|
|
1253
|
+
* of the full renderer surface so the `strings` prop can override either set. */
|
|
1254
|
+
declare function resolveStrings(overrides?: Partial<FilloRendererStrings>): FilloRendererStrings;
|
|
1103
1255
|
|
|
1104
1256
|
/** Result of syncing a code-defined form: its canonical id, slug, and branding. */
|
|
1105
1257
|
interface SyncedForm {
|
|
@@ -1110,12 +1262,21 @@ interface SyncedForm {
|
|
|
1110
1262
|
status?: "draft" | "published";
|
|
1111
1263
|
/** Changes were staged as a draft for a human to publish. */
|
|
1112
1264
|
staged?: boolean;
|
|
1265
|
+
/** Server-authoritative live snapshot when local code is not live yet. */
|
|
1266
|
+
resolvedSchema?: FormSchema;
|
|
1267
|
+
resolvedTheme?: FormTheme | null;
|
|
1268
|
+
/** Non-fatal integration problem; resolvedSchema remains safe to render. */
|
|
1269
|
+
syncError?: {
|
|
1270
|
+
code: string;
|
|
1271
|
+
message: string;
|
|
1272
|
+
};
|
|
1113
1273
|
warning?: string;
|
|
1114
1274
|
}
|
|
1115
1275
|
/**
|
|
1116
|
-
* A form whose structure lives in user code.
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
1276
|
+
* A form whose structure lives in user code. Development and explicit
|
|
1277
|
+
* render-only usage can show it immediately; production renderers with a
|
|
1278
|
+
* publishable key first resolve the canonical form from Fillo so responses,
|
|
1279
|
+
* uploads, webhooks, and exports stay bound to the published version.
|
|
1119
1280
|
*/
|
|
1120
1281
|
interface CodeForm {
|
|
1121
1282
|
/** Stable handle, unique in the workspace. */
|
|
@@ -1136,10 +1297,16 @@ declare function isCodeForm(form: unknown): form is CodeForm;
|
|
|
1136
1297
|
/** Stable djb2 hash of a string — used to key code-form sync by content. */
|
|
1137
1298
|
declare function contentHash(input: string): string;
|
|
1138
1299
|
/**
|
|
1139
|
-
*
|
|
1140
|
-
*
|
|
1141
|
-
*
|
|
1142
|
-
|
|
1300
|
+
* Compare normalized schema JSON while ignoring object-key order (Postgres
|
|
1301
|
+
* jsonb and custom API proxies may reorder keys). Array order remains part of
|
|
1302
|
+
* the form definition because it controls pages, blocks, and options.
|
|
1303
|
+
*/
|
|
1304
|
+
declare function formSchemasEqual(left: FormSchema, right: FormSchema): boolean;
|
|
1305
|
+
/**
|
|
1306
|
+
* Resolve a code-defined form with in-flight dedupe and bounded stable-result
|
|
1307
|
+
* caching (published 1h, draft 60s). Staged/live-fallback results are evicted
|
|
1308
|
+
* once settled so an SPA can observe publication without a hard reload.
|
|
1309
|
+
* `bypassCache` forces the network for submit-time compatibility checks.
|
|
1143
1310
|
*/
|
|
1144
1311
|
declare function syncCodeForm(client: FilloClient, form: CodeForm, opts?: {
|
|
1145
1312
|
bypassCache?: boolean;
|
|
@@ -1263,4 +1430,4 @@ declare class Sha1 {
|
|
|
1263
1430
|
}
|
|
1264
1431
|
declare const sha1Base64: (bytes: Uint8Array) => string;
|
|
1265
1432
|
|
|
1266
|
-
export { type AutoSubmitContext, BLOCK_KIND_META, type BaseField, type Block, type BlockKind, CONTENT_KINDS, type CheckboxField, type ChoiceField, type CodeForm, type Condition, type ConditionOp, type ContentBlock, type ContentKind, type CreatedDraft, type CustomField, DEFAULT_STRINGS, DRAFT_KINDS, type DateField, type DividerBlock, FILLO_DATA_ATTRS, FILLO_SCHEMA_VERSION, FILLO_SDK_VERSION, FILLO_SLOTS, FILLO_THEME_VARS, type Field, type FieldKind, type FieldSpec, type FieldValue, type FileUploadField, type FileValue, type FilloAppearance, FilloClient, type FilloClientOptions, FilloError, FilloJsxError, type FilloRespondent, type FilloSlot, type FilloStrings, type FormBranding, type FormController, type FormControllerOptions, type FormControllerState, type FormDraftSpec, type FormPage, type FormSchema, type FormSettings, type FormStatus, type FormTheme, type HeadingBlock, type HiddenField, JSX_BLOCK_COMPONENTS, JSX_BLOCK_SPECS, type JsonValue, type JsxFormMeta, type LinearScaleField, type MatrixField, type NumberField, PHONE_COUNTRIES, type ParagraphBlock, type ParsedPhone, type PhoneCountry, type PhoneField, type ProvisionWorkspaceResult, type PublishedForm, type RankingField, type RatingField, type ResponseData, type ResponseDraft, type ResponseLimit, type SchemaValidationResult, type SelectOption, Sha1, type SignatureField, type SlotClass, type SlotState, type SubmitMeta, type SubmitResult, type SyncFormResult, type SyncedForm, type TextField, type UploadFileOptions, type UploadProgress, type UploadSession, type UploadStatus, type UploadTransport, type ValidationResult, type WhenBuilder, allFields, assembleForm, codeFormFromJsx, contentHash, countryByDialCode, countryByIso, countryByTimeZone, createBlock, createClient, createEmptyForm, createFormController, createId, defineForm, digitsOnly, flagEmoji, formatAnswer, formatNational, isAutoSubmitBlock, isBlockVisible, isCodeForm, isField, isFilloError, isPossiblePhone, needsExplicitSubmit, normalizeFormSchema, normalizeFormTheme, normalizeSettings, parsePhone, pipeBlock, prefillFromParams, provisionWorkspace, resolveSlotClass, resolveStrings, resolveText, responseScopeValue, schemaFromJsx, sha1Base64, shouldAutoSubmit, slotClass, syncCodeForm, toE164, validateField, validateFormSchema, validateResponse, visibleBlocks, visibleFields, when };
|
|
1433
|
+
export { type AutoSubmitContext, BLOCK_KIND_META, type BaseField, type Block, type BlockKind, CONTENT_KINDS, type CheckboxField, type ChoiceField, type CodeForm, type Condition, type ConditionOp, type ContentBlock, type ContentKind, type CreatedDraft, type CustomField, DEFAULT_FIELD_STRINGS, DEFAULT_STRINGS, DRAFT_KINDS, type DateField, type DividerBlock, FILLO_DATA_ATTRS, FILLO_MIN_SDK_VERSION, FILLO_SCHEMA_VERSION, FILLO_SDK_VERSION, FILLO_SLOTS, FILLO_THEME_VARS, type Field, type FieldKind, type FieldSpec, type FieldValue, type FileUploadField, type FileValue, type FilloAppearance, FilloClient, type FilloClientOptions, FilloError, type FilloFieldStrings, FilloJsxError, type FilloRendererStrings, type FilloRespondent, type FilloSlot, type FilloStrings, type FormBranding, type FormController, type FormControllerOptions, type FormControllerState, type FormDraftSpec, type FormPage, type FormSchema, type FormSettings, type FormStatus, type FormTheme, type HeadingBlock, type HiddenField, JSX_BLOCK_COMPONENTS, JSX_BLOCK_SPECS, type JsonValue, type JsxFormMeta, type LinearScaleField, type MatrixField, type NumberField, PHONE_COUNTRIES, PHONE_POPOVER_VIEWPORT_GAP, type ParagraphBlock, type ParsedPhone, type PhoneCountry, type PhoneField, type PhonePopoverPlacement, type ProvisionWorkspaceResult, type PublishedForm, REQUIRED_FIELD_MESSAGE, type RankingField, type RatingField, type ResponseData, type ResponseDraft, type ResponseLimit, type SchemaValidationResult, type SelectOption, Sha1, type SignatureField, type SlotClass, type SlotState, type SubmitMeta, type SubmitResult, type SyncFormResult, type SyncedForm, type TextField, type UploadFileOptions, type UploadProgress, type UploadSession, type UploadStatus, type UploadTransport, type ValidationResult, type WhenBuilder, allFields, assembleForm, codeFormFromJsx, contentHash, countryByDialCode, countryByIso, countryByTimeZone, createBlock, createClient, createEmptyForm, createFormController, createId, defineForm, digitsOnly, flagEmoji, formSchemasEqual, formatAnswer, formatNational, isAutoSubmitBlock, isBlockVisible, isCodeForm, isField, isFilloError, isPossiblePhone, needsExplicitSubmit, normalizeFormSchema, normalizeFormTheme, normalizeSettings, parsePhone, pipeBlock, positionPhonePopover, prefillFromParams, provisionWorkspace, resolveSlotClass, resolveStrings, resolveText, responseScopeValue, schemaFromJsx, sha1Base64, shouldAutoSubmit, slotClass, syncCodeForm, toE164, validateField, validateFormSchema, validateResponse, visibleBlocks, visibleFields, visiblePageBlocks, when };
|