UNPKG

feedaura

Version:

Feedaura is a smart feedback collection tool that helps you gather, analyze, and manage user feedback efficiently.

1 lines 66.6 kB
{"version":3,"file":"index.mjs","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/style-inject/dist/style-inject.es.js","../src/utils/types.ts","../src/utils/collect-metadata.ts","../src/components/Feedback/components/Model.tsx","../src/components/Feedback/components/EmojiSelector.tsx","../src/components/Feedback/components/FeedbackTextArea.tsx","../src/components/Feedback/components/SubmitButton.tsx","../src/components/Feedback/components/Logo.tsx","../src/components/Feedback/components/PoweredByFeedaura.tsx","../src/components/Feedback/components/FeedbackForm.tsx","../src/components/Feedback/components/icons/FeedbackIcon.tsx","../src/components/Feedback/components/icons/MessageIcon.tsx","../src/components/Feedback/components/icons/ChatIcon.tsx","../src/components/Feedback/components/icons/FeedauraIcon.tsx","../src/components/Feedback/FeedbackWidget.tsx","../src/hooks/useLocalStorage.tsx","../src/hooks/useModel.tsx"],"sourcesContent":["/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n 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);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n 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;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","// Types for the component props\nexport type Position =\n | \"bottom-right\"\n | \"bottom-left\"\n | \"top-right\"\n | \"top-left\";\nexport type ButtonSize = \"small\" | \"medium\" | \"large\";\nexport type Theme = \"light\" | \"dark\";\nexport type ButtonIcon = \"feedback\" | \"chat\" | \"message\" | \"feedaura\" | \"none\";\nexport type WidgetStyle = \"floating\" | \"minimal\" | \"solid\";\n\nexport interface FeedbackProps {\n projectSecret?: string;\n position?: Position;\n primaryColor?: string;\n secondaryColor?: string;\n textColor?: string;\n backgroundColor?: string;\n theme?: Theme;\n buttonText?: string;\n buttonIcon?: ButtonIcon;\n iconColor?: string;\n buttonSize?: ButtonSize;\n buttonRadius?: string;\n widgetStyle?: WidgetStyle;\n zIndex?: number;\n autoCloseAfterSubmit?: boolean;\n apiEndpoint?: string;\n animated?: boolean;\n productName?: string;\n placeholder?: string;\n submitText?: string;\n headerText?: string;\n questionText?: string;\n feedbackLabelText?: string;\n}\n\nexport interface IconProps {\n size?: number;\n color?: string;\n animated?: boolean;\n}\n\n// src/components/Feedback.tsx\n\n// → make icons a bit larger\nexport const ICON_SIZE_MAP: Record<ButtonSize, number> = {\n small: 24,\n medium: 32,\n large: 40,\n};\n","const getBrowserInfo = () => {\n if (typeof navigator === 'undefined') return \"Unknown\";\n \n const userAgent = navigator.userAgent;\n let browser = \"Unknown\";\n \n if (userAgent.includes(\"Firefox\")) {\n browser = \"Firefox\";\n } else if (userAgent.includes(\"Edg/\")) {\n browser = \"Edge\";\n } else if (userAgent.includes(\"OPR\") || userAgent.includes(\"Opera\")) {\n browser = \"Opera\";\n } else if (userAgent.includes(\"Chrome\")) {\n browser = \"Chrome\";\n } else if (userAgent.includes(\"Safari\")) {\n browser = \"Safari\";\n } else if (userAgent.includes(\"Trident\") || userAgent.includes(\"MSIE\")) {\n browser = \"Internet Explorer\";\n }\n \n return browser;\n};\n\nconst getDeviceInfo = () => {\n if (typeof navigator === 'undefined') return \"Unknown\";\n \n const userAgent = navigator.userAgent;\n \n // Check for mobile devices\n if (/Android/i.test(userAgent)) {\n return \"Android\";\n } else if (/iPhone|iPad|iPod/i.test(userAgent)) {\n return (/iPad/i.test(userAgent)) ? \"iPad\" : (/iPod/i.test(userAgent) ? \"iPod\" : \"iPhone\");\n } else if (/Windows Phone/i.test(userAgent)) {\n return \"Windows Phone\";\n }\n \n // Check for desktop operating systems\n if (/Windows/i.test(userAgent)) {\n return \"Windows\";\n } else if (/Macintosh/i.test(userAgent)) {\n return \"Mac\";\n } else if (/Linux/i.test(userAgent)) {\n return \"Linux\";\n }\n \n return \"Unknown\";\n};\n\nexport const collectUserMetadata = async () => {\n try {\n // Fetch country information\n const countryResponse = await fetch(\"https://ipapi.co/json/\");\n const countryData = await countryResponse.json();\n \n return {\n country: countryData.country_name || \"Unknown\", // Full country name\n countryCode: countryData.country || \"Unknown\", // Two-letter country code\n device: getDeviceInfo(),\n browser: getBrowserInfo(),\n url: window.location.href,\n referrer: document.referrer,\n };\n } catch (error) {\n console.error(\"Error fetching country data:\", error);\n return {\n country: \"Unknown\",\n countryCode: \"Unknown\",\n device: getDeviceInfo(),\n browser: getBrowserInfo(),\n url: window.location.href,\n referrer: document.referrer,\n };\n }\n};","import React from \"react\";\n\ninterface ModalProps {\n isOpen: boolean;\n modalAnimation: string;\n onClose: () => void;\n // Allow null for the ref.\n modalRef: React.RefObject<HTMLDivElement | null>;\n children: React.ReactNode;\n headerText:string;\n}\n\nconst Modal: React.FC<ModalProps> = ({ isOpen, modalAnimation, onClose, modalRef, children,headerText }) => {\n if (!isOpen) return null;\n\n return (\n <div className={`feedback-modal ${modalAnimation}`} ref={modalRef} role=\"dialog\" aria-modal=\"true\">\n <div className=\"feedback-header\">\n <h3 id=\"feedback-header\">{headerText}</h3>\n <button className=\"close-button\" onClick={onClose} aria-label=\"Close feedback form\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M18 6L6 18\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M6 6L18 18\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n <div className=\"feedback-content\">{children}</div>\n </div>\n );\n};\n\nexport default Modal;\n","import React from \"react\";\n\nexport interface Emoji {\n icon: string;\n label: string;\n value: string;\n}\n\ninterface EmojiSelectorProps {\n selectedEmoji: string;\n onSelectEmoji: (value: string) => void;\n}\n\nconst emojis: Emoji[] = [\n { icon: \"😭\", label: \"Dissatisfied\", value: \"dissatisfied\" },\n { icon: \"😔\", label: \"Somewhat Dissatisfied\", value: \"somewhat_dissatisfied\" },\n { icon: \"😐\", label: \"Neutral\", value: \"neutral\" },\n { icon: \"🙂\", label: \"Somewhat Satisfied\", value: \"somewhat_satisfied\" },\n { icon: \"🤩\", label: \"Satisfied\", value: \"satisfied\" },\n];\n\nconst EmojiSelector: React.FC<EmojiSelectorProps> = ({ selectedEmoji, onSelectEmoji }) => {\n return (\n <div className=\"feedback-emojis\">\n {emojis.map((emoji) => (\n <button\n key={emoji.value}\n type=\"button\"\n className={`emoji-button ${selectedEmoji === emoji.value ? \"active\" : \"\"}`}\n onClick={() => onSelectEmoji(selectedEmoji === emoji.value ? \"\" : emoji.value)}\n aria-label={emoji.label}\n >\n <span className=\"emoji-icon\">{emoji.icon}</span>\n <span className=\"emoji-label\">\n {emoji.label === \"Somewhat Dissatisfied\"\n ? \"Dissatisfied\"\n : emoji.label === \"Somewhat Satisfied\"\n ? \"Satisfied\"\n : emoji.label}\n </span>\n </button>\n ))}\n </div>\n );\n};\n\nexport default EmojiSelector;\n","import React from \"react\";\n\ninterface FeedbackTextAreaProps {\n value: string;\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n errorMsg: string;\n placeholder: string;\n label: string;\n}\n\nconst FeedbackTextArea: React.FC<FeedbackTextAreaProps> = ({ value, onChange, errorMsg, placeholder, label }) => {\n return (\n <div className=\"feedback-text-section\">\n <label htmlFor=\"feedback-text\">\n {label} <span className=\"required-text\">*</span>\n </label>\n <textarea\n id=\"feedback-text\"\n placeholder={placeholder}\n value={value}\n onChange={onChange}\n aria-label=\"Feedback text\"\n required\n />\n {errorMsg && <div className=\"error-message\">{errorMsg}</div>}\n </div>\n );\n};\n\nexport default FeedbackTextArea;\n","import React from \"react\";\n\ninterface SubmitButtonProps {\n isSubmitting: boolean;\n disabled: boolean;\n onClick: () => void;\n primaryColor: string;\n submitText: string;\n}\n\nconst SubmitButton: React.FC<SubmitButtonProps> = ({ isSubmitting, disabled, onClick, primaryColor, submitText }) => {\n return (\n <button className=\"submit-button\" onClick={onClick} disabled={disabled} style={{ backgroundColor: primaryColor }}>\n {isSubmitting ? <span className=\"loading-spinner\"></span> : submitText}\n </button>\n );\n};\n\nexport default SubmitButton;\n","const Logo = ({ size = 20, color = '#EF2101' }: { size?: number; color?: string }) => {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 56 56\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M31.5 7.23333C30.3333 7.23333 29.1667 7 28 7C26.8333 7 25.6667 7.23333 24.5 7.23333\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M45.0333 15.8666C43.6416 14.0083 41.9916 12.3583 40.1333 10.9666\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M48.7666 31.5C48.9999 30.3333 48.9999 29.1667 48.9999 28C48.9999 26.8333 48.7666 25.6667 48.7666 24.5\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M40.1333 45.0333C41.9916 43.6416 43.6416 41.9916 45.0333 40.1333\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M24.5 48.7666C25.6667 48.9999 26.8333 48.9999 28 48.9999C29.1667 48.9999 30.3333 48.7666 31.5 48.7666\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M8.1665 40.8333L4.6665 51.3333L15.1665 47.8333\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M7.23333 24.5C7.23333 25.6667 7 26.8333 7 28C7 29.1667 7.23333 30.3333 7.23333 31.5\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M15.8668 10.9666C14.0085 12.3583 12.3585 14.0083 10.9668 15.8666\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M39.3133 28.0001H36.5076C36.0132 27.9991 35.532 28.16 35.1377 28.4583C34.7434 28.7566 34.4577 29.1758 34.3242 29.6519L31.6656 39.1096C31.6485 39.1684 31.6127 39.22 31.5638 39.2567C31.5148 39.2934 31.4553 39.3133 31.3941 39.3133C31.3329 39.3133 31.2733 39.2934 31.2244 39.2567C31.1754 39.22 31.1397 39.1684 31.1226 39.1096L24.8777 16.8906C24.8606 16.8319 24.8249 16.7803 24.7759 16.7436C24.7269 16.7069 24.6674 16.687 24.6062 16.687C24.545 16.687 24.4855 16.7069 24.4365 16.7436C24.3876 16.7803 24.3518 16.8319 24.3347 16.8906L21.6761 26.3484C21.5431 26.8226 21.2591 27.2405 20.8671 27.5386C20.475 27.8367 19.9965 27.9987 19.504 28.0001H16.687\" stroke={color} strokeWidth=\"3.05455\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n };\n \n export default Logo;\n ","import Logo from './Logo';\n\nconst PoweredByFeedaura = ({ primaryColor }: { primaryColor: string }) => {\n return (\n <div className=\"powered-by-feedaura\">\n <Logo color={primaryColor} size={18} />\n <span>\n Powered by <span className=\"feedaura-highlight\"style={{color:primaryColor}}>Feedaura</span>\n </span>\n </div>\n );\n};\n\nexport default PoweredByFeedaura;\n","import React from \"react\";\nimport EmojiSelector from \"./EmojiSelector\";\nimport FeedbackTextArea from \"./FeedbackTextArea\";\nimport SubmitButton from \"./SubmitButton\";\nimport { countWords } from \"../../../utils/text\";\nimport PoweredByFeedaura from \"./PoweredByFeedaura\";\n\ninterface FeedbackFormProps {\n feedback: { text: string; emoji: string };\n setFeedback: React.Dispatch<React.SetStateAction<{ text: string; emoji: string }>>;\n errorMsg: string;\n setErrorMsg: React.Dispatch<React.SetStateAction<string>>;\n primaryColor: string;\n placeholder: string;\n feedbackLabel: string;\n submitText: string;\n isSubmitting: boolean;\n onSubmit: () => void;\n questionText: string;\n}\n\nconst FeedbackForm: React.FC<FeedbackFormProps> = ({\n feedback,\n setFeedback,\n errorMsg,\n setErrorMsg,\n placeholder,\n feedbackLabel,\n submitText,\n isSubmitting,\n onSubmit,\n questionText,\n primaryColor\n}) => {\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newText = e.target.value;\n\n if (newText.length > 200) {\n setErrorMsg(\"Feedback text cannot exceed 200 words.\");\n return;\n }\n setErrorMsg(\"\");\n setFeedback((prev) => ({ ...prev, text: newText }));\n };\n\n\n\n return (\n <>\n <div className=\"feedback-question\">\n <p>{questionText}</p>\n </div>\n <EmojiSelector\n selectedEmoji={feedback.emoji}\n onSelectEmoji={(value) =>\n setFeedback((prev) => ({ ...prev, emoji: prev.emoji === value ? \"\" : value }))\n }\n />\n <FeedbackTextArea\n value={feedback.text}\n onChange={handleTextChange}\n errorMsg={errorMsg}\n placeholder={placeholder}\n label={feedbackLabel}\n />\n <div className=\"feedback-actions\">\n <SubmitButton\n isSubmitting={isSubmitting}\n disabled={isSubmitting || !feedback.text.trim() || Boolean(errorMsg)}\n onClick={onSubmit}\n primaryColor={primaryColor}\n submitText={submitText}\n />\n </div>\n <PoweredByFeedaura primaryColor={primaryColor} />\n </>\n );\n};\n\nexport default FeedbackForm;\n","import { IconProps } from \"../../../../utils/types\";\n\nexport const FeedbackIcon: React.FC<IconProps> = ({\n size = 24,\n color = 'white',\n animated = false,\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={animated ? 'animated-icon' : undefined}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 11.5C21.0034 12.8199 20.6951 14.1219 20.1 15.3C19.3944 16.7118 18.3098 17.8992 16.9674 18.7293C15.6251 19.5594 14.0782 19.9994 12.5 20C11.1801 20.0035 9.87812 19.6951 8.7 19.1L3 21L4.9 15.3C4.30493 14.1219 3.99656 12.8199 4 11.5C4.00061 9.92179 4.44061 8.37488 5.27072 7.03258C6.10083 5.69028 7.28825 4.6056 8.7 3.90003C9.87812 3.30496 11.1801 2.99659 12.5 3.00003H13C15.0843 3.11502 17.053 3.99479 18.5291 5.47089C20.0052 6.94699 20.885 8.91568 21 11V11.5Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n","import React from 'react';\nimport { IconProps } from '../../../../utils/types';\n\nexport const MessageIcon: React.FC<IconProps> = ({\n size = 24,\n color = 'white',\n animated = false,\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={animated ? 'animated-icon' : undefined}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M4 4H20C21.1 4 22 4.9 22 6V18C22 19.1 21.1 20 20 20H4C2.9 20 2 19.1 2 18V6C2 4.9 2.9 4 4 4Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M22 6L12 13L2 6\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n","import React from 'react';\nimport { IconProps } from '../../../../utils/types';\n\nexport const ChatIcon: React.FC<IconProps> = ({\n size = 24,\n color = 'white',\n animated = false,\n}) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={animated ? 'animated-icon' : undefined}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M21 15C21 15.5304 20.7893 16.0391 20.4142 16.4142C20.0391 16.7893 19.5304 17 19 17H7L3 21V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H19C19.5304 3 20.0391 3.21071 20.4142 3.58579C20.7893 3.96086 21 4.46957 21 5V15Z\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n","// src/components/icons/FeedauraIcon.tsx\nimport React from 'react';\nimport Logo from '../Logo';\nimport { IconProps } from '../../../../utils/types';\n\nexport const FeedauraIcon: React.FC<IconProps> = ({\n size = 24,\n color = 'white',\n animated = false,\n}) => (\n <div className={animated ? 'animated-icon' : undefined} style={{ lineHeight: 0 }}>\n {/* Logo already accepts size & color */}\n <Logo size={size} color={color} />\n </div>\n);\n","import type React from \"react\";\nimport { useState, useEffect } from \"react\";\nimport \"./feedback-widget.css\";\nimport { FeedbackProps, ICON_SIZE_MAP } from \"../../utils/types\";\nimport { collectUserMetadata } from \"../../utils/collect-metadata\";\nimport { useLocalStorage } from \"../../hooks/useLocalStorage\";\nimport { useModal } from \"../../hooks/useModel\";\nimport Modal from \"./components/Model\";\nimport FeedbackForm from \"./components/FeedbackForm\";\nimport { FeedbackIcon } from \"./components/icons/FeedbackIcon\";\nimport { MessageIcon } from \"./components/icons/MessageIcon\";\nimport { ChatIcon } from \"./components/icons/ChatIcon\";\nimport { FeedauraIcon } from \"./components/icons/FeedauraIcon\";\n\nconst DEFAULT_API_ENDPOINT =\n process.env.NODE_ENV === \"production\"\n ? \"https://feedaura.feedaura-ai.workers.dev/feedbacks\"\n : \"http://localhost:8787/feedbacks\";\n\nconst LOCAL_STORAGE_KEY = \"feedback-widget-text\";\n\nconst Feedback: React.FC<FeedbackProps> = ({\n projectSecret,\n position = 'bottom-right',\n primaryColor = '#0F8CFF',\n secondaryColor = '#0070E0',\n textColor = '#333333',\n backgroundColor = '#FFFFFF',\n theme = 'light',\n buttonText = '',\n buttonIcon = 'feedaura',\n iconColor = '#FFFFFF',\n buttonSize = 'medium',\n buttonRadius = '50%',\n widgetStyle = 'floating',\n zIndex = 9999,\n autoCloseAfterSubmit = true,\n apiEndpoint = DEFAULT_API_ENDPOINT,\n animated = true,\n productName = 'product',\n placeholder = 'Please write here',\n submitText = 'Submit',\n headerText = 'Give us your feedback',\n questionText = `What was your experience while using ${productName}?`,\n feedbackLabelText = 'Write your feedback',\n}) => {\n const [feedback, setFeedback] = useState({ text: \"\", emoji: \"\" });\n const [errorMsg, setErrorMsg] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isSubmitted, setIsSubmitted] = useState(false);\n const [storedText, setStoredText] = useLocalStorage(LOCAL_STORAGE_KEY, \"\");\n const { isOpen, modalAnimation, openModal, closeModal, modalRef, triggerButtonRef } = useModal(() => setIsSubmitted(false));\n\n // Load saved feedback text on mount.\n useEffect(() => {\n if (storedText && feedback.text === \"\") {\n setFeedback((prev) => ({ ...prev, text: storedText }))\n }\n }, [])\n\n // Update local storage when feedback text changes.\n useEffect(() => {\n // Only update localStorage if the text has actually changed from what's stored\n if (feedback.text !== storedText) {\n setStoredText(feedback.text)\n }\n }, [feedback.text, setStoredText, storedText])\n\n // Auto-close modal after submission if enabled.\n useEffect(() => {\n if (isSubmitted && autoCloseAfterSubmit) {\n const timer = setTimeout(() => {\n closeModal();\n }, 3000);\n return () => clearTimeout(timer);\n }\n }, [isSubmitted, autoCloseAfterSubmit, closeModal]);\n\n const handleSubmit = async () => {\n if (!projectSecret) {\n setErrorMsg(\"Project secret is missing.\");\n return;\n }\n if (!apiEndpoint) {\n setErrorMsg(\"API endpoint is missing.\");\n return;\n }\n if (feedback.text.trim() === \"\") {\n setErrorMsg(\"Feedback text is required.\");\n return;\n }\n\n setErrorMsg(\"\");\n setIsSubmitting(true);\n try {\n const metadata = await collectUserMetadata();\n const feedbackData = {\n text: feedback.text,\n ...(feedback.emoji ? { emoji: feedback.emoji } : {}),\n };\n const response = await fetch(apiEndpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n projectSecret,\n feedback: feedbackData,\n metadata,\n }),\n });\n if (response.ok) {\n setIsSubmitted(true);\n setStoredText(\"\");\n setFeedback({ text: \"\", emoji: \"\" });\n } else {\n const errorData = await response.json();\n if (errorData?.code === \"LIMIT_REACHED\") {\n setErrorMsg(\"The author has run out of free credits and can't accept more feedback at this time.\");\n } else {\n setErrorMsg(errorData?.message || \"Failed to submit feedback. Please try again later.\");\n }\n }\n } catch (error) {\n console.error(\"Error submitting feedback:\", error);\n setErrorMsg(\"An error occurred while submitting feedback.\");\n } finally {\n setIsSubmitting(false);\n }\n };\n\n // Dynamic styles.\n const dynamicStyles = {\n \"--primary-color\": primaryColor,\n \"--secondary-color\": secondaryColor,\n \"--text-color\": textColor,\n \"--background-color\": backgroundColor,\n \"--button-radius\": buttonRadius,\n \"--z-index\": zIndex,\n \"--icon-color\": iconColor,\n } as React.CSSProperties;\n\n // Compute CSS classes.\n const buttonSizeClass = `button-${buttonSize}`;\n const positionClass = `position-${position}`;\n const themeClass = `theme-${theme}`;\n const styleClass = `style-${widgetStyle}`;\n\n const iconSize = ICON_SIZE_MAP[buttonSize];\n\n const renderButtonIcon = () => {\n const props = { size: iconSize, color: iconColor, animated };\n switch (buttonIcon) {\n case 'feedback':\n return <FeedbackIcon {...props} />;\n case 'message':\n return <MessageIcon {...props} />;\n case 'chat':\n return <ChatIcon {...props} />;\n case 'feedaura':\n return <FeedauraIcon {...props} />;\n case 'none':\n default:\n return null;\n }\n };\n\n return (\n <div className={`feedback-widget ${positionClass} ${themeClass} ${styleClass}`} style={dynamicStyles}>\n <button\n ref={triggerButtonRef}\n className={`feedback-button ${buttonSizeClass}`}\n onClick={openModal}\n style={{ backgroundColor: primaryColor, borderRadius: buttonRadius }}\n aria-label=\"Open feedback form\"\n >\n {buttonIcon !== \"none\" && <span className=\"button-icon\">\n {renderButtonIcon()}\n </span>}\n {buttonText && <span className=\"button-text\">\n {buttonText}\n </span>}\n </button>\n {isOpen && (\n <Modal isOpen={isOpen} modalAnimation={modalAnimation} onClose={closeModal} modalRef={modalRef} headerText={headerText}>\n {isSubmitted ? (\n <div className=\"feedback-success\" aria-live=\"polite\">\n <div className=\"success-icon\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M22 11.08V12C21.9988 14.1564 21.3005 16.2547 20.0093 17.9818C18.7182 19.709 16.9033 20.9725 14.8354 21.5839C12.7674 22.1953 10.5573 22.1219 8.53447 21.3746C6.51168 20.6273 4.78465 19.2461 3.61096 17.4371C2.43727 15.628 1.87979 13.4881 2.02168 11.3363C2.16356 9.18455 2.99721 7.13631 4.39828 5.49706C5.79935 3.85781 7.69279 2.71537 9.79619 2.24013C11.8996 1.7649 14.1003 1.98232 16.07 2.85999\"\n stroke={primaryColor}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M22 4L12 14.01L9 11.01\"\n stroke={primaryColor}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </div>\n <h4>Thank you for your feedback!</h4>\n <p>We appreciate your input and will use it to improve our service.</p>\n </div>\n ) : (\n <>\n <FeedbackForm\n feedback={feedback}\n setFeedback={setFeedback}\n errorMsg={errorMsg}\n setErrorMsg={setErrorMsg}\n primaryColor={primaryColor}\n placeholder={placeholder}\n feedbackLabel={feedbackLabelText}\n submitText={submitText}\n isSubmitting={isSubmitting}\n onSubmit={handleSubmit}\n questionText={questionText}\n />\n </>\n )}\n </Modal>\n )}\n </div>\n );\n};\n\nexport default Feedback;\n","import { useState } from \"react\"\n\nexport function useLocalStorage(key: string, initialValue: string) {\n const [storedValue, setStoredValue] = useState<string | null>(() => {\n if (typeof window === \"undefined\") {\n return null\n }\n const item = window.localStorage.getItem(key)\n return item ? item : initialValue\n })\n\n const setValue = (value: string) => {\n // Only update if the value is different\n if (value !== storedValue) {\n setStoredValue(value)\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(key, value)\n }\n }\n }\n\n return [storedValue, setValue] as const\n}\n","import { useState, useEffect, useRef } from \"react\";\n\nexport function useModal(setIsSubmitted: () => void, closeDelay = 300) {\n const [isOpen, setIsOpen] = useState(false);\n const [modalAnimation, setModalAnimation] = useState(\"\");\n const modalRef = useRef<HTMLDivElement>(null);\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n\n const openModal = () => {\n setIsOpen(true);\n setModalAnimation(\"modalFadeIn\");\n };\n\n const closeModal = () => {\n setModalAnimation(\"modalFadeOut\");\n setTimeout(() => {\n setIsOpen(false);\n setModalAnimation(\"\");\n setIsSubmitted();\n }, closeDelay);\n };\n\n // Manage focus on open/close.\n useEffect(() => {\n if (isOpen) {\n modalRef.current?.querySelector<HTMLElement>(\".close-button\")?.focus();\n } else {\n triggerButtonRef.current?.focus();\n }\n }, [isOpen]);\n\n // Close modal on ESC or clicking outside.\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && isOpen) closeModal();\n };\n const handleClickOutside = (event: MouseEvent) => {\n if (modalRef.current && !modalRef.current.contains(event.target as Node)) {\n closeModal();\n }\n };\n if (isOpen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n\n return { isOpen, modalAnimation, openModal, closeModal, modalRef, triggerButtonRef };\n}\n"],"names":["__assign","Object","assign","t","s","i","n","arguments","length","p","prototype","hasOwnProperty","call","apply","this","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","value","step","next","e","rejected","result","done","then","__generator","body","f","y","_","label","sent","trys","ops","g","create","Iterator","verb","Symbol","iterator","v","op","TypeError","pop","push","SuppressedError","css","ref","insertAt","document","head","getElementsByTagName","style","createElement","type","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode","ICON_SIZE_MAP","small","medium","large","getBrowserInfo","navigator","userAgent","browser","includes","getDeviceInfo","test","Modal","_a","isOpen","modalAnimation","onClose","modalRef","children","headerText","_jsxs","className","concat","role","_jsx","id"