@perspective-ai/sdk-react 1.0.0-alpha.2 → 1.0.0-alpha.3
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 +139 -166
- package/dist/index.cjs +317 -270
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -54
- package/dist/index.d.ts +121 -54
- package/dist/index.js +317 -271
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/src/FloatBubble.test.tsx +0 -39
- package/src/FloatBubble.tsx +22 -48
- package/src/hooks/useFloatBubble.test.ts +91 -0
- package/src/hooks/useFloatBubble.ts +180 -0
- package/src/hooks/usePopup.test.ts +219 -0
- package/src/hooks/usePopup.ts +190 -0
- package/src/hooks/useSlider.test.ts +150 -0
- package/src/hooks/useSlider.ts +181 -0
- package/src/index.ts +26 -29
- package/src/PopupButton.test.tsx +0 -273
- package/src/PopupButton.tsx +0 -208
- package/src/SliderButton.test.tsx +0 -279
- package/src/SliderButton.tsx +0 -208
package/dist/index.cjs
CHANGED
|
@@ -15,33 +15,52 @@ function useStableCallback(callback) {
|
|
|
15
15
|
[]
|
|
16
16
|
);
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
|
|
19
|
+
// src/hooks/usePopup.ts
|
|
20
|
+
function usePopup(options) {
|
|
21
|
+
const {
|
|
22
|
+
researchId,
|
|
23
|
+
params,
|
|
24
|
+
brand,
|
|
25
|
+
theme,
|
|
26
|
+
host,
|
|
27
|
+
onReady,
|
|
28
|
+
onSubmit,
|
|
29
|
+
onNavigate,
|
|
30
|
+
onClose,
|
|
31
|
+
onError,
|
|
32
|
+
open: controlledOpen,
|
|
33
|
+
onOpenChange
|
|
34
|
+
} = options;
|
|
35
|
+
const [handle, setHandle] = react.useState(null);
|
|
36
|
+
const [internalOpen, setInternalOpen] = react.useState(false);
|
|
35
37
|
const handleRef = react.useRef(null);
|
|
38
|
+
const isControlled = controlledOpen !== void 0;
|
|
39
|
+
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
36
40
|
const stableOnReady = useStableCallback(onReady);
|
|
37
41
|
const stableOnSubmit = useStableCallback(onSubmit);
|
|
38
42
|
const stableOnNavigate = useStableCallback(onNavigate);
|
|
39
|
-
const stableOnClose = useStableCallback(onClose);
|
|
40
43
|
const stableOnError = useStableCallback(onError);
|
|
41
|
-
react.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const setOpen = react.useCallback(
|
|
45
|
+
(value) => {
|
|
46
|
+
if (isControlled) {
|
|
47
|
+
onOpenChange?.(value);
|
|
48
|
+
} else {
|
|
49
|
+
setInternalOpen(value);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
[isControlled, onOpenChange]
|
|
53
|
+
);
|
|
54
|
+
const handleClose = react.useCallback(() => {
|
|
55
|
+
handleRef.current = null;
|
|
56
|
+
setHandle(null);
|
|
57
|
+
setOpen(false);
|
|
58
|
+
onClose?.();
|
|
59
|
+
}, [setOpen, onClose]);
|
|
60
|
+
const stableOnClose = useStableCallback(handleClose);
|
|
61
|
+
const createPopup = react.useCallback(() => {
|
|
62
|
+
if (handleRef.current) return handleRef.current;
|
|
63
|
+
const newHandle = sdk.openPopup({
|
|
45
64
|
researchId,
|
|
46
65
|
params,
|
|
47
66
|
brand,
|
|
@@ -53,17 +72,9 @@ function Widget({
|
|
|
53
72
|
onClose: stableOnClose,
|
|
54
73
|
onError: stableOnError
|
|
55
74
|
});
|
|
56
|
-
handleRef.current =
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
return () => {
|
|
61
|
-
handle.unmount();
|
|
62
|
-
handleRef.current = null;
|
|
63
|
-
if (embedRef) {
|
|
64
|
-
embedRef.current = null;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
75
|
+
handleRef.current = newHandle;
|
|
76
|
+
setHandle(newHandle);
|
|
77
|
+
return newHandle;
|
|
67
78
|
}, [
|
|
68
79
|
researchId,
|
|
69
80
|
params,
|
|
@@ -74,42 +85,82 @@ function Widget({
|
|
|
74
85
|
stableOnSubmit,
|
|
75
86
|
stableOnNavigate,
|
|
76
87
|
stableOnClose,
|
|
77
|
-
stableOnError
|
|
78
|
-
embedRef
|
|
88
|
+
stableOnError
|
|
79
89
|
]);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
style: { minHeight: 500, ...style },
|
|
86
|
-
"data-testid": "perspective-widget",
|
|
87
|
-
...divProps
|
|
90
|
+
const destroyPopup = react.useCallback(() => {
|
|
91
|
+
if (handleRef.current) {
|
|
92
|
+
handleRef.current.destroy();
|
|
93
|
+
handleRef.current = null;
|
|
94
|
+
setHandle(null);
|
|
88
95
|
}
|
|
89
|
-
);
|
|
96
|
+
}, []);
|
|
97
|
+
const openFn = react.useCallback(() => {
|
|
98
|
+
if (isControlled) {
|
|
99
|
+
onOpenChange?.(true);
|
|
100
|
+
} else {
|
|
101
|
+
createPopup();
|
|
102
|
+
setInternalOpen(true);
|
|
103
|
+
}
|
|
104
|
+
}, [isControlled, onOpenChange, createPopup]);
|
|
105
|
+
const closeFn = react.useCallback(() => {
|
|
106
|
+
if (isControlled) {
|
|
107
|
+
onOpenChange?.(false);
|
|
108
|
+
} else {
|
|
109
|
+
destroyPopup();
|
|
110
|
+
setInternalOpen(false);
|
|
111
|
+
}
|
|
112
|
+
}, [isControlled, onOpenChange, destroyPopup]);
|
|
113
|
+
const toggleFn = react.useCallback(() => {
|
|
114
|
+
if (isOpen) {
|
|
115
|
+
closeFn();
|
|
116
|
+
} else {
|
|
117
|
+
openFn();
|
|
118
|
+
}
|
|
119
|
+
}, [isOpen, openFn, closeFn]);
|
|
120
|
+
react.useEffect(() => {
|
|
121
|
+
if (!isControlled) return;
|
|
122
|
+
if (controlledOpen && !handleRef.current) {
|
|
123
|
+
createPopup();
|
|
124
|
+
} else if (!controlledOpen && handleRef.current) {
|
|
125
|
+
destroyPopup();
|
|
126
|
+
}
|
|
127
|
+
}, [controlledOpen, isControlled, createPopup, destroyPopup]);
|
|
128
|
+
react.useEffect(() => {
|
|
129
|
+
return () => {
|
|
130
|
+
if (handleRef.current) {
|
|
131
|
+
handleRef.current.destroy();
|
|
132
|
+
handleRef.current = null;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}, []);
|
|
136
|
+
return {
|
|
137
|
+
open: openFn,
|
|
138
|
+
close: closeFn,
|
|
139
|
+
toggle: toggleFn,
|
|
140
|
+
isOpen,
|
|
141
|
+
handle
|
|
142
|
+
};
|
|
90
143
|
}
|
|
91
|
-
function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
...buttonProps
|
|
108
|
-
}) {
|
|
109
|
-
const handleRef = react.useRef(null);
|
|
144
|
+
function useSlider(options) {
|
|
145
|
+
const {
|
|
146
|
+
researchId,
|
|
147
|
+
params,
|
|
148
|
+
brand,
|
|
149
|
+
theme,
|
|
150
|
+
host,
|
|
151
|
+
onReady,
|
|
152
|
+
onSubmit,
|
|
153
|
+
onNavigate,
|
|
154
|
+
onClose,
|
|
155
|
+
onError,
|
|
156
|
+
open: controlledOpen,
|
|
157
|
+
onOpenChange
|
|
158
|
+
} = options;
|
|
159
|
+
const [handle, setHandle] = react.useState(null);
|
|
110
160
|
const [internalOpen, setInternalOpen] = react.useState(false);
|
|
111
|
-
const
|
|
112
|
-
const
|
|
161
|
+
const handleRef = react.useRef(null);
|
|
162
|
+
const isControlled = controlledOpen !== void 0;
|
|
163
|
+
const isOpen = isControlled ? controlledOpen : internalOpen;
|
|
113
164
|
const stableOnReady = useStableCallback(onReady);
|
|
114
165
|
const stableOnSubmit = useStableCallback(onSubmit);
|
|
115
166
|
const stableOnNavigate = useStableCallback(onNavigate);
|
|
@@ -126,13 +177,14 @@ function PopupButton({
|
|
|
126
177
|
);
|
|
127
178
|
const handleClose = react.useCallback(() => {
|
|
128
179
|
handleRef.current = null;
|
|
180
|
+
setHandle(null);
|
|
129
181
|
setOpen(false);
|
|
130
182
|
onClose?.();
|
|
131
183
|
}, [setOpen, onClose]);
|
|
132
184
|
const stableOnClose = useStableCallback(handleClose);
|
|
133
|
-
const
|
|
185
|
+
const createSlider = react.useCallback(() => {
|
|
134
186
|
if (handleRef.current) return handleRef.current;
|
|
135
|
-
const
|
|
187
|
+
const newHandle = sdk.openSlider({
|
|
136
188
|
researchId,
|
|
137
189
|
params,
|
|
138
190
|
brand,
|
|
@@ -144,8 +196,9 @@ function PopupButton({
|
|
|
144
196
|
onClose: stableOnClose,
|
|
145
197
|
onError: stableOnError
|
|
146
198
|
});
|
|
147
|
-
handleRef.current =
|
|
148
|
-
|
|
199
|
+
handleRef.current = newHandle;
|
|
200
|
+
setHandle(newHandle);
|
|
201
|
+
return newHandle;
|
|
149
202
|
}, [
|
|
150
203
|
researchId,
|
|
151
204
|
params,
|
|
@@ -158,129 +211,93 @@ function PopupButton({
|
|
|
158
211
|
stableOnClose,
|
|
159
212
|
stableOnError
|
|
160
213
|
]);
|
|
161
|
-
const
|
|
162
|
-
()
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
close: () => {
|
|
168
|
-
handleRef.current?.destroy();
|
|
169
|
-
handleRef.current = null;
|
|
170
|
-
setOpen(false);
|
|
171
|
-
},
|
|
172
|
-
toggle: () => {
|
|
173
|
-
if (handleRef.current) {
|
|
174
|
-
handleRef.current.destroy();
|
|
175
|
-
handleRef.current = null;
|
|
176
|
-
setOpen(false);
|
|
177
|
-
} else {
|
|
178
|
-
createPopup();
|
|
179
|
-
setOpen(true);
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
unmount: () => {
|
|
183
|
-
handleRef.current?.unmount();
|
|
184
|
-
handleRef.current = null;
|
|
185
|
-
setOpen(false);
|
|
186
|
-
},
|
|
187
|
-
get isOpen() {
|
|
188
|
-
return isOpen;
|
|
189
|
-
},
|
|
190
|
-
researchId
|
|
191
|
-
}),
|
|
192
|
-
[createPopup, setOpen, researchId, isOpen]
|
|
193
|
-
);
|
|
194
|
-
react.useEffect(() => {
|
|
195
|
-
if (embedRef) {
|
|
196
|
-
embedRef.current = proxyHandle;
|
|
214
|
+
const destroySlider = react.useCallback(() => {
|
|
215
|
+
if (handleRef.current) {
|
|
216
|
+
handleRef.current.destroy();
|
|
217
|
+
handleRef.current = null;
|
|
218
|
+
setHandle(null);
|
|
197
219
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
220
|
+
}, []);
|
|
221
|
+
const openFn = react.useCallback(() => {
|
|
222
|
+
if (isControlled) {
|
|
223
|
+
onOpenChange?.(true);
|
|
224
|
+
} else {
|
|
225
|
+
createSlider();
|
|
226
|
+
setInternalOpen(true);
|
|
227
|
+
}
|
|
228
|
+
}, [isControlled, onOpenChange, createSlider]);
|
|
229
|
+
const closeFn = react.useCallback(() => {
|
|
230
|
+
if (isControlled) {
|
|
231
|
+
onOpenChange?.(false);
|
|
232
|
+
} else {
|
|
233
|
+
destroySlider();
|
|
234
|
+
setInternalOpen(false);
|
|
235
|
+
}
|
|
236
|
+
}, [isControlled, onOpenChange, destroySlider]);
|
|
237
|
+
const toggleFn = react.useCallback(() => {
|
|
238
|
+
if (isOpen) {
|
|
239
|
+
closeFn();
|
|
240
|
+
} else {
|
|
241
|
+
openFn();
|
|
242
|
+
}
|
|
243
|
+
}, [isOpen, openFn, closeFn]);
|
|
204
244
|
react.useEffect(() => {
|
|
205
245
|
if (!isControlled) return;
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
} else if (!
|
|
209
|
-
|
|
210
|
-
handleRef.current = null;
|
|
246
|
+
if (controlledOpen && !handleRef.current) {
|
|
247
|
+
createSlider();
|
|
248
|
+
} else if (!controlledOpen && handleRef.current) {
|
|
249
|
+
destroySlider();
|
|
211
250
|
}
|
|
212
|
-
}, [
|
|
213
|
-
|
|
214
|
-
(
|
|
215
|
-
|
|
216
|
-
if (e.defaultPrevented) return;
|
|
217
|
-
if (isOpen && handleRef.current) {
|
|
251
|
+
}, [controlledOpen, isControlled, createSlider, destroySlider]);
|
|
252
|
+
react.useEffect(() => {
|
|
253
|
+
return () => {
|
|
254
|
+
if (handleRef.current) {
|
|
218
255
|
handleRef.current.destroy();
|
|
219
256
|
handleRef.current = null;
|
|
220
|
-
setOpen(false);
|
|
221
|
-
} else {
|
|
222
|
-
createPopup();
|
|
223
|
-
setOpen(true);
|
|
224
257
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
...buttonProps,
|
|
235
|
-
children
|
|
236
|
-
}
|
|
237
|
-
);
|
|
258
|
+
};
|
|
259
|
+
}, []);
|
|
260
|
+
return {
|
|
261
|
+
open: openFn,
|
|
262
|
+
close: closeFn,
|
|
263
|
+
toggle: toggleFn,
|
|
264
|
+
isOpen,
|
|
265
|
+
handle
|
|
266
|
+
};
|
|
238
267
|
}
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
...buttonProps
|
|
256
|
-
}) {
|
|
257
|
-
const handleRef = react.useRef(null);
|
|
268
|
+
function useFloatBubble(options) {
|
|
269
|
+
const {
|
|
270
|
+
researchId,
|
|
271
|
+
params,
|
|
272
|
+
brand,
|
|
273
|
+
theme,
|
|
274
|
+
host,
|
|
275
|
+
onReady,
|
|
276
|
+
onSubmit,
|
|
277
|
+
onNavigate,
|
|
278
|
+
onClose,
|
|
279
|
+
onError,
|
|
280
|
+
open: controlledOpen,
|
|
281
|
+
onOpenChange
|
|
282
|
+
} = options;
|
|
283
|
+
const [handle, setHandle] = react.useState(null);
|
|
258
284
|
const [internalOpen, setInternalOpen] = react.useState(false);
|
|
259
|
-
const
|
|
260
|
-
const
|
|
285
|
+
const handleRef = react.useRef(null);
|
|
286
|
+
const isControlled = controlledOpen !== void 0;
|
|
261
287
|
const stableOnReady = useStableCallback(onReady);
|
|
262
288
|
const stableOnSubmit = useStableCallback(onSubmit);
|
|
263
289
|
const stableOnNavigate = useStableCallback(onNavigate);
|
|
264
290
|
const stableOnError = useStableCallback(onError);
|
|
265
|
-
const setOpen = react.useCallback(
|
|
266
|
-
(value) => {
|
|
267
|
-
if (isControlled) {
|
|
268
|
-
onOpenChange?.(value);
|
|
269
|
-
} else {
|
|
270
|
-
setInternalOpen(value);
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
[isControlled, onOpenChange]
|
|
274
|
-
);
|
|
275
291
|
const handleClose = react.useCallback(() => {
|
|
276
|
-
|
|
277
|
-
|
|
292
|
+
setInternalOpen(false);
|
|
293
|
+
if (isControlled) {
|
|
294
|
+
onOpenChange?.(false);
|
|
295
|
+
}
|
|
278
296
|
onClose?.();
|
|
279
|
-
}, [
|
|
297
|
+
}, [isControlled, onOpenChange, onClose]);
|
|
280
298
|
const stableOnClose = useStableCallback(handleClose);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const handle = sdk.openSlider({
|
|
299
|
+
react.useEffect(() => {
|
|
300
|
+
const newHandle = sdk.createFloatBubble({
|
|
284
301
|
researchId,
|
|
285
302
|
params,
|
|
286
303
|
brand,
|
|
@@ -292,8 +309,15 @@ function SliderButton({
|
|
|
292
309
|
onClose: stableOnClose,
|
|
293
310
|
onError: stableOnError
|
|
294
311
|
});
|
|
295
|
-
handleRef.current =
|
|
296
|
-
|
|
312
|
+
handleRef.current = newHandle;
|
|
313
|
+
setHandle(newHandle);
|
|
314
|
+
return () => {
|
|
315
|
+
if (handleRef.current === newHandle) {
|
|
316
|
+
newHandle.unmount();
|
|
317
|
+
handleRef.current = null;
|
|
318
|
+
setHandle(null);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
297
321
|
}, [
|
|
298
322
|
researchId,
|
|
299
323
|
params,
|
|
@@ -306,85 +330,72 @@ function SliderButton({
|
|
|
306
330
|
stableOnClose,
|
|
307
331
|
stableOnError
|
|
308
332
|
]);
|
|
309
|
-
const proxyHandle = react.useMemo(
|
|
310
|
-
() => ({
|
|
311
|
-
open: () => {
|
|
312
|
-
createSlider();
|
|
313
|
-
setOpen(true);
|
|
314
|
-
},
|
|
315
|
-
close: () => {
|
|
316
|
-
handleRef.current?.destroy();
|
|
317
|
-
handleRef.current = null;
|
|
318
|
-
setOpen(false);
|
|
319
|
-
},
|
|
320
|
-
toggle: () => {
|
|
321
|
-
if (handleRef.current) {
|
|
322
|
-
handleRef.current.destroy();
|
|
323
|
-
handleRef.current = null;
|
|
324
|
-
setOpen(false);
|
|
325
|
-
} else {
|
|
326
|
-
createSlider();
|
|
327
|
-
setOpen(true);
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
unmount: () => {
|
|
331
|
-
handleRef.current?.unmount();
|
|
332
|
-
handleRef.current = null;
|
|
333
|
-
setOpen(false);
|
|
334
|
-
},
|
|
335
|
-
get isOpen() {
|
|
336
|
-
return isOpen;
|
|
337
|
-
},
|
|
338
|
-
researchId
|
|
339
|
-
}),
|
|
340
|
-
[createSlider, setOpen, researchId, isOpen]
|
|
341
|
-
);
|
|
342
333
|
react.useEffect(() => {
|
|
343
|
-
if (
|
|
344
|
-
|
|
334
|
+
if (!isControlled || !handle) return;
|
|
335
|
+
if (controlledOpen && !handle.isOpen) {
|
|
336
|
+
handle.open();
|
|
337
|
+
} else if (!controlledOpen && handle.isOpen) {
|
|
338
|
+
handle.close();
|
|
345
339
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (!isControlled) return;
|
|
354
|
-
if (open && !handleRef.current) {
|
|
355
|
-
createSlider();
|
|
356
|
-
} else if (!open && handleRef.current) {
|
|
357
|
-
handleRef.current.destroy();
|
|
358
|
-
handleRef.current = null;
|
|
340
|
+
}, [controlledOpen, isControlled, handle]);
|
|
341
|
+
const openFn = react.useCallback(() => {
|
|
342
|
+
if (isControlled) {
|
|
343
|
+
onOpenChange?.(true);
|
|
344
|
+
} else {
|
|
345
|
+
handleRef.current?.open();
|
|
346
|
+
setInternalOpen(true);
|
|
359
347
|
}
|
|
360
|
-
}, [
|
|
361
|
-
const
|
|
362
|
-
(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
);
|
|
376
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
377
|
-
"button",
|
|
378
|
-
{
|
|
379
|
-
type: "button",
|
|
380
|
-
onClick: handleClick,
|
|
381
|
-
"data-testid": "perspective-slider-button",
|
|
382
|
-
...buttonProps,
|
|
383
|
-
children
|
|
348
|
+
}, [isControlled, onOpenChange]);
|
|
349
|
+
const closeFn = react.useCallback(() => {
|
|
350
|
+
if (isControlled) {
|
|
351
|
+
onOpenChange?.(false);
|
|
352
|
+
} else {
|
|
353
|
+
handleRef.current?.close();
|
|
354
|
+
setInternalOpen(false);
|
|
355
|
+
}
|
|
356
|
+
}, [isControlled, onOpenChange]);
|
|
357
|
+
const toggleFn = react.useCallback(() => {
|
|
358
|
+
const currentlyOpen = handleRef.current?.isOpen ?? internalOpen;
|
|
359
|
+
if (currentlyOpen) {
|
|
360
|
+
closeFn();
|
|
361
|
+
} else {
|
|
362
|
+
openFn();
|
|
384
363
|
}
|
|
364
|
+
}, [internalOpen, openFn, closeFn]);
|
|
365
|
+
const unmountFn = react.useCallback(() => {
|
|
366
|
+
handleRef.current?.unmount();
|
|
367
|
+
handleRef.current = null;
|
|
368
|
+
setHandle(null);
|
|
369
|
+
setInternalOpen(false);
|
|
370
|
+
}, []);
|
|
371
|
+
const isOpen = isControlled ? controlledOpen : handle?.isOpen ?? internalOpen;
|
|
372
|
+
return {
|
|
373
|
+
open: openFn,
|
|
374
|
+
close: closeFn,
|
|
375
|
+
toggle: toggleFn,
|
|
376
|
+
unmount: unmountFn,
|
|
377
|
+
isOpen,
|
|
378
|
+
handle
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function useThemeSync(theme = "system") {
|
|
382
|
+
const [resolved, setResolved] = react.useState(
|
|
383
|
+
theme !== "system" ? theme : "light"
|
|
385
384
|
);
|
|
385
|
+
react.useEffect(() => {
|
|
386
|
+
if (theme !== "system") {
|
|
387
|
+
setResolved(theme);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
391
|
+
setResolved(mq.matches ? "dark" : "light");
|
|
392
|
+
const handler = (e) => setResolved(e.matches ? "dark" : "light");
|
|
393
|
+
mq.addEventListener("change", handler);
|
|
394
|
+
return () => mq.removeEventListener("change", handler);
|
|
395
|
+
}, [theme]);
|
|
396
|
+
return resolved;
|
|
386
397
|
}
|
|
387
|
-
function
|
|
398
|
+
function Widget({
|
|
388
399
|
researchId,
|
|
389
400
|
params,
|
|
390
401
|
brand,
|
|
@@ -395,8 +406,12 @@ function FloatBubble({
|
|
|
395
406
|
onNavigate,
|
|
396
407
|
onClose,
|
|
397
408
|
onError,
|
|
398
|
-
embedRef
|
|
409
|
+
embedRef,
|
|
410
|
+
className,
|
|
411
|
+
style,
|
|
412
|
+
...divProps
|
|
399
413
|
}) {
|
|
414
|
+
const containerRef = react.useRef(null);
|
|
400
415
|
const handleRef = react.useRef(null);
|
|
401
416
|
const stableOnReady = useStableCallback(onReady);
|
|
402
417
|
const stableOnSubmit = useStableCallback(onSubmit);
|
|
@@ -404,7 +419,9 @@ function FloatBubble({
|
|
|
404
419
|
const stableOnClose = useStableCallback(onClose);
|
|
405
420
|
const stableOnError = useStableCallback(onError);
|
|
406
421
|
react.useEffect(() => {
|
|
407
|
-
const
|
|
422
|
+
const container = containerRef.current;
|
|
423
|
+
if (!container) return;
|
|
424
|
+
const handle = sdk.createWidget(container, {
|
|
408
425
|
researchId,
|
|
409
426
|
params,
|
|
410
427
|
brand,
|
|
@@ -440,7 +457,16 @@ function FloatBubble({
|
|
|
440
457
|
stableOnError,
|
|
441
458
|
embedRef
|
|
442
459
|
]);
|
|
443
|
-
return
|
|
460
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
461
|
+
"div",
|
|
462
|
+
{
|
|
463
|
+
ref: containerRef,
|
|
464
|
+
className,
|
|
465
|
+
style: { minHeight: 500, ...style },
|
|
466
|
+
"data-testid": "perspective-widget",
|
|
467
|
+
...divProps
|
|
468
|
+
}
|
|
469
|
+
);
|
|
444
470
|
}
|
|
445
471
|
function Fullpage({
|
|
446
472
|
researchId,
|
|
@@ -500,29 +526,50 @@ function Fullpage({
|
|
|
500
526
|
]);
|
|
501
527
|
return null;
|
|
502
528
|
}
|
|
503
|
-
function
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
529
|
+
function FloatBubble({
|
|
530
|
+
researchId,
|
|
531
|
+
params,
|
|
532
|
+
brand,
|
|
533
|
+
theme,
|
|
534
|
+
host,
|
|
535
|
+
onReady,
|
|
536
|
+
onSubmit,
|
|
537
|
+
onNavigate,
|
|
538
|
+
onClose,
|
|
539
|
+
onError,
|
|
540
|
+
embedRef
|
|
541
|
+
}) {
|
|
542
|
+
const { handle } = useFloatBubble({
|
|
543
|
+
researchId,
|
|
544
|
+
params,
|
|
545
|
+
brand,
|
|
546
|
+
theme,
|
|
547
|
+
host,
|
|
548
|
+
onReady,
|
|
549
|
+
onSubmit,
|
|
550
|
+
onNavigate,
|
|
551
|
+
onClose,
|
|
552
|
+
onError
|
|
553
|
+
});
|
|
507
554
|
react.useEffect(() => {
|
|
508
|
-
if (
|
|
509
|
-
|
|
510
|
-
return;
|
|
555
|
+
if (embedRef) {
|
|
556
|
+
embedRef.current = handle;
|
|
511
557
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}, [
|
|
518
|
-
return
|
|
558
|
+
return () => {
|
|
559
|
+
if (embedRef) {
|
|
560
|
+
embedRef.current = null;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
}, [embedRef, handle]);
|
|
564
|
+
return null;
|
|
519
565
|
}
|
|
520
566
|
|
|
521
567
|
exports.FloatBubble = FloatBubble;
|
|
522
568
|
exports.Fullpage = Fullpage;
|
|
523
|
-
exports.PopupButton = PopupButton;
|
|
524
|
-
exports.SliderButton = SliderButton;
|
|
525
569
|
exports.Widget = Widget;
|
|
570
|
+
exports.useFloatBubble = useFloatBubble;
|
|
571
|
+
exports.usePopup = usePopup;
|
|
572
|
+
exports.useSlider = useSlider;
|
|
526
573
|
exports.useStableCallback = useStableCallback;
|
|
527
574
|
exports.useThemeSync = useThemeSync;
|
|
528
575
|
//# sourceMappingURL=index.cjs.map
|