survo-react-widget 1.0.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 ADDED
@@ -0,0 +1,71 @@
1
+ # survo-react-widget
2
+
3
+ Native React component for embedding [Survo](https://survo.digital) surveys in your application.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install survo-react-widget
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import { SurvoWidget } from 'survo-react-widget';
15
+
16
+ function App() {
17
+ return (
18
+ <SurvoWidget
19
+ apiKey="your-api-key"
20
+ surveyId="your-survey-id"
21
+ display="inline"
22
+ />
23
+ );
24
+ }
25
+ ```
26
+
27
+ ## Props
28
+
29
+ | Prop | Type | Default | Description |
30
+ |------|------|---------|-------------|
31
+ | `apiKey` | `string` | **required** | Your Survo API key |
32
+ | `surveyId` | `string` | **required** | The survey ID to display |
33
+ | `display` | `'modal' \| 'inline'` | `'modal'` | Display mode |
34
+ | `containerId` | `string` | `'survo-widget'` | Target container ID (inline mode) |
35
+ | `baseUrl` | `string` | `'https://api.survo.digital'` | API base URL |
36
+
37
+ ## Display Modes
38
+
39
+ ### Inline Mode
40
+
41
+ Renders the survey directly in your component tree:
42
+
43
+ ```tsx
44
+ <SurvoWidget
45
+ apiKey="your-api-key"
46
+ surveyId="your-survey-id"
47
+ display="inline"
48
+ />
49
+ ```
50
+
51
+ ### Modal Mode
52
+
53
+ Renders the survey as a floating modal in the bottom-right corner:
54
+
55
+ ```tsx
56
+ <SurvoWidget
57
+ apiKey="your-api-key"
58
+ surveyId="your-survey-id"
59
+ display="modal"
60
+ />
61
+ ```
62
+
63
+ ## Getting Your API Key
64
+
65
+ 1. Log in to [survo.digital](https://survo.digital)
66
+ 2. Navigate to your workspace settings
67
+ 3. Create an API key in the **API Keys** section
68
+
69
+ ## License
70
+
71
+ MIT © [Survo Digital](https://survo.digital)
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export interface SurvoConfig {
3
+ apiKey: string;
4
+ surveyId: string;
5
+ display?: 'modal' | 'inline';
6
+ containerId?: string;
7
+ baseUrl?: string;
8
+ }
9
+ export declare const SurvoWidget: React.FC<SurvoConfig>;
10
+ //# sourceMappingURL=SurvoWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SurvoWidget.d.ts","sourceRoot":"","sources":["../../src/components/SurvoWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmBD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA+Y7C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './components/SurvoWidget';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,581 @@
1
+ import te, { useState as y, useCallback as ne, useEffect as X } from "react";
2
+ var z = { exports: {} }, w = {};
3
+ var Z;
4
+ function oe() {
5
+ if (Z) return w;
6
+ Z = 1;
7
+ var x = /* @__PURE__ */ Symbol.for("react.transitional.element"), b = /* @__PURE__ */ Symbol.for("react.fragment");
8
+ function m(_, u, i) {
9
+ var h = null;
10
+ if (i !== void 0 && (h = "" + i), u.key !== void 0 && (h = "" + u.key), "key" in u) {
11
+ i = {};
12
+ for (var p in u)
13
+ p !== "key" && (i[p] = u[p]);
14
+ } else i = u;
15
+ return u = i.ref, {
16
+ $$typeof: x,
17
+ type: _,
18
+ key: h,
19
+ ref: u !== void 0 ? u : null,
20
+ props: i
21
+ };
22
+ }
23
+ return w.Fragment = b, w.jsx = m, w.jsxs = m, w;
24
+ }
25
+ var k = {};
26
+ var Q;
27
+ function ae() {
28
+ return Q || (Q = 1, process.env.NODE_ENV !== "production" && (function() {
29
+ function x(e) {
30
+ if (e == null) return null;
31
+ if (typeof e == "function")
32
+ return e.$$typeof === a ? null : e.displayName || e.name || null;
33
+ if (typeof e == "string") return e;
34
+ switch (e) {
35
+ case j:
36
+ return "Fragment";
37
+ case I:
38
+ return "Profiler";
39
+ case P:
40
+ return "StrictMode";
41
+ case g:
42
+ return "Suspense";
43
+ case $:
44
+ return "SuspenseList";
45
+ case c:
46
+ return "Activity";
47
+ }
48
+ if (typeof e == "object")
49
+ switch (typeof e.tag == "number" && console.error(
50
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
51
+ ), e.$$typeof) {
52
+ case W:
53
+ return "Portal";
54
+ case Y:
55
+ return e.displayName || "Context";
56
+ case F:
57
+ return (e._context.displayName || "Context") + ".Consumer";
58
+ case d:
59
+ var r = e.render;
60
+ return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
61
+ case D:
62
+ return r = e.displayName || null, r !== null ? r : x(e.type) || "Memo";
63
+ case n:
64
+ r = e._payload, e = e._init;
65
+ try {
66
+ return x(e(r));
67
+ } catch {
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ function b(e) {
73
+ return "" + e;
74
+ }
75
+ function m(e) {
76
+ try {
77
+ b(e);
78
+ var r = !1;
79
+ } catch {
80
+ r = !0;
81
+ }
82
+ if (r) {
83
+ r = console;
84
+ var o = r.error, s = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
85
+ return o.call(
86
+ r,
87
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
88
+ s
89
+ ), b(e);
90
+ }
91
+ }
92
+ function _(e) {
93
+ if (e === j) return "<>";
94
+ if (typeof e == "object" && e !== null && e.$$typeof === n)
95
+ return "<...>";
96
+ try {
97
+ var r = x(e);
98
+ return r ? "<" + r + ">" : "<...>";
99
+ } catch {
100
+ return "<...>";
101
+ }
102
+ }
103
+ function u() {
104
+ var e = f.A;
105
+ return e === null ? null : e.getOwner();
106
+ }
107
+ function i() {
108
+ return Error("react-stack-top-frame");
109
+ }
110
+ function h(e) {
111
+ if (V.call(e, "key")) {
112
+ var r = Object.getOwnPropertyDescriptor(e, "key").get;
113
+ if (r && r.isReactWarning) return !1;
114
+ }
115
+ return e.key !== void 0;
116
+ }
117
+ function p(e, r) {
118
+ function o() {
119
+ J || (J = !0, console.error(
120
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
121
+ r
122
+ ));
123
+ }
124
+ o.isReactWarning = !0, Object.defineProperty(e, "key", {
125
+ get: o,
126
+ configurable: !0
127
+ });
128
+ }
129
+ function T() {
130
+ var e = x(this.type);
131
+ return H[e] || (H[e] = !0, console.error(
132
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
133
+ )), e = this.props.ref, e !== void 0 ? e : null;
134
+ }
135
+ function A(e, r, o, s, N, q) {
136
+ var l = o.ref;
137
+ return e = {
138
+ $$typeof: C,
139
+ type: e,
140
+ key: r,
141
+ props: o,
142
+ _owner: s
143
+ }, (l !== void 0 ? l : null) !== null ? Object.defineProperty(e, "ref", {
144
+ enumerable: !1,
145
+ get: T
146
+ }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
147
+ configurable: !1,
148
+ enumerable: !1,
149
+ writable: !0,
150
+ value: 0
151
+ }), Object.defineProperty(e, "_debugInfo", {
152
+ configurable: !1,
153
+ enumerable: !1,
154
+ writable: !0,
155
+ value: null
156
+ }), Object.defineProperty(e, "_debugStack", {
157
+ configurable: !1,
158
+ enumerable: !1,
159
+ writable: !0,
160
+ value: N
161
+ }), Object.defineProperty(e, "_debugTask", {
162
+ configurable: !1,
163
+ enumerable: !1,
164
+ writable: !0,
165
+ value: q
166
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
167
+ }
168
+ function O(e, r, o, s, N, q) {
169
+ var l = r.children;
170
+ if (l !== void 0)
171
+ if (s)
172
+ if (ee(l)) {
173
+ for (s = 0; s < l.length; s++)
174
+ S(l[s]);
175
+ Object.freeze && Object.freeze(l);
176
+ } else
177
+ console.error(
178
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
179
+ );
180
+ else S(l);
181
+ if (V.call(r, "key")) {
182
+ l = x(e);
183
+ var R = Object.keys(r).filter(function(re) {
184
+ return re !== "key";
185
+ });
186
+ s = 0 < R.length ? "{key: someKey, " + R.join(": ..., ") + ": ...}" : "{key: someKey}", B[l + s] || (R = 0 < R.length ? "{" + R.join(": ..., ") + ": ...}" : "{}", console.error(
187
+ `A props object containing a "key" prop is being spread into JSX:
188
+ let props = %s;
189
+ <%s {...props} />
190
+ React keys must be passed directly to JSX without using spread:
191
+ let props = %s;
192
+ <%s key={someKey} {...props} />`,
193
+ s,
194
+ l,
195
+ R,
196
+ l
197
+ ), B[l + s] = !0);
198
+ }
199
+ if (l = null, o !== void 0 && (m(o), l = "" + o), h(r) && (m(r.key), l = "" + r.key), "key" in r) {
200
+ o = {};
201
+ for (var L in r)
202
+ L !== "key" && (o[L] = r[L]);
203
+ } else o = r;
204
+ return l && p(
205
+ o,
206
+ typeof e == "function" ? e.displayName || e.name || "Unknown" : e
207
+ ), A(
208
+ e,
209
+ l,
210
+ o,
211
+ u(),
212
+ N,
213
+ q
214
+ );
215
+ }
216
+ function S(e) {
217
+ E(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === n && (e._payload.status === "fulfilled" ? E(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
218
+ }
219
+ function E(e) {
220
+ return typeof e == "object" && e !== null && e.$$typeof === C;
221
+ }
222
+ var v = te, C = /* @__PURE__ */ Symbol.for("react.transitional.element"), W = /* @__PURE__ */ Symbol.for("react.portal"), j = /* @__PURE__ */ Symbol.for("react.fragment"), P = /* @__PURE__ */ Symbol.for("react.strict_mode"), I = /* @__PURE__ */ Symbol.for("react.profiler"), F = /* @__PURE__ */ Symbol.for("react.consumer"), Y = /* @__PURE__ */ Symbol.for("react.context"), d = /* @__PURE__ */ Symbol.for("react.forward_ref"), g = /* @__PURE__ */ Symbol.for("react.suspense"), $ = /* @__PURE__ */ Symbol.for("react.suspense_list"), D = /* @__PURE__ */ Symbol.for("react.memo"), n = /* @__PURE__ */ Symbol.for("react.lazy"), c = /* @__PURE__ */ Symbol.for("react.activity"), a = /* @__PURE__ */ Symbol.for("react.client.reference"), f = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, V = Object.prototype.hasOwnProperty, ee = Array.isArray, M = console.createTask ? console.createTask : function() {
223
+ return null;
224
+ };
225
+ v = {
226
+ react_stack_bottom_frame: function(e) {
227
+ return e();
228
+ }
229
+ };
230
+ var J, H = {}, U = v.react_stack_bottom_frame.bind(
231
+ v,
232
+ i
233
+ )(), G = M(_(i)), B = {};
234
+ k.Fragment = j, k.jsx = function(e, r, o) {
235
+ var s = 1e4 > f.recentlyCreatedOwnerStacks++;
236
+ return O(
237
+ e,
238
+ r,
239
+ o,
240
+ !1,
241
+ s ? Error("react-stack-top-frame") : U,
242
+ s ? M(_(e)) : G
243
+ );
244
+ }, k.jsxs = function(e, r, o) {
245
+ var s = 1e4 > f.recentlyCreatedOwnerStacks++;
246
+ return O(
247
+ e,
248
+ r,
249
+ o,
250
+ !0,
251
+ s ? Error("react-stack-top-frame") : U,
252
+ s ? M(_(e)) : G
253
+ );
254
+ };
255
+ })()), k;
256
+ }
257
+ var K;
258
+ function ie() {
259
+ return K || (K = 1, process.env.NODE_ENV === "production" ? z.exports = oe() : z.exports = ae()), z.exports;
260
+ }
261
+ var t = ie();
262
+ const le = ({
263
+ apiKey: x,
264
+ surveyId: b,
265
+ display: m = "modal",
266
+ containerId: _ = "survo-widget",
267
+ baseUrl: u = "https://api.survo.digital"
268
+ }) => {
269
+ const [i, h] = y(null), [p, T] = y(-1), [A, O] = y({}), [S, E] = y(!0), [v, C] = y(!1), [W, j] = y(!0), P = ne(async () => {
270
+ try {
271
+ const n = await fetch(`${u}/api/v1/widget/config?key=${x}&surveyId=${b}`);
272
+ if (!n.ok) throw new Error("Failed to load");
273
+ const c = await n.json();
274
+ h(c.survey);
275
+ } catch (n) {
276
+ console.error("[Survo Widget] Error loading survey:", n);
277
+ } finally {
278
+ E(!1);
279
+ }
280
+ }, [x, b, u]);
281
+ X(() => {
282
+ P();
283
+ }, [P]);
284
+ const I = async () => {
285
+ E(!0);
286
+ try {
287
+ await fetch(`${u}/api/v1/widget/submit`, {
288
+ method: "POST",
289
+ headers: { "Content-Type": "application/json" },
290
+ body: JSON.stringify({
291
+ key: x,
292
+ surveyId: b,
293
+ answers: A,
294
+ metadata: {
295
+ domain: window.location.hostname,
296
+ url: window.location.href,
297
+ submittedVia: "react-widget"
298
+ }
299
+ })
300
+ }), C(!0);
301
+ } catch (n) {
302
+ console.error("[Survo Widget] Error submitting answers:", n), alert("Erro ao enviar. Por favor tente novamente.");
303
+ } finally {
304
+ E(!1);
305
+ }
306
+ }, F = (n) => {
307
+ const c = i?.questions[p];
308
+ if (c?.required && (n === null || n === "")) {
309
+ alert("Por favor, responda a esta pergunta.");
310
+ return;
311
+ }
312
+ const a = { ...A };
313
+ c && (a[c.id] = n), O(a), p + 1 >= (i?.questions.length || 0) ? I() : T(p + 1);
314
+ };
315
+ if (!W || !S && !i) return null;
316
+ const Y = () => {
317
+ if (S && !v)
318
+ return /* @__PURE__ */ t.jsx("div", { style: { textAlign: "center", padding: "40px 0" }, children: /* @__PURE__ */ t.jsx("p", { style: { color: "#64748b", fontSize: "14px" }, children: "A carregar..." }) });
319
+ if (v)
320
+ return /* @__PURE__ */ t.jsxs("div", { style: { textAlign: "center", padding: "20px 0" }, children: [
321
+ /* @__PURE__ */ t.jsx("div", { style: {
322
+ width: "64px",
323
+ height: "64px",
324
+ background: "#000",
325
+ borderRadius: "50%",
326
+ margin: "0 auto 16px auto",
327
+ display: "flex",
328
+ alignItems: "center",
329
+ justifyContent: "center",
330
+ color: "#fff",
331
+ fontSize: "32px",
332
+ fontWeight: 700
333
+ }, children: "✓" }),
334
+ /* @__PURE__ */ t.jsx("h3", { style: { margin: 0, fontSize: "20px", fontWeight: 700, color: "#000" }, children: "Muito Obrigado!" }),
335
+ /* @__PURE__ */ t.jsx("p", { style: { fontSize: "14px", color: "#64748b", marginTop: "12px", lineHeight: 1.5 }, children: "Recebemos as suas respostas com sucesso. A sua opinião faz a diferença!" }),
336
+ /* @__PURE__ */ t.jsx(
337
+ "button",
338
+ {
339
+ onClick: () => j(!1),
340
+ style: {
341
+ marginTop: "24px",
342
+ padding: "12px",
343
+ width: "100%",
344
+ background: "#f1f5f9",
345
+ color: "#475569",
346
+ border: "none",
347
+ borderRadius: "8px",
348
+ cursor: "pointer",
349
+ fontWeight: 600
350
+ },
351
+ children: "Fechar"
352
+ }
353
+ )
354
+ ] });
355
+ if (p === -1)
356
+ return /* @__PURE__ */ t.jsxs("div", { children: [
357
+ /* @__PURE__ */ t.jsx("p", { style: { color: "#64748b", fontSize: "14px", margin: "0 0 24px 0", lineHeight: 1.5 }, children: i?.description || "A sua opinião é muito importante para nós." }),
358
+ /* @__PURE__ */ t.jsx(
359
+ "button",
360
+ {
361
+ onClick: () => T(0),
362
+ style: {
363
+ width: "100%",
364
+ padding: "12px",
365
+ background: "#000",
366
+ color: "#fff",
367
+ border: "none",
368
+ borderRadius: "8px",
369
+ cursor: "pointer",
370
+ fontWeight: 600,
371
+ fontSize: "14px"
372
+ },
373
+ children: "Começar Inquérito"
374
+ }
375
+ )
376
+ ] });
377
+ const n = i.questions[p];
378
+ return /* @__PURE__ */ t.jsxs("div", { children: [
379
+ /* @__PURE__ */ t.jsxs("div", { style: { fontSize: "10px", fontWeight: 700, color: "#94a3b8", textTransform: "uppercase", marginBottom: "8px", letterSpacing: "0.05em" }, children: [
380
+ "Pergunta ",
381
+ p + 1,
382
+ " de ",
383
+ i.questions.length
384
+ ] }),
385
+ /* @__PURE__ */ t.jsx("h4", { style: { margin: "0 0 20px 0", fontSize: "16px", color: "#000", fontWeight: 600, lineHeight: 1.4 }, children: n.title }),
386
+ /* @__PURE__ */ t.jsx("div", { style: { marginBottom: "20px" }, children: $(n) }),
387
+ /* @__PURE__ */ t.jsx(
388
+ "button",
389
+ {
390
+ id: "survo-next-btn",
391
+ onClick: () => F(d),
392
+ style: {
393
+ width: "100%",
394
+ padding: "12px",
395
+ background: "#000",
396
+ color: "#fff",
397
+ border: "none",
398
+ borderRadius: "8px",
399
+ cursor: "pointer",
400
+ fontWeight: 600,
401
+ fontSize: "14px"
402
+ },
403
+ children: p + 1 === i.questions.length ? "Finalizar" : "Continuar"
404
+ }
405
+ )
406
+ ] });
407
+ }, [d, g] = y(null);
408
+ X(() => {
409
+ g(null);
410
+ }, [p]);
411
+ const $ = (n) => {
412
+ if (["choice", "multiple_choice", "single_choice"].includes(n.type)) {
413
+ const c = Object.values(n.options || {});
414
+ return /* @__PURE__ */ t.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: c.map((a, f) => /* @__PURE__ */ t.jsx(
415
+ "div",
416
+ {
417
+ onClick: () => g(a),
418
+ style: {
419
+ padding: "12px",
420
+ border: "1px solid #e2e8f0",
421
+ borderRadius: "8px",
422
+ cursor: "pointer",
423
+ fontSize: "14px",
424
+ color: "#1e293b",
425
+ background: d === a ? "#f1f5f9" : "#fff",
426
+ borderColor: d === a ? "#000" : "#e2e8f0",
427
+ borderWidth: d === a ? "2px" : "1px",
428
+ fontWeight: d === a ? 600 : 400,
429
+ textAlign: "left"
430
+ },
431
+ children: a
432
+ },
433
+ f
434
+ )) });
435
+ }
436
+ if (n.type === "rating") {
437
+ const c = n.maxStars || 5;
438
+ return /* @__PURE__ */ t.jsx("div", { style: { display: "flex", gap: "12px", justifyContent: "flex-start" }, children: Array.from({ length: c }).map((a, f) => /* @__PURE__ */ t.jsx(
439
+ "button",
440
+ {
441
+ onClick: () => g(f + 1),
442
+ style: {
443
+ fontSize: "34px",
444
+ background: "none",
445
+ border: "none",
446
+ cursor: "pointer",
447
+ color: (d || 0) > f ? "#000" : "#e2e8f0",
448
+ padding: 0
449
+ },
450
+ children: "★"
451
+ },
452
+ f
453
+ )) });
454
+ }
455
+ if (n.type === "rating_emoji") {
456
+ const c = ["😡", "🙁", "😐", "🙂", "😍"];
457
+ return /* @__PURE__ */ t.jsx("div", { style: { display: "flex", gap: "12px", justifyContent: "flex-start" }, children: c.map((a, f) => /* @__PURE__ */ t.jsx(
458
+ "span",
459
+ {
460
+ onClick: () => g(f + 1),
461
+ style: {
462
+ fontSize: "28px",
463
+ cursor: "pointer",
464
+ opacity: d === f + 1 ? 1 : 0.3,
465
+ filter: d === f + 1 ? "grayscale(0)" : "grayscale(1)",
466
+ transform: d === f + 1 ? "scale(1.2)" : "scale(1)",
467
+ transition: "all 0.2s"
468
+ },
469
+ children: a
470
+ },
471
+ f
472
+ )) });
473
+ }
474
+ return n.type === "nps" ? /* @__PURE__ */ t.jsxs("div", { children: [
475
+ /* @__PURE__ */ t.jsx("div", { style: { display: "flex", justifyContent: "space-between", border: "1px solid #e2e8f0", borderRadius: "8px", padding: "4px" }, children: Array.from({ length: 11 }).map((c, a) => /* @__PURE__ */ t.jsx(
476
+ "div",
477
+ {
478
+ onClick: () => g(a),
479
+ style: {
480
+ flex: 1,
481
+ textAlign: "center",
482
+ padding: "8px 0",
483
+ fontSize: "12px",
484
+ fontWeight: 600,
485
+ cursor: "pointer",
486
+ borderRadius: "4px",
487
+ background: d === a ? "#000" : "transparent",
488
+ color: d === a ? "#fff" : "#1e293b"
489
+ },
490
+ children: a
491
+ },
492
+ a
493
+ )) }),
494
+ /* @__PURE__ */ t.jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: "10px", color: "#94a3b8", marginTop: "8px" }, children: [
495
+ /* @__PURE__ */ t.jsx("span", { children: "Nada provável" }),
496
+ /* @__PURE__ */ t.jsx("span", { children: "Muito provável" })
497
+ ] })
498
+ ] }) : n.type === "long_text" ? /* @__PURE__ */ t.jsx(
499
+ "textarea",
500
+ {
501
+ autoFocus: !0,
502
+ value: d || "",
503
+ onChange: (c) => g(c.target.value),
504
+ placeholder: "Escreva a sua resposta detalhada...",
505
+ style: {
506
+ width: "100%",
507
+ padding: "12px",
508
+ border: "1px solid #e2e8f0",
509
+ borderRadius: "8px",
510
+ fontSize: "14px",
511
+ fontFamily: "inherit",
512
+ minHeight: "100px",
513
+ boxSizing: "border-box"
514
+ }
515
+ }
516
+ ) : /* @__PURE__ */ t.jsx(
517
+ "input",
518
+ {
519
+ autoFocus: !0,
520
+ type: "text",
521
+ value: d || "",
522
+ onChange: (c) => g(c.target.value),
523
+ placeholder: "Escreva aqui...",
524
+ style: {
525
+ width: "100%",
526
+ padding: "12px",
527
+ border: "1px solid #e2e8f0",
528
+ borderRadius: "8px",
529
+ fontSize: "14px",
530
+ fontFamily: "inherit",
531
+ boxSizing: "border-box"
532
+ }
533
+ }
534
+ );
535
+ }, D = m === "modal" ? {
536
+ position: "fixed",
537
+ bottom: "20px",
538
+ right: "20px",
539
+ width: "360px",
540
+ maxHeight: "85vh",
541
+ boxShadow: "0 15px 45px rgba(0,0,0,0.15)",
542
+ borderRadius: "16px",
543
+ zIndex: 9999990,
544
+ background: "#fff",
545
+ border: "1px solid rgba(0,0,0,0.1)",
546
+ display: "flex",
547
+ flexDirection: "column",
548
+ overflow: "hidden",
549
+ fontFamily: "'Inter', -apple-system, sans-serif"
550
+ } : {
551
+ width: "100%",
552
+ background: "#fff",
553
+ border: "1px solid rgba(0,0,0,0.1)",
554
+ borderRadius: "12px",
555
+ display: "flex",
556
+ flexDirection: "column",
557
+ overflow: "hidden",
558
+ fontFamily: "'Inter', -apple-system, sans-serif"
559
+ };
560
+ return /* @__PURE__ */ t.jsxs("div", { className: "survo-react-widget", style: D, children: [
561
+ /* @__PURE__ */ t.jsxs("div", { style: { padding: "16px", background: "#fff", borderBottom: "1px solid #f1f5f9", display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
562
+ /* @__PURE__ */ t.jsx("span", { style: { fontWeight: 700, fontSize: "14px", color: "#000", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: i?.title || "Carregando..." }),
563
+ m === "modal" && /* @__PURE__ */ t.jsx(
564
+ "button",
565
+ {
566
+ onClick: () => j(!1),
567
+ style: { background: "none", border: "none", cursor: "pointer", color: "#000", fontSize: "24px", lineHeight: 1, padding: "4px" },
568
+ children: "×"
569
+ }
570
+ )
571
+ ] }),
572
+ /* @__PURE__ */ t.jsx("div", { style: { padding: "24px", overflowY: "auto" }, children: Y() }),
573
+ /* @__PURE__ */ t.jsxs("div", { style: { padding: "10px", textAlign: "center", fontSize: "10px", color: "#94a3b8", background: "#fff", borderTop: "1px solid #f1f5f9" }, children: [
574
+ "Disponibilizado pelo ",
575
+ /* @__PURE__ */ t.jsx("a", { href: "https://survo.digital", target: "_blank", rel: "noopener noreferrer", style: { color: "#64748b", fontWeight: 700, textDecoration: "none" }, children: "Survo" })
576
+ ] })
577
+ ] });
578
+ };
579
+ export {
580
+ le as SurvoWidget
581
+ };
@@ -0,0 +1,6 @@
1
+ (function(v,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],u):(v=typeof globalThis<"u"?globalThis:v||self,u(v.SurvoReact={},v.React))})(this,(function(v,u){"use strict";var A={exports:{}},w={};var U;function ee(){if(U)return w;U=1;var g=Symbol.for("react.transitional.element"),m=Symbol.for("react.fragment");function h(j,d,i){var y=null;if(i!==void 0&&(y=""+i),d.key!==void 0&&(y=""+d.key),"key"in d){i={};for(var x in d)x!=="key"&&(i[x]=d[x])}else i=d;return d=i.ref,{$$typeof:g,type:j,key:y,ref:d!==void 0?d:null,props:i}}return w.Fragment=m,w.jsx=h,w.jsxs=h,w}var k={};var G;function re(){return G||(G=1,process.env.NODE_ENV!=="production"&&(function(){function g(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===a?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case _:return"Fragment";case F:return"Profiler";case z:return"StrictMode";case b:return"Suspense";case M:return"SuspenseList";case c:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case I:return"Portal";case D:return e.displayName||"Context";case Y:return(e._context.displayName||"Context")+".Consumer";case f:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case L:return r=e.displayName||null,r!==null?r:g(e.type)||"Memo";case n:r=e._payload,e=e._init;try{return g(e(r))}catch{}}return null}function m(e){return""+e}function h(e){try{m(e);var r=!1}catch{r=!0}if(r){r=console;var o=r.error,s=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return o.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",s),m(e)}}function j(e){if(e===_)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===n)return"<...>";try{var r=g(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function d(){var e=p.A;return e===null?null:e.getOwner()}function i(){return Error("react-stack-top-frame")}function y(e){if(X.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function x(e,r){function o(){q||(q=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}o.isReactWarning=!0,Object.defineProperty(e,"key",{get:o,configurable:!0})}function O(){var e=g(this.type);return Z[e]||(Z[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function C(e,r,o,s,W,J){var l=o.ref;return e={$$typeof:N,type:e,key:r,props:o,_owner:s},(l!==void 0?l:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:O}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:W}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:J}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function P(e,r,o,s,W,J){var l=r.children;if(l!==void 0)if(s)if(oe(l)){for(s=0;s<l.length;s++)T(l[s]);Object.freeze&&Object.freeze(l)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else T(l);if(X.call(r,"key")){l=g(e);var R=Object.keys(r).filter(function(ae){return ae!=="key"});s=0<R.length?"{key: someKey, "+R.join(": ..., ")+": ...}":"{key: someKey}",K[l+s]||(R=0<R.length?"{"+R.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,s,l,R,l),K[l+s]=!0)}if(l=null,o!==void 0&&(h(o),l=""+o),y(r)&&(h(r.key),l=""+r.key),"key"in r){o={};for(var H in r)H!=="key"&&(o[H]=r[H])}else o=r;return l&&x(o,typeof e=="function"?e.displayName||e.name||"Unknown":e),C(e,l,o,d(),W,J)}function T(e){E(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===n&&(e._payload.status==="fulfilled"?E(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function E(e){return typeof e=="object"&&e!==null&&e.$$typeof===N}var S=u,N=Symbol.for("react.transitional.element"),I=Symbol.for("react.portal"),_=Symbol.for("react.fragment"),z=Symbol.for("react.strict_mode"),F=Symbol.for("react.profiler"),Y=Symbol.for("react.consumer"),D=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),b=Symbol.for("react.suspense"),M=Symbol.for("react.suspense_list"),L=Symbol.for("react.memo"),n=Symbol.for("react.lazy"),c=Symbol.for("react.activity"),a=Symbol.for("react.client.reference"),p=S.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,X=Object.prototype.hasOwnProperty,oe=Array.isArray,V=console.createTask?console.createTask:function(){return null};S={react_stack_bottom_frame:function(e){return e()}};var q,Z={},Q=S.react_stack_bottom_frame.bind(S,i)(),$=V(j(i)),K={};k.Fragment=_,k.jsx=function(e,r,o){var s=1e4>p.recentlyCreatedOwnerStacks++;return P(e,r,o,!1,s?Error("react-stack-top-frame"):Q,s?V(j(e)):$)},k.jsxs=function(e,r,o){var s=1e4>p.recentlyCreatedOwnerStacks++;return P(e,r,o,!0,s?Error("react-stack-top-frame"):Q,s?V(j(e)):$)}})()),k}var B;function te(){return B||(B=1,process.env.NODE_ENV==="production"?A.exports=ee():A.exports=re()),A.exports}var t=te();const ne=({apiKey:g,surveyId:m,display:h="modal",containerId:j="survo-widget",baseUrl:d="https://api.survo.digital"})=>{const[i,y]=u.useState(null),[x,O]=u.useState(-1),[C,P]=u.useState({}),[T,E]=u.useState(!0),[S,N]=u.useState(!1),[I,_]=u.useState(!0),z=u.useCallback(async()=>{try{const n=await fetch(`${d}/api/v1/widget/config?key=${g}&surveyId=${m}`);if(!n.ok)throw new Error("Failed to load");const c=await n.json();y(c.survey)}catch(n){console.error("[Survo Widget] Error loading survey:",n)}finally{E(!1)}},[g,m,d]);u.useEffect(()=>{z()},[z]);const F=async()=>{E(!0);try{await fetch(`${d}/api/v1/widget/submit`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:g,surveyId:m,answers:C,metadata:{domain:window.location.hostname,url:window.location.href,submittedVia:"react-widget"}})}),N(!0)}catch(n){console.error("[Survo Widget] Error submitting answers:",n),alert("Erro ao enviar. Por favor tente novamente.")}finally{E(!1)}},Y=n=>{const c=i?.questions[x];if(c?.required&&(n===null||n==="")){alert("Por favor, responda a esta pergunta.");return}const a={...C};c&&(a[c.id]=n),P(a),x+1>=(i?.questions.length||0)?F():O(x+1)};if(!I||!T&&!i)return null;const D=()=>{if(T&&!S)return t.jsx("div",{style:{textAlign:"center",padding:"40px 0"},children:t.jsx("p",{style:{color:"#64748b",fontSize:"14px"},children:"A carregar..."})});if(S)return t.jsxs("div",{style:{textAlign:"center",padding:"20px 0"},children:[t.jsx("div",{style:{width:"64px",height:"64px",background:"#000",borderRadius:"50%",margin:"0 auto 16px auto",display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:"32px",fontWeight:700},children:"✓"}),t.jsx("h3",{style:{margin:0,fontSize:"20px",fontWeight:700,color:"#000"},children:"Muito Obrigado!"}),t.jsx("p",{style:{fontSize:"14px",color:"#64748b",marginTop:"12px",lineHeight:1.5},children:"Recebemos as suas respostas com sucesso. A sua opinião faz a diferença!"}),t.jsx("button",{onClick:()=>_(!1),style:{marginTop:"24px",padding:"12px",width:"100%",background:"#f1f5f9",color:"#475569",border:"none",borderRadius:"8px",cursor:"pointer",fontWeight:600},children:"Fechar"})]});if(x===-1)return t.jsxs("div",{children:[t.jsx("p",{style:{color:"#64748b",fontSize:"14px",margin:"0 0 24px 0",lineHeight:1.5},children:i?.description||"A sua opinião é muito importante para nós."}),t.jsx("button",{onClick:()=>O(0),style:{width:"100%",padding:"12px",background:"#000",color:"#fff",border:"none",borderRadius:"8px",cursor:"pointer",fontWeight:600,fontSize:"14px"},children:"Começar Inquérito"})]});const n=i.questions[x];return t.jsxs("div",{children:[t.jsxs("div",{style:{fontSize:"10px",fontWeight:700,color:"#94a3b8",textTransform:"uppercase",marginBottom:"8px",letterSpacing:"0.05em"},children:["Pergunta ",x+1," de ",i.questions.length]}),t.jsx("h4",{style:{margin:"0 0 20px 0",fontSize:"16px",color:"#000",fontWeight:600,lineHeight:1.4},children:n.title}),t.jsx("div",{style:{marginBottom:"20px"},children:M(n)}),t.jsx("button",{id:"survo-next-btn",onClick:()=>Y(f),style:{width:"100%",padding:"12px",background:"#000",color:"#fff",border:"none",borderRadius:"8px",cursor:"pointer",fontWeight:600,fontSize:"14px"},children:x+1===i.questions.length?"Finalizar":"Continuar"})]})},[f,b]=u.useState(null);u.useEffect(()=>{b(null)},[x]);const M=n=>{if(["choice","multiple_choice","single_choice"].includes(n.type)){const c=Object.values(n.options||{});return t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:c.map((a,p)=>t.jsx("div",{onClick:()=>b(a),style:{padding:"12px",border:"1px solid #e2e8f0",borderRadius:"8px",cursor:"pointer",fontSize:"14px",color:"#1e293b",background:f===a?"#f1f5f9":"#fff",borderColor:f===a?"#000":"#e2e8f0",borderWidth:f===a?"2px":"1px",fontWeight:f===a?600:400,textAlign:"left"},children:a},p))})}if(n.type==="rating"){const c=n.maxStars||5;return t.jsx("div",{style:{display:"flex",gap:"12px",justifyContent:"flex-start"},children:Array.from({length:c}).map((a,p)=>t.jsx("button",{onClick:()=>b(p+1),style:{fontSize:"34px",background:"none",border:"none",cursor:"pointer",color:(f||0)>p?"#000":"#e2e8f0",padding:0},children:"★"},p))})}if(n.type==="rating_emoji"){const c=["😡","🙁","😐","🙂","😍"];return t.jsx("div",{style:{display:"flex",gap:"12px",justifyContent:"flex-start"},children:c.map((a,p)=>t.jsx("span",{onClick:()=>b(p+1),style:{fontSize:"28px",cursor:"pointer",opacity:f===p+1?1:.3,filter:f===p+1?"grayscale(0)":"grayscale(1)",transform:f===p+1?"scale(1.2)":"scale(1)",transition:"all 0.2s"},children:a},p))})}return n.type==="nps"?t.jsxs("div",{children:[t.jsx("div",{style:{display:"flex",justifyContent:"space-between",border:"1px solid #e2e8f0",borderRadius:"8px",padding:"4px"},children:Array.from({length:11}).map((c,a)=>t.jsx("div",{onClick:()=>b(a),style:{flex:1,textAlign:"center",padding:"8px 0",fontSize:"12px",fontWeight:600,cursor:"pointer",borderRadius:"4px",background:f===a?"#000":"transparent",color:f===a?"#fff":"#1e293b"},children:a},a))}),t.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:"10px",color:"#94a3b8",marginTop:"8px"},children:[t.jsx("span",{children:"Nada provável"}),t.jsx("span",{children:"Muito provável"})]})]}):n.type==="long_text"?t.jsx("textarea",{autoFocus:!0,value:f||"",onChange:c=>b(c.target.value),placeholder:"Escreva a sua resposta detalhada...",style:{width:"100%",padding:"12px",border:"1px solid #e2e8f0",borderRadius:"8px",fontSize:"14px",fontFamily:"inherit",minHeight:"100px",boxSizing:"border-box"}}):t.jsx("input",{autoFocus:!0,type:"text",value:f||"",onChange:c=>b(c.target.value),placeholder:"Escreva aqui...",style:{width:"100%",padding:"12px",border:"1px solid #e2e8f0",borderRadius:"8px",fontSize:"14px",fontFamily:"inherit",boxSizing:"border-box"}})},L=h==="modal"?{position:"fixed",bottom:"20px",right:"20px",width:"360px",maxHeight:"85vh",boxShadow:"0 15px 45px rgba(0,0,0,0.15)",borderRadius:"16px",zIndex:9999990,background:"#fff",border:"1px solid rgba(0,0,0,0.1)",display:"flex",flexDirection:"column",overflow:"hidden",fontFamily:"'Inter', -apple-system, sans-serif"}:{width:"100%",background:"#fff",border:"1px solid rgba(0,0,0,0.1)",borderRadius:"12px",display:"flex",flexDirection:"column",overflow:"hidden",fontFamily:"'Inter', -apple-system, sans-serif"};return t.jsxs("div",{className:"survo-react-widget",style:L,children:[t.jsxs("div",{style:{padding:"16px",background:"#fff",borderBottom:"1px solid #f1f5f9",display:"flex",justifyContent:"space-between",alignItems:"center"},children:[t.jsx("span",{style:{fontWeight:700,fontSize:"14px",color:"#000",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:i?.title||"Carregando..."}),h==="modal"&&t.jsx("button",{onClick:()=>_(!1),style:{background:"none",border:"none",cursor:"pointer",color:"#000",fontSize:"24px",lineHeight:1,padding:"4px"},children:"×"})]}),t.jsx("div",{style:{padding:"24px",overflowY:"auto"},children:D()}),t.jsxs("div",{style:{padding:"10px",textAlign:"center",fontSize:"10px",color:"#94a3b8",background:"#fff",borderTop:"1px solid #f1f5f9"},children:["Disponibilizado pelo ",t.jsx("a",{href:"https://survo.digital",target:"_blank",rel:"noopener noreferrer",style:{color:"#64748b",fontWeight:700,textDecoration:"none"},children:"Survo"})]})]})};v.SurvoWidget=ne,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"})}));
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "survo-react-widget",
3
+ "version": "1.0.0",
4
+ "description": "Native React widget for Survo surveys — embed beautiful survey forms in your React app",
5
+ "type": "module",
6
+ "main": "./dist/survo-react.umd.js",
7
+ "module": "./dist/survo-react.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/survo-react.es.js",
13
+ "require": "./dist/survo-react.umd.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "vite build && tsc -p tsconfig.build.json",
23
+ "preview": "vite preview",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "peerDependencies": {
27
+ "react": ">=16.8.0",
28
+ "react-dom": ">=16.8.0"
29
+ },
30
+ "keywords": [
31
+ "survo",
32
+ "survey",
33
+ "widget",
34
+ "react",
35
+ "form",
36
+ "feedback"
37
+ ],
38
+ "author": "Survo Digital",
39
+ "license": "MIT",
40
+ "homepage": "https://survo.digital",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/survo-digital/survo-react"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^25.2.3",
47
+ "@types/react": "^19.2.14",
48
+ "@types/react-dom": "^19.2.3",
49
+ "@vitejs/plugin-react": "^5.1.4",
50
+ "typescript": "^5.9.3",
51
+ "vite": "^7.3.1"
52
+ }
53
+ }