@mhosaic/feedback 0.7.0 → 0.7.2
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/{chunk-W6JAJT2U.mjs → chunk-2TLTE2VZ.mjs} +210 -26
- package/dist/chunk-2TLTE2VZ.mjs.map +1 -0
- package/dist/embed.min.js +143 -30
- package/dist/embed.min.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-W6JAJT2U.mjs.map +0 -1
|
@@ -486,6 +486,12 @@ var DEFAULT_STRINGS = {
|
|
|
486
486
|
"detail.close_cta": "Mark as resolved",
|
|
487
487
|
"detail.close_busy": "Marking\u2026",
|
|
488
488
|
"detail.history": "Status history",
|
|
489
|
+
"detail.context.submitted_at": "Submitted",
|
|
490
|
+
"detail.context.page": "Page",
|
|
491
|
+
"detail.context.capture.manual": "Manual capture",
|
|
492
|
+
"detail.context.capture.html2canvas": "Auto capture",
|
|
493
|
+
"detail.context.capture.display_media": "Screen share",
|
|
494
|
+
"detail.context.capture.none": "No screenshot",
|
|
489
495
|
"detail.author.staff": "Operator",
|
|
490
496
|
"detail.author.mcp": "Mhosaic Team",
|
|
491
497
|
"detail.author.system": "System",
|
|
@@ -559,6 +565,12 @@ var FRENCH_STRINGS = {
|
|
|
559
565
|
"detail.close_cta": "Marquer comme r\xE9solu",
|
|
560
566
|
"detail.close_busy": "Validation\u2026",
|
|
561
567
|
"detail.history": "Historique du statut",
|
|
568
|
+
"detail.context.submitted_at": "Envoy\xE9",
|
|
569
|
+
"detail.context.page": "Page",
|
|
570
|
+
"detail.context.capture.manual": "Capture manuelle",
|
|
571
|
+
"detail.context.capture.html2canvas": "Capture automatique",
|
|
572
|
+
"detail.context.capture.display_media": "Partage d\u2019\xE9cran",
|
|
573
|
+
"detail.context.capture.none": "Sans capture",
|
|
562
574
|
"detail.author.staff": "Op\xE9rateur",
|
|
563
575
|
"detail.author.mcp": "\xC9quipe Mhosaic",
|
|
564
576
|
"detail.author.system": "Syst\xE8me",
|
|
@@ -593,8 +605,28 @@ import { useCallback } from "preact/hooks";
|
|
|
593
605
|
|
|
594
606
|
// src/widget/Fab.tsx
|
|
595
607
|
import { jsx } from "preact/jsx-runtime";
|
|
608
|
+
function ChatBubbleIcon() {
|
|
609
|
+
return /* @__PURE__ */ jsx(
|
|
610
|
+
"svg",
|
|
611
|
+
{
|
|
612
|
+
width: "24",
|
|
613
|
+
height: "24",
|
|
614
|
+
viewBox: "0 0 24 24",
|
|
615
|
+
fill: "none",
|
|
616
|
+
"aria-hidden": "true",
|
|
617
|
+
focusable: "false",
|
|
618
|
+
children: /* @__PURE__ */ jsx(
|
|
619
|
+
"path",
|
|
620
|
+
{
|
|
621
|
+
d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z",
|
|
622
|
+
fill: "currentColor"
|
|
623
|
+
}
|
|
624
|
+
)
|
|
625
|
+
}
|
|
626
|
+
);
|
|
627
|
+
}
|
|
596
628
|
function Fab({ label, onClick }) {
|
|
597
|
-
return /* @__PURE__ */ jsx("button", { type: "button", class: "fab", "aria-label": label, onClick, children:
|
|
629
|
+
return /* @__PURE__ */ jsx("button", { type: "button", class: "fab", "aria-label": label, title: label, onClick, children: /* @__PURE__ */ jsx(ChatBubbleIcon, {}) });
|
|
598
630
|
}
|
|
599
631
|
|
|
600
632
|
// src/widget/Form.tsx
|
|
@@ -1464,6 +1496,7 @@ function ReportDetailView({
|
|
|
1464
1496
|
/* @__PURE__ */ jsx8("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status })
|
|
1465
1497
|
] }),
|
|
1466
1498
|
/* @__PURE__ */ jsxs7("div", { class: "report-detail-body", children: [
|
|
1499
|
+
/* @__PURE__ */ jsx8(ContextBlock, { detail, strings }),
|
|
1467
1500
|
/* @__PURE__ */ jsx8("p", { class: "report-detail-description", children: detail.description }),
|
|
1468
1501
|
detail.screenshot_url && /* @__PURE__ */ jsx8(
|
|
1469
1502
|
"a",
|
|
@@ -1518,6 +1551,44 @@ function appendComment(current, next) {
|
|
|
1518
1551
|
if (current.some((c) => c.id === next.id)) return current;
|
|
1519
1552
|
return [...current, next];
|
|
1520
1553
|
}
|
|
1554
|
+
function ContextBlock({ detail, strings }) {
|
|
1555
|
+
const captureKey = `detail.context.capture.${detail.capture_method}`;
|
|
1556
|
+
const captureLabel = strings[captureKey] ?? detail.capture_method;
|
|
1557
|
+
return /* @__PURE__ */ jsxs7("div", { class: "report-detail-context", children: [
|
|
1558
|
+
/* @__PURE__ */ jsxs7("div", { class: "report-detail-context-pills", children: [
|
|
1559
|
+
/* @__PURE__ */ jsx8("span", { class: "pill pill-type", children: strings[`type.${detail.feedback_type}`] }),
|
|
1560
|
+
/* @__PURE__ */ jsx8("span", { class: `pill pill-severity pill-severity--${detail.severity}`, children: strings[`severity.${detail.severity}`] }),
|
|
1561
|
+
/* @__PURE__ */ jsx8("span", { class: "pill pill-capture", children: captureLabel })
|
|
1562
|
+
] }),
|
|
1563
|
+
/* @__PURE__ */ jsxs7("div", { class: "report-detail-context-line", children: [
|
|
1564
|
+
/* @__PURE__ */ jsx8("span", { class: "report-detail-context-label", children: strings["detail.context.submitted_at"] }),
|
|
1565
|
+
/* @__PURE__ */ jsx8("span", { children: formatSubmittedAt(detail.created_at) })
|
|
1566
|
+
] }),
|
|
1567
|
+
detail.page_url && /* @__PURE__ */ jsxs7("div", { class: "report-detail-context-line", title: detail.page_url, children: [
|
|
1568
|
+
/* @__PURE__ */ jsx8("span", { class: "report-detail-context-label", children: strings["detail.context.page"] }),
|
|
1569
|
+
/* @__PURE__ */ jsx8(
|
|
1570
|
+
"a",
|
|
1571
|
+
{
|
|
1572
|
+
class: "report-detail-context-url",
|
|
1573
|
+
href: detail.page_url,
|
|
1574
|
+
target: "_blank",
|
|
1575
|
+
rel: "noopener noreferrer",
|
|
1576
|
+
children: truncateUrl(detail.page_url, 64)
|
|
1577
|
+
}
|
|
1578
|
+
)
|
|
1579
|
+
] })
|
|
1580
|
+
] });
|
|
1581
|
+
}
|
|
1582
|
+
function formatSubmittedAt(iso) {
|
|
1583
|
+
try {
|
|
1584
|
+
return new Date(iso).toLocaleString(void 0, {
|
|
1585
|
+
dateStyle: "medium",
|
|
1586
|
+
timeStyle: "short"
|
|
1587
|
+
});
|
|
1588
|
+
} catch {
|
|
1589
|
+
return iso;
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1521
1592
|
|
|
1522
1593
|
// src/widget/styles.ts
|
|
1523
1594
|
var WIDGET_STYLES = `
|
|
@@ -1550,28 +1621,60 @@ var WIDGET_STYLES = `
|
|
|
1550
1621
|
}
|
|
1551
1622
|
}
|
|
1552
1623
|
|
|
1624
|
+
/* FAB \u2014 56px (Material standard), two-layer elevation, scale-on-press,
|
|
1625
|
+
custom SVG icon (no emoji \u2014 emoji renders inconsistently across OSes
|
|
1626
|
+
and can't inherit color). */
|
|
1553
1627
|
.fab {
|
|
1554
1628
|
position: fixed;
|
|
1555
1629
|
bottom: 24px;
|
|
1556
1630
|
right: 24px;
|
|
1557
|
-
width:
|
|
1558
|
-
height:
|
|
1631
|
+
width: 56px;
|
|
1632
|
+
height: 56px;
|
|
1559
1633
|
border-radius: 999px;
|
|
1560
1634
|
background: var(--mfb-accent);
|
|
1561
1635
|
color: var(--mfb-accent-contrast);
|
|
1562
1636
|
border: none;
|
|
1563
1637
|
cursor: pointer;
|
|
1564
|
-
|
|
1565
|
-
|
|
1638
|
+
/* Two-layer elevation: ambient (soft, large) + key (tighter, near). */
|
|
1639
|
+
box-shadow:
|
|
1640
|
+
0 4px 12px rgba(0, 0, 0, 0.08),
|
|
1641
|
+
0 2px 4px rgba(0, 0, 0, 0.12);
|
|
1566
1642
|
display: grid;
|
|
1567
1643
|
place-items: center;
|
|
1568
|
-
transition: transform
|
|
1644
|
+
transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
1645
|
+
box-shadow 180ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
1569
1646
|
}
|
|
1570
1647
|
|
|
1571
|
-
.fab:hover {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1648
|
+
.fab:hover {
|
|
1649
|
+
transform: translateY(-2px);
|
|
1650
|
+
box-shadow:
|
|
1651
|
+
0 8px 24px rgba(0, 0, 0, 0.12),
|
|
1652
|
+
0 3px 6px rgba(0, 0, 0, 0.16);
|
|
1653
|
+
}
|
|
1654
|
+
.fab:active {
|
|
1655
|
+
transform: translateY(0) scale(0.96);
|
|
1656
|
+
box-shadow:
|
|
1657
|
+
0 3px 8px rgba(0, 0, 0, 0.10),
|
|
1658
|
+
0 1px 2px rgba(0, 0, 0, 0.14);
|
|
1659
|
+
}
|
|
1660
|
+
.fab:focus-visible {
|
|
1661
|
+
outline: 2px solid var(--mfb-accent-contrast);
|
|
1662
|
+
outline-offset: 3px;
|
|
1663
|
+
box-shadow:
|
|
1664
|
+
0 0 0 4px var(--mfb-accent),
|
|
1665
|
+
0 4px 12px rgba(0, 0, 0, 0.08),
|
|
1666
|
+
0 2px 4px rgba(0, 0, 0, 0.12);
|
|
1667
|
+
}
|
|
1668
|
+
@media (prefers-color-scheme: dark) {
|
|
1669
|
+
/* Slightly desaturate so the FAB doesn't glow against dark backgrounds. */
|
|
1670
|
+
.fab { box-shadow:
|
|
1671
|
+
0 4px 12px rgba(0, 0, 0, 0.32),
|
|
1672
|
+
0 2px 4px rgba(0, 0, 0, 0.40); }
|
|
1673
|
+
}
|
|
1674
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1675
|
+
.fab { transition: none; }
|
|
1676
|
+
.fab:hover, .fab:active { transform: none; }
|
|
1677
|
+
}
|
|
1575
1678
|
|
|
1576
1679
|
.backdrop {
|
|
1577
1680
|
position: fixed;
|
|
@@ -1585,11 +1688,16 @@ var WIDGET_STYLES = `
|
|
|
1585
1688
|
background: var(--mfb-bg);
|
|
1586
1689
|
border-radius: calc(var(--mfb-radius) * 1.5);
|
|
1587
1690
|
box-shadow: 0 20px 48px rgba(0, 0, 0, 0.25);
|
|
1588
|
-
|
|
1589
|
-
|
|
1691
|
+
/* 440px is the industry sweet spot for short forms \u2014 Linear, Plain,
|
|
1692
|
+
Sentry all sit in the 420-480 range. 92vw caps it on narrow screens. */
|
|
1693
|
+
width: min(440px, 92vw);
|
|
1694
|
+
/* 24px is shadcn's default; gives every input room to breathe. */
|
|
1695
|
+
padding: 24px;
|
|
1590
1696
|
display: flex;
|
|
1591
1697
|
flex-direction: column;
|
|
1592
|
-
|
|
1698
|
+
/* 18px between major blocks (h2 \u2192 field \u2192 field \u2192 footer). Within a
|
|
1699
|
+
field group, .field uses a tighter 6px label-to-input gap. */
|
|
1700
|
+
gap: 18px;
|
|
1593
1701
|
position: relative;
|
|
1594
1702
|
/* Cap modal height on short viewports (mobile landscape, tiny laptops)
|
|
1595
1703
|
so the form scrolls inside the modal rather than overflowing the
|
|
@@ -1598,7 +1706,23 @@ var WIDGET_STYLES = `
|
|
|
1598
1706
|
overflow-y: auto;
|
|
1599
1707
|
}
|
|
1600
1708
|
|
|
1601
|
-
.modal h2 {
|
|
1709
|
+
.modal h2 {
|
|
1710
|
+
margin: 0;
|
|
1711
|
+
font-size: 17px;
|
|
1712
|
+
font-weight: 600;
|
|
1713
|
+
padding-right: 28px;
|
|
1714
|
+
letter-spacing: -0.01em;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
/* The form sits inside .modal as a single flex child, so the modal-level
|
|
1718
|
+
gap doesn't separate the form's *own* children. Mirror the column +
|
|
1719
|
+
gap pattern on the form itself; 22px lands in the middle of the
|
|
1720
|
+
20-24px field-to-field range the design critic recommended. */
|
|
1721
|
+
.modal form {
|
|
1722
|
+
display: flex;
|
|
1723
|
+
flex-direction: column;
|
|
1724
|
+
gap: 22px;
|
|
1725
|
+
}
|
|
1602
1726
|
|
|
1603
1727
|
.modal-close {
|
|
1604
1728
|
position: absolute;
|
|
@@ -1620,15 +1744,22 @@ var WIDGET_STYLES = `
|
|
|
1620
1744
|
.modal-close:hover { background: var(--mfb-surface); color: var(--mfb-text); }
|
|
1621
1745
|
.modal-close:focus-visible { outline: 2px solid var(--mfb-accent); outline-offset: 2px; }
|
|
1622
1746
|
|
|
1623
|
-
|
|
1747
|
+
/* Each field group: label (13px medium, muted) + input (14px regular)
|
|
1748
|
+
stacked with a 6px gap. The 18px modal-level gap separates groups. */
|
|
1749
|
+
.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
|
|
1624
1750
|
|
|
1625
|
-
.field label {
|
|
1751
|
+
.field label {
|
|
1752
|
+
color: var(--mfb-text-muted);
|
|
1753
|
+
font-weight: 500;
|
|
1754
|
+
font-size: 12px;
|
|
1755
|
+
letter-spacing: 0.01em;
|
|
1756
|
+
}
|
|
1626
1757
|
|
|
1627
1758
|
.field input, .field select, .field textarea {
|
|
1628
1759
|
font-family: inherit;
|
|
1629
1760
|
font-size: 14px;
|
|
1630
1761
|
color: inherit;
|
|
1631
|
-
padding:
|
|
1762
|
+
padding: 9px 12px;
|
|
1632
1763
|
border: 1px solid var(--mfb-border);
|
|
1633
1764
|
border-radius: var(--mfb-radius);
|
|
1634
1765
|
background: var(--mfb-surface);
|
|
@@ -1652,28 +1783,44 @@ var WIDGET_STYLES = `
|
|
|
1652
1783
|
background-position: right 10px center;
|
|
1653
1784
|
}
|
|
1654
1785
|
|
|
1655
|
-
.field textarea { min-height:
|
|
1786
|
+
.field textarea { min-height: 96px; resize: vertical; line-height: 1.45; }
|
|
1656
1787
|
|
|
1657
|
-
.row { display: flex; gap:
|
|
1788
|
+
.row { display: flex; gap: 12px; }
|
|
1658
1789
|
.row > * { flex: 1; }
|
|
1659
1790
|
|
|
1660
|
-
|
|
1791
|
+
/* Footer separation: border-top + 16px breathing room, Stripe/Linear pattern.
|
|
1792
|
+
Stops Cancel/Send from floating against the dropzone or page-URL footer. */
|
|
1793
|
+
.actions {
|
|
1794
|
+
display: flex;
|
|
1795
|
+
gap: 8px;
|
|
1796
|
+
justify-content: flex-end;
|
|
1797
|
+
padding-top: 16px;
|
|
1798
|
+
margin-top: 4px;
|
|
1799
|
+
border-top: 1px solid var(--mfb-border);
|
|
1800
|
+
}
|
|
1661
1801
|
|
|
1662
1802
|
.btn {
|
|
1663
|
-
padding:
|
|
1803
|
+
padding: 9px 16px;
|
|
1664
1804
|
border-radius: var(--mfb-radius);
|
|
1665
1805
|
border: 1px solid var(--mfb-border);
|
|
1666
1806
|
background: var(--mfb-bg);
|
|
1667
1807
|
color: var(--mfb-text);
|
|
1668
1808
|
font: inherit;
|
|
1809
|
+
font-weight: 500;
|
|
1669
1810
|
cursor: pointer;
|
|
1811
|
+
transition: background 120ms ease, border-color 120ms ease;
|
|
1670
1812
|
}
|
|
1813
|
+
.btn:hover { background: var(--mfb-surface); }
|
|
1671
1814
|
|
|
1672
1815
|
.btn--primary {
|
|
1673
1816
|
background: var(--mfb-accent);
|
|
1674
1817
|
color: var(--mfb-accent-contrast);
|
|
1675
1818
|
border-color: var(--mfb-accent);
|
|
1676
1819
|
}
|
|
1820
|
+
.btn--primary:hover {
|
|
1821
|
+
background: color-mix(in srgb, var(--mfb-accent) 88%, black);
|
|
1822
|
+
border-color: color-mix(in srgb, var(--mfb-accent) 88%, black);
|
|
1823
|
+
}
|
|
1677
1824
|
|
|
1678
1825
|
.btn[disabled] { opacity: 0.6; cursor: not-allowed; }
|
|
1679
1826
|
|
|
@@ -1697,7 +1844,7 @@ var WIDGET_STYLES = `
|
|
|
1697
1844
|
.screenshot-dropzone {
|
|
1698
1845
|
border: 1px dashed var(--mfb-border);
|
|
1699
1846
|
border-radius: var(--mfb-radius);
|
|
1700
|
-
padding: 14px
|
|
1847
|
+
padding: 18px 14px;
|
|
1701
1848
|
text-align: center;
|
|
1702
1849
|
cursor: pointer;
|
|
1703
1850
|
background: var(--mfb-surface);
|
|
@@ -1770,12 +1917,12 @@ var WIDGET_STYLES = `
|
|
|
1770
1917
|
text-transform: uppercase;
|
|
1771
1918
|
font-weight: 600;
|
|
1772
1919
|
letter-spacing: 0.04em;
|
|
1920
|
+
font-size: 10px;
|
|
1773
1921
|
}
|
|
1774
1922
|
.page-context-url {
|
|
1775
1923
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
border-radius: 4px;
|
|
1924
|
+
font-size: 11px;
|
|
1925
|
+
color: var(--mfb-text-muted);
|
|
1779
1926
|
flex: 1;
|
|
1780
1927
|
overflow: hidden;
|
|
1781
1928
|
text-overflow: ellipsis;
|
|
@@ -2052,6 +2199,43 @@ var WIDGET_STYLES = `
|
|
|
2052
2199
|
margin: 8px 0 4px;
|
|
2053
2200
|
font-weight: 600;
|
|
2054
2201
|
}
|
|
2202
|
+
|
|
2203
|
+
.report-detail-context {
|
|
2204
|
+
display: flex;
|
|
2205
|
+
flex-direction: column;
|
|
2206
|
+
gap: 6px;
|
|
2207
|
+
padding: 10px 12px;
|
|
2208
|
+
background: var(--mfb-surface);
|
|
2209
|
+
border-radius: var(--mfb-radius);
|
|
2210
|
+
border: 1px solid var(--mfb-border);
|
|
2211
|
+
}
|
|
2212
|
+
.report-detail-context-pills { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
2213
|
+
.report-detail-context-line {
|
|
2214
|
+
display: flex;
|
|
2215
|
+
align-items: baseline;
|
|
2216
|
+
gap: 8px;
|
|
2217
|
+
font-size: 12px;
|
|
2218
|
+
color: var(--mfb-text);
|
|
2219
|
+
}
|
|
2220
|
+
.report-detail-context-label {
|
|
2221
|
+
text-transform: uppercase;
|
|
2222
|
+
letter-spacing: 0.04em;
|
|
2223
|
+
font-size: 10px;
|
|
2224
|
+
font-weight: 600;
|
|
2225
|
+
color: var(--mfb-text-muted);
|
|
2226
|
+
min-width: 56px;
|
|
2227
|
+
}
|
|
2228
|
+
.report-detail-context-url {
|
|
2229
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2230
|
+
color: var(--mfb-accent);
|
|
2231
|
+
text-decoration: none;
|
|
2232
|
+
font-size: 11px;
|
|
2233
|
+
overflow: hidden;
|
|
2234
|
+
text-overflow: ellipsis;
|
|
2235
|
+
white-space: nowrap;
|
|
2236
|
+
}
|
|
2237
|
+
.report-detail-context-url:hover { text-decoration: underline; }
|
|
2238
|
+
.pill-capture { background: var(--mfb-bg); color: var(--mfb-text-muted); border-color: var(--mfb-border); }
|
|
2055
2239
|
.report-detail-empty {
|
|
2056
2240
|
font-size: 12px;
|
|
2057
2241
|
color: var(--mfb-text-muted);
|
|
@@ -2398,4 +2582,4 @@ function createFeedback(config) {
|
|
|
2398
2582
|
export {
|
|
2399
2583
|
createFeedback
|
|
2400
2584
|
};
|
|
2401
|
-
//# sourceMappingURL=chunk-
|
|
2585
|
+
//# sourceMappingURL=chunk-2TLTE2VZ.mjs.map
|