@usero/sdk 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/api.ts","../src/colorUtils.ts","../src/validation.ts","../src/widgetCss.ts","../src/vanilla.ts"],"names":["EMOJI_MAP","RATING_LABELS","EMOJI_BACKGROUNDS","DEFAULT_API_URL","DEFAULT_THEME","DARK_THEME","mergeTheme","customTheme","isJsonErrorBody","value","parseScreenshotUploadBody","obj","success","error","rawShot","screenshot","s","FeedbackApiClient","baseUrl","data","response","errorMessage","errorData","result","message","file","clientId","formData","body","raw","colorNameToHex","color","ctx","getGradientEnd","hex","r","g","b","shiftedR","shiftedG","shiftedB","x","validateFeedbackSubmission","errors","hasRating","hasComment","FEEDBACK_CSS","EMAIL_STORAGE_KEY","escapeHtml","ch","readStoredEmail","writeStoredEmail","email","initUseroFeedbackWidget","props","err","position","theme","title","placeholder","showEmailOption","showScreenshotOption","environment","metadata","onSubmit","onError","onOpen","onClose","apiClient","isOpen","selectedRating","comment","shareEmail","userEmail","isSubmitting","submitMessage","screenshots","isUploadingScreenshot","screenshotError","MAX_SCREENSHOTS","MAX_SCREENSHOT_BYTES","host","root","style","buttonEl","backdropEl","panelEl","setSubmitMessage","next","render","open","handleScreenshotFile","uploaded","removeScreenshot","index","_","i","close","submitForm","feedbackData","submission","validation","msg","renderButton","renderBackdrop","renderPanel","remaining","lowChars","ratingsHtml","sel","bg","messageHtml","screenshotBlockHtml","atMax","btnDisabled","previewsHtml","shot","errorHtml","limitHtml","extrasHtml","emailBlockHtml","submitDisabled","submitStyle","e","btn","textarea","counter","left","shareCb","emailInp","fileInput","idx","onKeyDown","destroyed","needsRender"],"mappings":"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AAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ECoD5B,IAAMC,EAAAA,CAAoB,sBAE1B,SAASC,CAAAA,CAAWvC,EAAuB,CAC1C,OAAOA,EAAM,OAAA,CAAQ,UAAA,CAAYwC,GAAM,CACtC,OAAQA,GACP,KAAK,IACJ,OAAO,OAAA,CACR,KAAK,GAAA,CACJ,OAAO,OACR,KAAK,GAAA,CACJ,OAAO,MAAA,CACR,KAAK,IACJ,OAAO,QAAA,CACR,KAAK,GAAA,CACJ,OAAO,SACR,QACC,OAAOA,CACT,CACD,CAAC,CACF,CAEA,SAASC,EAAAA,EAA0B,CAClC,GAAI,OAAO,OAAW,GAAA,CAAa,OAAO,GAC1C,GAAI,CACH,OAAO,MAAA,CAAO,YAAA,CAAa,QAAQH,EAAiB,CAAA,EAAK,EAC1D,CAAA,KAAQ,CACP,OAAO,EACR,CACD,CAEA,SAASI,EAAAA,CAAiBC,CAAAA,CAAqB,CAC9C,GAAI,CACH,OAAO,YAAA,CAAa,OAAA,CAAQL,GAAmBK,CAAK,EACrD,MAAQ,CAER,CACD,CAEO,SAASC,EAAAA,CACfC,EACoB,CACpB,GAAI,OAAO,QAAA,CAAa,GAAA,CACvB,OAAO,CACN,OAAA,CAAS,IAAM,CAAC,CAAA,CAChB,IAAA,CAAM,IAAM,CAAC,CAAA,CACb,MAAO,IAAM,CAAC,EACd,MAAA,CAAQ,IAAM,CAAC,CAChB,CAAA,CAGD,GAAM,CAAE,QAAA,CAAA5B,EAAU,OAAA,CAAAR,CAAQ,EAAIoC,CAAAA,CAE9B,GAAI,CAAC5B,CAAAA,EAAYA,CAAAA,CAAS,OAAS,CAAA,CAAG,CACrC,IAAM6B,CAAAA,CAAM,IAAI,MAAM,gCAAgC,CAAA,CACtD,OAAAD,CAAAA,CAAM,OAAA,GAAUC,CAAG,CAAA,CACZ,CACN,QAAS,IAAM,CAAC,EAChB,IAAA,CAAM,IAAM,CAAC,CAAA,CACb,KAAA,CAAO,IAAM,CAAC,CAAA,CACd,MAAA,CAAQ,IAAM,CAAC,CAChB,CACD,CAKA,IAAIC,EAA2BF,CAAAA,CAAM,QAAA,EAAY,QAC7CG,CAAAA,CAAqBnD,CAAAA,CAAWgD,EAAM,KAAK,CAAA,CAC3CI,EAAgBJ,CAAAA,CAAM,KAAA,EAAS,gBAAA,CAC/BK,CAAAA,CAAsBL,CAAAA,CAAM,WAAA,EAAe,uCAC3CM,CAAAA,CAA2BN,CAAAA,CAAM,iBAAmB,IAAA,CACpDO,CAAAA,CAAgCP,EAAM,oBAAA,EAAwB,IAAA,CAC9DQ,EAAkCR,CAAAA,CAAM,WAAA,CACxCS,EAAgDT,CAAAA,CAAM,QAAA,CACtDU,EAA4CV,CAAAA,CAAM,QAAA,CAClDW,EAA0CX,CAAAA,CAAM,OAAA,CAChDY,CAAAA,CAAwCZ,CAAAA,CAAM,MAAA,CAC9Ca,CAAAA,CAA0Cb,EAAM,OAAA,CAE9Cc,CAAAA,CAAY,IAAInD,CAAAA,CAAkBC,CAAO,EAG3CmD,CAAAA,CAAS,KAAA,CACTC,EACAC,CAAAA,CAAU,EAAA,CACVC,EAAa,KAAA,CACbC,CAAAA,CAAYvB,IAAgB,CAC5BwB,CAAAA,CAAe,MACfC,CAAAA,CAAoE,IAAA,CACpEC,EAAgC,EAAC,CACjCC,EAAwB,KAAA,CACxBC,CAAAA,CAAiC,KAE/BC,CAAAA,CAAkB,CAAA,CAClBC,GAAuB,EAAA,CAAK,IAAA,CAAO,KAGnCC,CAAAA,CAAO,QAAA,CAAS,cAAc,KAAK,CAAA,CACzCA,EAAK,YAAA,CAAa,mBAAA,CAAqB,EAAE,CAAA,CAGzCA,CAAAA,CAAK,KAAA,CAAM,OAAA,CAAU,eAAA,CACrB,QAAA,CAAS,KAAK,WAAA,CAAYA,CAAI,EAC9B,IAAMC,CAAAA,CAAOD,EAAK,YAAA,CAAa,CAAE,KAAM,MAAO,CAAC,EAGzCE,CAAAA,CAAQ,QAAA,CAAS,cAAc,OAAO,CAAA,CAC5CA,EAAM,WAAA,CAAcrC,EAAAA,CACpBoC,CAAAA,CAAK,WAAA,CAAYC,CAAK,CAAA,CAGtB,IAAMC,CAAAA,CAAW,QAAA,CAAS,cAAc,QAAQ,CAAA,CAC1CC,EAAa,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA,CACzCC,CAAAA,CAAU,SAAS,aAAA,CAAc,KAAK,EAC5CJ,CAAAA,CAAK,WAAA,CAAYE,CAAQ,CAAA,CACzBF,CAAAA,CAAK,WAAA,CAAYG,CAAU,CAAA,CAC3BH,CAAAA,CAAK,YAAYI,CAAO,CAAA,CAExB,SAASC,EAAAA,CACRC,CAAAA,CACO,CACPb,CAAAA,CAAgBa,CAAAA,CAChBC,IACD,CAEA,SAASC,CAAAA,EAAa,CACjBrB,IACJA,CAAAA,CAAS,IAAA,CAETC,EAAiB,MAAA,CACjBC,CAAAA,CAAU,GACVC,CAAAA,CAAa,KAAA,CACbG,EAAgB,IAAA,CAChBC,CAAAA,CAAc,EAAC,CACfE,CAAAA,CAAkB,KAClBD,CAAAA,CAAwB,KAAA,CACxBT,EAAU,IAAA,EAAK,CACfF,KAAS,CACTuB,CAAAA,IACD,CAEA,eAAeE,GAAqBlE,CAAAA,CAA2B,CAE9D,GADAqD,CAAAA,CAAkB,IAAA,CACd,CAACrD,EAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,CAAG,CACpCqD,EAAkB,kBAAA,CAClBW,CAAAA,GACA,MACD,CACA,GAAIhE,CAAAA,CAAK,IAAA,CAAOuD,GAAsB,CACrCF,CAAAA,CAAkB,WAClBW,CAAAA,EAAO,CACP,MACD,CACA,GAAIb,CAAAA,CAAY,QAAUG,CAAAA,CAAiB,CAC1CD,EAAkB,CAAA,IAAA,EAAOC,CAAe,eACxCU,CAAAA,EAAO,CACP,MACD,CAEAZ,CAAAA,CAAwB,KACxBY,CAAAA,EAAO,CACP,GAAI,CACH,IAAMG,EAAW,MAAMxB,CAAAA,CAAU,gBAAA,CAAiB3C,CAAAA,CAAMC,CAAQ,CAAA,CAChEkD,EAAc,CAAC,GAAGA,EAAagB,CAAQ,EACxC,OAASrC,CAAAA,CAAK,CACbuB,EAAkBvB,CAAAA,YAAe,KAAA,CAAQA,EAAI,OAAA,CAAU,gBACxD,QAAE,CACDsB,CAAAA,CAAwB,MACxBY,CAAAA,GACD,CACD,CAEA,SAASI,GAAiBC,CAAAA,CAAqB,CAC9ClB,EAAcA,CAAAA,CAAY,MAAA,CAAO,CAACmB,CAAAA,CAAGC,CAAAA,GAAMA,IAAMF,CAAK,CAAA,CACtDL,IACD,CAEA,SAASQ,CAAAA,EAAc,CACjB5B,IACLA,CAAAA,CAAS,KAAA,CACTF,CAAAA,IAAU,CACVsB,CAAAA,EAAO,EACR,CAEA,eAAeS,EAAAA,EAA4B,CAC1C,GAAIxB,CAAAA,CAAc,OAClBA,CAAAA,CAAe,IAAA,CACfC,EAAgB,IAAA,CAChBc,CAAAA,GAEA,IAAMU,CAAAA,CAA6B,CAClC,MAAA,CAAQ7B,CAAAA,CACR,QAASC,CAAAA,CAAQ,IAAA,EAAK,EAAK,MAAA,CAC3B,SAAA,CAAWC,CAAAA,CAAaC,EAAY,MAAA,CACpC,WAAA,CAAaG,EAAY,MAAA,CAAS,CAAA,CAAIA,EAAc,MAAA,CACpD,QAAA,CAAU,CACT,OAAA,CAAS,MAAA,CAAO,SAAS,IAAA,CACzB,SAAA,CAAW,SAAS,KAAA,EAAS,eAAA,CAC7B,SAAU,QAAA,CAAS,QAAA,EAAY,MAAA,CAC/B,SAAA,CAAW,IAAA,CAAK,GAAA,EACjB,CACD,CAAA,CAEMwB,EAAiC,CACtC,QAAA,CAAA1E,EACA,MAAA,CAAQyE,CAAAA,CAAa,OACrB,OAAA,CAASA,CAAAA,CAAa,QACtB,SAAA,CAAWA,CAAAA,CAAa,UACxB,OAAA,CAASA,CAAAA,CAAa,SAAS,OAAA,CAC/B,SAAA,CAAWA,EAAa,QAAA,CAAS,SAAA,CACjC,SAAUA,CAAAA,CAAa,QAAA,CAAS,SAChC,WAAA,CAAArC,CACD,EACIc,CAAAA,CAAY,MAAA,CAAS,IAAGwB,CAAAA,CAAW,WAAA,CAAcxB,GACjDb,CAAAA,GAAa,MAAA,GAAWqC,EAAW,QAAA,CAAWrC,CAAAA,CAAAA,CAElD,IAAMsC,CAAAA,CAAa3D,EAAAA,CAA2B0D,CAAU,CAAA,CACxD,GAAI,CAACC,EAAW,OAAA,CAAS,CACxB3B,EAAe,KAAA,CACfa,EAAAA,CAAiB,CAAE,IAAA,CAAM,OAAA,CAAS,KAAMc,CAAAA,CAAW,MAAA,CAAO,KAAK,IAAI,CAAE,CAAC,CAAA,CACtE,MACD,CAEA,GAAI,CACH,IAAMjF,CAAAA,CAAW,MAAMgD,CAAAA,CAAU,eAAegC,CAAU,CAAA,CAC1D,GAAIhF,CAAAA,CAAS,OAAA,CACRoD,GAAcC,CAAAA,EAAWtB,EAAAA,CAAiBsB,CAAS,CAAA,CACvDT,CAAAA,GAAWmC,CAAY,CAAA,CACvB7B,CAAAA,CAAiB,OACjBC,CAAAA,CAAU,EAAA,CACVC,EAAa,CAAA,CAAA,CACbI,CAAAA,CAAc,EAAC,CACfE,CAAAA,CAAkB,IAAA,CAClBH,EAAgB,CAAE,IAAA,CAAM,UAAW,IAAA,CAAM,YAAa,OAChD,CACN,IAAM2B,EAAMlF,CAAAA,CAAS,KAAA,EAAS,6BAC9B6C,CAAAA,GAAU,IAAI,MAAMqC,CAAG,CAAC,EACxB3B,CAAAA,CAAgB,CAAE,KAAM,OAAA,CAAS,IAAA,CAAM2B,CAAI,EAC5C,CACD,OAAS/C,CAAAA,CAAK,CACb,IAAM+C,CAAAA,CAAM/C,CAAAA,YAAe,MAAQA,CAAAA,CAAI,OAAA,CAAU,6BACjDU,CAAAA,GAAU,IAAI,MAAMqC,CAAG,CAAC,EACxB3B,CAAAA,CAAgB,CAAE,IAAA,CAAM,OAAA,CAAS,IAAA,CAAM2B,CAAI,EAC5C,CAAA,OAAE,CACD5B,EAAe,KAAA,CACfe,CAAAA,GACD,CACD,CAGA,SAASc,EAAAA,EAAqB,CAC7BnB,EAAS,SAAA,CAAY,CAAA,eAAA,EAAkB5B,CAAQ,CAAA,CAAA,EAAIa,CAAAA,CAAS,eAAiB,EAAE,CAAA,CAAA,CAC/Ee,CAAAA,CAAS,YAAA,CAAa,YAAA,CAAc,eAAe,EACnDA,CAAAA,CAAS,IAAA,CAAO,SAChBA,CAAAA,CAAS,KAAA,CAAM,WAAa,CAAA,wBAAA,EAA2B3B,CAAAA,CAAM,OAAO,CAAA,EAAA,EAAKxB,CAAAA,CAAewB,EAAM,OAAO,CAAC,IACtG2B,CAAAA,CAAS,SAAA,CAAYf,EAClB,6CAAA,CACA,GACJ,CAEA,SAASmC,EAAAA,EAAuB,CAC/BnB,EAAW,SAAA,CAAY,aAAA,CACvBA,EAAW,KAAA,CAAM,OAAA,CAAUhB,EAAS,OAAA,CAAU,MAAA,CAC9CgB,EAAW,YAAA,CAAa,YAAA,CAAc,aAAa,EACpD,CAEA,SAASoB,EAAAA,EAAoB,CAC5BnB,EAAQ,SAAA,CAAY,CAAA,oBAAA,EAAuB9B,CAAQ,CAAA,CAAA,EAClDa,CAAAA,CAAS,eAAiB,gBAC3B,CAAA,CAAA,CACAiB,EAAQ,KAAA,CAAM,eAAA,CAAkB7B,EAAM,UAAA,CAClCD,CAAAA,GAAa,SAChB8B,CAAAA,CAAQ,KAAA,CAAM,WAAa,CAAA,UAAA,EAAa7B,CAAAA,CAAM,MAAM,CAAA,CAAA,CACpD6B,CAAAA,CAAQ,MAAM,WAAA,CAAc,EAAA,GAE5BA,CAAAA,CAAQ,KAAA,CAAM,WAAA,CAAc,CAAA,UAAA,EAAa7B,EAAM,MAAM,CAAA,CAAA,CACrD6B,EAAQ,KAAA,CAAM,UAAA,CAAa,IAE5BA,CAAAA,CAAQ,YAAA,CAAa,OAAQ,QAAQ,CAAA,CACrCA,EAAQ,YAAA,CAAa,YAAA,CAAc,MAAM,CAAA,CACzCA,CAAAA,CAAQ,aAAa,iBAAA,CAAmB,sBAAsB,CAAA,CAE9D,IAAMoB,CAAAA,CAAY,GAAA,CAAOnC,EAAQ,MAAA,CAC3BoC,CAAAA,CAAWD,EAAY,EAAA,CAEvBE,CAAAA,CAAe,CAAC,CAAA,CAAG,CAAA,CAAG,EAAG,CAAC,CAAA,CAC9B,IAAIzE,CAAAA,EAAK,CACT,IAAM0E,CAAAA,CAAMvC,CAAAA,GAAmBnC,EACzB2E,CAAAA,CAAK5G,EAAAA,CAAkBiC,CAAC,CAAA,CAE9B,OAAO;AAAA,iBAAA,EADK,CAAC,OAAA,CAAS0E,CAAAA,EAAO,YAAY,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAEjD,CAAA,oBAAA,EAAuBC,CAAE,CAAA;AAAA,uDAAA,EACU3E,CAAC,gCAAgC0E,CAAG,CAAA,cAAA,EAAiB1E,CAAC,CAAA,EAAA,EAAKlC,CAAAA,CAAckC,CAAC,CAAC,CAAA;AAAA,uDAAA,EAC3ElC,EAAckC,CAAC,CAAC,CAAA,EAAA,EAAKnC,EAAAA,CAAUmC,CAAC,CAAC,CAAA;AAAA,0BAAA,EAC9DlC,CAAAA,CAAckC,CAAC,CAAC,CAAA;AAAA;AAAA;AAAA,IAAA,CAIzC,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA,CAEH4E,CAAAA,CAAcpC,EACjB,CAAA,kCAAA,EAAqCA,CAAAA,CAAc,OAAS,SAAA,CAAY,YAAA,CAAe,aAAa,CAAA,EAAA,EAAKA,CAAAA,CAAc,OAAS,SAAA,CAAY,QAAA,CAAM,QAAG,CAAA,CAAA,EAAI3B,CAAAA,CAAW2B,EAAc,IAAI,CAAC,SACvL,EAAA,CAEGqC,CAAAA,CAAsBnD,GACxB,IAAM,CACP,IAAMoD,CAAAA,CAAQrC,CAAAA,CAAY,QAAUG,CAAAA,CAC9BmC,CAAAA,CAAcrC,GAAyBoC,CAAAA,CACvCE,CAAAA,CAAevC,EACnB,GAAA,CACA,CAACwC,GAAMpB,EAAAA,GAAM;AAAA;AAAA,mBAAA,EAEChD,EAAWoE,EAAAA,CAAK,GAAG,CAAC,CAAA,kBAAA,EAAqBpB,GAAI,CAAC,CAAA;AAAA,uFAAA,EACsBA,EAAC,CAAA;AAAA;AAAA,OAAA,CAGpF,EACC,IAAA,CAAK,EAAE,CAAA,CACHqB,EAAAA,CAAYvC,EACf,CAAA,2BAAA,EAAyB9B,CAAAA,CAAW8B,CAAe,CAAC,SACpD,EAAA,CACGwC,EAAAA,CAAYL,EACf,CAAA,uBAAA,EAA0BlC,CAAe,SACzC,EAAA,CACGwC,EAAAA,CACLzC,CAAAA,EAAmBF,CAAAA,CAAY,OAAS,CAAA,EAAKqC,CAAAA,CAC1C,CAAA,0BAAA,EAA6BI,EAAS,GACtCzC,CAAAA,CAAY,MAAA,CAAS,CAAA,CAClB,CAAA,mBAAA,EAAsBuC,CAAY,CAAA,MAAA,CAAA,CAClC,EACJ,GAAGG,EAAS,CAAA,MAAA,CAAA,CACX,GACJ,OAAO;AAAA;AAAA;AAAA,2CAAA,EAGiCJ,CAAAA,CAAc,aAAA,CAAgB,EAAE,CAAA,8BAAA,EAAiCA,CAAAA,CAAc,UAAA,CAAa,EAAE,CAAA,yBAAA,EAA4BzD,CAAAA,CAAM,MAAM,CAAA,OAAA,EAAUA,CAAAA,CAAM,IAAI,CAAA;AAAA,QAAA,EAE9LoB,CAAAA,CACG,4CACA,0BACJ;AAAA;AAAA,OAAA,EAEC0C,EAAU;AAAA;AAAA,KAAA,CAGf,CAAA,GAAG,CACF,EAAA,CAEGC,EAAAA,CAAiB5D,CAAAA,CACpB;AAAA;AAAA,8CAAA,EAE2CH,EAAM,IAAI,CAAA;AAAA,yEAAA,EACiBe,CAAAA,CAAa,UAAY,EAAE,CAAA;AAAA;AAAA;AAAA,KAAA,EAIhGA,CAAAA,CACG,CAAA,wEAAA,EAA2ExB,CAAAA,CAAWyB,CAAS,CAAC,CAAA,uHAAA,EAA0HhB,CAAAA,CAAM,MAAM,CAAA,OAAA,EAAUA,EAAM,IAAI,CAAA,kBAAA,EAAqBA,CAAAA,CAAM,UAAU,QAC/R,EACJ;AAAA;AAAA,GAAA,CAAA,CAGA,GAEGgE,CAAAA,CAAiB/C,CAAAA,CACjBgD,GAAc,CAAA,mCAAA,EAAsCjE,CAAAA,CAAM,OAAO,CAAA,EAAA,EAAKxB,CAAAA,CAAewB,CAAAA,CAAM,OAAO,CAAC,CAAA,gBAAA,EAAmBgE,CAAAA,CAAiB,kCAAoC,EAAE,CAAA,CAAA,CAEnLnC,EAAQ,SAAA,CAAY;AAAA;AAAA,uDAAA,EAEmC7B,EAAM,MAAM,CAAA;AAAA,+DAAA,EACJA,CAAAA,CAAM,IAAI,CAAA,EAAA,EAAKT,CAAAA,CAAWU,CAAK,CAAC,CAAA;AAAA,KAAA,EAC1FqD,CAAW;AAAA,iEAAA,EACiDtD,EAAM,IAAI,CAAA;AAAA;AAAA;AAAA,uEAAA,EAGJmD,CAAW,CAAA;AAAA,8DAAA,EACpB5D,CAAAA,CAAWW,CAAW,CAAC,CAAA,0EAAA,EAA6EF,EAAM,MAAM,CAAA,OAAA,EAAUA,CAAAA,CAAM,IAAI,qBAAqBA,CAAAA,CAAM,UAAU,CAAA,GAAA,EAAMT,CAAAA,CAAWuB,CAAO,CAAC,CAAA;AAAA;AAAA,uCAAA,EAEzNoC,EAAW,SAAA,CAAYlD,CAAAA,CAAM,IAAI,CAAA,SAAA,EAAYkD,CAAAA,CAAW,EAAI,EAAG,CAAA;AAAA,OAAA,EAC/FD,CAAS,CAAA;AAAA;AAAA;AAAA,KAAA,EAGXM,CAAmB;AAAA,KAAA,EACnBQ,EAAc;AAAA,2BAAA,EACQC,CAAAA,CAAiB,cAAgB,EAAE,CAAA,oCAAA,EAAuCA,EAAiB,UAAA,CAAa,EAAE,WAAWC,EAAW,CAAA;AAAA,MAAA,EACrJhD,CAAAA,CAAe,gCAAkC,EAAE;AAAA,MAAA,EACnDA,CAAAA,CAAe,gBAAkB,yBAAkB;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA,CAO5CY,CAAAA,CAAQ,cAA+B,wBAAwB,CAAA,EACtE,iBAAiB,QAAA,CAAUqC,CAAAA,EAAK,CACrCA,CAAAA,CAAE,cAAA,EAAe,CACZzB,KACN,CAAC,EAEDZ,CAAAA,CACE,aAAA,CAAiC,2BAA2B,CAAA,EAC3D,gBAAA,CAAiB,OAAA,CAASW,CAAK,CAAA,CAElCX,CAAAA,CACE,iBAAoC,qBAAqB,CAAA,CACzD,QAAQsC,CAAAA,EAAO,CACfA,EAAI,gBAAA,CAAiB,OAAA,CAAS,IAAM,CACnC,IAAMnH,CAAAA,CAAQmH,EAAI,OAAA,CAAQ,MAAA,CAAA,CACtBnH,CAAAA,GAAU,GAAA,EAAOA,CAAAA,GAAU,GAAA,EAAOA,IAAU,GAAA,EAAOA,CAAAA,GAAU,GAAA,IAChE6D,CAAAA,CAAiB,MAAA,CAAO7D,CAAK,EAC7BgF,CAAAA,EAAO,EAET,CAAC,EACF,CAAC,EAEF,IAAMoC,CAAAA,CAAWvC,CAAAA,CAAQ,aAAA,CACxB,+BACD,CAAA,CACIuC,GACHA,CAAAA,CAAS,gBAAA,CAAiB,QAAS,IAAM,CACxC,GAAIA,CAAAA,CAAS,KAAA,CAAM,MAAA,EAAU,GAAA,CAAM,CAClCtD,CAAAA,CAAUsD,EAAS,KAAA,CAEnB,IAAMC,EAAUxC,CAAAA,CAAQ,aAAA,CACvB,0BACD,CAAA,CACA,GAAIwC,CAAAA,CAAS,CACZ,IAAMC,CAAAA,CAAO,IAAOxD,CAAAA,CAAQ,MAAA,CAC5BuD,CAAAA,CAAQ,WAAA,CAAc,CAAA,EAAGC,CAAI,mBAC7BD,CAAAA,CAAQ,KAAA,CAAM,KAAA,CAAQC,CAAAA,CAAO,EAAA,CAAK,SAAA,CAAYtE,EAAM,IAAA,CACpDqE,CAAAA,CAAQ,MAAM,OAAA,CAAUC,CAAAA,CAAO,GAAK,GAAA,CAAM,MAC3C,CACD,CACD,CAAC,CAAA,CAGF,IAAMC,EAAAA,CAAU1C,CAAAA,CAAQ,cACvB,gCACD,CAAA,CACA0C,IAAS,gBAAA,CAAiB,QAAA,CAAU,IAAM,CACzCxD,CAAAA,CAAawD,EAAAA,CAAQ,QACrBvC,CAAAA,GACD,CAAC,CAAA,CAED,IAAMwC,EAAW3C,CAAAA,CAAQ,aAAA,CACxB,gCACD,CAAA,CACA2C,CAAAA,EAAU,gBAAA,CAAiB,QAAS,IAAM,CACrCA,CAAAA,CAAS,KAAA,CAAM,MAAA,EAAU,GAAA,GAC5BxD,EAAYwD,CAAAA,CAAS,KAAA,EAEvB,CAAC,CAAA,CAED,IAAMC,CAAAA,CAAY5C,EAAQ,aAAA,CACzB,qCACD,EACgBA,CAAAA,CAAQ,aAAA,CACvB,qCACD,CAAA,EACS,gBAAA,CAAiB,OAAA,CAAS,IAAM,CACxC4C,CAAAA,EAAW,QACZ,CAAC,EACDA,CAAAA,EAAW,gBAAA,CAAiB,SAAU,IAAM,CAC3C,IAAMzG,CAAAA,CAAOyG,CAAAA,CAAU,KAAA,GAAQ,CAAC,CAAA,CAC3BzG,CAAAA,EACAkE,GAAqBlE,CAAI,CAAA,CAAE,QAAQ,IAAM,CACzCyG,CAAAA,GAAWA,CAAAA,CAAU,KAAA,CAAQ,EAAA,EAClC,CAAC,EACF,CAAC,CAAA,CACD5C,CAAAA,CACE,gBAAA,CACA,uCACD,EACC,OAAA,CAAQsC,CAAAA,EAAO,CACfA,CAAAA,CAAI,gBAAA,CAAiB,OAAA,CAAS,IAAM,CACnC,IAAMO,EAAM,MAAA,CAAOP,CAAAA,CAAI,QAAQ,KAAK,CAAA,CAChC,MAAA,CAAO,SAAA,CAAUO,CAAG,CAAA,EAAGtC,GAAiBsC,CAAG,EAChD,CAAC,EACF,CAAC,EACH,CAEA,SAAS1C,CAAAA,EAAe,CACvBc,EAAAA,EAAa,CACbC,IAAe,CACfC,EAAAA,GACD,CAGArB,CAAAA,CAAS,iBAAiB,OAAA,CAAS,IAAM,CACpCf,CAAAA,CAAQ4B,CAAAA,EAAM,CACbP,IACN,CAAC,CAAA,CACDL,CAAAA,CAAW,gBAAA,CAAiB,OAAA,CAASY,CAAK,CAAA,CAE1C,IAAMmC,EAAAA,CAAa,CAAA,EAA2B,CACxC/D,CAAAA,GACD,EAAE,GAAA,GAAQ,QAAA,EAAU4B,GAAM,CAC1B,CAAA,CAAE,MAAQ,OAAA,GAAY,CAAA,CAAE,OAAA,EAAW,CAAA,CAAE,OAAA,CAAA,GACxC,CAAA,CAAE,gBAAe,CACZC,EAAAA,KAEP,CAAA,CACA,QAAA,CAAS,iBAAiB,SAAA,CAAWkC,EAAS,CAAA,CAG9C3C,CAAAA,EAAO,CAEP,IAAI4C,EAAY,KAAA,CAChB,OAAO,CACN,OAAA,CAAS,IAAM,CACVA,CAAAA,GACJA,CAAAA,CAAY,IAAA,CACZ,QAAA,CAAS,mBAAA,CAAoB,SAAA,CAAWD,EAAS,CAAA,CACjDnD,CAAAA,CAAK,MAAA,EAAO,EACb,CAAA,CACA,IAAA,CAAAS,EACA,KAAA,CAAAO,CAAAA,CACA,MAAA,CAAQT,CAAAA,EAAQ,CACf,GAAI6C,EAAW,OACf,IAAIC,EAAc,KAAA,CACd9C,CAAAA,CAAK,WAAa,MAAA,EAAaA,CAAAA,CAAK,QAAA,GAAahC,CAAAA,GACpDA,CAAAA,CAAWgC,CAAAA,CAAK,SAChB8C,CAAAA,CAAc,IAAA,CAAA,CAEX9C,EAAK,KAAA,GAAU,MAAA,GAClB/B,EAAQnD,CAAAA,CAAWkF,CAAAA,CAAK,KAAK,CAAA,CAC7B8C,CAAAA,CAAc,IAAA,CAAA,CAEX9C,EAAK,KAAA,GAAU,MAAA,EAAaA,EAAK,KAAA,GAAU9B,CAAAA,GAC9CA,EAAQ8B,CAAAA,CAAK,KAAA,CACb8C,CAAAA,CAAc,IAAA,CAAA,CAEX9C,CAAAA,CAAK,WAAA,GAAgB,QAAaA,CAAAA,CAAK,WAAA,GAAgB7B,CAAAA,GAC1DA,CAAAA,CAAc6B,CAAAA,CAAK,WAAA,CACnB8C,EAAc,IAAA,CAAA,CAGd9C,CAAAA,CAAK,eAAA,GAAoB,MAAA,EACzBA,CAAAA,CAAK,eAAA,GAAoB5B,IAEzBA,CAAAA,CAAkB4B,CAAAA,CAAK,gBACvB8C,CAAAA,CAAc,IAAA,CAAA,CAGd9C,EAAK,oBAAA,GAAyB,MAAA,EAC9BA,CAAAA,CAAK,oBAAA,GAAyB3B,CAAAA,GAE9BA,CAAAA,CAAuB2B,EAAK,oBAAA,CAC5B8C,CAAAA,CAAc,MAGX,aAAA,GAAiB9C,CAAAA,GAAM1B,EAAc0B,CAAAA,CAAK,WAAA,CAAA,CAC1C,UAAA,GAAcA,CAAAA,GAAMzB,CAAAA,CAAWyB,CAAAA,CAAK,UACpC,UAAA,GAAcA,CAAAA,GAAMxB,EAAWwB,CAAAA,CAAK,QAAA,CAAA,CACpC,YAAaA,CAAAA,GAAMvB,CAAAA,CAAUuB,CAAAA,CAAK,OAAA,CAAA,CAClC,QAAA,GAAYA,CAAAA,GAAMtB,EAASsB,CAAAA,CAAK,MAAA,CAAA,CAChC,SAAA,GAAaA,CAAAA,GAAMrB,CAAAA,CAAUqB,CAAAA,CAAK,SAClC8C,CAAAA,EAAa7C,CAAAA,GAClB,CACD,CACD","file":"usero.iife.js","sourcesContent":["// Shared types used by both the vanilla and React entry points.\n// Keep this file framework-free so the vanilla bundle never pulls react.\n\nexport type FeedbackRating = 1 | 2 | 3 | 4\n\nexport interface FeedbackMetadata {\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\ttimestamp: number\n}\n\nexport interface ScreenshotData {\n\tfileName: string\n\turl: string\n\tfileSize: number\n\twidth?: number\n\theight?: number\n\tmimeType: string\n}\n\nexport interface FeedbackSubmission {\n\tclientId: string\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\tenvironment?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata?: Record<string, unknown>\n}\n\nexport interface FeedbackData {\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata: FeedbackMetadata\n}\n\nexport type WidgetPosition = 'right' | 'left'\n\nexport interface WidgetTheme {\n\tprimary: string\n\tbackground: string\n\ttext: string\n\tborder: string\n\tshadow: string\n}\n\nexport interface FeedbackWidgetProps {\n\tclientId: string\n\tposition?: WidgetPosition\n\ttheme?: Partial<WidgetTheme>\n\ttitle?: string\n\tplaceholder?: string\n\tshowEmailOption?: boolean\n\tshowScreenshotOption?: boolean\n\tenvironment?: string\n\tbaseUrl?: string\n\tmetadata?: Record<string, unknown>\n\tonSubmit?: (feedback: FeedbackData) => void\n\tonError?: (error: Error) => void\n\tonOpen?: () => void\n\tonClose?: () => void\n}\n\nexport interface SubmissionResponse {\n\tsuccess: boolean\n\terror?: string\n\tid?: string\n\tmessage?: string\n\tdata?: unknown\n}\n\nexport const EMOJI_MAP: Record<FeedbackRating, string> = {\n\t1: '😞',\n\t2: '😐',\n\t3: '😊',\n\t4: '🤩',\n}\n\nexport const RATING_LABELS: Record<FeedbackRating, string> = {\n\t1: 'Needs work',\n\t2: \"It's okay\",\n\t3: 'Pretty good',\n\t4: 'Amazing!',\n}\n\nexport const EMOJI_BACKGROUNDS: Record<FeedbackRating, string> = {\n\t1: 'linear-gradient(135deg,#ff6b6b14,#ff6b6b1f)',\n\t2: 'linear-gradient(135deg,#9ca3af0f,#9ca3af1a)',\n\t3: 'linear-gradient(135deg,#3b82f614,#3b82f61f)',\n\t4: 'linear-gradient(135deg,#f59e0b14,#f59e0b1f)',\n}\n\nexport const DEFAULT_API_URL = 'https://usero.io'\n\nexport const DEFAULT_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#ffffff',\n\ttext: '#374151',\n\tborder: '#e5e7eb',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n}\n\nexport const DARK_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#1f2937',\n\ttext: '#f9fafb',\n\tborder: '#374151',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)',\n}\n\nexport function mergeTheme(customTheme: Partial<WidgetTheme> = {}): WidgetTheme {\n\treturn { ...DEFAULT_THEME, ...customTheme }\n}\n","import {\n\tDEFAULT_API_URL,\n\ttype FeedbackSubmission,\n\ttype ScreenshotData,\n\ttype SubmissionResponse,\n} from './types'\n\ninterface JsonErrorBody {\n\terror?: string\n}\n\nfunction isJsonErrorBody(value: unknown): value is JsonErrorBody {\n\treturn typeof value === 'object' && value !== null && 'error' in value\n}\n\ninterface ScreenshotUploadResponseBody {\n\tsuccess: boolean\n\terror?: string\n\tscreenshot?: ScreenshotData\n}\n\nfunction parseScreenshotUploadBody(\n\tvalue: unknown,\n): ScreenshotUploadResponseBody {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn { success: false, error: 'Invalid response' }\n\t}\n\tconst obj = value as Record<string, unknown>\n\tconst success = obj.success === true\n\tconst error = typeof obj.error === 'string' ? obj.error : undefined\n\tconst rawShot = obj.screenshot\n\tlet screenshot: ScreenshotData | undefined\n\tif (typeof rawShot === 'object' && rawShot !== null) {\n\t\tconst s = rawShot as Record<string, unknown>\n\t\tif (\n\t\t\ttypeof s.fileName === 'string' &&\n\t\t\ttypeof s.url === 'string' &&\n\t\t\ttypeof s.fileSize === 'number' &&\n\t\t\ttypeof s.mimeType === 'string'\n\t\t) {\n\t\t\tscreenshot = {\n\t\t\t\tfileName: s.fileName,\n\t\t\t\turl: s.url,\n\t\t\t\tfileSize: s.fileSize,\n\t\t\t\tmimeType: s.mimeType,\n\t\t\t\twidth: typeof s.width === 'number' ? s.width : undefined,\n\t\t\t\theight: typeof s.height === 'number' ? s.height : undefined,\n\t\t\t}\n\t\t}\n\t}\n\treturn { success, error, screenshot }\n}\n\nexport class FeedbackApiClient {\n\tprivate baseUrl: string\n\n\tconstructor(baseUrl: string = DEFAULT_API_URL) {\n\t\tthis.baseUrl = baseUrl.replace(/\\/$/, '')\n\t}\n\n\tasync submitFeedback(data: FeedbackSubmission): Promise<SubmissionResponse> {\n\t\ttry {\n\t\t\tconst response = await fetch(`${this.baseUrl}/api/feedback`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\tAccept: 'application/json',\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(data),\n\t\t\t\tsignal: AbortSignal.timeout(10000),\n\t\t\t})\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorMessage = `HTTP ${response.status}: ${response.statusText}`\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData: unknown = await response.json()\n\t\t\t\t\tif (isJsonErrorBody(errorData) && typeof errorData.error === 'string') {\n\t\t\t\t\t\terrorMessage = errorData.error\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore JSON parse errors\n\t\t\t\t}\n\t\t\t\tthrow new Error(errorMessage)\n\t\t\t}\n\n\t\t\tconst result: unknown = await response.json()\n\t\t\tconst message =\n\t\t\t\ttypeof result === 'object' &&\n\t\t\t\tresult !== null &&\n\t\t\t\t'message' in result &&\n\t\t\t\ttypeof (result as { message: unknown }).message === 'string'\n\t\t\t\t\t? (result as { message: string }).message\n\t\t\t\t\t: 'Feedback submitted successfully'\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: result,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror:\n\t\t\t\t\terror instanceof Error ? error.message : 'An unexpected error occurred',\n\t\t\t}\n\t\t}\n\t}\n\n\tasync uploadScreenshot(\n\t\tfile: File,\n\t\tclientId: string,\n\t): Promise<ScreenshotData> {\n\t\tconst formData = new FormData()\n\t\tformData.append('screenshot', file)\n\t\tformData.append('clientId', clientId)\n\n\t\tconst response = await fetch(`${this.baseUrl}/api/screenshots`, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: formData,\n\t\t\tsignal: AbortSignal.timeout(30000),\n\t\t})\n\n\t\tlet body: ScreenshotUploadResponseBody = { success: false }\n\t\ttry {\n\t\t\tconst raw: unknown = await response.json()\n\t\t\tbody = parseScreenshotUploadBody(raw)\n\t\t} catch {\n\t\t\t// fall through to error handling below\n\t\t}\n\n\t\tif (!response.ok || !body.success || !body.screenshot) {\n\t\t\tconst message =\n\t\t\t\tbody.error ?? `HTTP ${response.status}: ${response.statusText}`\n\t\t\tthrow new Error(message)\n\t\t}\n\n\t\treturn body.screenshot\n\t}\n\n\tping(): void {\n\t\tfetch(`${this.baseUrl}/api/ping`, {\n\t\t\tsignal: AbortSignal.timeout(5000),\n\t\t}).catch(() => {})\n\t}\n}\n","export function colorNameToHex(color: string): string {\n\tif (color.startsWith('#')) return color\n\tif (typeof document === 'undefined') return color\n\n\tconst canvas = document.createElement('canvas')\n\tconst ctx = canvas.getContext('2d')\n\tif (!ctx) return color\n\n\tctx.fillStyle = color\n\treturn ctx.fillStyle\n}\n\nexport function getGradientEnd(color: string): string {\n\tconst hex = colorNameToHex(color)\n\tif (!hex.startsWith('#') || hex.length < 7) return hex\n\tconst r = parseInt(hex.slice(1, 3), 16)\n\tconst g = parseInt(hex.slice(3, 5), 16)\n\tconst b = parseInt(hex.slice(5, 7), 16)\n\tconst shiftedR = Math.max(0, r - 60)\n\tconst shiftedG = Math.min(255, g + 40)\n\tconst shiftedB = Math.min(255, b + 20)\n\treturn `#${[shiftedR, shiftedG, shiftedB]\n\t\t.map(x => x.toString(16).padStart(2, '0'))\n\t\t.join('')}`\n}\n","import type { FeedbackSubmission } from './types'\n\nexport interface ValidationResult {\n\tisValid: boolean\n\terrors: string[]\n}\n\nexport function validateFeedbackSubmission(\n\tdata: Partial<FeedbackSubmission>,\n): ValidationResult {\n\tconst errors: string[] = []\n\tconst hasRating = data.rating != null\n\tconst hasComment = !!data.comment?.trim()\n\n\tif (!hasRating && !hasComment) {\n\t\terrors.push('Add rating or comment')\n\t}\n\tif (hasRating && data.rating !== undefined && ![1, 2, 3, 4].includes(data.rating)) {\n\t\terrors.push('Invalid rating')\n\t}\n\tif (hasComment && data.comment !== undefined) {\n\t\tif (data.comment.length > 1000) {\n\t\t\terrors.push('Comment too long')\n\t\t}\n\t\tif (/<script[^>]*>.*?<\\/script>/gi.test(data.comment)) {\n\t\t\terrors.push('Invalid comment')\n\t\t}\n\t}\n\n\treturn {\n\t\tisValid: errors.length === 0,\n\t\terrors,\n\t}\n}\n","// CSS used by both entry points.\n//\n// React entry injects it once into <head> via injectFeedbackCSS().\n// Vanilla entry injects it inside a shadow root, so host page styles\n// can't bleed in and our class names can't collide with the host.\n\nexport const FEEDBACK_CSS = `\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.fb-es {\n display: flex;\n justify-content: center;\n gap: 15px;\n padding-bottom: 10px;\n}\n\n.fb-ec {\n border-radius: 16px;\n padding: 0 5px;\n transition: all 300ms cubic-bezier(0.68, -0.55, 0.265, 1.55);\n border: 3px solid transparent;\n cursor: pointer;\n text-align: center;\n}\n\n.fb-ec--sel {\n border-color: #2563eb;\n transform: scale(1.05);\n box-shadow: 0 4px 15px rgba(37, 99, 235, 0.2);\n}\n\n.fb-ec--hov:not(.fb-ec--sel) {\n transform: scale(1.05);\n}\n\n.fb-eb {\n background: transparent;\n border: none;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n width: 100%;\n padding: 0;\n transition: all 200ms ease;\n}\n\n.fb-ei {\n font-size: 36px;\n transition: transform 200ms ease;\n}\n\n.fb-ei--hov {\n transform: scale(1.1);\n}\n\n.fb-el {\n font-size: 13px;\n font-weight: 600;\n color: currentColor;\n line-height: 1.2;\n}\n\n.fb-hdr {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 4px;\n margin-bottom: 10px;\n}\n\n.fb-msg {\n font-size: 14px;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n margin-bottom: 8px;\n border-radius: 6px;\n}\n\n.fb-msg--header {\n font-size: 12px;\n padding: 4px 8px;\n margin-bottom: 0;\n margin-left: auto;\n margin-right: 8px;\n}\n\n.fb-msg--ok {\n background-color: #f0fdf4;\n border: 1px solid #bbf7d0;\n color: #16a34a;\n}\n\n.fb-msg--err {\n background-color: #fef2f2;\n border: 1px solid #fecaca;\n color: #dc2626;\n}\n\n.fb-sub {\n width: 100%;\n padding: 16px 24px;\n border: none;\n border-radius: 12px;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n transition: all 200ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.fb-sub--dis {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.fb-spin {\n width: 16px;\n height: 16px;\n border: 2px solid transparent;\n border-top: 2px solid currentColor;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n.fb-cnt {\n padding: 24px;\n overflow: auto;\n max-height: calc(90vh - 48px);\n}\n\n.fb-ttl {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n}\n\n.fb-ta {\n width: 100%;\n min-height: 100px;\n padding: 12px;\n border-radius: 8px;\n font-size: 14px;\n font-family: inherit;\n outline: none;\n resize: vertical;\n transition: border-color 150ms ease;\n margin-bottom: 4px;\n box-sizing: border-box;\n}\n\n.fb-charcount {\n font-size: 12px;\n margin-left: auto;\n margin-bottom: 8px;\n text-align: right;\n}\n\n.fb-charcount--low {\n color: #dc2626;\n}\n\n.fb-email {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.fb-email-lbl {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.fb-email-cb {\n margin: 0;\n cursor: pointer;\n}\n\n.fb-email-inp {\n width: 100%;\n padding: 8px 12px;\n border-radius: 4px;\n font-size: 14px;\n outline: none;\n transition: border-color 150ms ease;\n box-sizing: border-box;\n}\n\n.fb-btn {\n position: fixed;\n width: 50px;\n height: 50px;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 18px;\n transition: all 300ms cubic-bezier(0.68, -0.55, 0.265, 1.55);\n z-index: 9998;\n color: #ffffff;\n top: 50%;\n transform: translateY(-50%);\n box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n\n.fb-btn--right {\n right: -25px;\n border-radius: 40px 0 0 40px;\n padding-right: 8px;\n box-shadow: -4px 0 15px rgba(37, 99, 235, 0.3);\n}\n\n.fb-btn--left {\n left: -25px;\n border-radius: 0 40px 40px 0;\n padding-left: 8px;\n box-shadow: 4px 0 15px rgba(37, 99, 235, 0.3);\n}\n\n.fb-btn--right.fb-btn--open {\n right: -15px;\n transform: translateY(-50%) scale(1.05);\n}\n\n.fb-btn--left.fb-btn--open {\n left: -15px;\n transform: translateY(-50%) scale(1.05);\n}\n\n.fb-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.3);\n transition: opacity 300ms ease;\n z-index: 9999;\n backdrop-filter: blur(8px);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n\n.fb-pnl-base {\n position: fixed;\n top: 10vh;\n width: 400px;\n max-width: 90vw;\n max-height: 60vh;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n transition: transform 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94);\n z-index: 10000;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n overflow-x: hidden;\n border-radius: 16px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n\n.fb-pnl--right { right: 0; }\n.fb-pnl--right.fb-pnl--open { transform: translateX(0px); }\n.fb-pnl--right.fb-pnl--closed { transform: translateX(100%); }\n\n.fb-pnl--left { left: 0; }\n.fb-pnl--left.fb-pnl--open { transform: translateX(0px); }\n.fb-pnl--left.fb-pnl--closed { transform: translateX(-100%); }\n\n.fb-close-btn {\n background: none;\n border: none;\n font-size: 24px;\n cursor: pointer;\n opacity: 0.7;\n padding: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color 150ms ease;\n}\n\n.fb-up {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.fb-upb {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n align-self: flex-start;\n padding: 8px 12px;\n border-radius: 8px;\n background: transparent;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 150ms ease, opacity 150ms ease;\n font-family: inherit;\n}\n\n.fb-upb:hover:not(.fb-upb--dis) {\n background-color: rgba(37, 99, 235, 0.06);\n}\n\n.fb-upb--dis {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.fb-ups {\n width: 12px;\n height: 12px;\n border: 2px solid transparent;\n border-top: 2px solid currentColor;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n display: inline-block;\n}\n\n.fb-up-extras {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.fb-upe {\n font-size: 12px;\n color: #dc2626;\n}\n\n.fb-ss {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.fb-sp {\n position: relative;\n width: 64px;\n height: 64px;\n border-radius: 6px;\n overflow: hidden;\n border: 1px solid rgba(0, 0, 0, 0.08);\n}\n\n.fb-si {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.fb-sr {\n position: absolute;\n top: 2px;\n right: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: none;\n background: rgba(0, 0, 0, 0.65);\n color: #fff;\n font-size: 11px;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n}\n\n.fb-sr:hover {\n background: rgba(0, 0, 0, 0.85);\n}\n\n.fb-sl {\n font-size: 11px;\n opacity: 0.6;\n}\n\n@media (max-width: 768px) {\n .fb-pnl-base {\n width: 100% !important;\n max-width: none !important;\n top: 5vh !important;\n max-height: 70vh !important;\n }\n .fb-cnt { padding: 20px !important; max-height: calc(100vh - 80px) !important; }\n .fb-ta { font-size: 16px !important; min-height: 80px !important; }\n .fb-ttl { font-size: 18px !important; }\n .fb-ei { font-size: 24px !important; }\n .fb-el { font-size: 11px !important; }\n .fb-sub { padding: 14px 20px !important; font-size: 16px !important; }\n}\n`\n\nexport function injectFeedbackCSS(): void {\n\tif (typeof document === 'undefined') return\n\tconst styleId = 'usero-feedback-widget-css'\n\tif (document.getElementById(styleId)) return\n\tconst style = document.createElement('style')\n\tstyle.id = styleId\n\tstyle.textContent = FEEDBACK_CSS\n\tdocument.head.appendChild(style)\n}\n","// Framework-free Usero widget. Renders into a shadow root attached to a\n// container <div> on document.body so host page styles cannot bleed in\n// and our class names cannot collide with the host's.\n//\n// API:\n// const widget = initUseroFeedbackWidget({ clientId: '...' })\n// widget.destroy()\n//\n// The endpoint and request shape match the React widget exactly so a\n// feedback row created here is indistinguishable from one created via React.\n\nimport { FeedbackApiClient } from './api'\nimport { getGradientEnd } from './colorUtils'\nimport {\n\tDARK_THEME,\n\tDEFAULT_THEME,\n\tEMOJI_BACKGROUNDS,\n\tEMOJI_MAP,\n\ttype FeedbackData,\n\ttype FeedbackRating,\n\ttype FeedbackSubmission,\n\ttype FeedbackWidgetProps,\n\tmergeTheme,\n\tRATING_LABELS,\n\ttype ScreenshotData,\n\ttype WidgetPosition,\n\ttype WidgetTheme,\n} from './types'\nimport { validateFeedbackSubmission } from './validation'\nimport { FEEDBACK_CSS } from './widgetCss'\n\nexport {\n\tDARK_THEME,\n\tDEFAULT_THEME,\n\tmergeTheme,\n}\nexport type {\n\tFeedbackData,\n\tFeedbackRating,\n\tFeedbackSubmission,\n\tFeedbackWidgetProps,\n\tScreenshotData,\n\tWidgetPosition,\n\tWidgetTheme,\n} from './types'\n\nexport interface UseroWidgetHandle {\n\tdestroy: () => void\n\topen: () => void\n\tclose: () => void\n\t// Hot-swap any subset of props EXCEPT `clientId` and `baseUrl`. Changing\n\t// those requires destroy + re-init (the API client is bound to baseUrl,\n\t// and clientId is the identity of the widget). Callers (e.g. the React\n\t// wrapper) typically route callbacks through this so identity changes on\n\t// re-render don't force a tear-down.\n\tupdate: (next: Partial<Omit<FeedbackWidgetProps, 'clientId' | 'baseUrl'>>) => void\n}\n\nconst EMAIL_STORAGE_KEY = 'feedback_user_email'\n\nfunction escapeHtml(value: string): string {\n\treturn value.replace(/[&<>\"']/g, ch => {\n\t\tswitch (ch) {\n\t\t\tcase '&':\n\t\t\t\treturn '&amp;'\n\t\t\tcase '<':\n\t\t\t\treturn '&lt;'\n\t\t\tcase '>':\n\t\t\t\treturn '&gt;'\n\t\t\tcase '\"':\n\t\t\t\treturn '&quot;'\n\t\t\tcase \"'\":\n\t\t\t\treturn '&#x27;'\n\t\t\tdefault:\n\t\t\t\treturn ch\n\t\t}\n\t})\n}\n\nfunction readStoredEmail(): string {\n\tif (typeof window === 'undefined') return ''\n\ttry {\n\t\treturn window.localStorage.getItem(EMAIL_STORAGE_KEY) ?? ''\n\t} catch {\n\t\treturn ''\n\t}\n}\n\nfunction writeStoredEmail(email: string): void {\n\ttry {\n\t\twindow.localStorage.setItem(EMAIL_STORAGE_KEY, email)\n\t} catch {\n\t\t// ignore\n\t}\n}\n\nexport function initUseroFeedbackWidget(\n\tprops: FeedbackWidgetProps,\n): UseroWidgetHandle {\n\tif (typeof document === 'undefined') {\n\t\treturn {\n\t\t\tdestroy: () => {},\n\t\t\topen: () => {},\n\t\t\tclose: () => {},\n\t\t\tupdate: () => {},\n\t\t}\n\t}\n\n\tconst { clientId, baseUrl } = props\n\n\tif (!clientId || clientId.length < 3) {\n\t\tconst err = new Error('Invalid config. Contact admin.')\n\t\tprops.onError?.(err)\n\t\treturn {\n\t\t\tdestroy: () => {},\n\t\t\topen: () => {},\n\t\t\tclose: () => {},\n\t\t\tupdate: () => {},\n\t\t}\n\t}\n\n\t// Mutable view of every prop that can be hot-swapped via update(). Read\n\t// these at render time, never destructure into local const above the\n\t// render closures or you'll capture stale values.\n\tlet position: WidgetPosition = props.position ?? 'right'\n\tlet theme: WidgetTheme = mergeTheme(props.theme)\n\tlet title: string = props.title ?? 'Share Feedback'\n\tlet placeholder: string = props.placeholder ?? 'Tell us what you think... (optional)'\n\tlet showEmailOption: boolean = props.showEmailOption ?? true\n\tlet showScreenshotOption: boolean = props.showScreenshotOption ?? true\n\tlet environment: string | undefined = props.environment\n\tlet metadata: Record<string, unknown> | undefined = props.metadata\n\tlet onSubmit: FeedbackWidgetProps['onSubmit'] = props.onSubmit\n\tlet onError: FeedbackWidgetProps['onError'] = props.onError\n\tlet onOpen: FeedbackWidgetProps['onOpen'] = props.onOpen\n\tlet onClose: FeedbackWidgetProps['onClose'] = props.onClose\n\n\tconst apiClient = new FeedbackApiClient(baseUrl)\n\n\t// State\n\tlet isOpen = false\n\tlet selectedRating: FeedbackRating | undefined = undefined\n\tlet comment = ''\n\tlet shareEmail = false\n\tlet userEmail = readStoredEmail()\n\tlet isSubmitting = false\n\tlet submitMessage: { type: 'success' | 'error'; text: string } | null = null\n\tlet screenshots: ScreenshotData[] = []\n\tlet isUploadingScreenshot = false\n\tlet screenshotError: string | null = null\n\n\tconst MAX_SCREENSHOTS = 3\n\tconst MAX_SCREENSHOT_BYTES = 10 * 1024 * 1024 // 10MB, matches old React widget\n\n\t// Host element on the page. ShadowRoot keeps host CSS isolated.\n\tconst host = document.createElement('div')\n\thost.setAttribute('data-usero-widget', '')\n\t// position: static so the host element doesn't take any space; the\n\t// fixed-position children inside the shadow root anchor to the viewport.\n\thost.style.cssText = 'all: initial;'\n\tdocument.body.appendChild(host)\n\tconst root = host.attachShadow({ mode: 'open' })\n\n\t// Inject styles once into the shadow root.\n\tconst style = document.createElement('style')\n\tstyle.textContent = FEEDBACK_CSS\n\troot.appendChild(style)\n\n\t// Containers\n\tconst buttonEl = document.createElement('button')\n\tconst backdropEl = document.createElement('div')\n\tconst panelEl = document.createElement('div')\n\troot.appendChild(buttonEl)\n\troot.appendChild(backdropEl)\n\troot.appendChild(panelEl)\n\n\tfunction setSubmitMessage(\n\t\tnext: { type: 'success' | 'error'; text: string } | null,\n\t): void {\n\t\tsubmitMessage = next\n\t\trender()\n\t}\n\n\tfunction open(): void {\n\t\tif (isOpen) return\n\t\tisOpen = true\n\t\t// Reset transient state\n\t\tselectedRating = undefined\n\t\tcomment = ''\n\t\tshareEmail = false\n\t\tsubmitMessage = null\n\t\tscreenshots = []\n\t\tscreenshotError = null\n\t\tisUploadingScreenshot = false\n\t\tapiClient.ping()\n\t\tonOpen?.()\n\t\trender()\n\t}\n\n\tasync function handleScreenshotFile(file: File): Promise<void> {\n\t\tscreenshotError = null\n\t\tif (!file.type.startsWith('image/')) {\n\t\t\tscreenshotError = 'Image files only'\n\t\t\trender()\n\t\t\treturn\n\t\t}\n\t\tif (file.size > MAX_SCREENSHOT_BYTES) {\n\t\t\tscreenshotError = 'Max 10MB'\n\t\t\trender()\n\t\t\treturn\n\t\t}\n\t\tif (screenshots.length >= MAX_SCREENSHOTS) {\n\t\t\tscreenshotError = `Max ${MAX_SCREENSHOTS} screenshots`\n\t\t\trender()\n\t\t\treturn\n\t\t}\n\n\t\tisUploadingScreenshot = true\n\t\trender()\n\t\ttry {\n\t\t\tconst uploaded = await apiClient.uploadScreenshot(file, clientId)\n\t\t\tscreenshots = [...screenshots, uploaded]\n\t\t} catch (err) {\n\t\t\tscreenshotError = err instanceof Error ? err.message : 'Upload failed'\n\t\t} finally {\n\t\t\tisUploadingScreenshot = false\n\t\t\trender()\n\t\t}\n\t}\n\n\tfunction removeScreenshot(index: number): void {\n\t\tscreenshots = screenshots.filter((_, i) => i !== index)\n\t\trender()\n\t}\n\n\tfunction close(): void {\n\t\tif (!isOpen) return\n\t\tisOpen = false\n\t\tonClose?.()\n\t\trender()\n\t}\n\n\tasync function submitForm(): Promise<void> {\n\t\tif (isSubmitting) return\n\t\tisSubmitting = true\n\t\tsubmitMessage = null\n\t\trender()\n\n\t\tconst feedbackData: FeedbackData = {\n\t\t\trating: selectedRating,\n\t\t\tcomment: comment.trim() || undefined,\n\t\t\tuserEmail: shareEmail ? userEmail : undefined,\n\t\t\tscreenshots: screenshots.length > 0 ? screenshots : undefined,\n\t\t\tmetadata: {\n\t\t\t\tpageUrl: window.location.href,\n\t\t\t\tpageTitle: document.title || 'Untitled Page',\n\t\t\t\treferrer: document.referrer || undefined,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t},\n\t\t}\n\n\t\tconst submission: FeedbackSubmission = {\n\t\t\tclientId,\n\t\t\trating: feedbackData.rating,\n\t\t\tcomment: feedbackData.comment,\n\t\t\tuserEmail: feedbackData.userEmail,\n\t\t\tpageUrl: feedbackData.metadata.pageUrl,\n\t\t\tpageTitle: feedbackData.metadata.pageTitle,\n\t\t\treferrer: feedbackData.metadata.referrer,\n\t\t\tenvironment,\n\t\t}\n\t\tif (screenshots.length > 0) submission.screenshots = screenshots\n\t\tif (metadata !== undefined) submission.metadata = metadata\n\n\t\tconst validation = validateFeedbackSubmission(submission)\n\t\tif (!validation.isValid) {\n\t\t\tisSubmitting = false\n\t\t\tsetSubmitMessage({ type: 'error', text: validation.errors.join(', ') })\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await apiClient.submitFeedback(submission)\n\t\t\tif (response.success) {\n\t\t\t\tif (shareEmail && userEmail) writeStoredEmail(userEmail)\n\t\t\t\tonSubmit?.(feedbackData)\n\t\t\t\tselectedRating = undefined\n\t\t\t\tcomment = ''\n\t\t\t\tshareEmail = false\n\t\t\t\tscreenshots = []\n\t\t\t\tscreenshotError = null\n\t\t\t\tsubmitMessage = { type: 'success', text: 'Thank you!' }\n\t\t\t} else {\n\t\t\t\tconst msg = response.error ?? 'Error occurred. Try again.'\n\t\t\t\tonError?.(new Error(msg))\n\t\t\t\tsubmitMessage = { type: 'error', text: msg }\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : 'Error occurred. Try again.'\n\t\t\tonError?.(new Error(msg))\n\t\t\tsubmitMessage = { type: 'error', text: msg }\n\t\t} finally {\n\t\t\tisSubmitting = false\n\t\t\trender()\n\t\t}\n\t}\n\n\t// Static button content + styles (only style.background changes once)\n\tfunction renderButton(): void {\n\t\tbuttonEl.className = `fb-btn fb-btn--${position} ${isOpen ? 'fb-btn--open' : ''}`\n\t\tbuttonEl.setAttribute('aria-label', 'Open feedback')\n\t\tbuttonEl.type = 'button'\n\t\tbuttonEl.style.background = `linear-gradient(135deg, ${theme.primary}, ${getGradientEnd(theme.primary)})`\n\t\tbuttonEl.innerHTML = isOpen\n\t\t\t? `<span style=\"font-size:20px;\">✕</span>`\n\t\t\t: ''\n\t}\n\n\tfunction renderBackdrop(): void {\n\t\tbackdropEl.className = 'fb-backdrop'\n\t\tbackdropEl.style.display = isOpen ? 'block' : 'none'\n\t\tbackdropEl.setAttribute('aria-label', 'Close modal')\n\t}\n\n\tfunction renderPanel(): void {\n\t\tpanelEl.className = `fb-pnl-base fb-pnl--${position} ${\n\t\t\tisOpen ? 'fb-pnl--open' : 'fb-pnl--closed'\n\t\t}`\n\t\tpanelEl.style.backgroundColor = theme.background\n\t\tif (position === 'right') {\n\t\t\tpanelEl.style.borderLeft = `1px solid ${theme.border}`\n\t\t\tpanelEl.style.borderRight = ''\n\t\t} else {\n\t\t\tpanelEl.style.borderRight = `1px solid ${theme.border}`\n\t\t\tpanelEl.style.borderLeft = ''\n\t\t}\n\t\tpanelEl.setAttribute('role', 'dialog')\n\t\tpanelEl.setAttribute('aria-modal', 'true')\n\t\tpanelEl.setAttribute('aria-labelledby', 'usero-feedback-title')\n\n\t\tconst remaining = 1000 - comment.length\n\t\tconst lowChars = remaining < 50\n\n\t\tconst ratingsHtml = ([1, 2, 3, 4] as FeedbackRating[])\n\t\t\t.map(r => {\n\t\t\t\tconst sel = selectedRating === r\n\t\t\t\tconst bg = EMOJI_BACKGROUNDS[r]\n\t\t\t\tconst cls = ['fb-ec', sel && 'fb-ec--sel'].filter(Boolean).join(' ')\n\t\t\t\treturn `\n\t\t\t\t\t<div class=\"${cls}\" style=\"background:${bg}\">\n\t\t\t\t\t\t<button type=\"button\" class=\"fb-eb\" data-rating=\"${r}\" role=\"radio\" aria-checked=\"${sel}\" aria-label=\"${r}: ${RATING_LABELS[r]}\">\n\t\t\t\t\t\t\t<div class=\"fb-ei\"><span role=\"img\" aria-label=\"${RATING_LABELS[r]}\">${EMOJI_MAP[r]}</span></div>\n\t\t\t\t\t\t\t<div class=\"fb-el\">${RATING_LABELS[r]}</div>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t`\n\t\t\t})\n\t\t\t.join('')\n\n\t\tconst messageHtml = submitMessage\n\t\t\t? `<div class=\"fb-msg fb-msg--header ${submitMessage.type === 'success' ? 'fb-msg--ok' : 'fb-msg--err'}\">${submitMessage.type === 'success' ? '✓' : '⚠'} ${escapeHtml(submitMessage.text)}</div>`\n\t\t\t: ''\n\n\t\tconst screenshotBlockHtml = showScreenshotOption\n\t\t\t? (() => {\n\t\t\t\t\tconst atMax = screenshots.length >= MAX_SCREENSHOTS\n\t\t\t\t\tconst btnDisabled = isUploadingScreenshot || atMax\n\t\t\t\t\tconst previewsHtml = screenshots\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(shot, i) => `\n\t\t\t\t\t\t\t\t<div class=\"fb-sp\">\n\t\t\t\t\t\t\t\t\t<img src=\"${escapeHtml(shot.url)}\" alt=\"Screenshot ${i + 1}\" class=\"fb-si\" />\n\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"fb-sr\" data-role=\"screenshot-remove\" data-index=\"${i}\" aria-label=\"Remove screenshot\">✕</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.join('')\n\t\t\t\t\tconst errorHtml = screenshotError\n\t\t\t\t\t\t? `<div class=\"fb-upe\">⚠ ${escapeHtml(screenshotError)}</div>`\n\t\t\t\t\t\t: ''\n\t\t\t\t\tconst limitHtml = atMax\n\t\t\t\t\t\t? `<div class=\"fb-sl\">Max ${MAX_SCREENSHOTS}</div>`\n\t\t\t\t\t\t: ''\n\t\t\t\t\tconst extrasHtml =\n\t\t\t\t\t\tscreenshotError || screenshots.length > 0 || atMax\n\t\t\t\t\t\t\t? `<div class=\"fb-up-extras\">${errorHtml}${\n\t\t\t\t\t\t\t\t\tscreenshots.length > 0\n\t\t\t\t\t\t\t\t\t\t? `<div class=\"fb-ss\">${previewsHtml}</div>`\n\t\t\t\t\t\t\t\t\t\t: ''\n\t\t\t\t\t\t\t\t}${limitHtml}</div>`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\treturn `\n\t\t\t\t\t\t<div class=\"fb-up\">\n\t\t\t\t\t\t\t<input type=\"file\" accept=\"image/*\" data-role=\"screenshot-input\" style=\"display:none;\" aria-label=\"Choose screenshot\" />\n\t\t\t\t\t\t\t<button type=\"button\" class=\"fb-upb ${btnDisabled ? 'fb-upb--dis' : ''}\" data-role=\"screenshot-pick\" ${btnDisabled ? 'disabled' : ''} style=\"border:1px solid ${theme.border};color:${theme.text};\">\n\t\t\t\t\t\t\t\t${\n\t\t\t\t\t\t\t\t\tisUploadingScreenshot\n\t\t\t\t\t\t\t\t\t\t? '<span class=\"fb-ups\"></span> Uploading...'\n\t\t\t\t\t\t\t\t\t\t: '📷 Add screenshot'\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t${extrasHtml}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`\n\t\t\t\t})()\n\t\t\t: ''\n\n\t\tconst emailBlockHtml = showEmailOption\n\t\t\t? `\n\t\t\t\t<div class=\"fb-email\">\n\t\t\t\t\t<label class=\"fb-email-lbl\" style=\"color:${theme.text}\">\n\t\t\t\t\t\t<input type=\"checkbox\" class=\"fb-email-cb\" data-role=\"share-email\" ${shareEmail ? 'checked' : ''} aria-label=\"Share email\" />\n\t\t\t\t\t\t<span>Share my email</span>\n\t\t\t\t\t</label>\n\t\t\t\t\t${\n\t\t\t\t\t\tshareEmail\n\t\t\t\t\t\t\t? `<input type=\"email\" class=\"fb-email-inp\" data-role=\"email-input\" value=\"${escapeHtml(userEmail)}\" placeholder=\"your.email@example.com\" aria-label=\"Email\" maxlength=\"254\" autocomplete=\"email\" style=\"border:1px solid ${theme.border};color:${theme.text};background-color:${theme.background};\" />`\n\t\t\t\t\t\t\t: ''\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t`\n\t\t\t: ''\n\n\t\tconst submitDisabled = isSubmitting\n\t\tconst submitStyle = `background:linear-gradient(135deg, ${theme.primary}, ${getGradientEnd(theme.primary)});color:#ffffff;${submitDisabled ? 'opacity:0.6;cursor:not-allowed;' : ''}`\n\n\t\tpanelEl.innerHTML = `\n\t\t\t<div class=\"fb-cnt\">\n\t\t\t\t<div class=\"fb-hdr\" style=\"border-bottom:1px solid ${theme.border}\">\n\t\t\t\t\t<h2 id=\"usero-feedback-title\" class=\"fb-ttl\" style=\"color:${theme.text}\">${escapeHtml(title)}</h2>\n\t\t\t\t\t${messageHtml}\n\t\t\t\t\t<button class=\"fb-close-btn\" data-role=\"close\" style=\"color:${theme.text}\" aria-label=\"Close\" type=\"button\">✕</button>\n\t\t\t\t</div>\n\t\t\t\t<form data-role=\"form\">\n\t\t\t\t\t<div class=\"fb-es\" role=\"radiogroup\" aria-label=\"Rate experience\">${ratingsHtml}</div>\n\t\t\t\t\t<textarea class=\"fb-ta\" data-role=\"comment\" placeholder=\"${escapeHtml(placeholder)}\" aria-label=\"Comments\" maxlength=\"1000\" rows=\"2\" style=\"border:1px solid ${theme.border};color:${theme.text};background-color:${theme.background};\">${escapeHtml(comment)}</textarea>\n\t\t\t\t\t<div style=\"display:flex;justify-content:flex-end;margin-bottom:8px;\">\n\t\t\t\t\t\t<div style=\"font-size:12px;color:${lowChars ? '#dc2626' : theme.text};opacity:${lowChars ? 1 : 0.6};margin-left:auto;\">\n\t\t\t\t\t\t\t${remaining} chars remaining\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t${screenshotBlockHtml}\n\t\t\t\t\t${emailBlockHtml}\n\t\t\t\t\t<button class=\"fb-sub ${submitDisabled ? 'fb-sub--dis' : ''}\" type=\"submit\" aria-label=\"Submit\" ${submitDisabled ? 'disabled' : ''} style=\"${submitStyle}\">\n\t\t\t\t\t\t${isSubmitting ? '<span class=\"fb-spin\"></span>' : ''}\n\t\t\t\t\t\t${isSubmitting ? 'Submitting...' : 'Send Feedback 🚀'}\n\t\t\t\t\t</button>\n\t\t\t\t</form>\n\t\t\t</div>\n\t\t`\n\n\t\t// Wire up panel-internal events\n\t\tconst form = panelEl.querySelector<HTMLFormElement>('form[data-role=\"form\"]')\n\t\tform?.addEventListener('submit', e => {\n\t\t\te.preventDefault()\n\t\t\tvoid submitForm()\n\t\t})\n\n\t\tpanelEl\n\t\t\t.querySelector<HTMLButtonElement>('button[data-role=\"close\"]')\n\t\t\t?.addEventListener('click', close)\n\n\t\tpanelEl\n\t\t\t.querySelectorAll<HTMLButtonElement>('button[data-rating]')\n\t\t\t.forEach(btn => {\n\t\t\t\tbtn.addEventListener('click', () => {\n\t\t\t\t\tconst value = btn.dataset.rating\n\t\t\t\t\tif (value === '1' || value === '2' || value === '3' || value === '4') {\n\t\t\t\t\t\tselectedRating = Number(value) as FeedbackRating\n\t\t\t\t\t\trender()\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\n\t\tconst textarea = panelEl.querySelector<HTMLTextAreaElement>(\n\t\t\t'textarea[data-role=\"comment\"]',\n\t\t)\n\t\tif (textarea) {\n\t\t\ttextarea.addEventListener('input', () => {\n\t\t\t\tif (textarea.value.length <= 1000) {\n\t\t\t\t\tcomment = textarea.value\n\t\t\t\t\t// Update char count without full rerender to avoid losing focus.\n\t\t\t\t\tconst counter = panelEl.querySelector<HTMLDivElement>(\n\t\t\t\t\t\t'.fb-cnt form > div > div',\n\t\t\t\t\t)\n\t\t\t\t\tif (counter) {\n\t\t\t\t\t\tconst left = 1000 - comment.length\n\t\t\t\t\t\tcounter.textContent = `${left} chars remaining`\n\t\t\t\t\t\tcounter.style.color = left < 50 ? '#dc2626' : theme.text\n\t\t\t\t\t\tcounter.style.opacity = left < 50 ? '1' : '0.6'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tconst shareCb = panelEl.querySelector<HTMLInputElement>(\n\t\t\t'input[data-role=\"share-email\"]',\n\t\t)\n\t\tshareCb?.addEventListener('change', () => {\n\t\t\tshareEmail = shareCb.checked\n\t\t\trender()\n\t\t})\n\n\t\tconst emailInp = panelEl.querySelector<HTMLInputElement>(\n\t\t\t'input[data-role=\"email-input\"]',\n\t\t)\n\t\temailInp?.addEventListener('input', () => {\n\t\t\tif (emailInp.value.length <= 254) {\n\t\t\t\tuserEmail = emailInp.value\n\t\t\t}\n\t\t})\n\n\t\tconst fileInput = panelEl.querySelector<HTMLInputElement>(\n\t\t\t'input[data-role=\"screenshot-input\"]',\n\t\t)\n\t\tconst pickBtn = panelEl.querySelector<HTMLButtonElement>(\n\t\t\t'button[data-role=\"screenshot-pick\"]',\n\t\t)\n\t\tpickBtn?.addEventListener('click', () => {\n\t\t\tfileInput?.click()\n\t\t})\n\t\tfileInput?.addEventListener('change', () => {\n\t\t\tconst file = fileInput.files?.[0]\n\t\t\tif (!file) return\n\t\t\tvoid handleScreenshotFile(file).finally(() => {\n\t\t\t\tif (fileInput) fileInput.value = ''\n\t\t\t})\n\t\t})\n\t\tpanelEl\n\t\t\t.querySelectorAll<HTMLButtonElement>(\n\t\t\t\t'button[data-role=\"screenshot-remove\"]',\n\t\t\t)\n\t\t\t.forEach(btn => {\n\t\t\t\tbtn.addEventListener('click', () => {\n\t\t\t\t\tconst idx = Number(btn.dataset.index)\n\t\t\t\t\tif (Number.isInteger(idx)) removeScreenshot(idx)\n\t\t\t\t})\n\t\t\t})\n\t}\n\n\tfunction render(): void {\n\t\trenderButton()\n\t\trenderBackdrop()\n\t\trenderPanel()\n\t}\n\n\t// Top-level event listeners\n\tbuttonEl.addEventListener('click', () => {\n\t\tif (isOpen) close()\n\t\telse open()\n\t})\n\tbackdropEl.addEventListener('click', close)\n\n\tconst onKeyDown = (e: KeyboardEvent): void => {\n\t\tif (!isOpen) return\n\t\tif (e.key === 'Escape') close()\n\t\tif (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n\t\t\te.preventDefault()\n\t\t\tvoid submitForm()\n\t\t}\n\t}\n\tdocument.addEventListener('keydown', onKeyDown)\n\n\t// Initial paint\n\trender()\n\n\tlet destroyed = false\n\treturn {\n\t\tdestroy: () => {\n\t\t\tif (destroyed) return\n\t\t\tdestroyed = true\n\t\t\tdocument.removeEventListener('keydown', onKeyDown)\n\t\t\thost.remove()\n\t\t},\n\t\topen,\n\t\tclose,\n\t\tupdate: next => {\n\t\t\tif (destroyed) return\n\t\t\tlet needsRender = false\n\t\t\tif (next.position !== undefined && next.position !== position) {\n\t\t\t\tposition = next.position\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\tif (next.theme !== undefined) {\n\t\t\t\ttheme = mergeTheme(next.theme)\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\tif (next.title !== undefined && next.title !== title) {\n\t\t\t\ttitle = next.title\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\tif (next.placeholder !== undefined && next.placeholder !== placeholder) {\n\t\t\t\tplaceholder = next.placeholder\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\tif (\n\t\t\t\tnext.showEmailOption !== undefined &&\n\t\t\t\tnext.showEmailOption !== showEmailOption\n\t\t\t) {\n\t\t\t\tshowEmailOption = next.showEmailOption\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\tif (\n\t\t\t\tnext.showScreenshotOption !== undefined &&\n\t\t\t\tnext.showScreenshotOption !== showScreenshotOption\n\t\t\t) {\n\t\t\t\tshowScreenshotOption = next.showScreenshotOption\n\t\t\t\tneedsRender = true\n\t\t\t}\n\t\t\t// Non-render-affecting props: just swap refs.\n\t\t\tif ('environment' in next) environment = next.environment\n\t\t\tif ('metadata' in next) metadata = next.metadata\n\t\t\tif ('onSubmit' in next) onSubmit = next.onSubmit\n\t\t\tif ('onError' in next) onError = next.onError\n\t\t\tif ('onOpen' in next) onOpen = next.onOpen\n\t\t\tif ('onClose' in next) onClose = next.onClose\n\t\t\tif (needsRender) render()\n\t\t},\n\t}\n}\n"]}