@usefillo/react 0.3.2 → 0.5.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
@@ -11,13 +11,11 @@ npm i @usefillo/react
11
11
  `react` and `react-dom` (18 or 19) are peer dependencies.
12
12
 
13
13
  ```tsx
14
- import { FilloForm, createClient } from "@usefillo/react";
14
+ import { FilloForm } from "@usefillo/react";
15
15
  import "@usefillo/react/styles.css"; // optional default theme — or bring your own
16
16
 
17
- const client = createClient({ key: "pk_live_…" });
18
-
19
17
  export function Feedback() {
20
- return <FilloForm client={client} formId="cust-feedback" onSubmitted={(r) => confetti()} />;
18
+ return <FilloForm formId="cust-feedback" onSubmitted={(r) => confetti()} />;
21
19
  }
22
20
  ```
23
21
 
@@ -29,6 +27,12 @@ Every part is replaceable. Pass your own field components, theme the form via th
29
27
  - `FormField` / `BlockRenderer` — render individual blocks
30
28
  - `defineForm()` — author a form in code and sync it to your workspace on first run
31
29
 
30
+ Published `formId` embeds can fetch and submit without a publishable key. Use `createClient({ key })` when syncing `defineForm()` schemas from code, or when you need to point the SDK at a custom API origin.
31
+
32
+ For tiny feedback widgets, set `settings.submitMode: "auto"` on a select/rating/checkbox/dropdown/linear scale form. The default renderer hides the first submit button, submits after a complete discrete answer, and brings the submit button back if that answer opens a text or upload follow-up. Add `submissionLimit: "once_per_visitor"` for browser-scoped one-response feedback.
33
+
34
+ The default stylesheet follows system dark mode for unthemed embeds. Pass `theme={{ colorScheme: "dark" }}` or `"light"` when the host surface is known.
35
+
32
36
  This package re-exports the embedding surface from [`@usefillo/core`](https://www.npmjs.com/package/@usefillo/core) (`createClient`, `FormSchema`, `FormTheme`, …) so a single import is usually enough.
33
37
 
34
38
  ## Links
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
- import { FormSchema, FilloClient, ResponseData, FieldValue, FormPage, Block, FormStatus, FieldKind, Field, CodeForm, FormTheme, FilloError } from '@usefillo/core';
3
+ import { FormSchema, FilloClient, ResponseData, FieldValue, FormPage, Block, FormStatus, FieldKind, Field, FormTheme, FilloError, CodeForm } from '@usefillo/core';
4
4
  export { CodeForm, Field, FieldValue, FileValue, FilloClient, FilloError, FormSchema, FormStatus, FormTheme, ProvisionWorkspaceResult, PublishedForm, ResponseData, createClient, defineForm, provisionWorkspace } from '@usefillo/core';
5
5
 
6
6
  /**
@@ -30,12 +30,22 @@ interface FilloApi {
30
30
  /** Used by upload fields to gate submission. */
31
31
  setUploading: (fieldId: string, busy: boolean) => void;
32
32
  }
33
- interface FieldComponentProps {
34
- field: Field;
33
+ interface FilloFieldIds {
34
+ inputId: string;
35
+ labelId: string;
36
+ descriptionId: string;
37
+ errorId: string;
38
+ name: string;
39
+ }
40
+ interface FieldComponentProps<F extends Field = Field> {
41
+ /** Narrow with the type param to skip a cast, e.g.
42
+ * `FieldComponentProps<CustomField>` to read `field.config` directly. */
43
+ field: F;
35
44
  value: FieldValue;
36
45
  error: string | undefined;
37
46
  setValue: (value: FieldValue) => void;
38
47
  api: FilloApi;
48
+ ids?: FilloFieldIds;
39
49
  }
40
50
  /** Per-kind component overrides — swap any built-in field for your own. */
41
51
  type FieldComponents = Partial<Record<FieldKind, ComponentType<FieldComponentProps>>>;
@@ -46,12 +56,7 @@ type FieldComponents = Partial<Record<FieldKind, ComponentType<FieldComponentPro
46
56
  */
47
57
  type CustomComponents = Record<string, ComponentType<FieldComponentProps>>;
48
58
 
49
- interface FilloFormProps {
50
- /** Render a schema directly, or a code-defined form from defineForm(). */
51
- form?: FormSchema | CodeForm;
52
- /** Or fetch it: a client plus the form id/slug. */
53
- client?: FilloClient;
54
- formId?: string;
59
+ interface FilloFormBaseProps {
55
60
  theme?: FormTheme;
56
61
  /** Swap any built-in field kind for your own component. */
57
62
  components?: FieldComponents;
@@ -72,17 +77,34 @@ interface FilloFormProps {
72
77
  renderSuccess?: () => ReactNode;
73
78
  /** Custom error screen — receives the failure (e.g. 404 vs network). */
74
79
  renderError?: (error: FilloError) => ReactNode;
75
- /** Let "Next" move between pages without validating — for builder previews. */
76
- skipValidation?: boolean;
77
80
  /**
78
- * Show the "Powered by Fillo" badge. Normally resolved from the workspace
79
- * plan by the server; set explicitly only by Fillo's own hosted pages.
80
- * Removing the badge on a free workspace violates the Fillo terms. Builder
81
- * previews (`skipValidation`) never show it.
81
+ * @internal Builder/test preview: let "Next" move between pages without
82
+ * client-side validation. Submission and branding are still authoritative.
82
83
  */
83
- poweredBy?: boolean;
84
+ skipValidation?: boolean;
84
85
  className?: string;
85
86
  }
87
+ type HostedFormProps = FilloFormBaseProps & {
88
+ /** Fetch a published form by id/slug. A default Fillo client is created if omitted. */
89
+ formId: string;
90
+ form?: undefined;
91
+ client?: FilloClient;
92
+ };
93
+ type CodeBackedFormProps = FilloFormBaseProps & {
94
+ /** Render a schema directly, or a code-defined form from defineForm(). */
95
+ form: FormSchema | CodeForm;
96
+ /** Required for code-defined forms that should save responses in Fillo. */
97
+ client: FilloClient;
98
+ formId?: string;
99
+ };
100
+ type PreviewFormProps = FilloFormBaseProps & {
101
+ /** Builder/test preview: render locally and complete locally. */
102
+ form: FormSchema | CodeForm;
103
+ client?: FilloClient;
104
+ formId?: string;
105
+ skipValidation: true;
106
+ };
107
+ type FilloFormProps = HostedFormProps | CodeBackedFormProps | PreviewFormProps;
86
108
  declare function FilloForm(props: FilloFormProps): react.JSX.Element;
87
109
 
88
110
  interface ControllerOptions {
@@ -94,7 +116,7 @@ interface ControllerOptions {
94
116
  onSubmitted?: (responseId: string | undefined, data: ResponseData) => void;
95
117
  /** Anti-spam signals provided by the renderer (honeypot value). */
96
118
  getHoneypot?: () => string;
97
- /** Let "next" move between pages without validating — for previews/builders. */
119
+ /** @internal Preview-only page navigation escape hatch. Submission still validates. */
98
120
  skipValidation?: boolean;
99
121
  /** Embedding surface; "headless" (FilloProvider) is server-enforced as paid. */
100
122
  surface?: "default" | "headless";
@@ -154,12 +176,18 @@ interface FieldHandle {
154
176
  */
155
177
  declare function useField(fieldId: string): FieldHandle;
156
178
 
157
- declare function BlockRenderer({ block, api, components, customComponents, }: {
179
+ interface BlockRendererProps {
158
180
  block: Block;
159
181
  api: FilloApi;
160
182
  components?: FieldComponents;
161
183
  customComponents?: CustomComponents;
162
- }): react.JSX.Element | null;
184
+ }
185
+ declare function BlockRendererInner({ block, api, components, customComponents }: BlockRendererProps): react.JSX.Element | null;
186
+ /**
187
+ * Memoized so a keystroke in one field doesn't re-render every other field —
188
+ * see blockPropsEqual for exactly what a block is allowed to depend on.
189
+ */
190
+ declare const BlockRenderer: react.MemoExoticComponent<typeof BlockRendererInner>;
163
191
  /**
164
192
  * Render a single field by id using the default (or overridden) component —
165
193
  * drop it anywhere inside a <FilloProvider> to place fields in your own
@@ -176,6 +204,6 @@ declare function FormField({ id, components, customComponents, }: {
176
204
  * progress, multiple files. Replace it entirely via the `components` prop if
177
205
  * you want your own — completed uploads are just FileValue[] in the data.
178
206
  */
179
- declare function FileUploadField({ field, value, error, setValue, api }: FieldComponentProps): react.JSX.Element;
207
+ declare function FileUploadField({ field, value, error, setValue, api, ids: providedIds }: FieldComponentProps): react.JSX.Element;
180
208
 
181
- export { BlockRenderer, type ControllerOptions, type CustomComponents, type FieldComponentProps, type FieldComponents, type FieldHandle, type FilloApi, FileUploadField as FilloFileUpload, FilloForm, type FilloFormProps, FilloProvider, type FilloProviderProps, FormField, useField, useFillo, useFilloController };
209
+ export { BlockRenderer, type ControllerOptions, type CustomComponents, type FieldComponentProps, type FieldComponents, type FieldHandle, type FilloApi, type FilloFieldIds, FileUploadField as FilloFileUpload, FilloForm, type FilloFormProps, FilloProvider, type FilloProviderProps, FormField, useField, useFillo, useFilloController };