@getuserfeedback/react 0.9.6 → 0.11.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 +22 -48
- package/dist/chunk-a3b04qn2.js +6 -0
- package/dist/chunk-a3b04qn2.js.map +10 -0
- package/dist/index.d.ts +55 -21
- package/dist/index.js +2 -2
- package/dist/index.js.map +2 -2
- package/dist/internal/inline-flow.d.ts +9 -1
- package/dist/internal/inline-flow.js +1 -1
- package/package.json +4 -3
- package/dist/chunk-thzce5rj.js +0 -6
- package/dist/chunk-thzce5rj.js.map +0 -10
package/README.md
CHANGED
|
@@ -1,68 +1,42 @@
|
|
|
1
1
|
# @getuserfeedback/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Add in-product surveys, forms, and messages to React applications with
|
|
4
|
+
[getuserfeedback.com](https://getuserfeedback.com).
|
|
4
5
|
|
|
5
|
-
>
|
|
6
|
+
> Using plain JavaScript or another browser framework? Use
|
|
7
|
+
> [@getuserfeedback/sdk](https://www.npmjs.com/package/@getuserfeedback/sdk).
|
|
6
8
|
>
|
|
7
|
-
> Building a React Native app? Use
|
|
9
|
+
> Building a React Native app? Use
|
|
10
|
+
> [@getuserfeedback/react-native](https://www.npmjs.com/package/@getuserfeedback/react-native).
|
|
8
11
|
|
|
9
|
-
##
|
|
12
|
+
## Get started
|
|
13
|
+
|
|
14
|
+
Install the SDK:
|
|
10
15
|
|
|
11
16
|
```bash
|
|
12
17
|
npm install @getuserfeedback/react
|
|
13
18
|
```
|
|
14
19
|
|
|
15
|
-
Requires
|
|
20
|
+
Requires React 18 or later.
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Installing this for someone? Start with our MCP server, not with this page. Connect `https://mcp.getuserfeedback.com` (listed in the MCP registry as `com.getuserfeedback/mcp`) and read its get-started resource — `getuserfeedback://docs/get-started`. It walks the whole path in order: workspace, API key (the MCP hands it to you), this package's install, the first survey, and which steps need a human.
|
|
20
|
-
|
|
21
|
-
## Get started
|
|
22
|
-
|
|
23
|
-
Grab your Public API key from the dashboard — Settings → Widget — and mount the provider near the root of your app:
|
|
22
|
+
Mount the provider near the root of your app using the Public API key from
|
|
23
|
+
[Widget settings](https://getuserfeedback.com/app/_/settings/widget):
|
|
24
24
|
|
|
25
25
|
```tsx
|
|
26
26
|
import { GetUserFeedbackProvider } from "@getuserfeedback/react";
|
|
27
27
|
|
|
28
28
|
export function App() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
If your app has signed-in users, also identify them. It lets surveys target signed-in users, and each answer arrives attributed to the person instead of anonymous. Call identify from an effect keyed on your auth state — resetting only when a signed-in user signs out, so anonymous visitors keep their identity — and render the component anywhere inside the provider:
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import { useEffect, useRef } from "react";
|
|
41
|
-
import { useGetUserFeedback } from "@getuserfeedback/react";
|
|
42
|
-
|
|
43
|
-
function IdentifyUser({ user }: { user: { id: string; email: string } | null }) {
|
|
44
|
-
const client = useGetUserFeedback();
|
|
45
|
-
const wasIdentified = useRef(false);
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (user) {
|
|
48
|
-
client.identify(user.id, { email: user.email });
|
|
49
|
-
wasIdentified.current = true;
|
|
50
|
-
} else if (wasIdentified.current) {
|
|
51
|
-
wasIdentified.current = false;
|
|
52
|
-
client.reset();
|
|
53
|
-
}
|
|
54
|
-
}, [user, client]);
|
|
55
|
-
return null;
|
|
29
|
+
return (
|
|
30
|
+
<GetUserFeedbackProvider clientOptions={{ apiKey: "YOUR_API_KEY" }}>
|
|
31
|
+
<YourApp />
|
|
32
|
+
</GetUserFeedbackProvider>
|
|
33
|
+
);
|
|
56
34
|
}
|
|
57
35
|
```
|
|
58
36
|
|
|
59
|
-
That
|
|
60
|
-
|
|
61
|
-
- Full guide: [getuserfeedback.com/docs/get-started/react-sdk](https://getuserfeedback.com/docs/get-started/react-sdk)
|
|
62
|
-
- API reference: [getuserfeedback.com/docs/reference/react-sdk-reference](https://getuserfeedback.com/docs/reference/react-sdk-reference)
|
|
63
|
-
|
|
64
|
-
## Links
|
|
37
|
+
That is enough to receive flows published for automatic Widget delivery.
|
|
65
38
|
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
39
|
+
- [React SDK guide](https://getuserfeedback.com/docs/get-started/react-sdk)
|
|
40
|
+
- [React SDK reference](https://getuserfeedback.com/docs/reference/react-sdk-reference)
|
|
41
|
+
- [Package versions](https://www.npmjs.com/package/@getuserfeedback/react?activeTab=versions)
|
|
42
|
+
- [Support](mailto:hello@getuserfeedback.com)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{createClient as L}from"@getuserfeedback/sdk";import{createActionRegistry as x}from"@getuserfeedback/sdk/internal/action-registry";import{createContext as E,useCallback as u,useContext as b,useEffect as P,useMemo as R,useRef as p,useState as S,useSyncExternalStore as D}from"react";import{jsx as j}from"react/jsx-runtime";var g={isOpen:!1,isLoading:!1,shouldRenderContainer:!1},T=(e)=>({isOpen:e.isOpen,isLoading:e.isLoading}),O=(e)=>typeof e.width==="number"&&typeof e.height==="number",M=(e,n)=>e.isOpen===n.isOpen&&e.isLoading===n.isLoading&&O(e)===O(n),I={isOpen:!1,isLoading:!1,width:void 0,height:void 0};function G(e){let n=p(e.getFlowState());return u(()=>{let o=e.getFlowState(),a=n.current;if(M(a,o))return a;return n.current=o,o},[e])}function U(e,n,o){let a=G(e),t=p(null),i=p(null),r=u(()=>{let s=a();if(t.current===s){let c=i.current;if(c!==null)return c}let l=n(s);return t.current=s,i.current=l,l},[a,n]);return D((s)=>e.subscribeFlowState(()=>{s()},{emitInitial:!1}),r,o)}var h=E(null),m=new WeakMap,v=(e)=>{try{return JSON.stringify(x(e).listRegistrationIdentities())}catch{return null}};function V({children:e,clientOptions:n}){let o=p(v(n.actions)),a=v(n.actions);if(a!==null&&o.current!==null&&a!==o.current)throw Error("GetUserFeedbackProvider clientOptions.actions definitions cannot change after mount. Keep each custom key and version fixed for the provider lifetime; handler functions may change.");let t=L(n),i=p(null),r=U(t,T,()=>g),s=u((d,f)=>{if(i.current!==d||m.get(t)!==d)return;t.setDefaultContainerPolicy({kind:"hostContainer",host:f,sharing:"perFlowRun"})},[t]),l=u((d,f)=>{let C=m.get(t);if(C!==void 0&&C!==d)throw Error("Only one useFlowContainer consumer can be mounted for a getuserfeedback client");return m.set(t,d),i.current=d,t.setDefaultContainerPolicy({kind:"hostContainer",host:f,sharing:"perFlowRun"}),()=>{if(i.current!==d||m.get(t)!==d)return;i.current=null,m.delete(t),t.setDefaultContainerPolicy({kind:"floating"})}},[t]),c=R(()=>{if(!r.isOpen&&!r.isLoading)return g;return{isOpen:r.isOpen,isLoading:r.isLoading,shouldRenderContainer:!0}},[r]),w=R(()=>({client:t,apiKey:n.apiKey,setDefaultFlowContainer:s,registerDefaultFlowContainerConsumer:l,defaultFlowContainerState:c}),[t,n.apiKey,c,l,s]);return j(h.Provider,{value:w,children:e})}var H=(e)=>{let{flowRun:n,openFlow:o,prerenderFlow:a,prefetchOnMount:t=!1,hideCloseButton:i}=e,r=e.mode==="container",s=p(null),l=U(n,(F)=>F,()=>I),c=u((F)=>o({container:r?s.current??null:void 0,hideCloseButton:i,metadata:F?.metadata}),[i,o,r]),w=u(()=>n.close(),[n]),d=u(()=>n.prefetch(),[n]),f=u((F)=>F?c():w(),[w,c]),C=u((F)=>{if(!r)return;s.current=F,n.setContainer(F)},[n,r]),y=O(l),k=r&&(l.isOpen||l.isLoading&&y);return P(()=>{if(!t)return;d().catch(()=>{})},[d,t]),{isOpen:l.isOpen,isLoading:l.isLoading,shouldRenderContainer:k,setOpen:f,open:c,close:w,prefetch:d,prerender:()=>a({container:r?s.current??null:void 0,hideCloseButton:i}),containerRef:C}};function B(e){let n=e.container??"default";if(p(n).current!==n)throw Error("useFlow container mode cannot change while mounted; remount the hook to change it");let a=n==="custom"?"container":"default",t=H({flowRun:e.flowRun,mode:a,openFlow:e.openFlow,prerenderFlow:e.prerenderFlow,prefetchOnMount:e.prefetchOnMount,hideCloseButton:e.hideCloseButton});if(a==="container")return{container:"custom",isOpen:t.isOpen,isLoading:t.isLoading,shouldRenderContainer:t.shouldRenderContainer,open:t.open,close:t.close,prefetch:t.prefetch,setOpen:t.setOpen,prerender:t.prerender,containerRef:t.containerRef};return{container:"default",isOpen:t.isOpen,isLoading:t.isLoading,open:t.open,close:t.close,prefetch:t.prefetch,prerender:t.prerender}}function _(e){let n=b(h);if(!n)throw Error("useFlow must be used within a GetUserFeedbackProvider");let o=R(()=>n.client.flow(e.flowId),[n.client,e.flowId]),a=u(({container:i,hideCloseButton:r,metadata:s})=>o.open(i===void 0?{hideCloseButton:r,metadata:s}:{container:i,hideCloseButton:r,metadata:s}),[o]),t=u(({hideCloseButton:i})=>o.prerender({hideCloseButton:i}),[o]);return B({flowRun:o,openFlow:a,prerenderFlow:t,container:e.container,prefetchOnMount:e.prefetchOnMount,hideCloseButton:e.hideCloseButton})}function W(){let e=b(h);if(!e)throw Error("useFlowContainer must be used within a GetUserFeedbackProvider");let{client:n,defaultFlowContainerState:o,registerDefaultFlowContainerConsumer:a,setDefaultFlowContainer:t}=e,i=p({}),r=p(null);P(()=>a(i.current,r.current),[a]);let s=u((c)=>{r.current=c,t(i.current,c)},[t]),l=u(()=>n.close(),[n]);return{isOpen:o.isOpen,isLoading:o.isLoading,shouldRenderContainer:o.shouldRenderContainer,close:l,containerRef:s}}function q(){let e=b(h);if(!e)throw Error("useFeedback must be used within a GetUserFeedbackProvider");let[n,o]=S(0),[a,t]=S(0),i=u(async(s)=>{o((l)=>l+1);try{return await e.client.feedback.fetch(s)}finally{o((l)=>l-1)}},[e.client]),r=u(async(s)=>{t((l)=>l+1);try{return await e.client.feedback.submit(s)}finally{t((l)=>l-1)}},[e.client]);return{fetch:i,isFetching:n>0,isSubmitting:a>0,submit:r}}function J(){let e=b(h);if(!e)throw Error("useGetUserFeedback must be used within a GetUserFeedbackProvider");return e.client}
|
|
3
|
+
export{h as a,V as b,B as c,_ as d,W as e,q as f,J as g};
|
|
4
|
+
|
|
5
|
+
//# debugId=3F0C5DDA586FBA5164756E2164756E21
|
|
6
|
+
//# sourceMappingURL=chunk-a3b04qn2.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/client.tsx"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"\"use client\";\n\nimport {\n\ttype Client,\n\ttype ClientOptions,\n\tcreateClient,\n\ttype FeedbackInput,\n\ttype FetchFeedbackInput,\n\ttype FetchFeedbackResult,\n\ttype FlowRun,\n\ttype FlowState,\n\ttype OpenFlowOptions as SdkOpenFlowOptions,\n\ttype SubmitFeedbackResult,\n} from \"@getuserfeedback/sdk\";\nimport { createActionRegistry } from \"@getuserfeedback/sdk/internal/action-registry\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\n\n/**\n * Return value for the experimental `useFeedback()` hook.\n *\n * @experimental\n */\nexport interface UseFeedbackReturn {\n\t/** Fetch feedback matching each selector for the JWT-authenticated user. */\n\tfetch: (input: FetchFeedbackInput) => Promise<FetchFeedbackResult>;\n\t/** True while one or more fetches from this hook are pending. */\n\tisFetching: boolean;\n\t/** True while one or more submissions from this hook are pending. */\n\tisSubmitting: boolean;\n\t/** Submit feedback about the current app or a specific target. */\n\tsubmit: (input: FeedbackInput) => Promise<SubmitFeedbackResult>;\n}\n\n/**\n * Options for useFlow().\n */\nexport interface UseFlowOptions {\n\t/** The flow/survey ID to control. */\n\tflowId: string;\n\t/** Prefetch the flow resources on mount so it opens faster. Default `false`. */\n\tprefetchOnMount?: boolean;\n\t/**\n\t * Where the flow mounts: `\"default\"` (floating container) or `\"custom\"` (your container via containerRef).\n\t * Default `\"default\"`. Remount the hook to change this mode.\n\t */\n\tcontainer?: \"default\" | \"custom\";\n\t/** When true, the view does not show a close button. */\n\thideCloseButton?: boolean;\n}\n\ntype UseFlowPresentationOptions = Pick<\n\tUseFlowOptions,\n\t\"container\" | \"hideCloseButton\" | \"prefetchOnMount\"\n>;\n\n/**\n * Per-open options for useFlow(). These apply to the specific response created\n * by that open action and do not affect prerendering.\n */\nexport interface UseFlowOpenOptions {\n\t/** Optional response metadata to preserve with the eventual submission. */\n\tmetadata?: SdkOpenFlowOptions[\"metadata\"];\n}\n\n/**\n * Return value for useFlow() when container is `\"default\"`: state and callbacks for the floating flow.\n */\nexport interface UseFlowReturn {\n\treadonly container: \"default\";\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True after open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** Open the flow. */\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\t/** Close the flow. */\n\tclose: () => Promise<void>;\n\t/** Prefetches the flow resources without opening it. */\n\tprefetch: () => Promise<void>;\n\t/** Prerendering warms up the flow for instant display later. */\n\tprerender: () => Promise<void>;\n}\n\n/**\n * Return value for useFlow() when container is `\"custom\"`: state and callbacks for host-managed container flows.\n */\nexport interface UseCustomFlowReturn {\n\treadonly container: \"custom\";\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True after open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the custom container element. */\n\tshouldRenderContainer: boolean;\n\t/** Open the flow in the custom container. */\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\t/** Close the flow. */\n\tclose: () => Promise<void>;\n\t/** Prefetches the flow resources without opening it. */\n\tprefetch: () => Promise<void>;\n\t/**\n\t * @deprecated Use `open()` or `close()` instead. Kept for compatibility.\n\t */\n\tsetOpen: (next: boolean) => Promise<void>;\n\t/** Prerendering warms up the flow for instant display later. */\n\tprerender: () => Promise<void>;\n\t/** Ref callback: attach this to the container element where the flow should render. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\n/**\n * Return value for useFlowContainer(): container ref and aggregate flow state\n * for flows using the default presentation in the same logical client\n * (including targeting-engine opens). Mount exactly one consumer per logical\n * client.\n */\nexport interface UseFlowContainerReturn {\n\t/** True when any flow is visible. */\n\tisOpen: boolean;\n\t/** True after any flow open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the provider-wide flow container. */\n\tshouldRenderContainer: boolean;\n\t/** Close all open flows owned by this logical client. */\n\tclose: () => Promise<void>;\n\t/** Ref callback for the provider-wide flow container element. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\ntype InstanceFlowRenderState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n};\n\ntype DefaultFlowContainerState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n};\n\nconst DEFAULT_FLOW_CONTAINER_STATE: DefaultFlowContainerState = {\n\tisOpen: false,\n\tisLoading: false,\n\tshouldRenderContainer: false,\n};\n\nconst toInstanceFlowRenderState = (\n\tstate: FlowState,\n): InstanceFlowRenderState => ({\n\tisOpen: state.isOpen,\n\tisLoading: state.isLoading,\n});\n\nconst hasPreparedFlowState = (state: FlowState): boolean =>\n\ttypeof state.width === \"number\" && typeof state.height === \"number\";\n\nconst isSameFlowLifecycleState = (\n\ta: Pick<FlowState, \"isOpen\" | \"isLoading\" | \"width\" | \"height\">,\n\tb: Pick<FlowState, \"isOpen\" | \"isLoading\" | \"width\" | \"height\">,\n): boolean =>\n\ta.isOpen === b.isOpen &&\n\ta.isLoading === b.isLoading &&\n\thasPreparedFlowState(a) === hasPreparedFlowState(b);\n\ntype FlowStateStore = {\n\tgetFlowState: () => FlowState;\n\tsubscribeFlowState: (\n\t\tlistener: (state: FlowState) => void,\n\t\toptions?: { emitInitial?: boolean },\n\t) => () => void;\n};\n\nconst FALLBACK_FLOW_STATE: FlowState = {\n\tisOpen: false,\n\tisLoading: false,\n\twidth: undefined,\n\theight: undefined,\n};\n\nfunction useStableFlowStateSnapshot(store: FlowStateStore): () => FlowState {\n\tconst snapshotRef = useRef<FlowState>(store.getFlowState());\n\n\treturn useCallback((): FlowState => {\n\t\tconst next = store.getFlowState();\n\t\tconst previous = snapshotRef.current;\n\t\tif (isSameFlowLifecycleState(previous, next)) {\n\t\t\treturn previous;\n\t\t}\n\t\tsnapshotRef.current = next;\n\t\treturn next;\n\t}, [store]);\n}\n\nfunction useFlowStateStoreValue<TState>(\n\tstore: FlowStateStore,\n\tproject: (state: FlowState) => TState,\n\tgetServerSnapshot: () => TState,\n): TState {\n\tconst getFlowStateSnapshot = useStableFlowStateSnapshot(store);\n\tconst lastSourceSnapshotRef = useRef<FlowState | null>(null);\n\tconst lastProjectedSnapshotRef = useRef<TState | null>(null);\n\tconst getProjectedSnapshot = useCallback((): TState => {\n\t\tconst sourceSnapshot = getFlowStateSnapshot();\n\t\tif (lastSourceSnapshotRef.current === sourceSnapshot) {\n\t\t\tconst cachedProjectedSnapshot = lastProjectedSnapshotRef.current;\n\t\t\tif (cachedProjectedSnapshot !== null) {\n\t\t\t\treturn cachedProjectedSnapshot;\n\t\t\t}\n\t\t}\n\t\tconst projectedSnapshot = project(sourceSnapshot);\n\t\tlastSourceSnapshotRef.current = sourceSnapshot;\n\t\tlastProjectedSnapshotRef.current = projectedSnapshot;\n\t\treturn projectedSnapshot;\n\t}, [getFlowStateSnapshot, project]);\n\n\treturn useSyncExternalStore<TState>(\n\t\t(onStoreChange) =>\n\t\t\tstore.subscribeFlowState(\n\t\t\t\t() => {\n\t\t\t\t\tonStoreChange();\n\t\t\t\t},\n\t\t\t\t{ emitInitial: false },\n\t\t\t),\n\t\tgetProjectedSnapshot,\n\t\tgetServerSnapshot,\n\t);\n}\n\ntype GetUserFeedbackContextValue = {\n\tclient: Client;\n\tapiKey: string;\n\tsetDefaultFlowContainer: (owner: object, element: HTMLElement | null) => void;\n\tregisterDefaultFlowContainerConsumer: (\n\t\towner: object,\n\t\telement: HTMLElement | null,\n\t) => () => void;\n\tdefaultFlowContainerState: DefaultFlowContainerState;\n};\n\nexport const GetUserFeedbackContext =\n\tcreateContext<GetUserFeedbackContextValue | null>(null);\n\nconst flowContainerOwnerByClient = new WeakMap<Client, object>();\n\nexport interface GetUserFeedbackProviderProps {\n\t/** Application subtree that can use getuserfeedback hooks. */\n\tchildren: ReactNode;\n\t/**\n\t * Core SDK client options used to create/reuse the underlying client.\n\t * Action definitions must remain fixed for the provider's mounted\n\t * lifetime; handlers may change while their custom key and version stay\n\t * the same.\n\t */\n\tclientOptions: ClientOptions;\n}\n\nconst toActionDefinitionsKey = (\n\tactions: ClientOptions[\"actions\"],\n): string | null => {\n\ttry {\n\t\treturn JSON.stringify(\n\t\t\tcreateActionRegistry(actions).listRegistrationIdentities(),\n\t\t);\n\t} catch {\n\t\treturn null;\n\t}\n};\n\n/**\n * Provider for getuserfeedback React hooks.\n * Wrap your app (or a subtree) so `useFlow`, `useFlowContainer`, and\n * `useGetUserFeedback` can access a client created from `clientOptions`.\n *\n * If your app uses `useFlowContainer()`, flows using the default presentation\n * in this subtree (including targeting-engine opens) target that container.\n * If the container ref is not mounted yet, loader keeps flows parked until it is.\n * Mount exactly one `useFlowContainer()` consumer per logical client. Providers\n * with the same API key and targeting context reuse that client.\n *\n * @example Basic usage\n * ```tsx\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <Routes />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n *\n * @example Display *any* flow in your own dialog (a shadcn/ui dialog in this example):\n * ```tsx\n * function AppFlowContainer() {\n * const { close, containerRef, shouldRenderContainer } = useFlowContainer();\n *\n * return (\n * <Dialog\n * open={shouldRenderContainer}\n * onOpenChange={(open) => {\n * if (!open) {\n * void close().catch((error) =>\n * console.error(\"Unable to close feedback\", error),\n * );\n * }\n * }}\n * >\n * <DialogContent>\n * <div ref={containerRef} style={{ width: \"100%\" }} />\n * </DialogContent>\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <AppFlowContainer /> // Targeted flows display in your dialog.\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function GetUserFeedbackProvider({\n\tchildren,\n\tclientOptions,\n}: GetUserFeedbackProviderProps): ReactElement {\n\tconst initialActionDefinitionsKeyRef = useRef(\n\t\ttoActionDefinitionsKey(clientOptions.actions),\n\t);\n\tconst actionDefinitionsKey = toActionDefinitionsKey(clientOptions.actions);\n\tif (\n\t\tactionDefinitionsKey !== null &&\n\t\tinitialActionDefinitionsKeyRef.current !== null &&\n\t\tactionDefinitionsKey !== initialActionDefinitionsKeyRef.current\n\t) {\n\t\tthrow new Error(\n\t\t\t\"GetUserFeedbackProvider clientOptions.actions definitions cannot change after mount. Keep each custom key and version fixed for the provider lifetime; handler functions may change.\",\n\t\t);\n\t}\n\tconst client = createClient(clientOptions);\n\tconst defaultFlowContainerOwnerRef = useRef<object | null>(null);\n\tconst instanceFlowState = useFlowStateStoreValue<InstanceFlowRenderState>(\n\t\tclient,\n\t\ttoInstanceFlowRenderState,\n\t\t() => DEFAULT_FLOW_CONTAINER_STATE,\n\t);\n\n\tconst setDefaultFlowContainer = useCallback(\n\t\t(owner: object, element: HTMLElement | null) => {\n\t\t\tif (\n\t\t\t\tdefaultFlowContainerOwnerRef.current !== owner ||\n\t\t\t\tflowContainerOwnerByClient.get(client) !== owner\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: element,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\t\t},\n\t\t[client],\n\t);\n\n\tconst registerDefaultFlowContainerConsumer = useCallback(\n\t\t(owner: object, element: HTMLElement | null) => {\n\t\t\tconst currentOwner = flowContainerOwnerByClient.get(client);\n\t\t\tif (currentOwner !== undefined && currentOwner !== owner) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Only one useFlowContainer consumer can be mounted for a getuserfeedback client\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tflowContainerOwnerByClient.set(client, owner);\n\t\t\tdefaultFlowContainerOwnerRef.current = owner;\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: element,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (\n\t\t\t\t\tdefaultFlowContainerOwnerRef.current !== owner ||\n\t\t\t\t\tflowContainerOwnerByClient.get(client) !== owner\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdefaultFlowContainerOwnerRef.current = null;\n\t\t\t\tflowContainerOwnerByClient.delete(client);\n\t\t\t\tclient.setDefaultContainerPolicy({ kind: \"floating\" });\n\t\t\t};\n\t\t},\n\t\t[client],\n\t);\n\n\tconst defaultFlowContainerState = useMemo<DefaultFlowContainerState>(() => {\n\t\tif (!instanceFlowState.isOpen && !instanceFlowState.isLoading) {\n\t\t\treturn DEFAULT_FLOW_CONTAINER_STATE;\n\t\t}\n\t\treturn {\n\t\t\tisOpen: instanceFlowState.isOpen,\n\t\t\tisLoading: instanceFlowState.isLoading,\n\t\t\tshouldRenderContainer: true,\n\t\t};\n\t}, [instanceFlowState]);\n\n\tconst contextValue = useMemo(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tapiKey: clientOptions.apiKey,\n\t\t\tsetDefaultFlowContainer,\n\t\t\tregisterDefaultFlowContainerConsumer,\n\t\t\tdefaultFlowContainerState,\n\t\t}),\n\t\t[\n\t\t\tclient,\n\t\t\tclientOptions.apiKey,\n\t\t\tdefaultFlowContainerState,\n\t\t\tregisterDefaultFlowContainerConsumer,\n\t\t\tsetDefaultFlowContainer,\n\t\t],\n\t);\n\n\treturn (\n\t\t<GetUserFeedbackContext.Provider value={contextValue}>\n\t\t\t{children}\n\t\t</GetUserFeedbackContext.Provider>\n\t);\n}\n\ntype FlowControllerRun = Pick<\n\tFlowRun,\n\t\"setContainer\" | \"getFlowState\" | \"subscribeFlowState\" | \"prefetch\" | \"close\"\n>;\n\ntype FlowControllerOpenInput = {\n\tcontainer: HTMLDivElement | null | undefined;\n\tmetadata?: UseFlowOpenOptions[\"metadata\"];\n\thideCloseButton?: boolean;\n};\n\nexport type UseFlowControllerOptions = {\n\tflowRun: FlowControllerRun;\n\tmode: \"default\" | \"container\";\n\topenFlow: (input: FlowControllerOpenInput) => Promise<void>;\n\tprerenderFlow: (input: {\n\t\tcontainer: HTMLDivElement | null | undefined;\n\t\thideCloseButton?: boolean;\n\t}) => Promise<void>;\n\tprefetchOnMount?: boolean;\n\thideCloseButton?: boolean;\n};\n\ntype UseFlowControllerReturn = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n\tsetOpen: (next: boolean) => Promise<void>;\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\tclose: () => Promise<void>;\n\tprefetch: () => Promise<void>;\n\tprerender: () => Promise<void>;\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n};\n\ntype UseFlowRunOptions = UseFlowPresentationOptions & {\n\tflowRun: FlowControllerRun;\n\topenFlow: UseFlowControllerOptions[\"openFlow\"];\n\tprerenderFlow: UseFlowControllerOptions[\"prerenderFlow\"];\n};\n\nconst useFlowController = (\n\toptions: UseFlowControllerOptions,\n): UseFlowControllerReturn => {\n\tconst {\n\t\tflowRun,\n\t\topenFlow,\n\t\tprerenderFlow,\n\t\tprefetchOnMount = false,\n\t\thideCloseButton,\n\t} = options;\n\tconst requiresContainer = options.mode === \"container\";\n\tconst customContainerRef = useRef<HTMLDivElement | null>(null);\n\n\t/** Flow state from loader events; dimensions are used only for prepared-view lifecycle. */\n\tconst flowState = useFlowStateStoreValue<FlowState>(\n\t\tflowRun,\n\t\t(state) => state,\n\t\t() => FALLBACK_FLOW_STATE,\n\t);\n\n\tconst open = useCallback(\n\t\t(openOptions?: UseFlowOpenOptions): Promise<void> =>\n\t\t\topenFlow({\n\t\t\t\tcontainer: requiresContainer\n\t\t\t\t\t? (customContainerRef.current ?? null)\n\t\t\t\t\t: undefined,\n\t\t\t\thideCloseButton,\n\t\t\t\tmetadata: openOptions?.metadata,\n\t\t\t}),\n\t\t[hideCloseButton, openFlow, requiresContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => flowRun.close(), [flowRun]);\n\tconst prefetch = useCallback(\n\t\t(): Promise<void> => flowRun.prefetch(),\n\t\t[flowRun],\n\t);\n\n\tconst setOpen = useCallback(\n\t\t(next: boolean): Promise<void> => (next ? open() : close()),\n\t\t[close, open],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tif (!requiresContainer) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcustomContainerRef.current = element;\n\t\t\tflowRun.setContainer(element);\n\t\t},\n\t\t[flowRun, requiresContainer],\n\t);\n\n\tconst hasPreparedCustomView = hasPreparedFlowState(flowState);\n\tconst shouldRenderContainer =\n\t\trequiresContainer &&\n\t\t(flowState.isOpen || (flowState.isLoading && hasPreparedCustomView));\n\n\tuseEffect(() => {\n\t\tif (!prefetchOnMount) {\n\t\t\treturn;\n\t\t}\n\t\tvoid prefetch().catch(() => {});\n\t}, [prefetch, prefetchOnMount]);\n\n\treturn {\n\t\tisOpen: flowState.isOpen,\n\t\tisLoading: flowState.isLoading,\n\t\tshouldRenderContainer,\n\t\tsetOpen,\n\t\topen,\n\t\tclose,\n\t\tprefetch,\n\t\tprerender: (): Promise<void> =>\n\t\t\tprerenderFlow({\n\t\t\t\tcontainer: requiresContainer\n\t\t\t\t\t? (customContainerRef.current ?? null)\n\t\t\t\t\t: undefined,\n\t\t\t\thideCloseButton,\n\t\t\t}),\n\t\tcontainerRef,\n\t};\n};\n\nexport function useFlowRun(\n\toptions: UseFlowRunOptions & { container?: \"default\" },\n): UseFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions & { container: \"custom\" },\n): UseCustomFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions,\n): UseFlowReturn | UseCustomFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions,\n): UseFlowReturn | UseCustomFlowReturn {\n\tconst container = options.container ?? \"default\";\n\tconst initialContainerRef = useRef(container);\n\tif (initialContainerRef.current !== container) {\n\t\tthrow new Error(\n\t\t\t\"useFlow container mode cannot change while mounted; remount the hook to change it\",\n\t\t);\n\t}\n\tconst mode = container === \"custom\" ? \"container\" : \"default\";\n\tconst controller = useFlowController({\n\t\tflowRun: options.flowRun,\n\t\tmode,\n\t\topenFlow: options.openFlow,\n\t\tprerenderFlow: options.prerenderFlow,\n\t\tprefetchOnMount: options.prefetchOnMount,\n\t\thideCloseButton: options.hideCloseButton,\n\t});\n\n\tif (mode === \"container\") {\n\t\treturn {\n\t\t\tcontainer: \"custom\",\n\t\t\tisOpen: controller.isOpen,\n\t\t\tisLoading: controller.isLoading,\n\t\t\tshouldRenderContainer: controller.shouldRenderContainer,\n\t\t\topen: controller.open,\n\t\t\tclose: controller.close,\n\t\t\tprefetch: controller.prefetch,\n\t\t\tsetOpen: controller.setOpen,\n\t\t\tprerender: controller.prerender,\n\t\t\tcontainerRef: controller.containerRef,\n\t\t};\n\t}\n\n\treturn {\n\t\tcontainer: \"default\",\n\t\tisOpen: controller.isOpen,\n\t\tisLoading: controller.isLoading,\n\t\topen: controller.open,\n\t\tclose: controller.close,\n\t\tprefetch: controller.prefetch,\n\t\tprerender: controller.prerender,\n\t};\n}\n\n/**\n * @name useFlow\n * @description Open a flow in the default container or your own container.\n * @example Default container\n * ```tsx\n * const { open, isLoading } = useFlow({ flowId: \"sur_123\" });\n * await open({\n * metadata: {\n * tags: {\n * journey_stage: \"onboarding\",\n * },\n * },\n * });\n * ```\n * @example Custom container\n * ```tsx\n * const { containerRef, shouldRenderContainer, open } = useFlow({ flowId: \"sur_123\", container: \"custom\" });\n * ```\n * @see https://getuserfeedback.com/docs/guides/advanced/containers\n */\nexport function useFlow(\n\toptions: UseFlowOptions & { container?: \"default\" },\n): UseFlowReturn;\nexport function useFlow(\n\toptions: UseFlowOptions & { container: \"custom\" },\n): UseCustomFlowReturn;\nexport function useFlow(\n\toptions: UseFlowOptions,\n): UseFlowReturn | UseCustomFlowReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useFlow must be used within a GetUserFeedbackProvider\");\n\t}\n\tconst flowRun = useMemo(\n\t\t() => ctx.client.flow(options.flowId),\n\t\t[ctx.client, options.flowId],\n\t);\n\tconst openFlow = useCallback(\n\t\t({ container, hideCloseButton, metadata }: FlowControllerOpenInput) =>\n\t\t\tflowRun.open(\n\t\t\t\tcontainer === undefined\n\t\t\t\t\t? { hideCloseButton, metadata }\n\t\t\t\t\t: { container, hideCloseButton, metadata },\n\t\t\t),\n\t\t[flowRun],\n\t);\n\tconst prerenderFlow = useCallback(\n\t\t({ hideCloseButton }: { hideCloseButton?: boolean }) =>\n\t\t\tflowRun.prerender({ hideCloseButton }),\n\t\t[flowRun],\n\t);\n\treturn useFlowRun({\n\t\tflowRun,\n\t\topenFlow,\n\t\tprerenderFlow,\n\t\tcontainer: options.container,\n\t\tprefetchOnMount: options.prefetchOnMount,\n\t\thideCloseButton: options.hideCloseButton,\n\t});\n}\n\n/**\n * @name useFlowContainer\n * @description Register and control the single default container for this provider subtree. Mount exactly one consumer per logical client.\n * @example Display any flow in your own dialog\n * ```tsx\n * function AppFlowContainer() {\n * const { close, containerRef, shouldRenderContainer } = useFlowContainer();\n * return (\n * <Dialog\n * open={shouldRenderContainer}\n * onOpenChange={(open) => {\n * if (!open) {\n * void close().catch((error) =>\n * console.error(\"Unable to close feedback\", error),\n * );\n * }\n * }}\n * >\n * <DialogContent>\n * <div ref={containerRef} style={{ width: \"100%\" }} />\n * </DialogContent>\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <AppFlowContainer />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n * @see https://getuserfeedback.com/docs/guides/advanced/containers\n */\nexport function useFlowContainer(): UseFlowContainerReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useFlowContainer must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\n\tconst {\n\t\tclient,\n\t\tdefaultFlowContainerState,\n\t\tregisterDefaultFlowContainerConsumer,\n\t\tsetDefaultFlowContainer,\n\t} = ctx;\n\tconst ownerRef = useRef<object>({});\n\tconst containerElementRef = useRef<HTMLDivElement | null>(null);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tregisterDefaultFlowContainerConsumer(\n\t\t\t\townerRef.current,\n\t\t\t\tcontainerElementRef.current,\n\t\t\t),\n\t\t[registerDefaultFlowContainerConsumer],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tcontainerElementRef.current = element;\n\t\t\tsetDefaultFlowContainer(ownerRef.current, element);\n\t\t},\n\t\t[setDefaultFlowContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => client.close(), [client]);\n\n\treturn {\n\t\tisOpen: defaultFlowContainerState.isOpen,\n\t\tisLoading: defaultFlowContainerState.isLoading,\n\t\tshouldRenderContainer: defaultFlowContainerState.shouldRenderContainer,\n\t\tclose,\n\t\tcontainerRef,\n\t};\n}\n\n/**\n * Experimental hook for submitting feedback or explicitly fetching the\n * JWT-authenticated user's feedback.\n *\n * Neither operation runs automatically. Each promise returns the corresponding\n * SDK result and rejects when the operation fails.\n *\n * @experimental\n */\nexport function useFeedback(): UseFeedbackReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useFeedback must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\n\tconst [pendingFetchCount, setPendingFetchCount] = useState(0);\n\tconst [pendingSubmissionCount, setPendingSubmissionCount] = useState(0);\n\tconst fetch = useCallback(\n\t\tasync (input: FetchFeedbackInput): Promise<FetchFeedbackResult> => {\n\t\t\tsetPendingFetchCount((count) => count + 1);\n\t\t\ttry {\n\t\t\t\treturn await ctx.client.feedback.fetch(input);\n\t\t\t} finally {\n\t\t\t\tsetPendingFetchCount((count) => count - 1);\n\t\t\t}\n\t\t},\n\t\t[ctx.client],\n\t);\n\tconst submit = useCallback(\n\t\tasync (input: FeedbackInput): Promise<SubmitFeedbackResult> => {\n\t\t\tsetPendingSubmissionCount((count) => count + 1);\n\t\t\ttry {\n\t\t\t\treturn await ctx.client.feedback.submit(input);\n\t\t\t} finally {\n\t\t\t\tsetPendingSubmissionCount((count) => count - 1);\n\t\t\t}\n\t\t},\n\t\t[ctx.client],\n\t);\n\n\treturn {\n\t\tfetch,\n\t\tisFetching: pendingFetchCount > 0,\n\t\tisSubmitting: pendingSubmissionCount > 0,\n\t\tsubmit,\n\t};\n}\n\n/**\n * Hook for accessing the getuserfeedback client instance.\n *\n * @see https://getuserfeedback.com/docs/reference/react-sdk-reference\n * @see https://getuserfeedback.com/docs/reference/events\n *\n * @example Basic usage\n * ```tsx\n * const client = useGetUserFeedback();\n *\n * async function handleLogin() {\n * await client.identify(\"user-123\", { email: \"user@example.com\" });\n * }\n *\n * async function handleCheckoutStarted() {\n * await client.track(\"Checkout Started\", { plan: \"pro\" });\n * }\n *\n * async function handleLogout() {\n * await client.reset();\n * }\n * ```\n *\n * @example Override color scheme\n * ```tsx\n * const client = useGetUserFeedback();\n * await client.configure({ colorScheme: \"dark\" });\n * ```\n */\nexport function useGetUserFeedback(): Client {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useGetUserFeedback must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\treturn ctx.client;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "3F0C5DDA586FBA5164756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { ReactNode, ReactElement } from 'react';
|
|
2
1
|
import { ClientOptions, OpenFlowOptions, FetchFeedbackInput, FetchFeedbackResult, FeedbackInput, SubmitFeedbackResult, Client } from '@getuserfeedback/sdk';
|
|
2
|
+
export { ActionsConfig, LinksConfig } from '@getuserfeedback/sdk';
|
|
3
|
+
import { ReactNode, ReactElement } from 'react';
|
|
3
4
|
|
|
4
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Return value for the experimental `useFeedback()` hook.
|
|
7
|
+
*
|
|
8
|
+
* @experimental
|
|
9
|
+
*/
|
|
5
10
|
interface UseFeedbackReturn {
|
|
6
11
|
/** Fetch feedback matching each selector for the JWT-authenticated user. */
|
|
7
12
|
fetch: (input: FetchFeedbackInput) => Promise<FetchFeedbackResult>;
|
|
@@ -49,6 +54,8 @@ interface UseFlowReturn {
|
|
|
49
54
|
open: (options?: UseFlowOpenOptions) => Promise<void>;
|
|
50
55
|
/** Close the flow. */
|
|
51
56
|
close: () => Promise<void>;
|
|
57
|
+
/** Prefetches the flow resources without opening it. */
|
|
58
|
+
prefetch: () => Promise<void>;
|
|
52
59
|
/** Prerendering warms up the flow for instant display later. */
|
|
53
60
|
prerender: () => Promise<void>;
|
|
54
61
|
}
|
|
@@ -65,7 +72,13 @@ interface UseCustomFlowReturn {
|
|
|
65
72
|
shouldRenderContainer: boolean;
|
|
66
73
|
/** Open the flow in the custom container. */
|
|
67
74
|
open: (options?: UseFlowOpenOptions) => Promise<void>;
|
|
68
|
-
/**
|
|
75
|
+
/** Close the flow. */
|
|
76
|
+
close: () => Promise<void>;
|
|
77
|
+
/** Prefetches the flow resources without opening it. */
|
|
78
|
+
prefetch: () => Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated Use `open()` or `close()` instead. Kept for compatibility.
|
|
81
|
+
*/
|
|
69
82
|
setOpen: (next: boolean) => Promise<void>;
|
|
70
83
|
/** Prerendering warms up the flow for instant display later. */
|
|
71
84
|
prerender: () => Promise<void>;
|
|
@@ -103,9 +116,8 @@ interface GetUserFeedbackProviderProps {
|
|
|
103
116
|
}
|
|
104
117
|
/**
|
|
105
118
|
* Provider for getuserfeedback React hooks.
|
|
106
|
-
* Wrap your app (or a subtree) so `
|
|
107
|
-
* `
|
|
108
|
-
* created from `clientOptions`.
|
|
119
|
+
* Wrap your app (or a subtree) so `useFlow`, `useFlowContainer`, and
|
|
120
|
+
* `useGetUserFeedback` can access a client created from `clientOptions`.
|
|
109
121
|
*
|
|
110
122
|
* If your app uses `useFlowContainer()`, flows using the default presentation
|
|
111
123
|
* in this subtree (including targeting-engine opens) target that container.
|
|
@@ -130,7 +142,16 @@ interface GetUserFeedbackProviderProps {
|
|
|
130
142
|
* const { close, containerRef, shouldRenderContainer } = useFlowContainer();
|
|
131
143
|
*
|
|
132
144
|
* return (
|
|
133
|
-
* <Dialog
|
|
145
|
+
* <Dialog
|
|
146
|
+
* open={shouldRenderContainer}
|
|
147
|
+
* onOpenChange={(open) => {
|
|
148
|
+
* if (!open) {
|
|
149
|
+
* void close().catch((error) =>
|
|
150
|
+
* console.error("Unable to close feedback", error),
|
|
151
|
+
* );
|
|
152
|
+
* }
|
|
153
|
+
* }}
|
|
154
|
+
* >
|
|
134
155
|
* <DialogContent>
|
|
135
156
|
* <div ref={containerRef} style={{ width: "100%" }} />
|
|
136
157
|
* </DialogContent>
|
|
@@ -151,8 +172,8 @@ interface GetUserFeedbackProviderProps {
|
|
|
151
172
|
declare function GetUserFeedbackProvider({ children, clientOptions, }: GetUserFeedbackProviderProps): ReactElement;
|
|
152
173
|
/**
|
|
153
174
|
* @name useFlow
|
|
154
|
-
* @description Open a
|
|
155
|
-
* @example Default
|
|
175
|
+
* @description Open a flow in the default container or your own container.
|
|
176
|
+
* @example Default container
|
|
156
177
|
* ```tsx
|
|
157
178
|
* const { open, isLoading } = useFlow({ flowId: "sur_123" });
|
|
158
179
|
* await open({
|
|
@@ -167,9 +188,7 @@ declare function GetUserFeedbackProvider({ children, clientOptions, }: GetUserFe
|
|
|
167
188
|
* ```tsx
|
|
168
189
|
* const { containerRef, shouldRenderContainer, open } = useFlow({ flowId: "sur_123", container: "custom" });
|
|
169
190
|
* ```
|
|
170
|
-
* @see docs/
|
|
171
|
-
* container and the per-flow custom container, cited by path so the internal
|
|
172
|
-
* set stays reachable. Level 3 is {@link useFlowContainer}.
|
|
191
|
+
* @see https://getuserfeedback.com/docs/guides/advanced/containers
|
|
173
192
|
*/
|
|
174
193
|
declare function useFlow(options: UseFlowOptions & {
|
|
175
194
|
container?: "default";
|
|
@@ -185,7 +204,16 @@ declare function useFlow(options: UseFlowOptions & {
|
|
|
185
204
|
* function AppFlowContainer() {
|
|
186
205
|
* const { close, containerRef, shouldRenderContainer } = useFlowContainer();
|
|
187
206
|
* return (
|
|
188
|
-
* <Dialog
|
|
207
|
+
* <Dialog
|
|
208
|
+
* open={shouldRenderContainer}
|
|
209
|
+
* onOpenChange={(open) => {
|
|
210
|
+
* if (!open) {
|
|
211
|
+
* void close().catch((error) =>
|
|
212
|
+
* console.error("Unable to close feedback", error),
|
|
213
|
+
* );
|
|
214
|
+
* }
|
|
215
|
+
* }}
|
|
216
|
+
* >
|
|
189
217
|
* <DialogContent>
|
|
190
218
|
* <div ref={containerRef} style={{ width: "100%" }} />
|
|
191
219
|
* </DialogContent>
|
|
@@ -202,14 +230,17 @@ declare function useFlow(options: UseFlowOptions & {
|
|
|
202
230
|
* );
|
|
203
231
|
* }
|
|
204
232
|
* ```
|
|
205
|
-
* @see docs/
|
|
233
|
+
* @see https://getuserfeedback.com/docs/guides/advanced/containers
|
|
206
234
|
*/
|
|
207
235
|
declare function useFlowContainer(): UseFlowContainerReturn;
|
|
208
236
|
/**
|
|
209
|
-
*
|
|
237
|
+
* Experimental hook for submitting feedback or explicitly fetching the
|
|
238
|
+
* JWT-authenticated user's feedback.
|
|
210
239
|
*
|
|
211
240
|
* Neither operation runs automatically. Each promise returns the corresponding
|
|
212
241
|
* SDK result and rejects when the operation fails.
|
|
242
|
+
*
|
|
243
|
+
* @experimental
|
|
213
244
|
*/
|
|
214
245
|
declare function useFeedback(): UseFeedbackReturn;
|
|
215
246
|
/**
|
|
@@ -222,14 +253,17 @@ declare function useFeedback(): UseFeedbackReturn;
|
|
|
222
253
|
* ```tsx
|
|
223
254
|
* const client = useGetUserFeedback();
|
|
224
255
|
*
|
|
225
|
-
*
|
|
226
|
-
* client.identify(
|
|
256
|
+
* async function handleLogin() {
|
|
257
|
+
* await client.identify("user-123", { email: "user@example.com" });
|
|
258
|
+
* }
|
|
227
259
|
*
|
|
228
|
-
*
|
|
229
|
-
* client.track("Checkout Started", { plan: "pro" });
|
|
260
|
+
* async function handleCheckoutStarted() {
|
|
261
|
+
* await client.track("Checkout Started", { plan: "pro" });
|
|
262
|
+
* }
|
|
230
263
|
*
|
|
231
|
-
*
|
|
232
|
-
* client.reset();
|
|
264
|
+
* async function handleLogout() {
|
|
265
|
+
* await client.reset();
|
|
266
|
+
* }
|
|
233
267
|
* ```
|
|
234
268
|
*
|
|
235
269
|
* @example Override color scheme
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{b as t,d as r,e as
|
|
2
|
+
import{b as t,d as r,e as s,f as n,g as _}from"./chunk-a3b04qn2.js";var e="0.11.0".trim(),o=e.length>0?e:"0.0.0-local";export{t as GetUserFeedbackProvider,o as REACT_SDK_VERSION,n as useFeedback,r as useFlow,s as useFlowContainer,_ as useGetUserFeedback};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=F9DD5B92FDB8C0E864756E2164756E21
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"declare const __GX_REACT_SDK_VERSION__: string | undefined;\n\nconst reactSdkVersion =\n\ttypeof __GX_REACT_SDK_VERSION__ === \"string\"\n\t\t? __GX_REACT_SDK_VERSION__.trim()\n\t\t: \"\";\n\n// Build scripts inject __GX_REACT_SDK_VERSION__ for published artifacts.\n// Source-linked workspace usage may not inject defines, so keep a safe fallback.\nexport const REACT_SDK_VERSION =\n\treactSdkVersion.length > 0 ? reactSdkVersion : \"0.0.0-local\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";oEAEA,IAAM,EAEF,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";oEAEA,IAAM,EAEF,SAAyB,KAAK,EAKrB,EACZ,EAAgB,OAAS,EAAI,EAAkB",
|
|
8
|
+
"debugId": "F9DD5B92FDB8C0E864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -23,6 +23,8 @@ interface UseFlowReturn {
|
|
|
23
23
|
open: (options?: UseFlowOpenOptions) => Promise<void>;
|
|
24
24
|
/** Close the flow. */
|
|
25
25
|
close: () => Promise<void>;
|
|
26
|
+
/** Prefetches the flow resources without opening it. */
|
|
27
|
+
prefetch: () => Promise<void>;
|
|
26
28
|
/** Prerendering warms up the flow for instant display later. */
|
|
27
29
|
prerender: () => Promise<void>;
|
|
28
30
|
}
|
|
@@ -39,7 +41,13 @@ interface UseCustomFlowReturn {
|
|
|
39
41
|
shouldRenderContainer: boolean;
|
|
40
42
|
/** Open the flow in the custom container. */
|
|
41
43
|
open: (options?: UseFlowOpenOptions) => Promise<void>;
|
|
42
|
-
/**
|
|
44
|
+
/** Close the flow. */
|
|
45
|
+
close: () => Promise<void>;
|
|
46
|
+
/** Prefetches the flow resources without opening it. */
|
|
47
|
+
prefetch: () => Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated Use `open()` or `close()` instead. Kept for compatibility.
|
|
50
|
+
*/
|
|
43
51
|
setOpen: (next: boolean) => Promise<void>;
|
|
44
52
|
/** Prerendering warms up the flow for instant display later. */
|
|
45
53
|
prerender: () => Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{a as s,c as i}from"../chunk-
|
|
2
|
+
import{a as s,c as i}from"../chunk-a3b04qn2.js";import{createInlineFlow as F}from"@getuserfeedback/sdk/internal/inline-flow";import{useCallback as l,useContext as p,useRef as f,useState as a}from"react";function R(t){let n=p(s);if(!n)throw Error("useFlow must be used within a GetUserFeedbackProvider");if(f(n.client).current!==n.client)throw Error("useFlow must be remounted when the GetUserFeedbackProvider client changes");let[e]=a(()=>F(n.client,t.flow)),u=l(({container:o,hideCloseButton:r,metadata:c})=>{if(o!==void 0)e.setContainer(o);return e.open({hideCloseButton:r,metadata:c})},[e]),w=l(({container:o,hideCloseButton:r})=>{if(o!==void 0)e.setContainer(o);return e.prerender({hideCloseButton:r})},[e]);return i({flowRun:e,openFlow:u,prerenderFlow:w,container:t.container,prefetchOnMount:t.prefetchOnMount,hideCloseButton:t.hideCloseButton})}export{R as useFlow};
|
|
3
3
|
|
|
4
4
|
//# debugId=49A3C1D11CF83FD564756E2164756E21
|
|
5
5
|
//# sourceMappingURL=inline-flow.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getuserfeedback/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "getuserfeedback React SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"getuserfeedback",
|
|
@@ -45,14 +45,15 @@
|
|
|
45
45
|
"lint": "biome check ."
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@getuserfeedback/sdk": "^0.
|
|
48
|
+
"@getuserfeedback/sdk": "^0.19.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"react": ">=18.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
+
"@typescript/typescript6": "^6.0.2",
|
|
54
55
|
"rollup": "^4.57.1",
|
|
55
|
-
"rollup-plugin-dts": "^6.
|
|
56
|
+
"rollup-plugin-dts": "^6.5.1",
|
|
56
57
|
"react-dom": "*"
|
|
57
58
|
}
|
|
58
59
|
}
|
package/dist/chunk-thzce5rj.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import{createClient as P}from"@getuserfeedback/sdk";import{createContext as L,useCallback as u,useContext as C,useEffect as U,useMemo as R,useRef as p,useState as S,useSyncExternalStore as x}from"react";import{jsx as B}from"react/jsx-runtime";var g={isOpen:!1,isLoading:!1,shouldRenderContainer:!1},E=(e)=>({isOpen:e.isOpen,isLoading:e.isLoading}),O=(e)=>typeof e.width==="number"&&typeof e.height==="number",T=(e,t)=>e.isOpen===t.isOpen&&e.isLoading===t.isLoading&&O(e)===O(t),D={isOpen:!1,isLoading:!1,width:void 0,height:void 0};function M(e){let t=p(e.getFlowState());return u(()=>{let o=e.getFlowState(),a=t.current;if(T(a,o))return a;return t.current=o,o},[e])}function v(e,t,o){let a=M(e),n=p(null),s=p(null),r=u(()=>{let i=a();if(n.current===i){let c=s.current;if(c!==null)return c}let l=t(i);return n.current=i,s.current=l,l},[a,t]);return x((i)=>e.subscribeFlowState(()=>{i()},{emitInitial:!1}),r,o)}var h=L(null),m=new WeakMap,I=(e,t)=>e<t?-1:e>t?1:0,y=(e)=>{if(e!==void 0&&!Array.isArray(e))return null;let t=[],o=new Set,a=!1;for(let n of e??[]){if(typeof n!=="object"||n===null)return null;let s=Reflect.get(n,"kind");if(s==="open-url"){if(a||typeof Reflect.get(n,"handler")!=="function")return null;a=!0,t.push("open-url");continue}if(s!=="custom")return null;let r=Reflect.get(n,"key"),i=Reflect.get(n,"version");if(typeof r!=="string"||r.trim().length===0||!Number.isSafeInteger(i)||i<=0||typeof Reflect.get(n,"handler")!=="function")return null;let l=`custom:${JSON.stringify([r.trim(),i])}`;if(o.has(l))return null;o.add(l),t.push(l)}return JSON.stringify(t.sort(I))};function K({children:e,clientOptions:t}){let o=p(y(t.actions)),a=y(t.actions);if(a!==null&&o.current!==null&&a!==o.current)throw Error("GetUserFeedbackProvider clientOptions.actions definitions cannot change after mount. Keep each custom key and version fixed for the provider lifetime; handler functions may change.");let n=P(t),s=p(null),r=v(n,E,()=>g),i=u((d,w)=>{if(s.current!==d||m.get(n)!==d)return;n.setDefaultContainerPolicy({kind:"hostContainer",host:w,sharing:"perFlowRun"})},[n]),l=u((d,w)=>{let b=m.get(n);if(b!==void 0&&b!==d)throw Error("Only one useFlowContainer consumer can be mounted for a getuserfeedback client");return m.set(n,d),s.current=d,n.setDefaultContainerPolicy({kind:"hostContainer",host:w,sharing:"perFlowRun"}),()=>{if(s.current!==d||m.get(n)!==d)return;s.current=null,m.delete(n),n.setDefaultContainerPolicy({kind:"floating"})}},[n]),c=R(()=>{if(!r.isOpen&&!r.isLoading)return g;return{isOpen:r.isOpen,isLoading:r.isLoading,shouldRenderContainer:!0}},[r]),f=R(()=>({client:n,apiKey:t.apiKey,setDefaultFlowContainer:i,registerDefaultFlowContainerConsumer:l,defaultFlowContainerState:c}),[n,t.apiKey,c,l,i]);return B(h.Provider,{value:f,children:e})}var G=(e)=>{let{flowRun:t,openFlow:o,prerenderFlow:a,prefetchOnMount:n=!1,hideCloseButton:s}=e,r=e.mode==="container",i=p(null),l=v(t,(F)=>F,()=>D),c=u((F)=>o({container:r?i.current??null:void 0,hideCloseButton:s,metadata:F?.metadata}),[s,o,r]),f=u(()=>t.close(),[t]),d=u((F)=>F?c():f(),[f,c]),w=u((F)=>{if(!r)return;i.current=F,t.setContainer(F)},[t,r]),b=O(l),k=r&&(l.isOpen||l.isLoading&&b);return U(()=>{if(!n)return;t.prefetch()},[t,n]),{isOpen:l.isOpen,isLoading:l.isLoading,shouldRenderContainer:k,setOpen:d,open:c,close:f,prerender:()=>a({container:r?i.current??null:void 0,hideCloseButton:s}),containerRef:w}};function H(e){let t=e.container??"default";if(p(t).current!==t)throw Error("useFlow container mode cannot change while mounted; remount the hook to change it");let a=t==="custom"?"container":"default",n=G({flowRun:e.flowRun,mode:a,openFlow:e.openFlow,prerenderFlow:e.prerenderFlow,prefetchOnMount:e.prefetchOnMount,hideCloseButton:e.hideCloseButton});if(a==="container")return{container:"custom",isOpen:n.isOpen,isLoading:n.isLoading,shouldRenderContainer:n.shouldRenderContainer,open:n.open,setOpen:n.setOpen,prerender:n.prerender,containerRef:n.containerRef};return{container:"default",isOpen:n.isOpen,isLoading:n.isLoading,open:n.open,close:n.close,prerender:n.prerender}}function N(e){let t=C(h);if(!t)throw Error("useFlow must be used within a GetUserFeedbackProvider");let o=R(()=>t.client.flow(e.flowId),[t.client,e.flowId]),a=u(({container:s,hideCloseButton:r,metadata:i})=>o.open(s===void 0?{hideCloseButton:r,metadata:i}:{container:s,hideCloseButton:r,metadata:i}),[o]),n=u(({hideCloseButton:s})=>o.prerender({hideCloseButton:s}),[o]);return H({flowRun:o,openFlow:a,prerenderFlow:n,container:e.container,prefetchOnMount:e.prefetchOnMount,hideCloseButton:e.hideCloseButton})}function V(){let e=C(h);if(!e)throw Error("useFlowContainer must be used within a GetUserFeedbackProvider");let{client:t,defaultFlowContainerState:o,registerDefaultFlowContainerConsumer:a,setDefaultFlowContainer:n}=e,s=p({}),r=p(null);U(()=>a(s.current,r.current),[a]);let i=u((c)=>{r.current=c,n(s.current,c)},[n]),l=u(()=>t.close(),[t]);return{isOpen:o.isOpen,isLoading:o.isLoading,shouldRenderContainer:o.shouldRenderContainer,close:l,containerRef:i}}function _(){let e=C(h);if(!e)throw Error("useFeedback must be used within a GetUserFeedbackProvider");let[t,o]=S(0),[a,n]=S(0),s=u(async(i)=>{o((l)=>l+1);try{return await e.client.feedback.fetch(i)}finally{o((l)=>l-1)}},[e.client]),r=u(async(i)=>{n((l)=>l+1);try{return await e.client.feedback.submit(i)}finally{n((l)=>l-1)}},[e.client]);return{fetch:s,isFetching:t>0,isSubmitting:a>0,submit:r}}function W(){let e=C(h);if(!e)throw Error("useGetUserFeedback must be used within a GetUserFeedbackProvider");return e.client}
|
|
3
|
-
export{h as a,K as b,H as c,N as d,V as e,_ as f,W as g};
|
|
4
|
-
|
|
5
|
-
//# debugId=86193C13A9FBB95364756E2164756E21
|
|
6
|
-
//# sourceMappingURL=chunk-thzce5rj.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/client.tsx"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"\"use client\";\n\nimport {\n\ttype Client,\n\ttype ClientOptions,\n\tcreateClient,\n\ttype FeedbackInput,\n\ttype FetchFeedbackInput,\n\ttype FetchFeedbackResult,\n\ttype FlowRun,\n\ttype FlowState,\n\ttype OpenFlowOptions as SdkOpenFlowOptions,\n\ttype SubmitFeedbackResult,\n} from \"@getuserfeedback/sdk\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\n\n/** Return value for useFeedback(). */\nexport interface UseFeedbackReturn {\n\t/** Fetch feedback matching each selector for the JWT-authenticated user. */\n\tfetch: (input: FetchFeedbackInput) => Promise<FetchFeedbackResult>;\n\t/** True while one or more fetches from this hook are pending. */\n\tisFetching: boolean;\n\t/** True while one or more submissions from this hook are pending. */\n\tisSubmitting: boolean;\n\t/** Submit feedback about the current app or a specific target. */\n\tsubmit: (input: FeedbackInput) => Promise<SubmitFeedbackResult>;\n}\n\n/**\n * Options for useFlow().\n */\nexport interface UseFlowOptions {\n\t/** The flow/survey ID to control. */\n\tflowId: string;\n\t/** Prefetch the flow resources on mount so it opens faster. Default `false`. */\n\tprefetchOnMount?: boolean;\n\t/**\n\t * Where the flow mounts: `\"default\"` (floating container) or `\"custom\"` (your container via containerRef).\n\t * Default `\"default\"`. Remount the hook to change this mode.\n\t */\n\tcontainer?: \"default\" | \"custom\";\n\t/** When true, the view does not show a close button. */\n\thideCloseButton?: boolean;\n}\n\ntype UseFlowPresentationOptions = Pick<\n\tUseFlowOptions,\n\t\"container\" | \"hideCloseButton\" | \"prefetchOnMount\"\n>;\n\n/**\n * Per-open options for useFlow(). These apply to the specific response created\n * by that open action and do not affect prerendering.\n */\nexport interface UseFlowOpenOptions {\n\t/** Optional response metadata to preserve with the eventual submission. */\n\tmetadata?: SdkOpenFlowOptions[\"metadata\"];\n}\n\n/**\n * Return value for useFlow() when container is `\"default\"`: state and callbacks for the floating flow.\n */\nexport interface UseFlowReturn {\n\treadonly container: \"default\";\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True after open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** Open the flow. */\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\t/** Close the flow. */\n\tclose: () => Promise<void>;\n\t/** Prerendering warms up the flow for instant display later. */\n\tprerender: () => Promise<void>;\n}\n\n/**\n * Return value for useFlow() when container is `\"custom\"`: state and callbacks for host-managed container flows.\n */\nexport interface UseCustomFlowReturn {\n\treadonly container: \"custom\";\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True after open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the custom container element. */\n\tshouldRenderContainer: boolean;\n\t/** Open the flow in the custom container. */\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\t/** Open the flow when `true`, close when `false`. */\n\tsetOpen: (next: boolean) => Promise<void>;\n\t/** Prerendering warms up the flow for instant display later. */\n\tprerender: () => Promise<void>;\n\t/** Ref callback: attach this to the container element where the flow should render. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\n/**\n * Return value for useFlowContainer(): container ref and aggregate flow state\n * for flows using the default presentation in the same logical client\n * (including targeting-engine opens). Mount exactly one consumer per logical\n * client.\n */\nexport interface UseFlowContainerReturn {\n\t/** True when any flow is visible. */\n\tisOpen: boolean;\n\t/** True after any flow open is requested while the flow is not visible yet. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the provider-wide flow container. */\n\tshouldRenderContainer: boolean;\n\t/** Close all open flows owned by this logical client. */\n\tclose: () => Promise<void>;\n\t/** Ref callback for the provider-wide flow container element. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\ntype InstanceFlowRenderState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n};\n\ntype DefaultFlowContainerState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n};\n\nconst DEFAULT_FLOW_CONTAINER_STATE: DefaultFlowContainerState = {\n\tisOpen: false,\n\tisLoading: false,\n\tshouldRenderContainer: false,\n};\n\nconst toInstanceFlowRenderState = (\n\tstate: FlowState,\n): InstanceFlowRenderState => ({\n\tisOpen: state.isOpen,\n\tisLoading: state.isLoading,\n});\n\nconst hasPreparedFlowState = (state: FlowState): boolean =>\n\ttypeof state.width === \"number\" && typeof state.height === \"number\";\n\nconst isSameFlowLifecycleState = (\n\ta: Pick<FlowState, \"isOpen\" | \"isLoading\" | \"width\" | \"height\">,\n\tb: Pick<FlowState, \"isOpen\" | \"isLoading\" | \"width\" | \"height\">,\n): boolean =>\n\ta.isOpen === b.isOpen &&\n\ta.isLoading === b.isLoading &&\n\thasPreparedFlowState(a) === hasPreparedFlowState(b);\n\ntype FlowStateStore = {\n\tgetFlowState: () => FlowState;\n\tsubscribeFlowState: (\n\t\tlistener: (state: FlowState) => void,\n\t\toptions?: { emitInitial?: boolean },\n\t) => () => void;\n};\n\nconst FALLBACK_FLOW_STATE: FlowState = {\n\tisOpen: false,\n\tisLoading: false,\n\twidth: undefined,\n\theight: undefined,\n};\n\nfunction useStableFlowStateSnapshot(store: FlowStateStore): () => FlowState {\n\tconst snapshotRef = useRef<FlowState>(store.getFlowState());\n\n\treturn useCallback((): FlowState => {\n\t\tconst next = store.getFlowState();\n\t\tconst previous = snapshotRef.current;\n\t\tif (isSameFlowLifecycleState(previous, next)) {\n\t\t\treturn previous;\n\t\t}\n\t\tsnapshotRef.current = next;\n\t\treturn next;\n\t}, [store]);\n}\n\nfunction useFlowStateStoreValue<TState>(\n\tstore: FlowStateStore,\n\tproject: (state: FlowState) => TState,\n\tgetServerSnapshot: () => TState,\n): TState {\n\tconst getFlowStateSnapshot = useStableFlowStateSnapshot(store);\n\tconst lastSourceSnapshotRef = useRef<FlowState | null>(null);\n\tconst lastProjectedSnapshotRef = useRef<TState | null>(null);\n\tconst getProjectedSnapshot = useCallback((): TState => {\n\t\tconst sourceSnapshot = getFlowStateSnapshot();\n\t\tif (lastSourceSnapshotRef.current === sourceSnapshot) {\n\t\t\tconst cachedProjectedSnapshot = lastProjectedSnapshotRef.current;\n\t\t\tif (cachedProjectedSnapshot !== null) {\n\t\t\t\treturn cachedProjectedSnapshot;\n\t\t\t}\n\t\t}\n\t\tconst projectedSnapshot = project(sourceSnapshot);\n\t\tlastSourceSnapshotRef.current = sourceSnapshot;\n\t\tlastProjectedSnapshotRef.current = projectedSnapshot;\n\t\treturn projectedSnapshot;\n\t}, [getFlowStateSnapshot, project]);\n\n\treturn useSyncExternalStore<TState>(\n\t\t(onStoreChange) =>\n\t\t\tstore.subscribeFlowState(\n\t\t\t\t() => {\n\t\t\t\t\tonStoreChange();\n\t\t\t\t},\n\t\t\t\t{ emitInitial: false },\n\t\t\t),\n\t\tgetProjectedSnapshot,\n\t\tgetServerSnapshot,\n\t);\n}\n\ntype GetUserFeedbackContextValue = {\n\tclient: Client;\n\tapiKey: string;\n\tsetDefaultFlowContainer: (owner: object, element: HTMLElement | null) => void;\n\tregisterDefaultFlowContainerConsumer: (\n\t\towner: object,\n\t\telement: HTMLElement | null,\n\t) => () => void;\n\tdefaultFlowContainerState: DefaultFlowContainerState;\n};\n\nexport const GetUserFeedbackContext =\n\tcreateContext<GetUserFeedbackContextValue | null>(null);\n\nconst flowContainerOwnerByClient = new WeakMap<Client, object>();\n\nexport interface GetUserFeedbackProviderProps {\n\t/** Application subtree that can use getuserfeedback hooks. */\n\tchildren: ReactNode;\n\t/**\n\t * Core SDK client options used to create/reuse the underlying client.\n\t * Action definitions must remain fixed for the provider's mounted\n\t * lifetime; handlers may change while their custom key and version stay\n\t * the same.\n\t */\n\tclientOptions: ClientOptions;\n}\n\nconst compareText = (left: string, right: string): number =>\n\tleft < right ? -1 : left > right ? 1 : 0;\n\nconst toActionDefinitionsKey = (\n\tactions: ClientOptions[\"actions\"],\n): string | null => {\n\tif (actions !== undefined && !Array.isArray(actions)) {\n\t\treturn null;\n\t}\n\tconst identities: string[] = [];\n\tconst customIdentities = new Set<string>();\n\tlet hasOpenUrl = false;\n\tfor (const registration of actions ?? []) {\n\t\tif (typeof registration !== \"object\" || registration === null) {\n\t\t\treturn null;\n\t\t}\n\t\tconst kind = Reflect.get(registration, \"kind\");\n\t\tif (kind === \"open-url\") {\n\t\t\tif (\n\t\t\t\thasOpenUrl ||\n\t\t\t\ttypeof Reflect.get(registration, \"handler\") !== \"function\"\n\t\t\t) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\thasOpenUrl = true;\n\t\t\tidentities.push(\"open-url\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (kind !== \"custom\") {\n\t\t\treturn null;\n\t\t}\n\t\tconst key = Reflect.get(registration, \"key\");\n\t\tconst version = Reflect.get(registration, \"version\");\n\t\tif (\n\t\t\ttypeof key !== \"string\" ||\n\t\t\tkey.trim().length === 0 ||\n\t\t\t!Number.isSafeInteger(version) ||\n\t\t\tversion <= 0 ||\n\t\t\ttypeof Reflect.get(registration, \"handler\") !== \"function\"\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\t\tconst identity = `custom:${JSON.stringify([key.trim(), version])}`;\n\t\tif (customIdentities.has(identity)) return null;\n\t\tcustomIdentities.add(identity);\n\t\tidentities.push(identity);\n\t}\n\treturn JSON.stringify(identities.sort(compareText));\n};\n\n/**\n * Provider for getuserfeedback React hooks.\n * Wrap your app (or a subtree) so `useFeedback`, `useFlow`,\n * `useFlowContainer`, and `useGetUserFeedback` can access a client\n * created from `clientOptions`.\n *\n * If your app uses `useFlowContainer()`, flows using the default presentation\n * in this subtree (including targeting-engine opens) target that container.\n * If the container ref is not mounted yet, loader keeps flows parked until it is.\n * Mount exactly one `useFlowContainer()` consumer per logical client. Providers\n * with the same API key and targeting context reuse that client.\n *\n * @example Basic usage\n * ```tsx\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <Routes />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n *\n * @example Display *any* flow in your own dialog (a shadcn/ui dialog in this example):\n * ```tsx\n * function AppFlowContainer() {\n * const { close, containerRef, shouldRenderContainer } = useFlowContainer();\n *\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={(open) => { if (!open) void close(); }}>\n * <DialogContent>\n * <div ref={containerRef} style={{ width: \"100%\" }} />\n * </DialogContent>\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <AppFlowContainer /> // Targeted flows display in your dialog.\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function GetUserFeedbackProvider({\n\tchildren,\n\tclientOptions,\n}: GetUserFeedbackProviderProps): ReactElement {\n\tconst initialActionDefinitionsKeyRef = useRef(\n\t\ttoActionDefinitionsKey(clientOptions.actions),\n\t);\n\tconst actionDefinitionsKey = toActionDefinitionsKey(clientOptions.actions);\n\tif (\n\t\tactionDefinitionsKey !== null &&\n\t\tinitialActionDefinitionsKeyRef.current !== null &&\n\t\tactionDefinitionsKey !== initialActionDefinitionsKeyRef.current\n\t) {\n\t\tthrow new Error(\n\t\t\t\"GetUserFeedbackProvider clientOptions.actions definitions cannot change after mount. Keep each custom key and version fixed for the provider lifetime; handler functions may change.\",\n\t\t);\n\t}\n\tconst client = createClient(clientOptions);\n\tconst defaultFlowContainerOwnerRef = useRef<object | null>(null);\n\tconst instanceFlowState = useFlowStateStoreValue<InstanceFlowRenderState>(\n\t\tclient,\n\t\ttoInstanceFlowRenderState,\n\t\t() => DEFAULT_FLOW_CONTAINER_STATE,\n\t);\n\n\tconst setDefaultFlowContainer = useCallback(\n\t\t(owner: object, element: HTMLElement | null) => {\n\t\t\tif (\n\t\t\t\tdefaultFlowContainerOwnerRef.current !== owner ||\n\t\t\t\tflowContainerOwnerByClient.get(client) !== owner\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: element,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\t\t},\n\t\t[client],\n\t);\n\n\tconst registerDefaultFlowContainerConsumer = useCallback(\n\t\t(owner: object, element: HTMLElement | null) => {\n\t\t\tconst currentOwner = flowContainerOwnerByClient.get(client);\n\t\t\tif (currentOwner !== undefined && currentOwner !== owner) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Only one useFlowContainer consumer can be mounted for a getuserfeedback client\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tflowContainerOwnerByClient.set(client, owner);\n\t\t\tdefaultFlowContainerOwnerRef.current = owner;\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: element,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\n\t\t\treturn () => {\n\t\t\t\tif (\n\t\t\t\t\tdefaultFlowContainerOwnerRef.current !== owner ||\n\t\t\t\t\tflowContainerOwnerByClient.get(client) !== owner\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdefaultFlowContainerOwnerRef.current = null;\n\t\t\t\tflowContainerOwnerByClient.delete(client);\n\t\t\t\tclient.setDefaultContainerPolicy({ kind: \"floating\" });\n\t\t\t};\n\t\t},\n\t\t[client],\n\t);\n\n\tconst defaultFlowContainerState = useMemo<DefaultFlowContainerState>(() => {\n\t\tif (!instanceFlowState.isOpen && !instanceFlowState.isLoading) {\n\t\t\treturn DEFAULT_FLOW_CONTAINER_STATE;\n\t\t}\n\t\treturn {\n\t\t\tisOpen: instanceFlowState.isOpen,\n\t\t\tisLoading: instanceFlowState.isLoading,\n\t\t\tshouldRenderContainer: true,\n\t\t};\n\t}, [instanceFlowState]);\n\n\tconst contextValue = useMemo(\n\t\t() => ({\n\t\t\tclient,\n\t\t\tapiKey: clientOptions.apiKey,\n\t\t\tsetDefaultFlowContainer,\n\t\t\tregisterDefaultFlowContainerConsumer,\n\t\t\tdefaultFlowContainerState,\n\t\t}),\n\t\t[\n\t\t\tclient,\n\t\t\tclientOptions.apiKey,\n\t\t\tdefaultFlowContainerState,\n\t\t\tregisterDefaultFlowContainerConsumer,\n\t\t\tsetDefaultFlowContainer,\n\t\t],\n\t);\n\n\treturn (\n\t\t<GetUserFeedbackContext.Provider value={contextValue}>\n\t\t\t{children}\n\t\t</GetUserFeedbackContext.Provider>\n\t);\n}\n\ntype FlowControllerRun = Pick<\n\tFlowRun,\n\t\"setContainer\" | \"getFlowState\" | \"subscribeFlowState\" | \"prefetch\" | \"close\"\n>;\n\ntype FlowControllerOpenInput = {\n\tcontainer: HTMLDivElement | null | undefined;\n\tmetadata?: UseFlowOpenOptions[\"metadata\"];\n\thideCloseButton?: boolean;\n};\n\nexport type UseFlowControllerOptions = {\n\tflowRun: FlowControllerRun;\n\tmode: \"default\" | \"container\";\n\topenFlow: (input: FlowControllerOpenInput) => Promise<void>;\n\tprerenderFlow: (input: {\n\t\tcontainer: HTMLDivElement | null | undefined;\n\t\thideCloseButton?: boolean;\n\t}) => Promise<void>;\n\tprefetchOnMount?: boolean;\n\thideCloseButton?: boolean;\n};\n\ntype UseFlowControllerReturn = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n\tsetOpen: (next: boolean) => Promise<void>;\n\topen: (options?: UseFlowOpenOptions) => Promise<void>;\n\tclose: () => Promise<void>;\n\tprerender: () => Promise<void>;\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n};\n\ntype UseFlowRunOptions = UseFlowPresentationOptions & {\n\tflowRun: FlowControllerRun;\n\topenFlow: UseFlowControllerOptions[\"openFlow\"];\n\tprerenderFlow: UseFlowControllerOptions[\"prerenderFlow\"];\n};\n\nconst useFlowController = (\n\toptions: UseFlowControllerOptions,\n): UseFlowControllerReturn => {\n\tconst {\n\t\tflowRun,\n\t\topenFlow,\n\t\tprerenderFlow,\n\t\tprefetchOnMount = false,\n\t\thideCloseButton,\n\t} = options;\n\tconst requiresContainer = options.mode === \"container\";\n\tconst customContainerRef = useRef<HTMLDivElement | null>(null);\n\n\t/** Flow state from loader events; dimensions are used only for prepared-view lifecycle. */\n\tconst flowState = useFlowStateStoreValue<FlowState>(\n\t\tflowRun,\n\t\t(state) => state,\n\t\t() => FALLBACK_FLOW_STATE,\n\t);\n\n\tconst open = useCallback(\n\t\t(openOptions?: UseFlowOpenOptions): Promise<void> =>\n\t\t\topenFlow({\n\t\t\t\tcontainer: requiresContainer\n\t\t\t\t\t? (customContainerRef.current ?? null)\n\t\t\t\t\t: undefined,\n\t\t\t\thideCloseButton,\n\t\t\t\tmetadata: openOptions?.metadata,\n\t\t\t}),\n\t\t[hideCloseButton, openFlow, requiresContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => flowRun.close(), [flowRun]);\n\n\tconst setOpen = useCallback(\n\t\t(next: boolean): Promise<void> => (next ? open() : close()),\n\t\t[close, open],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tif (!requiresContainer) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcustomContainerRef.current = element;\n\t\t\tflowRun.setContainer(element);\n\t\t},\n\t\t[flowRun, requiresContainer],\n\t);\n\n\tconst hasPreparedCustomView = hasPreparedFlowState(flowState);\n\tconst shouldRenderContainer =\n\t\trequiresContainer &&\n\t\t(flowState.isOpen || (flowState.isLoading && hasPreparedCustomView));\n\n\tuseEffect(() => {\n\t\tif (!prefetchOnMount) {\n\t\t\treturn;\n\t\t}\n\t\tflowRun.prefetch();\n\t}, [flowRun, prefetchOnMount]);\n\n\treturn {\n\t\tisOpen: flowState.isOpen,\n\t\tisLoading: flowState.isLoading,\n\t\tshouldRenderContainer,\n\t\tsetOpen,\n\t\topen,\n\t\tclose,\n\t\tprerender: (): Promise<void> =>\n\t\t\tprerenderFlow({\n\t\t\t\tcontainer: requiresContainer\n\t\t\t\t\t? (customContainerRef.current ?? null)\n\t\t\t\t\t: undefined,\n\t\t\t\thideCloseButton,\n\t\t\t}),\n\t\tcontainerRef,\n\t};\n};\n\nexport function useFlowRun(\n\toptions: UseFlowRunOptions & { container?: \"default\" },\n): UseFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions & { container: \"custom\" },\n): UseCustomFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions,\n): UseFlowReturn | UseCustomFlowReturn;\nexport function useFlowRun(\n\toptions: UseFlowRunOptions,\n): UseFlowReturn | UseCustomFlowReturn {\n\tconst container = options.container ?? \"default\";\n\tconst initialContainerRef = useRef(container);\n\tif (initialContainerRef.current !== container) {\n\t\tthrow new Error(\n\t\t\t\"useFlow container mode cannot change while mounted; remount the hook to change it\",\n\t\t);\n\t}\n\tconst mode = container === \"custom\" ? \"container\" : \"default\";\n\tconst controller = useFlowController({\n\t\tflowRun: options.flowRun,\n\t\tmode,\n\t\topenFlow: options.openFlow,\n\t\tprerenderFlow: options.prerenderFlow,\n\t\tprefetchOnMount: options.prefetchOnMount,\n\t\thideCloseButton: options.hideCloseButton,\n\t});\n\n\tif (mode === \"container\") {\n\t\treturn {\n\t\t\tcontainer: \"custom\",\n\t\t\tisOpen: controller.isOpen,\n\t\t\tisLoading: controller.isLoading,\n\t\t\tshouldRenderContainer: controller.shouldRenderContainer,\n\t\t\topen: controller.open,\n\t\t\tsetOpen: controller.setOpen,\n\t\t\tprerender: controller.prerender,\n\t\t\tcontainerRef: controller.containerRef,\n\t\t};\n\t}\n\n\treturn {\n\t\tcontainer: \"default\",\n\t\tisOpen: controller.isOpen,\n\t\tisLoading: controller.isLoading,\n\t\topen: controller.open,\n\t\tclose: controller.close,\n\t\tprerender: controller.prerender,\n\t};\n}\n\n/**\n * @name useFlow\n * @description Open a Widget survey in the default floating container or your own container.\n * @example Default (floating) container\n * ```tsx\n * const { open, isLoading } = useFlow({ flowId: \"sur_123\" });\n * await open({\n * metadata: {\n * tags: {\n * journey_stage: \"onboarding\",\n * },\n * },\n * });\n * ```\n * @example Custom container\n * ```tsx\n * const { containerRef, shouldRenderContainer, open } = useFlow({ flowId: \"sur_123\", container: \"custom\" });\n * ```\n * @see docs/custom-wrapper.md — integration levels 1 and 2, the default floating\n * container and the per-flow custom container, cited by path so the internal\n * set stays reachable. Level 3 is {@link useFlowContainer}.\n */\nexport function useFlow(\n\toptions: UseFlowOptions & { container?: \"default\" },\n): UseFlowReturn;\nexport function useFlow(\n\toptions: UseFlowOptions & { container: \"custom\" },\n): UseCustomFlowReturn;\nexport function useFlow(\n\toptions: UseFlowOptions,\n): UseFlowReturn | UseCustomFlowReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useFlow must be used within a GetUserFeedbackProvider\");\n\t}\n\tconst flowRun = useMemo(\n\t\t() => ctx.client.flow(options.flowId),\n\t\t[ctx.client, options.flowId],\n\t);\n\tconst openFlow = useCallback(\n\t\t({ container, hideCloseButton, metadata }: FlowControllerOpenInput) =>\n\t\t\tflowRun.open(\n\t\t\t\tcontainer === undefined\n\t\t\t\t\t? { hideCloseButton, metadata }\n\t\t\t\t\t: { container, hideCloseButton, metadata },\n\t\t\t),\n\t\t[flowRun],\n\t);\n\tconst prerenderFlow = useCallback(\n\t\t({ hideCloseButton }: { hideCloseButton?: boolean }) =>\n\t\t\tflowRun.prerender({ hideCloseButton }),\n\t\t[flowRun],\n\t);\n\treturn useFlowRun({\n\t\tflowRun,\n\t\topenFlow,\n\t\tprerenderFlow,\n\t\tcontainer: options.container,\n\t\tprefetchOnMount: options.prefetchOnMount,\n\t\thideCloseButton: options.hideCloseButton,\n\t});\n}\n\n/**\n * @name useFlowContainer\n * @description Register and control the single default container for this provider subtree. Mount exactly one consumer per logical client.\n * @example Display any flow in your own dialog\n * ```tsx\n * function AppFlowContainer() {\n * const { close, containerRef, shouldRenderContainer } = useFlowContainer();\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={(open) => { if (!open) void close(); }}>\n * <DialogContent>\n * <div ref={containerRef} style={{ width: \"100%\" }} />\n * </DialogContent>\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <AppFlowContainer />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n * @see docs/specs/2026-08-28-sdk-flow-container-contract.md\n */\nexport function useFlowContainer(): UseFlowContainerReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useFlowContainer must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\n\tconst {\n\t\tclient,\n\t\tdefaultFlowContainerState,\n\t\tregisterDefaultFlowContainerConsumer,\n\t\tsetDefaultFlowContainer,\n\t} = ctx;\n\tconst ownerRef = useRef<object>({});\n\tconst containerElementRef = useRef<HTMLDivElement | null>(null);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tregisterDefaultFlowContainerConsumer(\n\t\t\t\townerRef.current,\n\t\t\t\tcontainerElementRef.current,\n\t\t\t),\n\t\t[registerDefaultFlowContainerConsumer],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tcontainerElementRef.current = element;\n\t\t\tsetDefaultFlowContainer(ownerRef.current, element);\n\t\t},\n\t\t[setDefaultFlowContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => client.close(), [client]);\n\n\treturn {\n\t\tisOpen: defaultFlowContainerState.isOpen,\n\t\tisLoading: defaultFlowContainerState.isLoading,\n\t\tshouldRenderContainer: defaultFlowContainerState.shouldRenderContainer,\n\t\tclose,\n\t\tcontainerRef,\n\t};\n}\n\n/**\n * Submit feedback or explicitly fetch the JWT-authenticated user's feedback.\n *\n * Neither operation runs automatically. Each promise returns the corresponding\n * SDK result and rejects when the operation fails.\n */\nexport function useFeedback(): UseFeedbackReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useFeedback must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\n\tconst [pendingFetchCount, setPendingFetchCount] = useState(0);\n\tconst [pendingSubmissionCount, setPendingSubmissionCount] = useState(0);\n\tconst fetch = useCallback(\n\t\tasync (input: FetchFeedbackInput): Promise<FetchFeedbackResult> => {\n\t\t\tsetPendingFetchCount((count) => count + 1);\n\t\t\ttry {\n\t\t\t\treturn await ctx.client.feedback.fetch(input);\n\t\t\t} finally {\n\t\t\t\tsetPendingFetchCount((count) => count - 1);\n\t\t\t}\n\t\t},\n\t\t[ctx.client],\n\t);\n\tconst submit = useCallback(\n\t\tasync (input: FeedbackInput): Promise<SubmitFeedbackResult> => {\n\t\t\tsetPendingSubmissionCount((count) => count + 1);\n\t\t\ttry {\n\t\t\t\treturn await ctx.client.feedback.submit(input);\n\t\t\t} finally {\n\t\t\t\tsetPendingSubmissionCount((count) => count - 1);\n\t\t\t}\n\t\t},\n\t\t[ctx.client],\n\t);\n\n\treturn {\n\t\tfetch,\n\t\tisFetching: pendingFetchCount > 0,\n\t\tisSubmitting: pendingSubmissionCount > 0,\n\t\tsubmit,\n\t};\n}\n\n/**\n * Hook for accessing the getuserfeedback client instance.\n *\n * @see https://getuserfeedback.com/docs/reference/react-sdk-reference\n * @see https://getuserfeedback.com/docs/reference/events\n *\n * @example Basic usage\n * ```tsx\n * const client = useGetUserFeedback();\n *\n * // on login\n * client.identify('user-123', { email: 'user@example.com' });\n *\n * // track a product event\n * client.track(\"Checkout Started\", { plan: \"pro\" });\n *\n * // on logout\n * client.reset();\n * ```\n *\n * @example Override color scheme\n * ```tsx\n * const client = useGetUserFeedback();\n * await client.configure({ colorScheme: \"dark\" });\n * ```\n */\nexport function useGetUserFeedback(): Client {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useGetUserFeedback must be used within a GetUserFeedbackProvider\",\n\t\t);\n\t}\n\treturn ctx.client;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "86193C13A9FBB95364756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|