@ganeshdole/brainbox-react 0.1.0 → 0.3.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
@@ -33,13 +33,30 @@ const transport = brainboxTransport({ endpoint, projectKey });
33
33
 
34
34
  export function Root() {
35
35
  return (
36
- <BrainboxProvider transport={transport} identity={{ id: user.id, email: user.email }}>
36
+ <BrainboxProvider
37
+ transport={transport}
38
+ identity={{ id: user.id, email: user.email, name: user.name, phone: user.phone }}
39
+ fields={[
40
+ { label: "Plan", value: account.plan, highlight: true },
41
+ { label: "Account ID", value: account.id, type: "id" },
42
+ ]}
43
+ >
37
44
  <App />
38
45
  </BrainboxProvider>
39
46
  );
40
47
  }
41
48
  ```
42
49
 
50
+ `identity` is who is reporting, and `fields` are your app's own details,
51
+ whatever you want next to every report. The dashboard shows both in the
52
+ report's "Reported by" card: the person's name, email and phone, then your
53
+ fields with your labels, in your order. Adding one needs no change in
54
+ Brainbox. `type` is optional: `email`,
55
+ `phone` and `url` become links, `id` shows in monospace, anything else is
56
+ text. `highlight: true` also puts a field's value under the person's name, for
57
+ the one or two details that say where a report came from. Up to 30 fields,
58
+ labels up to 60 characters, values up to 500.
59
+
43
60
  Your own UI on top of the engine:
44
61
 
45
62
  ```tsx
@@ -63,7 +80,9 @@ function Panel({ draft }: { draft: Draft }) {
63
80
  keeps a server render side-effect free and leaves exactly one instance
64
81
  under StrictMode's mount-unmount-mount. The cost is one render in which
65
82
  `useBrainbox()` is `null`.
66
- - `identity` changes call `identify()` on the live instance. `onSubmitted`
83
+ - `identity` changes call `identify()`, and `fields` changes call
84
+ `setFields()`, on the live instance. The `fields` prop owns the instance's
85
+ fields: dropping it clears them. `onSubmitted`
67
86
  may change freely. Only a new `transport` rebuilds the instance.
68
87
  - `<BrainboxProvider brainbox={instance}>` provides an instance you created
69
88
  and own. Shells outside React (the script-tag bundle) use this.
@@ -1,11 +1,14 @@
1
1
  import { type ReactNode } from "react";
2
- import { type Brainbox, type Identity, type SubmitResult, type Transport } from "@ganeshdole/brainbox-core";
2
+ import { type Brainbox, type Identity, type ReportField, type SubmitResult, type Transport } from "@ganeshdole/brainbox-core";
3
3
  interface OwnedProps {
4
4
  /** Where finished reports go. Keep it stable (module-level or `useMemo`):
5
5
  * a new transport means a new instance. */
6
6
  transport: Transport;
7
7
  /** Who is filing. Changing it calls `identify()` on the live instance. */
8
8
  identity?: Identity;
9
+ /** Your app's own details for every report (clinic, plan, ...). Changing it
10
+ * calls `setFields()` on the live instance. */
11
+ fields?: ReportField[];
9
12
  /** Called after every successful submit. May change between renders. */
10
13
  onSubmitted?: (result: SubmitResult) => void;
11
14
  brainbox?: never;
@@ -17,6 +20,7 @@ interface GivenProps {
17
20
  brainbox: Brainbox;
18
21
  transport?: never;
19
22
  identity?: never;
23
+ fields?: never;
20
24
  onSubmitted?: never;
21
25
  }
22
26
  export type BrainboxProviderProps = (OwnedProps | GivenProps) & {
package/dist/provider.js CHANGED
@@ -17,7 +17,7 @@ export function BrainboxProvider(props) {
17
17
  }
18
18
  return _jsx(OwnedProvider, { ...props });
19
19
  }
20
- function OwnedProvider({ transport, identity, onSubmitted, children, }) {
20
+ function OwnedProvider({ transport, identity, fields, onSubmitted, children, }) {
21
21
  const [brainbox, setBrainbox] = useState(null);
22
22
  // Read through refs so a new callback or identity does not rebuild the instance.
23
23
  const onSubmittedRef = useRef(onSubmitted);
@@ -28,10 +28,15 @@ function OwnedProvider({ transport, identity, onSubmitted, children, }) {
28
28
  useEffect(() => {
29
29
  identityRef.current = identity;
30
30
  }, [identity]);
31
+ const fieldsRef = useRef(fields);
32
+ useEffect(() => {
33
+ fieldsRef.current = fields;
34
+ }, [fields]);
31
35
  useEffect(() => {
32
36
  const options = {
33
37
  transport,
34
38
  identity: identityRef.current,
39
+ fields: fieldsRef.current,
35
40
  onSubmitted: (result) => onSubmittedRef.current?.(result),
36
41
  };
37
42
  const instance = createBrainbox(options);
@@ -45,6 +50,11 @@ function OwnedProvider({ transport, identity, onSubmitted, children, }) {
45
50
  if (brainbox && identity)
46
51
  brainbox.identify(identity);
47
52
  }, [brainbox, identity]);
53
+ // The prop owns the instance's fields: dropping it clears them, so a
54
+ // signed-out user's reports never carry the previous account's details.
55
+ useEffect(() => {
56
+ brainbox?.setFields(fields ?? []);
57
+ }, [brainbox, fields]);
48
58
  return _jsx(BrainboxContext.Provider, { value: brainbox, children: children });
49
59
  }
50
60
  /** The nearest provider's instance. `null` during the first render and on the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganeshdole/brainbox-react",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "React bindings for @ganeshdole/brainbox-core: a provider that owns one Brainbox instance and hooks that read it. No UI.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://www.brainbox.sh",
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@ganeshdole/brainbox-core": "0.1.0"
30
+ "@ganeshdole/brainbox-core": "0.3.0"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": "^19.0.0"