@reqdesk/widget 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"react-8GCnIHnw.d.cts","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"}
1
+ {"version":3,"file":"react-SJ0r-FEh.d.cts","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,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_storage = require("./storage-Db9XjupR.cjs");
2
+ const require_storage = require("./storage-Cx5p1yP-.cjs");
3
3
  let react = require("react");
4
4
  let _tanstack_react_query = require("@tanstack/react-query");
5
5
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -32,7 +32,11 @@ function onAuthStateChange(listener) {
32
32
  listeners = listeners.filter((l) => l !== listener);
33
33
  };
34
34
  }
35
- async function initWidgetAuth(config) {
35
+ function initWidgetAuth(config) {
36
+ initPromise = _initWidgetAuth(config);
37
+ return initPromise;
38
+ }
39
+ async function _initWidgetAuth(config) {
36
40
  setState({ isLoading: true });
37
41
  try {
38
42
  const { createOidc } = await import("oidc-spa/core");
@@ -69,8 +73,13 @@ async function initWidgetAuth(config) {
69
73
  });
70
74
  }
71
75
  }
76
+ let initPromise = null;
72
77
  async function login() {
73
- if (!oidcInstance) return;
78
+ if (!oidcInstance && initPromise) await initPromise;
79
+ if (!oidcInstance) {
80
+ console.warn("[reqdesk-widget] Cannot login: OIDC not initialized. Check auth config.");
81
+ return;
82
+ }
74
83
  await oidcInstance.login({ doesCurrentHrefRequiresAuth: false });
75
84
  }
76
85
  async function logout() {
@@ -298,7 +307,7 @@ function TicketForm({ mode = "inline", onTicketCreated, onError, className, styl
298
307
  onError,
299
308
  t
300
309
  ]);
301
- const cssVars = require_storage.themeToVars(ctx.theme);
310
+ const cssVars = require_storage.themeToStyle(ctx.theme);
302
311
  const content = success ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
303
312
  className: "rqd-success",
304
313
  style: {
@@ -436,7 +445,7 @@ function TicketForm({ mode = "inline", onTicketCreated, onError, className, styl
436
445
  className,
437
446
  style: {
438
447
  ...style,
439
- cssText: cssVars
448
+ ...cssVars
440
449
  },
441
450
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
442
451
  className: "rqd-body",
@@ -445,7 +454,7 @@ function TicketForm({ mode = "inline", onTicketCreated, onError, className, styl
445
454
  }) });
446
455
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShadowRoot, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
447
456
  className: `rqd-inline ${className ?? ""}`,
448
- style: { cssText: cssVars },
457
+ style: cssVars,
449
458
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
450
459
  className: "rqd-body",
451
460
  children: content
@@ -457,10 +466,10 @@ function TicketForm({ mode = "inline", onTicketCreated, onError, className, styl
457
466
  function SupportPortal({ className }) {
458
467
  const ctx = useReqdeskContext();
459
468
  const { isLoading } = useReqdesk();
460
- const cssVars = require_storage.themeToVars(ctx.theme);
469
+ const cssVars = require_storage.themeToStyle(ctx.theme);
461
470
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShadowRoot, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
462
471
  className: `rqd-inline ${className ?? ""}`,
463
- style: { cssText: cssVars },
472
+ style: cssVars,
464
473
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
465
474
  className: "rqd-body",
466
475
  children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -481,6 +490,132 @@ function SupportPortal({ className }) {
481
490
  }) });
482
491
  }
483
492
  //#endregion
493
+ //#region src/react/queries.ts
494
+ const widgetTicketDetailOptions = (ticketId) => (0, _tanstack_react_query.queryOptions)({
495
+ queryKey: ["widget-ticket", ticketId],
496
+ queryFn: () => require_storage.getTicketDetail(ticketId),
497
+ staleTime: 6e4,
498
+ enabled: !!ticketId
499
+ });
500
+ const widgetMyTicketsOptions = (projectId, userId) => (0, _tanstack_react_query.queryOptions)({
501
+ queryKey: [
502
+ "widget-tickets",
503
+ projectId,
504
+ userId
505
+ ],
506
+ queryFn: () => require_storage.listMyTickets(projectId, userId),
507
+ staleTime: 3e4,
508
+ placeholderData: _tanstack_react_query.keepPreviousData,
509
+ enabled: !!userId
510
+ });
511
+ const widgetUserOptions = (projectId, email) => (0, _tanstack_react_query.queryOptions)({
512
+ queryKey: [
513
+ "widget-user",
514
+ projectId,
515
+ email
516
+ ],
517
+ queryFn: () => require_storage.resolveWidgetUser(projectId, email),
518
+ staleTime: 5 * 6e4,
519
+ enabled: !!email
520
+ });
521
+ const widgetCategoriesOptions = (projectId, parentId) => (0, _tanstack_react_query.queryOptions)({
522
+ queryKey: [
523
+ "widget-categories",
524
+ projectId,
525
+ parentId ?? "root"
526
+ ],
527
+ queryFn: () => require_storage.getCategories(projectId, parentId),
528
+ staleTime: 5 * 6e4
529
+ });
530
+ //#endregion
531
+ //#region src/client-metadata.ts
532
+ const STORAGE_PREFIX = "reqdesk_diag_";
533
+ const DEFAULT_PREFS = {
534
+ screenResolution: false,
535
+ deviceType: false,
536
+ timezone: false,
537
+ referrerUrl: false,
538
+ language: false,
539
+ platform: false
540
+ };
541
+ /** Always collected — minimal, non-sensitive */
542
+ function collectMinimalMetadata() {
543
+ const meta = {};
544
+ try {
545
+ meta.pageUrl = window.location.href;
546
+ meta.userAgent = navigator.userAgent;
547
+ } catch {}
548
+ return meta;
549
+ }
550
+ /** Full diagnostic set — only included for opted-in fields */
551
+ function collectDiagnosticMetadata(prefs) {
552
+ const meta = {};
553
+ try {
554
+ if (prefs.screenResolution) meta.screenResolution = `${screen.width}x${screen.height}`;
555
+ if (prefs.deviceType) meta.deviceType = detectDeviceType();
556
+ if (prefs.timezone) meta.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
557
+ if (prefs.referrerUrl && document.referrer) meta.referrerUrl = document.referrer;
558
+ if (prefs.language) meta.language = navigator.language;
559
+ if (prefs.platform) meta.platform = navigator.platform;
560
+ } catch {}
561
+ return meta;
562
+ }
563
+ /** Combine minimal + opted-in diagnostic metadata */
564
+ function collectAllMetadata(apiKey) {
565
+ const prefs = getMetadataPreferences(apiKey);
566
+ return {
567
+ ...collectMinimalMetadata(),
568
+ ...collectDiagnosticMetadata(prefs)
569
+ };
570
+ }
571
+ function getMetadataPreferences(apiKey) {
572
+ try {
573
+ const raw = localStorage.getItem(`${STORAGE_PREFIX}${apiKey}`);
574
+ if (raw) return {
575
+ ...DEFAULT_PREFS,
576
+ ...JSON.parse(raw)
577
+ };
578
+ } catch {}
579
+ return { ...DEFAULT_PREFS };
580
+ }
581
+ function saveMetadataPreferences(apiKey, prefs) {
582
+ try {
583
+ localStorage.setItem(`${STORAGE_PREFIX}${apiKey}`, JSON.stringify(prefs));
584
+ } catch {}
585
+ }
586
+ function detectDeviceType() {
587
+ const ua = navigator.userAgent.toLowerCase();
588
+ if (/tablet|ipad|playbook|silk/i.test(ua)) return "tablet";
589
+ if (/mobile|iphone|ipod|android.*mobile|windows phone/i.test(ua)) return "mobile";
590
+ return "desktop";
591
+ }
592
+ const DIAGNOSTIC_FIELDS = [
593
+ {
594
+ key: "screenResolution",
595
+ labelKey: "diag.screenResolution"
596
+ },
597
+ {
598
+ key: "deviceType",
599
+ labelKey: "diag.deviceType"
600
+ },
601
+ {
602
+ key: "timezone",
603
+ labelKey: "diag.timezone"
604
+ },
605
+ {
606
+ key: "referrerUrl",
607
+ labelKey: "diag.referrerUrl"
608
+ },
609
+ {
610
+ key: "language",
611
+ labelKey: "diag.language"
612
+ },
613
+ {
614
+ key: "platform",
615
+ labelKey: "diag.platform"
616
+ }
617
+ ];
618
+ //#endregion
484
619
  //#region src/react/views/SubmitTicketView.tsx
485
620
  const translations$4 = {
486
621
  en: require_storage.en,
@@ -530,6 +665,19 @@ function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, user
530
665
  const [uploadProgress, setUploadProgress] = (0, react.useState)(null);
531
666
  const [success, setSuccess] = (0, react.useState)(null);
532
667
  const [rememberEmail, setRememberEmail] = (0, react.useState)(!!savedEmail);
668
+ const [categoryPath, setCategoryPath] = (0, react.useState)([]);
669
+ const [selectedCategory, setSelectedCategory] = (0, react.useState)(null);
670
+ const { data: categories = [] } = (0, _tanstack_react_query.useQuery)(widgetCategoriesOptions(projectId, categoryPath.length > 0 ? categoryPath[categoryPath.length - 1].id : null));
671
+ const [diagOpen, setDiagOpen] = (0, react.useState)(false);
672
+ const [diagPrefs, setDiagPrefs] = (0, react.useState)(getMetadataPreferences(ctx.apiKey));
673
+ const diagValues = collectDiagnosticMetadata({
674
+ screenResolution: true,
675
+ deviceType: true,
676
+ timezone: true,
677
+ referrerUrl: true,
678
+ language: true,
679
+ platform: true
680
+ });
533
681
  const t = (0, react.useCallback)((key) => {
534
682
  if (ctx.translations?.[key]) return ctx.translations[key];
535
683
  return (translations$4[ctx.language] ?? translations$4.en)[key] ?? key;
@@ -616,12 +764,15 @@ function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, user
616
764
  }
617
765
  setErrors({});
618
766
  if (rememberEmail && email) require_storage.saveWidgetEmail(ctx.apiKey, email);
767
+ saveMetadataPreferences(ctx.apiKey, diagPrefs);
619
768
  const validFiles = files.filter((f) => !f.error);
620
769
  const data = {
621
770
  title,
622
771
  description: formData.get("description")?.trim() || void 0,
623
772
  email,
624
- priority: formData.get("priority") ?? "medium"
773
+ priority: formData.get("priority") ?? "medium",
774
+ categoryId: selectedCategory?.id,
775
+ clientMetadata: collectAllMetadata(ctx.apiKey)
625
776
  };
626
777
  submitMutation.mutate({
627
778
  data,
@@ -802,6 +953,97 @@ function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, user
802
953
  ]
803
954
  })]
804
955
  }),
956
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
957
+ className: "rqd-form-group",
958
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
959
+ className: "rqd-label",
960
+ children: t("form.categorySelected")
961
+ }), selectedCategory ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
962
+ className: "rqd-category-selected",
963
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
964
+ categoryPath.map((c) => c.name).join(" > "),
965
+ categoryPath.length > 0 ? " > " : "",
966
+ selectedCategory.name
967
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
968
+ type: "button",
969
+ onClick: () => {
970
+ setSelectedCategory(null);
971
+ setCategoryPath([]);
972
+ },
973
+ children: "×"
974
+ })]
975
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [categoryPath.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
976
+ className: "rqd-category-breadcrumb",
977
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
978
+ type: "button",
979
+ onClick: () => setCategoryPath([]),
980
+ children: t("form.categoryPlaceholder")
981
+ }), categoryPath.map((c, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
982
+ className: "rqd-category-breadcrumb-sep",
983
+ children: "›"
984
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
985
+ type: "button",
986
+ onClick: () => setCategoryPath((prev) => prev.slice(0, i + 1)),
987
+ children: c.name
988
+ })] }, c.id))]
989
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
990
+ className: "rqd-category-list",
991
+ children: [categories.map((cat) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
992
+ type: "button",
993
+ className: "rqd-category-item",
994
+ onClick: () => {
995
+ if (cat.hasChildren) setCategoryPath((prev) => [...prev, cat]);
996
+ else setSelectedCategory(cat);
997
+ },
998
+ children: [cat.name, cat.hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
999
+ className: "rqd-category-item-chevron",
1000
+ children: "›"
1001
+ })]
1002
+ }, cat.id)), categories.length === 0 && categoryPath.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1003
+ style: {
1004
+ fontSize: 13,
1005
+ color: "var(--rqd-text-secondary)"
1006
+ },
1007
+ children: t("form.categoryPlaceholder")
1008
+ })]
1009
+ })] })]
1010
+ }),
1011
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1012
+ className: "rqd-form-group",
1013
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1014
+ type: "button",
1015
+ className: "rqd-diag-toggle",
1016
+ onClick: () => setDiagOpen((prev) => !prev),
1017
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("diag.title") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: diagOpen ? "▲" : "▼" })]
1018
+ }), diagOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1019
+ className: "rqd-diag-panel",
1020
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1021
+ style: {
1022
+ fontSize: 12,
1023
+ color: "var(--rqd-text-secondary)",
1024
+ margin: "0 0 6px"
1025
+ },
1026
+ children: t("diag.hint")
1027
+ }), DIAGNOSTIC_FIELDS.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1028
+ className: "rqd-diag-item",
1029
+ children: [
1030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1031
+ type: "checkbox",
1032
+ checked: diagPrefs[field.key],
1033
+ onChange: (e) => setDiagPrefs((prev) => ({
1034
+ ...prev,
1035
+ [field.key]: e.target.checked
1036
+ }))
1037
+ }),
1038
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(field.labelKey) }),
1039
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1040
+ className: "rqd-diag-item-value",
1041
+ children: diagValues[field.key] ?? "—"
1042
+ })
1043
+ ]
1044
+ }, field.key))]
1045
+ })]
1046
+ }),
805
1047
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
806
1048
  className: "rqd-form-group",
807
1049
  children: [
@@ -865,35 +1107,6 @@ function SubmitTicketView({ projectId, onSuccess, onError, isAuthenticated, user
865
1107
  });
866
1108
  }
867
1109
  //#endregion
868
- //#region src/react/queries.ts
869
- const widgetTicketDetailOptions = (ticketId) => (0, _tanstack_react_query.queryOptions)({
870
- queryKey: ["widget-ticket", ticketId],
871
- queryFn: () => require_storage.getTicketDetail(ticketId),
872
- staleTime: 6e4,
873
- enabled: !!ticketId
874
- });
875
- const widgetMyTicketsOptions = (projectId, userId) => (0, _tanstack_react_query.queryOptions)({
876
- queryKey: [
877
- "widget-tickets",
878
- projectId,
879
- userId
880
- ],
881
- queryFn: () => require_storage.listMyTickets(projectId, userId),
882
- staleTime: 3e4,
883
- placeholderData: _tanstack_react_query.keepPreviousData,
884
- enabled: !!userId
885
- });
886
- const widgetUserOptions = (projectId, email) => (0, _tanstack_react_query.queryOptions)({
887
- queryKey: [
888
- "widget-user",
889
- projectId,
890
- email
891
- ],
892
- queryFn: () => require_storage.resolveWidgetUser(projectId, email),
893
- staleTime: 5 * 6e4,
894
- enabled: !!email
895
- });
896
- //#endregion
897
1110
  //#region src/react/views/MyTicketsView.tsx
898
1111
  const translations$3 = {
899
1112
  en: require_storage.en,
@@ -1075,6 +1288,24 @@ function TicketDetailView({ ticketId, onBack }) {
1075
1288
  if (context?.previous) queryClient.setQueryData(["widget-ticket", ticketId], context.previous);
1076
1289
  }
1077
1290
  });
1291
+ const resolveMutation = (0, _tanstack_react_query.useMutation)({
1292
+ mutationFn: () => require_storage.closeTicket(ticketId),
1293
+ onMutate: async () => {
1294
+ await queryClient.cancelQueries({ queryKey: ["widget-ticket", ticketId] });
1295
+ const previous = queryClient.getQueryData(["widget-ticket", ticketId]);
1296
+ if (previous) queryClient.setQueryData(["widget-ticket", ticketId], {
1297
+ ...previous,
1298
+ status: "resolved"
1299
+ });
1300
+ return { previous };
1301
+ },
1302
+ onSuccess: () => {
1303
+ queryClient.invalidateQueries({ queryKey: ["widget-ticket", ticketId] });
1304
+ },
1305
+ onError: (_err, _vars, context) => {
1306
+ if (context?.previous) queryClient.setQueryData(["widget-ticket", ticketId], context.previous);
1307
+ }
1308
+ });
1078
1309
  if (isLoading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1079
1310
  className: "rqd-loading",
1080
1311
  children: t("detail.loading")
@@ -1183,11 +1414,28 @@ function TicketDetailView({ ticketId, onBack }) {
1183
1414
  onChange: (e) => setReplyBody(e.target.value),
1184
1415
  placeholder: t("detail.replyPlaceholder"),
1185
1416
  rows: 3
1186
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1187
- className: "rqd-btn rqd-btn-primary",
1188
- onClick: () => replyMutation.mutate(replyBody.trim()),
1189
- disabled: !replyBody.trim() || replyMutation.isPending,
1190
- children: replyMutation.isPending ? t("detail.sending") : t("detail.sendReply")
1417
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1418
+ style: {
1419
+ display: "flex",
1420
+ gap: 8
1421
+ },
1422
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1423
+ className: "rqd-btn rqd-btn-primary",
1424
+ style: { flex: 1 },
1425
+ onClick: () => replyMutation.mutate(replyBody.trim()),
1426
+ disabled: !replyBody.trim() || replyMutation.isPending,
1427
+ children: replyMutation.isPending ? t("detail.sending") : t("detail.sendReply")
1428
+ }), ticket.status !== "resolved" && ticket.status !== "closed" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1429
+ className: "rqd-btn rqd-btn-secondary",
1430
+ style: {
1431
+ flex: 0,
1432
+ whiteSpace: "nowrap",
1433
+ padding: "10px 16px"
1434
+ },
1435
+ onClick: () => resolveMutation.mutate(),
1436
+ disabled: resolveMutation.isPending,
1437
+ children: resolveMutation.isPending ? t("detail.resolving") : t("detail.resolve")
1438
+ })]
1191
1439
  })]
1192
1440
  })
1193
1441
  ] });
@@ -1314,7 +1562,7 @@ function FloatingWidget({ position = "bottom-right", contained = false, onTicket
1314
1562
  return (translations[activeLang] ?? translations.en)[key] ?? key;
1315
1563
  }, [activeLang, ctx.translations]);
1316
1564
  const isRtl = activeLang === "ar";
1317
- const cssVars = require_storage.themeToVars(activeTheme);
1565
+ const cssVars = require_storage.themeToStyle(activeTheme);
1318
1566
  const posClass = `rqd-${position}`;
1319
1567
  const containedClass = contained ? " rqd-contained" : "";
1320
1568
  const brandName = ctx.theme?.brandName;
@@ -1556,7 +1804,7 @@ function FloatingWidget({ position = "bottom-right", contained = false, onTicket
1556
1804
  const canGoBack = view !== "home";
1557
1805
  const goBackTarget = view === "ticket-detail" ? "my-tickets" : "home";
1558
1806
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShadowRoot, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1559
- style: { cssText: cssVars },
1807
+ style: cssVars,
1560
1808
  ...isRtl ? { dir: "rtl" } : {},
1561
1809
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1562
1810
  className: `rqd-fab ${posClass}${containedClass}`,
package/dist/react.d.cts CHANGED
@@ -1 +1 @@
1
- export * from './react-8GCnIHnw.cjs';
1
+ export * from './react-SJ0r-FEh.cjs';
package/dist/react.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './react-D69QlAm1.js';
1
+ export * from './react-BLAoKiUb.js';