@usefillo/react 0.6.2 → 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 CHANGED
@@ -71,7 +71,8 @@ Every rendered part carries a named slot (`data-fillo`) and state attributes
71
71
  (`data-invalid`, `data-selected`, `data-checked`, …), and the default
72
72
  stylesheet is cascade-layered so your utilities always win. On Tailwind v3 or
73
73
  reset-heavy sites import `@usefillo/react/styles.unlayered.css` instead.
74
- Localize every built-in string with the `strings` prop. Styling contract:
74
+ Localize the shared form chrome (navigation, submit states, errors, and resume
75
+ notices) with the `strings` prop. Styling contract:
75
76
  [fillo.so/docs/styling](https://fillo.so/docs/styling).
76
77
 
77
78
  ## Go fully headless
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentType, ReactNode, ReactElement } from 'react';
3
3
  import * as _usefillo_core from '@usefillo/core';
4
- import { FormSchema, FilloClient, ResponseData, FieldValue, FormPage, Block, FormStatus, FieldKind, Field, CustomField, FormTheme, FilloAppearance, FilloStrings, FilloError, CodeForm, FormSettings, Condition, TextField, PhoneField, NumberField, ChoiceField, SelectOption, CheckboxField, RatingField, LinearScaleField, RankingField, SignatureField, DateField, FileUploadField as FileUploadField$1, HiddenField } from '@usefillo/core';
5
- export { CodeForm, Field, FieldValue, FileValue, FilloAppearance, FilloClient, FilloError, FilloJsxError, FilloSlot, FilloStrings, FormSchema, FormStatus, FormTheme, ProvisionWorkspaceResult, PublishedForm, ResponseData, SlotState, createClient, defineForm, provisionWorkspace, when } from '@usefillo/core';
4
+ import { FormSchema, FilloClient, ResponseData, FieldValue, FormPage, Block, FormStatus, FieldKind, Field, CustomField, FormTheme, FilloAppearance, FilloRendererStrings, FilloRespondent, FilloError, CodeForm, FormSettings, Condition, TextField, PhoneField, NumberField, ChoiceField, SelectOption, CheckboxField, RatingField, LinearScaleField, RankingField, SignatureField, DateField, FileUploadField as FileUploadField$1, HiddenField } from '@usefillo/core';
5
+ export { CodeForm, Field, FieldValue, FileValue, FilloAppearance, FilloClient, FilloError, FilloJsxError, FilloRendererStrings, FilloSlot, FilloStrings, FormSchema, FormStatus, FormTheme, ProvisionWorkspaceResult, PublishedForm, ResponseData, SlotState, createClient, defineForm, provisionWorkspace, when } from '@usefillo/core';
6
6
 
7
7
  /**
8
8
  * Everything a custom renderer needs. Returned by useFillo() and provided
@@ -30,6 +30,49 @@ interface FilloApi {
30
30
  uploading: boolean;
31
31
  /** Human-readable message for the last failed submit; cleared on edit/retry. */
32
32
  submitError?: string;
33
+ /**
34
+ * True when `status` is "submitted" because the once-per-visitor gate
35
+ * restored a previous visit's response, not because a submit happened in
36
+ * this mount. Skip one-time "just submitted" reactions (focus moves,
37
+ * redirects, confetti) when it's set — remounts replay them otherwise.
38
+ */
39
+ restoredSubmission: boolean;
40
+ /**
41
+ * True when a saved-progress draft (settings.saveProgress) restored answers
42
+ * and/or page position from a previous visit. Show a "picked up where you
43
+ * left off" affordance with a Start over action (resetDraft) when set.
44
+ */
45
+ resumedDraft: boolean;
46
+ /**
47
+ * True when an update-in-place limit prefilled the VERIFIED respondent's own
48
+ * previous answers — submitting updates that response in place.
49
+ */
50
+ editingPrevious: boolean;
51
+ /**
52
+ * True when the last submit was kept as an already-recorded response (a
53
+ * verified identify() repeat on a keep-mode form) rather than a fresh one.
54
+ * Renderers show an "already answered" note instead of implying a new save.
55
+ */
56
+ duplicateSubmission: boolean;
57
+ /**
58
+ * True when the last submit updated the person's existing response in place
59
+ * (responseLimit onRepeat "update") rather than creating a new one.
60
+ */
61
+ updatedSubmission: boolean;
62
+ /**
63
+ * True when a resume link (#fillo-draft=…) was expired, spent, or foreign, so
64
+ * no progress could be restored. Renderers explain the blank form instead of
65
+ * showing it with no context.
66
+ */
67
+ resumeLinkFailed: boolean;
68
+ /**
69
+ * Persist unsaved draft progress right now (settings.saveProgress forms).
70
+ * The built-in renderers call it on pagehide/visibility-hidden; custom
71
+ * headless layouts inside <FilloProvider> get the same wiring for free.
72
+ */
73
+ flushDraft: () => void;
74
+ /** Discard the saved draft and reset to a fresh fill ("Start over"). */
75
+ resetDraft: () => void;
33
76
  /** Used by upload fields to gate submission. */
34
77
  setUploading: (fieldId: string, busy: boolean) => void;
35
78
  }
@@ -79,12 +122,20 @@ interface FilloFormBaseProps {
79
122
  */
80
123
  appearance?: FilloAppearance;
81
124
  /** Override any visitor-facing renderer string (for localized sites). */
82
- strings?: Partial<FilloStrings>;
125
+ strings?: Partial<FilloRendererStrings>;
83
126
  /** Swap any built-in field kind for your own component. */
84
127
  components?: FieldComponents;
85
128
  /** Renderers for your own `custom` field kinds, keyed by `component`. */
86
129
  customComponents?: CustomComponents;
87
130
  initialData?: ResponseData;
131
+ /**
132
+ * identify(): your app's account context for the person filling the form
133
+ * ({ id, email?, name?, traits? } — id is your own user id). Recorded with
134
+ * the response as an unverified claim so responses, webhooks, and
135
+ * integrations can say who answered. Safe to pass late (after your session
136
+ * loads).
137
+ */
138
+ respondent?: FilloRespondent;
88
139
  onChange?: (data: ResponseData) => void;
89
140
  onSubmitted?: (responseId: string | undefined, data: ResponseData) => void;
90
141
  /** Observe load and code-form sync failures (otherwise only logged). */
@@ -133,8 +184,8 @@ declare function FilloForm(props: FilloFormProps): react.JSX.Element;
133
184
  * The authoring namespace: `<Fillo.Form id="contact"><Fillo.Email id="email"
134
185
  * label="Work email"/></Fillo.Form>`. Field elements are inert descriptors
135
186
  * compiled (never rendered) into the exact CodeForm defineForm() emits, then
136
- * fed to the existing framed <FilloForm> — same sync, same draft-by-default,
137
- * same badge, same responses. Define forms in a client module ("use client");
187
+ * fed to the existing framed <FilloForm> — same policy-aware resolution and
188
+ * staging, same badge, same responses. Define forms in a client module ("use client");
138
189
  * pass the compiled VALUE across server/client boundaries, never the JSX.
139
190
  */
140
191
  type WithVisible<T> = Omit<T, "kind" | "visibleIf"> & {
@@ -227,8 +278,14 @@ interface ControllerOptions {
227
278
  * renderers pass "default" explicitly.
228
279
  */
229
280
  surface?: "default" | "headless";
230
- /** Resolve the submission target at submit time when formId is still unset. */
281
+ /** Resolve/verify the canonical submission target immediately before submit. */
231
282
  resolveFormId?: () => Promise<string>;
283
+ /**
284
+ * Host-app account context (identify()): who is filling this form, by your
285
+ * own user id. Recorded with the response as an unverified claim so the
286
+ * dashboard, webhooks, and integrations can say who answered.
287
+ */
288
+ respondent?: FilloRespondent;
232
289
  }
233
290
  /**
234
291
  * React binding for the framework-agnostic engine in @usefillo/core
@@ -246,14 +303,19 @@ interface FilloProviderProps extends Omit<ControllerOptions, "form"> {
246
303
  /** Slot classes for FormField-rendered fields in your composed layout. */
247
304
  appearance?: FilloAppearance;
248
305
  /** Override any visitor-facing renderer string (for localized sites). */
249
- strings?: Partial<FilloStrings>;
306
+ strings?: Partial<FilloRendererStrings>;
307
+ /** Observe code-form sync/configuration failures. */
308
+ onError?: (error: FilloError) => void;
309
+ /** Custom unavailable state; receives the full actionable integration error. */
310
+ renderError?: (error: FilloError) => ReactNode;
250
311
  children: ReactNode;
251
312
  }
252
313
  /**
253
314
  * The headless escape hatch. Sets up the form engine (validation, conditional
254
- * logic, uploads, submit) and renders **no layout at all** — you compose the
255
- * entire form yourself with <FormField>, useField() and useFillo(),
256
- * interleaving any markup of your own between fields.
315
+ * logic, uploads, submit) and renders no resolved form layout — you compose it
316
+ * with <FormField>, useField() and useFillo(). In production, a code form
317
+ * withholds children (returns null) until its canonical schema is safe; pass
318
+ * renderError to own unavailable/not-published UI without adding SDK layout.
257
319
  *
258
320
  * <FilloProvider form={feedback} client={client}>
259
321
  * <YourErrorContext />
@@ -268,7 +330,7 @@ interface FilloProviderProps extends Omit<ControllerOptions, "form"> {
268
330
  * defineForm() form and a keyed client, the structure also syncs into your
269
331
  * workspace, exactly like <FilloForm>.
270
332
  */
271
- declare function FilloProvider({ children, form, formId, client, appearance, strings, ...options }: FilloProviderProps): react.JSX.Element;
333
+ declare function FilloProvider({ children, form, formId, client, appearance, strings, onError, renderError, ...options }: FilloProviderProps): react.JSX.Element | null;
272
334
 
273
335
  /**
274
336
  * The full form engine — data, errors, pages, submit, status. Use inside a
@@ -313,9 +375,9 @@ declare function FormField({ id, components, customComponents, }: {
313
375
  }): react.JSX.Element | null;
314
376
 
315
377
  /**
316
- * Default file upload field: drag & drop, resumable chunked uploads with live
317
- * progress, multiple files. Replace it entirely via the `components` prop if
318
- * you want your own — completed uploads are just FileValue[] in the data.
378
+ * Default file upload field: drag & drop, multiple files, live progress, and
379
+ * provider-aware browser-direct transfer (resumable where supported). Replace
380
+ * it via `components` if needed; completed uploads are FileValue[] in the data.
319
381
  */
320
382
  declare function FileUploadField({ field, value, error, setValue, api, ids: providedIds }: FieldComponentProps): react.JSX.Element;
321
383