@getuserfeedback/react 0.1.2 → 0.2.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
@@ -69,7 +69,7 @@ By default, flows are displayed in a floating container and [themed](https://get
69
69
  For example, if you're using shadcn/ui dialogs throughout your product, our widgets can be seamlessly rendered into them and appear just like any other part of your app.
70
70
 
71
71
  ```tsx
72
- import { useFlowContainer } from "@getuserfeedback/react";
72
+ import { useFlow } from "@getuserfeedback/react";
73
73
  import { Button, Dialog, DialogContent } from "ui";
74
74
 
75
75
  export function FeedbackDialog() {
@@ -80,7 +80,7 @@ export function FeedbackDialog() {
80
80
  containerRef,
81
81
  width,
82
82
  height
83
- } = useFlowContainer({ flowId: "YOUR_FLOW_ID" });
83
+ } = useFlow({ flowId: "YOUR_FLOW_ID", container: "custom" });
84
84
 
85
85
  return (
86
86
  <>
@@ -106,8 +106,7 @@ export function FeedbackDialog() {
106
106
 
107
107
  - `GetUserFeedbackProvider`
108
108
  - `useGetUserFeedback()`
109
- - `useFlow({ flowId, prefetchOnMount? })`
110
- - `useFlowContainer({ flowId, prefetchOnMount? })`
109
+ - `useFlow({ flowId, prefetchOnMount?, container?: "default" | "custom" })`
111
110
  - `useDefaultFlowContainer()`
112
111
 
113
112
  ## `GetUserFeedbackProvider`
package/dist/index.d.ts CHANGED
@@ -9,11 +9,17 @@ interface UseFlowOptions {
9
9
  flowId: string;
10
10
  /** Prefetch the flow resources on mount so it opens faster. Default `false`. */
11
11
  prefetchOnMount?: boolean;
12
+ /**
13
+ * Where the flow mounts: `"default"` (floating container) or `"custom"` (your container via containerRef).
14
+ * Default `"default"`.
15
+ */
16
+ container?: "default" | "custom";
12
17
  }
13
18
  /**
14
- * Return value for useFlow(): state and callbacks to show the default floating flow.
19
+ * Return value for useFlow() when container is `"default"`: state and callbacks for the floating flow.
15
20
  */
16
21
  interface UseFlowReturn {
22
+ readonly container: "default";
17
23
  /** True when the flow is visible. */
18
24
  isOpen: boolean;
19
25
  /** True when the flow is loading. */
@@ -30,9 +36,10 @@ interface UseFlowReturn {
30
36
  height?: number;
31
37
  }
32
38
  /**
33
- * Return value for useFlowContainer(): state and callbacks for host-managed container flows.
39
+ * Return value for useFlow() when container is `"custom"`: state and callbacks for host-managed container flows.
34
40
  */
35
41
  interface UseFlowContainerReturn {
42
+ readonly container: "custom";
36
43
  /** True when the flow is visible. */
37
44
  isOpen: boolean;
38
45
  /** True when the flow is loading. */
@@ -78,8 +85,8 @@ interface GetUserFeedbackProviderProps {
78
85
  }
79
86
  /**
80
87
  * Provider for getuserfeedback React hooks.
81
- * Wrap your app (or a subtree) so `useFlow`, `useFlowContainer`,
82
- * `useDefaultFlowContainer`, and `useGetUserFeedback` can access a client
88
+ * Wrap your app (or a subtree) so `useFlow`, `useDefaultFlowContainer`, and
89
+ * `useGetUserFeedback` can access a client
83
90
  * created from `clientOptions`.
84
91
  *
85
92
  * If your app uses `useDefaultFlowContainer()`, all flows in this subtree
@@ -122,47 +129,22 @@ interface GetUserFeedbackProviderProps {
122
129
  declare function GetUserFeedbackProvider({ children, clientOptions, }: GetUserFeedbackProviderProps): ReactElement;
123
130
  /**
124
131
  * @name useFlow
125
- * @description Imperatively display a flow.
126
- * @example Basic usage
132
+ * @description Imperatively display a flow in the default floating container or your own container.
133
+ * @example Default (floating) container
127
134
  * ```tsx
128
- * function FeedbackButton() {
129
- * const { open, isLoading } = useFlow({ flowId: "sur_123" });
130
- * return <Button onClick={() => open()} disabled={isLoading}>Feedback</Button>;
131
- * }
135
+ * const { open, isLoading } = useFlow({ flowId: "sur_123" });
132
136
  * ```
133
- */
134
- declare function useFlow(flow: UseFlowOptions): UseFlowReturn;
135
- /**
136
- * @name useFlowContainer
137
- * @description Imperatively display a flow in your own container element.
138
- * @example In a custom dialog
137
+ * @example Custom container
139
138
  * ```tsx
140
- * function FlowContainerDialog() {
141
- * const { containerRef, shouldRenderContainer, width, height, setOpen, isLoading } =
142
- * useFlowContainer({ flowId: "sur_123" });
143
- *
144
- * return (
145
- * <>
146
- * <Button onClick={() => setOpen(true)} loading={isLoading}>
147
- * Feedback
148
- * </Button>
149
- * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>
150
- * <DialogContent ref={containerRef} style={{ width, height }} />
151
- * </Dialog>
152
- * </>
153
- * );
154
- * }
155
- *
156
- * function App() {
157
- * return (
158
- * <GetUserFeedbackProvider clientOptions={{ apiKey: "YOUR_API_KEY" }}>
159
- * <FlowContainerDialog />
160
- * </GetUserFeedbackProvider>
161
- * );
162
- * }
139
+ * const { containerRef, shouldRenderContainer, setOpen } = useFlow({ flowId: "sur_123", container: "custom" });
163
140
  * ```
164
141
  */
165
- declare function useFlowContainer(flow: UseFlowOptions): UseFlowContainerReturn;
142
+ declare function useFlow(options: UseFlowOptions & {
143
+ container?: "default";
144
+ }): UseFlowReturn;
145
+ declare function useFlow(options: UseFlowOptions & {
146
+ container: "custom";
147
+ }): UseFlowContainerReturn;
166
148
  /**
167
149
  * @name useDefaultFlowContainer
168
150
  * @description Register and control a default flow container for all flows in this provider subtree.
@@ -212,5 +194,5 @@ declare function useGetUserFeedback(): Client;
212
194
 
213
195
  declare const REACT_SDK_VERSION: string;
214
196
 
215
- export { GetUserFeedbackProvider, REACT_SDK_VERSION, useDefaultFlowContainer, useFlow, useFlowContainer, useGetUserFeedback };
197
+ export { GetUserFeedbackProvider, REACT_SDK_VERSION, useDefaultFlowContainer, useFlow, useGetUserFeedback };
216
198
  export type { GetUserFeedbackProviderProps, UseDefaultFlowContainerReturn, UseFlowContainerReturn, UseFlowOptions, UseFlowReturn };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import{createClient as M}from"@getuserfeedback/sdk";import{createContext as Q,useCallback as _,useContext as q,useEffect as O,useMemo as h,useRef as y,useState as z}from"react";import{jsx as r}from"react/jsx-runtime";var W={isOpen:!1,isLoading:!1,shouldRenderContainer:!1,width:void 0,height:void 0},T=Q(null);function X({children:G,clientOptions:U}){let p=M(U),A=y(null),P=y(0),[R,v]=z(()=>({...p.getFlowState()})),b=_((E)=>{if(A.current=E,P.current===0)return;p.setDefaultContainerPolicy({kind:"hostContainer",host:E,sharing:"perFlowRun"})},[p]),F=_(()=>{if(P.current+=1,P.current===1)p.setDefaultContainerPolicy({kind:"hostContainer",host:A.current,sharing:"perFlowRun"});return()=>{if(P.current=Math.max(0,P.current-1),P.current===0)p.setDefaultContainerPolicy({kind:"floating"})}},[p]);O(()=>p.subscribeFlowState((E)=>{v({isOpen:E.isOpen,isLoading:E.isLoading,width:E.width,height:E.height})},{emitInitial:!0}),[p]);let K=h(()=>{if(!R.isOpen&&!R.isLoading)return W;return{isOpen:R.isOpen,isLoading:R.isLoading,shouldRenderContainer:!0,width:R.width,height:R.height}},[R]),N=h(()=>({client:p,apiKey:U.apiKey,setDefaultFlowContainer:b,registerDefaultFlowContainerConsumer:F,defaultFlowContainerState:K}),[p,U.apiKey,K,F,b]);return r(T.Provider,{value:N,children:G})}var B=(G)=>{let U=q(T);if(!U)throw Error("useFlow must be used within a GetUserFeedbackProvider");let{client:p}=U,{flowId:A,prefetchOnMount:P=!1}=G.flow,R=h(()=>p.flow(A),[p,A]),v=G.mode==="container",[b,F]=z(()=>R.getFlowState()),K=_(()=>{return R.open(v?{containerRequirement:"hostOnly"}:void 0)},[R,v]),N=_(()=>R.close(),[R]),E=_((I)=>I?K():N(),[N,K]),J=_((I)=>{if(!v)return;R.setContainer(I)},[R,v]),L=v&&(b.isLoading||b.isOpen);return O(()=>R.subscribeFlowState((I)=>F({isOpen:I.isOpen,isLoading:I.isLoading,width:I.width,height:I.height}),{emitInitial:!1}),[R]),O(()=>{if(!P)return;R.prefetch()},[R,P]),{isOpen:b.isOpen,isLoading:b.isLoading,width:b.width,height:b.height,shouldRenderContainer:L,setOpen:E,open:K,close:N,prerender:()=>R.prerender(),containerRef:J}};function Y(G){let U=B({flow:G,mode:"default"});return{isOpen:U.isOpen,isLoading:U.isLoading,width:U.width,height:U.height,open:U.open,close:U.close,prerender:U.prerender}}function Z(G){let U=B({flow:G,mode:"container"});return{isOpen:U.isOpen,isLoading:U.isLoading,width:U.width,height:U.height,shouldRenderContainer:U.shouldRenderContainer,setOpen:U.setOpen,prerender:U.prerender,containerRef:U.containerRef}}function $(){let G=q(T);if(!G)throw Error("useDefaultFlowContainer must be used within a GetUserFeedbackProvider");let{client:U,defaultFlowContainerState:p,registerDefaultFlowContainerConsumer:A,setDefaultFlowContainer:P}=G;O(()=>A(),[A]);let R=_((F)=>{P(F)},[P]),v=_(()=>U.close(),[U]),b=_((F)=>{if(F)return Promise.resolve();return v()},[v]);return{isOpen:p.isOpen,isLoading:p.isLoading,shouldRenderContainer:p.shouldRenderContainer,width:p.width,height:p.height,setOpen:b,containerRef:R}}function j(){let G=q(T);if(!G)throw Error("useGetUserFeedback must be used within a GetUserFeedbackProvider");return G.client}var H="0.1.2".trim(),D=H.length>0?H:"0.0.0-local";export{j as useGetUserFeedback,Z as useFlowContainer,Y as useFlow,$ as useDefaultFlowContainer,D as REACT_SDK_VERSION,X as GetUserFeedbackProvider};
2
+ import{createClient as L}from"@getuserfeedback/sdk";import{createContext as M,useCallback as A,useContext as y,useEffect as T,useMemo as q,useRef as z,useState as B}from"react";import{jsx as j}from"react/jsx-runtime";var Q={isOpen:!1,isLoading:!1,shouldRenderContainer:!1,width:void 0,height:void 0},h=M(null);function W({children:G,clientOptions:v}){let R=L(v),U=z(null),P=z(0),[p,E]=B(()=>({...R.getFlowState()})),b=A((_)=>{if(U.current=_,P.current===0)return;R.setDefaultContainerPolicy({kind:"hostContainer",host:_,sharing:"perFlowRun"})},[R]),I=A(()=>{if(P.current+=1,P.current===1)R.setDefaultContainerPolicy({kind:"hostContainer",host:U.current,sharing:"perFlowRun"});return()=>{if(P.current=Math.max(0,P.current-1),P.current===0)R.setDefaultContainerPolicy({kind:"floating"})}},[R]);T(()=>R.subscribeFlowState((_)=>{E({isOpen:_.isOpen,isLoading:_.isLoading,width:_.width,height:_.height})},{emitInitial:!0}),[R]);let N=q(()=>{if(!p.isOpen&&!p.isLoading)return Q;return{isOpen:p.isOpen,isLoading:p.isLoading,shouldRenderContainer:!0,width:p.width,height:p.height}},[p]),O=q(()=>({client:R,apiKey:v.apiKey,setDefaultFlowContainer:b,registerDefaultFlowContainerConsumer:I,defaultFlowContainerState:N}),[R,v.apiKey,N,I,b]);return j(h.Provider,{value:O,children:G})}var X=(G)=>{let v=y(h);if(!v)throw Error("useFlow must be used within a GetUserFeedbackProvider");let{client:R}=v,{flowId:U,prefetchOnMount:P=!1}=G.flow,p=q(()=>R.flow(U),[R,U]),E=G.mode==="container",[b,I]=B(()=>p.getFlowState()),N=A(()=>{return p.open(E?{containerRequirement:"hostOnly"}:void 0)},[p,E]),O=A(()=>p.close(),[p]),_=A((K)=>K?N():O(),[O,N]),H=A((K)=>{if(!E)return;p.setContainer(K)},[p,E]),J=E&&(b.isLoading||b.isOpen);return T(()=>p.subscribeFlowState((K)=>I({isOpen:K.isOpen,isLoading:K.isLoading,width:K.width,height:K.height}),{emitInitial:!1}),[p]),T(()=>{if(!P)return;p.prefetch()},[p,P]),{isOpen:b.isOpen,isLoading:b.isLoading,width:b.width,height:b.height,shouldRenderContainer:J,setOpen:_,open:N,close:O,prerender:()=>p.prerender(),containerRef:H}};function Y(G){let R=(G.container??"default")==="custom"?"container":"default",U=X({flow:{flowId:G.flowId,prefetchOnMount:G.prefetchOnMount},mode:R});if(R==="container")return{container:"custom",isOpen:U.isOpen,isLoading:U.isLoading,width:U.width,height:U.height,shouldRenderContainer:U.shouldRenderContainer,setOpen:U.setOpen,prerender:U.prerender,containerRef:U.containerRef};return{container:"default",isOpen:U.isOpen,isLoading:U.isLoading,width:U.width,height:U.height,open:U.open,close:U.close,prerender:U.prerender}}function Z(){let G=y(h);if(!G)throw Error("useDefaultFlowContainer must be used within a GetUserFeedbackProvider");let{client:v,defaultFlowContainerState:R,registerDefaultFlowContainerConsumer:U,setDefaultFlowContainer:P}=G;T(()=>U(),[U]);let p=A((I)=>{P(I)},[P]),E=A(()=>v.close(),[v]),b=A((I)=>{if(I)return Promise.resolve();return E()},[E]);return{isOpen:R.isOpen,isLoading:R.isLoading,shouldRenderContainer:R.shouldRenderContainer,width:R.width,height:R.height,setOpen:b,containerRef:p}}function $(){let G=y(h);if(!G)throw Error("useGetUserFeedback must be used within a GetUserFeedbackProvider");return G.client}var F="0.2.0".trim(),D=F.length>0?F:"0.0.0-local";export{$ as useGetUserFeedback,Y as useFlow,Z as useDefaultFlowContainer,D as REACT_SDK_VERSION,W as GetUserFeedbackProvider};
3
3
 
4
- //# debugId=19A31ABDDF01074064756E2164756E21
4
+ //# debugId=BB3039E864C61BE164756E2164756E21
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/client.tsx", "../src/version.ts"],
4
4
  "sourcesContent": [
5
- "\"use client\";\n\nimport {\n\ttype Client,\n\ttype ClientOptions,\n\tcreateClient,\n\ttype FlowState,\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} from \"react\";\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}\n\n/**\n * Return value for useFlow(): state and callbacks to show the default floating flow.\n */\nexport interface UseFlowReturn {\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True when the flow is loading. */\n\tisLoading: boolean;\n\t/** Open the flow. */\n\topen: () => 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\t/** Flow width in pixels (when known). */\n\twidth?: number;\n\t/** Flow height in pixels (when known). */\n\theight?: number;\n}\n\n/**\n * Return value for useFlowContainer(): state and callbacks for host-managed container flows.\n */\nexport interface UseFlowContainerReturn {\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True when the flow is loading. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the custom container element. */\n\tshouldRenderContainer: boolean;\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\t/** Flow width in pixels (when known). */\n\twidth?: number;\n\t/** Flow height in pixels (when known). */\n\theight?: number;\n}\n\n/**\n * Return value for useDefaultFlowContainer(): container ref and aggregate flow state\n * for all flows in the same provider subtree (including targeting-engine opens).\n */\nexport interface UseDefaultFlowContainerReturn {\n\t/** True when any flow is visible. */\n\tisOpen: boolean;\n\t/** True when any flow is loading. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the default flow container. */\n\tshouldRenderContainer: boolean;\n\t/** Active flow width in pixels (when known). */\n\twidth?: number;\n\t/** Active flow height in pixels (when known). */\n\theight?: number;\n\t/** Close currently displayed flows when `false`; opening is flow-driven. */\n\tsetOpen: (next: boolean) => Promise<void>;\n\t/** Ref callback for the default flow container element. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\ntype InstanceFlowRenderState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\twidth?: number;\n\theight?: number;\n};\n\ntype DefaultFlowContainerState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n\twidth?: number;\n\theight?: number;\n};\n\nconst DEFAULT_FLOW_CONTAINER_STATE: DefaultFlowContainerState = {\n\tisOpen: false,\n\tisLoading: false,\n\tshouldRenderContainer: false,\n\twidth: undefined,\n\theight: undefined,\n};\n\ntype GetUserFeedbackContextValue = {\n\tclient: Client;\n\tapiKey: string;\n\tsetDefaultFlowContainer: (element: HTMLElement | null) => void;\n\tregisterDefaultFlowContainerConsumer: () => () => void;\n\tdefaultFlowContainerState: DefaultFlowContainerState;\n};\n\nconst GetUserFeedbackContext =\n\tcreateContext<GetUserFeedbackContextValue | null>(null);\n\nexport interface GetUserFeedbackProviderProps {\n\t/** Application subtree that can use getuserfeedback hooks. */\n\tchildren: ReactNode;\n\t/** Core SDK client options used to create/reuse the underlying client. */\n\tclientOptions: ClientOptions;\n}\n\n/**\n * Provider for getuserfeedback React hooks.\n * Wrap your app (or a subtree) so `useFlow`, `useFlowContainer`,\n * `useDefaultFlowContainer`, and `useGetUserFeedback` can access a client\n * created from `clientOptions`.\n *\n * If your app uses `useDefaultFlowContainer()`, all flows in this subtree\n * (including targeting-engine opens) target that container.\n * If the container ref is not mounted yet, loader keeps flows parked until it is.\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 DefaultFlowContainer() {\n * const { containerRef, shouldRenderContainer, width, height, setOpen } = useDefaultFlowContainer();\n *\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>\n * <DialogContent ref={containerRef} style={{ width, height }} />\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <DefaultFlowContainer /> // Flows will be triggered by the targeting engine and displayed in your own dialog\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function GetUserFeedbackProvider({\n\tchildren,\n\tclientOptions,\n}: GetUserFeedbackProviderProps): ReactElement {\n\tconst client = createClient(clientOptions);\n\tconst defaultFlowContainerRef = useRef<HTMLElement | null>(null);\n\tconst defaultFlowContainerConsumerCountRef = useRef(0);\n\tconst [instanceFlowState, setInstanceFlowState] =\n\t\tuseState<InstanceFlowRenderState>(() => ({\n\t\t\t...client.getFlowState(),\n\t\t}));\n\n\tconst setDefaultFlowContainer = useCallback(\n\t\t(element: HTMLElement | null) => {\n\t\t\tdefaultFlowContainerRef.current = element;\n\t\t\tif (defaultFlowContainerConsumerCountRef.current === 0) {\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\tdefaultFlowContainerConsumerCountRef.current += 1;\n\t\tif (defaultFlowContainerConsumerCountRef.current === 1) {\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: defaultFlowContainerRef.current,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\t\t}\n\t\treturn () => {\n\t\t\tdefaultFlowContainerConsumerCountRef.current = Math.max(\n\t\t\t\t0,\n\t\t\t\tdefaultFlowContainerConsumerCountRef.current - 1,\n\t\t\t);\n\t\t\tif (defaultFlowContainerConsumerCountRef.current === 0) {\n\t\t\t\tclient.setDefaultContainerPolicy({ kind: \"floating\" });\n\t\t\t}\n\t\t};\n\t}, [client]);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tclient.subscribeFlowState(\n\t\t\t\t(state) => {\n\t\t\t\t\tsetInstanceFlowState({\n\t\t\t\t\t\tisOpen: state.isOpen,\n\t\t\t\t\t\tisLoading: state.isLoading,\n\t\t\t\t\t\twidth: state.width,\n\t\t\t\t\t\theight: state.height,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\temitInitial: true,\n\t\t\t\t},\n\t\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\twidth: instanceFlowState.width,\n\t\t\theight: instanceFlowState.height,\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 UseFlowControllerOptions = {\n\tflow: UseFlowOptions;\n\tmode: \"default\" | \"container\";\n};\n\ntype UseFlowControllerReturn = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\twidth?: number;\n\theight?: number;\n\tshouldRenderContainer: boolean;\n\tsetOpen: (next: boolean) => Promise<void>;\n\topen: () => Promise<void>;\n\tclose: () => Promise<void>;\n\tprerender: () => Promise<void>;\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n};\n\nconst useFlowController = (\n\toptions: UseFlowControllerOptions,\n): UseFlowControllerReturn => {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useFlow must be used within a GetUserFeedbackProvider\");\n\t}\n\tconst { client } = ctx;\n\tconst { flowId, prefetchOnMount = false } = options.flow;\n\tconst flowRun = useMemo(() => client.flow(flowId), [client, flowId]);\n\tconst requiresContainer = options.mode === \"container\";\n\n\t/** Flow state from loader events; open/loading + dimensions. */\n\tconst [flowState, setFlowState] = useState<FlowState>(() =>\n\t\tflowRun.getFlowState(),\n\t);\n\n\tconst open = useCallback((): Promise<void> => {\n\t\treturn flowRun.open(\n\t\t\trequiresContainer ? { containerRequirement: \"hostOnly\" } : undefined,\n\t\t);\n\t}, [flowRun, requiresContainer]);\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\tflowRun.setContainer(element);\n\t\t},\n\t\t[flowRun, requiresContainer],\n\t);\n\n\tconst shouldRenderContainer =\n\t\trequiresContainer && (flowState.isLoading || flowState.isOpen);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tflowRun.subscribeFlowState(\n\t\t\t\t(state) =>\n\t\t\t\t\tsetFlowState({\n\t\t\t\t\t\tisOpen: state.isOpen,\n\t\t\t\t\t\tisLoading: state.isLoading,\n\t\t\t\t\t\twidth: state.width,\n\t\t\t\t\t\theight: state.height,\n\t\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\temitInitial: false,\n\t\t\t\t},\n\t\t\t),\n\t\t[flowRun],\n\t);\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\twidth: flowState.width,\n\t\theight: flowState.height,\n\t\tshouldRenderContainer,\n\t\tsetOpen,\n\t\topen,\n\t\tclose,\n\t\tprerender: () => flowRun.prerender(),\n\t\tcontainerRef,\n\t};\n};\n\n/**\n * @name useFlow\n * @description Imperatively display a flow.\n * @example Basic usage\n * ```tsx\n * function FeedbackButton() {\n * const { open, isLoading } = useFlow({ flowId: \"sur_123\" });\n * return <Button onClick={() => open()} disabled={isLoading}>Feedback</Button>;\n * }\n * ```\n */\nexport function useFlow(flow: UseFlowOptions): UseFlowReturn {\n\tconst controller = useFlowController({ flow, mode: \"default\" });\n\treturn {\n\t\tisOpen: controller.isOpen,\n\t\tisLoading: controller.isLoading,\n\t\twidth: controller.width,\n\t\theight: controller.height,\n\t\topen: controller.open,\n\t\tclose: controller.close,\n\t\tprerender: controller.prerender,\n\t};\n}\n\n/**\n * @name useFlowContainer\n * @description Imperatively display a flow in your own container element.\n * @example In a custom dialog\n * ```tsx\n * function FlowContainerDialog() {\n * const { containerRef, shouldRenderContainer, width, height, setOpen, isLoading } =\n * useFlowContainer({ flowId: \"sur_123\" });\n *\n * return (\n * <>\n * <Button onClick={() => setOpen(true)} loading={isLoading}>\n * Feedback\n * </Button>\n * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>\n * <DialogContent ref={containerRef} style={{ width, height }} />\n * </Dialog>\n * </>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <FlowContainerDialog />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function useFlowContainer(flow: UseFlowOptions): UseFlowContainerReturn {\n\tconst controller = useFlowController({ flow, mode: \"container\" });\n\treturn {\n\t\tisOpen: controller.isOpen,\n\t\tisLoading: controller.isLoading,\n\t\twidth: controller.width,\n\t\theight: controller.height,\n\t\tshouldRenderContainer: controller.shouldRenderContainer,\n\t\tsetOpen: controller.setOpen,\n\t\tprerender: controller.prerender,\n\t\tcontainerRef: controller.containerRef,\n\t};\n}\n\n/**\n * @name useDefaultFlowContainer\n * @description Register and control a default flow container for all flows in this provider subtree.\n * @example Display any flow in your own dialog\n * ```tsx\n * function DefaultFlowContainer() {\n * const { containerRef, shouldRenderContainer, width, height, setOpen } = useDefaultFlowContainer();\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>\n * <DialogContent ref={containerRef} style={{ width, height }} />\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <DefaultFlowContainer />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function useDefaultFlowContainer(): UseDefaultFlowContainerReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useDefaultFlowContainer 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\n\tuseEffect(\n\t\t() => registerDefaultFlowContainerConsumer(),\n\t\t[registerDefaultFlowContainerConsumer],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tsetDefaultFlowContainer(element);\n\t\t},\n\t\t[setDefaultFlowContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => client.close(), [client]);\n\n\tconst setOpen = useCallback(\n\t\t(next: boolean): Promise<void> => {\n\t\t\tif (next) {\n\t\t\t\treturn Promise.resolve();\n\t\t\t}\n\t\t\treturn close();\n\t\t},\n\t\t[close],\n\t);\n\n\treturn {\n\t\tisOpen: defaultFlowContainerState.isOpen,\n\t\tisLoading: defaultFlowContainerState.isLoading,\n\t\tshouldRenderContainer: defaultFlowContainerState.shouldRenderContainer,\n\t\twidth: defaultFlowContainerState.width,\n\t\theight: defaultFlowContainerState.height,\n\t\tsetOpen,\n\t\tcontainerRef,\n\t};\n}\n\n/**\n * Hook for accessing the getuserfeedback client instance.\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 * // 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",
5
+ "\"use client\";\n\nimport {\n\ttype Client,\n\ttype ClientOptions,\n\tcreateClient,\n\ttype FlowState,\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} from \"react\";\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\"`.\n\t */\n\tcontainer?: \"default\" | \"custom\";\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 when the flow is loading. */\n\tisLoading: boolean;\n\t/** Open the flow. */\n\topen: () => 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\t/** Flow width in pixels (when known). */\n\twidth?: number;\n\t/** Flow height in pixels (when known). */\n\theight?: number;\n}\n\n/**\n * Return value for useFlow() when container is `\"custom\"`: state and callbacks for host-managed container flows.\n */\nexport interface UseFlowContainerReturn {\n\treadonly container: \"custom\";\n\t/** True when the flow is visible. */\n\tisOpen: boolean;\n\t/** True when the flow is loading. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the custom container element. */\n\tshouldRenderContainer: boolean;\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\t/** Flow width in pixels (when known). */\n\twidth?: number;\n\t/** Flow height in pixels (when known). */\n\theight?: number;\n}\n\n/**\n * Return value for useDefaultFlowContainer(): container ref and aggregate flow state\n * for all flows in the same provider subtree (including targeting-engine opens).\n */\nexport interface UseDefaultFlowContainerReturn {\n\t/** True when any flow is visible. */\n\tisOpen: boolean;\n\t/** True when any flow is loading. */\n\tisLoading: boolean;\n\t/** True when your host UI should render the default flow container. */\n\tshouldRenderContainer: boolean;\n\t/** Active flow width in pixels (when known). */\n\twidth?: number;\n\t/** Active flow height in pixels (when known). */\n\theight?: number;\n\t/** Close currently displayed flows when `false`; opening is flow-driven. */\n\tsetOpen: (next: boolean) => Promise<void>;\n\t/** Ref callback for the default flow container element. */\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n}\n\ntype InstanceFlowRenderState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\twidth?: number;\n\theight?: number;\n};\n\ntype DefaultFlowContainerState = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\tshouldRenderContainer: boolean;\n\twidth?: number;\n\theight?: number;\n};\n\nconst DEFAULT_FLOW_CONTAINER_STATE: DefaultFlowContainerState = {\n\tisOpen: false,\n\tisLoading: false,\n\tshouldRenderContainer: false,\n\twidth: undefined,\n\theight: undefined,\n};\n\ntype GetUserFeedbackContextValue = {\n\tclient: Client;\n\tapiKey: string;\n\tsetDefaultFlowContainer: (element: HTMLElement | null) => void;\n\tregisterDefaultFlowContainerConsumer: () => () => void;\n\tdefaultFlowContainerState: DefaultFlowContainerState;\n};\n\nconst GetUserFeedbackContext =\n\tcreateContext<GetUserFeedbackContextValue | null>(null);\n\nexport interface GetUserFeedbackProviderProps {\n\t/** Application subtree that can use getuserfeedback hooks. */\n\tchildren: ReactNode;\n\t/** Core SDK client options used to create/reuse the underlying client. */\n\tclientOptions: ClientOptions;\n}\n\n/**\n * Provider for getuserfeedback React hooks.\n * Wrap your app (or a subtree) so `useFlow`, `useDefaultFlowContainer`, and\n * `useGetUserFeedback` can access a client\n * created from `clientOptions`.\n *\n * If your app uses `useDefaultFlowContainer()`, all flows in this subtree\n * (including targeting-engine opens) target that container.\n * If the container ref is not mounted yet, loader keeps flows parked until it is.\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 DefaultFlowContainer() {\n * const { containerRef, shouldRenderContainer, width, height, setOpen } = useDefaultFlowContainer();\n *\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>\n * <DialogContent ref={containerRef} style={{ width, height }} />\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <DefaultFlowContainer /> // Flows will be triggered by the targeting engine and displayed in your own dialog\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function GetUserFeedbackProvider({\n\tchildren,\n\tclientOptions,\n}: GetUserFeedbackProviderProps): ReactElement {\n\tconst client = createClient(clientOptions);\n\tconst defaultFlowContainerRef = useRef<HTMLElement | null>(null);\n\tconst defaultFlowContainerConsumerCountRef = useRef(0);\n\tconst [instanceFlowState, setInstanceFlowState] =\n\t\tuseState<InstanceFlowRenderState>(() => ({\n\t\t\t...client.getFlowState(),\n\t\t}));\n\n\tconst setDefaultFlowContainer = useCallback(\n\t\t(element: HTMLElement | null) => {\n\t\t\tdefaultFlowContainerRef.current = element;\n\t\t\tif (defaultFlowContainerConsumerCountRef.current === 0) {\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\tdefaultFlowContainerConsumerCountRef.current += 1;\n\t\tif (defaultFlowContainerConsumerCountRef.current === 1) {\n\t\t\tclient.setDefaultContainerPolicy({\n\t\t\t\tkind: \"hostContainer\",\n\t\t\t\thost: defaultFlowContainerRef.current,\n\t\t\t\tsharing: \"perFlowRun\",\n\t\t\t});\n\t\t}\n\t\treturn () => {\n\t\t\tdefaultFlowContainerConsumerCountRef.current = Math.max(\n\t\t\t\t0,\n\t\t\t\tdefaultFlowContainerConsumerCountRef.current - 1,\n\t\t\t);\n\t\t\tif (defaultFlowContainerConsumerCountRef.current === 0) {\n\t\t\t\tclient.setDefaultContainerPolicy({ kind: \"floating\" });\n\t\t\t}\n\t\t};\n\t}, [client]);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tclient.subscribeFlowState(\n\t\t\t\t(state) => {\n\t\t\t\t\tsetInstanceFlowState({\n\t\t\t\t\t\tisOpen: state.isOpen,\n\t\t\t\t\t\tisLoading: state.isLoading,\n\t\t\t\t\t\twidth: state.width,\n\t\t\t\t\t\theight: state.height,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\temitInitial: true,\n\t\t\t\t},\n\t\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\twidth: instanceFlowState.width,\n\t\t\theight: instanceFlowState.height,\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 UseFlowControllerOptions = {\n\tflow: UseFlowOptions;\n\tmode: \"default\" | \"container\";\n};\n\ntype UseFlowControllerReturn = {\n\tisOpen: boolean;\n\tisLoading: boolean;\n\twidth?: number;\n\theight?: number;\n\tshouldRenderContainer: boolean;\n\tsetOpen: (next: boolean) => Promise<void>;\n\topen: () => Promise<void>;\n\tclose: () => Promise<void>;\n\tprerender: () => Promise<void>;\n\tcontainerRef: (element: HTMLDivElement | null) => void;\n};\n\nconst useFlowController = (\n\toptions: UseFlowControllerOptions,\n): UseFlowControllerReturn => {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useFlow must be used within a GetUserFeedbackProvider\");\n\t}\n\tconst { client } = ctx;\n\tconst { flowId, prefetchOnMount = false } = options.flow;\n\tconst flowRun = useMemo(() => client.flow(flowId), [client, flowId]);\n\tconst requiresContainer = options.mode === \"container\";\n\n\t/** Flow state from loader events; open/loading + dimensions. */\n\tconst [flowState, setFlowState] = useState<FlowState>(() =>\n\t\tflowRun.getFlowState(),\n\t);\n\n\tconst open = useCallback((): Promise<void> => {\n\t\treturn flowRun.open(\n\t\t\trequiresContainer ? { containerRequirement: \"hostOnly\" } : undefined,\n\t\t);\n\t}, [flowRun, requiresContainer]);\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\tflowRun.setContainer(element);\n\t\t},\n\t\t[flowRun, requiresContainer],\n\t);\n\n\tconst shouldRenderContainer =\n\t\trequiresContainer && (flowState.isLoading || flowState.isOpen);\n\n\tuseEffect(\n\t\t() =>\n\t\t\tflowRun.subscribeFlowState(\n\t\t\t\t(state) =>\n\t\t\t\t\tsetFlowState({\n\t\t\t\t\t\tisOpen: state.isOpen,\n\t\t\t\t\t\tisLoading: state.isLoading,\n\t\t\t\t\t\twidth: state.width,\n\t\t\t\t\t\theight: state.height,\n\t\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\temitInitial: false,\n\t\t\t\t},\n\t\t\t),\n\t\t[flowRun],\n\t);\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\twidth: flowState.width,\n\t\theight: flowState.height,\n\t\tshouldRenderContainer,\n\t\tsetOpen,\n\t\topen,\n\t\tclose,\n\t\tprerender: () => flowRun.prerender(),\n\t\tcontainerRef,\n\t};\n};\n\n/**\n * @name useFlow\n * @description Imperatively display a flow 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 * ```\n * @example Custom container\n * ```tsx\n * const { containerRef, shouldRenderContainer, setOpen } = useFlow({ flowId: \"sur_123\", container: \"custom\" });\n * ```\n */\nexport function useFlow(\n\toptions: UseFlowOptions & { container?: \"default\" },\n): UseFlowReturn;\nexport function useFlow(\n\toptions: UseFlowOptions & { container: \"custom\" },\n): UseFlowContainerReturn;\nexport function useFlow(\n\toptions: UseFlowOptions,\n): UseFlowReturn | UseFlowContainerReturn {\n\tconst container = options.container ?? \"default\";\n\tconst mode = container === \"custom\" ? \"container\" : \"default\";\n\tconst controller = useFlowController({\n\t\tflow: { flowId: options.flowId, prefetchOnMount: options.prefetchOnMount },\n\t\tmode,\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\twidth: controller.width,\n\t\t\theight: controller.height,\n\t\t\tshouldRenderContainer: controller.shouldRenderContainer,\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\twidth: controller.width,\n\t\theight: controller.height,\n\t\topen: controller.open,\n\t\tclose: controller.close,\n\t\tprerender: controller.prerender,\n\t};\n}\n\n/**\n * @name useDefaultFlowContainer\n * @description Register and control a default flow container for all flows in this provider subtree.\n * @example Display any flow in your own dialog\n * ```tsx\n * function DefaultFlowContainer() {\n * const { containerRef, shouldRenderContainer, width, height, setOpen } = useDefaultFlowContainer();\n * return (\n * <Dialog open={shouldRenderContainer} onOpenChange={setOpen}>\n * <DialogContent ref={containerRef} style={{ width, height }} />\n * </Dialog>\n * );\n * }\n *\n * function App() {\n * return (\n * <GetUserFeedbackProvider clientOptions={{ apiKey: \"YOUR_API_KEY\" }}>\n * <AppRoutes />\n * <DefaultFlowContainer />\n * </GetUserFeedbackProvider>\n * );\n * }\n * ```\n */\nexport function useDefaultFlowContainer(): UseDefaultFlowContainerReturn {\n\tconst ctx = useContext(GetUserFeedbackContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useDefaultFlowContainer 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\n\tuseEffect(\n\t\t() => registerDefaultFlowContainerConsumer(),\n\t\t[registerDefaultFlowContainerConsumer],\n\t);\n\n\tconst containerRef = useCallback(\n\t\t(element: HTMLDivElement | null): void => {\n\t\t\tsetDefaultFlowContainer(element);\n\t\t},\n\t\t[setDefaultFlowContainer],\n\t);\n\n\tconst close = useCallback((): Promise<void> => client.close(), [client]);\n\n\tconst setOpen = useCallback(\n\t\t(next: boolean): Promise<void> => {\n\t\t\tif (next) {\n\t\t\t\treturn Promise.resolve();\n\t\t\t}\n\t\t\treturn close();\n\t\t},\n\t\t[close],\n\t);\n\n\treturn {\n\t\tisOpen: defaultFlowContainerState.isOpen,\n\t\tisLoading: defaultFlowContainerState.isLoading,\n\t\tshouldRenderContainer: defaultFlowContainerState.shouldRenderContainer,\n\t\twidth: defaultFlowContainerState.width,\n\t\theight: defaultFlowContainerState.height,\n\t\tsetOpen,\n\t\tcontainerRef,\n\t};\n}\n\n/**\n * Hook for accessing the getuserfeedback client instance.\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 * // 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
6
  "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"
7
7
  ],
8
- "mappings": ";AAEA,uBAGC,6BAID,wBACC,iBACA,gBACA,eACA,aACA,YACA,cACA,sDA2FD,IAAM,EAA0D,CAC/D,OAAQ,GACR,UAAW,GACX,sBAAuB,GACvB,MAAO,OACP,OAAQ,MACT,EAUM,EACL,EAAkD,IAAI,EAoDhD,SAAS,CAAuB,EACtC,WACA,iBAC8C,CAC9C,IAAM,EAAS,EAAa,CAAa,EACnC,EAA0B,EAA2B,IAAI,EACzD,EAAuC,EAAO,CAAC,GAC9C,EAAmB,GACzB,EAAkC,KAAO,IACrC,EAAO,aAAa,CACxB,EAAE,EAEG,EAA0B,EAC/B,CAAC,IAAgC,CAEhC,GADA,EAAwB,QAAU,EAC9B,EAAqC,UAAY,EACpD,OAED,EAAO,0BAA0B,CAChC,KAAM,gBACN,KAAM,EACN,QAAS,YACV,CAAC,GAEF,CAAC,CAAM,CACR,EAEM,EAAuC,EAAY,IAAM,CAE9D,GADA,EAAqC,SAAW,EAC5C,EAAqC,UAAY,EACpD,EAAO,0BAA0B,CAChC,KAAM,gBACN,KAAM,EAAwB,QAC9B,QAAS,YACV,CAAC,EAEF,MAAO,IAAM,CAKZ,GAJA,EAAqC,QAAU,KAAK,IACnD,EACA,EAAqC,QAAU,CAChD,EACI,EAAqC,UAAY,EACpD,EAAO,0BAA0B,CAAE,KAAM,UAAW,CAAC,IAGrD,CAAC,CAAM,CAAC,EAEX,EACC,IACC,EAAO,mBACN,CAAC,IAAU,CACV,EAAqB,CACpB,OAAQ,EAAM,OACd,UAAW,EAAM,UACjB,MAAO,EAAM,MACb,OAAQ,EAAM,MACf,CAAC,GAEF,CACC,YAAa,EACd,CACD,EACD,CAAC,CAAM,CACR,EAEA,IAAM,EAA4B,EAAmC,IAAM,CAC1E,GAAI,CAAC,EAAkB,QAAU,CAAC,EAAkB,UACnD,OAAO,EAER,MAAO,CACN,OAAQ,EAAkB,OAC1B,UAAW,EAAkB,UAC7B,sBAAuB,GACvB,MAAO,EAAkB,MACzB,OAAQ,EAAkB,MAC3B,GACE,CAAC,CAAiB,CAAC,EAEhB,EAAe,EACpB,KAAO,CACN,SACA,OAAQ,EAAc,OACtB,0BACA,uCACA,2BACD,GACA,CACC,EACA,EAAc,OACd,EACA,EACA,CACD,CACD,EAEA,OACC,EAEE,EAAuB,SAFzB,CAAiC,MAAO,EAAxC,SACE,EACA,EAsBJ,IAAM,EAAoB,CACzB,IAC6B,CAC7B,IAAM,EAAM,EAAW,CAAsB,EAC7C,GAAI,CAAC,EACJ,MAAU,MAAM,uDAAuD,EAExE,IAAQ,UAAW,GACX,SAAQ,kBAAkB,IAAU,EAAQ,KAC9C,EAAU,EAAQ,IAAM,EAAO,KAAK,CAAM,EAAG,CAAC,EAAQ,CAAM,CAAC,EAC7D,EAAoB,EAAQ,OAAS,aAGpC,EAAW,GAAgB,EAAoB,IACrD,EAAQ,aAAa,CACtB,EAEM,EAAO,EAAY,IAAqB,CAC7C,OAAO,EAAQ,KACd,EAAoB,CAAE,qBAAsB,UAAW,EAAI,MAC5D,GACE,CAAC,EAAS,CAAiB,CAAC,EAEzB,EAAQ,EAAY,IAAqB,EAAQ,MAAM,EAAG,CAAC,CAAO,CAAC,EAEnE,EAAU,EACf,CAAC,IAAkC,EAAO,EAAK,EAAI,EAAM,EACzD,CAAC,EAAO,CAAI,CACb,EAEM,EAAe,EACpB,CAAC,IAAyC,CACzC,GAAI,CAAC,EACJ,OAED,EAAQ,aAAa,CAAO,GAE7B,CAAC,EAAS,CAAiB,CAC5B,EAEM,EACL,IAAsB,EAAU,WAAa,EAAU,QA0BxD,OAxBA,EACC,IACC,EAAQ,mBACP,CAAC,IACA,EAAa,CACZ,OAAQ,EAAM,OACd,UAAW,EAAM,UACjB,MAAO,EAAM,MACb,OAAQ,EAAM,MACf,CAAC,EACF,CACC,YAAa,EACd,CACD,EACD,CAAC,CAAO,CACT,EAEA,EAAU,IAAM,CACf,GAAI,CAAC,EACJ,OAED,EAAQ,SAAS,GACf,CAAC,EAAS,CAAe,CAAC,EAEtB,CACN,OAAQ,EAAU,OAClB,UAAW,EAAU,UACrB,MAAO,EAAU,MACjB,OAAQ,EAAU,OAClB,wBACA,UACA,OACA,QACA,UAAW,IAAM,EAAQ,UAAU,EACnC,cACD,GAcM,SAAS,CAAO,CAAC,EAAqC,CAC5D,IAAM,EAAa,EAAkB,CAAE,OAAM,KAAM,SAAU,CAAC,EAC9D,MAAO,CACN,OAAQ,EAAW,OACnB,UAAW,EAAW,UACtB,MAAO,EAAW,MAClB,OAAQ,EAAW,OACnB,KAAM,EAAW,KACjB,MAAO,EAAW,MAClB,UAAW,EAAW,SACvB,EAiCM,SAAS,CAAgB,CAAC,EAA8C,CAC9E,IAAM,EAAa,EAAkB,CAAE,OAAM,KAAM,WAAY,CAAC,EAChE,MAAO,CACN,OAAQ,EAAW,OACnB,UAAW,EAAW,UACtB,MAAO,EAAW,MAClB,OAAQ,EAAW,OACnB,sBAAuB,EAAW,sBAClC,QAAS,EAAW,QACpB,UAAW,EAAW,UACtB,aAAc,EAAW,YAC1B,EA2BM,SAAS,CAAuB,EAAkC,CACxE,IAAM,EAAM,EAAW,CAAsB,EAC7C,GAAI,CAAC,EACJ,MAAU,MACT,uEACD,EAGD,IACC,SACA,4BACA,uCACA,2BACG,EAEJ,EACC,IAAM,EAAqC,EAC3C,CAAC,CAAoC,CACtC,EAEA,IAAM,EAAe,EACpB,CAAC,IAAyC,CACzC,EAAwB,CAAO,GAEhC,CAAC,CAAuB,CACzB,EAEM,EAAQ,EAAY,IAAqB,EAAO,MAAM,EAAG,CAAC,CAAM,CAAC,EAEjE,EAAU,EACf,CAAC,IAAiC,CACjC,GAAI,EACH,OAAO,QAAQ,QAAQ,EAExB,OAAO,EAAM,GAEd,CAAC,CAAK,CACP,EAEA,MAAO,CACN,OAAQ,EAA0B,OAClC,UAAW,EAA0B,UACrC,sBAAuB,EAA0B,sBACjD,MAAO,EAA0B,MACjC,OAAQ,EAA0B,OAClC,UACA,cACD,EAuBM,SAAS,CAAkB,EAAW,CAC5C,IAAM,EAAM,EAAW,CAAsB,EAC7C,GAAI,CAAC,EACJ,MAAU,MACT,kEACD,EAED,OAAO,EAAI,OChiBZ,IAAM,EAEF,QAAyB,KAAK,EAKrB,EACZ,EAAgB,OAAS,EAAI,EAAkB",
9
- "debugId": "19A31ABDDF01074064756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "BB3039E864C61BE164756E2164756E21",
10
10
  "names": []
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getuserfeedback/react",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "getuserfeedback React SDK",
5
5
  "keywords": [
6
6
  "getuserfeedback",