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