@clubmed/trident-ui 2.0.0-beta.56 → 2.0.0-beta.58
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/examples/advanced-toast-demo.js +2 -2
- package/examples/advanced-toast-demo.js.map +1 -1
- package/examples/advanced-toast-green-demo.js +1 -1
- package/examples/advanced-toast-green-demo.js.map +1 -1
- package/examples/advanced-toast-no-dismiss-demo.js +1 -1
- package/examples/advanced-toast-no-dismiss-demo.js.map +1 -1
- package/examples/advanced-toast-red-demo.js +1 -1
- package/examples/advanced-toast-red-demo.js.map +1 -1
- package/examples/advanced-toast-with-details-demo.js +2 -2
- package/examples/advanced-toast-with-details-demo.js.map +1 -1
- package/examples/chat-window-csat-demo.d.ts +1 -0
- package/examples/chat-window-csat-demo.js +68 -0
- package/examples/chat-window-csat-demo.js.map +1 -0
- package/examples/chat-window-csat-prompt-demo.d.ts +1 -0
- package/examples/chat-window-csat-prompt-demo.js +40 -0
- package/examples/chat-window-csat-prompt-demo.js.map +1 -0
- package/examples/chat-window-demo.js +41 -17
- package/examples/chat-window-demo.js.map +1 -1
- package/examples/chat-window-quote-demo.d.ts +1 -0
- package/examples/chat-window-quote-demo.js +47 -0
- package/examples/chat-window-quote-demo.js.map +1 -0
- package/examples/chat-window-quotes-demo.d.ts +1 -0
- package/examples/chat-window-quotes-demo.js +67 -0
- package/examples/chat-window-quotes-demo.js.map +1 -0
- package/package.json +1 -1
- package/ui/AdvancedToast.js +7 -4
- package/ui/AdvancedToast.js.map +1 -1
- package/ui/ChatWindow.d.ts +14 -1
- package/ui/ChatWindow.js +78 -44
- package/ui/ChatWindow.js.map +1 -1
- package/ui/ChatWindowCsatPrompt.d.ts +15 -0
- package/ui/ChatWindowCsatPrompt.js +71 -0
- package/ui/ChatWindowCsatPrompt.js.map +1 -0
- package/ui/ChatWindowCsatThankYou.d.ts +9 -0
- package/ui/ChatWindowCsatThankYou.js +29 -0
- package/ui/ChatWindowCsatThankYou.js.map +1 -0
- package/ui/ChatWindowQuote.d.ts +22 -0
- package/ui/ChatWindowQuote.js +141 -0
- package/ui/ChatWindowQuote.js.map +1 -0
|
@@ -11,14 +11,14 @@ function l() {
|
|
|
11
11
|
n.custom((r) => /* @__PURE__ */ s(t, {
|
|
12
12
|
title: "Upload Complete",
|
|
13
13
|
body: "Your file has been successfully uploaded",
|
|
14
|
-
icon: "
|
|
14
|
+
icon: "CheckFilled",
|
|
15
15
|
isVisible: r.visible,
|
|
16
16
|
labels: {
|
|
17
17
|
close: "Close",
|
|
18
18
|
details: "Details"
|
|
19
19
|
},
|
|
20
20
|
onClose: () => n.dismiss(r.id),
|
|
21
|
-
accentColor: e.
|
|
21
|
+
accentColor: e.green,
|
|
22
22
|
toastId: r.id,
|
|
23
23
|
updateHeight: l.updateHeight
|
|
24
24
|
}), { duration: Infinity });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-toast-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Upload Complete\"\n body=\"Your file has been successfully uploaded\"\n icon=\"
|
|
1
|
+
{"version":3,"file":"advanced-toast-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Upload Complete\"\n body=\"Your file has been successfully uploaded\"\n icon=\"CheckFilled\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.green}\n toastId={t.id}\n updateHeight={handlers.updateHeight}\n />\n ),\n { duration: Infinity },\n );\n };\n\n return (\n <>\n <Toaster {...(getHotToastConfig() as ToasterProps)} />\n <button onClick={showToast}>Show Toast</button>\n </>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,IAAoB;CAC1C,IAAM,EAAE,gBAAa,GAAY,EAE3B,UAAkB;AACtB,IAAM,QACH,MACC,kBAAC,GAAD;GACE,OAAM;GACN,MAAK;GACL,MAAK;GACL,WAAW,EAAE;GACb,QAAQ;IAAE,OAAO;IAAS,SAAS;IAAW;GAC9C,eAAe,EAAM,QAAQ,EAAE,GAAG;GAClC,aAAa,EAAO;GACpB,SAAS,EAAE;GACX,cAAc,EAAS;GACvB,CAAA,EAEJ,EAAE,UAAU,UAAU,CACvB;;AAGH,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,GAAK,GAAmB,EAAqB,CAAA,EACtD,kBAAC,UAAD;EAAQ,SAAS;YAAW;EAAmB,CAAA,CAC9C,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-toast-green-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-green-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastGreenDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Success!\"\n body=\"Your changes have been saved successfully\"\n icon=\"
|
|
1
|
+
{"version":3,"file":"advanced-toast-green-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-green-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastGreenDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Success!\"\n body=\"Your changes have been saved successfully\"\n icon=\"CheckFilled\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.green}\n toastId={t.id}\n updateHeight={handlers.updateHeight}\n />\n ),\n { duration: Infinity },\n );\n };\n\n return (\n <>\n <Toaster {...(getHotToastConfig() as ToasterProps)} />\n <button onClick={showToast}>Show Toast</button>\n </>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,IAAyB;CAC/C,IAAM,EAAE,gBAAa,GAAY,EAE3B,UAAkB;AACtB,IAAM,QACH,MACC,kBAAC,GAAD;GACE,OAAM;GACN,MAAK;GACL,MAAK;GACL,WAAW,EAAE;GACb,QAAQ;IAAE,OAAO;IAAS,SAAS;IAAW;GAC9C,eAAe,EAAM,QAAQ,EAAE,GAAG;GAClC,aAAa,EAAO;GACpB,SAAS,EAAE;GACX,cAAc,EAAS;GACvB,CAAA,EAEJ,EAAE,UAAU,UAAU,CACvB;;AAGH,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,GAAK,GAAmB,EAAqB,CAAA,EACtD,kBAAC,UAAD;EAAQ,SAAS;YAAW;EAAmB,CAAA,CAC9C,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-toast-no-dismiss-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-no-dismiss-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastNoDismissDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Important Notice\"\n body=\"This notification will not auto-dismiss\"\n icon=\"Trident\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.
|
|
1
|
+
{"version":3,"file":"advanced-toast-no-dismiss-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-no-dismiss-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastNoDismissDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Important Notice\"\n body=\"This notification will not auto-dismiss\"\n icon=\"Trident\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.darkGrey}\n duration={false}\n toastId={t.id}\n updateHeight={handlers.updateHeight}\n />\n ),\n { duration: Infinity },\n );\n };\n\n return (\n <>\n <Toaster {...(getHotToastConfig() as ToasterProps)} />\n <button onClick={showToast}>Show Toast</button>\n </>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,IAA6B;CACnD,IAAM,EAAE,gBAAa,GAAY,EAE3B,UAAkB;AACtB,IAAM,QACH,MACC,kBAAC,GAAD;GACE,OAAM;GACN,MAAK;GACL,MAAK;GACL,WAAW,EAAE;GACb,QAAQ;IAAE,OAAO;IAAS,SAAS;IAAW;GAC9C,eAAe,EAAM,QAAQ,EAAE,GAAG;GAClC,aAAa,EAAO;GACpB,UAAU;GACV,SAAS,EAAE;GACX,cAAc,EAAS;GACvB,CAAA,EAEJ,EAAE,UAAU,UAAU,CACvB;;AAGH,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,GAAK,GAAmB,EAAqB,CAAA,EACtD,kBAAC,UAAD;EAAQ,SAAS;YAAW;EAAmB,CAAA,CAC9C,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-toast-red-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-red-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastRedDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Error\"\n body=\"Something went wrong. Please try again.\"\n icon=\"
|
|
1
|
+
{"version":3,"file":"advanced-toast-red-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-red-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastRedDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Error\"\n body=\"Something went wrong. Please try again.\"\n icon=\"Error\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.red}\n toastId={t.id}\n updateHeight={handlers.updateHeight}\n />\n ),\n { duration: Infinity },\n );\n };\n\n return (\n <>\n <Toaster {...(getHotToastConfig() as ToasterProps)} />\n <button onClick={showToast}>Show Toast</button>\n </>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,IAAuB;CAC7C,IAAM,EAAE,gBAAa,GAAY,EAE3B,UAAkB;AACtB,IAAM,QACH,MACC,kBAAC,GAAD;GACE,OAAM;GACN,MAAK;GACL,MAAK;GACL,WAAW,EAAE;GACb,QAAQ;IAAE,OAAO;IAAS,SAAS;IAAW;GAC9C,eAAe,EAAM,QAAQ,EAAE,GAAG;GAClC,aAAa,EAAO;GACpB,SAAS,EAAE;GACX,cAAc,EAAS;GACvB,CAAA,EAEJ,EAAE,UAAU,UAAU,CACvB;;AAGH,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,GAAK,GAAmB,EAAqB,CAAA,EACtD,kBAAC,UAAD;EAAQ,SAAS;YAAW;EAAmB,CAAA,CAC9C,EAAA,CAAA"}
|
|
@@ -11,14 +11,14 @@ function l() {
|
|
|
11
11
|
n.custom((r) => /* @__PURE__ */ s(t, {
|
|
12
12
|
title: "Upload Complete",
|
|
13
13
|
body: "Your file has been successfully uploaded",
|
|
14
|
-
icon: "
|
|
14
|
+
icon: "CheckFilled",
|
|
15
15
|
isVisible: r.visible,
|
|
16
16
|
labels: {
|
|
17
17
|
close: "Close",
|
|
18
18
|
details: "Details"
|
|
19
19
|
},
|
|
20
20
|
onClose: () => n.dismiss(r.id),
|
|
21
|
-
accentColor: e.
|
|
21
|
+
accentColor: e.green,
|
|
22
22
|
toastId: r.id,
|
|
23
23
|
updateHeight: l.updateHeight,
|
|
24
24
|
children: /* @__PURE__ */ c("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"advanced-toast-with-details-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-with-details-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastWithDetailsDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Upload Complete\"\n body=\"Your file has been successfully uploaded\"\n icon=\"
|
|
1
|
+
{"version":3,"file":"advanced-toast-with-details-demo.js","names":[],"sources":["../../lib/examples/advanced-toast-with-details-demo.tsx"],"sourcesContent":["'use client';\n\nimport { AdvancedToast } from '@/ui/AdvancedToast';\nimport { type ToasterProps, Toaster, toast, useToaster } from 'react-hot-toast';\nimport { getHotToastConfig } from '@/ui/AdvancedToast.config';\nimport { Colors } from '@/ui/helpers/colors/colors';\n\nexport default function AdvancedToastWithDetailsDemo() {\n const { handlers } = useToaster();\n\n const showToast = () => {\n toast.custom(\n (t) => (\n <AdvancedToast\n title=\"Upload Complete\"\n body=\"Your file has been successfully uploaded\"\n icon=\"CheckFilled\"\n isVisible={t.visible}\n labels={{ close: 'Close', details: 'Details' }}\n onClose={() => toast.dismiss(t.id)}\n accentColor={Colors.green}\n toastId={t.id}\n updateHeight={handlers.updateHeight}\n >\n <div className=\"text-b4\">\n <p>File: document.pdf</p>\n <p>Size: 2.5 MB</p>\n <p>Uploaded at: {new Date().toLocaleTimeString()}</p>\n </div>\n </AdvancedToast>\n ),\n { duration: Infinity },\n );\n };\n\n return (\n <>\n <Toaster {...(getHotToastConfig() as ToasterProps)} />\n <button onClick={showToast}>Show Toast</button>\n </>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,IAA+B;CACrD,IAAM,EAAE,gBAAa,GAAY,EAE3B,UAAkB;AACtB,IAAM,QACH,MACC,kBAAC,GAAD;GACE,OAAM;GACN,MAAK;GACL,MAAK;GACL,WAAW,EAAE;GACb,QAAQ;IAAE,OAAO;IAAS,SAAS;IAAW;GAC9C,eAAe,EAAM,QAAQ,EAAE,GAAG;GAClC,aAAa,EAAO;GACpB,SAAS,EAAE;GACX,cAAc,EAAS;aAEvB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,KAAD,EAAA,UAAG,sBAAsB,CAAA;KACzB,kBAAC,KAAD,EAAA,UAAG,gBAAgB,CAAA;KACnB,kBAAC,KAAD,EAAA,UAAA,CAAG,kCAAc,IAAI,MAAM,EAAC,oBAAoB,CAAK,EAAA,CAAA;;;GAEzC,CAAA,EAElB,EAAE,UAAU,UAAU,CACvB;;AAGH,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,GAAK,GAAmB,EAAqB,CAAA,EACtD,kBAAC,UAAD;EAAQ,SAAS;YAAW;EAAmB,CAAA,CAC9C,EAAA,CAAA"}
|
|
@@ -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 {
|
|
4
|
-
import { jsx as
|
|
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
|
-
|
|
7
|
-
|
|
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
|
-
}]), [
|
|
16
|
-
function
|
|
17
|
-
if (!
|
|
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:
|
|
40
|
+
content: u
|
|
22
41
|
};
|
|
23
|
-
|
|
24
|
-
|
|
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__ */
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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 {
|
|
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 {
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function ChatWindowQuoteDemo(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { ChatWindowQuote as e } from "../ui/ChatWindowQuote.js";
|
|
3
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
4
|
+
//#region lib/examples/chat-window-quote-demo.tsx
|
|
5
|
+
var r = {
|
|
6
|
+
id: "1",
|
|
7
|
+
resortName: "Cancún",
|
|
8
|
+
country: "Mexico",
|
|
9
|
+
imageUrl: "https://picsum.photos/seed/cancun/400/300",
|
|
10
|
+
dateRange: "15 June 2026 to 24 June 2026",
|
|
11
|
+
pax: "for 2 adults 2 children",
|
|
12
|
+
packageIncludes: [
|
|
13
|
+
"Meals and snacks at any time",
|
|
14
|
+
"Drinks, alcoholic and non-alcoholic",
|
|
15
|
+
"Sports and activities"
|
|
16
|
+
],
|
|
17
|
+
additionalInfo: "You can customise your transport and room category directly on the website."
|
|
18
|
+
}, i = {
|
|
19
|
+
id: "2",
|
|
20
|
+
resortName: "Punta Cana",
|
|
21
|
+
country: "Dominican Republic",
|
|
22
|
+
imageUrl: "https://picsum.photos/seed/puntacana/400/300",
|
|
23
|
+
dateRange: "20 July 2026 to 29 July 2026",
|
|
24
|
+
pax: "for 2 adults 2 children"
|
|
25
|
+
};
|
|
26
|
+
function a() {
|
|
27
|
+
return /* @__PURE__ */ n("div", {
|
|
28
|
+
className: "flex flex-col gap-32 w-340",
|
|
29
|
+
children: [/* @__PURE__ */ n("div", {
|
|
30
|
+
className: "flex flex-col gap-8",
|
|
31
|
+
children: [/* @__PURE__ */ t("p", {
|
|
32
|
+
className: "text-b4 font-semibold text-black",
|
|
33
|
+
children: "Single quote"
|
|
34
|
+
}), /* @__PURE__ */ t(e, { quotes: [r] })]
|
|
35
|
+
}), /* @__PURE__ */ n("div", {
|
|
36
|
+
className: "flex flex-col gap-8",
|
|
37
|
+
children: [/* @__PURE__ */ t("p", {
|
|
38
|
+
className: "text-b4 font-semibold text-black",
|
|
39
|
+
children: "Multiple quotes"
|
|
40
|
+
}), /* @__PURE__ */ t(e, { quotes: [r, i] })]
|
|
41
|
+
})]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { a as default };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=chat-window-quote-demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-window-quote-demo.js","names":[],"sources":["../../lib/examples/chat-window-quote-demo.tsx"],"sourcesContent":["'use client';\n\nimport { ChatWindowQuote } from '@/ui/ChatWindowQuote';\nimport type { ChatWindowQuoteItem } from '@/ui/ChatWindowQuote';\n\nconst cancun: ChatWindowQuoteItem = {\n id: '1',\n resortName: 'Cancún',\n country: 'Mexico',\n imageUrl: 'https://picsum.photos/seed/cancun/400/300',\n dateRange: '15 June 2026 to 24 June 2026',\n pax: 'for 2 adults 2 children',\n packageIncludes: [\n 'Meals and snacks at any time',\n 'Drinks, alcoholic and non-alcoholic',\n 'Sports and activities',\n ],\n additionalInfo: 'You can customise your transport and room category directly on the website.',\n};\n\nconst puntaCana: ChatWindowQuoteItem = {\n id: '2',\n resortName: 'Punta Cana',\n country: 'Dominican Republic',\n imageUrl: 'https://picsum.photos/seed/puntacana/400/300',\n dateRange: '20 July 2026 to 29 July 2026',\n pax: 'for 2 adults 2 children',\n};\n\nexport default function ChatWindowQuoteDemo() {\n return (\n <div className=\"flex flex-col gap-32 w-340\">\n <div className=\"flex flex-col gap-8\">\n <p className=\"text-b4 font-semibold text-black\">Single quote</p>\n <ChatWindowQuote quotes={[cancun]} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <p className=\"text-b4 font-semibold text-black\">Multiple quotes</p>\n <ChatWindowQuote quotes={[cancun, puntaCana]} />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AAKA,IAAM,IAA8B;CAClC,IAAI;CACJ,YAAY;CACZ,SAAS;CACT,UAAU;CACV,WAAW;CACX,KAAK;CACL,iBAAiB;EACf;EACA;EACA;EACD;CACD,gBAAgB;CACjB,EAEK,IAAiC;CACrC,IAAI;CACJ,YAAY;CACZ,SAAS;CACT,UAAU;CACV,WAAW;CACX,KAAK;CACN;AAED,SAAwB,IAAsB;AAC5C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAAgB,CAAA,EAChE,kBAAC,GAAD,EAAiB,QAAQ,CAAC,EAAO,EAAI,CAAA,CAAA;MAEvC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAmC;IAAmB,CAAA,EACnE,kBAAC,GAAD,EAAiB,QAAQ,CAAC,GAAQ,EAAU,EAAI,CAAA,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function ChatWindowQuotesDemo(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
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-quotes-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: "Can you show me some quotes for a family trip to the Caribbean?"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "3",
|
|
19
|
+
sender: "assistant",
|
|
20
|
+
content: "Of course! Here are some resorts in the Caribbean that could be perfect for your family vacation."
|
|
21
|
+
}
|
|
22
|
+
], a = [{
|
|
23
|
+
id: "1",
|
|
24
|
+
resortName: "Cancún",
|
|
25
|
+
country: "Mexico",
|
|
26
|
+
imageUrl: "https://picsum.photos/seed/cancun/400/300",
|
|
27
|
+
dateRange: "15 June 2026 to 24 June 2026",
|
|
28
|
+
pax: "for 2 adults 2 children",
|
|
29
|
+
packageIncludes: [
|
|
30
|
+
"Meals and snacks at any time",
|
|
31
|
+
"Drinks, alcoholic and non-alcoholic",
|
|
32
|
+
"Sports and activities"
|
|
33
|
+
],
|
|
34
|
+
additionalInfo: "You can customise your transport and room category directly on the website."
|
|
35
|
+
}, {
|
|
36
|
+
id: "2",
|
|
37
|
+
resortName: "Punta Cana",
|
|
38
|
+
country: "Dominican Republic",
|
|
39
|
+
imageUrl: "https://picsum.photos/seed/puntacana/400/300",
|
|
40
|
+
dateRange: "15 June 2026 to 24 June 2026",
|
|
41
|
+
pax: "for 2 adults 2 children"
|
|
42
|
+
}];
|
|
43
|
+
function o() {
|
|
44
|
+
let o = t(null);
|
|
45
|
+
return /* @__PURE__ */ r("div", {
|
|
46
|
+
className: "flex flex-col items-center gap-12",
|
|
47
|
+
children: [/* @__PURE__ */ n(e, {
|
|
48
|
+
ref: o,
|
|
49
|
+
messages: i,
|
|
50
|
+
inputValue: "",
|
|
51
|
+
onInputChange: () => {},
|
|
52
|
+
onSubmit: () => {},
|
|
53
|
+
onQuoteCtaClick: (e) => console.log("Selected quote:", e.resortName),
|
|
54
|
+
onClose: () => {},
|
|
55
|
+
className: "w-380 h-660"
|
|
56
|
+
}), /* @__PURE__ */ n("button", {
|
|
57
|
+
type: "button",
|
|
58
|
+
onClick: () => o.current?.showQuotes(a),
|
|
59
|
+
className: "px-16 py-8 bg-saffron rounded-pill text-black text-b4 font-semibold hover:opacity-80 transition-opacity",
|
|
60
|
+
children: "Trigger quotes"
|
|
61
|
+
})]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { o as default };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=chat-window-quotes-demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-window-quotes-demo.js","names":[],"sources":["../../lib/examples/chat-window-quotes-demo.tsx"],"sourcesContent":["'use client';\n\nimport { useRef } from 'react';\nimport { ChatWindow } from '@/ui/ChatWindow';\nimport type { ChatWindowHandle, ChatWindowMessage, ChatWindowQuoteItem } 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: 'Can you show me some quotes for a family trip to the Caribbean?',\n },\n {\n id: '3',\n sender: 'assistant',\n content:\n 'Of course! Here are some resorts in the Caribbean that could be perfect for your family vacation.',\n },\n];\n\nconst quotes: ChatWindowQuoteItem[] = [\n {\n id: '1',\n resortName: 'Cancún',\n country: 'Mexico',\n imageUrl: 'https://picsum.photos/seed/cancun/400/300',\n dateRange: '15 June 2026 to 24 June 2026',\n pax: 'for 2 adults 2 children',\n packageIncludes: [\n 'Meals and snacks at any time',\n 'Drinks, alcoholic and non-alcoholic',\n 'Sports and activities',\n ],\n additionalInfo: 'You can customise your transport and room category directly on the website.',\n },\n {\n id: '2',\n resortName: 'Punta Cana',\n country: 'Dominican Republic',\n imageUrl: 'https://picsum.photos/seed/puntacana/400/300',\n dateRange: '15 June 2026 to 24 June 2026',\n pax: 'for 2 adults 2 children',\n },\n];\n\nexport default function ChatWindowQuotesDemo() {\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 onQuoteCtaClick={(quote) => console.log('Selected quote:', quote.resortName)}\n onClose={() => {}}\n className=\"w-380 h-660\"\n />\n <button\n type=\"button\"\n onClick={() => chatRef.current?.showQuotes(quotes)}\n className=\"px-16 py-8 bg-saffron rounded-pill text-black text-b4 font-semibold hover:opacity-80 transition-opacity\"\n >\n Trigger quotes\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;AAMA,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,IAAgC,CACpC;CACE,IAAI;CACJ,YAAY;CACZ,SAAS;CACT,UAAU;CACV,WAAW;CACX,KAAK;CACL,iBAAiB;EACf;EACA;EACA;EACD;CACD,gBAAgB;CACjB,EACD;CACE,IAAI;CACJ,YAAY;CACZ,SAAS;CACT,UAAU;CACV,WAAW;CACX,KAAK;CACN,CACF;AAED,SAAwB,IAAuB;CAC7C,IAAM,IAAU,EAAyB,KAAK;AAE9C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GACE,KAAK;GACK;GACV,YAAW;GACX,qBAAqB;GACrB,gBAAgB;GAChB,kBAAkB,MAAU,QAAQ,IAAI,mBAAmB,EAAM,WAAW;GAC5E,eAAe;GACf,WAAU;GACV,CAAA,EACF,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAQ,SAAS,WAAW,EAAO;GAClD,WAAU;aACX;GAEQ,CAAA,CAAA"}
|
package/package.json
CHANGED
package/ui/AdvancedToast.js
CHANGED
|
@@ -32,10 +32,13 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
|
|
|
32
32
|
onMouseUp: I,
|
|
33
33
|
onMouseLeave: L,
|
|
34
34
|
children: [
|
|
35
|
-
/* @__PURE__ */ p(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
/* @__PURE__ */ p("span", {
|
|
36
|
+
className: e("w-30 h-30 pt-4", a(S)),
|
|
37
|
+
children: /* @__PURE__ */ p(f, {
|
|
38
|
+
name: v,
|
|
39
|
+
width: "30px",
|
|
40
|
+
className: e("flex-shrink-0")
|
|
41
|
+
})
|
|
39
42
|
}),
|
|
40
43
|
/* @__PURE__ */ m("div", {
|
|
41
44
|
className: "flex flex-1 flex-col gap-12 pe-24 text-b4",
|
package/ui/AdvancedToast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdvancedToast.js","names":[],"sources":["../../lib/ui/AdvancedToast.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n} from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { ElasticHeight } from './ElasticHeight';\nimport { Colors, getBgColor, getBorderColor, getTextColor } from './helpers/colors/colors';\nimport { useCountdown } from './hooks/useCountdown';\nimport useResizeObserver from './hooks/useResizeObserver';\n\ninterface Props extends ComponentPropsWithoutRef<'div'> {\n title: string;\n body: string;\n icon: IconicNames;\n isVisible: boolean;\n labels: {\n close: string;\n details: string;\n };\n onClose?: () => void;\n children?: React.ReactNode;\n accentColor?: Colors;\n moreInfoLabel?: string;\n moreInfoHref?: string;\n duration?: false | number;\n toastId: string;\n updateHeight: (id: string, height: number) => void;\n}\n\nexport const AdvancedToast: FunctionComponent<Props> = ({\n className,\n title,\n body,\n icon,\n isVisible,\n labels,\n children,\n accentColor = Colors.orange,\n duration = 10000,\n onClose,\n toastId,\n updateHeight,\n ...attrs\n}) => {\n const id = useId();\n const [isDetailsExpanded, setIsDetailsExpanded] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement>(null!);\n\n const { progress } = useCountdown({ duration, isPaused, isVisible });\n useEffect(() => {\n if (progress === 100) {\n onClose?.();\n }\n }, [progress, onClose]);\n\n const handleMouseDown = () => setIsPaused(true);\n const handleMouseUp = () => setIsPaused(false);\n const handleMouseLeave = () => setIsPaused(false);\n\n useResizeObserver<HTMLDivElement>({\n ref: toastRef,\n onResize: () => {\n if (toastRef.current) {\n updateHeight(toastId, toastRef.current.offsetHeight);\n }\n },\n });\n\n return (\n <div\n ref={toastRef}\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slide-right-enter' : 'animate-slide-right-exit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden',\n getBorderColor(accentColor),\n className,\n )}\n role=\"note\"\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n >\n <
|
|
1
|
+
{"version":3,"file":"AdvancedToast.js","names":[],"sources":["../../lib/ui/AdvancedToast.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n} from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { ElasticHeight } from './ElasticHeight';\nimport { Colors, getBgColor, getBorderColor, getTextColor } from './helpers/colors/colors';\nimport { useCountdown } from './hooks/useCountdown';\nimport useResizeObserver from './hooks/useResizeObserver';\n\ninterface Props extends ComponentPropsWithoutRef<'div'> {\n title: string;\n body: string;\n icon: IconicNames;\n isVisible: boolean;\n labels: {\n close: string;\n details: string;\n };\n onClose?: () => void;\n children?: React.ReactNode;\n accentColor?: Colors;\n moreInfoLabel?: string;\n moreInfoHref?: string;\n duration?: false | number;\n toastId: string;\n updateHeight: (id: string, height: number) => void;\n}\n\nexport const AdvancedToast: FunctionComponent<Props> = ({\n className,\n title,\n body,\n icon,\n isVisible,\n labels,\n children,\n accentColor = Colors.orange,\n duration = 10000,\n onClose,\n toastId,\n updateHeight,\n ...attrs\n}) => {\n const id = useId();\n const [isDetailsExpanded, setIsDetailsExpanded] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement>(null!);\n\n const { progress } = useCountdown({ duration, isPaused, isVisible });\n useEffect(() => {\n if (progress === 100) {\n onClose?.();\n }\n }, [progress, onClose]);\n\n const handleMouseDown = () => setIsPaused(true);\n const handleMouseUp = () => setIsPaused(false);\n const handleMouseLeave = () => setIsPaused(false);\n\n useResizeObserver<HTMLDivElement>({\n ref: toastRef,\n onResize: () => {\n if (toastRef.current) {\n updateHeight(toastId, toastRef.current.offsetHeight);\n }\n },\n });\n\n return (\n <div\n ref={toastRef}\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slide-right-enter' : 'animate-slide-right-exit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden',\n getBorderColor(accentColor),\n className,\n )}\n role=\"note\"\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n >\n <span className={clsx('w-30 h-30 pt-4', getTextColor(accentColor))}>\n <Icon name={icon} width=\"30px\" className={clsx('flex-shrink-0')} />\n </span>\n <div className=\"flex flex-1 flex-col gap-12 pe-24 text-b4\">\n <div>\n <p className=\" font-bold\" id={id}>\n {title}\n </p>\n <p>{body}</p>\n </div>\n\n {children && (\n <div>\n <button\n onClick={() => setIsDetailsExpanded(!isDetailsExpanded)}\n aria-expanded={isDetailsExpanded}\n className=\"flex w-fit items-center gap-8 text-b5 font-normal\"\n type=\"button\"\n >\n <span>{labels.details}</span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n style={{ rotate: isDetailsExpanded ? '180deg' : '0deg' }}\n className=\"transition-all duration-300\"\n />\n </button>\n <ElasticHeight isExpanded={isDetailsExpanded}>\n <div className=\"pt-4\">{children}</div>\n </ElasticHeight>\n </div>\n )}\n </div>\n\n {onClose && (\n <button\n aria-describedby={id}\n aria-label={labels.close}\n className=\"absolute end-0 top-0 mt-20 me-13 text-black\"\n onClick={onClose}\n type=\"button\"\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n\n {duration !== false && (\n <div className=\"absolute bottom-0 left-0 right-0 h-4 overflow-hidden rounded-b-16\">\n <div\n className={getBgColor(accentColor)}\n style={{\n width: '100%',\n height: '100%',\n transform: `scaleX(${(100 - progress) / 100})`,\n transformOrigin: 'left',\n transition: 'transform 16ms linear',\n }}\n />\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAqCA,IAAa,KAA2C,EACtD,cACA,UACA,SACA,SACA,cACA,WACA,aACA,iBAAc,EAAO,QACrB,cAAW,KACX,YACA,YACA,iBACA,GAAG,QACC;CACJ,IAAM,IAAK,GAAO,EACZ,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,IAAW,EAAuB,KAAM,EAExC,EAAE,gBAAa,EAAa;EAAE;EAAU;EAAU;EAAW,CAAC;AACpE,SAAgB;AACd,EAAI,MAAa,OACf,KAAW;IAEZ,CAAC,GAAU,EAAQ,CAAC;CAEvB,IAAM,UAAwB,EAAY,GAAK,EACzC,UAAsB,EAAY,GAAM,EACxC,UAAyB,EAAY,GAAM;AAWjD,QATA,EAAkC;EAChC,KAAK;EACL,gBAAgB;AACd,GAAI,EAAS,WACX,EAAa,GAAS,EAAS,QAAQ,aAAa;;EAGzD,CAAC,EAGA,kBAAC,OAAD;EACE,KAAK;EACL,GAAI;EACJ,WAAW,EACT,IAAY,8BAA8B,sCAC1C,+HACA,EAAe,EAAY,EAC3B,EACD;EACD,MAAK;EACL,aAAa;EACb,WAAW;EACX,cAAc;YAZhB;GAcE,kBAAC,QAAD;IAAM,WAAW,EAAK,kBAAkB,EAAa,EAAY,CAAC;cAChE,kBAAC,GAAD;KAAM,MAAM;KAAM,OAAM;KAAO,WAAW,EAAK,gBAAA;KAAoB,CAAA;IAC9D,CAAA;GACP,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;KAAiB;eAC3B;KACC,CAAA,EACJ,kBAAC,KAAD,EAAA,UAAI,GAAS,CAAA,CACT,EAAA,CAAA,EAEL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,UAAD;KACE,eAAe,EAAqB,CAAC,EAAkB;KACvD,iBAAe;KACf,WAAU;KACV,MAAK;eAJP,CAME,kBAAC,QAAD,EAAA,UAAO,EAAO,SAAe,CAAA,EAC7B,kBAAC,GAAD;MACE,MAAK;MACL,OAAM;MACN,OAAO,EAAE,QAAQ,IAAoB,WAAW,QAAQ;MACxD,WAAU;MACV,CAAA,CAAA;QAEJ,kBAAC,GAAD;KAAe,YAAY;eACzB,kBAAC,OAAD;MAAK,WAAU;MAAQ;MAAe,CAAA;KACxB,CAAA,CACZ,EAAA,CAAA,CAAA;;GAIT,KACC,kBAAC,UAAD;IACE,oBAAkB;IAClB,cAAY,EAAO;IACnB,WAAU;IACV,SAAS;IACT,MAAK;cAEL,kBAAC,GAAD;KAAM,MAAK;KAAe,OAAM;KAAS,CAAA;IAClC,CAAA;GAGV,MAAa,MACZ,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KACE,WAAW,EAAW,EAAY;KAClC,OAAO;MACL,OAAO;MACP,QAAQ;MACR,WAAW,WAAW,MAAM,KAAY,IAAI;MAC5C,iBAAiB;MACjB,YAAY;;KAEd,CAAA;IACE,CAAA"}
|
package/ui/ChatWindow.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import { ChatMessageSender } from './ChatMessage';
|
|
3
|
+
import { ChatWindowCsatPromptLabels } from './ChatWindowCsatPrompt';
|
|
4
|
+
import { ChatWindowCsatThankYouLabels } from './ChatWindowCsatThankYou';
|
|
5
|
+
import { ChatWindowQuoteItem } from './ChatWindowQuote';
|
|
6
|
+
export type { ChatWindowCsatPromptLabels, ChatWindowCsatThankYouLabels, ChatWindowQuoteItem };
|
|
3
7
|
export interface ChatWindowMessage {
|
|
4
8
|
id: string;
|
|
5
9
|
sender: ChatMessageSender;
|
|
@@ -17,5 +21,14 @@ export interface ChatWindowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'c
|
|
|
17
21
|
onClose?: () => void;
|
|
18
22
|
onAudioClick?: () => void;
|
|
19
23
|
logo?: ReactNode;
|
|
24
|
+
onFeedbackRate?: (rating: number) => void;
|
|
25
|
+
csatLabels?: ChatWindowCsatPromptLabels;
|
|
26
|
+
csatRenderRatingLabel?: (rating: number) => ReactNode;
|
|
27
|
+
csatThankYouLabels?: ChatWindowCsatThankYouLabels;
|
|
28
|
+
onQuoteCtaClick?: (quote: ChatWindowQuoteItem) => void;
|
|
20
29
|
}
|
|
21
|
-
export
|
|
30
|
+
export interface ChatWindowHandle {
|
|
31
|
+
askForFeedback: () => void;
|
|
32
|
+
showQuotes: (quotes: ChatWindowQuoteItem[]) => void;
|
|
33
|
+
}
|
|
34
|
+
export declare const ChatWindow: import('react').ForwardRefExoticComponent<ChatWindowProps & import('react').RefAttributes<ChatWindowHandle>>;
|
package/ui/ChatWindow.js
CHANGED
|
@@ -3,106 +3,140 @@ 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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { ChatWindowCsatPrompt as i } from "./ChatWindowCsatPrompt.js";
|
|
7
|
+
import { ChatWindowCsatThankYou as a } from "./ChatWindowCsatThankYou.js";
|
|
8
|
+
import { ChatWindowQuote as o } from "./ChatWindowQuote.js";
|
|
9
|
+
import { forwardRef as s, useEffect as c, useImperativeHandle as l, useRef as u, useState as d } from "react";
|
|
10
|
+
import { Icon as f } from "@clubmed/trident-icons";
|
|
11
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
12
|
//#region lib/ui/ChatWindow.tsx
|
|
10
|
-
var
|
|
13
|
+
var h = /* @__PURE__ */ p("svg", {
|
|
11
14
|
className: "absolute top-full inset-x-[50%] -translate-x-1/2",
|
|
12
15
|
width: "118",
|
|
13
16
|
height: "27",
|
|
14
17
|
viewBox: "0 0 118 27",
|
|
15
|
-
children: /* @__PURE__ */
|
|
18
|
+
children: /* @__PURE__ */ p("path", {
|
|
16
19
|
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
20
|
fill: "#F6EFE7"
|
|
18
21
|
})
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
}), g = s(function({ title: s = "Ask me a question", greeting: g, messages: _, inputValue: v, inputPlaceholder: y, isTyping: b = !1, onInputChange: x, onSubmit: S, onClose: C, onAudioClick: w, logo: T, onFeedbackRate: E, csatLabels: D, csatRenderRatingLabel: O, csatThankYouLabels: k, onQuoteCtaClick: A, className: j, ...M }, N) {
|
|
23
|
+
let P = u(null), [F, I] = d(!1), [L, R] = d(null), [z, B] = d([]);
|
|
24
|
+
l(N, () => ({
|
|
25
|
+
askForFeedback() {
|
|
26
|
+
I(!0);
|
|
27
|
+
},
|
|
28
|
+
showQuotes(e) {
|
|
29
|
+
B((t) => [...t, e]);
|
|
30
|
+
}
|
|
31
|
+
})), c(() => {
|
|
32
|
+
let e = P.current;
|
|
24
33
|
e && e.scrollTo({
|
|
25
34
|
top: e.scrollHeight,
|
|
26
35
|
behavior: "smooth"
|
|
27
36
|
});
|
|
28
|
-
}, [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
}, [
|
|
38
|
+
_,
|
|
39
|
+
b,
|
|
40
|
+
F,
|
|
41
|
+
L,
|
|
42
|
+
z
|
|
43
|
+
]);
|
|
44
|
+
function V(e) {
|
|
45
|
+
R(String(O ? O(e) : e)), E?.(e);
|
|
46
|
+
}
|
|
47
|
+
let H = F && D && O;
|
|
48
|
+
return /* @__PURE__ */ m("div", {
|
|
49
|
+
...M,
|
|
50
|
+
className: e("flex flex-col gap-20 items-center", j),
|
|
51
|
+
children: [/* @__PURE__ */ m("div", {
|
|
32
52
|
className: "chat-border bg-white flex flex-col h-full w-full rounded-32 overflow-hidden",
|
|
33
53
|
children: [
|
|
34
|
-
/* @__PURE__ */
|
|
54
|
+
/* @__PURE__ */ m("div", {
|
|
35
55
|
className: "relative flex flex-col items-center shrink-0 pt-4 px-4 h-133 overflow-hidden",
|
|
36
|
-
children: [/* @__PURE__ */
|
|
56
|
+
children: [/* @__PURE__ */ p("div", {
|
|
37
57
|
className: "absolute inset-x-4 top-4 h-102 bg-lightSand rounded-[24]",
|
|
38
|
-
children:
|
|
39
|
-
}), /* @__PURE__ */
|
|
58
|
+
children: h
|
|
59
|
+
}), /* @__PURE__ */ m("div", {
|
|
40
60
|
className: "relative flex flex-col flex-1 items-center justify-end pb-8 w-full z-10",
|
|
41
|
-
children: [/* @__PURE__ */
|
|
61
|
+
children: [/* @__PURE__ */ p("div", {
|
|
42
62
|
className: "flex items-center justify-center px-12 py-8 w-full",
|
|
43
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ p("p", {
|
|
44
64
|
className: "font-serif font-bold italic text-h5 text-center text-black line-clamp-2",
|
|
45
|
-
children:
|
|
65
|
+
children: s
|
|
46
66
|
})
|
|
47
|
-
}),
|
|
67
|
+
}), T ?? /* @__PURE__ */ p("button", {
|
|
48
68
|
type: "button",
|
|
49
69
|
"aria-label": "AI assistant",
|
|
50
70
|
className: "chat-border flex items-center justify-center size-48 rounded-full bg-white",
|
|
51
|
-
children: /* @__PURE__ */
|
|
71
|
+
children: /* @__PURE__ */ p(f, {
|
|
52
72
|
name: "Sparkles",
|
|
53
73
|
width: "24px"
|
|
54
74
|
})
|
|
55
75
|
})]
|
|
56
76
|
})]
|
|
57
77
|
}),
|
|
58
|
-
/* @__PURE__ */
|
|
59
|
-
ref:
|
|
78
|
+
/* @__PURE__ */ m("div", {
|
|
79
|
+
ref: P,
|
|
60
80
|
role: "log",
|
|
61
81
|
"aria-label": "Chat messages",
|
|
62
82
|
"aria-live": "polite",
|
|
63
83
|
className: "chat-message-log flex flex-col flex-1 gap-20 overflow-y-auto py-20",
|
|
64
84
|
children: [
|
|
65
|
-
|
|
85
|
+
g ? /* @__PURE__ */ p("div", {
|
|
66
86
|
className: "px-20",
|
|
67
|
-
children: /* @__PURE__ */
|
|
87
|
+
children: /* @__PURE__ */ p("p", {
|
|
68
88
|
className: "text-b3 text-black",
|
|
69
|
-
children:
|
|
89
|
+
children: g
|
|
70
90
|
})
|
|
71
91
|
}) : null,
|
|
72
|
-
|
|
92
|
+
_.map((e) => /* @__PURE__ */ p(n, {
|
|
73
93
|
sender: e.sender,
|
|
74
94
|
children: e.content
|
|
75
95
|
}, e.id)),
|
|
76
|
-
|
|
96
|
+
b && /* @__PURE__ */ p("div", {
|
|
77
97
|
className: "px-12",
|
|
78
|
-
children: /* @__PURE__ */
|
|
79
|
-
})
|
|
98
|
+
children: /* @__PURE__ */ p(r, {})
|
|
99
|
+
}),
|
|
100
|
+
H && /* @__PURE__ */ p(i, {
|
|
101
|
+
onRate: V,
|
|
102
|
+
labels: D,
|
|
103
|
+
renderRatingLabel: O
|
|
104
|
+
}),
|
|
105
|
+
L && /* @__PURE__ */ p(n, {
|
|
106
|
+
sender: "user",
|
|
107
|
+
children: L
|
|
108
|
+
}),
|
|
109
|
+
L && k && /* @__PURE__ */ p(a, { labels: k }),
|
|
110
|
+
z.map((e, t) => /* @__PURE__ */ p(o, {
|
|
111
|
+
quotes: e,
|
|
112
|
+
onCtaClick: A
|
|
113
|
+
}, t))
|
|
80
114
|
]
|
|
81
115
|
}),
|
|
82
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ p("div", {
|
|
83
117
|
className: "shrink-0 px-8 pb-8 pt-12",
|
|
84
|
-
children: /* @__PURE__ */
|
|
85
|
-
value:
|
|
86
|
-
placeholder:
|
|
87
|
-
onValueChange:
|
|
88
|
-
onSubmit:
|
|
89
|
-
onAudioClick:
|
|
118
|
+
children: /* @__PURE__ */ p(t, {
|
|
119
|
+
value: v,
|
|
120
|
+
placeholder: y,
|
|
121
|
+
onValueChange: x,
|
|
122
|
+
onSubmit: S,
|
|
123
|
+
onAudioClick: w
|
|
90
124
|
})
|
|
91
125
|
})
|
|
92
126
|
]
|
|
93
|
-
}),
|
|
127
|
+
}), C && /* @__PURE__ */ p("button", {
|
|
94
128
|
type: "button",
|
|
95
129
|
"aria-label": "Close chat",
|
|
96
|
-
onClick:
|
|
130
|
+
onClick: C,
|
|
97
131
|
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__ */
|
|
132
|
+
children: /* @__PURE__ */ p(f, {
|
|
99
133
|
name: "CrossDefault",
|
|
100
134
|
width: "24px"
|
|
101
135
|
})
|
|
102
136
|
})]
|
|
103
137
|
});
|
|
104
|
-
}
|
|
138
|
+
});
|
|
105
139
|
//#endregion
|
|
106
|
-
export {
|
|
140
|
+
export { g as ChatWindow };
|
|
107
141
|
|
|
108
142
|
//# sourceMappingURL=ChatWindow.js.map
|
package/ui/ChatWindow.js.map
CHANGED
|
@@ -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
|
|
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';\nimport { ChatWindowQuote } from './ChatWindowQuote';\nimport type { ChatWindowQuoteItem } from './ChatWindowQuote';\n\nexport type { ChatWindowCsatPromptLabels, ChatWindowCsatThankYouLabels, ChatWindowQuoteItem };\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 onQuoteCtaClick?: (quote: ChatWindowQuoteItem) => void;\n}\n\nexport interface ChatWindowHandle {\n askForFeedback: () => void;\n showQuotes: (quotes: ChatWindowQuoteItem[]) => 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 onQuoteCtaClick,\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 const [quoteGroups, setQuoteGroups] = useState<ChatWindowQuoteItem[][]>([]);\n\n useImperativeHandle(ref, () => ({\n askForFeedback() {\n setShowCsat(true);\n },\n showQuotes(quotes: ChatWindowQuoteItem[]) {\n setQuoteGroups((prev) => [...prev, quotes]);\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, quoteGroups]);\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 {quoteGroups.map((quotes, idx) => (\n <ChatWindowQuote key={idx} quotes={quotes} onCtaClick={onQuoteCtaClick} />\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":";;;;;;;;;;;;AAiDA,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,oBACA,cACA,GAAG,KAEL,GACA;CACA,IAAM,IAAS,EAAuB,KAAK,EACrC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAmB,KAAwB,EAAwB,KAAK,EACzE,CAAC,GAAa,KAAkB,EAAkC,EAAE,CAAC;AAW3E,CATA,EAAoB,UAAY;EAC9B,iBAAiB;AACf,KAAY,GAAK;;EAEnB,WAAW,GAA+B;AACxC,MAAgB,MAAS,CAAC,GAAG,GAAM,EAAO,CAAC;;EAE9C,EAAE,EAEH,QAAgB;EACd,IAAM,IAAK,EAAO;AAClB,EAAI,KAAI,EAAG,SAAS;GAAE,KAAK,EAAG;GAAc,UAAU;GAAU,CAAC;IAChE;EAAC;EAAU;EAAU;EAAU;EAAmB;EAAY,CAAC;CAElE,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;MAEvD,EAAY,KAAK,GAAQ,MACxB,kBAAC,GAAD;OAAmC;OAAQ,YAAY;OAAmB,EAApD,EAAoD,CAAA;;;IAI9E,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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ChatWindowQuoteItem {
|
|
2
|
+
id: string;
|
|
3
|
+
resortName: string;
|
|
4
|
+
country: string;
|
|
5
|
+
imageUrl: string;
|
|
6
|
+
/** Date range, e.g. "15 June 2026 to 24 June 2026" */
|
|
7
|
+
dateRange: string;
|
|
8
|
+
/** Pax info, e.g. "for 2 adults 2 children" */
|
|
9
|
+
pax: string;
|
|
10
|
+
/** CTA button label. Defaults to "See prices" */
|
|
11
|
+
ctaLabel?: string;
|
|
12
|
+
/** Bullet-point package items. Shown in single-quote inline mode only */
|
|
13
|
+
packageIncludes?: string[];
|
|
14
|
+
/** Free-text paragraph shown in single-quote inline mode only */
|
|
15
|
+
additionalInfo?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ChatWindowQuoteProps {
|
|
18
|
+
quotes: ChatWindowQuoteItem[];
|
|
19
|
+
onCtaClick?: (quote: ChatWindowQuoteItem) => void;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function ChatWindowQuote({ quotes, onCtaClick, className }: ChatWindowQuoteProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button as e } from "./buttons/Button.js";
|
|
3
|
+
import { twMerge as t } from "./helpers/twMerge.js";
|
|
4
|
+
import { Scrollbar as n } from "./Scrollbar.js";
|
|
5
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
6
|
+
//#region lib/ui/ChatWindowQuote.tsx
|
|
7
|
+
function a({ quote: t, onCtaClick: n }) {
|
|
8
|
+
return /* @__PURE__ */ i("article", {
|
|
9
|
+
"aria-label": t.resortName,
|
|
10
|
+
className: "flex flex-col bg-white border border-lightGrey rounded-32 shadow-[0px_2px_14px_0px_rgba(0,0,0,0.25)] overflow-hidden p-24 gap-16",
|
|
11
|
+
children: [/* @__PURE__ */ i("div", {
|
|
12
|
+
className: "relative h-210 w-full overflow-hidden rounded-16",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ r("img", {
|
|
15
|
+
src: t.imageUrl,
|
|
16
|
+
alt: "",
|
|
17
|
+
className: "absolute inset-0 size-full object-cover"
|
|
18
|
+
}),
|
|
19
|
+
/* @__PURE__ */ r("div", { className: "absolute inset-0 bg-gradient-to-b from-transparent from-50% to-[rgba(36,36,36,0.4)]" }),
|
|
20
|
+
/* @__PURE__ */ i("div", {
|
|
21
|
+
className: "absolute bottom-20 inset-x-0 flex flex-col items-center text-white text-center px-20",
|
|
22
|
+
children: [/* @__PURE__ */ r("p", {
|
|
23
|
+
className: "text-b2 font-semibold",
|
|
24
|
+
children: t.resortName
|
|
25
|
+
}), /* @__PURE__ */ r("p", {
|
|
26
|
+
className: "text-b3",
|
|
27
|
+
children: t.country
|
|
28
|
+
})]
|
|
29
|
+
})
|
|
30
|
+
]
|
|
31
|
+
}), /* @__PURE__ */ i("div", {
|
|
32
|
+
className: "flex flex-col gap-16 items-center",
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ i("p", {
|
|
35
|
+
className: "text-b4 font-semibold text-black text-center",
|
|
36
|
+
children: [
|
|
37
|
+
t.resortName,
|
|
38
|
+
", ",
|
|
39
|
+
t.dateRange,
|
|
40
|
+
", ",
|
|
41
|
+
t.pax
|
|
42
|
+
]
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ r(e, {
|
|
45
|
+
color: "saffron",
|
|
46
|
+
onClick: () => n?.(t),
|
|
47
|
+
children: t.ctaLabel ?? "See prices"
|
|
48
|
+
}),
|
|
49
|
+
t.packageIncludes && t.packageIncludes.length > 0 && /* @__PURE__ */ i("div", {
|
|
50
|
+
className: "flex flex-col gap-4 w-full",
|
|
51
|
+
children: [/* @__PURE__ */ r("p", {
|
|
52
|
+
className: "text-b3 font-semibold text-black",
|
|
53
|
+
children: "Your All-Inclusive package includes:"
|
|
54
|
+
}), /* @__PURE__ */ r("ul", {
|
|
55
|
+
className: "flex flex-col gap-2",
|
|
56
|
+
children: t.packageIncludes.map((e) => /* @__PURE__ */ i("li", {
|
|
57
|
+
className: "text-b3 text-black",
|
|
58
|
+
children: ["• ", e]
|
|
59
|
+
}, e))
|
|
60
|
+
})]
|
|
61
|
+
}),
|
|
62
|
+
t.additionalInfo && /* @__PURE__ */ r("p", {
|
|
63
|
+
className: "text-b3 text-black",
|
|
64
|
+
children: t.additionalInfo
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
})]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function o({ quote: t, onCtaClick: n }) {
|
|
71
|
+
return /* @__PURE__ */ i("article", {
|
|
72
|
+
"aria-label": t.resortName,
|
|
73
|
+
className: "flex flex-col gap-12 items-center shrink-0 w-200",
|
|
74
|
+
children: [/* @__PURE__ */ i("div", {
|
|
75
|
+
className: "relative size-200 rounded-16 overflow-hidden",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ r("img", {
|
|
78
|
+
src: t.imageUrl,
|
|
79
|
+
alt: "",
|
|
80
|
+
className: "absolute inset-0 size-full object-cover"
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ r("div", { className: "absolute inset-0 rounded-16 bg-gradient-to-b from-transparent from-50% to-[rgba(36,36,36,0.4)]" }),
|
|
83
|
+
/* @__PURE__ */ i("div", {
|
|
84
|
+
className: "absolute bottom-20 inset-x-0 flex flex-col items-center text-white text-center px-8",
|
|
85
|
+
children: [/* @__PURE__ */ r("p", {
|
|
86
|
+
className: "text-b4 font-semibold",
|
|
87
|
+
children: t.resortName
|
|
88
|
+
}), /* @__PURE__ */ r("p", {
|
|
89
|
+
className: "text-b5",
|
|
90
|
+
children: t.country
|
|
91
|
+
})]
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
}), /* @__PURE__ */ i("div", {
|
|
95
|
+
className: "flex flex-col gap-8 items-center",
|
|
96
|
+
children: [/* @__PURE__ */ i("p", {
|
|
97
|
+
className: "text-b5 font-semibold text-black text-center",
|
|
98
|
+
children: [
|
|
99
|
+
t.resortName,
|
|
100
|
+
/* @__PURE__ */ r("br", {}),
|
|
101
|
+
t.dateRange,
|
|
102
|
+
",",
|
|
103
|
+
/* @__PURE__ */ r("br", {}),
|
|
104
|
+
t.pax
|
|
105
|
+
]
|
|
106
|
+
}), /* @__PURE__ */ r(e, {
|
|
107
|
+
color: "black",
|
|
108
|
+
onClick: () => n?.(t),
|
|
109
|
+
children: t.ctaLabel ?? "See prices"
|
|
110
|
+
})]
|
|
111
|
+
})]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function s({ quotes: e, onCtaClick: i, className: s }) {
|
|
115
|
+
return e.length === 0 ? null : e.length === 1 ? /* @__PURE__ */ r("div", {
|
|
116
|
+
className: t(s),
|
|
117
|
+
children: /* @__PURE__ */ r(a, {
|
|
118
|
+
quote: e[0],
|
|
119
|
+
onCtaClick: i
|
|
120
|
+
})
|
|
121
|
+
}) : /* @__PURE__ */ r("div", {
|
|
122
|
+
className: t("flex flex-col gap-8", s),
|
|
123
|
+
children: /* @__PURE__ */ r(n, {
|
|
124
|
+
timelineName: "--chat-quote-scroller",
|
|
125
|
+
scrollerClassName: "pb-24",
|
|
126
|
+
scrollbarWidth: "60%",
|
|
127
|
+
"aria-label": "Quote options",
|
|
128
|
+
children: /* @__PURE__ */ r("div", {
|
|
129
|
+
className: "flex gap-12",
|
|
130
|
+
children: e.map((e) => /* @__PURE__ */ r(o, {
|
|
131
|
+
quote: e,
|
|
132
|
+
onCtaClick: i
|
|
133
|
+
}, e.id))
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
export { s as ChatWindowQuote };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=ChatWindowQuote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatWindowQuote.js","names":[],"sources":["../../lib/ui/ChatWindowQuote.tsx"],"sourcesContent":["'use client';\n\nimport { twMerge } from './helpers/twMerge';\nimport { Button } from './buttons/Button';\nimport { Scrollbar } from './Scrollbar';\n\nexport interface ChatWindowQuoteItem {\n id: string;\n resortName: string;\n country: string;\n imageUrl: string;\n /** Date range, e.g. \"15 June 2026 to 24 June 2026\" */\n dateRange: string;\n /** Pax info, e.g. \"for 2 adults 2 children\" */\n pax: string;\n /** CTA button label. Defaults to \"See prices\" */\n ctaLabel?: string;\n /** Bullet-point package items. Shown in single-quote inline mode only */\n packageIncludes?: string[];\n /** Free-text paragraph shown in single-quote inline mode only */\n additionalInfo?: string;\n}\n\nexport interface ChatWindowQuoteProps {\n quotes: ChatWindowQuoteItem[];\n onCtaClick?: (quote: ChatWindowQuoteItem) => void;\n className?: string;\n}\n\ninterface QuoteCardProps {\n quote: ChatWindowQuoteItem;\n onCtaClick?: (quote: ChatWindowQuoteItem) => void;\n}\n\nfunction SingleQuoteCard({ quote, onCtaClick }: QuoteCardProps) {\n return (\n <article\n aria-label={quote.resortName}\n className=\"flex flex-col bg-white border border-lightGrey rounded-32 shadow-[0px_2px_14px_0px_rgba(0,0,0,0.25)] overflow-hidden p-24 gap-16\"\n >\n <div className=\"relative h-210 w-full overflow-hidden rounded-16\">\n <img src={quote.imageUrl} alt=\"\" className=\"absolute inset-0 size-full object-cover\" />\n <div className=\"absolute inset-0 bg-gradient-to-b from-transparent from-50% to-[rgba(36,36,36,0.4)]\" />\n <div className=\"absolute bottom-20 inset-x-0 flex flex-col items-center text-white text-center px-20\">\n <p className=\"text-b2 font-semibold\">{quote.resortName}</p>\n <p className=\"text-b3\">{quote.country}</p>\n </div>\n </div>\n <div className=\"flex flex-col gap-16 items-center\">\n <p className=\"text-b4 font-semibold text-black text-center\">\n {quote.resortName}, {quote.dateRange}, {quote.pax}\n </p>\n <Button color=\"saffron\" onClick={() => onCtaClick?.(quote)}>\n {quote.ctaLabel ?? 'See prices'}\n </Button>\n {quote.packageIncludes && quote.packageIncludes.length > 0 && (\n <div className=\"flex flex-col gap-4 w-full\">\n <p className=\"text-b3 font-semibold text-black\">Your All-Inclusive package includes:</p>\n <ul className=\"flex flex-col gap-2\">\n {quote.packageIncludes.map((item) => (\n <li key={item} className=\"text-b3 text-black\">\n • {item}\n </li>\n ))}\n </ul>\n </div>\n )}\n {quote.additionalInfo && <p className=\"text-b3 text-black\">{quote.additionalInfo}</p>}\n </div>\n </article>\n );\n}\n\nfunction CompactQuoteCard({ quote, onCtaClick }: QuoteCardProps) {\n return (\n <article\n aria-label={quote.resortName}\n className=\"flex flex-col gap-12 items-center shrink-0 w-200\"\n >\n <div className=\"relative size-200 rounded-16 overflow-hidden\">\n <img src={quote.imageUrl} alt=\"\" className=\"absolute inset-0 size-full object-cover\" />\n <div className=\"absolute inset-0 rounded-16 bg-gradient-to-b from-transparent from-50% to-[rgba(36,36,36,0.4)]\" />\n <div className=\"absolute bottom-20 inset-x-0 flex flex-col items-center text-white text-center px-8\">\n <p className=\"text-b4 font-semibold\">{quote.resortName}</p>\n <p className=\"text-b5\">{quote.country}</p>\n </div>\n </div>\n <div className=\"flex flex-col gap-8 items-center\">\n <p className=\"text-b5 font-semibold text-black text-center\">\n {quote.resortName}\n <br />\n {quote.dateRange},\n <br />\n {quote.pax}\n </p>\n <Button color=\"black\" onClick={() => onCtaClick?.(quote)}>\n {quote.ctaLabel ?? 'See prices'}\n </Button>\n </div>\n </article>\n );\n}\n\nexport function ChatWindowQuote({ quotes, onCtaClick, className }: ChatWindowQuoteProps) {\n if (quotes.length === 0) return null;\n\n if (quotes.length === 1) {\n return (\n <div className={twMerge(className)}>\n <SingleQuoteCard quote={quotes[0]} onCtaClick={onCtaClick} />\n </div>\n );\n }\n\n return (\n <div className={twMerge('flex flex-col gap-8', className)}>\n <Scrollbar\n timelineName=\"--chat-quote-scroller\"\n scrollerClassName=\"pb-24\"\n scrollbarWidth=\"60%\"\n aria-label=\"Quote options\"\n >\n <div className=\"flex gap-12\">\n {quotes.map((quote) => (\n <CompactQuoteCard key={quote.id} quote={quote} onCtaClick={onCtaClick} />\n ))}\n </div>\n </Scrollbar>\n </div>\n );\n}\n"],"mappings":";;;;;;AAkCA,SAAS,EAAgB,EAAE,UAAO,iBAA8B;AAC9D,QACE,kBAAC,WAAD;EACE,cAAY,EAAM;EAClB,WAAU;YAFZ,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,KAAK,EAAM;KAAU,KAAI;KAAG,WAAU;KAA4C,CAAA;IACvF,kBAAC,OAAD,EAAK,WAAU,uFAAwF,CAAA;IACvG,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAyB,EAAM;MAAe,CAAA,EAC3D,kBAAC,KAAD;MAAG,WAAU;gBAAW,EAAM;MAAY,CAAA,CAAA;;;MAG9C,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAM;MAAW;MAAG,EAAM;MAAU;MAAG,EAAM;;;IAEhD,kBAAC,GAAD;KAAQ,OAAM;KAAU,eAAe,IAAa,EAAM;eACvD,EAAM,YAAY;KACZ,CAAA;IACR,EAAM,mBAAmB,EAAM,gBAAgB,SAAS,KACvD,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAmC;MAAwC,CAAA,EACxF,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAM,gBAAgB,KAAK,MAC1B,kBAAC,MAAD;OAAe,WAAU;iBAAzB,CAA8C,MACzC,EAAA;SADI,EAEJ,CAAA;MAEJ,CAAA,CAAA;;IAGR,EAAM,kBAAkB,kBAAC,KAAD;KAAG,WAAU;eAAsB,EAAM;KAAmB,CAAA;;;;;AAM7F,SAAS,EAAiB,EAAE,UAAO,iBAA8B;AAC/D,QACE,kBAAC,WAAD;EACE,cAAY,EAAM;EAClB,WAAU;YAFZ,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,KAAK,EAAM;KAAU,KAAI;KAAG,WAAU;KAA4C,CAAA;IACvF,kBAAC,OAAD,EAAK,WAAU,kGAAmG,CAAA;IAClH,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAyB,EAAM;MAAe,CAAA,EAC3D,kBAAC,KAAD;MAAG,WAAU;gBAAW,EAAM;MAAY,CAAA,CAAA;;;MAG9C,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAM;KACP,kBAAC,MAAD,EAAM,CAAA;KACL,EAAM;KAAU;KACjB,kBAAC,MAAD,EAAM,CAAA;KACL,EAAM;;OAET,kBAAC,GAAD;IAAQ,OAAM;IAAQ,eAAe,IAAa,EAAM;cACrD,EAAM,YAAY;IACZ,CAAA,CAAA;;;;AAMjB,SAAgB,EAAgB,EAAE,WAAQ,eAAY,gBAAmC;AAWvF,QAVI,EAAO,WAAW,IAAU,OAE5B,EAAO,WAAW,IAElB,kBAAC,OAAD;EAAK,WAAW,EAAQ,EAAU;YAChC,kBAAC,GAAD;GAAiB,OAAO,EAAO;GAAgB;GAAc,CAAA;EACzD,CAAA,GAKR,kBAAC,OAAD;EAAK,WAAW,EAAQ,uBAAuB,EAAU;YACvD,kBAAC,GAAD;GACE,cAAa;GACb,mBAAkB;GAClB,gBAAe;GACf,cAAW;aAEX,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO,KAAK,MACX,kBAAC,GAAD;KAAwC;KAAmB;KAAc,EAAlD,EAAM,GAA4C,CAAA;IAEvE,CAAA;GACI,CAAA;EACR,CAAA"}
|