@usefillo/react 0.6.0 → 0.6.2
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 +68 -14
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @usefillo/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components and hooks for embedding [Fillo](https://fillo.so) forms **natively inside your product** — rendered in your own DOM, with your styles, on your route. No iframe.
|
|
4
4
|
|
|
5
5
|
### 📚 Full documentation → **[fillo.so/docs](https://fillo.so/docs)**
|
|
6
6
|
|
|
@@ -10,34 +10,88 @@ npm i @usefillo/react
|
|
|
10
10
|
|
|
11
11
|
`react` and `react-dom` (18 or 19) are peer dependencies.
|
|
12
12
|
|
|
13
|
+
## Write forms as components
|
|
14
|
+
|
|
13
15
|
```tsx
|
|
14
|
-
|
|
16
|
+
"use client";
|
|
17
|
+
import { Fillo, when, createClient } from "@usefillo/react";
|
|
15
18
|
import "@usefillo/react/styles.css"; // optional default theme — or bring your own
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const client = createClient({ key: process.env.NEXT_PUBLIC_FILLO_KEY });
|
|
21
|
+
|
|
22
|
+
export function ContactForm() {
|
|
23
|
+
return (
|
|
24
|
+
<Fillo.Form id="contact" title="Talk to us" client={client}>
|
|
25
|
+
<Fillo.Text id="name" label="Your name" required />
|
|
26
|
+
<Fillo.Email id="email" label="Work email" required />
|
|
27
|
+
<Fillo.Select id="topic" label="Topic" required>
|
|
28
|
+
<Fillo.Option id="sales" label="Sales" />
|
|
29
|
+
<Fillo.Option id="support" label="Support" />
|
|
30
|
+
</Fillo.Select>
|
|
31
|
+
<Fillo.LongText id="message" label="How can we help?"
|
|
32
|
+
visibleIf={when("topic").eq("support")} />
|
|
33
|
+
</Fillo.Form>
|
|
34
|
+
);
|
|
19
35
|
}
|
|
20
36
|
```
|
|
21
37
|
|
|
22
|
-
|
|
38
|
+
The first time this runs, the form appears in your Fillo workspace as a draft —
|
|
39
|
+
publish it there and responses, logic, exports, webhooks, and integrations all
|
|
40
|
+
work. Field ids are permanent (they key your responses); conditional questions
|
|
41
|
+
are `visibleIf`, never conditional JSX. The equivalent config style,
|
|
42
|
+
`defineForm({ id, pages })`, remains first-class — JSX compiles to it exactly.
|
|
43
|
+
|
|
44
|
+
## Or embed a form built in the dashboard
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { FilloForm } from "@usefillo/react";
|
|
48
|
+
|
|
49
|
+
<FilloForm formId="cust-feedback" onSubmitted={(r) => confetti()} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Style it with your own classes
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<Fillo.Form
|
|
56
|
+
id="contact"
|
|
57
|
+
client={client}
|
|
58
|
+
appearance={{
|
|
59
|
+
theme: { primary: "#4f46e5", radius: "12px" }, // also themes your hosted page
|
|
60
|
+
classNames: {
|
|
61
|
+
control: "rounded-xl border-zinc-200 data-[invalid]:border-red-400",
|
|
62
|
+
option: "rounded-lg border p-3 data-[selected]:border-indigo-600",
|
|
63
|
+
button: (s) => (s.variant === "primary" ? "bg-indigo-600 text-white" : ""),
|
|
64
|
+
},
|
|
65
|
+
fields: { nps: { control: "grid grid-cols-11 gap-1" } },
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
```
|
|
23
69
|
|
|
24
|
-
|
|
25
|
-
- `
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
|
|
70
|
+
Every rendered part carries a named slot (`data-fillo`) and state attributes
|
|
71
|
+
(`data-invalid`, `data-selected`, `data-checked`, …), and the default
|
|
72
|
+
stylesheet is cascade-layered so your utilities always win. On Tailwind v3 or
|
|
73
|
+
reset-heavy sites import `@usefillo/react/styles.unlayered.css` instead.
|
|
74
|
+
Localize every built-in string with the `strings` prop. Styling contract:
|
|
75
|
+
[fillo.so/docs/styling](https://fillo.so/docs/styling).
|
|
29
76
|
|
|
30
|
-
|
|
77
|
+
## Go fully headless
|
|
31
78
|
|
|
32
|
-
|
|
79
|
+
Every part is replaceable — and every embed method is free:
|
|
33
80
|
|
|
34
|
-
|
|
81
|
+
- `components` / `customComponents` — swap any field kind for your own
|
|
82
|
+
- `<FilloProvider>` + `<FormField>` / `useField()` — your layout, Fillo's engine
|
|
83
|
+
- `useFilloController()` — the bare engine for total control
|
|
35
84
|
|
|
36
|
-
|
|
85
|
+
URL prefill works in embeds (`?field=value`, hidden-field `paramName`),
|
|
86
|
+
submissions retry safely, and failed submits show a visible, answer-preserving
|
|
87
|
+
error. This package re-exports the embedding surface from
|
|
88
|
+
[`@usefillo/core`](https://www.npmjs.com/package/@usefillo/core) so a single
|
|
89
|
+
import is usually enough.
|
|
37
90
|
|
|
38
91
|
## Links
|
|
39
92
|
|
|
40
93
|
- **Docs:** [fillo.so/docs](https://fillo.so/docs)
|
|
94
|
+
- **Authoring guide:** [fillo.so/docs/authoring](https://fillo.so/docs/authoring)
|
|
41
95
|
- **Website:** [fillo.so](https://fillo.so)
|
|
42
96
|
|
|
43
97
|
MIT licensed.
|
package/dist/index.d.ts
CHANGED
|
@@ -148,6 +148,7 @@ type ContentProps = {
|
|
|
148
148
|
id: string;
|
|
149
149
|
children?: string;
|
|
150
150
|
text?: string;
|
|
151
|
+
visibleIf?: Condition | Condition[];
|
|
151
152
|
};
|
|
152
153
|
/** Inert: rendering one throws; they exist to be read by the compiler. */
|
|
153
154
|
type Inert<P> = (props: P) => never;
|
|
@@ -194,6 +195,7 @@ declare const Fillo: {
|
|
|
194
195
|
readonly Paragraph: Inert<ContentProps>;
|
|
195
196
|
readonly Divider: Inert<{
|
|
196
197
|
id: string;
|
|
198
|
+
visibleIf?: Condition | Condition[];
|
|
197
199
|
}>;
|
|
198
200
|
readonly Page: Inert<{
|
|
199
201
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -706,10 +706,11 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
706
706
|
setInFlight((prev) => prev.filter((f) => f.key !== key));
|
|
707
707
|
const current = Array.isArray(api.data[field.id]) ? api.data[field.id] : [];
|
|
708
708
|
setValue([...current, uploaded]);
|
|
709
|
-
} catch {
|
|
709
|
+
} catch (err) {
|
|
710
710
|
if (mountedRef.current) {
|
|
711
|
+
const message = err instanceof Error && err.name === "FilloError" && err.message ? err.message : "Upload failed \u2014 try again";
|
|
711
712
|
setInFlight(
|
|
712
|
-
(prev) => prev.map((f) => f.key === key ? { ...f, error:
|
|
713
|
+
(prev) => prev.map((f) => f.key === key ? { ...f, error: message } : f)
|
|
713
714
|
);
|
|
714
715
|
}
|
|
715
716
|
} finally {
|
|
@@ -773,7 +774,7 @@ function FileUploadField({ field, value, error, setValue, api, ids: providedIds
|
|
|
773
774
|
hidden: true,
|
|
774
775
|
multiple: maxFiles > 1,
|
|
775
776
|
accept: schema.accept?.join(","),
|
|
776
|
-
onChange: (e) => handleFiles(e.target.files)
|
|
777
|
+
onChange: (e) => canUpload && handleFiles(e.target.files)
|
|
777
778
|
}
|
|
778
779
|
),
|
|
779
780
|
canUpload ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
@@ -2149,8 +2150,8 @@ function FilloProvider({ children, form, formId, client, appearance, strings, ..
|
|
|
2149
2150
|
client,
|
|
2150
2151
|
form: schema,
|
|
2151
2152
|
formId: syncedFormId ?? formId,
|
|
2152
|
-
// Headless
|
|
2153
|
-
//
|
|
2153
|
+
// Headless = your markup, no Fillo-rendered layout. Free like every embed
|
|
2154
|
+
// method; recorded per response so usage stays measurable.
|
|
2154
2155
|
surface: "headless"
|
|
2155
2156
|
});
|
|
2156
2157
|
return /* @__PURE__ */ jsx7(FilloContext.Provider, { value: api, children: /* @__PURE__ */ jsx7(FilloStringsContext.Provider, { value: resolveStrings2(strings), children: /* @__PURE__ */ jsx7(FilloAppearanceContext.Provider, { value: appearance, children: /* @__PURE__ */ jsx7(FilloInstanceIdContext.Provider, { value: instanceId, children }) }) }) });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usefillo/react",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Headless React components for embedding Fillo forms natively in your product.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@usefillo/core": "^0.6.
|
|
36
|
+
"@usefillo/core": "^0.6.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^18.0.0 || ^19.0.0",
|