@clubmed/trident-ui 2.0.0-beta.56 → 2.0.0-beta.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export default function ChatWindowCsatDemo(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,68 @@
1
+ "use client";
2
+ import { ChatWindow as e } from "../ui/ChatWindow.js";
3
+ import { useRef as t } from "react";
4
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ //#region lib/examples/chat-window-csat-demo.tsx
6
+ var i = [
7
+ {
8
+ id: "1",
9
+ sender: "assistant",
10
+ content: "Hi. Ask me anything about Club Med. I'm here to help you find the right information quickly."
11
+ },
12
+ {
13
+ id: "2",
14
+ sender: "user",
15
+ content: "My son is 14 years old, what activities are available for him during our stay?"
16
+ },
17
+ {
18
+ id: "3",
19
+ sender: "assistant",
20
+ content: "Great question! For teenagers aged 13–17, Club Med offers the Passworld programme — supervised sports, creative workshops, and evening events designed specifically for that age group."
21
+ }
22
+ ], a = {
23
+ intro: "Your opinion matters! Tell us what you think. Your feedback helps us improve.",
24
+ question: "Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,",
25
+ questionNote: "1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".",
26
+ groupAriaLabel: "Rate your experience from 1 to 5 stars",
27
+ starLabels: [
28
+ "Very dissatisfied",
29
+ "Dissatisfied",
30
+ "Neutral",
31
+ "Satisfied",
32
+ "Very satisfied"
33
+ ]
34
+ }, o = {
35
+ title: "Thank you for your feedback!",
36
+ body: "Your opinion means a lot to us. Thanks to your responses, we keep improving our services to offer you an even more exceptional Club Med experience."
37
+ };
38
+ function s(e) {
39
+ return `${e} star${e > 1 ? "s" : ""} — ${a.starLabels[e - 1]}`;
40
+ }
41
+ function c() {
42
+ let c = t(null);
43
+ return /* @__PURE__ */ r("div", {
44
+ className: "flex flex-col items-center gap-12",
45
+ children: [/* @__PURE__ */ n(e, {
46
+ ref: c,
47
+ messages: i,
48
+ inputValue: "",
49
+ onInputChange: () => {},
50
+ onSubmit: () => {},
51
+ csatLabels: a,
52
+ csatRenderRatingLabel: s,
53
+ csatThankYouLabels: o,
54
+ onFeedbackRate: (e) => console.log("Feedback rating:", e),
55
+ onClose: () => {},
56
+ className: "w-380 h-660"
57
+ }), /* @__PURE__ */ n("button", {
58
+ type: "button",
59
+ onClick: () => c.current?.askForFeedback(),
60
+ className: "px-16 py-8 bg-saffron rounded-pill text-black text-b4 font-semibold hover:opacity-80 transition-opacity",
61
+ children: "Trigger feedback prompt"
62
+ })]
63
+ });
64
+ }
65
+ //#endregion
66
+ export { c as default };
67
+
68
+ //# sourceMappingURL=chat-window-csat-demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-window-csat-demo.js","names":[],"sources":["../../lib/examples/chat-window-csat-demo.tsx"],"sourcesContent":["'use client';\n\nimport { useRef } from 'react';\nimport { ChatWindow } from '@/ui/ChatWindow';\nimport type {\n ChatWindowCsatPromptLabels,\n ChatWindowCsatThankYouLabels,\n ChatWindowHandle,\n ChatWindowMessage,\n} from '@/ui/ChatWindow';\n\nconst messages: ChatWindowMessage[] = [\n {\n id: '1',\n sender: 'assistant',\n content:\n \"Hi. Ask me anything about Club Med. I'm here to help you find the right information quickly.\",\n },\n {\n id: '2',\n sender: 'user',\n content: 'My son is 14 years old, what activities are available for him during our stay?',\n },\n {\n id: '3',\n sender: 'assistant',\n content:\n 'Great question! For teenagers aged 13–17, Club Med offers the Passworld programme — supervised sports, creative workshops, and evening events designed specifically for that age group.',\n },\n];\n\nconst csatLabels: ChatWindowCsatPromptLabels = {\n intro: 'Your opinion matters! Tell us what you think. Your feedback helps us improve.',\n question:\n 'Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,',\n questionNote: '1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".',\n groupAriaLabel: 'Rate your experience from 1 to 5 stars',\n starLabels: ['Very dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Very satisfied'],\n};\n\nconst csatThankYouLabels: ChatWindowCsatThankYouLabels = {\n title: 'Thank you for your feedback!',\n body: 'Your opinion means a lot to us. Thanks to your responses, we keep improving our services to offer you an even more exceptional Club Med experience.',\n};\n\nfunction csatRenderRatingLabel(rating: number) {\n return `${rating} star${rating > 1 ? 's' : ''} — ${csatLabels.starLabels[rating - 1]}`;\n}\n\nexport default function ChatWindowCsatDemo() {\n const chatRef = useRef<ChatWindowHandle>(null);\n\n return (\n <div className=\"flex flex-col items-center gap-12\">\n <ChatWindow\n ref={chatRef}\n messages={messages}\n inputValue=\"\"\n onInputChange={() => {}}\n onSubmit={() => {}}\n csatLabels={csatLabels}\n csatRenderRatingLabel={csatRenderRatingLabel}\n csatThankYouLabels={csatThankYouLabels}\n onFeedbackRate={(rating) => console.log('Feedback rating:', rating)}\n onClose={() => {}}\n className=\"w-380 h-660\"\n />\n <button\n type=\"button\"\n onClick={() => chatRef.current?.askForFeedback()}\n className=\"px-16 py-8 bg-saffron rounded-pill text-black text-b4 font-semibold hover:opacity-80 transition-opacity\"\n >\n Trigger feedback prompt\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;AAWA,IAAM,IAAgC;CACpC;EACE,IAAI;EACJ,QAAQ;EACR,SACE;EACH;CACD;EACE,IAAI;EACJ,QAAQ;EACR,SAAS;EACV;CACD;EACE,IAAI;EACJ,QAAQ;EACR,SACE;;CAEL,EAEK,IAAyC;CAC7C,OAAO;CACP,UACE;CACF,cAAc;CACd,gBAAgB;CAChB,YAAY;EAAC;EAAqB;EAAgB;EAAW;EAAa;;CAC3E,EAEK,IAAmD;CACvD,OAAO;CACP,MAAM;CACP;AAED,SAAS,EAAsB,GAAgB;AAC7C,QAAO,GAAG,EAAO,OAAO,IAAS,IAAI,MAAM,GAAG,KAAK,EAAW,WAAW,IAAS;;AAGpF,SAAwB,IAAqB;CAC3C,IAAM,IAAU,EAAyB,KAAK;AAE9C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GACE,KAAK;GACK;GACV,YAAW;GACX,qBAAqB;GACrB,gBAAgB;GACJ;GACW;GACH;GACpB,iBAAiB,MAAW,QAAQ,IAAI,oBAAoB,EAAO;GACnE,eAAe;GACf,WAAU;GACV,CAAA,EACF,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAQ,SAAS,gBAAgB;GAChD,WAAU;aACX;GAEQ,CAAA,CAAA"}
@@ -0,0 +1 @@
1
+ export default function ChatWindowCsatPromptDemo(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { ChatWindowCsatPrompt as e } from "../ui/ChatWindowCsatPrompt.js";
3
+ import { useState as t } from "react";
4
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ //#region lib/examples/chat-window-csat-prompt-demo.tsx
6
+ var i = {
7
+ intro: "Your opinion matters! Tell us what you think. Your feedback helps us improve.",
8
+ question: "Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,",
9
+ questionNote: "1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".",
10
+ groupAriaLabel: "Rate your experience from 1 to 5 stars",
11
+ starLabels: [
12
+ "Very dissatisfied",
13
+ "Dissatisfied",
14
+ "Neutral",
15
+ "Satisfied",
16
+ "Very satisfied"
17
+ ]
18
+ };
19
+ function a(e) {
20
+ let t = i.starLabels;
21
+ return `${e} star${e > 1 ? "s" : ""} — ${t[e - 1]}`;
22
+ }
23
+ function o() {
24
+ let [o, s] = t(null);
25
+ return /* @__PURE__ */ r("div", {
26
+ className: "flex flex-col gap-20 w-380",
27
+ children: [/* @__PURE__ */ n(e, {
28
+ labels: i,
29
+ renderRatingLabel: a,
30
+ onRate: s
31
+ }), o !== null && /* @__PURE__ */ r("p", {
32
+ className: "text-b4 text-darkGrey text-center",
33
+ children: ["onRate called with: ", /* @__PURE__ */ n("strong", { children: o })]
34
+ })]
35
+ });
36
+ }
37
+ //#endregion
38
+ export { o as default };
39
+
40
+ //# sourceMappingURL=chat-window-csat-prompt-demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-window-csat-prompt-demo.js","names":[],"sources":["../../lib/examples/chat-window-csat-prompt-demo.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { ChatWindowCsatPrompt } from '@/ui/ChatWindowCsatPrompt';\nimport type { ChatWindowCsatPromptLabels } from '@/ui/ChatWindowCsatPrompt';\n\nconst defaultCsatLabels: ChatWindowCsatPromptLabels = {\n intro: 'Your opinion matters! Tell us what you think. Your feedback helps us improve.',\n question:\n 'Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,',\n questionNote: '1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".',\n groupAriaLabel: 'Rate your experience from 1 to 5 stars',\n starLabels: ['Very dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Very satisfied'],\n};\n\nfunction defaultRenderRatingLabel(rating: number) {\n const labels = defaultCsatLabels.starLabels;\n return `${rating} star${rating > 1 ? 's' : ''} — ${labels[rating - 1]}`;\n}\n\nexport default function ChatWindowCsatPromptDemo() {\n const [lastRating, setLastRating] = useState<number | null>(null);\n\n return (\n <div className=\"flex flex-col gap-20 w-380\">\n <ChatWindowCsatPrompt\n labels={defaultCsatLabels}\n renderRatingLabel={defaultRenderRatingLabel}\n onRate={setLastRating}\n />\n {lastRating !== null && (\n <p className=\"text-b4 text-darkGrey text-center\">\n onRate called with: <strong>{lastRating}</strong>\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAMA,IAAM,IAAgD;CACpD,OAAO;CACP,UACE;CACF,cAAc;CACd,gBAAgB;CAChB,YAAY;EAAC;EAAqB;EAAgB;EAAW;EAAa;;CAC3E;AAED,SAAS,EAAyB,GAAgB;CAChD,IAAM,IAAS,EAAkB;AACjC,QAAO,GAAG,EAAO,OAAO,IAAS,IAAI,MAAM,GAAG,KAAK,EAAO,IAAS;;AAGrE,SAAwB,IAA2B;CACjD,IAAM,CAAC,GAAY,KAAiB,EAAwB,KAAK;AAEjE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GACE,QAAQ;GACR,mBAAmB;GACnB,QAAQ;GACR,CAAA,EACD,MAAe,QACd,kBAAC,KAAD;GAAG,WAAU;aAAb,CAAiD,wBAC3B,kBAAC,UAAD,EAAA,UAAS,GAAoB,CAAA,CAAA"}
@@ -1,10 +1,29 @@
1
1
  "use client";
2
2
  import { ChatWindow as e } from "../ui/ChatWindow.js";
3
- import { useState as t } from "react";
4
- import { jsx as n } from "react/jsx-runtime";
3
+ import { useRef as t, useState as n } from "react";
4
+ import { jsx as r } from "react/jsx-runtime";
5
5
  //#region lib/examples/chat-window-demo.tsx
6
- function r() {
7
- let [r, i] = t([{
6
+ var i = {
7
+ intro: "Your opinion matters! Tell us what you think. Your feedback helps us improve.",
8
+ question: "Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,",
9
+ questionNote: "1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".",
10
+ groupAriaLabel: "Rate your experience from 1 to 5 stars",
11
+ starLabels: [
12
+ "Very dissatisfied",
13
+ "Dissatisfied",
14
+ "Neutral",
15
+ "Satisfied",
16
+ "Very satisfied"
17
+ ]
18
+ }, a = {
19
+ title: "Thank you for your feedback!",
20
+ body: "Your opinion means a lot to us. Thanks to your responses, we keep improving our services to offer you an even more exceptional Club Med experience."
21
+ };
22
+ function o(e) {
23
+ return `${e} star${e > 1 ? "s" : ""} — ${i.starLabels[e - 1]}`;
24
+ }
25
+ function s() {
26
+ let s = t(null), [c, l] = n([{
8
27
  id: "1",
9
28
  sender: "assistant",
10
29
  content: "Hi. Ask me anything about Club Med. I'm here to help you find the right information quickly."
@@ -12,34 +31,39 @@ function r() {
12
31
  id: "2",
13
32
  sender: "user",
14
33
  content: "My son is 14 years old, and I would like to find activities for him during our stay."
15
- }]), [a, o] = t(""), [s, c] = t(!1);
16
- function l() {
17
- if (!a.trim()) return;
34
+ }]), [u, d] = n(""), [f, p] = n(!1);
35
+ function m() {
36
+ if (!u.trim()) return;
18
37
  let e = {
19
38
  id: Date.now().toString(),
20
39
  sender: "user",
21
- content: a
40
+ content: u
22
41
  };
23
- i((t) => [...t, e]), o(""), c(!0), setTimeout(() => {
24
- c(!1), i((e) => [...e, {
42
+ l((t) => [...t, e]), d(""), p(!0), setTimeout(() => {
43
+ p(!1), l((e) => [...e, {
25
44
  id: (Date.now() + 1).toString(),
26
45
  sender: "assistant",
27
46
  content: "Let me look into that for you…"
28
47
  }]);
29
48
  }, 2e3);
30
49
  }
31
- return /* @__PURE__ */ n(e, {
32
- messages: r,
33
- inputValue: a,
34
- isTyping: s,
35
- onInputChange: o,
36
- onSubmit: l,
50
+ return /* @__PURE__ */ r(e, {
51
+ ref: s,
52
+ messages: c,
53
+ inputValue: u,
54
+ isTyping: f,
55
+ onInputChange: d,
56
+ onSubmit: m,
37
57
  onClose: () => {},
38
58
  onAudioClick: () => {},
59
+ onFeedbackRate: (e) => console.log("Feedback rating:", e),
60
+ csatLabels: i,
61
+ csatRenderRatingLabel: o,
62
+ csatThankYouLabels: a,
39
63
  className: "w-380 h-660"
40
64
  });
41
65
  }
42
66
  //#endregion
43
- export { r as default };
67
+ export { s as default };
44
68
 
45
69
  //# sourceMappingURL=chat-window-demo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-window-demo.js","names":[],"sources":["../../lib/examples/chat-window-demo.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { ChatWindow } from '@/ui/ChatWindow';\nimport type { ChatWindowMessage } from '@/ui/ChatWindow';\n\nexport default function ChatWindowDemo() {\n const [messages, setMessages] = useState<ChatWindowMessage[]>([\n {\n id: '1',\n sender: 'assistant',\n content:\n \"Hi. Ask me anything about Club Med. I'm here to help you find the right information quickly.\",\n },\n {\n id: '2',\n sender: 'user',\n content:\n 'My son is 14 years old, and I would like to find activities for him during our stay.',\n },\n ]);\n const [inputValue, setInputValue] = useState('');\n const [isTyping, setIsTyping] = useState(false);\n\n function handleSubmit() {\n if (!inputValue.trim()) return;\n const userMsg: ChatWindowMessage = {\n id: Date.now().toString(),\n sender: 'user',\n content: inputValue,\n };\n setMessages((prev) => [...prev, userMsg]);\n setInputValue('');\n setIsTyping(true);\n setTimeout(() => {\n setIsTyping(false);\n setMessages((prev) => [\n ...prev,\n {\n id: (Date.now() + 1).toString(),\n sender: 'assistant',\n content: 'Let me look into that for you…',\n },\n ]);\n }, 2000);\n }\n\n return (\n <ChatWindow\n messages={messages}\n inputValue={inputValue}\n isTyping={isTyping}\n onInputChange={setInputValue}\n onSubmit={handleSubmit}\n onClose={() => {}}\n onAudioClick={() => {}}\n className=\"w-380 h-660\"\n />\n );\n}\n"],"mappings":";;;;;AAMA,SAAwB,IAAiB;CACvC,IAAM,CAAC,GAAU,KAAe,EAA8B,CAC5D;EACE,IAAI;EACJ,QAAQ;EACR,SACE;EACH,EACD;EACE,IAAI;EACJ,QAAQ;EACR,SACE;EACH,CACF,CAAC,EACI,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAU,KAAe,EAAS,GAAM;CAE/C,SAAS,IAAe;AACtB,MAAI,CAAC,EAAW,MAAM,CAAE;EACxB,IAAM,IAA6B;GACjC,IAAI,KAAK,KAAK,CAAC,UAAU;GACzB,QAAQ;GACR,SAAS;GACV;AAID,EAHA,GAAa,MAAS,CAAC,GAAG,GAAM,EAAQ,CAAC,EACzC,EAAc,GAAG,EACjB,EAAY,GAAK,EACjB,iBAAiB;AAEf,GADA,EAAY,GAAM,EAClB,GAAa,MAAS,CACpB,GAAG,GACH;IACE,KAAK,KAAK,KAAK,GAAG,GAAG,UAAU;IAC/B,QAAQ;IACR,SAAS;IACV,CACF,CAAC;KACD,IAAK;;AAGV,QACE,kBAAC,GAAD;EACY;EACE;EACF;EACV,eAAe;EACf,UAAU;EACV,eAAe;EACf,oBAAoB;EACpB,WAAU;EACV,CAAA"}
1
+ {"version":3,"file":"chat-window-demo.js","names":[],"sources":["../../lib/examples/chat-window-demo.tsx"],"sourcesContent":["'use client';\n\nimport { useRef, useState } from 'react';\nimport { ChatWindow } from '@/ui/ChatWindow';\nimport type {\n ChatWindowCsatPromptLabels,\n ChatWindowCsatThankYouLabels,\n ChatWindowHandle,\n ChatWindowMessage,\n} from '@/ui/ChatWindow';\n\nconst csatLabels: ChatWindowCsatPromptLabels = {\n intro: 'Your opinion matters! Tell us what you think. Your feedback helps us improve.',\n question:\n 'Following our conversation, from 1 to 5, how satisfied are you with the level of service you received,',\n questionNote: '1 star being \"Very dissatisfied\" and 5 stars \"Very satisfied\".',\n groupAriaLabel: 'Rate your experience from 1 to 5 stars',\n starLabels: ['Very dissatisfied', 'Dissatisfied', 'Neutral', 'Satisfied', 'Very satisfied'],\n};\n\nconst csatThankYouLabels: ChatWindowCsatThankYouLabels = {\n title: 'Thank you for your feedback!',\n body: 'Your opinion means a lot to us. Thanks to your responses, we keep improving our services to offer you an even more exceptional Club Med experience.',\n};\n\nfunction csatRenderRatingLabel(rating: number) {\n return `${rating} star${rating > 1 ? 's' : ''} — ${csatLabels.starLabels[rating - 1]}`;\n}\n\nexport default function ChatWindowDemo() {\n const chatRef = useRef<ChatWindowHandle>(null);\n const [messages, setMessages] = useState<ChatWindowMessage[]>([\n {\n id: '1',\n sender: 'assistant',\n content:\n \"Hi. Ask me anything about Club Med. I'm here to help you find the right information quickly.\",\n },\n {\n id: '2',\n sender: 'user',\n content:\n 'My son is 14 years old, and I would like to find activities for him during our stay.',\n },\n ]);\n const [inputValue, setInputValue] = useState('');\n const [isTyping, setIsTyping] = useState(false);\n\n function handleSubmit() {\n if (!inputValue.trim()) return;\n const userMsg: ChatWindowMessage = {\n id: Date.now().toString(),\n sender: 'user',\n content: inputValue,\n };\n setMessages((prev) => [...prev, userMsg]);\n setInputValue('');\n setIsTyping(true);\n setTimeout(() => {\n setIsTyping(false);\n setMessages((prev) => [\n ...prev,\n {\n id: (Date.now() + 1).toString(),\n sender: 'assistant',\n content: 'Let me look into that for you…',\n },\n ]);\n }, 2000);\n }\n\n return (\n <ChatWindow\n ref={chatRef}\n messages={messages}\n inputValue={inputValue}\n isTyping={isTyping}\n onInputChange={setInputValue}\n onSubmit={handleSubmit}\n onClose={() => {}}\n onAudioClick={() => {}}\n onFeedbackRate={(rating) => console.log('Feedback rating:', rating)}\n csatLabels={csatLabels}\n csatRenderRatingLabel={csatRenderRatingLabel}\n csatThankYouLabels={csatThankYouLabels}\n className=\"w-380 h-660\"\n />\n );\n}\n"],"mappings":";;;;;AAWA,IAAM,IAAyC;CAC7C,OAAO;CACP,UACE;CACF,cAAc;CACd,gBAAgB;CAChB,YAAY;EAAC;EAAqB;EAAgB;EAAW;EAAa;;CAC3E,EAEK,IAAmD;CACvD,OAAO;CACP,MAAM;CACP;AAED,SAAS,EAAsB,GAAgB;AAC7C,QAAO,GAAG,EAAO,OAAO,IAAS,IAAI,MAAM,GAAG,KAAK,EAAW,WAAW,IAAS;;AAGpF,SAAwB,IAAiB;CACvC,IAAM,IAAU,EAAyB,KAAK,EACxC,CAAC,GAAU,KAAe,EAA8B,CAC5D;EACE,IAAI;EACJ,QAAQ;EACR,SACE;EACH,EACD;EACE,IAAI;EACJ,QAAQ;EACR,SACE;EACH,CACF,CAAC,EACI,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAU,KAAe,EAAS,GAAM;CAE/C,SAAS,IAAe;AACtB,MAAI,CAAC,EAAW,MAAM,CAAE;EACxB,IAAM,IAA6B;GACjC,IAAI,KAAK,KAAK,CAAC,UAAU;GACzB,QAAQ;GACR,SAAS;GACV;AAID,EAHA,GAAa,MAAS,CAAC,GAAG,GAAM,EAAQ,CAAC,EACzC,EAAc,GAAG,EACjB,EAAY,GAAK,EACjB,iBAAiB;AAEf,GADA,EAAY,GAAM,EAClB,GAAa,MAAS,CACpB,GAAG,GACH;IACE,KAAK,KAAK,KAAK,GAAG,GAAG,UAAU;IAC/B,QAAQ;IACR,SAAS;IACV,CACF,CAAC;KACD,IAAK;;AAGV,QACE,kBAAC,GAAD;EACE,KAAK;EACK;EACE;EACF;EACV,eAAe;EACf,UAAU;EACV,eAAe;EACf,oBAAoB;EACpB,iBAAiB,MAAW,QAAQ,IAAI,oBAAoB,EAAO;EACvD;EACW;EACH;EACpB,WAAU;EACV,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubmed/trident-ui",
3
- "version": "2.0.0-beta.56",
3
+ "version": "2.0.0-beta.57",
4
4
  "type": "module",
5
5
  "description": "Shared ClubMed React UI components",
6
6
  "keywords": [
@@ -1,5 +1,8 @@
1
1
  import { HTMLAttributes, ReactNode } from 'react';
2
2
  import { ChatMessageSender } from './ChatMessage';
3
+ import { ChatWindowCsatPromptLabels } from './ChatWindowCsatPrompt';
4
+ import { ChatWindowCsatThankYouLabels } from './ChatWindowCsatThankYou';
5
+ export type { ChatWindowCsatPromptLabels, ChatWindowCsatThankYouLabels };
3
6
  export interface ChatWindowMessage {
4
7
  id: string;
5
8
  sender: ChatMessageSender;
@@ -17,5 +20,12 @@ export interface ChatWindowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
17
20
  onClose?: () => void;
18
21
  onAudioClick?: () => void;
19
22
  logo?: ReactNode;
23
+ onFeedbackRate?: (rating: number) => void;
24
+ csatLabels?: ChatWindowCsatPromptLabels;
25
+ csatRenderRatingLabel?: (rating: number) => ReactNode;
26
+ csatThankYouLabels?: ChatWindowCsatThankYouLabels;
20
27
  }
21
- export declare function ChatWindow({ title, greeting, messages, inputValue, inputPlaceholder, isTyping, onInputChange, onSubmit, onClose, onAudioClick, logo, className, ...props }: ChatWindowProps): import("react/jsx-runtime").JSX.Element;
28
+ export interface ChatWindowHandle {
29
+ askForFeedback: () => void;
30
+ }
31
+ export declare const ChatWindow: import('react').ForwardRefExoticComponent<ChatWindowProps & import('react').RefAttributes<ChatWindowHandle>>;
package/ui/ChatWindow.js CHANGED
@@ -3,106 +3,129 @@ import { twMerge as e } from "./helpers/twMerge.js";
3
3
  import { ChatInput as t } from "./ChatInput.js";
4
4
  import { t as n } from "../chunks/ChatMessage.js";
5
5
  import { ChatTypingIndicator as r } from "./ChatTypingIndicator.js";
6
- import { useEffect as i, useRef as a } from "react";
7
- import { Icon as o } from "@clubmed/trident-icons";
8
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
+ import { ChatWindowCsatPrompt as i } from "./ChatWindowCsatPrompt.js";
7
+ import { ChatWindowCsatThankYou as a } from "./ChatWindowCsatThankYou.js";
8
+ import { forwardRef as o, useEffect as s, useImperativeHandle as c, useRef as l, useState as u } from "react";
9
+ import { Icon as d } from "@clubmed/trident-icons";
10
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
9
11
  //#region lib/ui/ChatWindow.tsx
10
- var l = /* @__PURE__ */ s("svg", {
12
+ var m = /* @__PURE__ */ f("svg", {
11
13
  className: "absolute top-full inset-x-[50%] -translate-x-1/2",
12
14
  width: "118",
13
15
  height: "27",
14
16
  viewBox: "0 0 118 27",
15
- children: /* @__PURE__ */ s("path", {
17
+ children: /* @__PURE__ */ f("path", {
16
18
  d: "M0 0C10.8283 0 21.1946 5.40419 28.7327 13.2062L30.2673 14.7945C45.991 31.0685 72.009 31.0685 87.7327 14.7945L89.2673 13.2062C96.8054 5.40419 107.172 0 118 0C118 0 80.6853 0 0 0Z",
17
19
  fill: "#F6EFE7"
18
20
  })
19
- });
20
- function u({ title: u = "Ask me a question", greeting: d, messages: f, inputValue: p, inputPlaceholder: m, isTyping: h = !1, onInputChange: g, onSubmit: _, onClose: v, onAudioClick: y, logo: b, className: x, ...S }) {
21
- let C = a(null);
22
- return i(() => {
23
- let e = C.current;
21
+ }), h = o(function({ title: o = "Ask me a question", greeting: h, messages: g, inputValue: _, inputPlaceholder: v, isTyping: y = !1, onInputChange: b, onSubmit: x, onClose: S, onAudioClick: C, logo: w, onFeedbackRate: T, csatLabels: E, csatRenderRatingLabel: D, csatThankYouLabels: O, className: k, ...A }, j) {
22
+ let M = l(null), [N, P] = u(!1), [F, I] = u(null);
23
+ c(j, () => ({ askForFeedback() {
24
+ P(!0);
25
+ } })), s(() => {
26
+ let e = M.current;
24
27
  e && e.scrollTo({
25
28
  top: e.scrollHeight,
26
29
  behavior: "smooth"
27
30
  });
28
- }, [f, h]), /* @__PURE__ */ c("div", {
29
- ...S,
30
- className: e("flex flex-col gap-20 items-center", x),
31
- children: [/* @__PURE__ */ c("div", {
31
+ }, [
32
+ g,
33
+ y,
34
+ N,
35
+ F
36
+ ]);
37
+ function L(e) {
38
+ I(String(D ? D(e) : e)), T?.(e);
39
+ }
40
+ let R = N && E && D;
41
+ return /* @__PURE__ */ p("div", {
42
+ ...A,
43
+ className: e("flex flex-col gap-20 items-center", k),
44
+ children: [/* @__PURE__ */ p("div", {
32
45
  className: "chat-border bg-white flex flex-col h-full w-full rounded-32 overflow-hidden",
33
46
  children: [
34
- /* @__PURE__ */ c("div", {
47
+ /* @__PURE__ */ p("div", {
35
48
  className: "relative flex flex-col items-center shrink-0 pt-4 px-4 h-133 overflow-hidden",
36
- children: [/* @__PURE__ */ s("div", {
49
+ children: [/* @__PURE__ */ f("div", {
37
50
  className: "absolute inset-x-4 top-4 h-102 bg-lightSand rounded-[24]",
38
- children: l
39
- }), /* @__PURE__ */ c("div", {
51
+ children: m
52
+ }), /* @__PURE__ */ p("div", {
40
53
  className: "relative flex flex-col flex-1 items-center justify-end pb-8 w-full z-10",
41
- children: [/* @__PURE__ */ s("div", {
54
+ children: [/* @__PURE__ */ f("div", {
42
55
  className: "flex items-center justify-center px-12 py-8 w-full",
43
- children: /* @__PURE__ */ s("p", {
56
+ children: /* @__PURE__ */ f("p", {
44
57
  className: "font-serif font-bold italic text-h5 text-center text-black line-clamp-2",
45
- children: u
58
+ children: o
46
59
  })
47
- }), b ?? /* @__PURE__ */ s("button", {
60
+ }), w ?? /* @__PURE__ */ f("button", {
48
61
  type: "button",
49
62
  "aria-label": "AI assistant",
50
63
  className: "chat-border flex items-center justify-center size-48 rounded-full bg-white",
51
- children: /* @__PURE__ */ s(o, {
64
+ children: /* @__PURE__ */ f(d, {
52
65
  name: "Sparkles",
53
66
  width: "24px"
54
67
  })
55
68
  })]
56
69
  })]
57
70
  }),
58
- /* @__PURE__ */ c("div", {
59
- ref: C,
71
+ /* @__PURE__ */ p("div", {
72
+ ref: M,
60
73
  role: "log",
61
74
  "aria-label": "Chat messages",
62
75
  "aria-live": "polite",
63
76
  className: "chat-message-log flex flex-col flex-1 gap-20 overflow-y-auto py-20",
64
77
  children: [
65
- d ? /* @__PURE__ */ s("div", {
78
+ h ? /* @__PURE__ */ f("div", {
66
79
  className: "px-20",
67
- children: /* @__PURE__ */ s("p", {
80
+ children: /* @__PURE__ */ f("p", {
68
81
  className: "text-b3 text-black",
69
- children: d
82
+ children: h
70
83
  })
71
84
  }) : null,
72
- f.map((e) => /* @__PURE__ */ s(n, {
85
+ g.map((e) => /* @__PURE__ */ f(n, {
73
86
  sender: e.sender,
74
87
  children: e.content
75
88
  }, e.id)),
76
- h && /* @__PURE__ */ s("div", {
89
+ y && /* @__PURE__ */ f("div", {
77
90
  className: "px-12",
78
- children: /* @__PURE__ */ s(r, {})
79
- })
91
+ children: /* @__PURE__ */ f(r, {})
92
+ }),
93
+ R && /* @__PURE__ */ f(i, {
94
+ onRate: L,
95
+ labels: E,
96
+ renderRatingLabel: D
97
+ }),
98
+ F && /* @__PURE__ */ f(n, {
99
+ sender: "user",
100
+ children: F
101
+ }),
102
+ F && O && /* @__PURE__ */ f(a, { labels: O })
80
103
  ]
81
104
  }),
82
- /* @__PURE__ */ s("div", {
105
+ /* @__PURE__ */ f("div", {
83
106
  className: "shrink-0 px-8 pb-8 pt-12",
84
- children: /* @__PURE__ */ s(t, {
85
- value: p,
86
- placeholder: m,
87
- onValueChange: g,
88
- onSubmit: _,
89
- onAudioClick: y
107
+ children: /* @__PURE__ */ f(t, {
108
+ value: _,
109
+ placeholder: v,
110
+ onValueChange: b,
111
+ onSubmit: x,
112
+ onAudioClick: C
90
113
  })
91
114
  })
92
115
  ]
93
- }), v && /* @__PURE__ */ s("button", {
116
+ }), S && /* @__PURE__ */ f("button", {
94
117
  type: "button",
95
118
  "aria-label": "Close chat",
96
- onClick: v,
119
+ onClick: S,
97
120
  className: "flex items-center justify-center size-48 rounded-full bg-black border border-black text-white shrink-0 hover:opacity-80 transition-opacity",
98
- children: /* @__PURE__ */ s(o, {
121
+ children: /* @__PURE__ */ f(d, {
99
122
  name: "CrossDefault",
100
123
  width: "24px"
101
124
  })
102
125
  })]
103
126
  });
104
- }
127
+ });
105
128
  //#endregion
106
- export { u as ChatWindow };
129
+ export { h as ChatWindow };
107
130
 
108
131
  //# sourceMappingURL=ChatWindow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWindow.js","names":[],"sources":["../../lib/ui/ChatWindow.tsx"],"sourcesContent":["'use client';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { useEffect, useRef } from 'react';\nimport { twMerge } from './helpers/twMerge';\nimport { ChatInput } from './ChatInput';\nimport { ChatMessage } from './ChatMessage';\nimport type { ChatMessageSender } from './ChatMessage';\nimport { ChatTypingIndicator } from './ChatTypingIndicator';\n\nexport interface ChatWindowMessage {\n id: string;\n sender: ChatMessageSender;\n content: string;\n}\n\nexport interface ChatWindowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n title?: string;\n greeting?: string;\n messages: ChatWindowMessage[];\n inputValue: string;\n inputPlaceholder?: string;\n isTyping?: boolean;\n onInputChange: (value: string) => void;\n onSubmit: () => void;\n onClose?: () => void;\n onAudioClick?: () => void;\n logo?: ReactNode;\n}\n\nconst headerCurve = (\n <svg\n className=\"absolute top-full inset-x-[50%] -translate-x-1/2\"\n width=\"118\"\n height=\"27\"\n viewBox=\"0 0 118 27\"\n >\n <path\n d=\"M0 0C10.8283 0 21.1946 5.40419 28.7327 13.2062L30.2673 14.7945C45.991 31.0685 72.009 31.0685 87.7327 14.7945L89.2673 13.2062C96.8054 5.40419 107.172 0 118 0C118 0 80.6853 0 0 0Z\"\n fill=\"#F6EFE7\"\n />\n </svg>\n);\n\nexport function ChatWindow({\n title = 'Ask me a question',\n greeting,\n messages,\n inputValue,\n inputPlaceholder,\n isTyping = false,\n onInputChange,\n onSubmit,\n onClose,\n onAudioClick,\n logo,\n className,\n ...props\n}: ChatWindowProps) {\n const logRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n // Scroll to bottom on new message or typing indicator change\n const el = logRef.current;\n if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });\n }, [messages, isTyping]);\n\n return (\n <div {...props} className={twMerge('flex flex-col gap-20 items-center', className)}>\n <div className=\"chat-border bg-white flex flex-col h-full w-full rounded-32 overflow-hidden\">\n <div className=\"relative flex flex-col items-center shrink-0 pt-4 px-4 h-133 overflow-hidden\">\n <div className=\"absolute inset-x-4 top-4 h-102 bg-lightSand rounded-[24]\">\n {headerCurve}\n </div>\n <div className=\"relative flex flex-col flex-1 items-center justify-end pb-8 w-full z-10\">\n <div className=\"flex items-center justify-center px-12 py-8 w-full\">\n <p className=\"font-serif font-bold italic text-h5 text-center text-black line-clamp-2\">\n {title}\n </p>\n </div>\n {logo ?? (\n <button\n type=\"button\"\n aria-label=\"AI assistant\"\n className=\"chat-border flex items-center justify-center size-48 rounded-full bg-white\"\n >\n <Icon name=\"Sparkles\" width=\"24px\" />\n </button>\n )}\n </div>\n </div>\n\n <div\n ref={logRef}\n role=\"log\"\n aria-label=\"Chat messages\"\n aria-live=\"polite\"\n className=\"chat-message-log flex flex-col flex-1 gap-20 overflow-y-auto py-20\"\n >\n {greeting ? (\n <div className=\"px-20\">\n <p className=\"text-b3 text-black\">{greeting}</p>\n </div>\n ) : null}\n {messages.map((msg) => (\n <ChatMessage key={msg.id} sender={msg.sender}>\n {msg.content}\n </ChatMessage>\n ))}\n {isTyping && (\n <div className=\"px-12\">\n <ChatTypingIndicator />\n </div>\n )}\n </div>\n\n <div className=\"shrink-0 px-8 pb-8 pt-12\">\n <ChatInput\n value={inputValue}\n placeholder={inputPlaceholder}\n onValueChange={onInputChange}\n onSubmit={onSubmit}\n onAudioClick={onAudioClick}\n />\n </div>\n </div>\n\n {onClose && (\n <button\n type=\"button\"\n aria-label=\"Close chat\"\n onClick={onClose}\n className=\"flex items-center justify-center size-48 rounded-full bg-black border border-black text-white shrink-0 hover:opacity-80 transition-opacity\"\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AA+BA,IAAM,IACJ,kBAAC,OAAD;CACE,WAAU;CACV,OAAM;CACN,QAAO;CACP,SAAQ;WAER,kBAAC,QAAD;EACE,GAAE;EACF,MAAK;EACL,CAAA;CACE,CAAA;AAGR,SAAgB,EAAW,EACzB,WAAQ,qBACR,aACA,aACA,eACA,qBACA,cAAW,IACX,kBACA,aACA,YACA,iBACA,SACA,cACA,GAAG,KACe;CAClB,IAAM,IAAS,EAAuB,KAAK;AAQ3C,QANA,QAAgB;EAEd,IAAM,IAAK,EAAO;AAClB,EAAI,KAAI,EAAG,SAAS;GAAE,KAAK,EAAG;GAAc,UAAU;GAAU,CAAC;IAChE,CAAC,GAAU,EAAS,CAAC,EAGtB,kBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,EAAQ,qCAAqC,EAAU;YAAlF,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACZ;MACG,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA;OACA,CAAA,EACL,KACC,kBAAC,UAAD;OACE,MAAK;OACL,cAAW;OACX,WAAU;iBAEV,kBAAC,GAAD;QAAM,MAAK;QAAW,OAAM;QAAS,CAAA;OAC9B,CAAA,CAAA;;;IAKf,kBAAC,OAAD;KACE,KAAK;KACL,MAAK;KACL,cAAW;KACX,aAAU;KACV,WAAU;eALZ;MAOG,IACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBAAsB;QAAa,CAAA;OAC5C,CAAA,GACJ;MACH,EAAS,KAAK,MACb,kBAAC,GAAD;OAA0B,QAAQ,EAAI;iBACnC,EAAI;OACO,EAFI,EAAI,GAER,CACd;MACD,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAuB,CAAA;OACnB,CAAA;;;IAIV,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACE,OAAO;MACP,aAAa;MACb,eAAe;MACL;MACI;MACd,CAAA;KACE,CAAA;;MAGP,KACC,kBAAC,UAAD;GACE,MAAK;GACL,cAAW;GACX,SAAS;GACT,WAAU;aAEV,kBAAC,GAAD;IAAM,MAAK;IAAe,OAAM;IAAS,CAAA;GAClC,CAAA,CAAA"}
1
+ {"version":3,"file":"ChatWindow.js","names":[],"sources":["../../lib/ui/ChatWindow.tsx"],"sourcesContent":["'use client';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { twMerge } from './helpers/twMerge';\nimport { ChatInput } from './ChatInput';\nimport { ChatMessage } from './ChatMessage';\nimport type { ChatMessageSender } from './ChatMessage';\nimport { ChatTypingIndicator } from './ChatTypingIndicator';\nimport { ChatWindowCsatPrompt } from './ChatWindowCsatPrompt';\nimport type { ChatWindowCsatPromptLabels } from './ChatWindowCsatPrompt';\nimport { ChatWindowCsatThankYou } from './ChatWindowCsatThankYou';\nimport type { ChatWindowCsatThankYouLabels } from './ChatWindowCsatThankYou';\n\nexport type { ChatWindowCsatPromptLabels, ChatWindowCsatThankYouLabels };\n\nexport interface ChatWindowMessage {\n id: string;\n sender: ChatMessageSender;\n content: string;\n}\n\nexport interface ChatWindowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n title?: string;\n greeting?: string;\n messages: ChatWindowMessage[];\n inputValue: string;\n inputPlaceholder?: string;\n isTyping?: boolean;\n onInputChange: (value: string) => void;\n onSubmit: () => void;\n onClose?: () => void;\n onAudioClick?: () => void;\n logo?: ReactNode;\n onFeedbackRate?: (rating: number) => void;\n csatLabels?: ChatWindowCsatPromptLabels;\n csatRenderRatingLabel?: (rating: number) => ReactNode;\n csatThankYouLabels?: ChatWindowCsatThankYouLabels;\n}\n\nexport interface ChatWindowHandle {\n askForFeedback: () => void;\n}\n\nconst headerCurve = (\n <svg\n className=\"absolute top-full inset-x-[50%] -translate-x-1/2\"\n width=\"118\"\n height=\"27\"\n viewBox=\"0 0 118 27\"\n >\n <path\n d=\"M0 0C10.8283 0 21.1946 5.40419 28.7327 13.2062L30.2673 14.7945C45.991 31.0685 72.009 31.0685 87.7327 14.7945L89.2673 13.2062C96.8054 5.40419 107.172 0 118 0C118 0 80.6853 0 0 0Z\"\n fill=\"#F6EFE7\"\n />\n </svg>\n);\n\nexport const ChatWindow = forwardRef<ChatWindowHandle, ChatWindowProps>(function ChatWindow(\n {\n title = 'Ask me a question',\n greeting,\n messages,\n inputValue,\n inputPlaceholder,\n isTyping = false,\n onInputChange,\n onSubmit,\n onClose,\n onAudioClick,\n logo,\n onFeedbackRate,\n csatLabels,\n csatRenderRatingLabel,\n csatThankYouLabels,\n className,\n ...props\n },\n ref,\n) {\n const logRef = useRef<HTMLDivElement>(null);\n const [showCsat, setShowCsat] = useState(false);\n const [csatRatingMessage, setCsatRatingMessage] = useState<string | null>(null);\n\n useImperativeHandle(ref, () => ({\n askForFeedback() {\n setShowCsat(true);\n },\n }));\n\n useEffect(() => {\n const el = logRef.current;\n if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });\n }, [messages, isTyping, showCsat, csatRatingMessage]);\n\n function handleRate(rating: number) {\n const label = csatRenderRatingLabel ? String(csatRenderRatingLabel(rating)) : String(rating);\n setCsatRatingMessage(label);\n onFeedbackRate?.(rating);\n }\n\n const csatReady = showCsat && csatLabels && csatRenderRatingLabel;\n\n return (\n <div {...props} className={twMerge('flex flex-col gap-20 items-center', className)}>\n <div className=\"chat-border bg-white flex flex-col h-full w-full rounded-32 overflow-hidden\">\n <div className=\"relative flex flex-col items-center shrink-0 pt-4 px-4 h-133 overflow-hidden\">\n <div className=\"absolute inset-x-4 top-4 h-102 bg-lightSand rounded-[24]\">\n {headerCurve}\n </div>\n <div className=\"relative flex flex-col flex-1 items-center justify-end pb-8 w-full z-10\">\n <div className=\"flex items-center justify-center px-12 py-8 w-full\">\n <p className=\"font-serif font-bold italic text-h5 text-center text-black line-clamp-2\">\n {title}\n </p>\n </div>\n {logo ?? (\n <button\n type=\"button\"\n aria-label=\"AI assistant\"\n className=\"chat-border flex items-center justify-center size-48 rounded-full bg-white\"\n >\n <Icon name=\"Sparkles\" width=\"24px\" />\n </button>\n )}\n </div>\n </div>\n\n <div\n ref={logRef}\n role=\"log\"\n aria-label=\"Chat messages\"\n aria-live=\"polite\"\n className=\"chat-message-log flex flex-col flex-1 gap-20 overflow-y-auto py-20\"\n >\n {greeting ? (\n <div className=\"px-20\">\n <p className=\"text-b3 text-black\">{greeting}</p>\n </div>\n ) : null}\n {messages.map((msg) => (\n <ChatMessage key={msg.id} sender={msg.sender}>\n {msg.content}\n </ChatMessage>\n ))}\n {isTyping && (\n <div className=\"px-12\">\n <ChatTypingIndicator />\n </div>\n )}\n {csatReady && (\n <ChatWindowCsatPrompt\n onRate={handleRate}\n labels={csatLabels}\n renderRatingLabel={csatRenderRatingLabel}\n />\n )}\n {csatRatingMessage && <ChatMessage sender=\"user\">{csatRatingMessage}</ChatMessage>}\n {csatRatingMessage && csatThankYouLabels && (\n <ChatWindowCsatThankYou labels={csatThankYouLabels} />\n )}\n </div>\n\n <div className=\"shrink-0 px-8 pb-8 pt-12\">\n <ChatInput\n value={inputValue}\n placeholder={inputPlaceholder}\n onValueChange={onInputChange}\n onSubmit={onSubmit}\n onAudioClick={onAudioClick}\n />\n </div>\n </div>\n\n {onClose && (\n <button\n type=\"button\"\n aria-label=\"Close chat\"\n onClick={onClose}\n className=\"flex items-center justify-center size-48 rounded-full bg-black border border-black text-white shrink-0 hover:opacity-80 transition-opacity\"\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n </div>\n );\n});\n"],"mappings":";;;;;;;;;;;AA6CA,IAAM,IACJ,kBAAC,OAAD;CACE,WAAU;CACV,OAAM;CACN,QAAO;CACP,SAAQ;WAER,kBAAC,QAAD;EACE,GAAE;EACF,MAAK;EACL,CAAA;CACE,CAAA,EAGK,IAAa,EAA8C,SACtE,EACE,WAAQ,qBACR,aACA,aACA,eACA,qBACA,cAAW,IACX,kBACA,aACA,YACA,iBACA,SACA,mBACA,eACA,0BACA,uBACA,cACA,GAAG,KAEL,GACA;CACA,IAAM,IAAS,EAAuB,KAAK,EACrC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAmB,KAAwB,EAAwB,KAAK;AAQ/E,CANA,EAAoB,UAAY,EAC9B,iBAAiB;AACf,IAAY,GAAK;IAEpB,EAAE,EAEH,QAAgB;EACd,IAAM,IAAK,EAAO;AAClB,EAAI,KAAI,EAAG,SAAS;GAAE,KAAK,EAAG;GAAc,UAAU;GAAU,CAAC;IAChE;EAAC;EAAU;EAAU;EAAU;EAAkB,CAAC;CAErD,SAAS,EAAW,GAAgB;AAGlC,EADA,EADsC,OAAxB,IAA+B,EAAsB,EAAO,GAAW,EAAO,CACjE,EAC3B,IAAiB,EAAO;;CAG1B,IAAM,IAAY,KAAY,KAAc;AAE5C,QACE,kBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,EAAQ,qCAAqC,EAAU;YAAlF,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACZ;MACG,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA;OACA,CAAA,EACL,KACC,kBAAC,UAAD;OACE,MAAK;OACL,cAAW;OACX,WAAU;iBAEV,kBAAC,GAAD;QAAM,MAAK;QAAW,OAAM;QAAS,CAAA;OAC9B,CAAA,CAAA;;;IAKf,kBAAC,OAAD;KACE,KAAK;KACL,MAAK;KACL,cAAW;KACX,aAAU;KACV,WAAU;eALZ;MAOG,IACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBAAsB;QAAa,CAAA;OAC5C,CAAA,GACJ;MACH,EAAS,KAAK,MACb,kBAAC,GAAD;OAA0B,QAAQ,EAAI;iBACnC,EAAI;OACO,EAFI,EAAI,GAER,CACd;MACD,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAuB,CAAA;OACnB,CAAA;MAEP,KACC,kBAAC,GAAD;OACE,QAAQ;OACR,QAAQ;OACR,mBAAmB;OACnB,CAAA;MAEH,KAAqB,kBAAC,GAAD;OAAa,QAAO;iBAAQ;OAAgC,CAAA;MACjF,KAAqB,KACpB,kBAAC,GAAD,EAAwB,QAAQ,GAAsB,CAAA;;;IAI1D,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACE,OAAO;MACP,aAAa;MACb,eAAe;MACL;MACI;MACd,CAAA;KACE,CAAA;;MAGP,KACC,kBAAC,UAAD;GACE,MAAK;GACL,cAAW;GACX,SAAS;GACT,WAAU;aAEV,kBAAC,GAAD;IAAM,MAAK;IAAe,OAAM;IAAS,CAAA;GAClC,CAAA,CAAA;;EAIf"}
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ChatWindowCsatPromptLabels {
3
+ intro: string;
4
+ question: string;
5
+ questionNote: string;
6
+ groupAriaLabel: string;
7
+ starLabels: [string, string, string, string, string];
8
+ }
9
+ export interface ChatWindowCsatPromptProps {
10
+ onRate: (rating: number) => void;
11
+ labels: ChatWindowCsatPromptLabels;
12
+ renderRatingLabel: (rating: number) => ReactNode;
13
+ className?: string;
14
+ }
15
+ export declare function ChatWindowCsatPrompt({ onRate, labels, renderRatingLabel, className, }: ChatWindowCsatPromptProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,71 @@
1
+ "use client";
2
+ import { twMerge as e } from "./helpers/twMerge.js";
3
+ import { useState as t } from "react";
4
+ import { Icon as n } from "@clubmed/trident-icons";
5
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
6
+ //#region lib/ui/ChatWindowCsatPrompt.tsx
7
+ function a({ onRate: a, labels: o, renderRatingLabel: s, className: c }) {
8
+ let [l, u] = t(0), [d, f] = t(0);
9
+ function p(e) {
10
+ d > 0 || (f(e), a(e));
11
+ }
12
+ let m = l || d, h = d > 0;
13
+ return /* @__PURE__ */ i("div", {
14
+ className: e("flex flex-col gap-20 px-20", c),
15
+ children: [
16
+ /* @__PURE__ */ i("div", {
17
+ className: "flex flex-col gap-4",
18
+ children: [/* @__PURE__ */ r("p", {
19
+ className: "text-b3 text-black",
20
+ children: o.intro
21
+ }), /* @__PURE__ */ i("p", {
22
+ className: "text-b3 text-black",
23
+ children: [
24
+ o.question,
25
+ " ",
26
+ /* @__PURE__ */ r("span", {
27
+ className: "text-b4 text-black",
28
+ children: o.questionNote
29
+ })
30
+ ]
31
+ })]
32
+ }),
33
+ /* @__PURE__ */ r("div", {
34
+ role: "group",
35
+ "aria-label": o.groupAriaLabel,
36
+ className: "flex items-center gap-0",
37
+ children: o.starLabels.map((t, i) => {
38
+ let a = i + 1, o = a <= m;
39
+ return /* @__PURE__ */ r("button", {
40
+ type: "button",
41
+ "aria-label": `${a} star${a > 1 ? "s" : ""} — ${t}`,
42
+ "aria-pressed": d === a,
43
+ "aria-disabled": h,
44
+ onClick: () => p(a),
45
+ onMouseEnter: () => {
46
+ h || u(a);
47
+ },
48
+ onMouseLeave: () => {
49
+ h || u(0);
50
+ },
51
+ className: e("flex items-center justify-center size-48 rounded-full transition-colors", h ? "cursor-default" : "hover:bg-lightSand"),
52
+ children: /* @__PURE__ */ r(n, {
53
+ name: o ? "StarFilled" : "StarOutlined",
54
+ width: "24px",
55
+ className: "text-black"
56
+ })
57
+ }, a);
58
+ })
59
+ }),
60
+ m > 0 && /* @__PURE__ */ r("p", {
61
+ className: "text-b4 text-darkGrey",
62
+ "aria-live": "polite",
63
+ children: s(m)
64
+ })
65
+ ]
66
+ });
67
+ }
68
+ //#endregion
69
+ export { a as ChatWindowCsatPrompt };
70
+
71
+ //# sourceMappingURL=ChatWindowCsatPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWindowCsatPrompt.js","names":[],"sources":["../../lib/ui/ChatWindowCsatPrompt.tsx"],"sourcesContent":["'use client';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport type { ReactNode } from 'react';\nimport { useState } from 'react';\nimport { twMerge } from './helpers/twMerge';\n\nexport interface ChatWindowCsatPromptLabels {\n intro: string;\n question: string;\n questionNote: string;\n groupAriaLabel: string;\n starLabels: [string, string, string, string, string];\n}\n\nexport interface ChatWindowCsatPromptProps {\n onRate: (rating: number) => void;\n labels: ChatWindowCsatPromptLabels;\n renderRatingLabel: (rating: number) => ReactNode;\n className?: string;\n}\n\nexport function ChatWindowCsatPrompt({\n onRate,\n labels,\n renderRatingLabel,\n className,\n}: ChatWindowCsatPromptProps) {\n const [hovered, setHovered] = useState(0);\n const [selected, setSelected] = useState(0);\n\n function handleSelect(rating: number) {\n if (selected > 0) return;\n setSelected(rating);\n onRate(rating);\n }\n\n const activeRating = hovered || selected;\n const isLocked = selected > 0;\n\n return (\n <div className={twMerge('flex flex-col gap-20 px-20', className)}>\n <div className=\"flex flex-col gap-4\">\n <p className=\"text-b3 text-black\">{labels.intro}</p>\n <p className=\"text-b3 text-black\">\n {labels.question} <span className=\"text-b4 text-black\">{labels.questionNote}</span>\n </p>\n </div>\n\n <div role=\"group\" aria-label={labels.groupAriaLabel} className=\"flex items-center gap-0\">\n {labels.starLabels.map((label, i) => {\n const rating = i + 1;\n const isFilled = rating <= activeRating;\n return (\n <button\n key={rating}\n type=\"button\"\n aria-label={`${rating} star${rating > 1 ? 's' : ''} — ${label}`}\n aria-pressed={selected === rating}\n aria-disabled={isLocked}\n onClick={() => handleSelect(rating)}\n onMouseEnter={() => {\n if (!isLocked) setHovered(rating);\n }}\n onMouseLeave={() => {\n if (!isLocked) setHovered(0);\n }}\n className={twMerge(\n 'flex items-center justify-center size-48 rounded-full transition-colors',\n isLocked ? 'cursor-default' : 'hover:bg-lightSand',\n )}\n >\n <Icon\n name={isFilled ? 'StarFilled' : 'StarOutlined'}\n width=\"24px\"\n className=\"text-black\"\n />\n </button>\n );\n })}\n </div>\n\n {activeRating > 0 && (\n <p className=\"text-b4 text-darkGrey\" aria-live=\"polite\">\n {renderRatingLabel(activeRating)}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;AAsBA,SAAgB,EAAqB,EACnC,WACA,WACA,sBACA,gBAC4B;CAC5B,IAAM,CAAC,GAAS,KAAc,EAAS,EAAE,EACnC,CAAC,GAAU,KAAe,EAAS,EAAE;CAE3C,SAAS,EAAa,GAAgB;AAChC,MAAW,MACf,EAAY,EAAO,EACnB,EAAO,EAAO;;CAGhB,IAAM,IAAe,KAAW,GAC1B,IAAW,IAAW;AAE5B,QACE,kBAAC,OAAD;EAAK,WAAW,EAAQ,8BAA8B,EAAU;YAAhE;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAsB,EAAO;KAAU,CAAA,EACpD,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAO;MAAS;MAAC,kBAAC,QAAD;OAAM,WAAU;iBAAsB,EAAO;OAAoB,CAAA;;;;GAIvF,kBAAC,OAAD;IAAK,MAAK;IAAQ,cAAY,EAAO;IAAgB,WAAU;cAC5D,EAAO,WAAW,KAAK,GAAO,MAAM;KACnC,IAAM,IAAS,IAAI,GACb,IAAW,KAAU;AAC3B,YACE,kBAAC,UAAD;MAEE,MAAK;MACL,cAAY,GAAG,EAAO,OAAO,IAAS,IAAI,MAAM,GAAG,KAAK;MACxD,gBAAc,MAAa;MAC3B,iBAAe;MACf,eAAe,EAAa,EAAO;MACnC,oBAAoB;AAClB,OAAK,KAAU,EAAW,EAAO;;MAEnC,oBAAoB;AAClB,OAAK,KAAU,EAAW,EAAE;;MAE9B,WAAW,EACT,2EACA,IAAW,mBAAmB,qBAC/B;gBAED,kBAAC,GAAD;OACE,MAAM,IAAW,eAAe;OAChC,OAAM;OACN,WAAU;OACV,CAAA;MACK,EAtBF,EAsBE;;IAGT,CAAA;GAEL,IAAe,KACd,kBAAC,KAAD;IAAG,WAAU;IAAwB,aAAU;cAC5C,EAAkB,EAAA;IACjB,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { HTMLAttributes } from 'react';
2
+ export interface ChatWindowCsatThankYouLabels {
3
+ title: string;
4
+ body: string;
5
+ }
6
+ export interface ChatWindowCsatThankYouProps extends HTMLAttributes<HTMLDivElement> {
7
+ labels: ChatWindowCsatThankYouLabels;
8
+ }
9
+ export declare function ChatWindowCsatThankYou({ labels, className, ...props }: ChatWindowCsatThankYouProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { twMerge as e } from "./helpers/twMerge.js";
3
+ import { Icon as t } from "@clubmed/trident-icons";
4
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ //#region lib/ui/ChatWindowCsatThankYou.tsx
6
+ function i({ labels: i, className: a, ...o }) {
7
+ return /* @__PURE__ */ r("div", {
8
+ ...o,
9
+ className: e("flex flex-col gap-20 px-20", a),
10
+ children: [/* @__PURE__ */ r("div", {
11
+ className: "flex items-center gap-4 text-green",
12
+ children: [/* @__PURE__ */ n(t, {
13
+ name: "CheckFilled",
14
+ width: "24px",
15
+ className: "shrink-0"
16
+ }), /* @__PURE__ */ n("p", {
17
+ className: "text-b3 font-semibold text-black",
18
+ children: i.title
19
+ })]
20
+ }), /* @__PURE__ */ n("p", {
21
+ className: "text-b3 text-black",
22
+ children: i.body
23
+ })]
24
+ });
25
+ }
26
+ //#endregion
27
+ export { i as ChatWindowCsatThankYou };
28
+
29
+ //# sourceMappingURL=ChatWindowCsatThankYou.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWindowCsatThankYou.js","names":[],"sources":["../../lib/ui/ChatWindowCsatThankYou.tsx"],"sourcesContent":["'use client';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport type { HTMLAttributes } from 'react';\nimport { twMerge } from './helpers/twMerge';\n\nexport interface ChatWindowCsatThankYouLabels {\n title: string;\n body: string;\n}\n\nexport interface ChatWindowCsatThankYouProps extends HTMLAttributes<HTMLDivElement> {\n labels: ChatWindowCsatThankYouLabels;\n}\n\nexport function ChatWindowCsatThankYou({\n labels,\n className,\n ...props\n}: ChatWindowCsatThankYouProps) {\n return (\n <div {...props} className={twMerge('flex flex-col gap-20 px-20', className)}>\n <div className=\"flex items-center gap-4 text-green\">\n <Icon name=\"CheckFilled\" width=\"24px\" className=\"shrink-0\" />\n <p className=\"text-b3 font-semibold text-black\">{labels.title}</p>\n </div>\n <p className=\"text-b3 text-black\">{labels.body}</p>\n </div>\n );\n}\n"],"mappings":";;;;;AAeA,SAAgB,EAAuB,EACrC,WACA,cACA,GAAG,KAC2B;AAC9B,QACE,kBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,EAAQ,8BAA8B,EAAU;YAA3E,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAM,MAAK;IAAc,OAAM;IAAO,WAAU;IAAa,CAAA,EAC7D,kBAAC,KAAD;IAAG,WAAU;cAAoC,EAAO;IAAU,CAAA,CAAA;MAEpE,kBAAC,KAAD;GAAG,WAAU;aAAsB,EAAO;GAAS,CAAA,CAAA"}