@pocketping/widget 1.10.0 → 1.12.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.
package/dist/index.cjs CHANGED
@@ -515,6 +515,33 @@ function styles(options) {
515
515
  display: inline;
516
516
  }
517
517
 
518
+ /* Markdown styles */
519
+ .pp-message-content strong {
520
+ font-weight: 600;
521
+ }
522
+
523
+ .pp-message-content em {
524
+ font-style: italic;
525
+ }
526
+
527
+ .pp-message-content code {
528
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
529
+ font-size: 0.9em;
530
+ background: ${isDark ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.06)"};
531
+ padding: 1px 4px;
532
+ border-radius: 3px;
533
+ }
534
+
535
+ .pp-md-list {
536
+ margin: 4px 0;
537
+ padding-left: 20px;
538
+ display: block;
539
+ }
540
+
541
+ .pp-md-list li {
542
+ margin: 2px 0;
543
+ }
544
+
518
545
  /* WhatsApp-style inline timestamp - floats to the right */
519
546
  .pp-message-time {
520
547
  font-size: 11px;
@@ -601,23 +628,27 @@ function styles(options) {
601
628
  padding: 8px 10px;
602
629
  gap: 8px;
603
630
  background: ${resolvedFooterColor};
604
- align-items: center;
631
+ align-items: flex-end;
605
632
  }
606
633
 
607
634
  .pp-input {
608
635
  flex: 1;
609
636
  min-width: 0;
610
- height: 42px;
611
- line-height: 42px;
612
- padding: 0 14px;
637
+ min-height: 42px;
638
+ max-height: 120px;
639
+ padding: 10px 14px;
613
640
  border: none;
614
641
  border-radius: 8px;
615
642
  background: ${isDark ? "#2a3942" : "#ffffff"};
616
643
  color: ${isDark ? "#e9edef" : "#111b21"};
617
644
  font-size: 15px;
645
+ line-height: 1.4;
618
646
  outline: none;
619
647
  box-sizing: border-box;
620
648
  margin: 0;
649
+ resize: none;
650
+ font-family: inherit;
651
+ overflow-y: auto;
621
652
  }
622
653
 
623
654
  .pp-input:focus {
@@ -1886,6 +1917,40 @@ function PreChatForm({ client: client2, config, onComplete, onSkip }) {
1886
1917
  ] });
1887
1918
  }
1888
1919
 
1920
+ // src/utils/markdown.ts
1921
+ function renderMarkdown(text) {
1922
+ if (!text) return "";
1923
+ let html = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1924
+ const lines = html.split("\n");
1925
+ let inList = false;
1926
+ const processedLines = [];
1927
+ for (const line of lines) {
1928
+ const listMatch = line.match(/^[\s]*[*-]\s+(.+)$/);
1929
+ if (listMatch) {
1930
+ if (!inList) {
1931
+ processedLines.push('<ul class="pp-md-list">');
1932
+ inList = true;
1933
+ }
1934
+ processedLines.push(`<li>${processInline(listMatch[1])}</li>`);
1935
+ } else {
1936
+ if (inList) {
1937
+ processedLines.push("</ul>");
1938
+ inList = false;
1939
+ }
1940
+ processedLines.push(processInline(line));
1941
+ }
1942
+ }
1943
+ if (inList) {
1944
+ processedLines.push("</ul>");
1945
+ }
1946
+ html = processedLines.join("<br />");
1947
+ html = html.replace(/<br \/><ul/g, "<ul").replace(/<\/ul><br \/>/g, "</ul>").replace(/<br \/><li>/g, "<li>").replace(/<\/li><br \/>/g, "</li>");
1948
+ return html;
1949
+ }
1950
+ function processInline(text) {
1951
+ return text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>").replace(/__(.+?)__/g, "<strong>$1</strong>").replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, "<em>$1</em>").replace(/(?<!_)_([^_]+)_(?!_)/g, "<em>$1</em>").replace(/`([^`]+)`/g, "<code>$1</code>");
1952
+ }
1953
+
1889
1954
  // src/components/ChatWidget.tsx
1890
1955
  var import_jsx_runtime2 = require("preact/jsx-runtime");
1891
1956
  function formatDateSeparator(date) {
@@ -2042,6 +2107,9 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2042
2107
  setInputValue("");
2043
2108
  setPendingAttachments([]);
2044
2109
  setReplyingTo(null);
2110
+ if (inputRef.current) {
2111
+ inputRef.current.style.height = "auto";
2112
+ }
2045
2113
  try {
2046
2114
  await client2.sendMessage(content, attachmentIds, replyToId);
2047
2115
  } catch (err) {
@@ -2051,8 +2119,17 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2051
2119
  const handleInputChange = (e) => {
2052
2120
  const target = e.target;
2053
2121
  setInputValue(target.value);
2122
+ target.style.height = "auto";
2123
+ target.style.height = Math.min(target.scrollHeight, 120) + "px";
2054
2124
  client2.sendTyping(true);
2055
2125
  };
2126
+ const handleKeyDown = (e) => {
2127
+ if (e.key === "Enter" && !e.shiftKey) {
2128
+ e.preventDefault();
2129
+ const form = e.target.closest("form");
2130
+ if (form) form.requestSubmit();
2131
+ }
2132
+ };
2056
2133
  const handleFileSelect = async (e) => {
2057
2134
  const target = e.target;
2058
2135
  const files = target.files;
@@ -2468,7 +2545,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2468
2545
  " Message deleted"
2469
2546
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2470
2547
  msg.content && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-message-content", children: [
2471
- msg.content,
2548
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { dangerouslySetInnerHTML: { __html: renderMarkdown(msg.content) } }),
2472
2549
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { class: "pp-message-time", children: [
2473
2550
  formatTime(msg.timestamp),
2474
2551
  isEdited && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-edited-badge", children: "edited" }),
@@ -2597,15 +2674,16 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2597
2674
  }
2598
2675
  ),
2599
2676
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2600
- "input",
2677
+ "textarea",
2601
2678
  {
2602
2679
  ref: inputRef,
2603
- type: "text",
2604
2680
  class: "pp-input",
2605
2681
  placeholder: config.placeholder ?? "Type a message...",
2606
2682
  value: inputValue,
2607
2683
  onInput: handleInputChange,
2608
- disabled: !isConnected
2684
+ onKeyDown: handleKeyDown,
2685
+ disabled: !isConnected,
2686
+ rows: 1
2609
2687
  }
2610
2688
  ),
2611
2689
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
package/dist/index.js CHANGED
@@ -474,6 +474,33 @@ function styles(options) {
474
474
  display: inline;
475
475
  }
476
476
 
477
+ /* Markdown styles */
478
+ .pp-message-content strong {
479
+ font-weight: 600;
480
+ }
481
+
482
+ .pp-message-content em {
483
+ font-style: italic;
484
+ }
485
+
486
+ .pp-message-content code {
487
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
488
+ font-size: 0.9em;
489
+ background: ${isDark ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.06)"};
490
+ padding: 1px 4px;
491
+ border-radius: 3px;
492
+ }
493
+
494
+ .pp-md-list {
495
+ margin: 4px 0;
496
+ padding-left: 20px;
497
+ display: block;
498
+ }
499
+
500
+ .pp-md-list li {
501
+ margin: 2px 0;
502
+ }
503
+
477
504
  /* WhatsApp-style inline timestamp - floats to the right */
478
505
  .pp-message-time {
479
506
  font-size: 11px;
@@ -560,23 +587,27 @@ function styles(options) {
560
587
  padding: 8px 10px;
561
588
  gap: 8px;
562
589
  background: ${resolvedFooterColor};
563
- align-items: center;
590
+ align-items: flex-end;
564
591
  }
565
592
 
566
593
  .pp-input {
567
594
  flex: 1;
568
595
  min-width: 0;
569
- height: 42px;
570
- line-height: 42px;
571
- padding: 0 14px;
596
+ min-height: 42px;
597
+ max-height: 120px;
598
+ padding: 10px 14px;
572
599
  border: none;
573
600
  border-radius: 8px;
574
601
  background: ${isDark ? "#2a3942" : "#ffffff"};
575
602
  color: ${isDark ? "#e9edef" : "#111b21"};
576
603
  font-size: 15px;
604
+ line-height: 1.4;
577
605
  outline: none;
578
606
  box-sizing: border-box;
579
607
  margin: 0;
608
+ resize: none;
609
+ font-family: inherit;
610
+ overflow-y: auto;
580
611
  }
581
612
 
582
613
  .pp-input:focus {
@@ -1845,6 +1876,40 @@ function PreChatForm({ client: client2, config, onComplete, onSkip }) {
1845
1876
  ] });
1846
1877
  }
1847
1878
 
1879
+ // src/utils/markdown.ts
1880
+ function renderMarkdown(text) {
1881
+ if (!text) return "";
1882
+ let html = text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1883
+ const lines = html.split("\n");
1884
+ let inList = false;
1885
+ const processedLines = [];
1886
+ for (const line of lines) {
1887
+ const listMatch = line.match(/^[\s]*[*-]\s+(.+)$/);
1888
+ if (listMatch) {
1889
+ if (!inList) {
1890
+ processedLines.push('<ul class="pp-md-list">');
1891
+ inList = true;
1892
+ }
1893
+ processedLines.push(`<li>${processInline(listMatch[1])}</li>`);
1894
+ } else {
1895
+ if (inList) {
1896
+ processedLines.push("</ul>");
1897
+ inList = false;
1898
+ }
1899
+ processedLines.push(processInline(line));
1900
+ }
1901
+ }
1902
+ if (inList) {
1903
+ processedLines.push("</ul>");
1904
+ }
1905
+ html = processedLines.join("<br />");
1906
+ html = html.replace(/<br \/><ul/g, "<ul").replace(/<\/ul><br \/>/g, "</ul>").replace(/<br \/><li>/g, "<li>").replace(/<\/li><br \/>/g, "</li>");
1907
+ return html;
1908
+ }
1909
+ function processInline(text) {
1910
+ return text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>").replace(/__(.+?)__/g, "<strong>$1</strong>").replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, "<em>$1</em>").replace(/(?<!_)_([^_]+)_(?!_)/g, "<em>$1</em>").replace(/`([^`]+)`/g, "<code>$1</code>");
1911
+ }
1912
+
1848
1913
  // src/components/ChatWidget.tsx
1849
1914
  import { Fragment as Fragment3, jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
1850
1915
  function formatDateSeparator(date) {
@@ -2001,6 +2066,9 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2001
2066
  setInputValue("");
2002
2067
  setPendingAttachments([]);
2003
2068
  setReplyingTo(null);
2069
+ if (inputRef.current) {
2070
+ inputRef.current.style.height = "auto";
2071
+ }
2004
2072
  try {
2005
2073
  await client2.sendMessage(content, attachmentIds, replyToId);
2006
2074
  } catch (err) {
@@ -2010,8 +2078,17 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2010
2078
  const handleInputChange = (e) => {
2011
2079
  const target = e.target;
2012
2080
  setInputValue(target.value);
2081
+ target.style.height = "auto";
2082
+ target.style.height = Math.min(target.scrollHeight, 120) + "px";
2013
2083
  client2.sendTyping(true);
2014
2084
  };
2085
+ const handleKeyDown = (e) => {
2086
+ if (e.key === "Enter" && !e.shiftKey) {
2087
+ e.preventDefault();
2088
+ const form = e.target.closest("form");
2089
+ if (form) form.requestSubmit();
2090
+ }
2091
+ };
2015
2092
  const handleFileSelect = async (e) => {
2016
2093
  const target = e.target;
2017
2094
  const files = target.files;
@@ -2427,7 +2504,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2427
2504
  " Message deleted"
2428
2505
  ] }) : /* @__PURE__ */ jsxs2(Fragment3, { children: [
2429
2506
  msg.content && /* @__PURE__ */ jsxs2("div", { class: "pp-message-content", children: [
2430
- msg.content,
2507
+ /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: renderMarkdown(msg.content) } }),
2431
2508
  /* @__PURE__ */ jsxs2("span", { class: "pp-message-time", children: [
2432
2509
  formatTime(msg.timestamp),
2433
2510
  isEdited && /* @__PURE__ */ jsx2("span", { class: "pp-edited-badge", children: "edited" }),
@@ -2556,15 +2633,16 @@ function ChatWidget({ client: client2, config: initialConfig }) {
2556
2633
  }
2557
2634
  ),
2558
2635
  /* @__PURE__ */ jsx2(
2559
- "input",
2636
+ "textarea",
2560
2637
  {
2561
2638
  ref: inputRef,
2562
- type: "text",
2563
2639
  class: "pp-input",
2564
2640
  placeholder: config.placeholder ?? "Type a message...",
2565
2641
  value: inputValue,
2566
2642
  onInput: handleInputChange,
2567
- disabled: !isConnected
2643
+ onKeyDown: handleKeyDown,
2644
+ disabled: !isConnected,
2645
+ rows: 1
2568
2646
  }
2569
2647
  ),
2570
2648
  /* @__PURE__ */ jsx2(