UNPKG

customersay-widget

Version:

A plug-and-play feedback widget for React/Next.js applications with smart triggers and analytics

632 lines (631 loc) 39.4 kB
"use client"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; var FeedbackWidget = function (_a) { var _b; var workspace = _a.workspace, _c = _a.apiBase, apiBase = _c === void 0 ? "https://customersay.xyz/api" : _c, onFeedbackSubmit = _a.onFeedbackSubmit, onWidgetShow = _a.onWidgetShow, onWidgetHide = _a.onWidgetHide, className = _a.className, style = _a.style, _d = _a.autoLoad, autoLoad = _d === void 0 ? true : _d, _e = _a.position, position = _e === void 0 ? 'bottom-right' : _e; var _f = useState(null), config = _f[0], setConfig = _f[1]; var _g = useState(true), loading = _g[0], setLoading = _g[1]; var _h = useState({}), answers = _h[0], setAnswers = _h[1]; var _j = useState(false), submitted = _j[0], setSubmitted = _j[1]; var _k = useState(false), showOverlay = _k[0], setShowOverlay = _k[1]; var _l = useState(false), shouldShow = _l[0], setShouldShow = _l[1]; var _m = useState(false), showOverlayWidget = _m[0], setShowOverlayWidget = _m[1]; var _o = useState(false), showFeedbackPrompt = _o[0], setShowFeedbackPrompt = _o[1]; var _p = useState(true), showFloatingButton = _p[0], setShowFloatingButton = _p[1]; // Start with true, will be controlled by triggers var _q = useState(false), submitting = _q[0], setSubmitting = _q[1]; var _r = useState(null), error = _r[0], setError = _r[1]; var _s = useState(null), discountCode = _s[0], setDiscountCode = _s[1]; var _t = useState('manual'), triggeredBy = _t[0], setTriggeredBy = _t[1]; var _u = useState(false), hasInteracted = _u[0], setHasInteracted = _u[1]; useEffect(function () { if (!workspace || !autoLoad) return; var fetchConfig = function () { return __awaiter(void 0, void 0, void 0, function () { var res, data, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); return [4 /*yield*/, fetch("".concat(apiBase, "/widget-config?site_id=").concat(workspace))]; case 1: res = _a.sent(); if (!res.ok) { throw new Error("HTTP error! status: ".concat(res.status)); } return [4 /*yield*/, res.json()]; case 2: data = _a.sent(); setConfig(__assign(__assign({}, data.config), { discount_enabled: data.discount_enabled, discount_code: data.discount_code })); setLoading(false); return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); console.error('Failed to load widget config:', error_1); setLoading(false); setConfig({ title: 'Feedback', questions: [ { id: 'rating', type: 'rating', label: 'How would you rate your experience?', max: 5 }, { id: 'feedback', type: 'text', label: 'Any additional feedback?', rows: 3 } ], discount_enabled: false, displayMode: 'overlay', colors: { background: '#ffffff', button: '#1976d2', buttonText: '#ffffff', fieldBackground: '#ffffff', fieldText: '#000000', titleText: '#000000', labelText: '#000000', floatingButton: '#1976d2', floatingButtonIcon: '💬' }, triggers: {} }); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; fetchConfig(); }, [workspace, apiBase, autoLoad]); // Trigger logic useEffect(function () { var _a, _b, _c, _d, _e, _f, _g, _h; console.log('🔍 Trigger useEffect called:', { config: !!config, loading: loading, workspace: workspace }); if (!config || loading) { console.log('❌ Early return - no config or loading'); return; } var triggers = config.triggers || {}; console.log('📋 Triggers config:', triggers); // Check if widget was dismissed var isDismissed = localStorage.getItem("feedback_widget_dismissed_".concat(workspace)); console.log('🚫 Dismissed check:', isDismissed); if (isDismissed === 'true') { console.log('❌ Widget dismissed, returning'); return; } // Check if user has already interacted with widget in this session console.log('🤝 Has interacted check:', hasInteracted); if (hasInteracted) { console.log('❌ User already interacted, no more triggers'); return; } var cleanups = []; // Page Load Delay - controls floating button appearance if ((_a = triggers.pageLoadDelay) === null || _a === void 0 ? void 0 : _a.enabled) { console.log('⏰ Page Load Delay enabled:', triggers.pageLoadDelay); setShowFloatingButton(false); // Hide button initially var timeout_1 = setTimeout(function () { console.log('⏰ Page Load Delay timeout fired'); if (localStorage.getItem("feedback_widget_dismissed_".concat(workspace)) === 'true') { console.log('❌ Widget dismissed during page load delay'); return; } console.log('✅ Setting page load delay trigger'); setTriggeredBy('page_load_delay'); setShowFloatingButton(true); // Show button after delay }, (triggers.pageLoadDelay.delay || 5) * 1000); cleanups.push(function () { return clearTimeout(timeout_1); }); } // Time on Page - shows feedback prompt after time if ((_b = triggers.timeOnPage) === null || _b === void 0 ? void 0 : _b.enabled) { console.log('⏱️ Time on Page enabled:', triggers.timeOnPage); var timeout_2 = setTimeout(function () { console.log('⏱️ Time on Page timeout fired'); if (localStorage.getItem("feedback_widget_dismissed_".concat(workspace)) === 'true') { console.log('❌ Widget dismissed during time on page'); return; } console.log('✅ Setting time on page trigger'); setTriggeredBy('time_on_page'); setShowFeedbackPrompt(true); }, (triggers.timeOnPage.seconds || 30) * 1000); cleanups.push(function () { return clearTimeout(timeout_2); }); } // Scroll Percentage - shows feedback prompt on scroll if ((_c = triggers.scrollPercentage) === null || _c === void 0 ? void 0 : _c.enabled) { console.log('📜 Scroll Percentage enabled:', triggers.scrollPercentage); var handleScroll_1 = function () { var _a, _b; if (localStorage.getItem("feedback_widget_dismissed_".concat(workspace)) === 'true') { console.log('❌ Widget dismissed during scroll'); return; } var scrollPercent = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100; console.log('📜 Scroll percent:', scrollPercent, 'target:', ((_a = triggers.scrollPercentage) === null || _a === void 0 ? void 0 : _a.percentage) || 50); if (scrollPercent >= (((_b = triggers.scrollPercentage) === null || _b === void 0 ? void 0 : _b.percentage) || 50)) { console.log('✅ Setting scroll percentage trigger'); setTriggeredBy('scroll_percentage'); setShowFeedbackPrompt(true); window.removeEventListener('scroll', handleScroll_1); } }; window.addEventListener('scroll', handleScroll_1); cleanups.push(function () { return window.removeEventListener('scroll', handleScroll_1); }); } // Visit Count - shows feedback prompt after X visits if ((_d = triggers.visitCount) === null || _d === void 0 ? void 0 : _d.enabled) { console.log('👥 Visit Count enabled:', triggers.visitCount); var visitKey = "feedback_widget_visits_".concat(workspace); var currentVisits = parseInt(localStorage.getItem(visitKey) || '0') + 1; localStorage.setItem(visitKey, currentVisits.toString()); console.log('👥 Current visits:', currentVisits, 'target:', ((_e = triggers.visitCount) === null || _e === void 0 ? void 0 : _e.count) || 3); if (currentVisits >= (((_f = triggers.visitCount) === null || _f === void 0 ? void 0 : _f.count) || 3)) { console.log('✅ Setting visit count trigger'); setTriggeredBy('visit_count'); setShowFeedbackPrompt(true); } } // Exit Intent - shows feedback prompt when mouse leaves if ((_g = triggers.exitIntent) === null || _g === void 0 ? void 0 : _g.enabled) { console.log('🚪 Exit Intent enabled:', triggers.exitIntent); var handleMouseLeave_1 = function (e) { console.log('🚪 Mouse leave event:', e.clientY); if (e.clientY <= 0) { if (localStorage.getItem("feedback_widget_dismissed_".concat(workspace)) === 'true') { console.log('❌ Widget dismissed during exit intent'); return; } if (sessionStorage.getItem("exit_intent_triggered_".concat(workspace)) === 'true') { console.log('❌ Exit intent already triggered'); return; } console.log('✅ Setting exit intent trigger'); setTimeout(function () { setTriggeredBy('exit_intent'); setShowFeedbackPrompt(true); sessionStorage.setItem("exit_intent_triggered_".concat(workspace), 'true'); }, triggers.exitIntent.delay || 150); } }; document.addEventListener('mouseleave', handleMouseLeave_1); cleanups.push(function () { return document.removeEventListener('mouseleave', handleMouseLeave_1); }); } // Idle Time - shows feedback prompt after idle if ((_h = triggers.idleTime) === null || _h === void 0 ? void 0 : _h.enabled) { console.log('😴 Idle Time enabled:', triggers.idleTime); var idleTimer_1; var resetIdleTimer_1 = function () { var _a; clearTimeout(idleTimer_1); idleTimer_1 = setTimeout(function () { console.log('😴 Idle timer fired'); if (localStorage.getItem("feedback_widget_dismissed_".concat(workspace)) === 'true') { console.log('❌ Widget dismissed during idle'); return; } console.log('✅ Setting idle time trigger'); setTriggeredBy('idle_time'); setShowFeedbackPrompt(true); }, (((_a = triggers.idleTime) === null || _a === void 0 ? void 0 : _a.seconds) || 60) * 1000); }; var events_1 = ['mousemove', 'mousedown', 'keypress', 'scroll', 'touchstart', 'click']; events_1.forEach(function (event) { return document.addEventListener(event, resetIdleTimer_1); }); resetIdleTimer_1(); cleanups.push(function () { clearTimeout(idleTimer_1); events_1.forEach(function (event) { return document.removeEventListener(event, resetIdleTimer_1); }); }); } return function () { cleanups.forEach(function (cleanup) { return cleanup(); }); }; }, [config, loading, workspace]); var handleChange = function (id, value) { setAnswers(function (prev) { var _a; return (__assign(__assign({}, prev), (_a = {}, _a[id] = value, _a))); }); }; var normalizeRating = function (rating, maxRating) { return Math.round((rating / maxRating) * 10); }; var handleSubmit = function (e) { return __awaiter(void 0, void 0, void 0, function () { var featureRequest, featureQuestion, response, responseData, error_2; return __generator(this, function (_a) { switch (_a.label) { case 0: e.preventDefault(); setSubmitting(true); _a.label = 1; case 1: _a.trys.push([1, 6, 7, 8]); featureRequest = null; if (config === null || config === void 0 ? void 0 : config.questions) { featureQuestion = config.questions.find(function (q) { return q.type === 'FeatureRequest'; }); if (featureQuestion && answers[featureQuestion.id]) { featureRequest = answers[featureQuestion.id]; } } return [4 /*yield*/, fetch("".concat(apiBase, "/submit-feedback"), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ workspace: workspace, answers: Object.fromEntries(Object.entries(answers).map(function (_a) { var _b; var key = _a[0], value = _a[1]; // Normalize ratings to 1-10 scale var question = (_b = config === null || config === void 0 ? void 0 : config.questions) === null || _b === void 0 ? void 0 : _b.find(function (q) { return q.id === key; }); if ((question === null || question === void 0 ? void 0 : question.type) === 'rating' && typeof value === 'number') { return [key, normalizeRating(value, question.max || 5)]; } return [key, value]; })), page_url: window.location.href, user_agent: navigator.userAgent, referrer: document.referrer, triggered_by: triggeredBy, feature_request: featureRequest }) })]; case 2: response = _a.sent(); if (!response.ok) return [3 /*break*/, 4]; return [4 /*yield*/, response.json()]; case 3: responseData = _a.sent(); setSubmitted(true); onFeedbackSubmit === null || onFeedbackSubmit === void 0 ? void 0 : onFeedbackSubmit(__assign(__assign({}, answers), { discount_code: responseData.discount_code })); // Show discount code if available if (responseData.discount_code) { setDiscountCode(responseData.discount_code); } return [3 /*break*/, 5]; case 4: throw new Error('Failed to submit feedback'); case 5: return [3 /*break*/, 8]; case 6: error_2 = _a.sent(); console.error('Error submitting feedback:', error_2); setError('Failed to submit feedback. Please try again.'); return [3 /*break*/, 8]; case 7: setSubmitting(false); return [7 /*endfinally*/]; case 8: return [2 /*return*/]; } }); }); }; var handleClose = function () { console.log('❌ Widget closed'); setShowOverlay(false); setShowOverlayWidget(false); setShowFeedbackPrompt(false); setShouldShow(false); // Don't hide the floating button - it should stay visible onWidgetHide === null || onWidgetHide === void 0 ? void 0 : onWidgetHide(); }; var showWidget = function () { console.log('🖱️ Manual widget click'); setTriggeredBy('manual'); setHasInteracted(true); // Mark as interacted // Manual clicks go directly to the form setShowOverlayWidget(true); onWidgetShow === null || onWidgetShow === void 0 ? void 0 : onWidgetShow(); }; var colors = (config === null || config === void 0 ? void 0 : config.colors) || {}; // Position styles for floating button var getPositionStyles = function () { var baseStyles = { position: 'fixed', zIndex: 9999, }; switch (position) { case 'bottom-left': return __assign(__assign({}, baseStyles), { bottom: '20px', left: '20px' }); case 'top-right': return __assign(__assign({}, baseStyles), { top: '20px', right: '20px' }); case 'top-left': return __assign(__assign({}, baseStyles), { top: '20px', left: '20px' }); default: // bottom-right return __assign(__assign({}, baseStyles), { bottom: '20px', right: '20px' }); } }; // Position styles for widget popup var getWidgetPositionStyles = function () { var baseStyles = { position: 'fixed', zIndex: 10000, }; switch (position) { case 'bottom-left': return __assign(__assign({}, baseStyles), { bottom: '90px', left: '20px' }); case 'top-right': return __assign(__assign({}, baseStyles), { top: '90px', right: '20px' }); case 'top-left': return __assign(__assign({}, baseStyles), { top: '90px', left: '20px' }); default: // bottom-right return __assign(__assign({}, baseStyles), { bottom: '90px', right: '20px' }); } }; if (loading) { return null; // Don't show anything while loading } if (!config) { return null; // Don't show anything if no config } // Floating button var floatingButton = showFloatingButton ? (_jsx("div", { onClick: showWidget, style: __assign(__assign({ width: 60, height: 60, borderRadius: '50%', background: colors.floatingButton || '#1976d2', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 24, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.15)', transition: 'transform 0.2s', border: 'none' }, getPositionStyles()), style), className: className, children: colors.floatingButtonIcon || '💬' })) : null; // Widget form var widgetForm = (_jsx("div", { className: "feedback-widget-scroll", style: __assign({ maxWidth: '350px', width: '320px', maxHeight: '400px', overflow: 'auto' }, getWidgetPositionStyles()), children: _jsx("div", { style: { background: colors.background || '#fff', borderRadius: 16, boxShadow: '0 8px 32px rgba(0,0,0,0.15)', border: '1px solid #e0e0e0', padding: 24, fontFamily: 'Inter, Arial, sans-serif' }, children: submitted ? (_jsxs("div", { style: { textAlign: 'center' }, children: [_jsx("div", { style: { fontSize: 48, marginBottom: 16 }, children: "\uD83C\uDF89" }), _jsx("h3", { style: { color: colors.titleText || '#222', marginBottom: 16 }, children: "Thank you for your feedback!" }), discountCode && (_jsx("div", { style: { background: '#f0f8ff', padding: 16, borderRadius: 8, marginBottom: 16 }, children: _jsxs("p", { style: { margin: 0, color: '#1976d2' }, children: ["Use code: ", _jsx("strong", { children: discountCode })] }) })), _jsx("button", { onClick: handleClose, style: { background: colors.button || '#1976d2', color: colors.buttonText || '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '12px 24px', fontWeight: 600, fontSize: 16, cursor: 'pointer' }, children: "Close" })] })) : (_jsxs("form", { onSubmit: handleSubmit, children: [config.showHeader && (_jsxs("div", { style: { background: colors.headerBackground || '#1976d2', margin: -24, marginBottom: 24, padding: 20, borderRadius: '16px 16px 0 0', display: 'flex', alignItems: 'center', gap: 12 }, children: [config.showBrandLogo && config.brandLogo && (_jsx("img", { src: config.brandLogo, alt: "Logo", style: { width: 32, height: 32, borderRadius: 4 } })), config.showBrandName && config.brandName && (_jsx("span", { style: { color: colors.brandNameColor || '#fff', fontWeight: 600, fontSize: 18 }, children: config.brandName }))] })), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }, children: [_jsx("h3", { style: { color: colors.titleText || '#222', fontSize: 20, fontWeight: 600, margin: 0 }, children: config.title }), _jsx("button", { onClick: handleClose, style: { background: 'none', border: 'none', fontSize: 20, cursor: 'pointer', color: '#666', padding: 4, borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center' }, title: "Close", children: "\u2715" })] }), (_b = config.questions) === null || _b === void 0 ? void 0 : _b.map(function (question) { return (_jsxs("div", { style: { marginBottom: 20 }, children: [_jsx("label", { style: { display: 'block', marginBottom: 8, fontWeight: 500, color: colors.labelText || '#333', fontSize: 14 }, children: question.label }), question.type === 'rating' && (_jsx("div", { style: { display: 'flex', gap: 4 }, children: Array.from({ length: question.max || 5 }, function (_, i) { return (_jsx("button", { type: "button", onClick: function () { return handleChange(question.id, i + 1); }, style: { background: 'none', border: 'none', fontSize: 24, color: (answers[question.id] || 0) >= i + 1 ? '#ffd700' : '#ddd', cursor: 'pointer', padding: 4 }, children: "\u2605" }, i + 1)); }) })), question.type === 'text' && (_jsx("textarea", { value: answers[question.id] || '', onChange: function (e) { return handleChange(question.id, e.target.value); }, rows: question.rows || 3, placeholder: "Your feedback...", style: { width: '100%', padding: 12, borderRadius: 8, border: '1px solid #ddd', background: colors.fieldBackground || '#fff', color: colors.fieldText || '#333', fontSize: 14, fontFamily: 'inherit', resize: 'vertical' } })), question.type === 'FeatureRequest' && (_jsx("textarea", { value: answers[question.id] || '', onChange: function (e) { return handleChange(question.id, e.target.value); }, rows: 3, placeholder: "Describe the feature you'd like to see...", style: { width: '100%', padding: 12, borderRadius: 8, border: '1px solid #ddd', background: colors.fieldBackground || '#fff', color: colors.fieldText || '#333', fontSize: 14, fontFamily: 'inherit', resize: 'vertical' } }))] }, question.id)); }), error && (_jsx("div", { style: { color: '#d32f2f', marginBottom: 16, fontSize: 14 }, children: error })), _jsxs("div", { style: { display: 'flex', gap: 12 }, children: [_jsx("button", { type: "submit", disabled: submitting, style: { background: colors.button || '#1976d2', color: colors.buttonText || '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '12px 24px', fontWeight: 600, fontSize: 16, cursor: submitting ? 'not-allowed' : 'pointer', opacity: submitting ? 0.7 : 1 }, children: submitting ? 'Submitting...' : 'Submit Feedback' }), _jsx("button", { type: "button", onClick: handleClose, style: { background: '#6c757d', color: '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '12px 24px', fontWeight: 600, fontSize: 16, cursor: 'pointer' }, children: "Cancel" })] })] })) }) })); // Overlay mode if (config.displayMode === 'overlay') { return (_jsxs(_Fragment, { children: [_jsx("style", { children: "\n .feedback-widget-scroll::-webkit-scrollbar {\n width: 6px;\n }\n .feedback-widget-scroll::-webkit-scrollbar-track {\n background: transparent;\n }\n .feedback-widget-scroll::-webkit-scrollbar-thumb {\n background: #c1c1c1;\n border-radius: 3px;\n }\n .feedback-widget-scroll::-webkit-scrollbar-thumb:hover {\n background: #a8a8a8;\n }\n .feedback-widget-scroll {\n scrollbar-width: thin;\n scrollbar-color: #c1c1c1 transparent;\n }\n " }), floatingButton, showOverlayWidget && widgetForm, console.log('🎯 Rendering feedback prompt:', showFeedbackPrompt), showFeedbackPrompt && (_jsx("div", { style: __assign({ maxWidth: '280px', width: '280px' }, getWidgetPositionStyles()), children: _jsxs("div", { style: { background: colors.background || '#fff', border: '1px solid #e0e0e0', borderRadius: 16, boxShadow: '0 8px 32px rgba(0,0,0,0.15)', padding: 20, fontFamily: 'Inter, Arial, sans-serif', }, children: [_jsx("div", { style: { fontWeight: 600, fontSize: 16, color: colors.titleText || '#222', marginBottom: 16, textAlign: 'center', }, children: "Would you like to give feedback?" }), _jsxs("div", { style: { display: 'flex', gap: 8, justifyContent: 'center', }, children: [_jsx("button", { onClick: function () { setShowFeedbackPrompt(false); setHasInteracted(true); // Mark as interacted setShowOverlayWidget(true); }, style: { background: colors.button || '#1976d2', color: colors.buttonText || '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '8px 16px', fontWeight: 600, fontSize: 14, cursor: 'pointer' }, children: "Yes" }), _jsx("button", { onClick: function () { setShowFeedbackPrompt(false); setHasInteracted(true); // Mark as interacted localStorage.setItem("feedback_widget_dismissed_".concat(workspace), 'true'); }, style: { background: '#6c757d', color: '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '8px 16px', fontWeight: 600, fontSize: 14, cursor: 'pointer' }, children: "No" })] })] }) }))] })); } // Inline mode if (config.displayMode === 'inline') { return (_jsxs(_Fragment, { children: [showFeedbackPrompt && (_jsx("div", { style: { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', zIndex: 10000, maxWidth: '280px', width: 'fit-content', }, children: _jsxs("div", { style: { background: colors.background || '#fff', border: '1px solid #e0e0e0', borderRadius: 16, boxShadow: '0 8px 32px rgba(0,0,0,0.15)', padding: 20, fontFamily: 'Inter, Arial, sans-serif', }, children: [_jsx("div", { style: { fontWeight: 600, fontSize: 16, color: colors.titleText || '#222', marginBottom: 16, textAlign: 'center', }, children: "Would you like to give feedback?" }), _jsxs("div", { style: { display: 'flex', gap: 8, justifyContent: 'center', }, children: [_jsx("button", { onClick: function () { setShowFeedbackPrompt(false); setHasInteracted(true); // Mark as interacted setShouldShow(true); }, style: { background: colors.button || '#1976d2', color: colors.buttonText || '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '8px 16px', fontWeight: 600, fontSize: 14, cursor: 'pointer' }, children: "Yes" }), _jsx("button", { onClick: function () { setShowFeedbackPrompt(false); setHasInteracted(true); // Mark as interacted localStorage.setItem("feedback_widget_dismissed_".concat(workspace), 'true'); }, style: { background: '#6c757d', color: '#fff', border: '1px solid #a0a0a0', borderBottom: '3px solid #a0a0a0', borderRadius: 8, padding: '8px 16px', fontWeight: 600, fontSize: 14, cursor: 'pointer' }, children: "No" })] })] }) })), shouldShow && widgetForm] })); } // Default fallback - just show the floating button return floatingButton; }; export default FeedbackWidget; // Export for Next.js/React usage export { FeedbackWidget }; // UMD global export for script tag usage (backward compatibility) if (typeof window !== 'undefined') { window.FeedbackWidget = FeedbackWidget; }