@reqdesk/widget 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{react-DYAKyC3I.d.ts → react-Bmwfo1Qg.d.ts} +7 -7
- package/dist/{react-DYAKyC3I.d.ts.map → react-Bmwfo1Qg.d.ts.map} +1 -1
- package/dist/react.cjs +4 -9
- package/dist/react.d.ts +1 -1
- package/dist/react.js +4 -9
- package/dist/react.js.map +1 -1
- package/dist/{storage-BG7rsgWE.js → storage-0JN8SJi5.js} +2 -2
- package/dist/storage-0JN8SJi5.js.map +1 -0
- package/dist/{storage-Cx5p1yP-.cjs → storage-D5ZsuiB1.cjs} +1 -1
- package/package.json +1 -1
- package/dist/storage-BG7rsgWE.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_storage = require("./storage-
|
|
2
|
+
const require_storage = require("./storage-D5ZsuiB1.cjs");
|
|
3
3
|
//#region src/shadow-dom.ts
|
|
4
4
|
let shadowRoot = null;
|
|
5
5
|
let hostEl = null;
|
package/dist/index.iife.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var ReqdeskWidget=(function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let n=``,r=``;function i(e,t){r=e.replace(/\/$/,``),n=t}let a=t.ofetch.create({timeout:15e3,retry:2,retryStatusCodes:[408,429,500,502,503,504],async onRequest({options:e}){e.baseURL=`${r}/api/v1`;let t=new Headers(e.headers);t.set(`X-API-Key`,n),e.headers=t},onResponseError({response:e}){let t=e._data;throw{code:t?.responseCode??`HTTP_${e.status}`,message:t?.responseMessage??e.statusText}}});function o(){return crypto.randomUUID()}async function s(e,t){let n=await a(`/projects/${e}/tickets`,{method:`POST`,body:{title:t.title,description:t.description,priority:t.priority,categoryId:t.categoryId,email:t.email,clientMetadata:t.clientMetadata},headers:{"Idempotency-Key":o()}});return{id:n.data.id,ticketNumber:n.data.attributes.ticketNumber,trackingToken:n.meta?.trackingToken,status:n.data.attributes.status}}async function c(e){let t=await a(`/tickets/track?token=${encodeURIComponent(e)}`),n=t.included??[];return{id:t.data.id,ticketNumber:t.data.attributes.ticketNumber,title:t.data.attributes.title,status:t.data.attributes.status,priority:t.data.attributes.priority,createdAt:t.data.attributes.createdAt,replies:n.filter(e=>e.type===`public-reply`).map(e=>({id:e.id,body:e.attributes.body,authorName:e.attributes.authorName,isStaff:e.attributes.isStaff,createdAt:e.attributes.createdAt}))}}async function l(e,t){await a(`/tickets/track/reply`,{method:`POST`,body:{trackingToken:e,body:t}})}let u={"widget.title":`Support`,"widget.newTicket":`New Ticket`,"widget.trackTicket":`Track Ticket`,"form.title":`Title`,"form.titlePlaceholder":`Brief summary of your issue`,"form.description":`Description`,"form.descriptionPlaceholder":`Describe your issue in detail...`,"form.email":`Email`,"form.emailPlaceholder":`your@email.com`,"form.priority":`Priority`,"form.priorityLow":`Low`,"form.priorityMedium":`Medium`,"form.priorityHigh":`High`,"form.priorityUrgent":`Urgent`,"form.category":`Category`,"form.categoryNone":`Select a category`,"form.submit":`Submit Ticket`,"form.submitting":`Submitting...`,"form.cancel":`Cancel`,"form.attachment":`Attach files`,"success.title":`Ticket Submitted!`,"success.ticketNumber":`Ticket #`,"success.trackingToken":`Your tracking token:`,"success.trackingHint":`Save this token to track your ticket status.`,"success.copyToken":`Copy Token`,"success.copied":`Copied!`,"success.close":`Close`,"success.trackNow":`Track Ticket`,"tracker.title":`Track Your Ticket`,"tracker.tokenPlaceholder":`Enter your tracking token (trk_...)`,"tracker.submit":`Track`,"tracker.tracking":`Tracking...`,"tracker.status":`Status`,"tracker.priority":`Priority`,"tracker.created":`Created`,"tracker.replies":`Replies`,"tracker.noReplies":`No replies yet.`,"tracker.replyPlaceholder":`Write a reply...`,"tracker.sendReply":`Send Reply`,"tracker.sending":`Sending...`,"tracker.back":`Back`,"tracker.staff":`Staff`,"error.generic":`Something went wrong. Please try again.`,"error.network":`Network error. Check your connection.`,"error.tokenInvalid":`Invalid or expired tracking token.`,"error.required":`This field is required.`,"error.emailInvalid":`Please enter a valid email address.`,"error.titleMin":`Title must be at least 5 characters.`,"portal.title":`Support Portal`,"portal.myTickets":`My Tickets`,"portal.noTickets":`No tickets yet.`,"portal.newTicket":`New Ticket`,"widget.close":`Close`,"menu.newTicket":`Submit a Ticket`,"menu.newTicketDesc":`Create a new support request`,"menu.myTickets":`My Tickets`,"menu.myTicketsDesc":`View and manage your tickets`,"menu.trackTicket":`Track a Ticket`,"menu.trackTicketDesc":`Check status with your tracking token`,"menu.knowledgeBase":`Knowledge Base`,"menu.knowledgeBaseDesc":`Browse help articles and guides`,"menu.myTicketsPlaceholder":`Sign in to view your tickets.`,"menu.trackPlaceholder":`Ticket tracking is coming soon.`,"menu.kbPlaceholder":`Knowledge base is coming soon.`,"menu.preferences":`Preferences`,"menu.preferencesDesc":`Language and appearance settings`,"prefs.title":`Preferences`,"prefs.language":`Language`,"prefs.theme":`Theme`,"prefs.light":`Light`,"prefs.dark":`Dark`,"prefs.auto":`System`,"branding.poweredBy":`Powered by`,"attach.dropzone":`Drop files here or click to browse`,"attach.dropzoneActive":`Drop files here`,"attach.maxFiles":`Maximum {max} files`,"attach.remove":`Remove`,"attach.uploading":`Uploading files...`,"attach.uploadProgress":`Uploading {name}... {percent}%`,"attach.invalidType":`File type not allowed`,"attach.tooLarge":`File exceeds maximum size`,"attach.tooMany":`Maximum number of files reached`,"attach.download":`Download`,"mytickets.title":`My Tickets`,"mytickets.emailPrompt":`Enter your email to view your tickets`,"mytickets.emailPlaceholder":`your@email.com`,"mytickets.rememberMe":`Remember me`,"mytickets.lookup":`Find My Tickets`,"mytickets.lookingUp":`Looking up...`,"mytickets.noTickets":`No tickets yet.`,"mytickets.submitFirst":`Submit your first ticket`,"mytickets.noAccount":`No tickets found for this email.`,"detail.description":`Description`,"detail.attachments":`Attachments`,"detail.noAttachments":`No attachments`,"detail.replies":`Conversation`,"detail.noReplies":`No replies yet.`,"detail.replyPlaceholder":`Write a reply...`,"detail.sendReply":`Send`,"detail.sending":`Sending...`,"detail.staff":`Staff`,"detail.you":`You`,"detail.loading":`Loading ticket...`,"track.title":`Track a Ticket`,"track.tokenPlaceholder":`Enter tracking token (trk_...)`,"track.submit":`Track`,"track.tracking":`Tracking...`,"track.recentTickets":`Recent Tickets`,"track.invalidToken":`Invalid or expired tracking token.`,"prefs.clearEmail":`Clear saved email`,"prefs.emailCleared":`Email cleared`,"auth.login":`Login`,"auth.logout":`Logout`,"auth.sessionExpired":`Session expired. Please log in again.`,"prefs.accentColor":`Accent Color`,"form.categoryPlaceholder":`Select a category`,"form.categoryBack":`Back`,"form.categorySelected":`Category`,"diag.title":`Share diagnostic info`,"diag.hint":`Help us resolve your issue faster`,"diag.screenResolution":`Screen resolution`,"diag.deviceType":`Device type`,"diag.timezone":`Timezone`,"diag.referrerUrl":`Referrer URL`,"diag.language":`Browser language`,"diag.platform":`Platform`,"detail.resolve":`Mark as Resolved`,"detail.resolving":`Resolving...`,"detail.resolved":`Resolved`,"detail.sla":`SLA`},d={"widget.title":`الدعم`,"widget.newTicket":`تذكرة جديدة`,"widget.trackTicket":`تتبع التذكرة`,"form.title":`العنوان`,"form.titlePlaceholder":`ملخص موجز لمشكلتك`,"form.description":`الوصف`,"form.descriptionPlaceholder":`صف مشكلتك بالتفصيل...`,"form.email":`البريد الإلكتروني`,"form.emailPlaceholder":`your@email.com`,"form.priority":`الأولوية`,"form.priorityLow":`منخفضة`,"form.priorityMedium":`متوسطة`,"form.priorityHigh":`عالية`,"form.priorityUrgent":`عاجلة`,"form.category":`الفئة`,"form.categoryNone":`اختر فئة`,"form.submit":`إرسال التذكرة`,"form.submitting":`جارِ الإرسال...`,"form.cancel":`إلغاء`,"form.attachment":`إرفاق ملفات`,"success.title":`تم إرسال التذكرة!`,"success.ticketNumber":`تذكرة #`,"success.trackingToken":`رمز التتبع الخاص بك:`,"success.trackingHint":`احفظ هذا الرمز لتتبع حالة تذكرتك.`,"success.copyToken":`نسخ الرمز`,"success.copied":`تم النسخ!`,"success.close":`إغلاق`,"success.trackNow":`تتبع التذكرة`,"tracker.title":`تتبع تذكرتك`,"tracker.tokenPlaceholder":`أدخل رمز التتبع الخاص بك (trk_...)`,"tracker.submit":`تتبع`,"tracker.tracking":`جارِ التتبع...`,"tracker.status":`الحالة`,"tracker.priority":`الأولوية`,"tracker.created":`تاريخ الإنشاء`,"tracker.replies":`الردود`,"tracker.noReplies":`لا توجد ردود بعد.`,"tracker.replyPlaceholder":`اكتب رداً...`,"tracker.sendReply":`إرسال الرد`,"tracker.sending":`جارِ الإرسال...`,"tracker.back":`رجوع`,"tracker.staff":`فريق الدعم`,"error.generic":`حدث خطأ ما. يرجى المحاولة مرة أخرى.`,"error.network":`خطأ في الشبكة. تحقق من اتصالك.`,"error.tokenInvalid":`رمز التتبع غير صالح أو منتهي الصلاحية.`,"error.required":`هذا الحقل مطلوب.`,"error.emailInvalid":`يرجى إدخال بريد إلكتروني صالح.`,"error.titleMin":`يجب أن يكون العنوان 5 أحرف على الأقل.`,"portal.title":`بوابة الدعم`,"portal.myTickets":`تذاكري`,"portal.noTickets":`لا توجد تذاكر بعد.`,"portal.newTicket":`تذكرة جديدة`,"widget.close":`إغلاق`,"menu.newTicket":`إرسال تذكرة`,"menu.newTicketDesc":`إنشاء طلب ��عم جديد`,"menu.myTickets":`تذاكري`,"menu.myTicketsDesc":`عرض وإدارة تذاكرك`,"menu.trackTicket":`تتبع تذكرة`,"menu.trackTicketDesc":`تحقق من الحالة باستخدام رمز التتبع`,"menu.knowledgeBase":`قاعدة المعرفة`,"menu.knowledgeBaseDesc":`تصفح مقالات المساعدة والأدلة`,"menu.myTicketsPlaceholder":`سجّل الدخول ��عرض تذاكرك.`,"menu.trackPlaceholder":`تتبع التذاكر قريبًا.`,"menu.kbPlaceholder":`قاعدة المعرفة قريبًا.`,"menu.preferences":`التفضيلات`,"menu.preferencesDesc":`إعدادات اللغة والمظهر`,"prefs.title":`التفضيلات`,"prefs.language":`اللغة`,"prefs.theme":`المظهر`,"prefs.light":`فاتح`,"prefs.dark":`داكن`,"prefs.auto":`النظام`,"branding.poweredBy":`مدعوم من`,"attach.dropzone":`اسحب الملفات هنا أو انقر للتصفح`,"attach.dropzoneActive":`أفلت الملفات هنا`,"attach.maxFiles":`بحد أقصى {max} ملفات`,"attach.remove":`إزالة`,"attach.uploading":`جارِ رفع الملفات...`,"attach.uploadProgress":`جارِ رفع {name}... {percent}%`,"attach.invalidType":`نوع الملف غير مسموح`,"attach.tooLarge":`حجم الملف يتجاوز الحد الأقصى`,"attach.tooMany":`تم الوصول للحد الأقصى لعدد الملفات`,"attach.download":`تحميل`,"mytickets.title":`تذاكري`,"mytickets.emailPrompt":`أدخل بريدك الإلكتروني لعرض تذاكرك`,"mytickets.emailPlaceholder":`your@email.com`,"mytickets.rememberMe":`تذكرني`,"mytickets.lookup":`البحث عن تذاكري`,"mytickets.lookingUp":`جارِ البحث...`,"mytickets.noTickets":`لا توجد تذاكر بعد.`,"mytickets.submitFirst":`أرسل تذكرتك الأولى`,"mytickets.noAccount":`لم يتم العثور على تذاكر لهذا البريد.`,"detail.description":`الوصف`,"detail.attachments":`المرفقات`,"detail.noAttachments":`لا توجد مرفقات`,"detail.replies":`المحادثة`,"detail.noReplies":`لا توجد ردود بعد.`,"detail.replyPlaceholder":`اكتب رداً...`,"detail.sendReply":`إرسال`,"detail.sending":`جارِ الإرسال...`,"detail.staff":`فريق الدعم`,"detail.you":`أنت`,"detail.loading":`جارِ تحميل التذكرة...`,"track.title":`تتبع تذكرة`,"track.tokenPlaceholder":`أدخل رمز التتبع (trk_...)`,"track.submit":`تتبع`,"track.tracking":`جارِ التتبع...`,"track.recentTickets":`التذاكر الأخيرة`,"track.invalidToken":`رمز التتبع غير صالح أو منتهي.`,"prefs.clearEmail":`مسح البريد المحفوظ`,"prefs.emailCleared":`تم مسح البريد`,"auth.login":`تسجيل الدخول`,"auth.logout":`تسجيل الخروج`,"auth.sessionExpired":`انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.`,"prefs.accentColor":`لون التمييز`,"form.categoryPlaceholder":`اختر فئة`,"form.categoryBack":`رجوع`,"form.categorySelected":`الفئة`,"diag.title":`مشاركة معلومات التشخيص`,"diag.hint":`ساعدنا في حل مشكلتك بشكل أسرع`,"diag.screenResolution":`دقة الشاشة`,"diag.deviceType":`نوع الجهاز`,"diag.timezone":`المنطقة الزمنية`,"diag.referrerUrl":`رابط المصدر`,"diag.language":`لغة المتصفح`,"diag.platform":`المنصة`,"detail.resolve":`تحديد كمحلول`,"detail.resolving":`جارِ الحل...`,"detail.resolved":`محلول`,"detail.sla":`اتفاقية الخدمة`},f={primaryColor:`#42b983`,mode:`light`,borderRadius:`8px`,fontFamily:`inherit`,zIndex:9999};function p(e){return e===`auto`?typeof window<`u`&&window.matchMedia?.(`(prefers-color-scheme: dark)`).matches?`dark`:`light`:e??`light`}function m(e={}){let t={...f,...e,mode:p(e.mode??f.mode)},n=h(t.primaryColor),r=Math.min(n.l+30,95),i=Math.max(n.l-15,10);return[`--rqd-primary: ${t.primaryColor}`,`--rqd-primary-h: ${n.h}`,`--rqd-primary-s: ${n.s}%`,`--rqd-primary-l: ${n.l}%`,`--rqd-primary-light: hsl(${n.h}, ${n.s}%, ${r}%)`,`--rqd-primary-dark: hsl(${n.h}, ${n.s}%, ${i}%)`,`--rqd-radius: ${t.borderRadius}`,`--rqd-font: ${t.fontFamily}`,`--rqd-z: ${t.zIndex}`,`--rqd-bg: ${t.mode===`dark`?`#1a1a2e`:`#ffffff`}`,`--rqd-bg-secondary: ${t.mode===`dark`?`#16213e`:`#f8f9fa`}`,`--rqd-text: ${t.mode===`dark`?`#e0e0e0`:`#1a1a2e`}`,`--rqd-text-secondary: ${t.mode===`dark`?`#a0a0b0`:`#6c757d`}`,`--rqd-border: ${t.mode===`dark`?`#2a2a4a`:`#e0e0e0`}`,`--rqd-input-bg: ${t.mode===`dark`?`#0f3460`:`#ffffff`}`,`--rqd-shadow: ${t.mode===`dark`?`0 8px 32px rgba(0,0,0,0.4)`:`0 8px 32px rgba(0,0,0,0.12)`}`].join(`; `)}function h(e){let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);if(!t)return{h:160,s:51,l:49};let n=parseInt(t[1],16)/255,r=parseInt(t[2],16)/255,i=parseInt(t[3],16)/255,a=Math.max(n,r,i),o=Math.min(n,r,i),s=0,c=0,l=(a+o)/2;if(a!==o){let e=a-o;c=l>.5?e/(2-a-o):e/(a+o),s=a===n?((r-i)/e+(r<i?6:0))/6:a===r?((i-n)/e+2)/6:((n-r)/e+4)/6}return{h:Math.round(s*360),s:Math.round(c*100),l:Math.round(l*100)}}function ee(){return te}let te=`:host { all: initial; }
|
|
1
|
+
var ReqdeskWidget=(function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let n=``,r=``;function i(e,t){r=e.replace(/\/$/,``),n=t}let a=t.ofetch.create({timeout:15e3,retry:2,retryStatusCodes:[408,429,500,502,503,504],async onRequest({options:e}){e.baseURL=`${r}/api/v1`;let t=new Headers(e.headers);t.set(`X-API-Key`,n),e.headers=t},onResponseError({response:e}){let t=e._data;throw{code:t?.responseCode??`HTTP_${e.status}`,message:t?.responseMessage??e.statusText}}});function o(){return crypto.randomUUID()}async function s(e,t){let n=await a(`/projects/${e}/tickets`,{method:`POST`,body:{title:t.title,description:t.description,priority:t.priority,categoryId:t.categoryId,email:t.email,clientMetadata:t.clientMetadata},headers:{"Idempotency-Key":o()}});return{id:n.data.id,ticketNumber:n.data.attributes.ticketNumber,trackingToken:n.meta?.trackingToken,status:n.data.attributes.status}}async function c(e){let t=await a(`/tickets/track?token=${encodeURIComponent(e)}`),n=t.included??[];return{id:t.data.id,ticketNumber:t.data.attributes.ticketNumber,title:t.data.attributes.title,status:t.data.attributes.status,priority:t.data.attributes.priority,createdAt:t.data.attributes.createdAt,replies:n.filter(e=>e.type===`public-reply`).map(e=>({id:e.id,body:e.attributes.body,authorName:e.attributes.authorName,isStaff:e.attributes.isStaff,createdAt:e.attributes.createdAt}))}}async function l(e,t){await a(`/tickets/track/reply`,{method:`POST`,body:{trackingToken:e,body:t}})}let u={"widget.title":`Support`,"widget.newTicket":`New Ticket`,"widget.trackTicket":`Track Ticket`,"form.title":`Title`,"form.titlePlaceholder":`Brief summary of your issue`,"form.description":`Description`,"form.descriptionPlaceholder":`Describe your issue in detail...`,"form.email":`Email`,"form.emailPlaceholder":`your@email.com`,"form.priority":`Priority`,"form.priorityLow":`Low`,"form.priorityMedium":`Medium`,"form.priorityHigh":`High`,"form.priorityUrgent":`Urgent`,"form.category":`Category`,"form.categoryNone":`Select a category`,"form.submit":`Submit Ticket`,"form.submitting":`Submitting...`,"form.cancel":`Cancel`,"form.attachment":`Attach files`,"success.title":`Ticket Submitted!`,"success.ticketNumber":`Ticket #`,"success.trackingToken":`Your tracking token:`,"success.trackingHint":`Save this token to track your ticket status.`,"success.copyToken":`Copy Token`,"success.copied":`Copied!`,"success.close":`Close`,"success.trackNow":`Track Ticket`,"tracker.title":`Track Your Ticket`,"tracker.tokenPlaceholder":`Enter your tracking token (trk_...)`,"tracker.submit":`Track`,"tracker.tracking":`Tracking...`,"tracker.status":`Status`,"tracker.priority":`Priority`,"tracker.created":`Created`,"tracker.replies":`Replies`,"tracker.noReplies":`No replies yet.`,"tracker.replyPlaceholder":`Write a reply...`,"tracker.sendReply":`Send Reply`,"tracker.sending":`Sending...`,"tracker.back":`Back`,"tracker.staff":`Staff`,"error.generic":`Something went wrong. Please try again.`,"error.network":`Network error. Check your connection.`,"error.tokenInvalid":`Invalid or expired tracking token.`,"error.required":`This field is required.`,"error.emailInvalid":`Please enter a valid email address.`,"error.titleMin":`Title must be at least 5 characters.`,"portal.title":`Support Portal`,"portal.myTickets":`My Tickets`,"portal.noTickets":`No tickets yet.`,"portal.newTicket":`New Ticket`,"widget.close":`Close`,"menu.newTicket":`Submit a Ticket`,"menu.newTicketDesc":`Create a new support request`,"menu.myTickets":`My Tickets`,"menu.myTicketsDesc":`View and manage your tickets`,"menu.trackTicket":`Track a Ticket`,"menu.trackTicketDesc":`Check status with your tracking token`,"menu.knowledgeBase":`Knowledge Base`,"menu.knowledgeBaseDesc":`Browse help articles and guides`,"menu.myTicketsPlaceholder":`Sign in to view your tickets.`,"menu.trackPlaceholder":`Ticket tracking is coming soon.`,"menu.kbPlaceholder":`Knowledge base is coming soon.`,"menu.preferences":`Preferences`,"menu.preferencesDesc":`Language and appearance settings`,"prefs.title":`Preferences`,"prefs.language":`Language`,"prefs.theme":`Theme`,"prefs.light":`Light`,"prefs.dark":`Dark`,"prefs.auto":`System`,"branding.poweredBy":`Powered by`,"attach.dropzone":`Drop files here or click to browse`,"attach.dropzoneActive":`Drop files here`,"attach.maxFiles":`Maximum {max} files`,"attach.remove":`Remove`,"attach.uploading":`Uploading files...`,"attach.uploadProgress":`Uploading {name}... {percent}%`,"attach.invalidType":`File type not allowed`,"attach.tooLarge":`File exceeds maximum size`,"attach.tooMany":`Maximum number of files reached`,"attach.download":`Download`,"mytickets.title":`My Tickets`,"mytickets.emailPrompt":`Enter your email to view your tickets`,"mytickets.emailPlaceholder":`your@email.com`,"mytickets.rememberMe":`Remember me`,"mytickets.lookup":`Find My Tickets`,"mytickets.lookingUp":`Looking up...`,"mytickets.noTickets":`No tickets yet.`,"mytickets.submitFirst":`Submit your first ticket`,"mytickets.noAccount":`No tickets found for this email.`,"detail.description":`Description`,"detail.attachments":`Attachments`,"detail.noAttachments":`No attachments`,"detail.replies":`Conversation`,"detail.noReplies":`No replies yet.`,"detail.replyPlaceholder":`Write a reply...`,"detail.sendReply":`Send`,"detail.sending":`Sending...`,"detail.staff":`Staff`,"detail.you":`You`,"detail.loading":`Loading ticket...`,"track.title":`Track a Ticket`,"track.tokenPlaceholder":`Enter tracking token (trk_...)`,"track.submit":`Track`,"track.tracking":`Tracking...`,"track.recentTickets":`Recent Tickets`,"track.invalidToken":`Invalid or expired tracking token.`,"prefs.clearEmail":`Clear saved email`,"prefs.emailCleared":`Email cleared`,"auth.login":`Login`,"auth.logout":`Logout`,"auth.sessionExpired":`Session expired. Please log in again.`,"prefs.accentColor":`Accent Color`,"form.categoryPlaceholder":`Select a category`,"form.categoryBack":`Back`,"form.categorySelected":`Category`,"diag.title":`Share diagnostic info`,"diag.hint":`Help us resolve your issue faster`,"diag.screenResolution":`Screen resolution`,"diag.deviceType":`Device type`,"diag.timezone":`Timezone`,"diag.referrerUrl":`Referrer URL`,"diag.language":`Browser language`,"diag.platform":`Platform`,"detail.resolve":`Mark as Resolved`,"detail.resolving":`Resolving...`,"detail.resolved":`Resolved`,"detail.sla":`SLA`},d={"widget.title":`الدعم`,"widget.newTicket":`تذكرة جديدة`,"widget.trackTicket":`تتبع التذكرة`,"form.title":`العنوان`,"form.titlePlaceholder":`ملخص موجز لمشكلتك`,"form.description":`الوصف`,"form.descriptionPlaceholder":`صف مشكلتك بالتفصيل...`,"form.email":`البريد الإلكتروني`,"form.emailPlaceholder":`your@email.com`,"form.priority":`الأولوية`,"form.priorityLow":`منخفضة`,"form.priorityMedium":`متوسطة`,"form.priorityHigh":`عالية`,"form.priorityUrgent":`عاجلة`,"form.category":`الفئة`,"form.categoryNone":`اختر فئة`,"form.submit":`إرسال التذكرة`,"form.submitting":`جارِ الإرسال...`,"form.cancel":`إلغاء`,"form.attachment":`إرفاق ملفات`,"success.title":`تم إرسال التذكرة!`,"success.ticketNumber":`تذكرة #`,"success.trackingToken":`رمز التتبع الخاص بك:`,"success.trackingHint":`احفظ هذا الرمز لتتبع حالة تذكرتك.`,"success.copyToken":`نسخ الرمز`,"success.copied":`تم النسخ!`,"success.close":`إغلاق`,"success.trackNow":`تتبع التذكرة`,"tracker.title":`تتبع تذكرتك`,"tracker.tokenPlaceholder":`أدخل رمز التتبع الخاص بك (trk_...)`,"tracker.submit":`تتبع`,"tracker.tracking":`جارِ التتبع...`,"tracker.status":`الحالة`,"tracker.priority":`الأولوية`,"tracker.created":`تاريخ الإنشاء`,"tracker.replies":`الردود`,"tracker.noReplies":`لا توجد ردود بعد.`,"tracker.replyPlaceholder":`اكتب رداً...`,"tracker.sendReply":`إرسال الرد`,"tracker.sending":`جارِ الإرسال...`,"tracker.back":`رجوع`,"tracker.staff":`فريق الدعم`,"error.generic":`حدث خطأ ما. يرجى المحاولة مرة أخرى.`,"error.network":`خطأ في الشبكة. تحقق من اتصالك.`,"error.tokenInvalid":`رمز التتبع غير صالح أو منتهي الصلاحية.`,"error.required":`هذا الحقل مطلوب.`,"error.emailInvalid":`يرجى إدخال بريد إلكتروني صالح.`,"error.titleMin":`يجب أن يكون العنوان 5 أحرف على الأقل.`,"portal.title":`بوابة الدعم`,"portal.myTickets":`تذاكري`,"portal.noTickets":`لا توجد تذاكر بعد.`,"portal.newTicket":`تذكرة جديدة`,"widget.close":`إغلاق`,"menu.newTicket":`إرسال تذكرة`,"menu.newTicketDesc":`إنشاء طلب ��عم جديد`,"menu.myTickets":`تذاكري`,"menu.myTicketsDesc":`عرض وإدارة تذاكرك`,"menu.trackTicket":`تتبع تذكرة`,"menu.trackTicketDesc":`تحقق من الحالة باستخدام رمز التتبع`,"menu.knowledgeBase":`قاعدة المعرفة`,"menu.knowledgeBaseDesc":`تصفح مقالات المساعدة والأدلة`,"menu.myTicketsPlaceholder":`سجّل الدخول ��عرض تذاكرك.`,"menu.trackPlaceholder":`تتبع التذاكر قريبًا.`,"menu.kbPlaceholder":`قاعدة المعرفة قريبًا.`,"menu.preferences":`التفضيلات`,"menu.preferencesDesc":`إعدادات اللغة والمظهر`,"prefs.title":`التفضيلات`,"prefs.language":`اللغة`,"prefs.theme":`المظهر`,"prefs.light":`فاتح`,"prefs.dark":`داكن`,"prefs.auto":`النظام`,"branding.poweredBy":`مدعوم من`,"attach.dropzone":`اسحب الملفات هنا أو انقر للتصفح`,"attach.dropzoneActive":`أفلت الملفات هنا`,"attach.maxFiles":`بحد أقصى {max} ملفات`,"attach.remove":`إزالة`,"attach.uploading":`جارِ رفع الملفات...`,"attach.uploadProgress":`جارِ رفع {name}... {percent}%`,"attach.invalidType":`نوع الملف غير مسموح`,"attach.tooLarge":`حجم الملف يتجاوز الحد الأقصى`,"attach.tooMany":`تم الوصول للحد الأقصى لعدد الملفات`,"attach.download":`تحميل`,"mytickets.title":`تذاكري`,"mytickets.emailPrompt":`أدخل بريدك الإلكتروني لعرض تذاكرك`,"mytickets.emailPlaceholder":`your@email.com`,"mytickets.rememberMe":`تذكرني`,"mytickets.lookup":`البحث عن تذاكري`,"mytickets.lookingUp":`جارِ البحث...`,"mytickets.noTickets":`لا توجد تذاكر بعد.`,"mytickets.submitFirst":`أرسل تذكرتك الأولى`,"mytickets.noAccount":`لم يتم العثور على تذاكر لهذا البريد.`,"detail.description":`الوصف`,"detail.attachments":`المرفقات`,"detail.noAttachments":`لا توجد مرفقات`,"detail.replies":`المحادثة`,"detail.noReplies":`لا توجد ردود بعد.`,"detail.replyPlaceholder":`اكتب رداً...`,"detail.sendReply":`إرسال`,"detail.sending":`جارِ الإرسال...`,"detail.staff":`فريق الدعم`,"detail.you":`أنت`,"detail.loading":`جارِ تحميل التذكرة...`,"track.title":`تتبع تذكرة`,"track.tokenPlaceholder":`أدخل رمز التتبع (trk_...)`,"track.submit":`تتبع`,"track.tracking":`جارِ التتبع...`,"track.recentTickets":`التذاكر الأخيرة`,"track.invalidToken":`رمز التتبع غير صالح أو منتهي.`,"prefs.clearEmail":`مسح البريد المحفوظ`,"prefs.emailCleared":`تم مسح البريد`,"auth.login":`تسجيل الدخول`,"auth.logout":`تسجيل الخروج`,"auth.sessionExpired":`انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.`,"prefs.accentColor":`لون التمييز`,"form.categoryPlaceholder":`اختر فئة`,"form.categoryBack":`رجوع`,"form.categorySelected":`الفئة`,"diag.title":`مشاركة معلومات التشخيص`,"diag.hint":`ساعدنا في حل مشكلتك بشكل أسرع`,"diag.screenResolution":`دقة الشاشة`,"diag.deviceType":`نوع الجهاز`,"diag.timezone":`المنطقة الزمنية`,"diag.referrerUrl":`رابط المصدر`,"diag.language":`لغة المتصفح`,"diag.platform":`المنصة`,"detail.resolve":`تحديد كمحلول`,"detail.resolving":`جارِ الحل...`,"detail.resolved":`محلول`,"detail.sla":`اتفاقية الخدمة`},f={primaryColor:`#42b983`,mode:`auto`,borderRadius:`8px`,fontFamily:`inherit`,zIndex:9999};function p(e){return e===`auto`?typeof window<`u`&&window.matchMedia?.(`(prefers-color-scheme: dark)`).matches?`dark`:`light`:e??`light`}function m(e={}){let t={...f,...e,mode:p(e.mode??f.mode)},n=h(t.primaryColor),r=Math.min(n.l+30,95),i=Math.max(n.l-15,10);return[`--rqd-primary: ${t.primaryColor}`,`--rqd-primary-h: ${n.h}`,`--rqd-primary-s: ${n.s}%`,`--rqd-primary-l: ${n.l}%`,`--rqd-primary-light: hsl(${n.h}, ${n.s}%, ${r}%)`,`--rqd-primary-dark: hsl(${n.h}, ${n.s}%, ${i}%)`,`--rqd-radius: ${t.borderRadius}`,`--rqd-font: ${t.fontFamily}`,`--rqd-z: ${t.zIndex}`,`--rqd-bg: ${t.mode===`dark`?`#1a1a2e`:`#ffffff`}`,`--rqd-bg-secondary: ${t.mode===`dark`?`#16213e`:`#f8f9fa`}`,`--rqd-text: ${t.mode===`dark`?`#e0e0e0`:`#1a1a2e`}`,`--rqd-text-secondary: ${t.mode===`dark`?`#a0a0b0`:`#6c757d`}`,`--rqd-border: ${t.mode===`dark`?`#2a2a4a`:`#e0e0e0`}`,`--rqd-input-bg: ${t.mode===`dark`?`#0f3460`:`#ffffff`}`,`--rqd-shadow: ${t.mode===`dark`?`0 8px 32px rgba(0,0,0,0.4)`:`0 8px 32px rgba(0,0,0,0.12)`}`].join(`; `)}function h(e){let t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);if(!t)return{h:160,s:51,l:49};let n=parseInt(t[1],16)/255,r=parseInt(t[2],16)/255,i=parseInt(t[3],16)/255,a=Math.max(n,r,i),o=Math.min(n,r,i),s=0,c=0,l=(a+o)/2;if(a!==o){let e=a-o;c=l>.5?e/(2-a-o):e/(a+o),s=a===n?((r-i)/e+(r<i?6:0))/6:a===r?((i-n)/e+2)/6:((n-r)/e+4)/6}return{h:Math.round(s*360),s:Math.round(c*100),l:Math.round(l*100)}}function ee(){return te}let te=`:host { all: initial; }
|
|
2
2
|
.rqd-root { font-family: var(--rqd-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif); font-size: 14px; line-height: 1.5; color: var(--rqd-text); -webkit-font-smoothing: antialiased; }
|
|
3
3
|
.rqd-fab { position: fixed; bottom: 20px; width: 56px; height: 56px; border-radius: 50%; background: var(--rqd-primary); color: #fff; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 16px rgba(0,0,0,0.2); transition: transform 0.2s, box-shadow 0.2s; pointer-events: auto; z-index: var(--rqd-z, 9999); }
|
|
4
4
|
.rqd-fab:hover { transform: scale(1.08); box-shadow: 0 6px 20px rgba(0,0,0,0.25); }
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as configureWidgetClient, a as saveTrackingToken, b as submitTrackingReply, c as getWidgetStyles, d as ar, f as en, n as getTrackingTokens, o as saveWidgetConfig, r as loadWidgetConfig, u as themeToVars, x as trackTicket, y as submitTicket } from "./storage-
|
|
1
|
+
import { C as configureWidgetClient, a as saveTrackingToken, b as submitTrackingReply, c as getWidgetStyles, d as ar, f as en, n as getTrackingTokens, o as saveWidgetConfig, r as loadWidgetConfig, u as themeToVars, x as trackTicket, y as submitTicket } from "./storage-0JN8SJi5.js";
|
|
2
2
|
//#region src/shadow-dom.ts
|
|
3
3
|
let shadowRoot = null;
|
|
4
4
|
let hostEl = null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as TicketResult, i as PublicReply, l as TrackedTicketResult, o as SubmitTicketData, r as OidcAuthConfig, s as ThemeConfig, t as CustomerConfig, u as WidgetError } from "./types-rPiXlS0A.js";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
|
-
import * as
|
|
3
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/react/types.d.ts
|
|
6
6
|
interface ReqdeskProviderProps {
|
|
@@ -44,7 +44,7 @@ declare function ReqdeskProvider({
|
|
|
44
44
|
customer,
|
|
45
45
|
translations,
|
|
46
46
|
children
|
|
47
|
-
}: ReqdeskProviderProps):
|
|
47
|
+
}: ReqdeskProviderProps): react_jsx_runtime2.JSX.Element;
|
|
48
48
|
//# sourceMappingURL=ReqdeskProvider.d.ts.map
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/react/TicketForm.d.ts
|
|
@@ -54,13 +54,13 @@ declare function TicketForm({
|
|
|
54
54
|
onError,
|
|
55
55
|
className,
|
|
56
56
|
style
|
|
57
|
-
}: TicketFormProps):
|
|
57
|
+
}: TicketFormProps): react_jsx_runtime2.JSX.Element;
|
|
58
58
|
//# sourceMappingURL=TicketForm.d.ts.map
|
|
59
59
|
//#endregion
|
|
60
60
|
//#region src/react/SupportPortal.d.ts
|
|
61
61
|
declare function SupportPortal({
|
|
62
62
|
className
|
|
63
|
-
}: SupportPortalProps):
|
|
63
|
+
}: SupportPortalProps): react_jsx_runtime2.JSX.Element;
|
|
64
64
|
//# sourceMappingURL=SupportPortal.d.ts.map
|
|
65
65
|
//#endregion
|
|
66
66
|
//#region src/react/FloatingWidget.d.ts
|
|
@@ -75,7 +75,7 @@ declare function FloatingWidget({
|
|
|
75
75
|
contained,
|
|
76
76
|
onTicketCreated,
|
|
77
77
|
onError
|
|
78
|
-
}: FloatingWidgetProps):
|
|
78
|
+
}: FloatingWidgetProps): react_jsx_runtime2.JSX.Element;
|
|
79
79
|
//#endregion
|
|
80
80
|
//#region src/react/useReqdesk.d.ts
|
|
81
81
|
declare function useReqdesk(): UseReqdeskReturn;
|
|
@@ -87,7 +87,7 @@ interface ShadowRootProps {
|
|
|
87
87
|
}
|
|
88
88
|
declare function ShadowRoot({
|
|
89
89
|
children
|
|
90
|
-
}: ShadowRootProps):
|
|
90
|
+
}: ShadowRootProps): react_jsx_runtime2.JSX.Element;
|
|
91
91
|
//#endregion
|
|
92
92
|
//#region src/storage.d.ts
|
|
93
93
|
interface WidgetConfigPersist {
|
|
@@ -104,4 +104,4 @@ declare function loadWidgetConfig(apiKey: string): WidgetConfigPersist | null;
|
|
|
104
104
|
|
|
105
105
|
//#endregion
|
|
106
106
|
export { type CustomerConfig, FloatingWidget, type PublicReply, ReqdeskProvider, type ReqdeskProviderProps, ShadowRoot, type SubmitTicketData, SupportPortal, type SupportPortalProps, type ThemeConfig, TicketForm, type TicketFormProps, type TicketResult, type TrackedTicketResult, type UseReqdeskReturn, type WidgetConfigPersist, type WidgetError, loadWidgetConfig as getWidgetDefaults, useReqdesk };
|
|
107
|
-
//# sourceMappingURL=react-
|
|
107
|
+
//# sourceMappingURL=react-Bmwfo1Qg.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-
|
|
1
|
+
{"version":3,"file":"react-Bmwfo1Qg.d.ts","names":[],"sources":["../src/react/types.ts","../src/react/ReqdeskProvider.tsx","../src/react/TicketForm.tsx","../src/react/SupportPortal.tsx","../src/react/FloatingWidget.tsx","../src/react/useReqdesk.ts","../src/react/shadow-root.tsx","../src/storage.ts"],"mappings":";;;;;UAIiB,oBAAA;;SAER;EAFQ,KAAA,CAAA,EAGP,WAHO;EAAoB,QAAA,CAAA,EAAA,MAAA;UAE5B,CAAA,EAGI,cAHJ;cACC,CAAA,EAGO,MAHP,CAAA,MAAA,EAAA,MAAA,CAAA;UAEG,EAED,KAAA,CAAM,SAFL;;AAED,UAGK,eAAA,CAHC;EAAS,IAAA,CAAA,EAAA,UAAA,GAAA,QAAA;EAGV,QAAA,CAAA,EAAA,cAAe,GAAA,aAAA;EAAA,eAAA,CAAA,EAAA,MAAA;iBAIH,CAAA,EAAA,CAAA,MAAA,EAAA,YAAA,EAAA,GAAA,IAAA;SACT,CAAA,EAAA,CAAA,KAAA,EAAA,WAAA,EAAA,GAAA,IAAA;WAEJ,CAAA,EAAA,MAAA;EAAa,KAAA,CAAA,EAAnB,KAAA,CAAM,aAAa;AAG7B;AAOiB,UAPA,kBAAA,CAOgB;EAAA,eAAA,CAAA,EAAA,MAAA;kBACZ,CAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,GAAA,IAAA;WAA2B,CAAA,EAAA,MAAA;OAAR,CAAA,EAJ9B,KAAA,CAAM,aAIwB;;AACV,UAFb,gBAAA,CAEa;cACsB,CAAA,IAAA,EAF/B,gBAE+B,CAAA,EAFZ,OAEY,CAFJ,YAEI,CAAA;aAE3C,CAAA,KAAA,EAAA,MAAA,CAAA,EAHqB,OAGrB,CAH6B,mBAG7B,CAAA;EAAW,mBAAA,CAAA,KAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,CAAA,EAFgC,OAEhC,CAAA,IAAA,CAAA;;SAAX;;;;iBCAO,eAAA;;;;;;;;GAAqF,uBAAoB,kBAAA,CAAA,GAAA,CAAA;;;;iBCxBzG,UAAA;;;;;;GAA4E,kBAAe,kBAAA,CAAA,GAAA,CAAA;;;;iBCN3F,aAAA;;GAA6B,qBAAkB,kBAAA,CAAA,GAAA,CAAA;;;;UCYrD,mBAAA;;;6BAGmB;EJjBZ,OAAA,CAAA,EAAA,CAAA,KAAA,EIkBG,WJlBiB,EAAA,GAAA,IAAA;;AAE5B,iBIuCO,cAAA,CJvCP;EAAA,QAAA;EAAA,SAAA;EAAA,eAAA;EAAA;AAAA,CAAA,EI4CN,mBJ5CM,CAAA,EI4Ca,kBAAA,CAAA,GAAA,CAAA,OJ5Cb;;;iBKDO,UAAA,CAAA,GAAc;;;;UCDpB,eAAA;YACE;;iBAGI,UAAA;;GAAyB,kBAAe,kBAAA,CAAA,GAAA,CAAA;;;UCRvC,mBAAA;;;;;IPIA,IAAA,CAAA,EAAA,OAAA,GAAA,MAAoB,GAAA,MAAA;EAAA,CAAA;QAE5B,CAAA,EAAA,aAAA,GAAA,gBAAA;;AAYoB,iBO6Eb,gBAAA,CP7Ea,MAAA,EAAA,MAAA,CAAA,EO6EqB,mBP7ErB,GAAA,IAAA"}
|
package/dist/react.cjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_storage = require("./storage-
|
|
2
|
+
const require_storage = require("./storage-D5ZsuiB1.cjs");
|
|
3
3
|
let react = require("react");
|
|
4
4
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
5
|
-
let oidc_spa_entrypoint = require("oidc-spa/entrypoint");
|
|
6
5
|
let oidc_spa_core = require("oidc-spa/core");
|
|
7
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
7
|
let react_dom = require("react-dom");
|
|
@@ -14,7 +13,6 @@ let authState = {
|
|
|
14
13
|
let listeners = [];
|
|
15
14
|
let oidcInstance = null;
|
|
16
15
|
let initPromise = null;
|
|
17
|
-
let earlyInitCalled = false;
|
|
18
16
|
function notify() {
|
|
19
17
|
for (const listener of listeners) try {
|
|
20
18
|
listener(authState);
|
|
@@ -37,10 +35,6 @@ function onAuthStateChange(listener) {
|
|
|
37
35
|
};
|
|
38
36
|
}
|
|
39
37
|
function initWidgetAuth(config) {
|
|
40
|
-
if (!earlyInitCalled) {
|
|
41
|
-
(0, oidc_spa_entrypoint.oidcEarlyInit)({ BASE_URL: "/" });
|
|
42
|
-
earlyInitCalled = true;
|
|
43
|
-
}
|
|
44
38
|
initPromise = _initWidgetAuth(config);
|
|
45
39
|
return initPromise;
|
|
46
40
|
}
|
|
@@ -49,7 +43,8 @@ async function _initWidgetAuth(config) {
|
|
|
49
43
|
try {
|
|
50
44
|
const oidc = await (0, oidc_spa_core.createOidc)({
|
|
51
45
|
issuerUri: config.issuerUri,
|
|
52
|
-
clientId: config.clientId
|
|
46
|
+
clientId: config.clientId,
|
|
47
|
+
BASE_URL: "/"
|
|
53
48
|
});
|
|
54
49
|
oidcInstance = oidc;
|
|
55
50
|
if (oidc.isUserLoggedIn) {
|
|
@@ -1556,7 +1551,7 @@ function FloatingWidget({ position = "bottom-right", contained = false, onTicket
|
|
|
1556
1551
|
const [userThemeMode, setUserThemeMode] = (0, react.useState)(savedPrefs?.theme?.mode ?? null);
|
|
1557
1552
|
const [userColor, setUserColor] = (0, react.useState)(savedPrefs?.theme?.primaryColor ?? null);
|
|
1558
1553
|
const activeLang = userLang ?? ctx.language ?? "en";
|
|
1559
|
-
const activeThemeMode = userThemeMode ?? ctx.theme?.mode ?? "
|
|
1554
|
+
const activeThemeMode = userThemeMode ?? ctx.theme?.mode ?? "auto";
|
|
1560
1555
|
const activeColor = userColor ?? ctx.theme?.primaryColor ?? "#42b983";
|
|
1561
1556
|
const activeTheme = {
|
|
1562
1557
|
...ctx.theme,
|
package/dist/react.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './react-
|
|
1
|
+
export * from './react-Bmwfo1Qg.js';
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { C as configureWidgetClient, S as uploadAttachment, _ as resolveWidgetUser, a as saveTrackingToken, b as submitTrackingReply, c as getWidgetStyles, d as ar, f as en, g as listMyTickets, h as getTicketDetail, i as loadWidgetEmail, l as themeToStyle, m as getCategories, n as getTrackingTokens, o as saveWidgetConfig, p as closeTicket, r as loadWidgetConfig, s as saveWidgetEmail, t as clearWidgetEmail, v as submitReply, w as setOidcTokenProvider, x as trackTicket, y as submitTicket } from "./storage-
|
|
1
|
+
import { C as configureWidgetClient, S as uploadAttachment, _ as resolveWidgetUser, a as saveTrackingToken, b as submitTrackingReply, c as getWidgetStyles, d as ar, f as en, g as listMyTickets, h as getTicketDetail, i as loadWidgetEmail, l as themeToStyle, m as getCategories, n as getTrackingTokens, o as saveWidgetConfig, p as closeTicket, r as loadWidgetConfig, s as saveWidgetEmail, t as clearWidgetEmail, v as submitReply, w as setOidcTokenProvider, x as trackTicket, y as submitTicket } from "./storage-0JN8SJi5.js";
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { QueryClient, QueryClientProvider, keepPreviousData, queryOptions, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
|
-
import { oidcEarlyInit } from "oidc-spa/entrypoint";
|
|
5
4
|
import { createOidc } from "oidc-spa/core";
|
|
6
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
6
|
import { createPortal } from "react-dom";
|
|
@@ -13,7 +12,6 @@ let authState = {
|
|
|
13
12
|
let listeners = [];
|
|
14
13
|
let oidcInstance = null;
|
|
15
14
|
let initPromise = null;
|
|
16
|
-
let earlyInitCalled = false;
|
|
17
15
|
function notify() {
|
|
18
16
|
for (const listener of listeners) try {
|
|
19
17
|
listener(authState);
|
|
@@ -36,10 +34,6 @@ function onAuthStateChange(listener) {
|
|
|
36
34
|
};
|
|
37
35
|
}
|
|
38
36
|
function initWidgetAuth(config) {
|
|
39
|
-
if (!earlyInitCalled) {
|
|
40
|
-
oidcEarlyInit({ BASE_URL: "/" });
|
|
41
|
-
earlyInitCalled = true;
|
|
42
|
-
}
|
|
43
37
|
initPromise = _initWidgetAuth(config);
|
|
44
38
|
return initPromise;
|
|
45
39
|
}
|
|
@@ -48,7 +42,8 @@ async function _initWidgetAuth(config) {
|
|
|
48
42
|
try {
|
|
49
43
|
const oidc = await createOidc({
|
|
50
44
|
issuerUri: config.issuerUri,
|
|
51
|
-
clientId: config.clientId
|
|
45
|
+
clientId: config.clientId,
|
|
46
|
+
BASE_URL: "/"
|
|
52
47
|
});
|
|
53
48
|
oidcInstance = oidc;
|
|
54
49
|
if (oidc.isUserLoggedIn) {
|
|
@@ -1555,7 +1550,7 @@ function FloatingWidget({ position = "bottom-right", contained = false, onTicket
|
|
|
1555
1550
|
const [userThemeMode, setUserThemeMode] = useState(savedPrefs?.theme?.mode ?? null);
|
|
1556
1551
|
const [userColor, setUserColor] = useState(savedPrefs?.theme?.primaryColor ?? null);
|
|
1557
1552
|
const activeLang = userLang ?? ctx.language ?? "en";
|
|
1558
|
-
const activeThemeMode = userThemeMode ?? ctx.theme?.mode ?? "
|
|
1553
|
+
const activeThemeMode = userThemeMode ?? ctx.theme?.mode ?? "auto";
|
|
1559
1554
|
const activeColor = userColor ?? ctx.theme?.primaryColor ?? "#42b983";
|
|
1560
1555
|
const activeTheme = {
|
|
1561
1556
|
...ctx.theme,
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["apiSubmitTicket","apiTrackTicket","apiSubmitTrackingReply","translations","translations","formatFileSize","apiSubmitTicket","translations","translations","translations"],"sources":["../src/auth/widget-auth.ts","../src/react/ReqdeskProvider.tsx","../src/react/useReqdesk.ts","../src/react/shadow-root.tsx","../src/react/TicketForm.tsx","../src/react/SupportPortal.tsx","../src/react/queries.ts","../src/client-metadata.ts","../src/react/views/SubmitTicketView.tsx","../src/react/views/MyTicketsView.tsx","../src/react/views/TicketDetailView.tsx","../src/react/views/TrackTicketView.tsx","../src/react/FloatingWidget.tsx"],"sourcesContent":["import { oidcEarlyInit } from 'oidc-spa/entrypoint'\nimport { createOidc } from 'oidc-spa/core'\nimport type { OidcAuthConfig } from '../types'\nimport { setOidcTokenProvider } from '../ofetch-client'\n\nexport interface WidgetAuthState {\n isAuthenticated: boolean\n isLoading: boolean\n userEmail?: string\n userName?: string\n}\n\ntype AuthStateListener = (state: WidgetAuthState) => void\n\nlet authState: WidgetAuthState = { isAuthenticated: false, isLoading: false }\nlet listeners: AuthStateListener[] = []\nlet oidcInstance: any = null\nlet initPromise: Promise<void> | null = null\nlet earlyInitCalled = false\n\nfunction notify() {\n for (const listener of listeners) {\n try { listener(authState) } catch { /* ignore */ }\n }\n}\n\nfunction setState(update: Partial<WidgetAuthState>) {\n authState = { ...authState, ...update }\n notify()\n}\n\nexport function getAuthState(): WidgetAuthState {\n return authState\n}\n\nexport function onAuthStateChange(listener: AuthStateListener): () => void {\n listeners.push(listener)\n return () => {\n listeners = listeners.filter(l => l !== listener)\n }\n}\n\nexport function initWidgetAuth(config: OidcAuthConfig): Promise<void> {\n // oidcEarlyInit MUST be called synchronously before createOidc.\n // It handles the OIDC callback redirect and sets up internal state.\n if (!earlyInitCalled) {\n oidcEarlyInit({ BASE_URL: '/' })\n earlyInitCalled = true\n }\n\n initPromise = _initWidgetAuth(config)\n return initPromise\n}\n\nasync function _initWidgetAuth(config: OidcAuthConfig): Promise<void> {\n setState({ isLoading: true })\n\n try {\n const oidc = await createOidc({\n issuerUri: config.issuerUri,\n clientId: config.clientId,\n })\n\n oidcInstance = oidc\n\n if (oidc.isUserLoggedIn) {\n setOidcTokenProvider(() => oidc.getTokens())\n\n const tokens = await oidc.getTokens()\n const payload = decodeJwtPayload(tokens.accessToken)\n\n setState({\n isAuthenticated: true,\n isLoading: false,\n userEmail: payload?.email,\n userName: payload?.name ?? payload?.preferred_username,\n })\n\n oidc.subscribeToTokensChange(async (newTokens) => {\n const p = decodeJwtPayload(newTokens.accessToken)\n setState({\n userEmail: p?.email ?? authState.userEmail,\n userName: p?.name ?? p?.preferred_username ?? authState.userName,\n })\n })\n } else {\n setState({ isAuthenticated: false, isLoading: false })\n }\n } catch (err) {\n console.warn('[reqdesk-widget] oidc-spa initialization failed:', err)\n setState({ isAuthenticated: false, isLoading: false })\n }\n}\n\nexport async function login(): Promise<void> {\n if (!oidcInstance && initPromise) {\n await initPromise\n }\n if (!oidcInstance) {\n console.warn('[reqdesk-widget] Cannot login: OIDC not initialized. Check auth config.')\n return\n }\n await oidcInstance.login({ doesCurrentHrefRequiresAuth: false })\n}\n\nexport async function logout(): Promise<void> {\n if (!oidcInstance) return\n setOidcTokenProvider(null)\n setState({ isAuthenticated: false, userEmail: undefined, userName: undefined })\n await oidcInstance.logout({ redirectTo: 'current page' })\n}\n\nexport function isAuthConfigured(): boolean {\n return oidcInstance !== null\n}\n\nfunction decodeJwtPayload(token: string): Record<string, any> | null {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return null\n const payload = atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(payload)\n } catch {\n return null\n }\n}\n","import { createContext, useContext, useMemo, useEffect, useRef, useState } from 'react'\r\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\r\nimport { configureWidgetClient } from '../ofetch-client'\r\nimport { loadWidgetConfig, saveWidgetConfig } from '../storage'\r\nimport { initWidgetAuth, getAuthState, onAuthStateChange, type WidgetAuthState } from '../auth/widget-auth'\r\nimport type { ReqdeskProviderProps, ReqdeskContextValue } from './types'\r\n\r\nconst ReqdeskContext = createContext<ReqdeskContextValue | null>(null)\r\n\r\nexport function useReqdeskContext(): ReqdeskContextValue {\r\n const ctx = useContext(ReqdeskContext)\r\n if (!ctx) throw new Error('useReqdesk must be used within a <ReqdeskProvider>')\r\n return ctx\r\n}\r\n\r\n// Widget-scoped QueryClient — completely isolated from host app\r\nconst widgetQueryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 5 * 60 * 1000,\r\n gcTime: 10 * 60 * 1000,\r\n retry: (failureCount, error) => {\r\n const status = (error as any)?.status ?? (error as any)?.statusCode\r\n if (status && status >= 400 && status < 500 && status !== 408) return false\r\n if (status && status >= 500) return false\r\n return failureCount < 2\r\n },\r\n retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),\r\n refetchOnWindowFocus: false,\r\n },\r\n mutations: {\r\n retry: false,\r\n },\r\n },\r\n})\r\n\r\nexport function ReqdeskProvider({ apiKey, auth, theme, language, customer, translations, children }: ReqdeskProviderProps) {\r\n const initialized = useRef(false)\r\n const [authState, setAuthState] = useState<WidgetAuthState>(getAuthState)\r\n\r\n const saved = initialized.current ? null : loadWidgetConfig(apiKey)\r\n const resolvedLanguage = language ?? saved?.language ?? 'en'\r\n const resolvedTheme = theme ?? saved?.theme\r\n\r\n useEffect(() => {\r\n if (!initialized.current) {\r\n configureWidgetClient(window.location.origin, apiKey)\r\n initialized.current = true\r\n\r\n if (auth) {\r\n initWidgetAuth(auth)\r\n }\r\n }\r\n }, [apiKey, auth])\r\n\r\n useEffect(() => {\r\n return onAuthStateChange(setAuthState)\r\n }, [])\r\n\r\n useEffect(() => {\r\n saveWidgetConfig(apiKey, {\r\n language: resolvedLanguage,\r\n theme: resolvedTheme,\r\n })\r\n }, [apiKey, resolvedLanguage, resolvedTheme])\r\n\r\n const value = useMemo<ReqdeskContextValue>(() => ({\r\n apiKey,\r\n auth,\r\n theme: resolvedTheme,\r\n language: resolvedLanguage,\r\n customer,\r\n translations,\r\n isAuthenticated: authState.isAuthenticated,\r\n userEmail: authState.userEmail,\r\n userName: authState.userName,\r\n }), [apiKey, auth, resolvedTheme, resolvedLanguage, customer, translations, authState])\r\n\r\n return (\r\n <ReqdeskContext.Provider value={value}>\r\n <QueryClientProvider client={widgetQueryClient}>\r\n {children}\r\n </QueryClientProvider>\r\n </ReqdeskContext.Provider>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { submitTicket as apiSubmitTicket, trackTicket as apiTrackTicket, submitTrackingReply as apiSubmitTrackingReply } from '../api-client'\r\nimport type { SubmitTicketData, TicketResult, TrackedTicketResult, WidgetError, UseReqdeskReturn } from './types'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\n\r\nexport function useReqdesk(): UseReqdeskReturn {\r\n useReqdeskContext() // ensure we're inside a provider\r\n\r\n const [isLoading, setIsLoading] = useState(false)\r\n const [error, setError] = useState<WidgetError | null>(null)\r\n\r\n const submitTicket = useCallback(async (data: SubmitTicketData): Promise<TicketResult> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n const result = await apiSubmitTicket('_current', data)\r\n return result\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n const trackTicket = useCallback(async (token: string): Promise<TrackedTicketResult> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n const result = await apiTrackTicket(token)\r\n return result\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n const submitTrackingReply = useCallback(async (token: string, body: string): Promise<void> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n await apiSubmitTrackingReply(token, body)\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n return { submitTicket, trackTicket, submitTrackingReply, isLoading, error }\r\n}\r\n","import { useRef, useEffect, useState, type ReactNode } from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { getWidgetStyles } from '../theme'\r\n\r\ninterface ShadowRootProps {\r\n children: ReactNode\r\n}\r\n\r\nexport function ShadowRoot({ children }: ShadowRootProps) {\r\n const hostRef = useRef<HTMLDivElement>(null)\r\n const [mountPoint, setMountPoint] = useState<HTMLElement | null>(null)\r\n\r\n useEffect(() => {\r\n const host = hostRef.current\r\n if (!host || host.shadowRoot) return\r\n\r\n const shadow = host.attachShadow({ mode: 'open' })\r\n\r\n const style = document.createElement('style')\r\n style.textContent = getWidgetStyles()\r\n shadow.appendChild(style)\r\n\r\n const mount = document.createElement('div')\r\n mount.className = 'rqd-root'\r\n shadow.appendChild(mount)\r\n\r\n setMountPoint(mount)\r\n }, [])\r\n\r\n return (\r\n <div ref={hostRef}>\r\n {mountPoint && createPortal(children, mountPoint)}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback, type FormEvent } from 'react'\r\nimport { useReqdesk } from './useReqdesk'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\nimport { en } from '../i18n/en'\r\nimport { ar } from '../i18n/ar'\r\nimport { themeToStyle } from '../theme'\r\nimport { saveTrackingToken } from '../storage'\r\nimport type { TicketFormProps, TicketResult, WidgetError, SubmitTicketData } from './types'\r\nimport { ShadowRoot } from './shadow-root'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\nexport function TicketForm({ mode = 'inline', onTicketCreated, onError, className, style }: TicketFormProps) {\r\n const ctx = useReqdeskContext()\r\n const { submitTicket, isLoading } = useReqdesk()\r\n const [success, setSuccess] = useState<TicketResult | null>(null)\r\n const [errors, setErrors] = useState<Record<string, string>>({})\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const handleSubmit = useCallback(async (e: FormEvent<HTMLFormElement>) => {\r\n e.preventDefault()\r\n const form = e.currentTarget\r\n const formData = new FormData(form)\r\n\r\n const title = (formData.get('title') as string)?.trim() ?? ''\r\n const email = (formData.get('email') as string)?.trim() ?? ''\r\n const newErrors: Record<string, string> = {}\r\n\r\n if (!title) newErrors.title = t('error.required')\r\n else if (title.length < 5) newErrors.title = t('error.titleMin')\r\n if (!email) newErrors.email = t('error.required')\r\n else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) newErrors.email = t('error.emailInvalid')\r\n\r\n if (Object.keys(newErrors).length > 0) {\r\n setErrors(newErrors)\r\n return\r\n }\r\n\r\n setErrors({})\r\n const data: SubmitTicketData = {\r\n title,\r\n description: (formData.get('description') as string)?.trim() || undefined,\r\n email,\r\n priority: (formData.get('priority') as SubmitTicketData['priority']) ?? 'medium',\r\n }\r\n\r\n try {\r\n const result = await submitTicket(data)\r\n if (result.trackingToken) saveTrackingToken(ctx.apiKey, result.trackingToken)\r\n setSuccess(result)\r\n onTicketCreated?.(result)\r\n } catch (err) {\r\n onError?.(err as WidgetError)\r\n }\r\n }, [submitTicket, ctx.apiKey, ctx.translations, ctx.language, onTicketCreated, onError, t])\r\n\r\n const cssVars = themeToStyle(ctx.theme)\r\n\r\n const content = success ? (\r\n <div className=\"rqd-success\" style={{ textAlign: 'center', padding: '24px 0' }}>\r\n <div style={{ fontSize: 48, marginBottom: 12 }}>{'\\u2705'}</div>\r\n <h3 style={{ margin: '0 0 8px', fontSize: 18 }}>{t('success.title')}</h3>\r\n <p>{t('success.ticketNumber')}{success.ticketNumber}</p>\r\n {success.trackingToken && (\r\n <>\r\n <p style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('success.trackingHint')}</p>\r\n <div className=\"rqd-token-box\">{success.trackingToken}</div>\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n onClick={() => navigator.clipboard.writeText(success.trackingToken!)}\r\n >\r\n {t('success.copyToken')}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n ) : (\r\n <form className=\"rqd-form\" onSubmit={handleSubmit} noValidate>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.title')}</label>\r\n <input className=\"rqd-input\" name=\"title\" placeholder={t('form.titlePlaceholder')} required />\r\n {errors.title && <div className=\"rqd-error-text\">{errors.title}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.description')}</label>\r\n <textarea className=\"rqd-textarea\" name=\"description\" placeholder={t('form.descriptionPlaceholder')} />\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.email')}</label>\r\n <input className=\"rqd-input\" name=\"email\" type=\"email\" placeholder={t('form.emailPlaceholder')} required />\r\n {errors.email && <div className=\"rqd-error-text\">{errors.email}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.priority')}</label>\r\n <select className=\"rqd-select\" name=\"priority\" defaultValue=\"medium\">\r\n <option value=\"low\">{t('form.priorityLow')}</option>\r\n <option value=\"medium\">{t('form.priorityMedium')}</option>\r\n <option value=\"high\">{t('form.priorityHigh')}</option>\r\n <option value=\"urgent\">{t('form.priorityUrgent')}</option>\r\n </select>\r\n </div>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={isLoading}>\r\n {isLoading ? t('form.submitting') : t('form.submit')}\r\n </button>\r\n </form>\r\n )\r\n\r\n if (mode === 'floating') {\r\n return (\r\n <ShadowRoot>\r\n <div className={className} style={{ ...style, ...cssVars } as React.CSSProperties}>\r\n <div className=\"rqd-body\">{content}</div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n }\r\n\r\n return (\r\n <ShadowRoot>\r\n <div className={`rqd-inline ${className ?? ''}`} style={cssVars as React.CSSProperties}>\r\n <div className=\"rqd-body\">{content}</div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n","import { useReqdeskContext } from './ReqdeskProvider'\r\nimport { useReqdesk } from './useReqdesk'\r\nimport { themeToStyle } from '../theme'\r\nimport { ShadowRoot } from './shadow-root'\r\nimport type { SupportPortalProps } from './types'\r\n\r\nexport function SupportPortal({ className }: SupportPortalProps) {\r\n const ctx = useReqdeskContext()\r\n const { isLoading } = useReqdesk()\r\n const cssVars = themeToStyle(ctx.theme)\r\n\r\n return (\r\n <ShadowRoot>\r\n <div className={`rqd-inline ${className ?? ''}`} style={cssVars as React.CSSProperties}>\r\n <div className=\"rqd-body\">\r\n {isLoading ? (\r\n <p style={{ textAlign: 'center', color: 'var(--rqd-text-secondary)' }}>Loading...</p>\r\n ) : (\r\n <p style={{ textAlign: 'center', color: 'var(--rqd-text-secondary)', padding: '24px 0' }}>\r\n Support Portal — coming in a future update.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n","import { queryOptions, keepPreviousData } from '@tanstack/react-query'\r\nimport { getTicketDetail, listMyTickets, resolveWidgetUser, trackTicket, getCategories } from '../api-client'\r\n\r\nexport const widgetTicketDetailOptions = (ticketId: string) =>\r\n queryOptions({\r\n queryKey: ['widget-ticket', ticketId],\r\n queryFn: () => getTicketDetail(ticketId),\r\n staleTime: 60_000,\r\n enabled: !!ticketId,\r\n })\r\n\r\nexport const widgetMyTicketsOptions = (projectId: string, userId: string) =>\r\n queryOptions({\r\n queryKey: ['widget-tickets', projectId, userId],\r\n queryFn: () => listMyTickets(projectId, userId),\r\n staleTime: 30_000,\r\n placeholderData: keepPreviousData,\r\n enabled: !!userId,\r\n })\r\n\r\nexport const widgetUserOptions = (projectId: string, email: string) =>\r\n queryOptions({\r\n queryKey: ['widget-user', projectId, email],\r\n queryFn: () => resolveWidgetUser(projectId, email),\r\n staleTime: 5 * 60_000,\r\n enabled: !!email,\r\n })\r\n\r\nexport const widgetTrackTicketOptions = (token: string) =>\r\n queryOptions({\r\n queryKey: ['widget-track', token],\r\n queryFn: () => trackTicket(token),\r\n staleTime: 60_000,\r\n enabled: !!token,\r\n })\r\n\r\nexport const widgetCategoriesOptions = (projectId: string, parentId?: string | null) =>\r\n queryOptions({\r\n queryKey: ['widget-categories', projectId, parentId ?? 'root'],\r\n queryFn: () => getCategories(projectId, parentId),\r\n staleTime: 5 * 60_000,\r\n })\r\n","const STORAGE_PREFIX = 'reqdesk_diag_'\n\nexport interface MetadataPreferences {\n screenResolution: boolean\n deviceType: boolean\n timezone: boolean\n referrerUrl: boolean\n language: boolean\n platform: boolean\n}\n\nconst DEFAULT_PREFS: MetadataPreferences = {\n screenResolution: false,\n deviceType: false,\n timezone: false,\n referrerUrl: false,\n language: false,\n platform: false,\n}\n\n/** Always collected — minimal, non-sensitive */\nexport function collectMinimalMetadata(): Record<string, string> {\n const meta: Record<string, string> = {}\n try {\n meta.pageUrl = window.location.href\n meta.userAgent = navigator.userAgent\n } catch { /* SSR safety */ }\n return meta\n}\n\n/** Full diagnostic set — only included for opted-in fields */\nexport function collectDiagnosticMetadata(prefs: MetadataPreferences): Record<string, string> {\n const meta: Record<string, string> = {}\n try {\n if (prefs.screenResolution) meta.screenResolution = `${screen.width}x${screen.height}`\n if (prefs.deviceType) meta.deviceType = detectDeviceType()\n if (prefs.timezone) meta.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (prefs.referrerUrl && document.referrer) meta.referrerUrl = document.referrer\n if (prefs.language) meta.language = navigator.language\n if (prefs.platform) meta.platform = navigator.platform\n } catch { /* SSR safety */ }\n return meta\n}\n\n/** Combine minimal + opted-in diagnostic metadata */\nexport function collectAllMetadata(apiKey: string): Record<string, string> {\n const prefs = getMetadataPreferences(apiKey)\n return {\n ...collectMinimalMetadata(),\n ...collectDiagnosticMetadata(prefs),\n }\n}\n\nexport function getMetadataPreferences(apiKey: string): MetadataPreferences {\n try {\n const raw = localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`)\n if (raw) return { ...DEFAULT_PREFS, ...JSON.parse(raw) }\n } catch { /* ignore */ }\n return { ...DEFAULT_PREFS }\n}\n\nexport function saveMetadataPreferences(apiKey: string, prefs: MetadataPreferences): void {\n try {\n localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, JSON.stringify(prefs))\n } catch { /* ignore */ }\n}\n\nexport function isDiagnosticEnabled(apiKey: string): boolean {\n const prefs = getMetadataPreferences(apiKey)\n return Object.values(prefs).some(v => v)\n}\n\nfunction detectDeviceType(): string {\n const ua = navigator.userAgent.toLowerCase()\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android.*mobile|windows phone/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\nexport const DIAGNOSTIC_FIELDS = [\n { key: 'screenResolution' as const, labelKey: 'diag.screenResolution' },\n { key: 'deviceType' as const, labelKey: 'diag.deviceType' },\n { key: 'timezone' as const, labelKey: 'diag.timezone' },\n { key: 'referrerUrl' as const, labelKey: 'diag.referrerUrl' },\n { key: 'language' as const, labelKey: 'diag.language' },\n { key: 'platform' as const, labelKey: 'diag.platform' },\n] as const\n","import { useState, useRef, useCallback, type FormEvent, type DragEvent } from 'react'\r\nimport { useMutation, useQuery } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetCategoriesOptions } from '../queries'\r\nimport { submitTicket as apiSubmitTicket, uploadAttachment, type CategoryItem } from '../../api-client'\r\nimport { saveTrackingToken, saveWidgetEmail, loadWidgetEmail } from '../../storage'\r\nimport { collectAllMetadata, getMetadataPreferences, saveMetadataPreferences, collectDiagnosticMetadata, DIAGNOSTIC_FIELDS, type MetadataPreferences } from '../../client-metadata'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\nimport type { TicketResult, WidgetError, SubmitTicketData } from '../types'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\nconst ALLOWED_MIME_TYPES = new Set([\r\n 'image/jpeg', 'image/png', 'image/gif', 'image/webp',\r\n 'application/pdf',\r\n 'text/plain', 'text/csv',\r\n 'application/zip', 'application/x-zip-compressed',\r\n 'application/msword',\r\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n 'application/vnd.ms-excel',\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n 'application/vnd.ms-powerpoint',\r\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\r\n])\r\n\r\nconst BLOCKED_EXTENSIONS = new Set(['.exe', '.bat', '.cmd', '.sh', '.ps1', '.msi', '.dll', '.scr'])\r\nconst MAX_FILES = 5\r\nconst MAX_SIZE_MB = 10\r\n\r\ninterface SubmitTicketViewProps {\r\n projectId: string\r\n onSuccess?: (result: TicketResult) => void\r\n onError?: (error: WidgetError) => void\r\n isAuthenticated?: boolean\r\n userEmail?: string\r\n}\r\n\r\ninterface QueuedFile {\r\n file: File\r\n id: string\r\n error?: string\r\n}\r\n\r\ninterface UploadProgress {\r\n fileId: string\r\n fileName: string\r\n percent: number\r\n}\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\r\n}\r\n\r\nexport function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, userEmail }: SubmitTicketViewProps) {\r\n const ctx = useReqdeskContext()\r\n const fileInputRef = useRef<HTMLInputElement>(null)\r\n const savedEmail = loadWidgetEmail(ctx.apiKey)\r\n\r\n const [errors, setErrors] = useState<Record<string, string>>({})\r\n const [files, setFiles] = useState<QueuedFile[]>([])\r\n const [isDragOver, setIsDragOver] = useState(false)\r\n const [uploadProgress, setUploadProgress] = useState<UploadProgress | null>(null)\r\n const [success, setSuccess] = useState<TicketResult | null>(null)\r\n const [rememberEmail, setRememberEmail] = useState(!!savedEmail)\r\n\r\n // Category selector state\r\n const [categoryPath, setCategoryPath] = useState<CategoryItem[]>([])\r\n const [selectedCategory, setSelectedCategory] = useState<CategoryItem | null>(null)\r\n const currentParentId = categoryPath.length > 0 ? categoryPath[categoryPath.length - 1].id : null\r\n const { data: categories = [] } = useQuery(widgetCategoriesOptions(projectId, currentParentId))\r\n\r\n // Diagnostic metadata state\r\n const [diagOpen, setDiagOpen] = useState(false)\r\n const [diagPrefs, setDiagPrefs] = useState<MetadataPreferences>(getMetadataPreferences(ctx.apiKey))\r\n const diagValues = collectDiagnosticMetadata({\r\n screenResolution: true, deviceType: true, timezone: true,\r\n referrerUrl: true, language: true, platform: true,\r\n })\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const submitMutation = useMutation({\r\n mutationFn: async ({ data, validFiles }: { data: SubmitTicketData; validFiles: QueuedFile[] }) => {\r\n const result = await apiSubmitTicket(projectId, data)\r\n if (result.trackingToken) saveTrackingToken(ctx.apiKey, result.trackingToken)\r\n\r\n // Upload attachments sequentially after ticket creation\r\n for (const queued of validFiles) {\r\n setUploadProgress({ fileId: queued.id, fileName: queued.file.name, percent: 0 })\r\n await uploadAttachment(result.id, queued.file, (percent) => {\r\n setUploadProgress({ fileId: queued.id, fileName: queued.file.name, percent })\r\n })\r\n }\r\n setUploadProgress(null)\r\n return result\r\n },\r\n onSuccess: (result) => {\r\n setSuccess(result)\r\n onSuccess?.(result)\r\n },\r\n onError: (err) => {\r\n setUploadProgress(null)\r\n onError?.(err as unknown as WidgetError)\r\n },\r\n })\r\n\r\n function validateFile(file: File): string | null {\r\n const ext = '.' + file.name.split('.').pop()?.toLowerCase()\r\n if (BLOCKED_EXTENSIONS.has(ext)) return t('attach.invalidType')\r\n if (!ALLOWED_MIME_TYPES.has(file.type) && !file.type.startsWith('application/vnd.openxmlformats-officedocument.')) {\r\n return t('attach.invalidType')\r\n }\r\n if (file.size > MAX_SIZE_MB * 1024 * 1024) return t('attach.tooLarge')\r\n return null\r\n }\r\n\r\n function addFiles(newFiles: FileList | File[]) {\r\n const toAdd: QueuedFile[] = []\r\n for (const file of Array.from(newFiles)) {\r\n if (files.length + toAdd.length >= MAX_FILES) break\r\n const error = validateFile(file)\r\n toAdd.push({ file, id: crypto.randomUUID(), error: error ?? undefined })\r\n }\r\n setFiles(prev => [...prev, ...toAdd])\r\n }\r\n\r\n function removeFile(id: string) {\r\n setFiles(prev => prev.filter(f => f.id !== id))\r\n }\r\n\r\n function handleDragOver(e: DragEvent) { e.preventDefault(); setIsDragOver(true) }\r\n function handleDragLeave(e: DragEvent) { e.preventDefault(); setIsDragOver(false) }\r\n function handleDrop(e: DragEvent) {\r\n e.preventDefault(); setIsDragOver(false)\r\n if (e.dataTransfer.files.length > 0) addFiles(e.dataTransfer.files)\r\n }\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n const form = e.currentTarget\r\n const formData = new FormData(form)\r\n\r\n const title = (formData.get('title') as string)?.trim() ?? ''\r\n const email = (formData.get('email') as string)?.trim() ?? userEmail ?? ''\r\n const newErrors: Record<string, string> = {}\r\n\r\n if (!title) newErrors.title = t('error.required')\r\n else if (title.length < 5) newErrors.title = t('error.titleMin')\r\n if (!isAuthenticated && email && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\r\n newErrors.email = t('error.emailInvalid')\r\n }\r\n\r\n if (Object.keys(newErrors).length > 0) { setErrors(newErrors); return }\r\n setErrors({})\r\n\r\n if (rememberEmail && email) saveWidgetEmail(ctx.apiKey, email)\r\n\r\n // Save diagnostic preferences\r\n saveMetadataPreferences(ctx.apiKey, diagPrefs)\r\n\r\n const validFiles = files.filter(f => !f.error)\r\n const data: SubmitTicketData = {\r\n title,\r\n description: (formData.get('description') as string)?.trim() || undefined,\r\n email,\r\n priority: (formData.get('priority') as SubmitTicketData['priority']) ?? 'medium',\r\n categoryId: selectedCategory?.id,\r\n clientMetadata: collectAllMetadata(ctx.apiKey),\r\n }\r\n\r\n submitMutation.mutate({ data, validFiles })\r\n }\r\n\r\n if (success) {\r\n return (\r\n <div className=\"rqd-success\" style={{ textAlign: 'center', padding: '24px 0' }}>\r\n <div style={{ fontSize: 48, marginBottom: 12 }}>{'\\u2705'}</div>\r\n <h3 style={{ margin: '0 0 8px', fontSize: 18 }}>{t('success.title')}</h3>\r\n <p>{t('success.ticketNumber')}{success.ticketNumber}</p>\r\n {success.trackingToken && (\r\n <>\r\n <p style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('success.trackingHint')}</p>\r\n <div className=\"rqd-token-box\">{success.trackingToken}</div>\r\n <button className=\"rqd-btn rqd-btn-secondary\" onClick={() => navigator.clipboard.writeText(success.trackingToken!)}>\r\n {t('success.copyToken')}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n if (submitMutation.isPending && uploadProgress) {\r\n return (\r\n <div style={{ padding: '24px 0', textAlign: 'center' }}>\r\n <p style={{ marginBottom: 12, fontWeight: 500 }}>{t('attach.uploading')}</p>\r\n <div className=\"rqd-file-item\" style={{ marginBottom: 8 }}>\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{uploadProgress.fileName}</span>\r\n </div>\r\n <span style={{ fontSize: 12, color: 'var(--rqd-text-secondary)' }}>{uploadProgress.percent}%</span>\r\n </div>\r\n <div className=\"rqd-progress\">\r\n <div className=\"rqd-progress-bar\" style={{ width: `${uploadProgress.percent}%` }} />\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <form className=\"rqd-form\" onSubmit={handleSubmit} noValidate>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.title')}</label>\r\n <input className=\"rqd-input\" name=\"title\" placeholder={t('form.titlePlaceholder')} required />\r\n {errors.title && <div className=\"rqd-error-text\">{errors.title}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.description')}</label>\r\n <textarea className=\"rqd-textarea\" name=\"description\" placeholder={t('form.descriptionPlaceholder')} />\r\n </div>\r\n {!isAuthenticated && (\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.email')}</label>\r\n <input className=\"rqd-input\" name=\"email\" type=\"email\" placeholder={t('form.emailPlaceholder')} defaultValue={userEmail ?? savedEmail ?? ''} />\r\n {errors.email && <div className=\"rqd-error-text\">{errors.email}</div>}\r\n <label className=\"rqd-checkbox-label\" style={{ marginTop: 6 }}>\r\n <input type=\"checkbox\" checked={rememberEmail} onChange={(e) => setRememberEmail(e.target.checked)} />\r\n {t('mytickets.rememberMe')}\r\n </label>\r\n </div>\r\n )}\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.priority')}</label>\r\n <select className=\"rqd-select\" name=\"priority\" defaultValue=\"medium\">\r\n <option value=\"low\">{t('form.priorityLow')}</option>\r\n <option value=\"medium\">{t('form.priorityMedium')}</option>\r\n <option value=\"high\">{t('form.priorityHigh')}</option>\r\n <option value=\"urgent\">{t('form.priorityUrgent')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Category Selector */}\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.categorySelected')}</label>\r\n {selectedCategory ? (\r\n <div className=\"rqd-category-selected\">\r\n <span>\r\n {categoryPath.map(c => c.name).join(' > ')}{categoryPath.length > 0 ? ' > ' : ''}{selectedCategory.name}\r\n </span>\r\n <button type=\"button\" onClick={() => { setSelectedCategory(null); setCategoryPath([]) }}>×</button>\r\n </div>\r\n ) : (\r\n <>\r\n {categoryPath.length > 0 && (\r\n <div className=\"rqd-category-breadcrumb\">\r\n <button type=\"button\" onClick={() => setCategoryPath([])}>{t('form.categoryPlaceholder')}</button>\r\n {categoryPath.map((c, i) => (\r\n <span key={c.id}>\r\n <span className=\"rqd-category-breadcrumb-sep\">›</span>\r\n <button type=\"button\" onClick={() => setCategoryPath(prev => prev.slice(0, i + 1))}>{c.name}</button>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n <div className=\"rqd-category-list\">\r\n {categories.map(cat => (\r\n <button\r\n key={cat.id}\r\n type=\"button\"\r\n className=\"rqd-category-item\"\r\n onClick={() => {\r\n if (cat.hasChildren) {\r\n setCategoryPath(prev => [...prev, cat])\r\n } else {\r\n setSelectedCategory(cat)\r\n }\r\n }}\r\n >\r\n {cat.name}\r\n {cat.hasChildren && <span className=\"rqd-category-item-chevron\">›</span>}\r\n </button>\r\n ))}\r\n {categories.length === 0 && categoryPath.length === 0 && (\r\n <span style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('form.categoryPlaceholder')}</span>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Diagnostic Metadata */}\r\n <div className=\"rqd-form-group\">\r\n <button\r\n type=\"button\"\r\n className=\"rqd-diag-toggle\"\r\n onClick={() => setDiagOpen(prev => !prev)}\r\n >\r\n <span>{t('diag.title')}</span>\r\n <span>{diagOpen ? '\\u25B2' : '\\u25BC'}</span>\r\n </button>\r\n {diagOpen && (\r\n <div className=\"rqd-diag-panel\">\r\n <p style={{ fontSize: 12, color: 'var(--rqd-text-secondary)', margin: '0 0 6px' }}>{t('diag.hint')}</p>\r\n {DIAGNOSTIC_FIELDS.map(field => (\r\n <label key={field.key} className=\"rqd-diag-item\">\r\n <input\r\n type=\"checkbox\"\r\n checked={diagPrefs[field.key]}\r\n onChange={(e) => setDiagPrefs(prev => ({ ...prev, [field.key]: e.target.checked }))}\r\n />\r\n <span>{t(field.labelKey)}</span>\r\n <span className=\"rqd-diag-item-value\">{diagValues[field.key] ?? '—'}</span>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.attachment')}</label>\r\n <div\r\n className={`rqd-dropzone${isDragOver ? ' rqd-dropzone-active' : ''}`}\r\n onDragOver={handleDragOver} onDragLeave={handleDragLeave} onDrop={handleDrop}\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n {isDragOver ? t('attach.dropzoneActive') : t('attach.dropzone')}\r\n <input ref={fileInputRef} type=\"file\" multiple style={{ display: 'none' }}\r\n onChange={(e) => { if (e.target.files) addFiles(e.target.files); e.target.value = '' }} />\r\n </div>\r\n {files.length > 0 && (\r\n <div className=\"rqd-file-list\">\r\n {files.map(f => (\r\n <div key={f.id} className=\"rqd-file-item\">\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{f.file.name}</span>\r\n <span className=\"rqd-file-item-size\">\r\n {formatFileSize(f.file.size)}\r\n {f.error && <span style={{ color: '#e74c3c', marginLeft: 6 }}>{f.error}</span>}\r\n </span>\r\n </div>\r\n <button className=\"rqd-file-remove\" onClick={() => removeFile(f.id)} type=\"button\">×</button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={submitMutation.isPending}>\r\n {submitMutation.isPending ? t('form.submitting') : t('form.submit')}\r\n </button>\r\n </form>\r\n )\r\n}\r\n","import { useState, useEffect, useCallback, type FormEvent } from 'react'\r\nimport { useQuery } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetMyTicketsOptions, widgetUserOptions } from '../queries'\r\nimport { trackTicket, type TicketListItem } from '../../api-client'\r\nimport { saveWidgetEmail, loadWidgetEmail, getTrackingTokens } from '../../storage'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface MyTicketsViewProps {\r\n projectId: string\r\n onSelectTicket: (ticketId: string) => void\r\n isAuthenticated?: boolean\r\n userEmail?: string\r\n}\r\n\r\nexport function MyTicketsView({ projectId, onSelectTicket, isAuthenticated, userEmail }: MyTicketsViewProps) {\r\n const ctx = useReqdeskContext()\r\n const savedEmail = loadWidgetEmail(ctx.apiKey)\r\n\r\n const [email, setEmail] = useState(userEmail ?? savedEmail ?? '')\r\n const [rememberMe, setRememberMe] = useState(!!savedEmail)\r\n const [submittedEmail, setSubmittedEmail] = useState<string | null>(\r\n isAuthenticated && userEmail ? userEmail : savedEmail,\r\n )\r\n const [tokenTickets, setTokenTickets] = useState<TicketListItem[]>([])\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n // Resolve email → userId\r\n const { data: widgetUser } = useQuery(widgetUserOptions(projectId, submittedEmail ?? ''))\r\n const userId = widgetUser?.userId ?? ''\r\n\r\n // Fetch tickets once userId is resolved\r\n const { data: emailTickets = [], isLoading } = useQuery(widgetMyTicketsOptions(projectId, userId))\r\n\r\n // Also load token-based tickets\r\n useEffect(() => {\r\n const tokens = getTrackingTokens(ctx.apiKey)\r\n if (tokens.length === 0) return\r\n\r\n Promise.allSettled(\r\n tokens.slice(0, 5).map(tk => trackTicket(tk)),\r\n ).then(results => {\r\n const tracked: TicketListItem[] = []\r\n for (const r of results) {\r\n if (r.status === 'fulfilled') {\r\n const t = r.value\r\n if (!emailTickets.some(et => et.id === t.id)) {\r\n tracked.push({\r\n id: t.id,\r\n ticketNumber: t.ticketNumber,\r\n title: t.title,\r\n status: t.status,\r\n priority: t.priority,\r\n createdAt: t.createdAt,\r\n })\r\n }\r\n }\r\n }\r\n setTokenTickets(tracked)\r\n })\r\n }, [ctx.apiKey, emailTickets])\r\n\r\n const allTickets = [...emailTickets, ...tokenTickets]\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n const trimmed = email.trim()\r\n if (!trimmed || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return\r\n\r\n if (rememberMe) saveWidgetEmail(ctx.apiKey, trimmed)\r\n setSubmittedEmail(trimmed)\r\n }\r\n\r\n function formatDate(iso: string): string {\r\n try { return new Date(iso).toLocaleDateString() } catch { return iso }\r\n }\r\n\r\n // Show email entry form if not yet submitted and not authenticated\r\n if (!submittedEmail && !isAuthenticated) {\r\n return (\r\n <div className=\"rqd-email-form\">\r\n <p>{t('mytickets.emailPrompt')}</p>\r\n <form onSubmit={handleSubmit}>\r\n <div className=\"rqd-form-group\">\r\n <input\r\n className=\"rqd-input\"\r\n type=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n placeholder={t('mytickets.emailPlaceholder')}\r\n required\r\n />\r\n </div>\r\n <label className=\"rqd-checkbox-label\">\r\n <input\r\n type=\"checkbox\"\r\n checked={rememberMe}\r\n onChange={(e) => setRememberMe(e.target.checked)}\r\n />\r\n {t('mytickets.rememberMe')}\r\n </label>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" style={{ marginTop: 12 }}>\r\n {t('mytickets.lookup')}\r\n </button>\r\n </form>\r\n </div>\r\n )\r\n }\r\n\r\n if (isLoading) {\r\n return <div className=\"rqd-loading\">{t('mytickets.lookingUp')}</div>\r\n }\r\n\r\n if (allTickets.length === 0) {\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <p>{submittedEmail && !widgetUser ? t('mytickets.noAccount') : t('mytickets.noTickets')}</p>\r\n {submittedEmail && !isAuthenticated && (\r\n <button className=\"rqd-btn rqd-btn-secondary\" style={{ width: 'auto', padding: '8px 20px' }} onClick={() => setSubmittedEmail(null)}>\r\n {t('tracker.back')}\r\n </button>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div className=\"rqd-ticket-list\">\r\n {allTickets.map(ticket => (\r\n <div\r\n key={ticket.id}\r\n className=\"rqd-ticket-card\"\r\n onClick={() => onSelectTicket(ticket.id)}\r\n >\r\n <div className=\"rqd-ticket-card-top\">\r\n <span className=\"rqd-ticket-card-number\">{ticket.ticketNumber}</span>\r\n <span className=\"rqd-badge\">{ticket.status}</span>\r\n </div>\r\n <span className=\"rqd-ticket-card-title\">{ticket.title}</span>\r\n <span className=\"rqd-ticket-card-date\">{formatDate(ticket.createdAt)}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetTicketDetailOptions } from '../queries'\r\nimport { submitReply, closeTicket, type AttachmentMeta, type TicketDetail } from '../../api-client'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface TicketDetailViewProps {\r\n ticketId: string\r\n onBack: () => void\r\n}\r\n\r\nfunction formatDate(iso: string): string {\r\n try { return new Date(iso).toLocaleString() } catch { return iso }\r\n}\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\r\n}\r\n\r\nexport function TicketDetailView({ ticketId, onBack }: TicketDetailViewProps) {\r\n const ctx = useReqdeskContext()\r\n const queryClient = useQueryClient()\r\n const [replyBody, setReplyBody] = useState('')\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const { data: ticket, isLoading, error } = useQuery(widgetTicketDetailOptions(ticketId))\r\n\r\n const replyMutation = useMutation({\r\n mutationFn: (body: string) => submitReply(ticketId, body),\r\n onMutate: async (body) => {\r\n // Optimistic update: append reply to cache\r\n await queryClient.cancelQueries({ queryKey: ['widget-ticket', ticketId] })\r\n const previous = queryClient.getQueryData<TicketDetail>(['widget-ticket', ticketId])\r\n\r\n if (previous) {\r\n queryClient.setQueryData<TicketDetail>(['widget-ticket', ticketId], {\r\n ...previous,\r\n replies: [...previous.replies, {\r\n id: `optimistic-${Date.now()}`,\r\n body,\r\n authorName: ctx.userName ?? ctx.userEmail ?? 'You',\r\n isStaff: false,\r\n createdAt: new Date().toISOString(),\r\n }],\r\n })\r\n }\r\n return { previous }\r\n },\r\n onSuccess: () => {\r\n setReplyBody('')\r\n queryClient.invalidateQueries({ queryKey: ['widget-ticket', ticketId] })\r\n },\r\n onError: (_err, _vars, context) => {\r\n if (context?.previous) {\r\n queryClient.setQueryData(['widget-ticket', ticketId], context.previous)\r\n }\r\n },\r\n })\r\n\r\n const resolveMutation = useMutation({\r\n mutationFn: () => closeTicket(ticketId),\r\n onMutate: async () => {\r\n await queryClient.cancelQueries({ queryKey: ['widget-ticket', ticketId] })\r\n const previous = queryClient.getQueryData<TicketDetail>(['widget-ticket', ticketId])\r\n if (previous) {\r\n queryClient.setQueryData<TicketDetail>(['widget-ticket', ticketId], {\r\n ...previous,\r\n status: 'resolved',\r\n })\r\n }\r\n return { previous }\r\n },\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: ['widget-ticket', ticketId] })\r\n },\r\n onError: (_err, _vars, context) => {\r\n if (context?.previous) {\r\n queryClient.setQueryData(['widget-ticket', ticketId], context.previous)\r\n }\r\n },\r\n })\r\n\r\n if (isLoading) {\r\n return <div className=\"rqd-loading\">{t('detail.loading')}</div>\r\n }\r\n\r\n if (error || !ticket) {\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <p>{t('error.generic')}</p>\r\n <button className=\"rqd-btn rqd-btn-secondary\" style={{ width: 'auto', padding: '8px 20px' }} onClick={onBack}>\r\n {t('tracker.back')}\r\n </button>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div>\r\n <div className=\"rqd-ticket-header\">\r\n <h3>{ticket.title}</h3>\r\n <div className=\"rqd-ticket-header-meta\">\r\n <span className=\"rqd-ticket-card-number\">{ticket.ticketNumber}</span>\r\n <span className=\"rqd-badge\">{ticket.status}</span>\r\n <span className=\"rqd-badge\" style={{ background: 'var(--rqd-bg-secondary)', color: 'var(--rqd-text-secondary)' }}>\r\n {ticket.priority}\r\n </span>\r\n <span className=\"rqd-ticket-card-date\">{formatDate(ticket.createdAt)}</span>\r\n </div>\r\n </div>\r\n\r\n {ticket.description && (\r\n <>\r\n <div className=\"rqd-section-title\">{t('detail.description')}</div>\r\n <div className=\"rqd-ticket-desc\">{ticket.description}</div>\r\n </>\r\n )}\r\n\r\n {ticket.attachments.length > 0 && (\r\n <>\r\n <div className=\"rqd-section-title\">{t('detail.attachments')}</div>\r\n <div className=\"rqd-attachment-list\">\r\n {ticket.attachments.map((a: AttachmentMeta) => (\r\n <div key={a.id} className=\"rqd-attachment-item\">\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{a.fileName}</span>\r\n <span className=\"rqd-file-item-size\">{formatFileSize(a.fileSize)}</span>\r\n </div>\r\n {a.downloadUrl && (\r\n <a href={a.downloadUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n {t('attach.download')}\r\n </a>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n <div className=\"rqd-section-title\">{t('detail.replies')}</div>\r\n {ticket.replies.length === 0 ? (\r\n <p style={{ color: 'var(--rqd-text-secondary)', fontSize: 13, margin: '0 0 12px' }}>\r\n {t('detail.noReplies')}\r\n </p>\r\n ) : (\r\n <div>\r\n {ticket.replies.map(reply => (\r\n <div key={reply.id} className=\"rqd-reply\">\r\n <div className=\"rqd-reply-header\">\r\n <span className={reply.isStaff ? 'rqd-reply-staff' : ''}>\r\n {reply.isStaff ? `${reply.authorName} \\u00b7 ${t('detail.staff')}` : reply.authorName}\r\n </span>\r\n <span>{formatDate(reply.createdAt)}</span>\r\n </div>\r\n <div className=\"rqd-reply-body\">{reply.body}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"rqd-reply-compose\">\r\n <textarea\r\n className=\"rqd-textarea\"\r\n value={replyBody}\r\n onChange={(e) => setReplyBody(e.target.value)}\r\n placeholder={t('detail.replyPlaceholder')}\r\n rows={3}\r\n />\r\n <div style={{ display: 'flex', gap: 8 }}>\r\n <button\r\n className=\"rqd-btn rqd-btn-primary\"\r\n style={{ flex: 1 }}\r\n onClick={() => replyMutation.mutate(replyBody.trim())}\r\n disabled={!replyBody.trim() || replyMutation.isPending}\r\n >\r\n {replyMutation.isPending ? t('detail.sending') : t('detail.sendReply')}\r\n </button>\r\n {ticket.status !== 'resolved' && ticket.status !== 'closed' && (\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n style={{ flex: 0, whiteSpace: 'nowrap', padding: '10px 16px' }}\r\n onClick={() => resolveMutation.mutate()}\r\n disabled={resolveMutation.isPending}\r\n >\r\n {resolveMutation.isPending ? t('detail.resolving') : t('detail.resolve')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback, type FormEvent } from 'react'\r\nimport { useMutation } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { trackTicket } from '../../api-client'\r\nimport { getTrackingTokens } from '../../storage'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface TrackTicketViewProps {\r\n onTrackSuccess: (ticketId: string) => void\r\n}\r\n\r\nexport function TrackTicketView({ onTrackSuccess }: TrackTicketViewProps) {\r\n const ctx = useReqdeskContext()\r\n const [token, setToken] = useState('')\r\n const savedTokens = getTrackingTokens(ctx.apiKey)\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const trackMutation = useMutation({\r\n mutationFn: (trackToken: string) => trackTicket(trackToken.trim()),\r\n onSuccess: (result) => onTrackSuccess(result.id),\r\n })\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n if (token.trim()) trackMutation.mutate(token)\r\n }\r\n\r\n return (\r\n <div>\r\n <form onSubmit={handleSubmit}>\r\n <div className=\"rqd-form-group\">\r\n <input\r\n className=\"rqd-input\"\r\n value={token}\r\n onChange={(e) => setToken(e.target.value)}\r\n placeholder={t('track.tokenPlaceholder')}\r\n required\r\n />\r\n {trackMutation.isError && <div className=\"rqd-error-text\">{t('track.invalidToken')}</div>}\r\n </div>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={trackMutation.isPending || !token.trim()}>\r\n {trackMutation.isPending ? t('track.tracking') : t('track.submit')}\r\n </button>\r\n </form>\r\n\r\n {savedTokens.length > 0 && (\r\n <div style={{ marginTop: 20 }}>\r\n <div className=\"rqd-section-title\">{t('track.recentTickets')}</div>\r\n <div className=\"rqd-ticket-list\">\r\n {savedTokens.slice(0, 5).map(tk => (\r\n <button\r\n key={tk}\r\n className=\"rqd-ticket-card\"\r\n style={{ border: 'none', textAlign: 'start', width: '100%' }}\r\n onClick={() => trackMutation.mutate(tk)}\r\n >\r\n <span className=\"rqd-ticket-card-number\" style={{ fontFamily: 'monospace', fontSize: 12 }}>\r\n {tk.slice(0, 20)}...\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\nimport { en } from '../i18n/en'\r\nimport { ar } from '../i18n/ar'\r\nimport { themeToStyle } from '../theme'\r\nimport { saveWidgetConfig, loadWidgetConfig, loadWidgetEmail, clearWidgetEmail } from '../storage'\r\nimport { login, logout, isAuthConfigured } from '../auth/widget-auth'\r\nimport { ShadowRoot } from './shadow-root'\r\nimport { SubmitTicketView } from './views/SubmitTicketView'\r\nimport { MyTicketsView } from './views/MyTicketsView'\r\nimport { TicketDetailView } from './views/TicketDetailView'\r\nimport { TrackTicketView } from './views/TrackTicketView'\r\nimport type { TicketResult, WidgetError } from './types'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ntype WidgetView = 'home' | 'new-ticket' | 'my-tickets' | 'ticket-detail' | 'track' | 'kb' | 'preferences'\r\n\r\ninterface FloatingWidgetProps {\r\n position?: 'bottom-right' | 'bottom-left'\r\n contained?: boolean\r\n onTicketCreated?: (ticket: TicketResult) => void\r\n onError?: (error: WidgetError) => void\r\n}\r\n\r\nconst ICONS = {\r\n chat: 'M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z',\r\n close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',\r\n newTicket: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',\r\n tickets: 'M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zM8 15.01l1.41 1.41L11 14.84V19h2v-4.16l1.59 1.59L16 15.01 12.01 11z',\r\n track: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',\r\n kb: 'M21 5c-1.11-.35-2.33-.5-3.5-.5-1.95 0-4.05.4-5.5 1.5-1.45-1.1-3.55-1.5-5.5-1.5S2.45 4.9 1 6v14.65c0 .25.25.5.5.5.1 0 .15-.05.25-.05C3.1 20.45 5.05 20 6.5 20c1.95 0 4.05.4 5.5 1.5 1.35-.85 3.8-1.5 5.5-1.5 1.65 0 3.35.3 4.75 1.05.1.05.15.05.25.05.25 0 .5-.25.5-.5V6c-.6-.45-1.25-.75-2-1zm0 13.5c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5V8c1.35-.85 3.8-1.5 5.5-1.5 1.2 0 2.4.15 3.5.5v11.5z',\r\n back: 'M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z',\r\n backRtl: 'M4 11h12.17l-5.59-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-2z',\r\n settings: 'M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 00-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.49.49 0 00-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6A3.6 3.6 0 1115.6 12 3.6 3.6 0 0112 15.6z',\r\n}\r\n\r\nfunction SvgIcon({ path, size = 20 }: { path: string; size?: number }) {\r\n return (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\" style={{ display: 'block', flexShrink: 0 }}>\r\n <path d={path} />\r\n </svg>\r\n )\r\n}\r\n\r\nexport function FloatingWidget({\r\n position = 'bottom-right',\r\n contained = false,\r\n onTicketCreated,\r\n onError,\r\n}: FloatingWidgetProps) {\r\n const ctx = useReqdeskContext()\r\n const [isOpen, setIsOpen] = useState(false)\r\n const [view, setView] = useState<WidgetView>('home')\r\n const [selectedTicketId, setSelectedTicketId] = useState<string | null>(null)\r\n const [emailCleared, setEmailCleared] = useState(false)\r\n\r\n const savedPrefs = loadWidgetConfig(ctx.apiKey)\r\n const [userLang, setUserLang] = useState<string | null>(savedPrefs?.language ?? null)\r\n const [userThemeMode, setUserThemeMode] = useState<string | null>(savedPrefs?.theme?.mode ?? null)\r\n const [userColor, setUserColor] = useState<string | null>(savedPrefs?.theme?.primaryColor ?? null)\r\n\r\n const activeLang = userLang ?? ctx.language ?? 'en'\r\n const activeThemeMode = (userThemeMode ?? ctx.theme?.mode ?? 'light') as 'light' | 'dark' | 'auto'\r\n const activeColor = userColor ?? ctx.theme?.primaryColor ?? '#42b983'\r\n const activeTheme = { ...ctx.theme, mode: activeThemeMode, primaryColor: activeColor }\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[activeLang] ?? translations.en\r\n return lang[key] ?? key\r\n }, [activeLang, ctx.translations])\r\n\r\n const isRtl = activeLang === 'ar'\r\n const cssVars = themeToStyle(activeTheme)\r\n const posClass = `rqd-${position}`\r\n const containedClass = contained ? ' rqd-contained' : ''\r\n const brandName = ctx.theme?.brandName\r\n const brandLogo = ctx.theme?.logo\r\n const hideBranding = ctx.theme?.hideBranding === true\r\n\r\n // Derive projectId from API key context (resolved server-side)\r\n const projectId = '_current'\r\n\r\n function toggleOpen() {\r\n setIsOpen(prev => !prev)\r\n if (!isOpen) {\r\n setView('home')\r\n setSelectedTicketId(null)\r\n }\r\n }\r\n\r\n function goHome() {\r\n setView('home')\r\n setSelectedTicketId(null)\r\n setEmailCleared(false)\r\n }\r\n\r\n function handleLangChange(lang: string) {\r\n setUserLang(lang)\r\n saveWidgetConfig(ctx.apiKey, { language: lang })\r\n }\r\n\r\n function handleThemeChange(mode: string) {\r\n setUserThemeMode(mode)\r\n saveWidgetConfig(ctx.apiKey, { theme: { ...ctx.theme, mode: mode as 'light' | 'dark' | 'auto', primaryColor: activeColor } })\r\n }\r\n\r\n function handleColorChange(color: string) {\r\n setUserColor(color)\r\n saveWidgetConfig(ctx.apiKey, { theme: { ...ctx.theme, mode: activeThemeMode, primaryColor: color } })\r\n }\r\n\r\n const COLOR_PRESETS = [\r\n { color: '#42b983', label: 'Green' },\r\n { color: '#3b82f6', label: 'Blue' },\r\n { color: '#8b5cf6', label: 'Purple' },\r\n { color: '#f59e0b', label: 'Orange' },\r\n { color: '#ef4444', label: 'Red' },\r\n ]\r\n\r\n function handleClearEmail() {\r\n clearWidgetEmail(ctx.apiKey)\r\n setEmailCleared(true)\r\n setTimeout(() => setEmailCleared(false), 2000)\r\n }\r\n\r\n function openTicketDetail(ticketId: string) {\r\n setSelectedTicketId(ticketId)\r\n setView('ticket-detail')\r\n }\r\n\r\n const menuItems = [\r\n { key: 'new-ticket' as const, icon: ICONS.newTicket, label: t('menu.newTicket'), desc: t('menu.newTicketDesc') },\r\n { key: 'my-tickets' as const, icon: ICONS.tickets, label: t('menu.myTickets'), desc: t('menu.myTicketsDesc') },\r\n { key: 'track' as const, icon: ICONS.track, label: t('menu.trackTicket'), desc: t('menu.trackTicketDesc') },\r\n { key: 'kb' as const, icon: ICONS.kb, label: t('menu.knowledgeBase'), desc: t('menu.knowledgeBaseDesc') },\r\n { key: 'preferences' as const, icon: ICONS.settings, label: t('menu.preferences'), desc: t('menu.preferencesDesc') },\r\n ]\r\n\r\n function renderViewContent() {\r\n switch (view) {\r\n case 'home':\r\n return (\r\n <div className=\"rqd-menu\">\r\n {menuItems.map(item => (\r\n <button\r\n key={item.key}\r\n className=\"rqd-menu-item\"\r\n onClick={() => setView(item.key)}\r\n >\r\n <div className=\"rqd-menu-icon\">\r\n <SvgIcon path={item.icon} size={22} />\r\n </div>\r\n <div className=\"rqd-menu-text\">\r\n <span className=\"rqd-menu-label\">{item.label}</span>\r\n <span className=\"rqd-menu-desc\">{item.desc}</span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n )\r\n\r\n case 'new-ticket':\r\n return (\r\n <SubmitTicketView\r\n projectId={projectId}\r\n onSuccess={(result) => {\r\n onTicketCreated?.(result)\r\n }}\r\n onError={onError}\r\n isAuthenticated={ctx.isAuthenticated}\r\n userEmail={ctx.userEmail}\r\n />\r\n )\r\n\r\n case 'my-tickets':\r\n return (\r\n <MyTicketsView\r\n projectId={projectId}\r\n onSelectTicket={openTicketDetail}\r\n isAuthenticated={ctx.isAuthenticated}\r\n userEmail={ctx.userEmail}\r\n />\r\n )\r\n\r\n case 'ticket-detail':\r\n if (!selectedTicketId) return null\r\n return (\r\n <TicketDetailView\r\n ticketId={selectedTicketId}\r\n onBack={() => setView('my-tickets')}\r\n />\r\n )\r\n\r\n case 'track':\r\n return (\r\n <TrackTicketView\r\n onTrackSuccess={openTicketDetail}\r\n />\r\n )\r\n\r\n case 'kb':\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <SvgIcon path={ICONS.kb} size={40} />\r\n <p>{t('menu.kbPlaceholder')}</p>\r\n </div>\r\n )\r\n\r\n case 'preferences':\r\n return (\r\n <div className=\"rqd-prefs\">\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.language')}</span>\r\n <div className=\"rqd-prefs-options\">\r\n <button\r\n className={`rqd-prefs-option${activeLang === 'en' ? ' rqd-active' : ''}`}\r\n onClick={() => handleLangChange('en')}\r\n >\r\n English\r\n </button>\r\n <button\r\n className={`rqd-prefs-option${activeLang === 'ar' ? ' rqd-active' : ''}`}\r\n onClick={() => handleLangChange('ar')}\r\n >\r\n العربية\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.theme')}</span>\r\n <div className=\"rqd-prefs-options\">\r\n {(['light', 'dark', 'auto'] as const).map(mode => (\r\n <button\r\n key={mode}\r\n className={`rqd-prefs-option${activeThemeMode === mode ? ' rqd-active' : ''}`}\r\n onClick={() => handleThemeChange(mode)}\r\n >\r\n {t(`prefs.${mode}`)}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Accent Color */}\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.accentColor')}</span>\r\n <div className=\"rqd-color-presets\">\r\n {COLOR_PRESETS.map(preset => (\r\n <button\r\n key={preset.color}\r\n className={`rqd-color-preset${activeColor === preset.color ? ' rqd-active' : ''}`}\r\n style={{ background: preset.color, color: preset.color }}\r\n onClick={() => handleColorChange(preset.color)}\r\n aria-label={preset.label}\r\n title={preset.label}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Clear saved email */}\r\n {loadWidgetEmail(ctx.apiKey) && (\r\n <div className=\"rqd-prefs-group\">\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n onClick={handleClearEmail}\r\n style={{ width: 'auto', padding: '8px 16px' }}\r\n >\r\n {emailCleared ? t('prefs.emailCleared') : t('prefs.clearEmail')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n }\r\n }\r\n\r\n const viewTitle: Record<WidgetView, string> = {\r\n home: brandName ?? t('widget.title'),\r\n 'new-ticket': t('widget.newTicket'),\r\n 'my-tickets': t('menu.myTickets'),\r\n 'ticket-detail': t('menu.myTickets'),\r\n track: t('widget.trackTicket'),\r\n kb: t('menu.knowledgeBase'),\r\n preferences: t('prefs.title'),\r\n }\r\n\r\n const canGoBack = view !== 'home'\r\n const goBackTarget = view === 'ticket-detail' ? 'my-tickets' : 'home'\r\n\r\n return (\r\n <ShadowRoot>\r\n <div\r\n style={cssVars as React.CSSProperties}\r\n {...(isRtl ? { dir: 'rtl' } : {})}\r\n >\r\n <button\r\n className={`rqd-fab ${posClass}${containedClass}`}\r\n onClick={toggleOpen}\r\n aria-label={isOpen ? t('widget.close') : t('widget.title')}\r\n >\r\n <SvgIcon path={isOpen ? ICONS.close : ICONS.chat} size={24} />\r\n </button>\r\n\r\n <div className={`rqd-panel ${posClass}${containedClass}${isOpen ? '' : ' rqd-hidden'}`}>\r\n <div className=\"rqd-header\">\r\n <div className=\"rqd-header-brand\">\r\n {canGoBack && (\r\n <button\r\n className=\"rqd-header-close\"\r\n onClick={() => goBackTarget === 'home' ? goHome() : setView(goBackTarget as WidgetView)}\r\n aria-label={t('tracker.back')}\r\n >\r\n <SvgIcon path={isRtl ? ICONS.backRtl : ICONS.back} size={18} />\r\n </button>\r\n )}\r\n {view === 'home' && brandLogo && (\r\n <img src={brandLogo} alt=\"\" className=\"rqd-header-logo\" />\r\n )}\r\n <span className=\"rqd-header-title\">{viewTitle[view]}</span>\r\n </div>\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\r\n {(ctx.auth || isAuthConfigured()) && view === 'home' && (\r\n <button\r\n className=\"rqd-auth-btn\"\r\n onClick={() => ctx.isAuthenticated ? logout() : login()}\r\n aria-label={ctx.isAuthenticated ? t('auth.logout') : t('auth.login')}\r\n >\r\n {ctx.isAuthenticated ? ctx.userName ?? t('auth.logout') : t('auth.login')}\r\n </button>\r\n )}\r\n <button\r\n className=\"rqd-header-close\"\r\n onClick={toggleOpen}\r\n aria-label={t('widget.close')}\r\n >\r\n <SvgIcon path={ICONS.close} size={18} />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"rqd-body\">\r\n {renderViewContent()}\r\n </div>\r\n\r\n {!hideBranding && (\r\n <div className=\"rqd-footer\">\r\n <span>{t('branding.poweredBy')}</span>\r\n <a href=\"https://reqdesk.com\" target=\"_blank\" rel=\"noopener noreferrer\">Reqdesk</a>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","names":["apiSubmitTicket","apiTrackTicket","apiSubmitTrackingReply","translations","translations","formatFileSize","apiSubmitTicket","translations","translations","translations"],"sources":["../src/auth/widget-auth.ts","../src/react/ReqdeskProvider.tsx","../src/react/useReqdesk.ts","../src/react/shadow-root.tsx","../src/react/TicketForm.tsx","../src/react/SupportPortal.tsx","../src/react/queries.ts","../src/client-metadata.ts","../src/react/views/SubmitTicketView.tsx","../src/react/views/MyTicketsView.tsx","../src/react/views/TicketDetailView.tsx","../src/react/views/TrackTicketView.tsx","../src/react/FloatingWidget.tsx"],"sourcesContent":["import { createOidc } from 'oidc-spa/core'\nimport type { OidcAuthConfig } from '../types'\nimport { setOidcTokenProvider } from '../ofetch-client'\n\nexport interface WidgetAuthState {\n isAuthenticated: boolean\n isLoading: boolean\n userEmail?: string\n userName?: string\n}\n\ntype AuthStateListener = (state: WidgetAuthState) => void\n\nlet authState: WidgetAuthState = { isAuthenticated: false, isLoading: false }\nlet listeners: AuthStateListener[] = []\nlet oidcInstance: any = null\nlet initPromise: Promise<void> | null = null\n\nfunction notify() {\n for (const listener of listeners) {\n try { listener(authState) } catch { /* ignore */ }\n }\n}\n\nfunction setState(update: Partial<WidgetAuthState>) {\n authState = { ...authState, ...update }\n notify()\n}\n\nexport function getAuthState(): WidgetAuthState {\n return authState\n}\n\nexport function onAuthStateChange(listener: AuthStateListener): () => void {\n listeners.push(listener)\n return () => {\n listeners = listeners.filter(l => l !== listener)\n }\n}\n\nexport function initWidgetAuth(config: OidcAuthConfig): Promise<void> {\n initPromise = _initWidgetAuth(config)\n return initPromise\n}\n\nasync function _initWidgetAuth(config: OidcAuthConfig): Promise<void> {\n setState({ isLoading: true })\n\n try {\n const oidc = await createOidc({\n issuerUri: config.issuerUri,\n clientId: config.clientId,\n BASE_URL: '/',\n })\n\n oidcInstance = oidc\n\n if (oidc.isUserLoggedIn) {\n setOidcTokenProvider(() => oidc.getTokens())\n\n const tokens = await oidc.getTokens()\n const payload = decodeJwtPayload(tokens.accessToken)\n\n setState({\n isAuthenticated: true,\n isLoading: false,\n userEmail: payload?.email,\n userName: payload?.name ?? payload?.preferred_username,\n })\n\n oidc.subscribeToTokensChange(async (newTokens) => {\n const p = decodeJwtPayload(newTokens.accessToken)\n setState({\n userEmail: p?.email ?? authState.userEmail,\n userName: p?.name ?? p?.preferred_username ?? authState.userName,\n })\n })\n } else {\n setState({ isAuthenticated: false, isLoading: false })\n }\n } catch (err) {\n console.warn('[reqdesk-widget] oidc-spa initialization failed:', err)\n setState({ isAuthenticated: false, isLoading: false })\n }\n}\n\nexport async function login(): Promise<void> {\n if (!oidcInstance && initPromise) {\n await initPromise\n }\n if (!oidcInstance) {\n console.warn('[reqdesk-widget] Cannot login: OIDC not initialized. Check auth config.')\n return\n }\n await oidcInstance.login({ doesCurrentHrefRequiresAuth: false })\n}\n\nexport async function logout(): Promise<void> {\n if (!oidcInstance) return\n setOidcTokenProvider(null)\n setState({ isAuthenticated: false, userEmail: undefined, userName: undefined })\n await oidcInstance.logout({ redirectTo: 'current page' })\n}\n\nexport function isAuthConfigured(): boolean {\n return oidcInstance !== null\n}\n\nfunction decodeJwtPayload(token: string): Record<string, any> | null {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return null\n const payload = atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(payload)\n } catch {\n return null\n }\n}\n","import { createContext, useContext, useMemo, useEffect, useRef, useState } from 'react'\r\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\r\nimport { configureWidgetClient } from '../ofetch-client'\r\nimport { loadWidgetConfig, saveWidgetConfig } from '../storage'\r\nimport { initWidgetAuth, getAuthState, onAuthStateChange, type WidgetAuthState } from '../auth/widget-auth'\r\nimport type { ReqdeskProviderProps, ReqdeskContextValue } from './types'\r\n\r\nconst ReqdeskContext = createContext<ReqdeskContextValue | null>(null)\r\n\r\nexport function useReqdeskContext(): ReqdeskContextValue {\r\n const ctx = useContext(ReqdeskContext)\r\n if (!ctx) throw new Error('useReqdesk must be used within a <ReqdeskProvider>')\r\n return ctx\r\n}\r\n\r\n// Widget-scoped QueryClient — completely isolated from host app\r\nconst widgetQueryClient = new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 5 * 60 * 1000,\r\n gcTime: 10 * 60 * 1000,\r\n retry: (failureCount, error) => {\r\n const status = (error as any)?.status ?? (error as any)?.statusCode\r\n if (status && status >= 400 && status < 500 && status !== 408) return false\r\n if (status && status >= 500) return false\r\n return failureCount < 2\r\n },\r\n retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),\r\n refetchOnWindowFocus: false,\r\n },\r\n mutations: {\r\n retry: false,\r\n },\r\n },\r\n})\r\n\r\nexport function ReqdeskProvider({ apiKey, auth, theme, language, customer, translations, children }: ReqdeskProviderProps) {\r\n const initialized = useRef(false)\r\n const [authState, setAuthState] = useState<WidgetAuthState>(getAuthState)\r\n\r\n const saved = initialized.current ? null : loadWidgetConfig(apiKey)\r\n const resolvedLanguage = language ?? saved?.language ?? 'en'\r\n const resolvedTheme = theme ?? saved?.theme\r\n\r\n useEffect(() => {\r\n if (!initialized.current) {\r\n configureWidgetClient(window.location.origin, apiKey)\r\n initialized.current = true\r\n\r\n if (auth) {\r\n initWidgetAuth(auth)\r\n }\r\n }\r\n }, [apiKey, auth])\r\n\r\n useEffect(() => {\r\n return onAuthStateChange(setAuthState)\r\n }, [])\r\n\r\n useEffect(() => {\r\n saveWidgetConfig(apiKey, {\r\n language: resolvedLanguage,\r\n theme: resolvedTheme,\r\n })\r\n }, [apiKey, resolvedLanguage, resolvedTheme])\r\n\r\n const value = useMemo<ReqdeskContextValue>(() => ({\r\n apiKey,\r\n auth,\r\n theme: resolvedTheme,\r\n language: resolvedLanguage,\r\n customer,\r\n translations,\r\n isAuthenticated: authState.isAuthenticated,\r\n userEmail: authState.userEmail,\r\n userName: authState.userName,\r\n }), [apiKey, auth, resolvedTheme, resolvedLanguage, customer, translations, authState])\r\n\r\n return (\r\n <ReqdeskContext.Provider value={value}>\r\n <QueryClientProvider client={widgetQueryClient}>\r\n {children}\r\n </QueryClientProvider>\r\n </ReqdeskContext.Provider>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { submitTicket as apiSubmitTicket, trackTicket as apiTrackTicket, submitTrackingReply as apiSubmitTrackingReply } from '../api-client'\r\nimport type { SubmitTicketData, TicketResult, TrackedTicketResult, WidgetError, UseReqdeskReturn } from './types'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\n\r\nexport function useReqdesk(): UseReqdeskReturn {\r\n useReqdeskContext() // ensure we're inside a provider\r\n\r\n const [isLoading, setIsLoading] = useState(false)\r\n const [error, setError] = useState<WidgetError | null>(null)\r\n\r\n const submitTicket = useCallback(async (data: SubmitTicketData): Promise<TicketResult> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n const result = await apiSubmitTicket('_current', data)\r\n return result\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n const trackTicket = useCallback(async (token: string): Promise<TrackedTicketResult> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n const result = await apiTrackTicket(token)\r\n return result\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n const submitTrackingReply = useCallback(async (token: string, body: string): Promise<void> => {\r\n setIsLoading(true)\r\n setError(null)\r\n try {\r\n await apiSubmitTrackingReply(token, body)\r\n } catch (err) {\r\n const widgetError = err as WidgetError\r\n setError(widgetError)\r\n throw widgetError\r\n } finally {\r\n setIsLoading(false)\r\n }\r\n }, [])\r\n\r\n return { submitTicket, trackTicket, submitTrackingReply, isLoading, error }\r\n}\r\n","import { useRef, useEffect, useState, type ReactNode } from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { getWidgetStyles } from '../theme'\r\n\r\ninterface ShadowRootProps {\r\n children: ReactNode\r\n}\r\n\r\nexport function ShadowRoot({ children }: ShadowRootProps) {\r\n const hostRef = useRef<HTMLDivElement>(null)\r\n const [mountPoint, setMountPoint] = useState<HTMLElement | null>(null)\r\n\r\n useEffect(() => {\r\n const host = hostRef.current\r\n if (!host || host.shadowRoot) return\r\n\r\n const shadow = host.attachShadow({ mode: 'open' })\r\n\r\n const style = document.createElement('style')\r\n style.textContent = getWidgetStyles()\r\n shadow.appendChild(style)\r\n\r\n const mount = document.createElement('div')\r\n mount.className = 'rqd-root'\r\n shadow.appendChild(mount)\r\n\r\n setMountPoint(mount)\r\n }, [])\r\n\r\n return (\r\n <div ref={hostRef}>\r\n {mountPoint && createPortal(children, mountPoint)}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback, type FormEvent } from 'react'\r\nimport { useReqdesk } from './useReqdesk'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\nimport { en } from '../i18n/en'\r\nimport { ar } from '../i18n/ar'\r\nimport { themeToStyle } from '../theme'\r\nimport { saveTrackingToken } from '../storage'\r\nimport type { TicketFormProps, TicketResult, WidgetError, SubmitTicketData } from './types'\r\nimport { ShadowRoot } from './shadow-root'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\nexport function TicketForm({ mode = 'inline', onTicketCreated, onError, className, style }: TicketFormProps) {\r\n const ctx = useReqdeskContext()\r\n const { submitTicket, isLoading } = useReqdesk()\r\n const [success, setSuccess] = useState<TicketResult | null>(null)\r\n const [errors, setErrors] = useState<Record<string, string>>({})\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const handleSubmit = useCallback(async (e: FormEvent<HTMLFormElement>) => {\r\n e.preventDefault()\r\n const form = e.currentTarget\r\n const formData = new FormData(form)\r\n\r\n const title = (formData.get('title') as string)?.trim() ?? ''\r\n const email = (formData.get('email') as string)?.trim() ?? ''\r\n const newErrors: Record<string, string> = {}\r\n\r\n if (!title) newErrors.title = t('error.required')\r\n else if (title.length < 5) newErrors.title = t('error.titleMin')\r\n if (!email) newErrors.email = t('error.required')\r\n else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) newErrors.email = t('error.emailInvalid')\r\n\r\n if (Object.keys(newErrors).length > 0) {\r\n setErrors(newErrors)\r\n return\r\n }\r\n\r\n setErrors({})\r\n const data: SubmitTicketData = {\r\n title,\r\n description: (formData.get('description') as string)?.trim() || undefined,\r\n email,\r\n priority: (formData.get('priority') as SubmitTicketData['priority']) ?? 'medium',\r\n }\r\n\r\n try {\r\n const result = await submitTicket(data)\r\n if (result.trackingToken) saveTrackingToken(ctx.apiKey, result.trackingToken)\r\n setSuccess(result)\r\n onTicketCreated?.(result)\r\n } catch (err) {\r\n onError?.(err as WidgetError)\r\n }\r\n }, [submitTicket, ctx.apiKey, ctx.translations, ctx.language, onTicketCreated, onError, t])\r\n\r\n const cssVars = themeToStyle(ctx.theme)\r\n\r\n const content = success ? (\r\n <div className=\"rqd-success\" style={{ textAlign: 'center', padding: '24px 0' }}>\r\n <div style={{ fontSize: 48, marginBottom: 12 }}>{'\\u2705'}</div>\r\n <h3 style={{ margin: '0 0 8px', fontSize: 18 }}>{t('success.title')}</h3>\r\n <p>{t('success.ticketNumber')}{success.ticketNumber}</p>\r\n {success.trackingToken && (\r\n <>\r\n <p style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('success.trackingHint')}</p>\r\n <div className=\"rqd-token-box\">{success.trackingToken}</div>\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n onClick={() => navigator.clipboard.writeText(success.trackingToken!)}\r\n >\r\n {t('success.copyToken')}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n ) : (\r\n <form className=\"rqd-form\" onSubmit={handleSubmit} noValidate>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.title')}</label>\r\n <input className=\"rqd-input\" name=\"title\" placeholder={t('form.titlePlaceholder')} required />\r\n {errors.title && <div className=\"rqd-error-text\">{errors.title}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.description')}</label>\r\n <textarea className=\"rqd-textarea\" name=\"description\" placeholder={t('form.descriptionPlaceholder')} />\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.email')}</label>\r\n <input className=\"rqd-input\" name=\"email\" type=\"email\" placeholder={t('form.emailPlaceholder')} required />\r\n {errors.email && <div className=\"rqd-error-text\">{errors.email}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.priority')}</label>\r\n <select className=\"rqd-select\" name=\"priority\" defaultValue=\"medium\">\r\n <option value=\"low\">{t('form.priorityLow')}</option>\r\n <option value=\"medium\">{t('form.priorityMedium')}</option>\r\n <option value=\"high\">{t('form.priorityHigh')}</option>\r\n <option value=\"urgent\">{t('form.priorityUrgent')}</option>\r\n </select>\r\n </div>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={isLoading}>\r\n {isLoading ? t('form.submitting') : t('form.submit')}\r\n </button>\r\n </form>\r\n )\r\n\r\n if (mode === 'floating') {\r\n return (\r\n <ShadowRoot>\r\n <div className={className} style={{ ...style, ...cssVars } as React.CSSProperties}>\r\n <div className=\"rqd-body\">{content}</div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n }\r\n\r\n return (\r\n <ShadowRoot>\r\n <div className={`rqd-inline ${className ?? ''}`} style={cssVars as React.CSSProperties}>\r\n <div className=\"rqd-body\">{content}</div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n","import { useReqdeskContext } from './ReqdeskProvider'\r\nimport { useReqdesk } from './useReqdesk'\r\nimport { themeToStyle } from '../theme'\r\nimport { ShadowRoot } from './shadow-root'\r\nimport type { SupportPortalProps } from './types'\r\n\r\nexport function SupportPortal({ className }: SupportPortalProps) {\r\n const ctx = useReqdeskContext()\r\n const { isLoading } = useReqdesk()\r\n const cssVars = themeToStyle(ctx.theme)\r\n\r\n return (\r\n <ShadowRoot>\r\n <div className={`rqd-inline ${className ?? ''}`} style={cssVars as React.CSSProperties}>\r\n <div className=\"rqd-body\">\r\n {isLoading ? (\r\n <p style={{ textAlign: 'center', color: 'var(--rqd-text-secondary)' }}>Loading...</p>\r\n ) : (\r\n <p style={{ textAlign: 'center', color: 'var(--rqd-text-secondary)', padding: '24px 0' }}>\r\n Support Portal — coming in a future update.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n","import { queryOptions, keepPreviousData } from '@tanstack/react-query'\r\nimport { getTicketDetail, listMyTickets, resolveWidgetUser, trackTicket, getCategories } from '../api-client'\r\n\r\nexport const widgetTicketDetailOptions = (ticketId: string) =>\r\n queryOptions({\r\n queryKey: ['widget-ticket', ticketId],\r\n queryFn: () => getTicketDetail(ticketId),\r\n staleTime: 60_000,\r\n enabled: !!ticketId,\r\n })\r\n\r\nexport const widgetMyTicketsOptions = (projectId: string, userId: string) =>\r\n queryOptions({\r\n queryKey: ['widget-tickets', projectId, userId],\r\n queryFn: () => listMyTickets(projectId, userId),\r\n staleTime: 30_000,\r\n placeholderData: keepPreviousData,\r\n enabled: !!userId,\r\n })\r\n\r\nexport const widgetUserOptions = (projectId: string, email: string) =>\r\n queryOptions({\r\n queryKey: ['widget-user', projectId, email],\r\n queryFn: () => resolveWidgetUser(projectId, email),\r\n staleTime: 5 * 60_000,\r\n enabled: !!email,\r\n })\r\n\r\nexport const widgetTrackTicketOptions = (token: string) =>\r\n queryOptions({\r\n queryKey: ['widget-track', token],\r\n queryFn: () => trackTicket(token),\r\n staleTime: 60_000,\r\n enabled: !!token,\r\n })\r\n\r\nexport const widgetCategoriesOptions = (projectId: string, parentId?: string | null) =>\r\n queryOptions({\r\n queryKey: ['widget-categories', projectId, parentId ?? 'root'],\r\n queryFn: () => getCategories(projectId, parentId),\r\n staleTime: 5 * 60_000,\r\n })\r\n","const STORAGE_PREFIX = 'reqdesk_diag_'\n\nexport interface MetadataPreferences {\n screenResolution: boolean\n deviceType: boolean\n timezone: boolean\n referrerUrl: boolean\n language: boolean\n platform: boolean\n}\n\nconst DEFAULT_PREFS: MetadataPreferences = {\n screenResolution: false,\n deviceType: false,\n timezone: false,\n referrerUrl: false,\n language: false,\n platform: false,\n}\n\n/** Always collected — minimal, non-sensitive */\nexport function collectMinimalMetadata(): Record<string, string> {\n const meta: Record<string, string> = {}\n try {\n meta.pageUrl = window.location.href\n meta.userAgent = navigator.userAgent\n } catch { /* SSR safety */ }\n return meta\n}\n\n/** Full diagnostic set — only included for opted-in fields */\nexport function collectDiagnosticMetadata(prefs: MetadataPreferences): Record<string, string> {\n const meta: Record<string, string> = {}\n try {\n if (prefs.screenResolution) meta.screenResolution = `${screen.width}x${screen.height}`\n if (prefs.deviceType) meta.deviceType = detectDeviceType()\n if (prefs.timezone) meta.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (prefs.referrerUrl && document.referrer) meta.referrerUrl = document.referrer\n if (prefs.language) meta.language = navigator.language\n if (prefs.platform) meta.platform = navigator.platform\n } catch { /* SSR safety */ }\n return meta\n}\n\n/** Combine minimal + opted-in diagnostic metadata */\nexport function collectAllMetadata(apiKey: string): Record<string, string> {\n const prefs = getMetadataPreferences(apiKey)\n return {\n ...collectMinimalMetadata(),\n ...collectDiagnosticMetadata(prefs),\n }\n}\n\nexport function getMetadataPreferences(apiKey: string): MetadataPreferences {\n try {\n const raw = localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`)\n if (raw) return { ...DEFAULT_PREFS, ...JSON.parse(raw) }\n } catch { /* ignore */ }\n return { ...DEFAULT_PREFS }\n}\n\nexport function saveMetadataPreferences(apiKey: string, prefs: MetadataPreferences): void {\n try {\n localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, JSON.stringify(prefs))\n } catch { /* ignore */ }\n}\n\nexport function isDiagnosticEnabled(apiKey: string): boolean {\n const prefs = getMetadataPreferences(apiKey)\n return Object.values(prefs).some(v => v)\n}\n\nfunction detectDeviceType(): string {\n const ua = navigator.userAgent.toLowerCase()\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android.*mobile|windows phone/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\nexport const DIAGNOSTIC_FIELDS = [\n { key: 'screenResolution' as const, labelKey: 'diag.screenResolution' },\n { key: 'deviceType' as const, labelKey: 'diag.deviceType' },\n { key: 'timezone' as const, labelKey: 'diag.timezone' },\n { key: 'referrerUrl' as const, labelKey: 'diag.referrerUrl' },\n { key: 'language' as const, labelKey: 'diag.language' },\n { key: 'platform' as const, labelKey: 'diag.platform' },\n] as const\n","import { useState, useRef, useCallback, type FormEvent, type DragEvent } from 'react'\r\nimport { useMutation, useQuery } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetCategoriesOptions } from '../queries'\r\nimport { submitTicket as apiSubmitTicket, uploadAttachment, type CategoryItem } from '../../api-client'\r\nimport { saveTrackingToken, saveWidgetEmail, loadWidgetEmail } from '../../storage'\r\nimport { collectAllMetadata, getMetadataPreferences, saveMetadataPreferences, collectDiagnosticMetadata, DIAGNOSTIC_FIELDS, type MetadataPreferences } from '../../client-metadata'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\nimport type { TicketResult, WidgetError, SubmitTicketData } from '../types'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\nconst ALLOWED_MIME_TYPES = new Set([\r\n 'image/jpeg', 'image/png', 'image/gif', 'image/webp',\r\n 'application/pdf',\r\n 'text/plain', 'text/csv',\r\n 'application/zip', 'application/x-zip-compressed',\r\n 'application/msword',\r\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n 'application/vnd.ms-excel',\r\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n 'application/vnd.ms-powerpoint',\r\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\r\n])\r\n\r\nconst BLOCKED_EXTENSIONS = new Set(['.exe', '.bat', '.cmd', '.sh', '.ps1', '.msi', '.dll', '.scr'])\r\nconst MAX_FILES = 5\r\nconst MAX_SIZE_MB = 10\r\n\r\ninterface SubmitTicketViewProps {\r\n projectId: string\r\n onSuccess?: (result: TicketResult) => void\r\n onError?: (error: WidgetError) => void\r\n isAuthenticated?: boolean\r\n userEmail?: string\r\n}\r\n\r\ninterface QueuedFile {\r\n file: File\r\n id: string\r\n error?: string\r\n}\r\n\r\ninterface UploadProgress {\r\n fileId: string\r\n fileName: string\r\n percent: number\r\n}\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\r\n}\r\n\r\nexport function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, userEmail }: SubmitTicketViewProps) {\r\n const ctx = useReqdeskContext()\r\n const fileInputRef = useRef<HTMLInputElement>(null)\r\n const savedEmail = loadWidgetEmail(ctx.apiKey)\r\n\r\n const [errors, setErrors] = useState<Record<string, string>>({})\r\n const [files, setFiles] = useState<QueuedFile[]>([])\r\n const [isDragOver, setIsDragOver] = useState(false)\r\n const [uploadProgress, setUploadProgress] = useState<UploadProgress | null>(null)\r\n const [success, setSuccess] = useState<TicketResult | null>(null)\r\n const [rememberEmail, setRememberEmail] = useState(!!savedEmail)\r\n\r\n // Category selector state\r\n const [categoryPath, setCategoryPath] = useState<CategoryItem[]>([])\r\n const [selectedCategory, setSelectedCategory] = useState<CategoryItem | null>(null)\r\n const currentParentId = categoryPath.length > 0 ? categoryPath[categoryPath.length - 1].id : null\r\n const { data: categories = [] } = useQuery(widgetCategoriesOptions(projectId, currentParentId))\r\n\r\n // Diagnostic metadata state\r\n const [diagOpen, setDiagOpen] = useState(false)\r\n const [diagPrefs, setDiagPrefs] = useState<MetadataPreferences>(getMetadataPreferences(ctx.apiKey))\r\n const diagValues = collectDiagnosticMetadata({\r\n screenResolution: true, deviceType: true, timezone: true,\r\n referrerUrl: true, language: true, platform: true,\r\n })\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const submitMutation = useMutation({\r\n mutationFn: async ({ data, validFiles }: { data: SubmitTicketData; validFiles: QueuedFile[] }) => {\r\n const result = await apiSubmitTicket(projectId, data)\r\n if (result.trackingToken) saveTrackingToken(ctx.apiKey, result.trackingToken)\r\n\r\n // Upload attachments sequentially after ticket creation\r\n for (const queued of validFiles) {\r\n setUploadProgress({ fileId: queued.id, fileName: queued.file.name, percent: 0 })\r\n await uploadAttachment(result.id, queued.file, (percent) => {\r\n setUploadProgress({ fileId: queued.id, fileName: queued.file.name, percent })\r\n })\r\n }\r\n setUploadProgress(null)\r\n return result\r\n },\r\n onSuccess: (result) => {\r\n setSuccess(result)\r\n onSuccess?.(result)\r\n },\r\n onError: (err) => {\r\n setUploadProgress(null)\r\n onError?.(err as unknown as WidgetError)\r\n },\r\n })\r\n\r\n function validateFile(file: File): string | null {\r\n const ext = '.' + file.name.split('.').pop()?.toLowerCase()\r\n if (BLOCKED_EXTENSIONS.has(ext)) return t('attach.invalidType')\r\n if (!ALLOWED_MIME_TYPES.has(file.type) && !file.type.startsWith('application/vnd.openxmlformats-officedocument.')) {\r\n return t('attach.invalidType')\r\n }\r\n if (file.size > MAX_SIZE_MB * 1024 * 1024) return t('attach.tooLarge')\r\n return null\r\n }\r\n\r\n function addFiles(newFiles: FileList | File[]) {\r\n const toAdd: QueuedFile[] = []\r\n for (const file of Array.from(newFiles)) {\r\n if (files.length + toAdd.length >= MAX_FILES) break\r\n const error = validateFile(file)\r\n toAdd.push({ file, id: crypto.randomUUID(), error: error ?? undefined })\r\n }\r\n setFiles(prev => [...prev, ...toAdd])\r\n }\r\n\r\n function removeFile(id: string) {\r\n setFiles(prev => prev.filter(f => f.id !== id))\r\n }\r\n\r\n function handleDragOver(e: DragEvent) { e.preventDefault(); setIsDragOver(true) }\r\n function handleDragLeave(e: DragEvent) { e.preventDefault(); setIsDragOver(false) }\r\n function handleDrop(e: DragEvent) {\r\n e.preventDefault(); setIsDragOver(false)\r\n if (e.dataTransfer.files.length > 0) addFiles(e.dataTransfer.files)\r\n }\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n const form = e.currentTarget\r\n const formData = new FormData(form)\r\n\r\n const title = (formData.get('title') as string)?.trim() ?? ''\r\n const email = (formData.get('email') as string)?.trim() ?? userEmail ?? ''\r\n const newErrors: Record<string, string> = {}\r\n\r\n if (!title) newErrors.title = t('error.required')\r\n else if (title.length < 5) newErrors.title = t('error.titleMin')\r\n if (!isAuthenticated && email && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\r\n newErrors.email = t('error.emailInvalid')\r\n }\r\n\r\n if (Object.keys(newErrors).length > 0) { setErrors(newErrors); return }\r\n setErrors({})\r\n\r\n if (rememberEmail && email) saveWidgetEmail(ctx.apiKey, email)\r\n\r\n // Save diagnostic preferences\r\n saveMetadataPreferences(ctx.apiKey, diagPrefs)\r\n\r\n const validFiles = files.filter(f => !f.error)\r\n const data: SubmitTicketData = {\r\n title,\r\n description: (formData.get('description') as string)?.trim() || undefined,\r\n email,\r\n priority: (formData.get('priority') as SubmitTicketData['priority']) ?? 'medium',\r\n categoryId: selectedCategory?.id,\r\n clientMetadata: collectAllMetadata(ctx.apiKey),\r\n }\r\n\r\n submitMutation.mutate({ data, validFiles })\r\n }\r\n\r\n if (success) {\r\n return (\r\n <div className=\"rqd-success\" style={{ textAlign: 'center', padding: '24px 0' }}>\r\n <div style={{ fontSize: 48, marginBottom: 12 }}>{'\\u2705'}</div>\r\n <h3 style={{ margin: '0 0 8px', fontSize: 18 }}>{t('success.title')}</h3>\r\n <p>{t('success.ticketNumber')}{success.ticketNumber}</p>\r\n {success.trackingToken && (\r\n <>\r\n <p style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('success.trackingHint')}</p>\r\n <div className=\"rqd-token-box\">{success.trackingToken}</div>\r\n <button className=\"rqd-btn rqd-btn-secondary\" onClick={() => navigator.clipboard.writeText(success.trackingToken!)}>\r\n {t('success.copyToken')}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n if (submitMutation.isPending && uploadProgress) {\r\n return (\r\n <div style={{ padding: '24px 0', textAlign: 'center' }}>\r\n <p style={{ marginBottom: 12, fontWeight: 500 }}>{t('attach.uploading')}</p>\r\n <div className=\"rqd-file-item\" style={{ marginBottom: 8 }}>\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{uploadProgress.fileName}</span>\r\n </div>\r\n <span style={{ fontSize: 12, color: 'var(--rqd-text-secondary)' }}>{uploadProgress.percent}%</span>\r\n </div>\r\n <div className=\"rqd-progress\">\r\n <div className=\"rqd-progress-bar\" style={{ width: `${uploadProgress.percent}%` }} />\r\n </div>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <form className=\"rqd-form\" onSubmit={handleSubmit} noValidate>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.title')}</label>\r\n <input className=\"rqd-input\" name=\"title\" placeholder={t('form.titlePlaceholder')} required />\r\n {errors.title && <div className=\"rqd-error-text\">{errors.title}</div>}\r\n </div>\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.description')}</label>\r\n <textarea className=\"rqd-textarea\" name=\"description\" placeholder={t('form.descriptionPlaceholder')} />\r\n </div>\r\n {!isAuthenticated && (\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.email')}</label>\r\n <input className=\"rqd-input\" name=\"email\" type=\"email\" placeholder={t('form.emailPlaceholder')} defaultValue={userEmail ?? savedEmail ?? ''} />\r\n {errors.email && <div className=\"rqd-error-text\">{errors.email}</div>}\r\n <label className=\"rqd-checkbox-label\" style={{ marginTop: 6 }}>\r\n <input type=\"checkbox\" checked={rememberEmail} onChange={(e) => setRememberEmail(e.target.checked)} />\r\n {t('mytickets.rememberMe')}\r\n </label>\r\n </div>\r\n )}\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.priority')}</label>\r\n <select className=\"rqd-select\" name=\"priority\" defaultValue=\"medium\">\r\n <option value=\"low\">{t('form.priorityLow')}</option>\r\n <option value=\"medium\">{t('form.priorityMedium')}</option>\r\n <option value=\"high\">{t('form.priorityHigh')}</option>\r\n <option value=\"urgent\">{t('form.priorityUrgent')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Category Selector */}\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.categorySelected')}</label>\r\n {selectedCategory ? (\r\n <div className=\"rqd-category-selected\">\r\n <span>\r\n {categoryPath.map(c => c.name).join(' > ')}{categoryPath.length > 0 ? ' > ' : ''}{selectedCategory.name}\r\n </span>\r\n <button type=\"button\" onClick={() => { setSelectedCategory(null); setCategoryPath([]) }}>×</button>\r\n </div>\r\n ) : (\r\n <>\r\n {categoryPath.length > 0 && (\r\n <div className=\"rqd-category-breadcrumb\">\r\n <button type=\"button\" onClick={() => setCategoryPath([])}>{t('form.categoryPlaceholder')}</button>\r\n {categoryPath.map((c, i) => (\r\n <span key={c.id}>\r\n <span className=\"rqd-category-breadcrumb-sep\">›</span>\r\n <button type=\"button\" onClick={() => setCategoryPath(prev => prev.slice(0, i + 1))}>{c.name}</button>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n <div className=\"rqd-category-list\">\r\n {categories.map(cat => (\r\n <button\r\n key={cat.id}\r\n type=\"button\"\r\n className=\"rqd-category-item\"\r\n onClick={() => {\r\n if (cat.hasChildren) {\r\n setCategoryPath(prev => [...prev, cat])\r\n } else {\r\n setSelectedCategory(cat)\r\n }\r\n }}\r\n >\r\n {cat.name}\r\n {cat.hasChildren && <span className=\"rqd-category-item-chevron\">›</span>}\r\n </button>\r\n ))}\r\n {categories.length === 0 && categoryPath.length === 0 && (\r\n <span style={{ fontSize: 13, color: 'var(--rqd-text-secondary)' }}>{t('form.categoryPlaceholder')}</span>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Diagnostic Metadata */}\r\n <div className=\"rqd-form-group\">\r\n <button\r\n type=\"button\"\r\n className=\"rqd-diag-toggle\"\r\n onClick={() => setDiagOpen(prev => !prev)}\r\n >\r\n <span>{t('diag.title')}</span>\r\n <span>{diagOpen ? '\\u25B2' : '\\u25BC'}</span>\r\n </button>\r\n {diagOpen && (\r\n <div className=\"rqd-diag-panel\">\r\n <p style={{ fontSize: 12, color: 'var(--rqd-text-secondary)', margin: '0 0 6px' }}>{t('diag.hint')}</p>\r\n {DIAGNOSTIC_FIELDS.map(field => (\r\n <label key={field.key} className=\"rqd-diag-item\">\r\n <input\r\n type=\"checkbox\"\r\n checked={diagPrefs[field.key]}\r\n onChange={(e) => setDiagPrefs(prev => ({ ...prev, [field.key]: e.target.checked }))}\r\n />\r\n <span>{t(field.labelKey)}</span>\r\n <span className=\"rqd-diag-item-value\">{diagValues[field.key] ?? '—'}</span>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"rqd-form-group\">\r\n <label className=\"rqd-label\">{t('form.attachment')}</label>\r\n <div\r\n className={`rqd-dropzone${isDragOver ? ' rqd-dropzone-active' : ''}`}\r\n onDragOver={handleDragOver} onDragLeave={handleDragLeave} onDrop={handleDrop}\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n {isDragOver ? t('attach.dropzoneActive') : t('attach.dropzone')}\r\n <input ref={fileInputRef} type=\"file\" multiple style={{ display: 'none' }}\r\n onChange={(e) => { if (e.target.files) addFiles(e.target.files); e.target.value = '' }} />\r\n </div>\r\n {files.length > 0 && (\r\n <div className=\"rqd-file-list\">\r\n {files.map(f => (\r\n <div key={f.id} className=\"rqd-file-item\">\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{f.file.name}</span>\r\n <span className=\"rqd-file-item-size\">\r\n {formatFileSize(f.file.size)}\r\n {f.error && <span style={{ color: '#e74c3c', marginLeft: 6 }}>{f.error}</span>}\r\n </span>\r\n </div>\r\n <button className=\"rqd-file-remove\" onClick={() => removeFile(f.id)} type=\"button\">×</button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={submitMutation.isPending}>\r\n {submitMutation.isPending ? t('form.submitting') : t('form.submit')}\r\n </button>\r\n </form>\r\n )\r\n}\r\n","import { useState, useEffect, useCallback, type FormEvent } from 'react'\r\nimport { useQuery } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetMyTicketsOptions, widgetUserOptions } from '../queries'\r\nimport { trackTicket, type TicketListItem } from '../../api-client'\r\nimport { saveWidgetEmail, loadWidgetEmail, getTrackingTokens } from '../../storage'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface MyTicketsViewProps {\r\n projectId: string\r\n onSelectTicket: (ticketId: string) => void\r\n isAuthenticated?: boolean\r\n userEmail?: string\r\n}\r\n\r\nexport function MyTicketsView({ projectId, onSelectTicket, isAuthenticated, userEmail }: MyTicketsViewProps) {\r\n const ctx = useReqdeskContext()\r\n const savedEmail = loadWidgetEmail(ctx.apiKey)\r\n\r\n const [email, setEmail] = useState(userEmail ?? savedEmail ?? '')\r\n const [rememberMe, setRememberMe] = useState(!!savedEmail)\r\n const [submittedEmail, setSubmittedEmail] = useState<string | null>(\r\n isAuthenticated && userEmail ? userEmail : savedEmail,\r\n )\r\n const [tokenTickets, setTokenTickets] = useState<TicketListItem[]>([])\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n // Resolve email → userId\r\n const { data: widgetUser } = useQuery(widgetUserOptions(projectId, submittedEmail ?? ''))\r\n const userId = widgetUser?.userId ?? ''\r\n\r\n // Fetch tickets once userId is resolved\r\n const { data: emailTickets = [], isLoading } = useQuery(widgetMyTicketsOptions(projectId, userId))\r\n\r\n // Also load token-based tickets\r\n useEffect(() => {\r\n const tokens = getTrackingTokens(ctx.apiKey)\r\n if (tokens.length === 0) return\r\n\r\n Promise.allSettled(\r\n tokens.slice(0, 5).map(tk => trackTicket(tk)),\r\n ).then(results => {\r\n const tracked: TicketListItem[] = []\r\n for (const r of results) {\r\n if (r.status === 'fulfilled') {\r\n const t = r.value\r\n if (!emailTickets.some(et => et.id === t.id)) {\r\n tracked.push({\r\n id: t.id,\r\n ticketNumber: t.ticketNumber,\r\n title: t.title,\r\n status: t.status,\r\n priority: t.priority,\r\n createdAt: t.createdAt,\r\n })\r\n }\r\n }\r\n }\r\n setTokenTickets(tracked)\r\n })\r\n }, [ctx.apiKey, emailTickets])\r\n\r\n const allTickets = [...emailTickets, ...tokenTickets]\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n const trimmed = email.trim()\r\n if (!trimmed || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return\r\n\r\n if (rememberMe) saveWidgetEmail(ctx.apiKey, trimmed)\r\n setSubmittedEmail(trimmed)\r\n }\r\n\r\n function formatDate(iso: string): string {\r\n try { return new Date(iso).toLocaleDateString() } catch { return iso }\r\n }\r\n\r\n // Show email entry form if not yet submitted and not authenticated\r\n if (!submittedEmail && !isAuthenticated) {\r\n return (\r\n <div className=\"rqd-email-form\">\r\n <p>{t('mytickets.emailPrompt')}</p>\r\n <form onSubmit={handleSubmit}>\r\n <div className=\"rqd-form-group\">\r\n <input\r\n className=\"rqd-input\"\r\n type=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n placeholder={t('mytickets.emailPlaceholder')}\r\n required\r\n />\r\n </div>\r\n <label className=\"rqd-checkbox-label\">\r\n <input\r\n type=\"checkbox\"\r\n checked={rememberMe}\r\n onChange={(e) => setRememberMe(e.target.checked)}\r\n />\r\n {t('mytickets.rememberMe')}\r\n </label>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" style={{ marginTop: 12 }}>\r\n {t('mytickets.lookup')}\r\n </button>\r\n </form>\r\n </div>\r\n )\r\n }\r\n\r\n if (isLoading) {\r\n return <div className=\"rqd-loading\">{t('mytickets.lookingUp')}</div>\r\n }\r\n\r\n if (allTickets.length === 0) {\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <p>{submittedEmail && !widgetUser ? t('mytickets.noAccount') : t('mytickets.noTickets')}</p>\r\n {submittedEmail && !isAuthenticated && (\r\n <button className=\"rqd-btn rqd-btn-secondary\" style={{ width: 'auto', padding: '8px 20px' }} onClick={() => setSubmittedEmail(null)}>\r\n {t('tracker.back')}\r\n </button>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div className=\"rqd-ticket-list\">\r\n {allTickets.map(ticket => (\r\n <div\r\n key={ticket.id}\r\n className=\"rqd-ticket-card\"\r\n onClick={() => onSelectTicket(ticket.id)}\r\n >\r\n <div className=\"rqd-ticket-card-top\">\r\n <span className=\"rqd-ticket-card-number\">{ticket.ticketNumber}</span>\r\n <span className=\"rqd-badge\">{ticket.status}</span>\r\n </div>\r\n <span className=\"rqd-ticket-card-title\">{ticket.title}</span>\r\n <span className=\"rqd-ticket-card-date\">{formatDate(ticket.createdAt)}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { widgetTicketDetailOptions } from '../queries'\r\nimport { submitReply, closeTicket, type AttachmentMeta, type TicketDetail } from '../../api-client'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface TicketDetailViewProps {\r\n ticketId: string\r\n onBack: () => void\r\n}\r\n\r\nfunction formatDate(iso: string): string {\r\n try { return new Date(iso).toLocaleString() } catch { return iso }\r\n}\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\r\n}\r\n\r\nexport function TicketDetailView({ ticketId, onBack }: TicketDetailViewProps) {\r\n const ctx = useReqdeskContext()\r\n const queryClient = useQueryClient()\r\n const [replyBody, setReplyBody] = useState('')\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const { data: ticket, isLoading, error } = useQuery(widgetTicketDetailOptions(ticketId))\r\n\r\n const replyMutation = useMutation({\r\n mutationFn: (body: string) => submitReply(ticketId, body),\r\n onMutate: async (body) => {\r\n // Optimistic update: append reply to cache\r\n await queryClient.cancelQueries({ queryKey: ['widget-ticket', ticketId] })\r\n const previous = queryClient.getQueryData<TicketDetail>(['widget-ticket', ticketId])\r\n\r\n if (previous) {\r\n queryClient.setQueryData<TicketDetail>(['widget-ticket', ticketId], {\r\n ...previous,\r\n replies: [...previous.replies, {\r\n id: `optimistic-${Date.now()}`,\r\n body,\r\n authorName: ctx.userName ?? ctx.userEmail ?? 'You',\r\n isStaff: false,\r\n createdAt: new Date().toISOString(),\r\n }],\r\n })\r\n }\r\n return { previous }\r\n },\r\n onSuccess: () => {\r\n setReplyBody('')\r\n queryClient.invalidateQueries({ queryKey: ['widget-ticket', ticketId] })\r\n },\r\n onError: (_err, _vars, context) => {\r\n if (context?.previous) {\r\n queryClient.setQueryData(['widget-ticket', ticketId], context.previous)\r\n }\r\n },\r\n })\r\n\r\n const resolveMutation = useMutation({\r\n mutationFn: () => closeTicket(ticketId),\r\n onMutate: async () => {\r\n await queryClient.cancelQueries({ queryKey: ['widget-ticket', ticketId] })\r\n const previous = queryClient.getQueryData<TicketDetail>(['widget-ticket', ticketId])\r\n if (previous) {\r\n queryClient.setQueryData<TicketDetail>(['widget-ticket', ticketId], {\r\n ...previous,\r\n status: 'resolved',\r\n })\r\n }\r\n return { previous }\r\n },\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: ['widget-ticket', ticketId] })\r\n },\r\n onError: (_err, _vars, context) => {\r\n if (context?.previous) {\r\n queryClient.setQueryData(['widget-ticket', ticketId], context.previous)\r\n }\r\n },\r\n })\r\n\r\n if (isLoading) {\r\n return <div className=\"rqd-loading\">{t('detail.loading')}</div>\r\n }\r\n\r\n if (error || !ticket) {\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <p>{t('error.generic')}</p>\r\n <button className=\"rqd-btn rqd-btn-secondary\" style={{ width: 'auto', padding: '8px 20px' }} onClick={onBack}>\r\n {t('tracker.back')}\r\n </button>\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div>\r\n <div className=\"rqd-ticket-header\">\r\n <h3>{ticket.title}</h3>\r\n <div className=\"rqd-ticket-header-meta\">\r\n <span className=\"rqd-ticket-card-number\">{ticket.ticketNumber}</span>\r\n <span className=\"rqd-badge\">{ticket.status}</span>\r\n <span className=\"rqd-badge\" style={{ background: 'var(--rqd-bg-secondary)', color: 'var(--rqd-text-secondary)' }}>\r\n {ticket.priority}\r\n </span>\r\n <span className=\"rqd-ticket-card-date\">{formatDate(ticket.createdAt)}</span>\r\n </div>\r\n </div>\r\n\r\n {ticket.description && (\r\n <>\r\n <div className=\"rqd-section-title\">{t('detail.description')}</div>\r\n <div className=\"rqd-ticket-desc\">{ticket.description}</div>\r\n </>\r\n )}\r\n\r\n {ticket.attachments.length > 0 && (\r\n <>\r\n <div className=\"rqd-section-title\">{t('detail.attachments')}</div>\r\n <div className=\"rqd-attachment-list\">\r\n {ticket.attachments.map((a: AttachmentMeta) => (\r\n <div key={a.id} className=\"rqd-attachment-item\">\r\n <div className=\"rqd-file-item-info\">\r\n <span className=\"rqd-file-item-name\">{a.fileName}</span>\r\n <span className=\"rqd-file-item-size\">{formatFileSize(a.fileSize)}</span>\r\n </div>\r\n {a.downloadUrl && (\r\n <a href={a.downloadUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n {t('attach.download')}\r\n </a>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n <div className=\"rqd-section-title\">{t('detail.replies')}</div>\r\n {ticket.replies.length === 0 ? (\r\n <p style={{ color: 'var(--rqd-text-secondary)', fontSize: 13, margin: '0 0 12px' }}>\r\n {t('detail.noReplies')}\r\n </p>\r\n ) : (\r\n <div>\r\n {ticket.replies.map(reply => (\r\n <div key={reply.id} className=\"rqd-reply\">\r\n <div className=\"rqd-reply-header\">\r\n <span className={reply.isStaff ? 'rqd-reply-staff' : ''}>\r\n {reply.isStaff ? `${reply.authorName} \\u00b7 ${t('detail.staff')}` : reply.authorName}\r\n </span>\r\n <span>{formatDate(reply.createdAt)}</span>\r\n </div>\r\n <div className=\"rqd-reply-body\">{reply.body}</div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"rqd-reply-compose\">\r\n <textarea\r\n className=\"rqd-textarea\"\r\n value={replyBody}\r\n onChange={(e) => setReplyBody(e.target.value)}\r\n placeholder={t('detail.replyPlaceholder')}\r\n rows={3}\r\n />\r\n <div style={{ display: 'flex', gap: 8 }}>\r\n <button\r\n className=\"rqd-btn rqd-btn-primary\"\r\n style={{ flex: 1 }}\r\n onClick={() => replyMutation.mutate(replyBody.trim())}\r\n disabled={!replyBody.trim() || replyMutation.isPending}\r\n >\r\n {replyMutation.isPending ? t('detail.sending') : t('detail.sendReply')}\r\n </button>\r\n {ticket.status !== 'resolved' && ticket.status !== 'closed' && (\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n style={{ flex: 0, whiteSpace: 'nowrap', padding: '10px 16px' }}\r\n onClick={() => resolveMutation.mutate()}\r\n disabled={resolveMutation.isPending}\r\n >\r\n {resolveMutation.isPending ? t('detail.resolving') : t('detail.resolve')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback, type FormEvent } from 'react'\r\nimport { useMutation } from '@tanstack/react-query'\r\nimport { useReqdeskContext } from '../ReqdeskProvider'\r\nimport { trackTicket } from '../../api-client'\r\nimport { getTrackingTokens } from '../../storage'\r\nimport { en } from '../../i18n/en'\r\nimport { ar } from '../../i18n/ar'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ninterface TrackTicketViewProps {\r\n onTrackSuccess: (ticketId: string) => void\r\n}\r\n\r\nexport function TrackTicketView({ onTrackSuccess }: TrackTicketViewProps) {\r\n const ctx = useReqdeskContext()\r\n const [token, setToken] = useState('')\r\n const savedTokens = getTrackingTokens(ctx.apiKey)\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[ctx.language] ?? translations.en\r\n return lang[key] ?? key\r\n }, [ctx.language, ctx.translations])\r\n\r\n const trackMutation = useMutation({\r\n mutationFn: (trackToken: string) => trackTicket(trackToken.trim()),\r\n onSuccess: (result) => onTrackSuccess(result.id),\r\n })\r\n\r\n function handleSubmit(e: FormEvent<HTMLFormElement>) {\r\n e.preventDefault()\r\n if (token.trim()) trackMutation.mutate(token)\r\n }\r\n\r\n return (\r\n <div>\r\n <form onSubmit={handleSubmit}>\r\n <div className=\"rqd-form-group\">\r\n <input\r\n className=\"rqd-input\"\r\n value={token}\r\n onChange={(e) => setToken(e.target.value)}\r\n placeholder={t('track.tokenPlaceholder')}\r\n required\r\n />\r\n {trackMutation.isError && <div className=\"rqd-error-text\">{t('track.invalidToken')}</div>}\r\n </div>\r\n <button className=\"rqd-btn rqd-btn-primary\" type=\"submit\" disabled={trackMutation.isPending || !token.trim()}>\r\n {trackMutation.isPending ? t('track.tracking') : t('track.submit')}\r\n </button>\r\n </form>\r\n\r\n {savedTokens.length > 0 && (\r\n <div style={{ marginTop: 20 }}>\r\n <div className=\"rqd-section-title\">{t('track.recentTickets')}</div>\r\n <div className=\"rqd-ticket-list\">\r\n {savedTokens.slice(0, 5).map(tk => (\r\n <button\r\n key={tk}\r\n className=\"rqd-ticket-card\"\r\n style={{ border: 'none', textAlign: 'start', width: '100%' }}\r\n onClick={() => trackMutation.mutate(tk)}\r\n >\r\n <span className=\"rqd-ticket-card-number\" style={{ fontFamily: 'monospace', fontSize: 12 }}>\r\n {tk.slice(0, 20)}...\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useState, useCallback } from 'react'\r\nimport { useReqdeskContext } from './ReqdeskProvider'\r\nimport { en } from '../i18n/en'\r\nimport { ar } from '../i18n/ar'\r\nimport { themeToStyle } from '../theme'\r\nimport { saveWidgetConfig, loadWidgetConfig, loadWidgetEmail, clearWidgetEmail } from '../storage'\r\nimport { login, logout, isAuthConfigured } from '../auth/widget-auth'\r\nimport { ShadowRoot } from './shadow-root'\r\nimport { SubmitTicketView } from './views/SubmitTicketView'\r\nimport { MyTicketsView } from './views/MyTicketsView'\r\nimport { TicketDetailView } from './views/TicketDetailView'\r\nimport { TrackTicketView } from './views/TrackTicketView'\r\nimport type { TicketResult, WidgetError } from './types'\r\n\r\nconst translations: Record<string, Record<string, string>> = { en, ar }\r\n\r\ntype WidgetView = 'home' | 'new-ticket' | 'my-tickets' | 'ticket-detail' | 'track' | 'kb' | 'preferences'\r\n\r\ninterface FloatingWidgetProps {\r\n position?: 'bottom-right' | 'bottom-left'\r\n contained?: boolean\r\n onTicketCreated?: (ticket: TicketResult) => void\r\n onError?: (error: WidgetError) => void\r\n}\r\n\r\nconst ICONS = {\r\n chat: 'M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z',\r\n close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',\r\n newTicket: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z',\r\n tickets: 'M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zM8 15.01l1.41 1.41L11 14.84V19h2v-4.16l1.59 1.59L16 15.01 12.01 11z',\r\n track: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',\r\n kb: 'M21 5c-1.11-.35-2.33-.5-3.5-.5-1.95 0-4.05.4-5.5 1.5-1.45-1.1-3.55-1.5-5.5-1.5S2.45 4.9 1 6v14.65c0 .25.25.5.5.5.1 0 .15-.05.25-.05C3.1 20.45 5.05 20 6.5 20c1.95 0 4.05.4 5.5 1.5 1.35-.85 3.8-1.5 5.5-1.5 1.65 0 3.35.3 4.75 1.05.1.05.15.05.25.05.25 0 .5-.25.5-.5V6c-.6-.45-1.25-.75-2-1zm0 13.5c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5V8c1.35-.85 3.8-1.5 5.5-1.5 1.2 0 2.4.15 3.5.5v11.5z',\r\n back: 'M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z',\r\n backRtl: 'M4 11h12.17l-5.59-5.59L12 4l8 8-8 8-1.41-1.41L16.17 13H4v-2z',\r\n settings: 'M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 00-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.49.49 0 00-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6A3.6 3.6 0 1115.6 12 3.6 3.6 0 0112 15.6z',\r\n}\r\n\r\nfunction SvgIcon({ path, size = 20 }: { path: string; size?: number }) {\r\n return (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\" style={{ display: 'block', flexShrink: 0 }}>\r\n <path d={path} />\r\n </svg>\r\n )\r\n}\r\n\r\nexport function FloatingWidget({\r\n position = 'bottom-right',\r\n contained = false,\r\n onTicketCreated,\r\n onError,\r\n}: FloatingWidgetProps) {\r\n const ctx = useReqdeskContext()\r\n const [isOpen, setIsOpen] = useState(false)\r\n const [view, setView] = useState<WidgetView>('home')\r\n const [selectedTicketId, setSelectedTicketId] = useState<string | null>(null)\r\n const [emailCleared, setEmailCleared] = useState(false)\r\n\r\n const savedPrefs = loadWidgetConfig(ctx.apiKey)\r\n const [userLang, setUserLang] = useState<string | null>(savedPrefs?.language ?? null)\r\n const [userThemeMode, setUserThemeMode] = useState<string | null>(savedPrefs?.theme?.mode ?? null)\r\n const [userColor, setUserColor] = useState<string | null>(savedPrefs?.theme?.primaryColor ?? null)\r\n\r\n const activeLang = userLang ?? ctx.language ?? 'en'\r\n const activeThemeMode = (userThemeMode ?? ctx.theme?.mode ?? 'auto') as 'light' | 'dark' | 'auto'\r\n const activeColor = userColor ?? ctx.theme?.primaryColor ?? '#42b983'\r\n const activeTheme = { ...ctx.theme, mode: activeThemeMode, primaryColor: activeColor }\r\n\r\n const t = useCallback((key: string): string => {\r\n if (ctx.translations?.[key]) return ctx.translations[key]\r\n const lang = translations[activeLang] ?? translations.en\r\n return lang[key] ?? key\r\n }, [activeLang, ctx.translations])\r\n\r\n const isRtl = activeLang === 'ar'\r\n const cssVars = themeToStyle(activeTheme)\r\n const posClass = `rqd-${position}`\r\n const containedClass = contained ? ' rqd-contained' : ''\r\n const brandName = ctx.theme?.brandName\r\n const brandLogo = ctx.theme?.logo\r\n const hideBranding = ctx.theme?.hideBranding === true\r\n\r\n // Derive projectId from API key context (resolved server-side)\r\n const projectId = '_current'\r\n\r\n function toggleOpen() {\r\n setIsOpen(prev => !prev)\r\n if (!isOpen) {\r\n setView('home')\r\n setSelectedTicketId(null)\r\n }\r\n }\r\n\r\n function goHome() {\r\n setView('home')\r\n setSelectedTicketId(null)\r\n setEmailCleared(false)\r\n }\r\n\r\n function handleLangChange(lang: string) {\r\n setUserLang(lang)\r\n saveWidgetConfig(ctx.apiKey, { language: lang })\r\n }\r\n\r\n function handleThemeChange(mode: string) {\r\n setUserThemeMode(mode)\r\n saveWidgetConfig(ctx.apiKey, { theme: { ...ctx.theme, mode: mode as 'light' | 'dark' | 'auto', primaryColor: activeColor } })\r\n }\r\n\r\n function handleColorChange(color: string) {\r\n setUserColor(color)\r\n saveWidgetConfig(ctx.apiKey, { theme: { ...ctx.theme, mode: activeThemeMode, primaryColor: color } })\r\n }\r\n\r\n const COLOR_PRESETS = [\r\n { color: '#42b983', label: 'Green' },\r\n { color: '#3b82f6', label: 'Blue' },\r\n { color: '#8b5cf6', label: 'Purple' },\r\n { color: '#f59e0b', label: 'Orange' },\r\n { color: '#ef4444', label: 'Red' },\r\n ]\r\n\r\n function handleClearEmail() {\r\n clearWidgetEmail(ctx.apiKey)\r\n setEmailCleared(true)\r\n setTimeout(() => setEmailCleared(false), 2000)\r\n }\r\n\r\n function openTicketDetail(ticketId: string) {\r\n setSelectedTicketId(ticketId)\r\n setView('ticket-detail')\r\n }\r\n\r\n const menuItems = [\r\n { key: 'new-ticket' as const, icon: ICONS.newTicket, label: t('menu.newTicket'), desc: t('menu.newTicketDesc') },\r\n { key: 'my-tickets' as const, icon: ICONS.tickets, label: t('menu.myTickets'), desc: t('menu.myTicketsDesc') },\r\n { key: 'track' as const, icon: ICONS.track, label: t('menu.trackTicket'), desc: t('menu.trackTicketDesc') },\r\n { key: 'kb' as const, icon: ICONS.kb, label: t('menu.knowledgeBase'), desc: t('menu.knowledgeBaseDesc') },\r\n { key: 'preferences' as const, icon: ICONS.settings, label: t('menu.preferences'), desc: t('menu.preferencesDesc') },\r\n ]\r\n\r\n function renderViewContent() {\r\n switch (view) {\r\n case 'home':\r\n return (\r\n <div className=\"rqd-menu\">\r\n {menuItems.map(item => (\r\n <button\r\n key={item.key}\r\n className=\"rqd-menu-item\"\r\n onClick={() => setView(item.key)}\r\n >\r\n <div className=\"rqd-menu-icon\">\r\n <SvgIcon path={item.icon} size={22} />\r\n </div>\r\n <div className=\"rqd-menu-text\">\r\n <span className=\"rqd-menu-label\">{item.label}</span>\r\n <span className=\"rqd-menu-desc\">{item.desc}</span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n )\r\n\r\n case 'new-ticket':\r\n return (\r\n <SubmitTicketView\r\n projectId={projectId}\r\n onSuccess={(result) => {\r\n onTicketCreated?.(result)\r\n }}\r\n onError={onError}\r\n isAuthenticated={ctx.isAuthenticated}\r\n userEmail={ctx.userEmail}\r\n />\r\n )\r\n\r\n case 'my-tickets':\r\n return (\r\n <MyTicketsView\r\n projectId={projectId}\r\n onSelectTicket={openTicketDetail}\r\n isAuthenticated={ctx.isAuthenticated}\r\n userEmail={ctx.userEmail}\r\n />\r\n )\r\n\r\n case 'ticket-detail':\r\n if (!selectedTicketId) return null\r\n return (\r\n <TicketDetailView\r\n ticketId={selectedTicketId}\r\n onBack={() => setView('my-tickets')}\r\n />\r\n )\r\n\r\n case 'track':\r\n return (\r\n <TrackTicketView\r\n onTrackSuccess={openTicketDetail}\r\n />\r\n )\r\n\r\n case 'kb':\r\n return (\r\n <div className=\"rqd-placeholder\">\r\n <SvgIcon path={ICONS.kb} size={40} />\r\n <p>{t('menu.kbPlaceholder')}</p>\r\n </div>\r\n )\r\n\r\n case 'preferences':\r\n return (\r\n <div className=\"rqd-prefs\">\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.language')}</span>\r\n <div className=\"rqd-prefs-options\">\r\n <button\r\n className={`rqd-prefs-option${activeLang === 'en' ? ' rqd-active' : ''}`}\r\n onClick={() => handleLangChange('en')}\r\n >\r\n English\r\n </button>\r\n <button\r\n className={`rqd-prefs-option${activeLang === 'ar' ? ' rqd-active' : ''}`}\r\n onClick={() => handleLangChange('ar')}\r\n >\r\n العربية\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.theme')}</span>\r\n <div className=\"rqd-prefs-options\">\r\n {(['light', 'dark', 'auto'] as const).map(mode => (\r\n <button\r\n key={mode}\r\n className={`rqd-prefs-option${activeThemeMode === mode ? ' rqd-active' : ''}`}\r\n onClick={() => handleThemeChange(mode)}\r\n >\r\n {t(`prefs.${mode}`)}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Accent Color */}\r\n <div className=\"rqd-prefs-group\">\r\n <span className=\"rqd-prefs-label\">{t('prefs.accentColor')}</span>\r\n <div className=\"rqd-color-presets\">\r\n {COLOR_PRESETS.map(preset => (\r\n <button\r\n key={preset.color}\r\n className={`rqd-color-preset${activeColor === preset.color ? ' rqd-active' : ''}`}\r\n style={{ background: preset.color, color: preset.color }}\r\n onClick={() => handleColorChange(preset.color)}\r\n aria-label={preset.label}\r\n title={preset.label}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Clear saved email */}\r\n {loadWidgetEmail(ctx.apiKey) && (\r\n <div className=\"rqd-prefs-group\">\r\n <button\r\n className=\"rqd-btn rqd-btn-secondary\"\r\n onClick={handleClearEmail}\r\n style={{ width: 'auto', padding: '8px 16px' }}\r\n >\r\n {emailCleared ? t('prefs.emailCleared') : t('prefs.clearEmail')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n }\r\n }\r\n\r\n const viewTitle: Record<WidgetView, string> = {\r\n home: brandName ?? t('widget.title'),\r\n 'new-ticket': t('widget.newTicket'),\r\n 'my-tickets': t('menu.myTickets'),\r\n 'ticket-detail': t('menu.myTickets'),\r\n track: t('widget.trackTicket'),\r\n kb: t('menu.knowledgeBase'),\r\n preferences: t('prefs.title'),\r\n }\r\n\r\n const canGoBack = view !== 'home'\r\n const goBackTarget = view === 'ticket-detail' ? 'my-tickets' : 'home'\r\n\r\n return (\r\n <ShadowRoot>\r\n <div\r\n style={cssVars as React.CSSProperties}\r\n {...(isRtl ? { dir: 'rtl' } : {})}\r\n >\r\n <button\r\n className={`rqd-fab ${posClass}${containedClass}`}\r\n onClick={toggleOpen}\r\n aria-label={isOpen ? t('widget.close') : t('widget.title')}\r\n >\r\n <SvgIcon path={isOpen ? ICONS.close : ICONS.chat} size={24} />\r\n </button>\r\n\r\n <div className={`rqd-panel ${posClass}${containedClass}${isOpen ? '' : ' rqd-hidden'}`}>\r\n <div className=\"rqd-header\">\r\n <div className=\"rqd-header-brand\">\r\n {canGoBack && (\r\n <button\r\n className=\"rqd-header-close\"\r\n onClick={() => goBackTarget === 'home' ? goHome() : setView(goBackTarget as WidgetView)}\r\n aria-label={t('tracker.back')}\r\n >\r\n <SvgIcon path={isRtl ? ICONS.backRtl : ICONS.back} size={18} />\r\n </button>\r\n )}\r\n {view === 'home' && brandLogo && (\r\n <img src={brandLogo} alt=\"\" className=\"rqd-header-logo\" />\r\n )}\r\n <span className=\"rqd-header-title\">{viewTitle[view]}</span>\r\n </div>\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\r\n {(ctx.auth || isAuthConfigured()) && view === 'home' && (\r\n <button\r\n className=\"rqd-auth-btn\"\r\n onClick={() => ctx.isAuthenticated ? logout() : login()}\r\n aria-label={ctx.isAuthenticated ? t('auth.logout') : t('auth.login')}\r\n >\r\n {ctx.isAuthenticated ? ctx.userName ?? t('auth.logout') : t('auth.login')}\r\n </button>\r\n )}\r\n <button\r\n className=\"rqd-header-close\"\r\n onClick={toggleOpen}\r\n aria-label={t('widget.close')}\r\n >\r\n <SvgIcon path={ICONS.close} size={18} />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"rqd-body\">\r\n {renderViewContent()}\r\n </div>\r\n\r\n {!hideBranding && (\r\n <div className=\"rqd-footer\">\r\n <span>{t('branding.poweredBy')}</span>\r\n <a href=\"https://reqdesk.com\" target=\"_blank\" rel=\"noopener noreferrer\">Reqdesk</a>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </ShadowRoot>\r\n )\r\n}\r\n"],"mappings":"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"}
|
|
@@ -484,7 +484,7 @@ const ar = {
|
|
|
484
484
|
//#region src/theme.ts
|
|
485
485
|
const DEFAULT_THEME = {
|
|
486
486
|
primaryColor: "#42b983",
|
|
487
|
-
mode: "
|
|
487
|
+
mode: "auto",
|
|
488
488
|
borderRadius: "8px",
|
|
489
489
|
fontFamily: "inherit",
|
|
490
490
|
zIndex: 9999
|
|
@@ -816,4 +816,4 @@ function loadWidgetConfig(apiKey) {
|
|
|
816
816
|
//#endregion
|
|
817
817
|
export { configureWidgetClient as C, uploadAttachment as S, resolveWidgetUser as _, saveTrackingToken as a, submitTrackingReply as b, getWidgetStyles as c, ar as d, en as f, listMyTickets as g, getTicketDetail as h, loadWidgetEmail as i, themeToStyle as l, getCategories as m, getTrackingTokens as n, saveWidgetConfig as o, closeTicket as p, loadWidgetConfig as r, saveWidgetEmail as s, clearWidgetEmail as t, themeToVars as u, submitReply as v, setOidcTokenProvider as w, trackTicket as x, submitTicket as y };
|
|
818
818
|
|
|
819
|
-
//# sourceMappingURL=storage-
|
|
819
|
+
//# sourceMappingURL=storage-0JN8SJi5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-0JN8SJi5.js","names":[],"sources":["../src/ofetch-client.ts","../src/api-client.ts","../src/i18n/en.ts","../src/i18n/ar.ts","../src/theme.ts","../src/storage.ts"],"sourcesContent":["import { ofetch } from 'ofetch'\r\nimport type { WidgetError } from './types'\r\n\r\nlet apiKey = ''\r\nlet baseUrl = ''\r\nlet oidcTokenProvider: (() => Promise<{ accessToken: string }>) | null = null\r\n\r\nexport function configureWidgetClient(url: string, key: string) {\r\n baseUrl = url.replace(/\\/$/, '')\r\n apiKey = key\r\n}\r\n\r\nexport function setOidcTokenProvider(provider: (() => Promise<{ accessToken: string }>) | null) {\r\n oidcTokenProvider = provider\r\n}\r\n\r\nexport const widgetFetch = ofetch.create({\r\n timeout: 15000,\r\n retry: 2,\r\n retryStatusCodes: [408, 429, 500, 502, 503, 504],\r\n\r\n async onRequest({ options }) {\r\n options.baseURL = `${baseUrl}/api/v1`\r\n const headers = new Headers(options.headers as HeadersInit)\r\n headers.set('X-API-Key', apiKey)\r\n\r\n // Get fresh token on every request — oidc-spa handles refresh internally\r\n if (oidcTokenProvider) {\r\n try {\r\n const tokens = await oidcTokenProvider()\r\n headers.set('Authorization', `Bearer ${tokens.accessToken}`)\r\n } catch {\r\n // Auth unavailable — continue with API key only\r\n }\r\n }\r\n\r\n options.headers = headers\r\n },\r\n\r\n onResponseError({ response }) {\r\n const body = response._data as Record<string, unknown> | undefined\r\n const error: WidgetError = {\r\n code: (body?.responseCode as string) ?? `HTTP_${response.status}`,\r\n message: (body?.responseMessage as string) ?? response.statusText,\r\n }\r\n throw error\r\n },\r\n})\r\n\r\n// Upload helper using XHR for progress tracking (ofetch doesn't support upload progress)\r\nexport function uploadWithProgress(\r\n path: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<unknown> {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest()\r\n xhr.open('POST', `${baseUrl}${path}`)\r\n xhr.setRequestHeader('X-API-Key', apiKey)\r\n\r\n // For uploads, use cached token (can't await in XHR setup)\r\n // The token was set on the last ofetch request via the interceptor\r\n if (oidcTokenProvider) {\r\n oidcTokenProvider()\r\n .then(tokens => {\r\n xhr.setRequestHeader('Authorization', `Bearer ${tokens.accessToken}`)\r\n sendXhr()\r\n })\r\n .catch(() => sendXhr())\r\n } else {\r\n sendXhr()\r\n }\r\n\r\n function sendXhr() {\r\n if (onProgress) {\r\n xhr.upload.addEventListener('progress', (e) => {\r\n if (e.lengthComputable) onProgress(Math.round((e.loaded / e.total) * 100))\r\n })\r\n }\r\n\r\n xhr.addEventListener('load', () => {\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n try { resolve(JSON.parse(xhr.responseText)) } catch { resolve({}) }\r\n } else {\r\n reject({ code: `HTTP_${xhr.status}`, message: xhr.statusText } as WidgetError)\r\n }\r\n })\r\n\r\n xhr.addEventListener('error', () => {\r\n reject({ code: 'NETWORK_ERROR', message: 'Network error during upload' } as WidgetError)\r\n })\r\n\r\n const form = new FormData()\r\n form.append('file', file)\r\n xhr.send(form)\r\n }\r\n })\r\n}\r\n","import { widgetFetch, uploadWithProgress, configureWidgetClient, setOidcTokenProvider } from './ofetch-client'\r\nimport type { SubmitTicketData, TicketResult, TrackedTicketResult, PublicReply } from './types'\r\n\r\n// Re-export client configuration\r\nexport { configureWidgetClient as configureClient, setOidcTokenProvider }\r\n\r\n// Legacy compat — setBearerToken is no longer needed (ofetch interceptor handles it)\r\nexport function setBearerToken(_token: string | null) {\r\n // No-op: token is now fetched per-request via oidcTokenProvider\r\n}\r\n\r\nfunction generateIdempotencyKey(): string {\r\n return crypto.randomUUID()\r\n}\r\n\r\n// ── JSON:API response shape ──────────────────────────────────────────────────\r\n\r\ninterface ApiResponse<T> {\r\n responseCode: string\r\n responseMessage: string\r\n httpCode: number\r\n data: T\r\n meta?: Record<string, unknown>\r\n included?: unknown[]\r\n}\r\n\r\n// ── Ticket Submission ────────────────────────────────────────────────────────\r\n\r\nexport async function submitTicket(projectId: string, data: SubmitTicketData): Promise<TicketResult> {\r\n const res = await widgetFetch<ApiResponse<{ id: string; attributes: { ticketNumber: string; status: string } }> & { meta?: { trackingToken?: string } }>(\r\n `/projects/${projectId}/tickets`,\r\n {\r\n method: 'POST',\r\n body: {\r\n title: data.title,\r\n description: data.description,\r\n priority: data.priority,\r\n categoryId: data.categoryId,\r\n email: data.email,\r\n clientMetadata: data.clientMetadata,\r\n },\r\n headers: { 'Idempotency-Key': generateIdempotencyKey() },\r\n },\r\n )\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n trackingToken: res.meta?.trackingToken as string | undefined,\r\n status: res.data.attributes.status,\r\n }\r\n}\r\n\r\n// ── Tracking ─────────────────────────────────────────────────────────────────\r\n\r\nexport async function trackTicket(token: string): Promise<TrackedTicketResult> {\r\n const res = await widgetFetch<ApiResponse<{ id: string; attributes: { ticketNumber: string; title: string; status: string; priority: string; createdAt: string } }>>(`/tickets/track?token=${encodeURIComponent(token)}`)\r\n\r\n const included = (res.included ?? []) as Array<{ id: string; type: string; attributes: Record<string, unknown> }>\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n title: res.data.attributes.title,\r\n status: res.data.attributes.status,\r\n priority: res.data.attributes.priority,\r\n createdAt: res.data.attributes.createdAt,\r\n replies: included\r\n .filter(i => i.type === 'public-reply')\r\n .map(i => ({\r\n id: i.id,\r\n body: i.attributes.body as string,\r\n authorName: i.attributes.authorName as string,\r\n isStaff: i.attributes.isStaff as boolean,\r\n createdAt: i.attributes.createdAt as string,\r\n })),\r\n }\r\n}\r\n\r\nexport async function submitTrackingReply(token: string, body: string): Promise<void> {\r\n await widgetFetch('/tickets/track/reply', {\r\n method: 'POST',\r\n body: { trackingToken: token, body },\r\n })\r\n}\r\n\r\n// ── Categories ───────────────────────────────────────────────────────────────\r\n\r\nexport interface CategoryItem {\r\n id: string\r\n name: string\r\n parentId?: string\r\n hasChildren: boolean\r\n}\r\n\r\nexport async function getCategories(projectId: string, parentId?: string | null): Promise<CategoryItem[]> {\r\n const params = new URLSearchParams({ 'filter[active]': 'true' })\r\n if (parentId === null || parentId === undefined) params.set('filter[parentId]', 'root')\r\n else params.set('filter[parentId]', parentId)\r\n\r\n const res = await widgetFetch<ApiResponse<Array<{ id: string; attributes: { name: string; parentId?: string; hasChildren: boolean } }>>>(\r\n `/projects/${projectId}/categories?${params}`,\r\n )\r\n const items = Array.isArray(res.data) ? res.data : []\r\n return items.map(c => ({\r\n id: c.id,\r\n name: c.attributes.name,\r\n parentId: c.attributes.parentId,\r\n hasChildren: c.attributes.hasChildren,\r\n }))\r\n}\r\n\r\nexport async function closeTicket(ticketId: string): Promise<void> {\r\n await widgetFetch(`/tickets/${ticketId}/status`, {\r\n method: 'PUT',\r\n body: { status: 'resolved' },\r\n })\r\n}\r\n\r\n// ── Attachments ──────────────────────────────────────────────────────────────\r\n\r\nexport interface AttachmentMeta {\r\n id: string\r\n fileName: string\r\n contentType: string\r\n fileSize: number\r\n downloadUrl?: string\r\n downloadUrlExpiresAt?: string\r\n}\r\n\r\nexport function uploadAttachment(\r\n ticketId: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<AttachmentMeta> {\r\n return uploadWithProgress(`/api/v1/tickets/${ticketId}/attachments`, file, onProgress) as Promise<AttachmentMeta>\r\n}\r\n\r\nexport function uploadReplyAttachment(\r\n ticketId: string,\r\n replyId: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<AttachmentMeta> {\r\n return uploadWithProgress(`/api/v1/tickets/${ticketId}/replies/${replyId}/attachments`, file, onProgress) as Promise<AttachmentMeta>\r\n}\r\n\r\nexport async function getAttachmentDownloadUrl(attachmentId: string): Promise<{ downloadUrl: string; expiresAt: string }> {\r\n return widgetFetch(`/attachments/${attachmentId}/download`)\r\n}\r\n\r\n// ── Ticket Detail ────────────────────────────────────────────────────────────\r\n\r\nexport interface TicketDetail {\r\n id: string\r\n ticketNumber: string\r\n title: string\r\n description?: string\r\n status: string\r\n priority: string\r\n createdAt: string\r\n replies: PublicReply[]\r\n attachments: AttachmentMeta[]\r\n}\r\n\r\nexport async function getTicketDetail(ticketId: string, includeMedia = true): Promise<TicketDetail> {\r\n const include = includeMedia ? '?include=media' : ''\r\n const res = await widgetFetch<ApiResponse<{\r\n id: string\r\n attributes: {\r\n ticketNumber: string\r\n title: string\r\n description?: string\r\n status: string\r\n priority: string\r\n timestamps: { createdAt: string }\r\n }\r\n }>>(`/tickets/${ticketId}${include}`)\r\n\r\n const included = (res.included ?? []) as Array<{ id: string; type: string; attributes: Record<string, unknown> }>\r\n\r\n const replies = included\r\n .filter(i => i.type === 'ticket-reply')\r\n .map(i => ({\r\n id: i.id,\r\n body: i.attributes.body as string,\r\n authorName: i.attributes.authorName as string ?? 'Anonymous',\r\n isStaff: i.attributes.isStaff as boolean ?? false,\r\n createdAt: (i.attributes.timestamps as Record<string, string>)?.createdAt ?? i.attributes.createdAt as string ?? '',\r\n }))\r\n\r\n const attachments = included\r\n .filter(i => i.type === 'attachment')\r\n .map(i => ({\r\n id: i.id,\r\n fileName: i.attributes.fileName as string,\r\n contentType: i.attributes.contentType as string,\r\n fileSize: i.attributes.fileSize as number,\r\n downloadUrl: i.attributes.downloadUrl as string | undefined,\r\n downloadUrlExpiresAt: i.attributes.downloadUrlExpiresAt as string | undefined,\r\n }))\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n title: res.data.attributes.title,\r\n description: res.data.attributes.description,\r\n status: res.data.attributes.status,\r\n priority: res.data.attributes.priority,\r\n createdAt: res.data.attributes.timestamps?.createdAt ?? '',\r\n replies,\r\n attachments,\r\n }\r\n}\r\n\r\nexport async function submitReply(ticketId: string, body: string): Promise<{ id: string }> {\r\n const res = await widgetFetch<ApiResponse<{ id: string }>>(`/tickets/${ticketId}/replies`, {\r\n method: 'POST',\r\n body: { body, isInternal: false },\r\n })\r\n return { id: res.data.id }\r\n}\r\n\r\n// ── My Tickets ───────────────────────────────────────────────────────────────\r\n\r\nexport interface WidgetUser {\r\n userId: string\r\n email: string\r\n displayName: string\r\n}\r\n\r\nexport async function resolveWidgetUser(projectId: string, email: string): Promise<WidgetUser | null> {\r\n try {\r\n return await widgetFetch<WidgetUser>(`/projects/${projectId}/widget-users?email=${encodeURIComponent(email)}`)\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport interface TicketListItem {\r\n id: string\r\n ticketNumber: string\r\n title: string\r\n status: string\r\n priority: string\r\n createdAt: string\r\n}\r\n\r\nexport async function listMyTickets(\r\n projectId: string,\r\n userId: string,\r\n page = 1,\r\n pageSize = 20,\r\n): Promise<TicketListItem[]> {\r\n const params = new URLSearchParams({\r\n 'filter[createdBy]': userId,\r\n 'sort': '-created_at',\r\n 'page[number]': String(page),\r\n 'page[size]': String(pageSize),\r\n })\r\n\r\n const res = await widgetFetch<ApiResponse<Array<{\r\n id: string\r\n attributes: {\r\n ticketNumber: string\r\n title: string\r\n status: string\r\n priority: string\r\n timestamps: { createdAt: string }\r\n }\r\n }>>>(`/projects/${projectId}/tickets?${params}`)\r\n\r\n const items = Array.isArray(res.data) ? res.data : []\r\n return items.map(t => ({\r\n id: t.id,\r\n ticketNumber: t.attributes.ticketNumber,\r\n title: t.attributes.title,\r\n status: t.attributes.status,\r\n priority: t.attributes.priority,\r\n createdAt: t.attributes.timestamps?.createdAt ?? '',\r\n }))\r\n}\r\n","export const en: Record<string, string> = {\r\n 'widget.title': 'Support',\r\n 'widget.newTicket': 'New Ticket',\r\n 'widget.trackTicket': 'Track Ticket',\r\n 'form.title': 'Title',\r\n 'form.titlePlaceholder': 'Brief summary of your issue',\r\n 'form.description': 'Description',\r\n 'form.descriptionPlaceholder': 'Describe your issue in detail...',\r\n 'form.email': 'Email',\r\n 'form.emailPlaceholder': 'your@email.com',\r\n 'form.priority': 'Priority',\r\n 'form.priorityLow': 'Low',\r\n 'form.priorityMedium': 'Medium',\r\n 'form.priorityHigh': 'High',\r\n 'form.priorityUrgent': 'Urgent',\r\n 'form.category': 'Category',\r\n 'form.categoryNone': 'Select a category',\r\n 'form.submit': 'Submit Ticket',\r\n 'form.submitting': 'Submitting...',\r\n 'form.cancel': 'Cancel',\r\n 'form.attachment': 'Attach files',\r\n 'success.title': 'Ticket Submitted!',\r\n 'success.ticketNumber': 'Ticket #',\r\n 'success.trackingToken': 'Your tracking token:',\r\n 'success.trackingHint': 'Save this token to track your ticket status.',\r\n 'success.copyToken': 'Copy Token',\r\n 'success.copied': 'Copied!',\r\n 'success.close': 'Close',\r\n 'success.trackNow': 'Track Ticket',\r\n 'tracker.title': 'Track Your Ticket',\r\n 'tracker.tokenPlaceholder': 'Enter your tracking token (trk_...)',\r\n 'tracker.submit': 'Track',\r\n 'tracker.tracking': 'Tracking...',\r\n 'tracker.status': 'Status',\r\n 'tracker.priority': 'Priority',\r\n 'tracker.created': 'Created',\r\n 'tracker.replies': 'Replies',\r\n 'tracker.noReplies': 'No replies yet.',\r\n 'tracker.replyPlaceholder': 'Write a reply...',\r\n 'tracker.sendReply': 'Send Reply',\r\n 'tracker.sending': 'Sending...',\r\n 'tracker.back': 'Back',\r\n 'tracker.staff': 'Staff',\r\n 'error.generic': 'Something went wrong. Please try again.',\r\n 'error.network': 'Network error. Check your connection.',\r\n 'error.tokenInvalid': 'Invalid or expired tracking token.',\r\n 'error.required': 'This field is required.',\r\n 'error.emailInvalid': 'Please enter a valid email address.',\r\n 'error.titleMin': 'Title must be at least 5 characters.',\r\n 'portal.title': 'Support Portal',\r\n 'portal.myTickets': 'My Tickets',\r\n 'portal.noTickets': 'No tickets yet.',\r\n 'portal.newTicket': 'New Ticket',\r\n 'widget.close': 'Close',\r\n 'menu.newTicket': 'Submit a Ticket',\r\n 'menu.newTicketDesc': 'Create a new support request',\r\n 'menu.myTickets': 'My Tickets',\r\n 'menu.myTicketsDesc': 'View and manage your tickets',\r\n 'menu.trackTicket': 'Track a Ticket',\r\n 'menu.trackTicketDesc': 'Check status with your tracking token',\r\n 'menu.knowledgeBase': 'Knowledge Base',\r\n 'menu.knowledgeBaseDesc': 'Browse help articles and guides',\r\n 'menu.myTicketsPlaceholder': 'Sign in to view your tickets.',\r\n 'menu.trackPlaceholder': 'Ticket tracking is coming soon.',\r\n 'menu.kbPlaceholder': 'Knowledge base is coming soon.',\r\n 'menu.preferences': 'Preferences',\r\n 'menu.preferencesDesc': 'Language and appearance settings',\r\n 'prefs.title': 'Preferences',\r\n 'prefs.language': 'Language',\r\n 'prefs.theme': 'Theme',\r\n 'prefs.light': 'Light',\r\n 'prefs.dark': 'Dark',\r\n 'prefs.auto': 'System',\r\n 'branding.poweredBy': 'Powered by',\r\n 'attach.dropzone': 'Drop files here or click to browse',\r\n 'attach.dropzoneActive': 'Drop files here',\r\n 'attach.maxFiles': 'Maximum {max} files',\r\n 'attach.remove': 'Remove',\r\n 'attach.uploading': 'Uploading files...',\r\n 'attach.uploadProgress': 'Uploading {name}... {percent}%',\r\n 'attach.invalidType': 'File type not allowed',\r\n 'attach.tooLarge': 'File exceeds maximum size',\r\n 'attach.tooMany': 'Maximum number of files reached',\r\n 'attach.download': 'Download',\r\n 'mytickets.title': 'My Tickets',\r\n 'mytickets.emailPrompt': 'Enter your email to view your tickets',\r\n 'mytickets.emailPlaceholder': 'your@email.com',\r\n 'mytickets.rememberMe': 'Remember me',\r\n 'mytickets.lookup': 'Find My Tickets',\r\n 'mytickets.lookingUp': 'Looking up...',\r\n 'mytickets.noTickets': 'No tickets yet.',\r\n 'mytickets.submitFirst': 'Submit your first ticket',\r\n 'mytickets.noAccount': 'No tickets found for this email.',\r\n 'detail.description': 'Description',\r\n 'detail.attachments': 'Attachments',\r\n 'detail.noAttachments': 'No attachments',\r\n 'detail.replies': 'Conversation',\r\n 'detail.noReplies': 'No replies yet.',\r\n 'detail.replyPlaceholder': 'Write a reply...',\r\n 'detail.sendReply': 'Send',\r\n 'detail.sending': 'Sending...',\r\n 'detail.staff': 'Staff',\r\n 'detail.you': 'You',\r\n 'detail.loading': 'Loading ticket...',\r\n 'track.title': 'Track a Ticket',\r\n 'track.tokenPlaceholder': 'Enter tracking token (trk_...)',\r\n 'track.submit': 'Track',\r\n 'track.tracking': 'Tracking...',\r\n 'track.recentTickets': 'Recent Tickets',\r\n 'track.invalidToken': 'Invalid or expired tracking token.',\r\n 'prefs.clearEmail': 'Clear saved email',\r\n 'prefs.emailCleared': 'Email cleared',\r\n 'auth.login': 'Login',\r\n 'auth.logout': 'Logout',\r\n 'auth.sessionExpired': 'Session expired. Please log in again.',\r\n 'prefs.accentColor': 'Accent Color',\r\n 'form.categoryPlaceholder': 'Select a category',\r\n 'form.categoryBack': 'Back',\r\n 'form.categorySelected': 'Category',\r\n 'diag.title': 'Share diagnostic info',\r\n 'diag.hint': 'Help us resolve your issue faster',\r\n 'diag.screenResolution': 'Screen resolution',\r\n 'diag.deviceType': 'Device type',\r\n 'diag.timezone': 'Timezone',\r\n 'diag.referrerUrl': 'Referrer URL',\r\n 'diag.language': 'Browser language',\r\n 'diag.platform': 'Platform',\r\n 'detail.resolve': 'Mark as Resolved',\r\n 'detail.resolving': 'Resolving...',\r\n 'detail.resolved': 'Resolved',\r\n 'detail.sla': 'SLA',\r\n}\r\n","export const ar: Record<string, string> = {\r\n 'widget.title': 'الدعم',\r\n 'widget.newTicket': 'تذكرة جديدة',\r\n 'widget.trackTicket': 'تتبع التذكرة',\r\n 'form.title': 'العنوان',\r\n 'form.titlePlaceholder': 'ملخص موجز لمشكلتك',\r\n 'form.description': 'الوصف',\r\n 'form.descriptionPlaceholder': 'صف مشكلتك بالتفصيل...',\r\n 'form.email': 'البريد الإلكتروني',\r\n 'form.emailPlaceholder': 'your@email.com',\r\n 'form.priority': 'الأولوية',\r\n 'form.priorityLow': 'منخفضة',\r\n 'form.priorityMedium': 'متوسطة',\r\n 'form.priorityHigh': 'عالية',\r\n 'form.priorityUrgent': 'عاجلة',\r\n 'form.category': 'الفئة',\r\n 'form.categoryNone': 'اختر فئة',\r\n 'form.submit': 'إرسال التذكرة',\r\n 'form.submitting': 'جارِ الإرسال...',\r\n 'form.cancel': 'إلغاء',\r\n 'form.attachment': 'إرفاق ملفات',\r\n 'success.title': 'تم إرسال التذكرة!',\r\n 'success.ticketNumber': 'تذكرة #',\r\n 'success.trackingToken': 'رمز التتبع الخاص بك:',\r\n 'success.trackingHint': 'احفظ هذا الرمز لتتبع حالة تذكرتك.',\r\n 'success.copyToken': 'نسخ الرمز',\r\n 'success.copied': 'تم النسخ!',\r\n 'success.close': 'إغلاق',\r\n 'success.trackNow': 'تتبع التذكرة',\r\n 'tracker.title': 'تتبع تذكرتك',\r\n 'tracker.tokenPlaceholder': 'أدخل رمز التتبع الخاص بك (trk_...)',\r\n 'tracker.submit': 'تتبع',\r\n 'tracker.tracking': 'جارِ التتبع...',\r\n 'tracker.status': 'الحالة',\r\n 'tracker.priority': 'الأولوية',\r\n 'tracker.created': 'تاريخ الإنشاء',\r\n 'tracker.replies': 'الردود',\r\n 'tracker.noReplies': 'لا توجد ردود بعد.',\r\n 'tracker.replyPlaceholder': 'اكتب رداً...',\r\n 'tracker.sendReply': 'إرسال الرد',\r\n 'tracker.sending': 'جارِ الإرسال...',\r\n 'tracker.back': 'رجوع',\r\n 'tracker.staff': 'فريق الدعم',\r\n 'error.generic': 'حدث خطأ ما. يرجى المحاولة مرة أخرى.',\r\n 'error.network': 'خطأ في الشبكة. تحقق من اتصالك.',\r\n 'error.tokenInvalid': 'رمز التتبع غير صالح أو منتهي الصلاحية.',\r\n 'error.required': 'هذا الحقل مطلوب.',\r\n 'error.emailInvalid': 'يرجى إدخال بريد إلكتروني صالح.',\r\n 'error.titleMin': 'يجب أن يكون العنوان 5 أحرف على الأقل.',\r\n 'portal.title': 'بوابة الدعم',\r\n 'portal.myTickets': 'تذاكري',\r\n 'portal.noTickets': 'لا توجد تذاكر بعد.',\r\n 'portal.newTicket': 'تذكرة جديدة',\r\n 'widget.close': 'إغلاق',\r\n 'menu.newTicket': 'إرسال تذكرة',\r\n 'menu.newTicketDesc': 'إنشاء طلب ��عم جديد',\r\n 'menu.myTickets': 'تذاكري',\r\n 'menu.myTicketsDesc': 'عرض وإدارة تذاكرك',\r\n 'menu.trackTicket': 'تتبع تذكرة',\r\n 'menu.trackTicketDesc': 'تحقق من الحالة باستخدام رمز التتبع',\r\n 'menu.knowledgeBase': 'قاعدة المعرفة',\r\n 'menu.knowledgeBaseDesc': 'تصفح مقالات المساعدة والأدلة',\r\n 'menu.myTicketsPlaceholder': 'سجّل الدخول ��عرض تذاكرك.',\r\n 'menu.trackPlaceholder': 'تتبع التذاكر قريبًا.',\r\n 'menu.kbPlaceholder': 'قاعدة المعرفة قريبًا.',\r\n 'menu.preferences': 'التفضيلات',\r\n 'menu.preferencesDesc': 'إعدادات اللغة والمظهر',\r\n 'prefs.title': 'التفضيلات',\r\n 'prefs.language': 'اللغة',\r\n 'prefs.theme': 'المظهر',\r\n 'prefs.light': 'فاتح',\r\n 'prefs.dark': 'داكن',\r\n 'prefs.auto': 'النظام',\r\n 'branding.poweredBy': 'مدعوم من',\r\n 'attach.dropzone': 'اسحب الملفات هنا أو انقر للتصفح',\r\n 'attach.dropzoneActive': 'أفلت الملفات هنا',\r\n 'attach.maxFiles': 'بحد أقصى {max} ملفات',\r\n 'attach.remove': 'إزالة',\r\n 'attach.uploading': 'جارِ رفع الملفات...',\r\n 'attach.uploadProgress': 'جارِ رفع {name}... {percent}%',\r\n 'attach.invalidType': 'نوع الملف غير مسموح',\r\n 'attach.tooLarge': 'حجم الملف يتجاوز الحد الأقصى',\r\n 'attach.tooMany': 'تم الوصول للحد الأقصى لعدد الملفات',\r\n 'attach.download': 'تحميل',\r\n 'mytickets.title': 'تذاكري',\r\n 'mytickets.emailPrompt': 'أدخل بريدك الإلكتروني لعرض تذاكرك',\r\n 'mytickets.emailPlaceholder': 'your@email.com',\r\n 'mytickets.rememberMe': 'تذكرني',\r\n 'mytickets.lookup': 'البحث عن تذاكري',\r\n 'mytickets.lookingUp': 'جارِ البحث...',\r\n 'mytickets.noTickets': 'لا توجد تذاكر بعد.',\r\n 'mytickets.submitFirst': 'أرسل تذكرتك الأولى',\r\n 'mytickets.noAccount': 'لم يتم العثور على تذاكر لهذا البريد.',\r\n 'detail.description': 'الوصف',\r\n 'detail.attachments': 'المرفقات',\r\n 'detail.noAttachments': 'لا توجد مرفقات',\r\n 'detail.replies': 'المحادثة',\r\n 'detail.noReplies': 'لا توجد ردود بعد.',\r\n 'detail.replyPlaceholder': 'اكتب رداً...',\r\n 'detail.sendReply': 'إرسال',\r\n 'detail.sending': 'جارِ الإرسال...',\r\n 'detail.staff': 'فريق الدعم',\r\n 'detail.you': 'أنت',\r\n 'detail.loading': 'جارِ تحميل التذكرة...',\r\n 'track.title': 'تتبع تذكرة',\r\n 'track.tokenPlaceholder': 'أدخل رمز التتبع (trk_...)',\r\n 'track.submit': 'تتبع',\r\n 'track.tracking': 'جارِ التتبع...',\r\n 'track.recentTickets': 'التذاكر الأخيرة',\r\n 'track.invalidToken': 'رمز التتبع غير صالح أو منتهي.',\r\n 'prefs.clearEmail': 'مسح البريد المحفوظ',\r\n 'prefs.emailCleared': 'تم مسح البريد',\r\n 'auth.login': 'تسجيل الدخول',\r\n 'auth.logout': 'تسجيل الخروج',\r\n 'auth.sessionExpired': 'انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.',\r\n 'prefs.accentColor': 'لون التمييز',\r\n 'form.categoryPlaceholder': 'اختر فئة',\r\n 'form.categoryBack': 'رجوع',\r\n 'form.categorySelected': 'الفئة',\r\n 'diag.title': 'مشاركة معلومات التشخيص',\r\n 'diag.hint': 'ساعدنا في حل مشكلتك بشكل أسرع',\r\n 'diag.screenResolution': 'دقة الشاشة',\r\n 'diag.deviceType': 'نوع الجهاز',\r\n 'diag.timezone': 'المنطقة الزمنية',\r\n 'diag.referrerUrl': 'رابط المصدر',\r\n 'diag.language': 'لغة المتصفح',\r\n 'diag.platform': 'المنصة',\r\n 'detail.resolve': 'تحديد كمحلول',\r\n 'detail.resolving': 'جارِ الحل...',\r\n 'detail.resolved': 'محلول',\r\n 'detail.sla': 'اتفاقية الخدمة',\r\n}\r\n","import type { ThemeConfig } from './types'\r\n\r\nconst DEFAULT_THEME: Required<Omit<ThemeConfig, 'logo' | 'brandName' | 'hideBranding'>> & { logo?: string; brandName?: string; hideBranding?: boolean } = {\r\n primaryColor: '#42b983',\r\n mode: 'auto',\r\n borderRadius: '8px',\r\n fontFamily: 'inherit',\r\n zIndex: 9999,\r\n}\r\n\r\nfunction resolveMode(mode: ThemeConfig['mode']): 'light' | 'dark' {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches) {\r\n return 'dark'\r\n }\r\n return 'light'\r\n }\r\n return mode ?? 'light'\r\n}\r\n\r\nexport function themeToVars(theme: ThemeConfig = {}): string {\r\n const t = { ...DEFAULT_THEME, ...theme, mode: resolveMode(theme.mode ?? DEFAULT_THEME.mode) }\r\n const hsl = hexToHsl(t.primaryColor)\r\n const lightL = Math.min(hsl.l + 30, 95)\r\n const darkL = Math.max(hsl.l - 15, 10)\r\n return [\r\n `--rqd-primary: ${t.primaryColor}`,\r\n `--rqd-primary-h: ${hsl.h}`,\r\n `--rqd-primary-s: ${hsl.s}%`,\r\n `--rqd-primary-l: ${hsl.l}%`,\r\n `--rqd-primary-light: hsl(${hsl.h}, ${hsl.s}%, ${lightL}%)`,\r\n `--rqd-primary-dark: hsl(${hsl.h}, ${hsl.s}%, ${darkL}%)`,\r\n `--rqd-radius: ${t.borderRadius}`,\r\n `--rqd-font: ${t.fontFamily}`,\r\n `--rqd-z: ${t.zIndex}`,\r\n `--rqd-bg: ${t.mode === 'dark' ? '#1a1a2e' : '#ffffff'}`,\r\n `--rqd-bg-secondary: ${t.mode === 'dark' ? '#16213e' : '#f8f9fa'}`,\r\n `--rqd-text: ${t.mode === 'dark' ? '#e0e0e0' : '#1a1a2e'}`,\r\n `--rqd-text-secondary: ${t.mode === 'dark' ? '#a0a0b0' : '#6c757d'}`,\r\n `--rqd-border: ${t.mode === 'dark' ? '#2a2a4a' : '#e0e0e0'}`,\r\n `--rqd-input-bg: ${t.mode === 'dark' ? '#0f3460' : '#ffffff'}`,\r\n `--rqd-shadow: ${t.mode === 'dark' ? '0 8px 32px rgba(0,0,0,0.4)' : '0 8px 32px rgba(0,0,0,0.12)'}`,\r\n ].join('; ')\r\n}\r\n\r\n/**\r\n * Returns CSS custom properties as a React-compatible style object.\r\n * React's `style` prop supports custom properties (--var) as keys directly.\r\n */\r\nexport function themeToStyle(theme: ThemeConfig = {}): Record<string, string | number> {\r\n const t = { ...DEFAULT_THEME, ...theme, mode: resolveMode(theme.mode ?? DEFAULT_THEME.mode) }\r\n const hsl = hexToHsl(t.primaryColor)\r\n const lightL = Math.min(hsl.l + 30, 95)\r\n const darkL = Math.max(hsl.l - 15, 10)\r\n return {\r\n '--rqd-primary': t.primaryColor,\r\n '--rqd-primary-h': String(hsl.h),\r\n '--rqd-primary-s': `${hsl.s}%`,\r\n '--rqd-primary-l': `${hsl.l}%`,\r\n '--rqd-primary-light': `hsl(${hsl.h}, ${hsl.s}%, ${lightL}%)`,\r\n '--rqd-primary-dark': `hsl(${hsl.h}, ${hsl.s}%, ${darkL}%)`,\r\n '--rqd-radius': t.borderRadius,\r\n '--rqd-font': t.fontFamily,\r\n '--rqd-z': t.zIndex,\r\n '--rqd-bg': t.mode === 'dark' ? '#1a1a2e' : '#ffffff',\r\n '--rqd-bg-secondary': t.mode === 'dark' ? '#16213e' : '#f8f9fa',\r\n '--rqd-text': t.mode === 'dark' ? '#e0e0e0' : '#1a1a2e',\r\n '--rqd-text-secondary': t.mode === 'dark' ? '#a0a0b0' : '#6c757d',\r\n '--rqd-border': t.mode === 'dark' ? '#2a2a4a' : '#e0e0e0',\r\n '--rqd-input-bg': t.mode === 'dark' ? '#0f3460' : '#ffffff',\r\n '--rqd-shadow': t.mode === 'dark' ? '0 8px 32px rgba(0,0,0,0.4)' : '0 8px 32px rgba(0,0,0,0.12)',\r\n }\r\n}\r\n\r\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\r\n if (!result) return { h: 160, s: 51, l: 49 }\r\n\r\n const r = parseInt(result[1], 16) / 255\r\n const g = parseInt(result[2], 16) / 255\r\n const b = parseInt(result[3], 16) / 255\r\n\r\n const max = Math.max(r, g, b)\r\n const min = Math.min(r, g, b)\r\n let h = 0\r\n let s = 0\r\n const l = (max + min) / 2\r\n\r\n if (max !== min) {\r\n const d = max - min\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\r\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\r\n else if (max === g) h = ((b - r) / d + 2) / 6\r\n else h = ((r - g) / d + 4) / 6\r\n }\r\n\r\n return {\r\n h: Math.round(h * 360),\r\n s: Math.round(s * 100),\r\n l: Math.round(l * 100),\r\n }\r\n}\r\n\r\nexport function getWidgetStyles(): string {\r\n return WIDGET_CSS\r\n}\r\n\r\nconst WIDGET_CSS = `:host { all: initial; }\r\n.rqd-root { font-family: var(--rqd-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif); font-size: 14px; line-height: 1.5; color: var(--rqd-text); -webkit-font-smoothing: antialiased; }\r\n.rqd-fab { position: fixed; bottom: 20px; width: 56px; height: 56px; border-radius: 50%; background: var(--rqd-primary); color: #fff; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 16px rgba(0,0,0,0.2); transition: transform 0.2s, box-shadow 0.2s; pointer-events: auto; z-index: var(--rqd-z, 9999); }\r\n.rqd-fab:hover { transform: scale(1.08); box-shadow: 0 6px 20px rgba(0,0,0,0.25); }\r\n.rqd-fab.rqd-bottom-right { right: 20px; }\r\n.rqd-fab.rqd-bottom-left { left: 20px; }\r\n.rqd-fab svg { width: 24px; height: 24px; fill: currentColor; }\r\n.rqd-panel { position: fixed; bottom: 88px; width: 380px; max-height: calc(100vh - 120px); background: var(--rqd-bg); border-radius: var(--rqd-radius); box-shadow: var(--rqd-shadow); overflow: hidden; display: flex; flex-direction: column; pointer-events: auto; animation: rqd-slide-up 0.25s ease-out; border: 1px solid var(--rqd-border); }\r\n.rqd-panel.rqd-bottom-right { right: 20px; }\r\n.rqd-panel.rqd-bottom-left { left: 20px; }\r\n.rqd-panel.rqd-hidden { display: none; }\r\n@keyframes rqd-slide-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }\r\n.rqd-header { display: flex; align-items: center; justify-content: space-between; padding: 16px; background: var(--rqd-primary); color: #fff; }\r\n.rqd-header-title { font-size: 16px; font-weight: 600; }\r\n.rqd-header-close { background: none; border: none; color: #fff; cursor: pointer; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.15s; }\r\n.rqd-header-close:hover { background: rgba(255,255,255,0.2); }\r\n.rqd-tabs { display: flex; border-bottom: 1px solid var(--rqd-border); }\r\n.rqd-tab { flex: 1; padding: 10px; text-align: center; background: none; border: none; cursor: pointer; font-size: 13px; font-weight: 500; color: var(--rqd-text-secondary); border-bottom: 2px solid transparent; transition: color 0.15s, border-color 0.15s; }\r\n.rqd-tab.rqd-active { color: var(--rqd-primary); border-bottom-color: var(--rqd-primary); }\r\n.rqd-body { flex: 1; overflow-y: auto; padding: 16px; }\r\n.rqd-form-group { margin-bottom: 14px; }\r\n.rqd-label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 4px; color: var(--rqd-text); }\r\n.rqd-input, .rqd-textarea, .rqd-select { width: 100%; padding: 8px 12px; border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 14px; font-family: inherit; background: var(--rqd-input-bg); color: var(--rqd-text); outline: none; transition: border-color 0.15s; box-sizing: border-box; }\r\n.rqd-input:focus, .rqd-textarea:focus, .rqd-select:focus { border-color: var(--rqd-primary); }\r\n.rqd-textarea { resize: vertical; min-height: 80px; }\r\n.rqd-error-text { color: #e74c3c; font-size: 12px; margin-top: 2px; }\r\n.rqd-btn { width: 100%; padding: 10px; border: none; border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 14px; font-weight: 600; cursor: pointer; transition: opacity 0.15s; }\r\n.rqd-btn:disabled { opacity: 0.6; cursor: not-allowed; }\r\n.rqd-btn-primary { background: var(--rqd-primary); color: #fff; }\r\n.rqd-btn-primary:hover:not(:disabled) { opacity: 0.9; }\r\n.rqd-btn-secondary { background: transparent; color: var(--rqd-primary); border: 1px solid var(--rqd-primary); }\r\n.rqd-success { text-align: center; padding: 24px 0; }\r\n.rqd-success-icon { font-size: 48px; margin-bottom: 12px; }\r\n.rqd-success h3 { margin: 0 0 8px; font-size: 18px; color: var(--rqd-text); }\r\n.rqd-token-box { background: var(--rqd-bg-secondary); border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 8px 12px; font-family: monospace; font-size: 12px; word-break: break-all; margin: 8px 0; color: var(--rqd-text); }\r\n.rqd-ticket-info { background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 12px; margin-bottom: 12px; }\r\n.rqd-ticket-row { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 13px; }\r\n.rqd-ticket-label { color: var(--rqd-text-secondary); }\r\n.rqd-badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; background: var(--rqd-primary-light); color: var(--rqd-primary-dark); }\r\n.rqd-reply { padding: 10px 0; border-bottom: 1px solid var(--rqd-border); }\r\n.rqd-reply:last-child { border-bottom: none; }\r\n.rqd-reply-header { display: flex; justify-content: space-between; font-size: 12px; color: var(--rqd-text-secondary); margin-bottom: 4px; }\r\n.rqd-reply-staff { color: var(--rqd-primary); font-weight: 600; }\r\n.rqd-reply-body { font-size: 14px; white-space: pre-wrap; }\r\n.rqd-inline { pointer-events: auto; background: var(--rqd-bg); border: 1px solid var(--rqd-border); border-radius: var(--rqd-radius); overflow: hidden; }\r\n.rqd-inline .rqd-body { max-height: none; }\r\n:host([dir=\"rtl\"]) .rqd-root { direction: rtl; text-align: right; }\r\n:host([dir=\"rtl\"]) .rqd-fab.rqd-bottom-right { right: auto; left: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-fab.rqd-bottom-left { left: auto; right: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-panel.rqd-bottom-right { right: auto; left: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-panel.rqd-bottom-left { left: auto; right: 20px; }\r\n.rqd-menu { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-menu-item { display: flex; align-items: center; gap: 14px; width: 100%; padding: 14px 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 1.5); cursor: pointer; text-align: start; transition: border-color 0.15s, background 0.15s, transform 0.1s; font-family: inherit; color: var(--rqd-text); }\r\n.rqd-menu-item:hover { border-color: var(--rqd-primary); background: var(--rqd-bg); transform: translateY(-1px); }\r\n.rqd-menu-icon { width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; border-radius: calc(var(--rqd-radius, 8px) / 2); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); flex-shrink: 0; }\r\n.rqd-menu-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\r\n.rqd-menu-label { font-size: 14px; font-weight: 600; line-height: 1.3; }\r\n.rqd-menu-desc { font-size: 12px; color: var(--rqd-text-secondary); line-height: 1.3; }\r\n.rqd-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 40px 16px; color: var(--rqd-text-secondary); text-align: center; }\r\n.rqd-placeholder p { margin: 0; font-size: 14px; }\r\n.rqd-header-brand { display: flex; align-items: center; gap: 8px; min-width: 0; }\r\n.rqd-header-logo { width: 24px; height: 24px; border-radius: 4px; object-fit: contain; flex-shrink: 0; }\r\n.rqd-footer { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 8px 16px; border-top: 1px solid var(--rqd-border); font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-footer a { color: var(--rqd-text-secondary); text-decoration: none; font-weight: 600; transition: color 0.15s; }\r\n.rqd-footer a:hover { color: var(--rqd-primary); }\r\n.rqd-prefs { display: flex; flex-direction: column; gap: 16px; }\r\n.rqd-prefs-group { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-prefs-label { font-size: 13px; font-weight: 600; color: var(--rqd-text); }\r\n.rqd-prefs-options { display: flex; gap: 6px; }\r\n.rqd-prefs-option { flex: 1; padding: 8px 12px; background: var(--rqd-bg-secondary); border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; text-align: center; font-size: 13px; font-family: inherit; color: var(--rqd-text); transition: border-color 0.15s, background 0.15s; }\r\n.rqd-prefs-option:hover { border-color: var(--rqd-primary); }\r\n.rqd-prefs-option.rqd-active { border-color: var(--rqd-primary); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); font-weight: 600; }\r\n.rqd-dropzone { border: 2px dashed var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 16px; text-align: center; cursor: pointer; transition: border-color 0.15s, background 0.15s; color: var(--rqd-text-secondary); font-size: 13px; margin-bottom: 14px; }\r\n.rqd-dropzone:hover { border-color: var(--rqd-primary); }\r\n.rqd-dropzone.rqd-dropzone-active { border-color: var(--rqd-primary); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); }\r\n.rqd-file-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }\r\n.rqd-file-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; }\r\n.rqd-file-item-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\r\n.rqd-file-item-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\r\n.rqd-file-item-size { font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-file-remove { background: none; border: none; color: var(--rqd-text-secondary); cursor: pointer; padding: 4px; font-size: 16px; line-height: 1; flex-shrink: 0; }\r\n.rqd-file-remove:hover { color: #e74c3c; }\r\n.rqd-progress { width: 100%; height: 6px; background: var(--rqd-bg-secondary); border-radius: 3px; overflow: hidden; margin-top: 6px; }\r\n.rqd-progress-bar { height: 100%; background: var(--rqd-primary); border-radius: 3px; transition: width 0.2s ease; }\r\n.rqd-upload-status { font-size: 12px; color: var(--rqd-text-secondary); margin-top: 4px; }\r\n.rqd-attachment-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }\r\n.rqd-attachment-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; }\r\n.rqd-attachment-item a { color: var(--rqd-primary); text-decoration: none; font-weight: 500; font-size: 12px; flex-shrink: 0; }\r\n.rqd-attachment-item a:hover { text-decoration: underline; }\r\n.rqd-ticket-header { margin-bottom: 12px; }\r\n.rqd-ticket-header h3 { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--rqd-text); }\r\n.rqd-ticket-header-meta { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }\r\n.rqd-ticket-desc { font-size: 14px; color: var(--rqd-text); white-space: pre-wrap; margin-bottom: 16px; padding: 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); }\r\n.rqd-section-title { font-size: 13px; font-weight: 600; color: var(--rqd-text); margin-bottom: 8px; }\r\n.rqd-email-form { display: flex; flex-direction: column; gap: 12px; padding: 24px 0; }\r\n.rqd-email-form p { margin: 0; font-size: 14px; color: var(--rqd-text-secondary); text-align: center; }\r\n.rqd-checkbox-label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--rqd-text-secondary); cursor: pointer; }\r\n.rqd-checkbox-label input[type=\"checkbox\"] { accent-color: var(--rqd-primary); width: 16px; height: 16px; cursor: pointer; }\r\n.rqd-ticket-card { display: flex; flex-direction: column; gap: 4px; padding: 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 1.5); cursor: pointer; transition: border-color 0.15s, transform 0.1s; }\r\n.rqd-ticket-card:hover { border-color: var(--rqd-primary); transform: translateY(-1px); }\r\n.rqd-ticket-card-top { display: flex; justify-content: space-between; align-items: center; }\r\n.rqd-ticket-card-number { font-size: 12px; font-weight: 600; color: var(--rqd-text-secondary); }\r\n.rqd-ticket-card-title { font-size: 14px; font-weight: 500; color: var(--rqd-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\r\n.rqd-ticket-card-date { font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-ticket-list { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-loading { text-align: center; padding: 24px 0; color: var(--rqd-text-secondary); font-size: 14px; }\r\n.rqd-reply-compose { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }\r\n.rqd-category-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px; }\r\n.rqd-category-item { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; font-size: 14px; font-family: inherit; color: var(--rqd-text); transition: border-color 0.15s, background 0.15s; text-align: start; width: 100%; }\r\n.rqd-category-item:hover { border-color: var(--rqd-primary); }\r\n.rqd-category-item-chevron { color: var(--rqd-text-secondary); font-size: 16px; }\r\n.rqd-category-breadcrumb { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; font-size: 12px; color: var(--rqd-text-secondary); }\r\n.rqd-category-breadcrumb button { background: none; border: none; color: var(--rqd-primary); cursor: pointer; font-size: 12px; font-family: inherit; padding: 0; }\r\n.rqd-category-breadcrumb button:hover { text-decoration: underline; }\r\n.rqd-category-breadcrumb-sep { color: var(--rqd-text-secondary); }\r\n.rqd-category-selected { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--rqd-primary-light); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; color: var(--rqd-primary-dark); margin-bottom: 14px; }\r\n.rqd-category-selected button { background: none; border: none; color: var(--rqd-primary-dark); cursor: pointer; font-size: 14px; margin-left: auto; padding: 0; }\r\n.rqd-diag-toggle { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; font-size: 13px; color: var(--rqd-text-secondary); border: none; width: 100%; font-family: inherit; text-align: start; margin-bottom: 8px; }\r\n.rqd-diag-toggle:hover { color: var(--rqd-text); }\r\n.rqd-diag-panel { display: flex; flex-direction: column; gap: 6px; padding: 8px 0; }\r\n.rqd-diag-item { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--rqd-text-secondary); }\r\n.rqd-diag-item input[type=\"checkbox\"] { accent-color: var(--rqd-primary); width: 14px; height: 14px; }\r\n.rqd-diag-item-value { color: var(--rqd-text); font-family: monospace; font-size: 11px; margin-left: auto; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\r\n.rqd-auth-btn { background: rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.4); color: #fff; cursor: pointer; padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: 500; font-family: inherit; transition: background 0.15s; white-space: nowrap; }\r\n.rqd-auth-btn:hover { background: rgba(255,255,255,0.3); }\r\n.rqd-color-presets { display: flex; gap: 8px; flex-wrap: wrap; }\r\n.rqd-color-preset { width: 28px; height: 28px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; transition: transform 0.15s, box-shadow 0.15s; padding: 0; }\r\n.rqd-color-preset:hover { transform: scale(1.15); }\r\n.rqd-color-preset.rqd-active { box-shadow: 0 0 0 3px var(--rqd-bg), 0 0 0 5px currentColor; }\r\n.rqd-contained.rqd-fab { position: absolute; }\r\n.rqd-contained.rqd-panel { position: absolute; }\r\n@media (max-width: 440px) { .rqd-panel { width: calc(100vw - 24px); right: 12px !important; left: 12px !important; bottom: 76px; } .rqd-fab { bottom: 12px; } .rqd-fab.rqd-bottom-right { right: 12px; } .rqd-fab.rqd-bottom-left { left: 12px; } }\r\n`\r\n","export interface WidgetConfigPersist {\r\n position?: 'bottom-right' | 'bottom-left'\r\n language?: string\r\n theme?: { primaryColor?: string; mode?: 'light' | 'dark' | 'auto' }\r\n widget?: 'ticket-form' | 'support-portal'\r\n}\r\n\r\nconst STORAGE_PREFIX = 'reqdesk_'\r\n\r\nfunction getStorage(): Storage | null {\r\n try {\r\n const s = window.localStorage\r\n s.setItem('__test__', '1')\r\n s.removeItem('__test__')\r\n return s\r\n } catch {\r\n try {\r\n return window.sessionStorage\r\n } catch {\r\n return null\r\n }\r\n }\r\n}\r\n\r\nexport function saveTrackingToken(projectSlug: string, token: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n\r\n const key = `${STORAGE_PREFIX}tokens_${projectSlug}`\r\n try {\r\n const existing = JSON.parse(storage.getItem(key) ?? '[]') as string[]\r\n if (!existing.includes(token)) {\r\n existing.push(token)\r\n storage.setItem(key, JSON.stringify(existing))\r\n }\r\n } catch {\r\n storage.setItem(key, JSON.stringify([token]))\r\n }\r\n}\r\n\r\nexport function getTrackingTokens(projectSlug: string): string[] {\r\n const storage = getStorage()\r\n if (!storage) return []\r\n\r\n const key = `${STORAGE_PREFIX}tokens_${projectSlug}`\r\n try {\r\n return JSON.parse(storage.getItem(key) ?? '[]') as string[]\r\n } catch {\r\n return []\r\n }\r\n}\r\n\r\nexport function saveWidgetConfig(apiKey: string, config: WidgetConfigPersist): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n\r\n const key = `${STORAGE_PREFIX}config_${apiKey}`\r\n try {\r\n const existing = loadWidgetConfig(apiKey)\r\n const merged = { ...existing, ...config }\r\n if (config.theme && existing?.theme) {\r\n merged.theme = { ...existing.theme, ...config.theme }\r\n }\r\n storage.setItem(key, JSON.stringify(merged))\r\n } catch {\r\n // Silently fail if storage is full or unavailable\r\n }\r\n}\r\n\r\nexport function saveWidgetEmail(apiKey: string, email: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n try {\r\n storage.setItem(`${STORAGE_PREFIX}email_${apiKey}`, email)\r\n } catch { /* ignore */ }\r\n}\r\n\r\nexport function loadWidgetEmail(apiKey: string): string | null {\r\n const storage = getStorage()\r\n if (!storage) return null\r\n try {\r\n return storage.getItem(`${STORAGE_PREFIX}email_${apiKey}`)\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport function clearWidgetEmail(apiKey: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n try {\r\n storage.removeItem(`${STORAGE_PREFIX}email_${apiKey}`)\r\n } catch { /* ignore */ }\r\n}\r\n\r\nexport function loadWidgetConfig(apiKey: string): WidgetConfigPersist | null {\r\n const storage = getStorage()\r\n if (!storage) return null\r\n\r\n const key = `${STORAGE_PREFIX}config_${apiKey}`\r\n try {\r\n const raw = storage.getItem(key)\r\n if (!raw) return null\r\n return JSON.parse(raw) as WidgetConfigPersist\r\n } catch {\r\n return null\r\n }\r\n}\r\n"],"mappings":";;AAGA,IAAI,SAAS;AACb,IAAI,UAAU;AACd,IAAI,oBAAqE;AAEzE,SAAgB,sBAAsB,KAAa,KAAa;AAC9D,WAAU,IAAI,QAAQ,OAAO,GAAG;AAChC,UAAS;;AAGX,SAAgB,qBAAqB,UAA2D;AAC9F,qBAAoB;;AAGtB,MAAa,cAAc,OAAO,OAAO;CACvC,SAAS;CACT,OAAO;CACP,kBAAkB;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAI;CAEhD,MAAM,UAAU,EAAE,WAAW;AAC3B,UAAQ,UAAU,GAAG,QAAQ;EAC7B,MAAM,UAAU,IAAI,QAAQ,QAAQ,QAAuB;AAC3D,UAAQ,IAAI,aAAa,OAAO;AAGhC,MAAI,kBACF,KAAI;GACF,MAAM,SAAS,MAAM,mBAAmB;AACxC,WAAQ,IAAI,iBAAiB,UAAU,OAAO,cAAc;UACtD;AAKV,UAAQ,UAAU;;CAGpB,gBAAgB,EAAE,YAAY;EAC5B,MAAM,OAAO,SAAS;AAKtB,QAJ2B;GACzB,MAAO,MAAM,gBAA2B,QAAQ,SAAS;GACzD,SAAU,MAAM,mBAA8B,SAAS;GACxD;;CAGJ,CAAC;AAGF,SAAgB,mBACd,MACA,MACA,YACkB;AAClB,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,MAAM,IAAI,gBAAgB;AAChC,MAAI,KAAK,QAAQ,GAAG,UAAU,OAAO;AACrC,MAAI,iBAAiB,aAAa,OAAO;AAIzC,MAAI,kBACF,oBAAmB,CAChB,MAAK,WAAU;AACd,OAAI,iBAAiB,iBAAiB,UAAU,OAAO,cAAc;AACrE,YAAS;IACT,CACD,YAAY,SAAS,CAAC;MAEzB,UAAS;EAGX,SAAS,UAAU;AACjB,OAAI,WACF,KAAI,OAAO,iBAAiB,aAAa,MAAM;AAC7C,QAAI,EAAE,iBAAkB,YAAW,KAAK,MAAO,EAAE,SAAS,EAAE,QAAS,IAAI,CAAC;KAC1E;AAGJ,OAAI,iBAAiB,cAAc;AACjC,QAAI,IAAI,UAAU,OAAO,IAAI,SAAS,IACpC,KAAI;AAAE,aAAQ,KAAK,MAAM,IAAI,aAAa,CAAC;YAAS;AAAE,aAAQ,EAAE,CAAC;;QAEjE,QAAO;KAAE,MAAM,QAAQ,IAAI;KAAU,SAAS,IAAI;KAAY,CAAgB;KAEhF;AAEF,OAAI,iBAAiB,eAAe;AAClC,WAAO;KAAE,MAAM;KAAiB,SAAS;KAA+B,CAAgB;KACxF;GAEF,MAAM,OAAO,IAAI,UAAU;AAC3B,QAAK,OAAO,QAAQ,KAAK;AACzB,OAAI,KAAK,KAAK;;GAEhB;;;;ACrFJ,SAAS,yBAAiC;AACxC,QAAO,OAAO,YAAY;;AAgB5B,eAAsB,aAAa,WAAmB,MAA+C;CACnG,MAAM,MAAM,MAAM,YAChB,aAAa,UAAU,WACvB;EACE,QAAQ;EACR,MAAM;GACJ,OAAO,KAAK;GACZ,aAAa,KAAK;GAClB,UAAU,KAAK;GACf,YAAY,KAAK;GACjB,OAAO,KAAK;GACZ,gBAAgB,KAAK;GACtB;EACD,SAAS,EAAE,mBAAmB,wBAAwB,EAAE;EACzD,CACF;AAED,QAAO;EACL,IAAI,IAAI,KAAK;EACb,cAAc,IAAI,KAAK,WAAW;EAClC,eAAe,IAAI,MAAM;EACzB,QAAQ,IAAI,KAAK,WAAW;EAC7B;;AAKH,eAAsB,YAAY,OAA6C;CAC7E,MAAM,MAAM,MAAM,YAAmJ,wBAAwB,mBAAmB,MAAM,GAAG;CAEzN,MAAM,WAAY,IAAI,YAAY,EAAE;AAEpC,QAAO;EACL,IAAI,IAAI,KAAK;EACb,cAAc,IAAI,KAAK,WAAW;EAClC,OAAO,IAAI,KAAK,WAAW;EAC3B,QAAQ,IAAI,KAAK,WAAW;EAC5B,UAAU,IAAI,KAAK,WAAW;EAC9B,WAAW,IAAI,KAAK,WAAW;EAC/B,SAAS,SACN,QAAO,MAAK,EAAE,SAAS,eAAe,CACtC,KAAI,OAAM;GACT,IAAI,EAAE;GACN,MAAM,EAAE,WAAW;GACnB,YAAY,EAAE,WAAW;GACzB,SAAS,EAAE,WAAW;GACtB,WAAW,EAAE,WAAW;GACzB,EAAE;EACN;;AAGH,eAAsB,oBAAoB,OAAe,MAA6B;AACpF,OAAM,YAAY,wBAAwB;EACxC,QAAQ;EACR,MAAM;GAAE,eAAe;GAAO;GAAM;EACrC,CAAC;;AAYJ,eAAsB,cAAc,WAAmB,UAAmD;CACxG,MAAM,SAAS,IAAI,gBAAgB,EAAE,kBAAkB,QAAQ,CAAC;AAChE,KAAI,aAAa,QAAQ,aAAa,KAAA,EAAW,QAAO,IAAI,oBAAoB,OAAO;KAClF,QAAO,IAAI,oBAAoB,SAAS;CAE7C,MAAM,MAAM,MAAM,YAChB,aAAa,UAAU,cAAc,SACtC;AAED,SADc,MAAM,QAAQ,IAAI,KAAK,GAAG,IAAI,OAAO,EAAE,EACxC,KAAI,OAAM;EACrB,IAAI,EAAE;EACN,MAAM,EAAE,WAAW;EACnB,UAAU,EAAE,WAAW;EACvB,aAAa,EAAE,WAAW;EAC3B,EAAE;;AAGL,eAAsB,YAAY,UAAiC;AACjE,OAAM,YAAY,YAAY,SAAS,UAAU;EAC/C,QAAQ;EACR,MAAM,EAAE,QAAQ,YAAY;EAC7B,CAAC;;AAcJ,SAAgB,iBACd,UACA,MACA,YACyB;AACzB,QAAO,mBAAmB,mBAAmB,SAAS,eAAe,MAAM,WAAW;;AA8BxF,eAAsB,gBAAgB,UAAkB,eAAe,MAA6B;CAElG,MAAM,MAAM,MAAM,YAUd,YAAY,WAXA,eAAe,mBAAmB,KAWb;CAErC,MAAM,WAAY,IAAI,YAAY,EAAE;CAEpC,MAAM,UAAU,SACb,QAAO,MAAK,EAAE,SAAS,eAAe,CACtC,KAAI,OAAM;EACT,IAAI,EAAE;EACN,MAAM,EAAE,WAAW;EACnB,YAAY,EAAE,WAAW,cAAwB;EACjD,SAAS,EAAE,WAAW,WAAsB;EAC5C,WAAY,EAAE,WAAW,YAAuC,aAAa,EAAE,WAAW,aAAuB;EAClH,EAAE;CAEL,MAAM,cAAc,SACjB,QAAO,MAAK,EAAE,SAAS,aAAa,CACpC,KAAI,OAAM;EACT,IAAI,EAAE;EACN,UAAU,EAAE,WAAW;EACvB,aAAa,EAAE,WAAW;EAC1B,UAAU,EAAE,WAAW;EACvB,aAAa,EAAE,WAAW;EAC1B,sBAAsB,EAAE,WAAW;EACpC,EAAE;AAEL,QAAO;EACL,IAAI,IAAI,KAAK;EACb,cAAc,IAAI,KAAK,WAAW;EAClC,OAAO,IAAI,KAAK,WAAW;EAC3B,aAAa,IAAI,KAAK,WAAW;EACjC,QAAQ,IAAI,KAAK,WAAW;EAC5B,UAAU,IAAI,KAAK,WAAW;EAC9B,WAAW,IAAI,KAAK,WAAW,YAAY,aAAa;EACxD;EACA;EACD;;AAGH,eAAsB,YAAY,UAAkB,MAAuC;AAKzF,QAAO,EAAE,KAJG,MAAM,YAAyC,YAAY,SAAS,WAAW;EACzF,QAAQ;EACR,MAAM;GAAE;GAAM,YAAY;GAAO;EAClC,CAAC,EACe,KAAK,IAAI;;AAW5B,eAAsB,kBAAkB,WAAmB,OAA2C;AACpG,KAAI;AACF,SAAO,MAAM,YAAwB,aAAa,UAAU,sBAAsB,mBAAmB,MAAM,GAAG;SACxG;AACN,SAAO;;;AAaX,eAAsB,cACpB,WACA,QACA,OAAO,GACP,WAAW,IACgB;CAQ3B,MAAM,MAAM,MAAM,YASb,aAAa,UAAU,WAhBb,IAAI,gBAAgB;EACjC,qBAAqB;EACrB,QAAQ;EACR,gBAAgB,OAAO,KAAK;EAC5B,cAAc,OAAO,SAAS;EAC/B,CAAC,GAW8C;AAGhD,SADc,MAAM,QAAQ,IAAI,KAAK,GAAG,IAAI,OAAO,EAAE,EACxC,KAAI,OAAM;EACrB,IAAI,EAAE;EACN,cAAc,EAAE,WAAW;EAC3B,OAAO,EAAE,WAAW;EACpB,QAAQ,EAAE,WAAW;EACrB,UAAU,EAAE,WAAW;EACvB,WAAW,EAAE,WAAW,YAAY,aAAa;EAClD,EAAE;;;;ACxRL,MAAa,KAA6B;CACxC,gBAAgB;CAChB,oBAAoB;CACpB,sBAAsB;CACtB,cAAc;CACd,yBAAyB;CACzB,oBAAoB;CACpB,+BAA+B;CAC/B,cAAc;CACd,yBAAyB;CACzB,iBAAiB;CACjB,oBAAoB;CACpB,uBAAuB;CACvB,qBAAqB;CACrB,uBAAuB;CACvB,iBAAiB;CACjB,qBAAqB;CACrB,eAAe;CACf,mBAAmB;CACnB,eAAe;CACf,mBAAmB;CACnB,iBAAiB;CACjB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,qBAAqB;CACrB,kBAAkB;CAClB,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,4BAA4B;CAC5B,kBAAkB;CAClB,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,mBAAmB;CACnB,mBAAmB;CACnB,qBAAqB;CACrB,4BAA4B;CAC5B,qBAAqB;CACrB,mBAAmB;CACnB,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,sBAAsB;CACtB,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,gBAAgB;CAChB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,sBAAsB;CACtB,oBAAoB;CACpB,wBAAwB;CACxB,sBAAsB;CACtB,0BAA0B;CAC1B,6BAA6B;CAC7B,yBAAyB;CACzB,sBAAsB;CACtB,oBAAoB;CACpB,wBAAwB;CACxB,eAAe;CACf,kBAAkB;CAClB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,sBAAsB;CACtB,mBAAmB;CACnB,yBAAyB;CACzB,mBAAmB;CACnB,iBAAiB;CACjB,oBAAoB;CACpB,yBAAyB;CACzB,sBAAsB;CACtB,mBAAmB;CACnB,kBAAkB;CAClB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,8BAA8B;CAC9B,wBAAwB;CACxB,oBAAoB;CACpB,uBAAuB;CACvB,uBAAuB;CACvB,yBAAyB;CACzB,uBAAuB;CACvB,sBAAsB;CACtB,sBAAsB;CACtB,wBAAwB;CACxB,kBAAkB;CAClB,oBAAoB;CACpB,2BAA2B;CAC3B,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,cAAc;CACd,kBAAkB;CAClB,eAAe;CACf,0BAA0B;CAC1B,gBAAgB;CAChB,kBAAkB;CAClB,uBAAuB;CACvB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,cAAc;CACd,eAAe;CACf,uBAAuB;CACvB,qBAAqB;CACrB,4BAA4B;CAC5B,qBAAqB;CACrB,yBAAyB;CACzB,cAAc;CACd,aAAa;CACb,yBAAyB;CACzB,mBAAmB;CACnB,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,kBAAkB;CAClB,oBAAoB;CACpB,mBAAmB;CACnB,cAAc;CACf;;;ACnID,MAAa,KAA6B;CACxC,gBAAgB;CAChB,oBAAoB;CACpB,sBAAsB;CACtB,cAAc;CACd,yBAAyB;CACzB,oBAAoB;CACpB,+BAA+B;CAC/B,cAAc;CACd,yBAAyB;CACzB,iBAAiB;CACjB,oBAAoB;CACpB,uBAAuB;CACvB,qBAAqB;CACrB,uBAAuB;CACvB,iBAAiB;CACjB,qBAAqB;CACrB,eAAe;CACf,mBAAmB;CACnB,eAAe;CACf,mBAAmB;CACnB,iBAAiB;CACjB,wBAAwB;CACxB,yBAAyB;CACzB,wBAAwB;CACxB,qBAAqB;CACrB,kBAAkB;CAClB,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,4BAA4B;CAC5B,kBAAkB;CAClB,oBAAoB;CACpB,kBAAkB;CAClB,oBAAoB;CACpB,mBAAmB;CACnB,mBAAmB;CACnB,qBAAqB;CACrB,4BAA4B;CAC5B,qBAAqB;CACrB,mBAAmB;CACnB,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,sBAAsB;CACtB,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,gBAAgB;CAChB,oBAAoB;CACpB,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,sBAAsB;CACtB,oBAAoB;CACpB,wBAAwB;CACxB,sBAAsB;CACtB,0BAA0B;CAC1B,6BAA6B;CAC7B,yBAAyB;CACzB,sBAAsB;CACtB,oBAAoB;CACpB,wBAAwB;CACxB,eAAe;CACf,kBAAkB;CAClB,eAAe;CACf,eAAe;CACf,cAAc;CACd,cAAc;CACd,sBAAsB;CACtB,mBAAmB;CACnB,yBAAyB;CACzB,mBAAmB;CACnB,iBAAiB;CACjB,oBAAoB;CACpB,yBAAyB;CACzB,sBAAsB;CACtB,mBAAmB;CACnB,kBAAkB;CAClB,mBAAmB;CACnB,mBAAmB;CACnB,yBAAyB;CACzB,8BAA8B;CAC9B,wBAAwB;CACxB,oBAAoB;CACpB,uBAAuB;CACvB,uBAAuB;CACvB,yBAAyB;CACzB,uBAAuB;CACvB,sBAAsB;CACtB,sBAAsB;CACtB,wBAAwB;CACxB,kBAAkB;CAClB,oBAAoB;CACpB,2BAA2B;CAC3B,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,cAAc;CACd,kBAAkB;CAClB,eAAe;CACf,0BAA0B;CAC1B,gBAAgB;CAChB,kBAAkB;CAClB,uBAAuB;CACvB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,cAAc;CACd,eAAe;CACf,uBAAuB;CACvB,qBAAqB;CACrB,4BAA4B;CAC5B,qBAAqB;CACrB,yBAAyB;CACzB,cAAc;CACd,aAAa;CACb,yBAAyB;CACzB,mBAAmB;CACnB,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,kBAAkB;CAClB,oBAAoB;CACpB,mBAAmB;CACnB,cAAc;CACf;;;ACjID,MAAM,gBAAoJ;CACxJ,cAAc;CACd,MAAM;CACN,cAAc;CACd,YAAY;CACZ,QAAQ;CACT;AAED,SAAS,YAAY,MAA6C;AAChE,KAAI,SAAS,QAAQ;AACnB,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,+BAA+B,CAAC,QACvF,QAAO;AAET,SAAO;;AAET,QAAO,QAAQ;;AAGjB,SAAgB,YAAY,QAAqB,EAAE,EAAU;CAC3D,MAAM,IAAI;EAAE,GAAG;EAAe,GAAG;EAAO,MAAM,YAAY,MAAM,QAAQ,cAAc,KAAK;EAAE;CAC7F,MAAM,MAAM,SAAS,EAAE,aAAa;CACpC,MAAM,SAAS,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG;CACvC,MAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG;AACtC,QAAO;EACL,kBAAkB,EAAE;EACpB,oBAAoB,IAAI;EACxB,oBAAoB,IAAI,EAAE;EAC1B,oBAAoB,IAAI,EAAE;EAC1B,4BAA4B,IAAI,EAAE,IAAI,IAAI,EAAE,KAAK,OAAO;EACxD,2BAA2B,IAAI,EAAE,IAAI,IAAI,EAAE,KAAK,MAAM;EACtD,iBAAiB,EAAE;EACnB,eAAe,EAAE;EACjB,YAAY,EAAE;EACd,aAAa,EAAE,SAAS,SAAS,YAAY;EAC7C,uBAAuB,EAAE,SAAS,SAAS,YAAY;EACvD,eAAe,EAAE,SAAS,SAAS,YAAY;EAC/C,yBAAyB,EAAE,SAAS,SAAS,YAAY;EACzD,iBAAiB,EAAE,SAAS,SAAS,YAAY;EACjD,mBAAmB,EAAE,SAAS,SAAS,YAAY;EACnD,iBAAiB,EAAE,SAAS,SAAS,+BAA+B;EACrE,CAAC,KAAK,KAAK;;;;;;AAOd,SAAgB,aAAa,QAAqB,EAAE,EAAmC;CACrF,MAAM,IAAI;EAAE,GAAG;EAAe,GAAG;EAAO,MAAM,YAAY,MAAM,QAAQ,cAAc,KAAK;EAAE;CAC7F,MAAM,MAAM,SAAS,EAAE,aAAa;CACpC,MAAM,SAAS,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG;CACvC,MAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG;AACtC,QAAO;EACL,iBAAiB,EAAE;EACnB,mBAAmB,OAAO,IAAI,EAAE;EAChC,mBAAmB,GAAG,IAAI,EAAE;EAC5B,mBAAmB,GAAG,IAAI,EAAE;EAC5B,uBAAuB,OAAO,IAAI,EAAE,IAAI,IAAI,EAAE,KAAK,OAAO;EAC1D,sBAAsB,OAAO,IAAI,EAAE,IAAI,IAAI,EAAE,KAAK,MAAM;EACxD,gBAAgB,EAAE;EAClB,cAAc,EAAE;EAChB,WAAW,EAAE;EACb,YAAY,EAAE,SAAS,SAAS,YAAY;EAC5C,sBAAsB,EAAE,SAAS,SAAS,YAAY;EACtD,cAAc,EAAE,SAAS,SAAS,YAAY;EAC9C,wBAAwB,EAAE,SAAS,SAAS,YAAY;EACxD,gBAAgB,EAAE,SAAS,SAAS,YAAY;EAChD,kBAAkB,EAAE,SAAS,SAAS,YAAY;EAClD,gBAAgB,EAAE,SAAS,SAAS,+BAA+B;EACpE;;AAGH,SAAS,SAAS,KAAkD;CAClE,MAAM,SAAS,4CAA4C,KAAK,IAAI;AACpE,KAAI,CAAC,OAAQ,QAAO;EAAE,GAAG;EAAK,GAAG;EAAI,GAAG;EAAI;CAE5C,MAAM,IAAI,SAAS,OAAO,IAAI,GAAG,GAAG;CACpC,MAAM,IAAI,SAAS,OAAO,IAAI,GAAG,GAAG;CACpC,MAAM,IAAI,SAAS,OAAO,IAAI,GAAG,GAAG;CAEpC,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,EAAE;CAC7B,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,EAAE;CAC7B,IAAI,IAAI;CACR,IAAI,IAAI;CACR,MAAM,KAAK,MAAM,OAAO;AAExB,KAAI,QAAQ,KAAK;EACf,MAAM,IAAI,MAAM;AAChB,MAAI,IAAI,KAAM,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM;AAC/C,MAAI,QAAQ,EAAG,OAAM,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,MAAM;WAC5C,QAAQ,EAAG,OAAM,IAAI,KAAK,IAAI,KAAK;MACvC,OAAM,IAAI,KAAK,IAAI,KAAK;;AAG/B,QAAO;EACL,GAAG,KAAK,MAAM,IAAI,IAAI;EACtB,GAAG,KAAK,MAAM,IAAI,IAAI;EACtB,GAAG,KAAK,MAAM,IAAI,IAAI;EACvB;;AAGH,SAAgB,kBAA0B;AACxC,QAAO;;AAGT,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpGnB,MAAM,iBAAiB;AAEvB,SAAS,aAA6B;AACpC,KAAI;EACF,MAAM,IAAI,OAAO;AACjB,IAAE,QAAQ,YAAY,IAAI;AAC1B,IAAE,WAAW,WAAW;AACxB,SAAO;SACD;AACN,MAAI;AACF,UAAO,OAAO;UACR;AACN,UAAO;;;;AAKb,SAAgB,kBAAkB,aAAqB,OAAqB;CAC1E,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS;CAEd,MAAM,MAAM,GAAG,eAAe,SAAS;AACvC,KAAI;EACF,MAAM,WAAW,KAAK,MAAM,QAAQ,QAAQ,IAAI,IAAI,KAAK;AACzD,MAAI,CAAC,SAAS,SAAS,MAAM,EAAE;AAC7B,YAAS,KAAK,MAAM;AACpB,WAAQ,QAAQ,KAAK,KAAK,UAAU,SAAS,CAAC;;SAE1C;AACN,UAAQ,QAAQ,KAAK,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC;;;AAIjD,SAAgB,kBAAkB,aAA+B;CAC/D,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS,QAAO,EAAE;CAEvB,MAAM,MAAM,GAAG,eAAe,SAAS;AACvC,KAAI;AACF,SAAO,KAAK,MAAM,QAAQ,QAAQ,IAAI,IAAI,KAAK;SACzC;AACN,SAAO,EAAE;;;AAIb,SAAgB,iBAAiB,QAAgB,QAAmC;CAClF,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS;CAEd,MAAM,MAAM,GAAG,eAAe,SAAS;AACvC,KAAI;EACF,MAAM,WAAW,iBAAiB,OAAO;EACzC,MAAM,SAAS;GAAE,GAAG;GAAU,GAAG;GAAQ;AACzC,MAAI,OAAO,SAAS,UAAU,MAC5B,QAAO,QAAQ;GAAE,GAAG,SAAS;GAAO,GAAG,OAAO;GAAO;AAEvD,UAAQ,QAAQ,KAAK,KAAK,UAAU,OAAO,CAAC;SACtC;;AAKV,SAAgB,gBAAgB,QAAgB,OAAqB;CACnE,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS;AACd,KAAI;AACF,UAAQ,QAAQ,GAAG,eAAe,QAAQ,UAAU,MAAM;SACpD;;AAGV,SAAgB,gBAAgB,QAA+B;CAC7D,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI;AACF,SAAO,QAAQ,QAAQ,GAAG,eAAe,QAAQ,SAAS;SACpD;AACN,SAAO;;;AAIX,SAAgB,iBAAiB,QAAsB;CACrD,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS;AACd,KAAI;AACF,UAAQ,WAAW,GAAG,eAAe,QAAQ,SAAS;SAChD;;AAGV,SAAgB,iBAAiB,QAA4C;CAC3E,MAAM,UAAU,YAAY;AAC5B,KAAI,CAAC,QAAS,QAAO;CAErB,MAAM,MAAM,GAAG,eAAe,SAAS;AACvC,KAAI;EACF,MAAM,MAAM,QAAQ,QAAQ,IAAI;AAChC,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage-BG7rsgWE.js","names":[],"sources":["../src/ofetch-client.ts","../src/api-client.ts","../src/i18n/en.ts","../src/i18n/ar.ts","../src/theme.ts","../src/storage.ts"],"sourcesContent":["import { ofetch } from 'ofetch'\r\nimport type { WidgetError } from './types'\r\n\r\nlet apiKey = ''\r\nlet baseUrl = ''\r\nlet oidcTokenProvider: (() => Promise<{ accessToken: string }>) | null = null\r\n\r\nexport function configureWidgetClient(url: string, key: string) {\r\n baseUrl = url.replace(/\\/$/, '')\r\n apiKey = key\r\n}\r\n\r\nexport function setOidcTokenProvider(provider: (() => Promise<{ accessToken: string }>) | null) {\r\n oidcTokenProvider = provider\r\n}\r\n\r\nexport const widgetFetch = ofetch.create({\r\n timeout: 15000,\r\n retry: 2,\r\n retryStatusCodes: [408, 429, 500, 502, 503, 504],\r\n\r\n async onRequest({ options }) {\r\n options.baseURL = `${baseUrl}/api/v1`\r\n const headers = new Headers(options.headers as HeadersInit)\r\n headers.set('X-API-Key', apiKey)\r\n\r\n // Get fresh token on every request — oidc-spa handles refresh internally\r\n if (oidcTokenProvider) {\r\n try {\r\n const tokens = await oidcTokenProvider()\r\n headers.set('Authorization', `Bearer ${tokens.accessToken}`)\r\n } catch {\r\n // Auth unavailable — continue with API key only\r\n }\r\n }\r\n\r\n options.headers = headers\r\n },\r\n\r\n onResponseError({ response }) {\r\n const body = response._data as Record<string, unknown> | undefined\r\n const error: WidgetError = {\r\n code: (body?.responseCode as string) ?? `HTTP_${response.status}`,\r\n message: (body?.responseMessage as string) ?? response.statusText,\r\n }\r\n throw error\r\n },\r\n})\r\n\r\n// Upload helper using XHR for progress tracking (ofetch doesn't support upload progress)\r\nexport function uploadWithProgress(\r\n path: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<unknown> {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest()\r\n xhr.open('POST', `${baseUrl}${path}`)\r\n xhr.setRequestHeader('X-API-Key', apiKey)\r\n\r\n // For uploads, use cached token (can't await in XHR setup)\r\n // The token was set on the last ofetch request via the interceptor\r\n if (oidcTokenProvider) {\r\n oidcTokenProvider()\r\n .then(tokens => {\r\n xhr.setRequestHeader('Authorization', `Bearer ${tokens.accessToken}`)\r\n sendXhr()\r\n })\r\n .catch(() => sendXhr())\r\n } else {\r\n sendXhr()\r\n }\r\n\r\n function sendXhr() {\r\n if (onProgress) {\r\n xhr.upload.addEventListener('progress', (e) => {\r\n if (e.lengthComputable) onProgress(Math.round((e.loaded / e.total) * 100))\r\n })\r\n }\r\n\r\n xhr.addEventListener('load', () => {\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n try { resolve(JSON.parse(xhr.responseText)) } catch { resolve({}) }\r\n } else {\r\n reject({ code: `HTTP_${xhr.status}`, message: xhr.statusText } as WidgetError)\r\n }\r\n })\r\n\r\n xhr.addEventListener('error', () => {\r\n reject({ code: 'NETWORK_ERROR', message: 'Network error during upload' } as WidgetError)\r\n })\r\n\r\n const form = new FormData()\r\n form.append('file', file)\r\n xhr.send(form)\r\n }\r\n })\r\n}\r\n","import { widgetFetch, uploadWithProgress, configureWidgetClient, setOidcTokenProvider } from './ofetch-client'\r\nimport type { SubmitTicketData, TicketResult, TrackedTicketResult, PublicReply } from './types'\r\n\r\n// Re-export client configuration\r\nexport { configureWidgetClient as configureClient, setOidcTokenProvider }\r\n\r\n// Legacy compat — setBearerToken is no longer needed (ofetch interceptor handles it)\r\nexport function setBearerToken(_token: string | null) {\r\n // No-op: token is now fetched per-request via oidcTokenProvider\r\n}\r\n\r\nfunction generateIdempotencyKey(): string {\r\n return crypto.randomUUID()\r\n}\r\n\r\n// ── JSON:API response shape ──────────────────────────────────────────────────\r\n\r\ninterface ApiResponse<T> {\r\n responseCode: string\r\n responseMessage: string\r\n httpCode: number\r\n data: T\r\n meta?: Record<string, unknown>\r\n included?: unknown[]\r\n}\r\n\r\n// ── Ticket Submission ────────────────────────────────────────────────────────\r\n\r\nexport async function submitTicket(projectId: string, data: SubmitTicketData): Promise<TicketResult> {\r\n const res = await widgetFetch<ApiResponse<{ id: string; attributes: { ticketNumber: string; status: string } }> & { meta?: { trackingToken?: string } }>(\r\n `/projects/${projectId}/tickets`,\r\n {\r\n method: 'POST',\r\n body: {\r\n title: data.title,\r\n description: data.description,\r\n priority: data.priority,\r\n categoryId: data.categoryId,\r\n email: data.email,\r\n clientMetadata: data.clientMetadata,\r\n },\r\n headers: { 'Idempotency-Key': generateIdempotencyKey() },\r\n },\r\n )\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n trackingToken: res.meta?.trackingToken as string | undefined,\r\n status: res.data.attributes.status,\r\n }\r\n}\r\n\r\n// ── Tracking ─────────────────────────────────────────────────────────────────\r\n\r\nexport async function trackTicket(token: string): Promise<TrackedTicketResult> {\r\n const res = await widgetFetch<ApiResponse<{ id: string; attributes: { ticketNumber: string; title: string; status: string; priority: string; createdAt: string } }>>(`/tickets/track?token=${encodeURIComponent(token)}`)\r\n\r\n const included = (res.included ?? []) as Array<{ id: string; type: string; attributes: Record<string, unknown> }>\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n title: res.data.attributes.title,\r\n status: res.data.attributes.status,\r\n priority: res.data.attributes.priority,\r\n createdAt: res.data.attributes.createdAt,\r\n replies: included\r\n .filter(i => i.type === 'public-reply')\r\n .map(i => ({\r\n id: i.id,\r\n body: i.attributes.body as string,\r\n authorName: i.attributes.authorName as string,\r\n isStaff: i.attributes.isStaff as boolean,\r\n createdAt: i.attributes.createdAt as string,\r\n })),\r\n }\r\n}\r\n\r\nexport async function submitTrackingReply(token: string, body: string): Promise<void> {\r\n await widgetFetch('/tickets/track/reply', {\r\n method: 'POST',\r\n body: { trackingToken: token, body },\r\n })\r\n}\r\n\r\n// ── Categories ───────────────────────────────────────────────────────────────\r\n\r\nexport interface CategoryItem {\r\n id: string\r\n name: string\r\n parentId?: string\r\n hasChildren: boolean\r\n}\r\n\r\nexport async function getCategories(projectId: string, parentId?: string | null): Promise<CategoryItem[]> {\r\n const params = new URLSearchParams({ 'filter[active]': 'true' })\r\n if (parentId === null || parentId === undefined) params.set('filter[parentId]', 'root')\r\n else params.set('filter[parentId]', parentId)\r\n\r\n const res = await widgetFetch<ApiResponse<Array<{ id: string; attributes: { name: string; parentId?: string; hasChildren: boolean } }>>>(\r\n `/projects/${projectId}/categories?${params}`,\r\n )\r\n const items = Array.isArray(res.data) ? res.data : []\r\n return items.map(c => ({\r\n id: c.id,\r\n name: c.attributes.name,\r\n parentId: c.attributes.parentId,\r\n hasChildren: c.attributes.hasChildren,\r\n }))\r\n}\r\n\r\nexport async function closeTicket(ticketId: string): Promise<void> {\r\n await widgetFetch(`/tickets/${ticketId}/status`, {\r\n method: 'PUT',\r\n body: { status: 'resolved' },\r\n })\r\n}\r\n\r\n// ── Attachments ──────────────────────────────────────────────────────────────\r\n\r\nexport interface AttachmentMeta {\r\n id: string\r\n fileName: string\r\n contentType: string\r\n fileSize: number\r\n downloadUrl?: string\r\n downloadUrlExpiresAt?: string\r\n}\r\n\r\nexport function uploadAttachment(\r\n ticketId: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<AttachmentMeta> {\r\n return uploadWithProgress(`/api/v1/tickets/${ticketId}/attachments`, file, onProgress) as Promise<AttachmentMeta>\r\n}\r\n\r\nexport function uploadReplyAttachment(\r\n ticketId: string,\r\n replyId: string,\r\n file: File,\r\n onProgress?: (percent: number) => void,\r\n): Promise<AttachmentMeta> {\r\n return uploadWithProgress(`/api/v1/tickets/${ticketId}/replies/${replyId}/attachments`, file, onProgress) as Promise<AttachmentMeta>\r\n}\r\n\r\nexport async function getAttachmentDownloadUrl(attachmentId: string): Promise<{ downloadUrl: string; expiresAt: string }> {\r\n return widgetFetch(`/attachments/${attachmentId}/download`)\r\n}\r\n\r\n// ── Ticket Detail ────────────────────────────────────────────────────────────\r\n\r\nexport interface TicketDetail {\r\n id: string\r\n ticketNumber: string\r\n title: string\r\n description?: string\r\n status: string\r\n priority: string\r\n createdAt: string\r\n replies: PublicReply[]\r\n attachments: AttachmentMeta[]\r\n}\r\n\r\nexport async function getTicketDetail(ticketId: string, includeMedia = true): Promise<TicketDetail> {\r\n const include = includeMedia ? '?include=media' : ''\r\n const res = await widgetFetch<ApiResponse<{\r\n id: string\r\n attributes: {\r\n ticketNumber: string\r\n title: string\r\n description?: string\r\n status: string\r\n priority: string\r\n timestamps: { createdAt: string }\r\n }\r\n }>>(`/tickets/${ticketId}${include}`)\r\n\r\n const included = (res.included ?? []) as Array<{ id: string; type: string; attributes: Record<string, unknown> }>\r\n\r\n const replies = included\r\n .filter(i => i.type === 'ticket-reply')\r\n .map(i => ({\r\n id: i.id,\r\n body: i.attributes.body as string,\r\n authorName: i.attributes.authorName as string ?? 'Anonymous',\r\n isStaff: i.attributes.isStaff as boolean ?? false,\r\n createdAt: (i.attributes.timestamps as Record<string, string>)?.createdAt ?? i.attributes.createdAt as string ?? '',\r\n }))\r\n\r\n const attachments = included\r\n .filter(i => i.type === 'attachment')\r\n .map(i => ({\r\n id: i.id,\r\n fileName: i.attributes.fileName as string,\r\n contentType: i.attributes.contentType as string,\r\n fileSize: i.attributes.fileSize as number,\r\n downloadUrl: i.attributes.downloadUrl as string | undefined,\r\n downloadUrlExpiresAt: i.attributes.downloadUrlExpiresAt as string | undefined,\r\n }))\r\n\r\n return {\r\n id: res.data.id,\r\n ticketNumber: res.data.attributes.ticketNumber,\r\n title: res.data.attributes.title,\r\n description: res.data.attributes.description,\r\n status: res.data.attributes.status,\r\n priority: res.data.attributes.priority,\r\n createdAt: res.data.attributes.timestamps?.createdAt ?? '',\r\n replies,\r\n attachments,\r\n }\r\n}\r\n\r\nexport async function submitReply(ticketId: string, body: string): Promise<{ id: string }> {\r\n const res = await widgetFetch<ApiResponse<{ id: string }>>(`/tickets/${ticketId}/replies`, {\r\n method: 'POST',\r\n body: { body, isInternal: false },\r\n })\r\n return { id: res.data.id }\r\n}\r\n\r\n// ── My Tickets ───────────────────────────────────────────────────────────────\r\n\r\nexport interface WidgetUser {\r\n userId: string\r\n email: string\r\n displayName: string\r\n}\r\n\r\nexport async function resolveWidgetUser(projectId: string, email: string): Promise<WidgetUser | null> {\r\n try {\r\n return await widgetFetch<WidgetUser>(`/projects/${projectId}/widget-users?email=${encodeURIComponent(email)}`)\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport interface TicketListItem {\r\n id: string\r\n ticketNumber: string\r\n title: string\r\n status: string\r\n priority: string\r\n createdAt: string\r\n}\r\n\r\nexport async function listMyTickets(\r\n projectId: string,\r\n userId: string,\r\n page = 1,\r\n pageSize = 20,\r\n): Promise<TicketListItem[]> {\r\n const params = new URLSearchParams({\r\n 'filter[createdBy]': userId,\r\n 'sort': '-created_at',\r\n 'page[number]': String(page),\r\n 'page[size]': String(pageSize),\r\n })\r\n\r\n const res = await widgetFetch<ApiResponse<Array<{\r\n id: string\r\n attributes: {\r\n ticketNumber: string\r\n title: string\r\n status: string\r\n priority: string\r\n timestamps: { createdAt: string }\r\n }\r\n }>>>(`/projects/${projectId}/tickets?${params}`)\r\n\r\n const items = Array.isArray(res.data) ? res.data : []\r\n return items.map(t => ({\r\n id: t.id,\r\n ticketNumber: t.attributes.ticketNumber,\r\n title: t.attributes.title,\r\n status: t.attributes.status,\r\n priority: t.attributes.priority,\r\n createdAt: t.attributes.timestamps?.createdAt ?? '',\r\n }))\r\n}\r\n","export const en: Record<string, string> = {\r\n 'widget.title': 'Support',\r\n 'widget.newTicket': 'New Ticket',\r\n 'widget.trackTicket': 'Track Ticket',\r\n 'form.title': 'Title',\r\n 'form.titlePlaceholder': 'Brief summary of your issue',\r\n 'form.description': 'Description',\r\n 'form.descriptionPlaceholder': 'Describe your issue in detail...',\r\n 'form.email': 'Email',\r\n 'form.emailPlaceholder': 'your@email.com',\r\n 'form.priority': 'Priority',\r\n 'form.priorityLow': 'Low',\r\n 'form.priorityMedium': 'Medium',\r\n 'form.priorityHigh': 'High',\r\n 'form.priorityUrgent': 'Urgent',\r\n 'form.category': 'Category',\r\n 'form.categoryNone': 'Select a category',\r\n 'form.submit': 'Submit Ticket',\r\n 'form.submitting': 'Submitting...',\r\n 'form.cancel': 'Cancel',\r\n 'form.attachment': 'Attach files',\r\n 'success.title': 'Ticket Submitted!',\r\n 'success.ticketNumber': 'Ticket #',\r\n 'success.trackingToken': 'Your tracking token:',\r\n 'success.trackingHint': 'Save this token to track your ticket status.',\r\n 'success.copyToken': 'Copy Token',\r\n 'success.copied': 'Copied!',\r\n 'success.close': 'Close',\r\n 'success.trackNow': 'Track Ticket',\r\n 'tracker.title': 'Track Your Ticket',\r\n 'tracker.tokenPlaceholder': 'Enter your tracking token (trk_...)',\r\n 'tracker.submit': 'Track',\r\n 'tracker.tracking': 'Tracking...',\r\n 'tracker.status': 'Status',\r\n 'tracker.priority': 'Priority',\r\n 'tracker.created': 'Created',\r\n 'tracker.replies': 'Replies',\r\n 'tracker.noReplies': 'No replies yet.',\r\n 'tracker.replyPlaceholder': 'Write a reply...',\r\n 'tracker.sendReply': 'Send Reply',\r\n 'tracker.sending': 'Sending...',\r\n 'tracker.back': 'Back',\r\n 'tracker.staff': 'Staff',\r\n 'error.generic': 'Something went wrong. Please try again.',\r\n 'error.network': 'Network error. Check your connection.',\r\n 'error.tokenInvalid': 'Invalid or expired tracking token.',\r\n 'error.required': 'This field is required.',\r\n 'error.emailInvalid': 'Please enter a valid email address.',\r\n 'error.titleMin': 'Title must be at least 5 characters.',\r\n 'portal.title': 'Support Portal',\r\n 'portal.myTickets': 'My Tickets',\r\n 'portal.noTickets': 'No tickets yet.',\r\n 'portal.newTicket': 'New Ticket',\r\n 'widget.close': 'Close',\r\n 'menu.newTicket': 'Submit a Ticket',\r\n 'menu.newTicketDesc': 'Create a new support request',\r\n 'menu.myTickets': 'My Tickets',\r\n 'menu.myTicketsDesc': 'View and manage your tickets',\r\n 'menu.trackTicket': 'Track a Ticket',\r\n 'menu.trackTicketDesc': 'Check status with your tracking token',\r\n 'menu.knowledgeBase': 'Knowledge Base',\r\n 'menu.knowledgeBaseDesc': 'Browse help articles and guides',\r\n 'menu.myTicketsPlaceholder': 'Sign in to view your tickets.',\r\n 'menu.trackPlaceholder': 'Ticket tracking is coming soon.',\r\n 'menu.kbPlaceholder': 'Knowledge base is coming soon.',\r\n 'menu.preferences': 'Preferences',\r\n 'menu.preferencesDesc': 'Language and appearance settings',\r\n 'prefs.title': 'Preferences',\r\n 'prefs.language': 'Language',\r\n 'prefs.theme': 'Theme',\r\n 'prefs.light': 'Light',\r\n 'prefs.dark': 'Dark',\r\n 'prefs.auto': 'System',\r\n 'branding.poweredBy': 'Powered by',\r\n 'attach.dropzone': 'Drop files here or click to browse',\r\n 'attach.dropzoneActive': 'Drop files here',\r\n 'attach.maxFiles': 'Maximum {max} files',\r\n 'attach.remove': 'Remove',\r\n 'attach.uploading': 'Uploading files...',\r\n 'attach.uploadProgress': 'Uploading {name}... {percent}%',\r\n 'attach.invalidType': 'File type not allowed',\r\n 'attach.tooLarge': 'File exceeds maximum size',\r\n 'attach.tooMany': 'Maximum number of files reached',\r\n 'attach.download': 'Download',\r\n 'mytickets.title': 'My Tickets',\r\n 'mytickets.emailPrompt': 'Enter your email to view your tickets',\r\n 'mytickets.emailPlaceholder': 'your@email.com',\r\n 'mytickets.rememberMe': 'Remember me',\r\n 'mytickets.lookup': 'Find My Tickets',\r\n 'mytickets.lookingUp': 'Looking up...',\r\n 'mytickets.noTickets': 'No tickets yet.',\r\n 'mytickets.submitFirst': 'Submit your first ticket',\r\n 'mytickets.noAccount': 'No tickets found for this email.',\r\n 'detail.description': 'Description',\r\n 'detail.attachments': 'Attachments',\r\n 'detail.noAttachments': 'No attachments',\r\n 'detail.replies': 'Conversation',\r\n 'detail.noReplies': 'No replies yet.',\r\n 'detail.replyPlaceholder': 'Write a reply...',\r\n 'detail.sendReply': 'Send',\r\n 'detail.sending': 'Sending...',\r\n 'detail.staff': 'Staff',\r\n 'detail.you': 'You',\r\n 'detail.loading': 'Loading ticket...',\r\n 'track.title': 'Track a Ticket',\r\n 'track.tokenPlaceholder': 'Enter tracking token (trk_...)',\r\n 'track.submit': 'Track',\r\n 'track.tracking': 'Tracking...',\r\n 'track.recentTickets': 'Recent Tickets',\r\n 'track.invalidToken': 'Invalid or expired tracking token.',\r\n 'prefs.clearEmail': 'Clear saved email',\r\n 'prefs.emailCleared': 'Email cleared',\r\n 'auth.login': 'Login',\r\n 'auth.logout': 'Logout',\r\n 'auth.sessionExpired': 'Session expired. Please log in again.',\r\n 'prefs.accentColor': 'Accent Color',\r\n 'form.categoryPlaceholder': 'Select a category',\r\n 'form.categoryBack': 'Back',\r\n 'form.categorySelected': 'Category',\r\n 'diag.title': 'Share diagnostic info',\r\n 'diag.hint': 'Help us resolve your issue faster',\r\n 'diag.screenResolution': 'Screen resolution',\r\n 'diag.deviceType': 'Device type',\r\n 'diag.timezone': 'Timezone',\r\n 'diag.referrerUrl': 'Referrer URL',\r\n 'diag.language': 'Browser language',\r\n 'diag.platform': 'Platform',\r\n 'detail.resolve': 'Mark as Resolved',\r\n 'detail.resolving': 'Resolving...',\r\n 'detail.resolved': 'Resolved',\r\n 'detail.sla': 'SLA',\r\n}\r\n","export const ar: Record<string, string> = {\r\n 'widget.title': 'الدعم',\r\n 'widget.newTicket': 'تذكرة جديدة',\r\n 'widget.trackTicket': 'تتبع التذكرة',\r\n 'form.title': 'العنوان',\r\n 'form.titlePlaceholder': 'ملخص موجز لمشكلتك',\r\n 'form.description': 'الوصف',\r\n 'form.descriptionPlaceholder': 'صف مشكلتك بالتفصيل...',\r\n 'form.email': 'البريد الإلكتروني',\r\n 'form.emailPlaceholder': 'your@email.com',\r\n 'form.priority': 'الأولوية',\r\n 'form.priorityLow': 'منخفضة',\r\n 'form.priorityMedium': 'متوسطة',\r\n 'form.priorityHigh': 'عالية',\r\n 'form.priorityUrgent': 'عاجلة',\r\n 'form.category': 'الفئة',\r\n 'form.categoryNone': 'اختر فئة',\r\n 'form.submit': 'إرسال التذكرة',\r\n 'form.submitting': 'جارِ الإرسال...',\r\n 'form.cancel': 'إلغاء',\r\n 'form.attachment': 'إرفاق ملفات',\r\n 'success.title': 'تم إرسال التذكرة!',\r\n 'success.ticketNumber': 'تذكرة #',\r\n 'success.trackingToken': 'رمز التتبع الخاص بك:',\r\n 'success.trackingHint': 'احفظ هذا الرمز لتتبع حالة تذكرتك.',\r\n 'success.copyToken': 'نسخ الرمز',\r\n 'success.copied': 'تم النسخ!',\r\n 'success.close': 'إغلاق',\r\n 'success.trackNow': 'تتبع التذكرة',\r\n 'tracker.title': 'تتبع تذكرتك',\r\n 'tracker.tokenPlaceholder': 'أدخل رمز التتبع الخاص بك (trk_...)',\r\n 'tracker.submit': 'تتبع',\r\n 'tracker.tracking': 'جارِ التتبع...',\r\n 'tracker.status': 'الحالة',\r\n 'tracker.priority': 'الأولوية',\r\n 'tracker.created': 'تاريخ الإنشاء',\r\n 'tracker.replies': 'الردود',\r\n 'tracker.noReplies': 'لا توجد ردود بعد.',\r\n 'tracker.replyPlaceholder': 'اكتب رداً...',\r\n 'tracker.sendReply': 'إرسال الرد',\r\n 'tracker.sending': 'جارِ الإرسال...',\r\n 'tracker.back': 'رجوع',\r\n 'tracker.staff': 'فريق الدعم',\r\n 'error.generic': 'حدث خطأ ما. يرجى المحاولة مرة أخرى.',\r\n 'error.network': 'خطأ في الشبكة. تحقق من اتصالك.',\r\n 'error.tokenInvalid': 'رمز التتبع غير صالح أو منتهي الصلاحية.',\r\n 'error.required': 'هذا الحقل مطلوب.',\r\n 'error.emailInvalid': 'يرجى إدخال بريد إلكتروني صالح.',\r\n 'error.titleMin': 'يجب أن يكون العنوان 5 أحرف على الأقل.',\r\n 'portal.title': 'بوابة الدعم',\r\n 'portal.myTickets': 'تذاكري',\r\n 'portal.noTickets': 'لا توجد تذاكر بعد.',\r\n 'portal.newTicket': 'تذكرة جديدة',\r\n 'widget.close': 'إغلاق',\r\n 'menu.newTicket': 'إرسال تذكرة',\r\n 'menu.newTicketDesc': 'إنشاء طلب ��عم جديد',\r\n 'menu.myTickets': 'تذاكري',\r\n 'menu.myTicketsDesc': 'عرض وإدارة تذاكرك',\r\n 'menu.trackTicket': 'تتبع تذكرة',\r\n 'menu.trackTicketDesc': 'تحقق من الحالة باستخدام رمز التتبع',\r\n 'menu.knowledgeBase': 'قاعدة المعرفة',\r\n 'menu.knowledgeBaseDesc': 'تصفح مقالات المساعدة والأدلة',\r\n 'menu.myTicketsPlaceholder': 'سجّل الدخول ��عرض تذاكرك.',\r\n 'menu.trackPlaceholder': 'تتبع التذاكر قريبًا.',\r\n 'menu.kbPlaceholder': 'قاعدة المعرفة قريبًا.',\r\n 'menu.preferences': 'التفضيلات',\r\n 'menu.preferencesDesc': 'إعدادات اللغة والمظهر',\r\n 'prefs.title': 'التفضيلات',\r\n 'prefs.language': 'اللغة',\r\n 'prefs.theme': 'المظهر',\r\n 'prefs.light': 'فاتح',\r\n 'prefs.dark': 'داكن',\r\n 'prefs.auto': 'النظام',\r\n 'branding.poweredBy': 'مدعوم من',\r\n 'attach.dropzone': 'اسحب الملفات هنا أو انقر للتصفح',\r\n 'attach.dropzoneActive': 'أفلت الملفات هنا',\r\n 'attach.maxFiles': 'بحد أقصى {max} ملفات',\r\n 'attach.remove': 'إزالة',\r\n 'attach.uploading': 'جارِ رفع الملفات...',\r\n 'attach.uploadProgress': 'جارِ رفع {name}... {percent}%',\r\n 'attach.invalidType': 'نوع الملف غير مسموح',\r\n 'attach.tooLarge': 'حجم الملف يتجاوز الحد الأقصى',\r\n 'attach.tooMany': 'تم الوصول للحد الأقصى لعدد الملفات',\r\n 'attach.download': 'تحميل',\r\n 'mytickets.title': 'تذاكري',\r\n 'mytickets.emailPrompt': 'أدخل بريدك الإلكتروني لعرض تذاكرك',\r\n 'mytickets.emailPlaceholder': 'your@email.com',\r\n 'mytickets.rememberMe': 'تذكرني',\r\n 'mytickets.lookup': 'البحث عن تذاكري',\r\n 'mytickets.lookingUp': 'جارِ البحث...',\r\n 'mytickets.noTickets': 'لا توجد تذاكر بعد.',\r\n 'mytickets.submitFirst': 'أرسل تذكرتك الأولى',\r\n 'mytickets.noAccount': 'لم يتم العثور على تذاكر لهذا البريد.',\r\n 'detail.description': 'الوصف',\r\n 'detail.attachments': 'المرفقات',\r\n 'detail.noAttachments': 'لا توجد مرفقات',\r\n 'detail.replies': 'المحادثة',\r\n 'detail.noReplies': 'لا توجد ردود بعد.',\r\n 'detail.replyPlaceholder': 'اكتب رداً...',\r\n 'detail.sendReply': 'إرسال',\r\n 'detail.sending': 'جارِ الإرسال...',\r\n 'detail.staff': 'فريق الدعم',\r\n 'detail.you': 'أنت',\r\n 'detail.loading': 'جارِ تحميل التذكرة...',\r\n 'track.title': 'تتبع تذكرة',\r\n 'track.tokenPlaceholder': 'أدخل رمز التتبع (trk_...)',\r\n 'track.submit': 'تتبع',\r\n 'track.tracking': 'جارِ التتبع...',\r\n 'track.recentTickets': 'التذاكر الأخيرة',\r\n 'track.invalidToken': 'رمز التتبع غير صالح أو منتهي.',\r\n 'prefs.clearEmail': 'مسح البريد المحفوظ',\r\n 'prefs.emailCleared': 'تم مسح البريد',\r\n 'auth.login': 'تسجيل الدخول',\r\n 'auth.logout': 'تسجيل الخروج',\r\n 'auth.sessionExpired': 'انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.',\r\n 'prefs.accentColor': 'لون التمييز',\r\n 'form.categoryPlaceholder': 'اختر فئة',\r\n 'form.categoryBack': 'رجوع',\r\n 'form.categorySelected': 'الفئة',\r\n 'diag.title': 'مشاركة معلومات التشخيص',\r\n 'diag.hint': 'ساعدنا في حل مشكلتك بشكل أسرع',\r\n 'diag.screenResolution': 'دقة الشاشة',\r\n 'diag.deviceType': 'نوع الجهاز',\r\n 'diag.timezone': 'المنطقة الزمنية',\r\n 'diag.referrerUrl': 'رابط المصدر',\r\n 'diag.language': 'لغة المتصفح',\r\n 'diag.platform': 'المنصة',\r\n 'detail.resolve': 'تحديد كمحلول',\r\n 'detail.resolving': 'جارِ الحل...',\r\n 'detail.resolved': 'محلول',\r\n 'detail.sla': 'اتفاقية الخدمة',\r\n}\r\n","import type { ThemeConfig } from './types'\r\n\r\nconst DEFAULT_THEME: Required<Omit<ThemeConfig, 'logo' | 'brandName' | 'hideBranding'>> & { logo?: string; brandName?: string; hideBranding?: boolean } = {\r\n primaryColor: '#42b983',\r\n mode: 'light',\r\n borderRadius: '8px',\r\n fontFamily: 'inherit',\r\n zIndex: 9999,\r\n}\r\n\r\nfunction resolveMode(mode: ThemeConfig['mode']): 'light' | 'dark' {\r\n if (mode === 'auto') {\r\n if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches) {\r\n return 'dark'\r\n }\r\n return 'light'\r\n }\r\n return mode ?? 'light'\r\n}\r\n\r\nexport function themeToVars(theme: ThemeConfig = {}): string {\r\n const t = { ...DEFAULT_THEME, ...theme, mode: resolveMode(theme.mode ?? DEFAULT_THEME.mode) }\r\n const hsl = hexToHsl(t.primaryColor)\r\n const lightL = Math.min(hsl.l + 30, 95)\r\n const darkL = Math.max(hsl.l - 15, 10)\r\n return [\r\n `--rqd-primary: ${t.primaryColor}`,\r\n `--rqd-primary-h: ${hsl.h}`,\r\n `--rqd-primary-s: ${hsl.s}%`,\r\n `--rqd-primary-l: ${hsl.l}%`,\r\n `--rqd-primary-light: hsl(${hsl.h}, ${hsl.s}%, ${lightL}%)`,\r\n `--rqd-primary-dark: hsl(${hsl.h}, ${hsl.s}%, ${darkL}%)`,\r\n `--rqd-radius: ${t.borderRadius}`,\r\n `--rqd-font: ${t.fontFamily}`,\r\n `--rqd-z: ${t.zIndex}`,\r\n `--rqd-bg: ${t.mode === 'dark' ? '#1a1a2e' : '#ffffff'}`,\r\n `--rqd-bg-secondary: ${t.mode === 'dark' ? '#16213e' : '#f8f9fa'}`,\r\n `--rqd-text: ${t.mode === 'dark' ? '#e0e0e0' : '#1a1a2e'}`,\r\n `--rqd-text-secondary: ${t.mode === 'dark' ? '#a0a0b0' : '#6c757d'}`,\r\n `--rqd-border: ${t.mode === 'dark' ? '#2a2a4a' : '#e0e0e0'}`,\r\n `--rqd-input-bg: ${t.mode === 'dark' ? '#0f3460' : '#ffffff'}`,\r\n `--rqd-shadow: ${t.mode === 'dark' ? '0 8px 32px rgba(0,0,0,0.4)' : '0 8px 32px rgba(0,0,0,0.12)'}`,\r\n ].join('; ')\r\n}\r\n\r\n/**\r\n * Returns CSS custom properties as a React-compatible style object.\r\n * React's `style` prop supports custom properties (--var) as keys directly.\r\n */\r\nexport function themeToStyle(theme: ThemeConfig = {}): Record<string, string | number> {\r\n const t = { ...DEFAULT_THEME, ...theme, mode: resolveMode(theme.mode ?? DEFAULT_THEME.mode) }\r\n const hsl = hexToHsl(t.primaryColor)\r\n const lightL = Math.min(hsl.l + 30, 95)\r\n const darkL = Math.max(hsl.l - 15, 10)\r\n return {\r\n '--rqd-primary': t.primaryColor,\r\n '--rqd-primary-h': String(hsl.h),\r\n '--rqd-primary-s': `${hsl.s}%`,\r\n '--rqd-primary-l': `${hsl.l}%`,\r\n '--rqd-primary-light': `hsl(${hsl.h}, ${hsl.s}%, ${lightL}%)`,\r\n '--rqd-primary-dark': `hsl(${hsl.h}, ${hsl.s}%, ${darkL}%)`,\r\n '--rqd-radius': t.borderRadius,\r\n '--rqd-font': t.fontFamily,\r\n '--rqd-z': t.zIndex,\r\n '--rqd-bg': t.mode === 'dark' ? '#1a1a2e' : '#ffffff',\r\n '--rqd-bg-secondary': t.mode === 'dark' ? '#16213e' : '#f8f9fa',\r\n '--rqd-text': t.mode === 'dark' ? '#e0e0e0' : '#1a1a2e',\r\n '--rqd-text-secondary': t.mode === 'dark' ? '#a0a0b0' : '#6c757d',\r\n '--rqd-border': t.mode === 'dark' ? '#2a2a4a' : '#e0e0e0',\r\n '--rqd-input-bg': t.mode === 'dark' ? '#0f3460' : '#ffffff',\r\n '--rqd-shadow': t.mode === 'dark' ? '0 8px 32px rgba(0,0,0,0.4)' : '0 8px 32px rgba(0,0,0,0.12)',\r\n }\r\n}\r\n\r\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\r\n if (!result) return { h: 160, s: 51, l: 49 }\r\n\r\n const r = parseInt(result[1], 16) / 255\r\n const g = parseInt(result[2], 16) / 255\r\n const b = parseInt(result[3], 16) / 255\r\n\r\n const max = Math.max(r, g, b)\r\n const min = Math.min(r, g, b)\r\n let h = 0\r\n let s = 0\r\n const l = (max + min) / 2\r\n\r\n if (max !== min) {\r\n const d = max - min\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\r\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\r\n else if (max === g) h = ((b - r) / d + 2) / 6\r\n else h = ((r - g) / d + 4) / 6\r\n }\r\n\r\n return {\r\n h: Math.round(h * 360),\r\n s: Math.round(s * 100),\r\n l: Math.round(l * 100),\r\n }\r\n}\r\n\r\nexport function getWidgetStyles(): string {\r\n return WIDGET_CSS\r\n}\r\n\r\nconst WIDGET_CSS = `:host { all: initial; }\r\n.rqd-root { font-family: var(--rqd-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif); font-size: 14px; line-height: 1.5; color: var(--rqd-text); -webkit-font-smoothing: antialiased; }\r\n.rqd-fab { position: fixed; bottom: 20px; width: 56px; height: 56px; border-radius: 50%; background: var(--rqd-primary); color: #fff; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 16px rgba(0,0,0,0.2); transition: transform 0.2s, box-shadow 0.2s; pointer-events: auto; z-index: var(--rqd-z, 9999); }\r\n.rqd-fab:hover { transform: scale(1.08); box-shadow: 0 6px 20px rgba(0,0,0,0.25); }\r\n.rqd-fab.rqd-bottom-right { right: 20px; }\r\n.rqd-fab.rqd-bottom-left { left: 20px; }\r\n.rqd-fab svg { width: 24px; height: 24px; fill: currentColor; }\r\n.rqd-panel { position: fixed; bottom: 88px; width: 380px; max-height: calc(100vh - 120px); background: var(--rqd-bg); border-radius: var(--rqd-radius); box-shadow: var(--rqd-shadow); overflow: hidden; display: flex; flex-direction: column; pointer-events: auto; animation: rqd-slide-up 0.25s ease-out; border: 1px solid var(--rqd-border); }\r\n.rqd-panel.rqd-bottom-right { right: 20px; }\r\n.rqd-panel.rqd-bottom-left { left: 20px; }\r\n.rqd-panel.rqd-hidden { display: none; }\r\n@keyframes rqd-slide-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }\r\n.rqd-header { display: flex; align-items: center; justify-content: space-between; padding: 16px; background: var(--rqd-primary); color: #fff; }\r\n.rqd-header-title { font-size: 16px; font-weight: 600; }\r\n.rqd-header-close { background: none; border: none; color: #fff; cursor: pointer; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.15s; }\r\n.rqd-header-close:hover { background: rgba(255,255,255,0.2); }\r\n.rqd-tabs { display: flex; border-bottom: 1px solid var(--rqd-border); }\r\n.rqd-tab { flex: 1; padding: 10px; text-align: center; background: none; border: none; cursor: pointer; font-size: 13px; font-weight: 500; color: var(--rqd-text-secondary); border-bottom: 2px solid transparent; transition: color 0.15s, border-color 0.15s; }\r\n.rqd-tab.rqd-active { color: var(--rqd-primary); border-bottom-color: var(--rqd-primary); }\r\n.rqd-body { flex: 1; overflow-y: auto; padding: 16px; }\r\n.rqd-form-group { margin-bottom: 14px; }\r\n.rqd-label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 4px; color: var(--rqd-text); }\r\n.rqd-input, .rqd-textarea, .rqd-select { width: 100%; padding: 8px 12px; border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 14px; font-family: inherit; background: var(--rqd-input-bg); color: var(--rqd-text); outline: none; transition: border-color 0.15s; box-sizing: border-box; }\r\n.rqd-input:focus, .rqd-textarea:focus, .rqd-select:focus { border-color: var(--rqd-primary); }\r\n.rqd-textarea { resize: vertical; min-height: 80px; }\r\n.rqd-error-text { color: #e74c3c; font-size: 12px; margin-top: 2px; }\r\n.rqd-btn { width: 100%; padding: 10px; border: none; border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 14px; font-weight: 600; cursor: pointer; transition: opacity 0.15s; }\r\n.rqd-btn:disabled { opacity: 0.6; cursor: not-allowed; }\r\n.rqd-btn-primary { background: var(--rqd-primary); color: #fff; }\r\n.rqd-btn-primary:hover:not(:disabled) { opacity: 0.9; }\r\n.rqd-btn-secondary { background: transparent; color: var(--rqd-primary); border: 1px solid var(--rqd-primary); }\r\n.rqd-success { text-align: center; padding: 24px 0; }\r\n.rqd-success-icon { font-size: 48px; margin-bottom: 12px; }\r\n.rqd-success h3 { margin: 0 0 8px; font-size: 18px; color: var(--rqd-text); }\r\n.rqd-token-box { background: var(--rqd-bg-secondary); border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 8px 12px; font-family: monospace; font-size: 12px; word-break: break-all; margin: 8px 0; color: var(--rqd-text); }\r\n.rqd-ticket-info { background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 12px; margin-bottom: 12px; }\r\n.rqd-ticket-row { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 13px; }\r\n.rqd-ticket-label { color: var(--rqd-text-secondary); }\r\n.rqd-badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; background: var(--rqd-primary-light); color: var(--rqd-primary-dark); }\r\n.rqd-reply { padding: 10px 0; border-bottom: 1px solid var(--rqd-border); }\r\n.rqd-reply:last-child { border-bottom: none; }\r\n.rqd-reply-header { display: flex; justify-content: space-between; font-size: 12px; color: var(--rqd-text-secondary); margin-bottom: 4px; }\r\n.rqd-reply-staff { color: var(--rqd-primary); font-weight: 600; }\r\n.rqd-reply-body { font-size: 14px; white-space: pre-wrap; }\r\n.rqd-inline { pointer-events: auto; background: var(--rqd-bg); border: 1px solid var(--rqd-border); border-radius: var(--rqd-radius); overflow: hidden; }\r\n.rqd-inline .rqd-body { max-height: none; }\r\n:host([dir=\"rtl\"]) .rqd-root { direction: rtl; text-align: right; }\r\n:host([dir=\"rtl\"]) .rqd-fab.rqd-bottom-right { right: auto; left: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-fab.rqd-bottom-left { left: auto; right: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-panel.rqd-bottom-right { right: auto; left: 20px; }\r\n:host([dir=\"rtl\"]) .rqd-panel.rqd-bottom-left { left: auto; right: 20px; }\r\n.rqd-menu { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-menu-item { display: flex; align-items: center; gap: 14px; width: 100%; padding: 14px 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 1.5); cursor: pointer; text-align: start; transition: border-color 0.15s, background 0.15s, transform 0.1s; font-family: inherit; color: var(--rqd-text); }\r\n.rqd-menu-item:hover { border-color: var(--rqd-primary); background: var(--rqd-bg); transform: translateY(-1px); }\r\n.rqd-menu-icon { width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; border-radius: calc(var(--rqd-radius, 8px) / 2); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); flex-shrink: 0; }\r\n.rqd-menu-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\r\n.rqd-menu-label { font-size: 14px; font-weight: 600; line-height: 1.3; }\r\n.rqd-menu-desc { font-size: 12px; color: var(--rqd-text-secondary); line-height: 1.3; }\r\n.rqd-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 40px 16px; color: var(--rqd-text-secondary); text-align: center; }\r\n.rqd-placeholder p { margin: 0; font-size: 14px; }\r\n.rqd-header-brand { display: flex; align-items: center; gap: 8px; min-width: 0; }\r\n.rqd-header-logo { width: 24px; height: 24px; border-radius: 4px; object-fit: contain; flex-shrink: 0; }\r\n.rqd-footer { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 8px 16px; border-top: 1px solid var(--rqd-border); font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-footer a { color: var(--rqd-text-secondary); text-decoration: none; font-weight: 600; transition: color 0.15s; }\r\n.rqd-footer a:hover { color: var(--rqd-primary); }\r\n.rqd-prefs { display: flex; flex-direction: column; gap: 16px; }\r\n.rqd-prefs-group { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-prefs-label { font-size: 13px; font-weight: 600; color: var(--rqd-text); }\r\n.rqd-prefs-options { display: flex; gap: 6px; }\r\n.rqd-prefs-option { flex: 1; padding: 8px 12px; background: var(--rqd-bg-secondary); border: 1px solid var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; text-align: center; font-size: 13px; font-family: inherit; color: var(--rqd-text); transition: border-color 0.15s, background 0.15s; }\r\n.rqd-prefs-option:hover { border-color: var(--rqd-primary); }\r\n.rqd-prefs-option.rqd-active { border-color: var(--rqd-primary); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); font-weight: 600; }\r\n.rqd-dropzone { border: 2px dashed var(--rqd-border); border-radius: calc(var(--rqd-radius, 8px) / 2); padding: 16px; text-align: center; cursor: pointer; transition: border-color 0.15s, background 0.15s; color: var(--rqd-text-secondary); font-size: 13px; margin-bottom: 14px; }\r\n.rqd-dropzone:hover { border-color: var(--rqd-primary); }\r\n.rqd-dropzone.rqd-dropzone-active { border-color: var(--rqd-primary); background: var(--rqd-primary-light); color: var(--rqd-primary-dark); }\r\n.rqd-file-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }\r\n.rqd-file-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; }\r\n.rqd-file-item-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\r\n.rqd-file-item-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\r\n.rqd-file-item-size { font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-file-remove { background: none; border: none; color: var(--rqd-text-secondary); cursor: pointer; padding: 4px; font-size: 16px; line-height: 1; flex-shrink: 0; }\r\n.rqd-file-remove:hover { color: #e74c3c; }\r\n.rqd-progress { width: 100%; height: 6px; background: var(--rqd-bg-secondary); border-radius: 3px; overflow: hidden; margin-top: 6px; }\r\n.rqd-progress-bar { height: 100%; background: var(--rqd-primary); border-radius: 3px; transition: width 0.2s ease; }\r\n.rqd-upload-status { font-size: 12px; color: var(--rqd-text-secondary); margin-top: 4px; }\r\n.rqd-attachment-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }\r\n.rqd-attachment-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; }\r\n.rqd-attachment-item a { color: var(--rqd-primary); text-decoration: none; font-weight: 500; font-size: 12px; flex-shrink: 0; }\r\n.rqd-attachment-item a:hover { text-decoration: underline; }\r\n.rqd-ticket-header { margin-bottom: 12px; }\r\n.rqd-ticket-header h3 { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--rqd-text); }\r\n.rqd-ticket-header-meta { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }\r\n.rqd-ticket-desc { font-size: 14px; color: var(--rqd-text); white-space: pre-wrap; margin-bottom: 16px; padding: 10px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); }\r\n.rqd-section-title { font-size: 13px; font-weight: 600; color: var(--rqd-text); margin-bottom: 8px; }\r\n.rqd-email-form { display: flex; flex-direction: column; gap: 12px; padding: 24px 0; }\r\n.rqd-email-form p { margin: 0; font-size: 14px; color: var(--rqd-text-secondary); text-align: center; }\r\n.rqd-checkbox-label { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--rqd-text-secondary); cursor: pointer; }\r\n.rqd-checkbox-label input[type=\"checkbox\"] { accent-color: var(--rqd-primary); width: 16px; height: 16px; cursor: pointer; }\r\n.rqd-ticket-card { display: flex; flex-direction: column; gap: 4px; padding: 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 1.5); cursor: pointer; transition: border-color 0.15s, transform 0.1s; }\r\n.rqd-ticket-card:hover { border-color: var(--rqd-primary); transform: translateY(-1px); }\r\n.rqd-ticket-card-top { display: flex; justify-content: space-between; align-items: center; }\r\n.rqd-ticket-card-number { font-size: 12px; font-weight: 600; color: var(--rqd-text-secondary); }\r\n.rqd-ticket-card-title { font-size: 14px; font-weight: 500; color: var(--rqd-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\r\n.rqd-ticket-card-date { font-size: 11px; color: var(--rqd-text-secondary); }\r\n.rqd-ticket-list { display: flex; flex-direction: column; gap: 6px; }\r\n.rqd-loading { text-align: center; padding: 24px 0; color: var(--rqd-text-secondary); font-size: 14px; }\r\n.rqd-reply-compose { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }\r\n.rqd-category-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px; }\r\n.rqd-category-item { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; background: var(--rqd-bg-secondary); border: 1px solid transparent; border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; font-size: 14px; font-family: inherit; color: var(--rqd-text); transition: border-color 0.15s, background 0.15s; text-align: start; width: 100%; }\r\n.rqd-category-item:hover { border-color: var(--rqd-primary); }\r\n.rqd-category-item-chevron { color: var(--rqd-text-secondary); font-size: 16px; }\r\n.rqd-category-breadcrumb { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; font-size: 12px; color: var(--rqd-text-secondary); }\r\n.rqd-category-breadcrumb button { background: none; border: none; color: var(--rqd-primary); cursor: pointer; font-size: 12px; font-family: inherit; padding: 0; }\r\n.rqd-category-breadcrumb button:hover { text-decoration: underline; }\r\n.rqd-category-breadcrumb-sep { color: var(--rqd-text-secondary); }\r\n.rqd-category-selected { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--rqd-primary-light); border-radius: calc(var(--rqd-radius, 8px) / 2); font-size: 13px; color: var(--rqd-primary-dark); margin-bottom: 14px; }\r\n.rqd-category-selected button { background: none; border: none; color: var(--rqd-primary-dark); cursor: pointer; font-size: 14px; margin-left: auto; padding: 0; }\r\n.rqd-diag-toggle { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; background: var(--rqd-bg-secondary); border-radius: calc(var(--rqd-radius, 8px) / 2); cursor: pointer; font-size: 13px; color: var(--rqd-text-secondary); border: none; width: 100%; font-family: inherit; text-align: start; margin-bottom: 8px; }\r\n.rqd-diag-toggle:hover { color: var(--rqd-text); }\r\n.rqd-diag-panel { display: flex; flex-direction: column; gap: 6px; padding: 8px 0; }\r\n.rqd-diag-item { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--rqd-text-secondary); }\r\n.rqd-diag-item input[type=\"checkbox\"] { accent-color: var(--rqd-primary); width: 14px; height: 14px; }\r\n.rqd-diag-item-value { color: var(--rqd-text); font-family: monospace; font-size: 11px; margin-left: auto; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\r\n.rqd-auth-btn { background: rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.4); color: #fff; cursor: pointer; padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: 500; font-family: inherit; transition: background 0.15s; white-space: nowrap; }\r\n.rqd-auth-btn:hover { background: rgba(255,255,255,0.3); }\r\n.rqd-color-presets { display: flex; gap: 8px; flex-wrap: wrap; }\r\n.rqd-color-preset { width: 28px; height: 28px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; transition: transform 0.15s, box-shadow 0.15s; padding: 0; }\r\n.rqd-color-preset:hover { transform: scale(1.15); }\r\n.rqd-color-preset.rqd-active { box-shadow: 0 0 0 3px var(--rqd-bg), 0 0 0 5px currentColor; }\r\n.rqd-contained.rqd-fab { position: absolute; }\r\n.rqd-contained.rqd-panel { position: absolute; }\r\n@media (max-width: 440px) { .rqd-panel { width: calc(100vw - 24px); right: 12px !important; left: 12px !important; bottom: 76px; } .rqd-fab { bottom: 12px; } .rqd-fab.rqd-bottom-right { right: 12px; } .rqd-fab.rqd-bottom-left { left: 12px; } }\r\n`\r\n","export interface WidgetConfigPersist {\r\n position?: 'bottom-right' | 'bottom-left'\r\n language?: string\r\n theme?: { primaryColor?: string; mode?: 'light' | 'dark' | 'auto' }\r\n widget?: 'ticket-form' | 'support-portal'\r\n}\r\n\r\nconst STORAGE_PREFIX = 'reqdesk_'\r\n\r\nfunction getStorage(): Storage | null {\r\n try {\r\n const s = window.localStorage\r\n s.setItem('__test__', '1')\r\n s.removeItem('__test__')\r\n return s\r\n } catch {\r\n try {\r\n return window.sessionStorage\r\n } catch {\r\n return null\r\n }\r\n }\r\n}\r\n\r\nexport function saveTrackingToken(projectSlug: string, token: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n\r\n const key = `${STORAGE_PREFIX}tokens_${projectSlug}`\r\n try {\r\n const existing = JSON.parse(storage.getItem(key) ?? '[]') as string[]\r\n if (!existing.includes(token)) {\r\n existing.push(token)\r\n storage.setItem(key, JSON.stringify(existing))\r\n }\r\n } catch {\r\n storage.setItem(key, JSON.stringify([token]))\r\n }\r\n}\r\n\r\nexport function getTrackingTokens(projectSlug: string): string[] {\r\n const storage = getStorage()\r\n if (!storage) return []\r\n\r\n const key = `${STORAGE_PREFIX}tokens_${projectSlug}`\r\n try {\r\n return JSON.parse(storage.getItem(key) ?? '[]') as string[]\r\n } catch {\r\n return []\r\n }\r\n}\r\n\r\nexport function saveWidgetConfig(apiKey: string, config: WidgetConfigPersist): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n\r\n const key = `${STORAGE_PREFIX}config_${apiKey}`\r\n try {\r\n const existing = loadWidgetConfig(apiKey)\r\n const merged = { ...existing, ...config }\r\n if (config.theme && existing?.theme) {\r\n merged.theme = { ...existing.theme, ...config.theme }\r\n }\r\n storage.setItem(key, JSON.stringify(merged))\r\n } catch {\r\n // Silently fail if storage is full or unavailable\r\n }\r\n}\r\n\r\nexport function saveWidgetEmail(apiKey: string, email: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n try {\r\n storage.setItem(`${STORAGE_PREFIX}email_${apiKey}`, email)\r\n } catch { /* ignore */ }\r\n}\r\n\r\nexport function loadWidgetEmail(apiKey: string): string | null {\r\n const storage = getStorage()\r\n if (!storage) return null\r\n try {\r\n return storage.getItem(`${STORAGE_PREFIX}email_${apiKey}`)\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport function clearWidgetEmail(apiKey: string): void {\r\n const storage = getStorage()\r\n if (!storage) return\r\n try {\r\n storage.removeItem(`${STORAGE_PREFIX}email_${apiKey}`)\r\n } catch { /* ignore */ }\r\n}\r\n\r\nexport function loadWidgetConfig(apiKey: string): WidgetConfigPersist | null {\r\n const storage = getStorage()\r\n if (!storage) return null\r\n\r\n const key = `${STORAGE_PREFIX}config_${apiKey}`\r\n try {\r\n const raw = storage.getItem(key)\r\n if (!raw) return null\r\n return JSON.parse(raw) as WidgetConfigPersist\r\n } catch {\r\n return null\r\n }\r\n}\r\n"],"mappings":"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"}
|