@clubmed/trident-ui 2.0.0-beta.4 → 2.0.0-beta.40
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/chunks/Carousel.context.js +1548 -0
- package/chunks/Carousel.context.js.map +1 -0
- package/chunks/ChatMessage.js +14395 -0
- package/chunks/ChatMessage.js.map +1 -0
- package/chunks/DateField.js +177 -63
- package/chunks/DateField.js.map +1 -1
- package/chunks/Tooltip.js +4461 -0
- package/chunks/Tooltip.js.map +1 -0
- package/chunks/chunk.js +11 -4
- package/chunks/client.js +18953 -0
- package/chunks/client.js.map +1 -0
- package/examples/button-demo.js +2 -2
- package/examples/button-demo.js.map +1 -1
- package/examples/chat-input-demo.d.ts +1 -0
- package/examples/chat-input-demo.js +21 -0
- package/examples/chat-input-demo.js.map +1 -0
- package/examples/chat-message-demo.d.ts +1 -0
- package/examples/chat-message-demo.js +20 -0
- package/examples/chat-message-demo.js.map +1 -0
- package/examples/chat-typing-indicator-demo.d.ts +1 -0
- package/examples/chat-typing-indicator-demo.js +14 -0
- package/examples/chat-typing-indicator-demo.js.map +1 -0
- package/examples/chat-window-demo.d.ts +1 -0
- package/examples/chat-window-demo.js +45 -0
- package/examples/chat-window-demo.js.map +1 -0
- package/examples/checkbox-demo.js +16 -20
- package/examples/checkbox-demo.js.map +1 -1
- package/examples/checkbox-select-demo.d.ts +1 -0
- package/examples/checkbox-select-demo.js +101 -0
- package/examples/checkbox-select-demo.js.map +1 -0
- package/examples/checkboxes-demo.js +6 -6
- package/examples/checkboxes-demo.js.map +1 -1
- package/examples/checkboxes-with-form-control-demo.js +4 -4
- package/examples/choice-expander-demo.js +4 -67
- package/examples/choice-expander-demo.js.map +1 -1
- package/examples/dropdown-demo.js +9 -1
- package/examples/dropdown-demo.js.map +1 -1
- package/examples/elastic-height-demo.js +2 -1
- package/examples/elastic-height-demo.js.map +1 -1
- package/examples/frame-demo.d.ts +1 -0
- package/examples/frame-demo.js +36 -0
- package/examples/frame-demo.js.map +1 -0
- package/examples/frame-horizontal-demo.d.ts +1 -0
- package/examples/frame-horizontal-demo.js +44 -0
- package/examples/frame-horizontal-demo.js.map +1 -0
- package/examples/frame-no-image-demo.d.ts +1 -0
- package/examples/frame-no-image-demo.js +47 -0
- package/examples/frame-no-image-demo.js.map +1 -0
- package/examples/frame-vertical-demo.d.ts +1 -0
- package/examples/frame-vertical-demo.js +44 -0
- package/examples/frame-vertical-demo.js.map +1 -0
- package/examples/frame-with-tag-demo.d.ts +1 -0
- package/examples/frame-with-tag-demo.js +48 -0
- package/examples/frame-with-tag-demo.js.map +1 -0
- package/examples/scrollbar-demo.d.ts +1 -0
- package/examples/scrollbar-demo.js +40 -0
- package/examples/scrollbar-demo.js.map +1 -0
- package/examples/slider-frame-demo.d.ts +1 -0
- package/examples/slider-frame-demo.js +38 -0
- package/examples/slider-frame-demo.js.map +1 -0
- package/examples/slider-frame-with-button-demo.d.ts +1 -0
- package/examples/slider-frame-with-button-demo.js +46 -0
- package/examples/slider-frame-with-button-demo.js.map +1 -0
- package/examples/slider-frame-with-tag-demo.d.ts +1 -0
- package/examples/slider-frame-with-tag-demo.js +50 -0
- package/examples/slider-frame-with-tag-demo.js.map +1 -0
- package/examples/switch-demo.js +1 -1
- package/examples/switch-demo.js.map +1 -1
- package/examples/tooltip-demo.d.ts +1 -0
- package/examples/tooltip-demo.js +103 -0
- package/examples/tooltip-demo.js.map +1 -0
- package/package.json +10 -3
- package/styles/animate.css +19 -19
- package/styles/components.css +82 -0
- package/styles/theme.css +23 -18
- package/styles/ui/button.css +19 -25
- package/styles/ui/chat-button.css +68 -1
- package/styles/ui/controls.css +9 -63
- package/styles/ui/range.css +1 -1
- package/styles/variants.css +0 -2
- package/ui/AdvancedToast.js +11 -11
- package/ui/AdvancedToast.js.map +1 -1
- package/ui/BasicToast.js +1 -1
- package/ui/BasicToast.js.map +1 -1
- package/ui/Breadcrumb.d.ts +2 -2
- package/ui/Breadcrumb.js +31 -35
- package/ui/Breadcrumb.js.map +1 -1
- package/ui/ChatButton.js +1 -1
- package/ui/ChatButton.js.map +1 -1
- package/ui/ChatInput.d.ts +10 -0
- package/ui/ChatInput.js +149 -0
- package/ui/ChatInput.js.map +1 -0
- package/ui/ChatMessage.d.ts +6 -0
- package/ui/ChatMessage.js +2 -0
- package/ui/ChatTypingIndicator.d.ts +2 -0
- package/ui/ChatTypingIndicator.js +30 -0
- package/ui/ChatTypingIndicator.js.map +1 -0
- package/ui/ChatWindow.d.ts +21 -0
- package/ui/ChatWindow.js +108 -0
- package/ui/ChatWindow.js.map +1 -0
- package/ui/ChoiceExpander.js +1 -1
- package/ui/ChoiceExpander.js.map +1 -1
- package/ui/Dropdown.d.ts +20 -3
- package/ui/Dropdown.js +57 -23
- package/ui/Dropdown.js.map +1 -1
- package/ui/ElasticHeight.d.ts +0 -1
- package/ui/ElasticHeight.js +14 -23
- package/ui/ElasticHeight.js.map +1 -1
- package/ui/Loader.d.ts +5 -4
- package/ui/Loader.js +11 -10
- package/ui/Loader.js.map +1 -1
- package/ui/Popin.js +2 -2
- package/ui/Popin.js.map +1 -1
- package/ui/Scrollbar.d.ts +14 -0
- package/ui/Scrollbar.js +68 -0
- package/ui/Scrollbar.js.map +1 -0
- package/ui/SidebarLayout.d.ts +3 -1
- package/ui/SidebarLayout.js +32 -24
- package/ui/SidebarLayout.js.map +1 -1
- package/ui/Tooltip.d.ts +8 -0
- package/ui/Tooltip.js +2 -0
- package/ui/arrows/Arrows.d.ts +1 -0
- package/ui/arrows/Arrows.js +19 -17
- package/ui/arrows/Arrows.js.map +1 -1
- package/ui/buttons/Button.type.d.ts +1 -1
- package/ui/buttons/Button.type.js.map +1 -1
- package/ui/carousel/Carousel.context.d.ts +27 -0
- package/ui/carousel/Carousel.context.js +2 -0
- package/ui/carousel/Carousel.d.ts +3 -0
- package/ui/carousel/Carousel.js +12 -0
- package/ui/carousel/Carousel.js.map +1 -0
- package/ui/carousel/CarouselBody.d.ts +6 -0
- package/ui/carousel/CarouselBody.js +21 -0
- package/ui/carousel/CarouselBody.js.map +1 -0
- package/ui/carousel/CarouselItem.d.ts +6 -0
- package/ui/carousel/CarouselItem.js +21 -0
- package/ui/carousel/CarouselItem.js.map +1 -0
- package/ui/carousel/CarouselNext.d.ts +8 -0
- package/ui/carousel/CarouselNext.js +23 -0
- package/ui/carousel/CarouselNext.js.map +1 -0
- package/ui/carousel/CarouselPrevious.d.ts +8 -0
- package/ui/carousel/CarouselPrevious.js +23 -0
- package/ui/carousel/CarouselPrevious.js.map +1 -0
- package/ui/contexts/TridentUIConfig.js +1 -1
- package/ui/forms/CheckboxSelect.d.ts +31 -0
- package/ui/forms/CheckboxSelect.js +119 -0
- package/ui/forms/CheckboxSelect.js.map +1 -0
- package/ui/forms/Filter.d.ts +8 -4
- package/ui/forms/Filter.js +23 -45
- package/ui/forms/Filter.js.map +1 -1
- package/ui/forms/FormControl.js +6 -6
- package/ui/forms/NumberField.d.ts +10 -10
- package/ui/forms/NumberField.js +8 -8
- package/ui/forms/PhoneField.d.ts +5 -10
- package/ui/forms/PhoneField.js +29 -211
- package/ui/forms/PhoneField.js.map +1 -1
- package/ui/forms/PhoneFieldFullInput.d.ts +16 -0
- package/ui/forms/PhoneFieldFullInput.js +116 -0
- package/ui/forms/PhoneFieldFullInput.js.map +1 -0
- package/ui/forms/PhoneFieldSplitInput.d.ts +19 -0
- package/ui/forms/PhoneFieldSplitInput.js +159 -0
- package/ui/forms/PhoneFieldSplitInput.js.map +1 -0
- package/ui/forms/Select.js +4 -4
- package/ui/forms/Switch.d.ts +3 -3
- package/ui/forms/Switch.js +51 -34
- package/ui/forms/Switch.js.map +1 -1
- package/ui/forms/TextField.js +4 -4
- package/ui/forms/TextField.js.map +1 -1
- package/ui/forms/checkboxes/Checkbox.d.ts +10 -12
- package/ui/forms/checkboxes/Checkbox.js +38 -55
- package/ui/forms/checkboxes/Checkbox.js.map +1 -1
- package/ui/forms/checkboxes/Checkboxes.js +2 -2
- package/ui/forms/checkboxes/Checkboxes.js.map +1 -1
- package/ui/forms/password/Password.js +4 -4
- package/ui/frame/Frame.d.ts +8 -0
- package/ui/frame/Frame.js +16 -0
- package/ui/frame/Frame.js.map +1 -0
- package/ui/frame/FrameLabelsWrapper.d.ts +5 -0
- package/ui/frame/FrameLabelsWrapper.js +12 -0
- package/ui/frame/FrameLabelsWrapper.js.map +1 -0
- package/ui/frame/FrameTitle.d.ts +7 -0
- package/ui/frame/FrameTitle.js +25 -0
- package/ui/frame/FrameTitle.js.map +1 -0
- package/ui/frame/FrameWrapper.d.ts +6 -0
- package/ui/frame/FrameWrapper.js +14 -0
- package/ui/frame/FrameWrapper.js.map +1 -0
- package/ui/frame/SliderFrame.d.ts +14 -0
- package/ui/frame/SliderFrame.js +50 -0
- package/ui/frame/SliderFrame.js.map +1 -0
- package/ui/helpers/colors/colors.d.ts +4 -0
- package/ui/helpers/colors/colors.js +6 -1
- package/ui/helpers/colors/colors.js.map +1 -1
- package/ui/helpers/phone/defaultPrefixes.js +28 -28
- package/ui/helpers/phone/defaultPrefixes.js.map +1 -1
- package/ui/helpers/phone/formatters.d.ts +11 -0
- package/ui/helpers/phone/formatters.js +32 -1
- package/ui/helpers/phone/formatters.js.map +1 -1
- package/ui/helpers/phone/index.d.ts +1 -1
- package/ui/helpers/phone/index.js +3 -3
- package/ui/hooks/useValue.js +1 -1
- package/ui/hooks/useValue.js.map +1 -1
- package/ui/tabs/Tabs.js +1 -1
- package/ui/tabs/Tabs.js.map +1 -1
- package/ui/Breadcrumb.themes.d.ts +0 -8
- package/ui/Breadcrumb.themes.js +0 -16
- package/ui/Breadcrumb.themes.js.map +0 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HTMLAttributes, PropsWithChildren } from 'react';
|
|
2
|
+
export type ChatMessageSender = 'assistant' | 'user';
|
|
3
|
+
export interface ChatMessageProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
sender: ChatMessageSender;
|
|
5
|
+
}
|
|
6
|
+
export declare const ChatMessage: import('react').NamedExoticComponent<PropsWithChildren<ChatMessageProps>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { twMerge as e } from "./helpers/twMerge.js";
|
|
2
|
+
import { memo as t } from "react";
|
|
3
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
|
+
//#region lib/ui/ChatTypingIndicator.tsx
|
|
5
|
+
var i = t(function({ className: t, ...i }) {
|
|
6
|
+
return /* @__PURE__ */ r("div", {
|
|
7
|
+
role: "status",
|
|
8
|
+
"aria-label": "Typing",
|
|
9
|
+
...i,
|
|
10
|
+
className: e("flex items-center gap-4 h-34 w-66 overflow-hidden rounded-pill bg-pearl px-20", t),
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ n("span", {
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
className: "size-6 rounded-full bg-black animate-bounce [animation-delay:-300ms]"
|
|
15
|
+
}),
|
|
16
|
+
/* @__PURE__ */ n("span", {
|
|
17
|
+
"aria-hidden": "true",
|
|
18
|
+
className: "size-6 rounded-full bg-black animate-bounce [animation-delay:-150ms]"
|
|
19
|
+
}),
|
|
20
|
+
/* @__PURE__ */ n("span", {
|
|
21
|
+
"aria-hidden": "true",
|
|
22
|
+
className: "size-6 rounded-full bg-black animate-bounce"
|
|
23
|
+
})
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//#endregion
|
|
28
|
+
export { i as ChatTypingIndicator };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=ChatTypingIndicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatTypingIndicator.js","names":[],"sources":["../../lib/ui/ChatTypingIndicator.tsx"],"sourcesContent":["import { memo, type HTMLAttributes } from 'react';\nimport { twMerge } from './helpers/twMerge';\n\nexport const ChatTypingIndicator = memo(function ChatTypingIndicator({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n role=\"status\"\n aria-label=\"Typing\"\n {...props}\n className={twMerge(\n 'flex items-center gap-4 h-34 w-66 overflow-hidden rounded-pill bg-pearl px-20',\n className,\n )}\n >\n <span\n aria-hidden=\"true\"\n className=\"size-6 rounded-full bg-black animate-bounce [animation-delay:-300ms]\"\n />\n <span\n aria-hidden=\"true\"\n className=\"size-6 rounded-full bg-black animate-bounce [animation-delay:-150ms]\"\n />\n <span aria-hidden=\"true\" className=\"size-6 rounded-full bg-black animate-bounce\" />\n </div>\n );\n});\n"],"mappings":";;;;AAGA,IAAa,IAAsB,EAAK,SAA6B,EACnE,cACA,GAAG,KAC8B;AACjC,QACE,kBAAC,OAAD;EACE,MAAK;EACL,cAAW;EACX,GAAI;EACJ,WAAW,EACT,iFACA,EACD;YAPH;GASE,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACV,CAAA;GACF,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACV,CAAA;GACF,kBAAC,QAAD;IAAM,eAAY;IAAO,WAAU;IAAgD,CAAA;GAC/E;;EAER"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ChatMessageSender } from './ChatMessage';
|
|
3
|
+
export interface ChatWindowMessage {
|
|
4
|
+
id: string;
|
|
5
|
+
sender: ChatMessageSender;
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ChatWindowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
9
|
+
title?: string;
|
|
10
|
+
greeting?: string;
|
|
11
|
+
messages: ChatWindowMessage[];
|
|
12
|
+
inputValue: string;
|
|
13
|
+
inputPlaceholder?: string;
|
|
14
|
+
isTyping?: boolean;
|
|
15
|
+
onInputChange: (value: string) => void;
|
|
16
|
+
onSubmit: () => void;
|
|
17
|
+
onClose?: () => void;
|
|
18
|
+
onAudioClick?: () => void;
|
|
19
|
+
logo?: ReactNode;
|
|
20
|
+
}
|
|
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;
|
package/ui/ChatWindow.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { twMerge as e } from "./helpers/twMerge.js";
|
|
3
|
+
import { ChatInput as t } from "./ChatInput.js";
|
|
4
|
+
import { t as n } from "../chunks/ChatMessage.js";
|
|
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";
|
|
9
|
+
//#region lib/ui/ChatWindow.tsx
|
|
10
|
+
var l = /* @__PURE__ */ s("svg", {
|
|
11
|
+
className: "absolute top-full inset-x-[50%] -translate-x-1/2",
|
|
12
|
+
width: "118",
|
|
13
|
+
height: "27",
|
|
14
|
+
viewBox: "0 0 118 27",
|
|
15
|
+
children: /* @__PURE__ */ s("path", {
|
|
16
|
+
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
|
+
fill: "#F6EFE7"
|
|
18
|
+
})
|
|
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;
|
|
24
|
+
e && e.scrollTo({
|
|
25
|
+
top: e.scrollHeight,
|
|
26
|
+
behavior: "smooth"
|
|
27
|
+
});
|
|
28
|
+
}, [f, h]), /* @__PURE__ */ c("div", {
|
|
29
|
+
...S,
|
|
30
|
+
className: e("flex flex-col gap-20 items-center", x),
|
|
31
|
+
children: [/* @__PURE__ */ c("div", {
|
|
32
|
+
className: "chat-border bg-white flex flex-col h-full w-full rounded-32 overflow-hidden",
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ c("div", {
|
|
35
|
+
className: "relative flex flex-col items-center shrink-0 pt-4 px-4 h-133 overflow-hidden",
|
|
36
|
+
children: [/* @__PURE__ */ s("div", {
|
|
37
|
+
className: "absolute inset-x-4 top-4 h-102 bg-lightSand rounded-[24]",
|
|
38
|
+
children: l
|
|
39
|
+
}), /* @__PURE__ */ c("div", {
|
|
40
|
+
className: "relative flex flex-col flex-1 items-center justify-end pb-8 w-full z-10",
|
|
41
|
+
children: [/* @__PURE__ */ s("div", {
|
|
42
|
+
className: "flex items-center justify-center px-12 py-8 w-full",
|
|
43
|
+
children: /* @__PURE__ */ s("p", {
|
|
44
|
+
className: "font-serif font-bold italic text-h5 text-center text-black line-clamp-2",
|
|
45
|
+
children: u
|
|
46
|
+
})
|
|
47
|
+
}), b ?? /* @__PURE__ */ s("button", {
|
|
48
|
+
type: "button",
|
|
49
|
+
"aria-label": "AI assistant",
|
|
50
|
+
className: "chat-border flex items-center justify-center size-48 rounded-full bg-white",
|
|
51
|
+
children: /* @__PURE__ */ s(o, {
|
|
52
|
+
name: "Sparkles",
|
|
53
|
+
width: "24px"
|
|
54
|
+
})
|
|
55
|
+
})]
|
|
56
|
+
})]
|
|
57
|
+
}),
|
|
58
|
+
/* @__PURE__ */ c("div", {
|
|
59
|
+
ref: C,
|
|
60
|
+
role: "log",
|
|
61
|
+
"aria-label": "Chat messages",
|
|
62
|
+
"aria-live": "polite",
|
|
63
|
+
className: "chat-message-log flex flex-col flex-1 gap-20 overflow-y-auto py-20",
|
|
64
|
+
children: [
|
|
65
|
+
d ? /* @__PURE__ */ s("div", {
|
|
66
|
+
className: "px-20",
|
|
67
|
+
children: /* @__PURE__ */ s("p", {
|
|
68
|
+
className: "text-b3 text-black",
|
|
69
|
+
children: d
|
|
70
|
+
})
|
|
71
|
+
}) : null,
|
|
72
|
+
f.map((e) => /* @__PURE__ */ s(n, {
|
|
73
|
+
sender: e.sender,
|
|
74
|
+
children: e.content
|
|
75
|
+
}, e.id)),
|
|
76
|
+
h && /* @__PURE__ */ s("div", {
|
|
77
|
+
className: "px-12",
|
|
78
|
+
children: /* @__PURE__ */ s(r, {})
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ s("div", {
|
|
83
|
+
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
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
}), v && /* @__PURE__ */ s("button", {
|
|
94
|
+
type: "button",
|
|
95
|
+
"aria-label": "Close chat",
|
|
96
|
+
onClick: v,
|
|
97
|
+
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, {
|
|
99
|
+
name: "CrossDefault",
|
|
100
|
+
width: "24px"
|
|
101
|
+
})
|
|
102
|
+
})]
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { u as ChatWindow };
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=ChatWindow.js.map
|
|
@@ -0,0 +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"}
|
package/ui/ChoiceExpander.js
CHANGED
|
@@ -43,7 +43,7 @@ var d = ({ label: d, showCheckIcon: f = !1, children: p, expanded: m, defaultExp
|
|
|
43
43
|
children: /* @__PURE__ */ u("div", {
|
|
44
44
|
ref: O,
|
|
45
45
|
className: e("absolute top-0 grid transition-all duration-500", !M && [
|
|
46
|
-
"w-240 rounded-pill border-transparent",
|
|
46
|
+
"w-240 rounded-pill-transitionable border-transparent",
|
|
47
47
|
t(y),
|
|
48
48
|
n(b)
|
|
49
49
|
], M && [
|
package/ui/ChoiceExpander.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChoiceExpander.js","names":[],"sources":["../../lib/ui/ChoiceExpander.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport { getBgColor, getTextColor } from './helpers/colors/colors';\nimport type { Colors } from './types/Colors';\n\nexport interface ChoiceExpanderProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Text shown when collapsed (e.g., \"From $255\")\n */\n label: string;\n\n /**\n * Show check icon in collapsed state (selected variant)\n */\n showCheckIcon?: boolean;\n\n /**\n * Content shown when expanded\n */\n children: ReactNode;\n\n /**\n * Controlled state - if provided, component is controlled\n */\n expanded?: boolean;\n\n /**\n * Initial state for uncontrolled mode\n */\n defaultExpanded?: boolean;\n\n /**\n * Callback when expanded state changes\n */\n onExpandedChange?: (isExpanded: boolean) => void;\n\n /**\n * Disable interaction\n */\n disabled?: boolean;\n\n /**\n * Custom aria-label for button\n */\n ariaLabel?: string;\n\n /**\n * Background color for unexpanded button state\n */\n buttonBgColor?: Colors;\n\n /**\n * Text color for unexpanded button state\n */\n buttonTextColor?: Colors;\n\n /**\n * collapse label for screen readers\n */\n collapseLabel: string;\n\n /**\n * expand label for screen readers\n */\n expandLabel: string;\n}\n\nexport const ChoiceExpander: FunctionComponent<ChoiceExpanderProps> = ({\n label,\n showCheckIcon = false,\n children,\n expanded,\n defaultExpanded = false,\n onExpandedChange,\n disabled = false,\n ariaLabel,\n buttonBgColor = 'black',\n buttonTextColor = 'white',\n collapseLabel,\n expandLabel,\n className,\n ...props\n}) => {\n const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);\n const contentId = useId();\n const morphContainerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLButtonElement>(null);\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const hasInteractedRef = useRef(false);\n\n const isExpanded = expanded !== undefined ? expanded : internalExpanded;\n\n const handleToggle = useCallback(() => {\n if (disabled) return;\n\n hasInteractedRef.current = true;\n const newState = !isExpanded;\n\n if (expanded === undefined) {\n setInternalExpanded(newState);\n }\n\n onExpandedChange?.(newState);\n }, [disabled, isExpanded, expanded, onExpandedChange]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n handleToggle();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isExpanded, handleToggle]);\n\n useEffect(() => {\n if (isExpanded && closeButtonRef.current) {\n closeButtonRef.current.focus();\n } else if (!isExpanded && hasInteractedRef.current && triggerButtonRef.current) {\n triggerButtonRef.current.focus();\n }\n }, [isExpanded]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (morphContainerRef.current && !morphContainerRef.current.contains(event.target as Node)) {\n handleToggle();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isExpanded, handleToggle]);\n\n return (\n <div\n className={clsx('relative flex items-center justify-center', className)}\n data-name=\"ChoiceExpander\"\n data-testid=\"choice-expander\"\n style={{ width: '240px', height: 48 }}\n {...props}\n >\n <div\n ref={morphContainerRef}\n className={clsx(\n 'absolute top-0 grid transition-all duration-500',\n !isExpanded && [\n 'w-240 rounded-pill border-transparent',\n getBgColor(buttonBgColor),\n getTextColor(buttonTextColor),\n ],\n isExpanded && [\n 'w-324 rounded-16 bg-white text-black border border-gray-900',\n 'z-10',\n disabled && 'opacity-50',\n ],\n )}\n >\n <button\n ref={triggerButtonRef}\n type=\"button\"\n data-testid=\"choice-expander-button\"\n aria-expanded={isExpanded}\n aria-controls={contentId}\n aria-label={ariaLabel || label}\n disabled={disabled}\n onClick={handleToggle}\n className={clsx(\n 'flex items-center justify-center w-240 mx-auto relative gap-20 transition-opacity duration-200',\n 'rounded-pill focus-visible:ring focus-visible:ring-8 focus-visible:ring-lavender/20 outline-none px-20 py-12 ',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n '[@supports(anchor-name:_--label-anchor)]:[--anchorSupport:1]',\n )}\n >\n {/* invisible top middle anchor position */}\n <div\n aria-hidden=\"true\"\n className=\"absolute h-24 w-24 mx-auto pointer-events-none\"\n style={{ anchorName: '--middle-anchor' } as React.CSSProperties}\n ></div>\n <span className=\"text-b3 flex items-center font-semibold\">\n {/* label anchor */}\n <span\n className={clsx('transition-opacity duration-200 pe-8', isExpanded && 'opacity-0')}\n >\n {label}\n </span>\n <div\n className=\"h-24 w-24\"\n style={{ anchorName: '--label-anchor' } as React.CSSProperties}\n aria-hidden=\"true\"\n >\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx(\n isExpanded ? 'absolute left-[calc(50%-12px)] rotate-180' : 'rotate-[0deg]',\n )}\n style={\n {\n transition: 'rotate 0.3s, left 0.3s',\n opacity: 'calc((1 - var(--anchorSupport)) * 1)',\n } as React.CSSProperties\n }\n />\n </div>\n <span className=\"sr-only\">{isExpanded ? collapseLabel : expandLabel}</span>\n </span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('absolute', isExpanded ? 'rotate-180' : 'rotate-[0deg]')}\n style={\n {\n positionAnchor: isExpanded ? '--middle-anchor' : '--label-anchor',\n left: 'anchor(left)',\n top: 'anchor(top)',\n transition: 'left 0.3s, rotate 0.3s',\n } as React.CSSProperties\n }\n />\n {showCheckIcon && (\n <Icon\n name=\"CheckDefault\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('transition-opacity duration-200', isExpanded && 'opacity-0')}\n />\n )}\n </button>\n\n <div\n className={clsx(\n 'grid overflow-hidden transition-[grid-template-rows,opacity] duration-500',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr] opacity-0',\n )}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-8 pb-8\" id={contentId}>\n {children}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChoiceExpander.js","names":[],"sources":["../../lib/ui/ChoiceExpander.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport { getBgColor, getTextColor } from './helpers/colors/colors';\nimport type { Colors } from './types/Colors';\n\nexport interface ChoiceExpanderProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Text shown when collapsed (e.g., \"From $255\")\n */\n label: string;\n\n /**\n * Show check icon in collapsed state (selected variant)\n */\n showCheckIcon?: boolean;\n\n /**\n * Content shown when expanded\n */\n children: ReactNode;\n\n /**\n * Controlled state - if provided, component is controlled\n */\n expanded?: boolean;\n\n /**\n * Initial state for uncontrolled mode\n */\n defaultExpanded?: boolean;\n\n /**\n * Callback when expanded state changes\n */\n onExpandedChange?: (isExpanded: boolean) => void;\n\n /**\n * Disable interaction\n */\n disabled?: boolean;\n\n /**\n * Custom aria-label for button\n */\n ariaLabel?: string;\n\n /**\n * Background color for unexpanded button state\n */\n buttonBgColor?: Colors;\n\n /**\n * Text color for unexpanded button state\n */\n buttonTextColor?: Colors;\n\n /**\n * collapse label for screen readers\n */\n collapseLabel: string;\n\n /**\n * expand label for screen readers\n */\n expandLabel: string;\n}\n\nexport const ChoiceExpander: FunctionComponent<ChoiceExpanderProps> = ({\n label,\n showCheckIcon = false,\n children,\n expanded,\n defaultExpanded = false,\n onExpandedChange,\n disabled = false,\n ariaLabel,\n buttonBgColor = 'black',\n buttonTextColor = 'white',\n collapseLabel,\n expandLabel,\n className,\n ...props\n}) => {\n const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);\n const contentId = useId();\n const morphContainerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLButtonElement>(null);\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const hasInteractedRef = useRef(false);\n\n const isExpanded = expanded !== undefined ? expanded : internalExpanded;\n\n const handleToggle = useCallback(() => {\n if (disabled) return;\n\n hasInteractedRef.current = true;\n const newState = !isExpanded;\n\n if (expanded === undefined) {\n setInternalExpanded(newState);\n }\n\n onExpandedChange?.(newState);\n }, [disabled, isExpanded, expanded, onExpandedChange]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n handleToggle();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isExpanded, handleToggle]);\n\n useEffect(() => {\n if (isExpanded && closeButtonRef.current) {\n closeButtonRef.current.focus();\n } else if (!isExpanded && hasInteractedRef.current && triggerButtonRef.current) {\n triggerButtonRef.current.focus();\n }\n }, [isExpanded]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (morphContainerRef.current && !morphContainerRef.current.contains(event.target as Node)) {\n handleToggle();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isExpanded, handleToggle]);\n\n return (\n <div\n className={clsx('relative flex items-center justify-center', className)}\n data-name=\"ChoiceExpander\"\n data-testid=\"choice-expander\"\n style={{ width: '240px', height: 48 }}\n {...props}\n >\n <div\n ref={morphContainerRef}\n className={clsx(\n 'absolute top-0 grid transition-all duration-500',\n !isExpanded && [\n 'w-240 rounded-pill-transitionable border-transparent',\n getBgColor(buttonBgColor),\n getTextColor(buttonTextColor),\n ],\n isExpanded && [\n 'w-324 rounded-16 bg-white text-black border border-gray-900',\n 'z-10',\n disabled && 'opacity-50',\n ],\n )}\n >\n <button\n ref={triggerButtonRef}\n type=\"button\"\n data-testid=\"choice-expander-button\"\n aria-expanded={isExpanded}\n aria-controls={contentId}\n aria-label={ariaLabel || label}\n disabled={disabled}\n onClick={handleToggle}\n className={clsx(\n 'flex items-center justify-center w-240 mx-auto relative gap-20 transition-opacity duration-200',\n 'rounded-pill focus-visible:ring focus-visible:ring-8 focus-visible:ring-lavender/20 outline-none px-20 py-12 ',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n '[@supports(anchor-name:_--label-anchor)]:[--anchorSupport:1]',\n )}\n >\n {/* invisible top middle anchor position */}\n <div\n aria-hidden=\"true\"\n className=\"absolute h-24 w-24 mx-auto pointer-events-none\"\n style={{ anchorName: '--middle-anchor' } as React.CSSProperties}\n ></div>\n <span className=\"text-b3 flex items-center font-semibold\">\n {/* label anchor */}\n <span\n className={clsx('transition-opacity duration-200 pe-8', isExpanded && 'opacity-0')}\n >\n {label}\n </span>\n <div\n className=\"h-24 w-24\"\n style={{ anchorName: '--label-anchor' } as React.CSSProperties}\n aria-hidden=\"true\"\n >\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx(\n isExpanded ? 'absolute left-[calc(50%-12px)] rotate-180' : 'rotate-[0deg]',\n )}\n style={\n {\n transition: 'rotate 0.3s, left 0.3s',\n opacity: 'calc((1 - var(--anchorSupport)) * 1)',\n } as React.CSSProperties\n }\n />\n </div>\n <span className=\"sr-only\">{isExpanded ? collapseLabel : expandLabel}</span>\n </span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('absolute', isExpanded ? 'rotate-180' : 'rotate-[0deg]')}\n style={\n {\n positionAnchor: isExpanded ? '--middle-anchor' : '--label-anchor',\n left: 'anchor(left)',\n top: 'anchor(top)',\n transition: 'left 0.3s, rotate 0.3s',\n } as React.CSSProperties\n }\n />\n {showCheckIcon && (\n <Icon\n name=\"CheckDefault\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('transition-opacity duration-200', isExpanded && 'opacity-0')}\n />\n )}\n </button>\n\n <div\n className={clsx(\n 'grid overflow-hidden transition-[grid-template-rows,opacity] duration-500',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr] opacity-0',\n )}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-8 pb-8\" id={contentId}>\n {children}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
package/ui/Dropdown.d.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
import { ComponentPropsWithoutRef,
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
2
|
import { IconicNames } from '@clubmed/trident-icons';
|
|
3
|
-
|
|
3
|
+
interface DropdownRenderContext {
|
|
4
|
+
close: () => void;
|
|
5
|
+
open: boolean;
|
|
6
|
+
toggle: () => void;
|
|
7
|
+
}
|
|
8
|
+
type DropdownChildren = ReactNode | ((context: DropdownRenderContext) => ReactNode);
|
|
9
|
+
export interface DropdownProps extends Omit<ComponentPropsWithoutRef<'button'>, 'children'> {
|
|
10
|
+
children?: DropdownChildren;
|
|
4
11
|
icon?: IconicNames;
|
|
5
12
|
}
|
|
6
|
-
export declare function
|
|
13
|
+
export declare function useDropdown(initialChildren?: DropdownChildren): {
|
|
14
|
+
children: ReactNode[];
|
|
15
|
+
close: () => void;
|
|
16
|
+
containerRef: import('react').RefObject<HTMLDivElement | null>;
|
|
17
|
+
isLeaving: boolean;
|
|
18
|
+
label: ReactNode[];
|
|
19
|
+
open: boolean;
|
|
20
|
+
toggle: () => void;
|
|
21
|
+
};
|
|
22
|
+
export declare function Dropdown({ icon, className, children: initialChildren, ...attrs }: DropdownProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
package/ui/Dropdown.js
CHANGED
|
@@ -5,43 +5,77 @@ import { useCallback as r, useEffect as i, useRef as a, useState as o } from "re
|
|
|
5
5
|
import { Icon as s } from "@clubmed/trident-icons";
|
|
6
6
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
7
|
//#region lib/ui/Dropdown.tsx
|
|
8
|
-
function u(
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
}, [])
|
|
8
|
+
function u(e) {
|
|
9
|
+
let [t, s] = o(!1), c = a(null), l = a(t), u = l.current, d = !t && u;
|
|
10
|
+
l.current = t;
|
|
11
|
+
let f = r(() => {
|
|
12
|
+
s((e) => !e);
|
|
13
|
+
}, []), p = r(() => {
|
|
14
|
+
s(!1);
|
|
15
|
+
}, []), m = typeof e == "function" ? e({
|
|
16
|
+
close: p,
|
|
17
|
+
open: t,
|
|
18
|
+
toggle: f
|
|
19
|
+
}) : e, { label: h, children: g } = n(m, ["label"]);
|
|
14
20
|
return i(() => {
|
|
15
|
-
if (!
|
|
21
|
+
if (!c.current) return;
|
|
22
|
+
let e = c.current.querySelectorAll(".dropdown-panel a[href], .dropdown-panel [data-dropdown-item]"), t = Array.from(e, (e) => {
|
|
23
|
+
let t = () => {
|
|
24
|
+
p();
|
|
25
|
+
};
|
|
26
|
+
return e.addEventListener("click", t), {
|
|
27
|
+
handleItemClick: t,
|
|
28
|
+
item: e
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
t.forEach(({ handleItemClick: e, item: t }) => {
|
|
33
|
+
t.removeEventListener("click", e);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}, [p, m]), i(() => {
|
|
37
|
+
if (!t) return;
|
|
16
38
|
let e = (e) => {
|
|
17
|
-
!
|
|
39
|
+
!c.current || e.composedPath().includes(c.current) || p();
|
|
18
40
|
};
|
|
19
|
-
return document.addEventListener("
|
|
20
|
-
document.removeEventListener("
|
|
41
|
+
return document.addEventListener("click", e), () => {
|
|
42
|
+
document.removeEventListener("click", e);
|
|
21
43
|
};
|
|
22
|
-
}, [
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
}, [p, t]), {
|
|
45
|
+
children: g,
|
|
46
|
+
close: p,
|
|
47
|
+
containerRef: c,
|
|
48
|
+
isLeaving: d,
|
|
49
|
+
label: h,
|
|
50
|
+
open: t,
|
|
51
|
+
toggle: f
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function d({ icon: n = "ArrowOutlinedDown", className: r, children: i, ...a }) {
|
|
55
|
+
let { children: o, containerRef: d, isLeaving: f, label: p, open: m, toggle: h } = u(i);
|
|
56
|
+
return /* @__PURE__ */ l("div", {
|
|
57
|
+
ref: d,
|
|
58
|
+
className: t("flex items-center gap-8 relative", r),
|
|
25
59
|
children: [/* @__PURE__ */ l("button", {
|
|
26
60
|
tabIndex: -1,
|
|
27
|
-
...
|
|
61
|
+
...a,
|
|
28
62
|
className: "flex gap-8 items-center relative",
|
|
29
|
-
onClick:
|
|
30
|
-
children: [
|
|
31
|
-
name:
|
|
63
|
+
onClick: h,
|
|
64
|
+
children: [p, /* @__PURE__ */ c(s, {
|
|
65
|
+
name: n,
|
|
32
66
|
className: "w-30"
|
|
33
67
|
})]
|
|
34
68
|
}), /* @__PURE__ */ c("div", {
|
|
35
|
-
className: t(e("z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]", {
|
|
36
|
-
"animate-
|
|
37
|
-
"animate-
|
|
38
|
-
"opacity-0 scale-90 pointer-events-none": !
|
|
69
|
+
className: t(e("dropdown-panel z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]", {
|
|
70
|
+
"animate-zoom-in": m,
|
|
71
|
+
"animate-zoom-out": !m && f,
|
|
72
|
+
"opacity-0 scale-90 pointer-events-none": !m && !f
|
|
39
73
|
})),
|
|
40
|
-
children:
|
|
74
|
+
children: o
|
|
41
75
|
})]
|
|
42
76
|
});
|
|
43
77
|
}
|
|
44
78
|
//#endregion
|
|
45
|
-
export {
|
|
79
|
+
export { d as Dropdown, u as useDropdown };
|
|
46
80
|
|
|
47
81
|
//# sourceMappingURL=Dropdown.js.map
|
package/ui/Dropdown.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.js","names":[],"sources":["../../lib/ui/Dropdown.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type
|
|
1
|
+
{"version":3,"file":"Dropdown.js","names":[],"sources":["../../lib/ui/Dropdown.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport clsx from 'clsx';\nimport { twMerge } from '@/ui/helpers/twMerge';\nimport { useSlots } from '@/ui/hooks/useSlots';\n\ninterface DropdownRenderContext {\n close: () => void;\n open: boolean;\n toggle: () => void;\n}\n\ntype DropdownChildren = ReactNode | ((context: DropdownRenderContext) => ReactNode);\n\nexport interface DropdownProps extends Omit<ComponentPropsWithoutRef<'button'>, 'children'> {\n children?: DropdownChildren;\n icon?: IconicNames;\n}\n\nexport function useDropdown(initialChildren?: DropdownChildren) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const wasVisibleRef = useRef(open);\n const wasVisible = wasVisibleRef.current;\n const isLeaving = !open && wasVisible;\n\n // update ref for next render\n wasVisibleRef.current = open;\n\n const toggle = useCallback(() => {\n setOpen((prev) => !prev);\n }, []);\n\n const close = useCallback(() => {\n setOpen(false);\n }, []);\n\n const renderedChildren =\n typeof initialChildren === 'function'\n ? initialChildren({ close, open, toggle })\n : initialChildren;\n\n const { label, children } = useSlots(renderedChildren, ['label']);\n\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const items = containerRef.current.querySelectorAll(\n '.dropdown-panel a[href], .dropdown-panel [data-dropdown-item]',\n );\n const listeners = Array.from(items, (item) => {\n const handleItemClick = () => {\n close();\n };\n item.addEventListener('click', handleItemClick);\n return { handleItemClick, item };\n });\n\n return () => {\n listeners.forEach(({ handleItemClick, item }) => {\n item.removeEventListener('click', handleItemClick);\n });\n };\n }, [close, renderedChildren]);\n\n // Close overlay when clicking outside using composedPath\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const handleOutsideClick = (event: PointerEvent) => {\n if (!containerRef.current || event.composedPath().includes(containerRef.current)) {\n return;\n }\n\n close();\n };\n\n document.addEventListener('click', handleOutsideClick);\n return () => {\n document.removeEventListener('click', handleOutsideClick);\n };\n }, [close, open]);\n\n return {\n children,\n close,\n containerRef,\n isLeaving,\n label,\n open,\n toggle,\n };\n}\n\nexport function Dropdown({\n icon = 'ArrowOutlinedDown',\n className,\n children: initialChildren,\n ...attrs\n}: DropdownProps) {\n const { children, containerRef, isLeaving, label, open, toggle } = useDropdown(initialChildren);\n\n return (\n <div ref={containerRef} className={twMerge('flex items-center gap-8 relative', className)}>\n <button\n tabIndex={-1}\n {...attrs}\n className=\"flex gap-8 items-center relative\"\n onClick={toggle}\n >\n {label}\n\n <Icon name={icon} className=\"w-30\" />\n </button>\n\n <div\n className={twMerge(\n clsx(\n 'dropdown-panel z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]',\n {\n 'animate-zoom-in': open,\n 'animate-zoom-out': !open && isLeaving,\n 'opacity-0 scale-90 pointer-events-none': !open && !isLeaving,\n },\n ),\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AA0BA,SAAgB,EAAY,GAAoC;CAC9D,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAe,EAAuB,KAAK,EAC3C,IAAgB,EAAO,EAAK,EAC5B,IAAa,EAAc,SAC3B,IAAY,CAAC,KAAQ;AAG3B,GAAc,UAAU;CAExB,IAAM,IAAS,QAAkB;AAC/B,KAAS,MAAS,CAAC,EAAK;IACvB,EAAE,CAAC,EAEA,IAAQ,QAAkB;AAC9B,IAAQ,GAAM;IACb,EAAE,CAAC,EAEA,IACJ,OAAO,KAAoB,aACvB,EAAgB;EAAE;EAAO;EAAM;EAAQ,CAAC,GACxC,GAEA,EAAE,UAAO,gBAAa,EAAS,GAAkB,CAAC,QAAQ,CAAC;AA6CjE,QA3CA,QAAgB;AACd,MAAI,CAAC,EAAa,QAChB;EAGF,IAAM,IAAQ,EAAa,QAAQ,iBACjC,gEACD,EACK,IAAY,MAAM,KAAK,IAAQ,MAAS;GAC5C,IAAM,UAAwB;AAC5B,OAAO;;AAGT,UADA,EAAK,iBAAiB,SAAS,EAAgB,EACxC;IAAE;IAAiB;IAAM;IAChC;AAEF,eAAa;AACX,KAAU,SAAS,EAAE,oBAAiB,cAAW;AAC/C,MAAK,oBAAoB,SAAS,EAAgB;KAClD;;IAEH,CAAC,GAAO,EAAiB,CAAC,EAG7B,QAAgB;AACd,MAAI,CAAC,EACH;EAGF,IAAM,KAAsB,MAAwB;AAC9C,IAAC,EAAa,WAAW,EAAM,cAAc,CAAC,SAAS,EAAa,QAAQ,IAIhF,GAAO;;AAIT,SADA,SAAS,iBAAiB,SAAS,EAAmB,QACzC;AACX,YAAS,oBAAoB,SAAS,EAAmB;;IAE1D,CAAC,GAAO,EAAK,CAAC,EAEV;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;AAGH,SAAgB,EAAS,EACvB,UAAO,qBACP,cACA,UAAU,GACV,GAAG,KACa;CAChB,IAAM,EAAE,aAAU,iBAAc,cAAW,UAAO,SAAM,cAAW,EAAY,EAAgB;AAE/F,QACE,kBAAC,OAAD;EAAK,KAAK;EAAc,WAAW,EAAQ,oCAAoC,EAAU;YAAzF,CACE,kBAAC,UAAD;GACE,UAAU;GACV,GAAI;GACJ,WAAU;GACV,SAAS;aAJX,CAMG,GAED,kBAAC,GAAD;IAAM,MAAM;IAAM,WAAU;IAAS,CAAA,CAC9B;MAET,kBAAC,OAAD;GACE,WAAW,EACT,EACE,8MACA;IACE,mBAAmB;IACnB,oBAAoB,CAAC,KAAQ;IAC7B,0CAA0C,CAAC,KAAQ,CAAC;IACrD,CACF,CACF;GAEA;GACG,CAAA,CACF"}
|
package/ui/ElasticHeight.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ interface ElasticHeightProps extends ComponentPropsWithoutRef<'div'> {
|
|
|
3
3
|
innerClassName?: string;
|
|
4
4
|
isExpanded?: boolean;
|
|
5
5
|
min?: number;
|
|
6
|
-
onHeightChange?: (height: number) => void;
|
|
7
6
|
}
|
|
8
7
|
export declare const ElasticHeight: FunctionComponent<ElasticHeightProps>;
|
|
9
8
|
export {};
|
package/ui/ElasticHeight.js
CHANGED
|
@@ -1,31 +1,22 @@
|
|
|
1
|
-
"use client";
|
|
2
1
|
import { t as e } from "../chunks/clsx.js";
|
|
3
|
-
import t from "
|
|
4
|
-
import {
|
|
5
|
-
import { jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as t } from "react";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
6
4
|
//#region lib/ui/ElasticHeight.tsx
|
|
7
|
-
var
|
|
8
|
-
let
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
className: e("overflow-hidden transition-all duration-500", o),
|
|
19
|
-
"data-expanded": l,
|
|
20
|
-
style: { height: l ? p : u },
|
|
21
|
-
children: /* @__PURE__ */ a("div", {
|
|
22
|
-
className: c,
|
|
23
|
-
ref: f,
|
|
24
|
-
children: s
|
|
5
|
+
var r = ({ className: r, children: i, innerClassName: a, isExpanded: o = !1, min: s = 0, ...c }) => {
|
|
6
|
+
let l = t(null);
|
|
7
|
+
return /* @__PURE__ */ n("div", {
|
|
8
|
+
...c,
|
|
9
|
+
className: e("overflow-hidden transition-all duration-500 grid", "data-[expanded=true]:grid-rows-[1fr]", "data-[expanded=false]:grid-rows-[0fr]", r),
|
|
10
|
+
"data-expanded": o,
|
|
11
|
+
children: /* @__PURE__ */ n("div", {
|
|
12
|
+
style: { minHeight: s },
|
|
13
|
+
className: e("overflow-hidden", a),
|
|
14
|
+
ref: l,
|
|
15
|
+
children: i
|
|
25
16
|
})
|
|
26
17
|
});
|
|
27
18
|
};
|
|
28
19
|
//#endregion
|
|
29
|
-
export {
|
|
20
|
+
export { r as ElasticHeight };
|
|
30
21
|
|
|
31
22
|
//# sourceMappingURL=ElasticHeight.js.map
|
package/ui/ElasticHeight.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElasticHeight.js","names":[],"sources":["../../lib/ui/ElasticHeight.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"ElasticHeight.js","names":[],"sources":["../../lib/ui/ElasticHeight.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { type ComponentPropsWithoutRef, type FunctionComponent, useRef } from 'react';\n\ninterface ElasticHeightProps extends ComponentPropsWithoutRef<'div'> {\n innerClassName?: string;\n isExpanded?: boolean;\n min?: number;\n}\n\nexport const ElasticHeight: FunctionComponent<ElasticHeightProps> = ({\n className,\n children,\n innerClassName,\n isExpanded = false,\n min = 0,\n ...attrs\n}) => {\n const ref = useRef<HTMLDivElement>(null as any);\n\n return (\n <div\n {...attrs}\n className={clsx(\n 'overflow-hidden transition-all duration-500 grid',\n 'data-[expanded=true]:grid-rows-[1fr]',\n 'data-[expanded=false]:grid-rows-[0fr]',\n className,\n )}\n data-expanded={isExpanded}\n >\n <div style={{ minHeight: min }} className={clsx('overflow-hidden', innerClassName)} ref={ref}>\n {children}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;AASA,IAAa,KAAwD,EACnE,cACA,aACA,mBACA,gBAAa,IACb,SAAM,GACN,GAAG,QACC;CACJ,IAAM,IAAM,EAAuB,KAAY;AAE/C,QACE,kBAAC,OAAD;EACE,GAAI;EACJ,WAAW,EACT,oDACA,wCACA,yCACA,EACD;EACD,iBAAe;YAEf,kBAAC,OAAD;GAAK,OAAO,EAAE,WAAW,GAAK;GAAE,WAAW,EAAK,mBAAmB,EAAe;GAAO;GACtF;GACG,CAAA;EACF,CAAA"}
|
package/ui/Loader.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { FunctionComponent } from 'react';
|
|
2
|
-
|
|
1
|
+
import { ComponentProps, FunctionComponent } from 'react';
|
|
2
|
+
import { Backdrop } from './Backdrop';
|
|
3
|
+
export interface LoaderProps {
|
|
3
4
|
isVisible?: boolean;
|
|
4
5
|
label?: string;
|
|
6
|
+
portalId?: ComponentProps<typeof Backdrop>['target'];
|
|
5
7
|
}
|
|
6
|
-
export declare const Loader: FunctionComponent<
|
|
7
|
-
export {};
|
|
8
|
+
export declare const Loader: FunctionComponent<LoaderProps>;
|
package/ui/Loader.js
CHANGED
|
@@ -33,8 +33,8 @@ var o = /* @__PURE__ */ a("svg", {
|
|
|
33
33
|
})]
|
|
34
34
|
})]
|
|
35
35
|
})]
|
|
36
|
-
}), s = ({ isVisible: s, label: c }) => {
|
|
37
|
-
let [{ status:
|
|
36
|
+
}), s = ({ isVisible: s, label: c, portalId: l }) => {
|
|
37
|
+
let [{ status: u, isMounted: d }, f] = t({
|
|
38
38
|
timeout: {
|
|
39
39
|
enter: 250,
|
|
40
40
|
exit: 250
|
|
@@ -44,16 +44,17 @@ var o = /* @__PURE__ */ a("svg", {
|
|
|
44
44
|
preEnter: !0
|
|
45
45
|
});
|
|
46
46
|
r(() => {
|
|
47
|
-
|
|
48
|
-
}, [s,
|
|
49
|
-
let
|
|
47
|
+
f(s);
|
|
48
|
+
}, [s, f]);
|
|
49
|
+
let p = u === "preEnter" || u === "entering", m = u === "exiting";
|
|
50
50
|
return /* @__PURE__ */ i(n, {
|
|
51
51
|
isVisible: s,
|
|
52
|
+
target: l,
|
|
52
53
|
sweep: !0,
|
|
53
|
-
children:
|
|
54
|
+
children: d && /* @__PURE__ */ a("div", {
|
|
54
55
|
className: e("flex flex-col items-center transition-all duration-500", {
|
|
55
|
-
"-translate-x-full opacity-0":
|
|
56
|
-
"translate-x-full opacity-100":
|
|
56
|
+
"-translate-x-full opacity-0": p,
|
|
57
|
+
"translate-x-full opacity-100": m
|
|
57
58
|
}),
|
|
58
59
|
role: "alert",
|
|
59
60
|
children: [/* @__PURE__ */ i("div", {
|
|
@@ -65,8 +66,8 @@ var o = /* @__PURE__ */ a("svg", {
|
|
|
65
66
|
children: o
|
|
66
67
|
}), /* @__PURE__ */ i("div", {
|
|
67
68
|
className: e("mx-auto max-w-[320px] px-20 text-center text-b3 transition-all delay-100 duration-400", {
|
|
68
|
-
"-translate-x-full opacity-0":
|
|
69
|
-
"translate-x-full opacity-100":
|
|
69
|
+
"-translate-x-full opacity-0": p,
|
|
70
|
+
"translate-x-full opacity-100": m
|
|
70
71
|
}),
|
|
71
72
|
children: c
|
|
72
73
|
})]
|
package/ui/Loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Loader.js","names":[],"sources":["../../lib/ui/Loader.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport { useEffect, type FunctionComponent } from 'react';\nimport { useTransitionState } from 'react-transition-state';\n\nimport { Backdrop } from './Backdrop';\n\
|
|
1
|
+
{"version":3,"file":"Loader.js","names":[],"sources":["../../lib/ui/Loader.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport { useEffect, type ComponentProps, type FunctionComponent } from 'react';\nimport { useTransitionState } from 'react-transition-state';\n\nimport { Backdrop } from './Backdrop';\n\nexport interface LoaderProps {\n isVisible?: boolean;\n label?: string;\n portalId?: ComponentProps<typeof Backdrop>['target'];\n}\n\nconst loaderSVG = (\n <svg viewBox=\"0 0 140 140\" width={140}>\n <defs>\n <path\n id=\"a\"\n d=\"m70 74.1-9.6 9.6 9.6 9.5 9.5-9.5L70 74Zm6.6-70.7c-.7-2.7-6.9 1.1-20.1 13 5.3 5.8 7.9 2.5 12.1 1 3.4 6.4 4.8 35.4-17.3 44 .6-29.1.9-60.4.9-60.4a1 1 0 0 0-1.3-1c-6.1.8-17 11.6-25.3 20.6 4.6 7.5 10.4.8 15-1.1 0 1.2-1 22.8-.6 44.7C17.3 66 21 19.5 22.2 13.6 22.8 8.9 7.6 19.3 0 26.4c2.4 4.3 5.7 3.4 10 1.8C8.3 49 23 67.9 40 67.5c.6 21.4 2.9 42.2 9 43.7 1 .2 1.6-21.8 2-46.1C92 52.4 76.5 3.4 76.5 3.4\"\n />\n </defs>\n <g fill=\"none\" fillRule=\"evenodd\" transform=\"translate(27 14)\">\n <mask id=\"b\" fill=\"#fff\">\n <use xlinkHref=\"#a\" />\n </mask>\n <g mask=\"url(#b)\">\n <path\n fill=\"#1E2643\"\n fillRule=\"nonzero\"\n d=\"M-83.1-23s6.7 3 11.2 3c4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3 4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3 4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3C.2-20 2.3-23 7-23c4.5 0 6.7 3 11.2 3 4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3 4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3 4.6 0 6.7-3 11.3-3 4.5 0 6.7 3 11.2 3 4.6 0 11.3-3 11.3-3v138H-83V-23Z\"\n className=\"animate-wave\"\n />\n <path\n fill=\"#1E2643\"\n fillRule=\"nonzero\"\n d=\"m70 74.1.7-.7-.7-.7-.7.7.7.7Zm-9.6 9.6-.7-.7-.7.7.7.7.7-.7Zm9.6 9.5-.7.7.7.7.7-.7-.7-.7Zm9.5-9.5.7.7.7-.7-.7-.7-.7.7Zm-23-67.3-.7-.7-.7.6.7.8.7-.7Zm12.1 1 1-.5-.5-.8-.8.3.3 1Zm-17.3 44h-1V63l1.4-.6-.4-1ZM52.2 1h1-1Zm-1.3-1v1h.2L51 0ZM25.6 20.6l-.7-.7-.5.5.4.7.8-.5Zm15-1.1h1V18l-1.4.5.4 1ZM40 64.2l.1 1h1v-1h-1ZM22.2 13.6l1 .2-1-.2ZM0 26.4l-.7-.8-.6.6.4.7.9-.5Zm10 1.8h1v-1.5l-1.4.6.3.9Zm30 39.3h1v-1h-1v1Zm9 43.7.3-1-.2 1Zm2-46.1-.2-1-.7.2v.8h1Zm18.2 8.3L59.7 83l1.4 1.4 9.6-9.6-1.4-1.4Zm-9.6 11 9.6 9.5 1.4-1.4L61 83l-1.4 1.4Zm11 9.5 9.5-9.5-1.4-1.4-9.5 9.5 1.4 1.4Zm9.5-11-9.5-9.5-1.4 1.4 9.5 9.6 1.4-1.4ZM77.6 3.2a2 2 0 0 0-1-1.3c-.6-.3-1.2-.3-1.8-.2-1 .2-2.4 1-4.1 2-3.4 2.1-8.2 6.1-14.9 12l1.4 1.6c6.6-6 11.4-9.9 14.6-12a11 11 0 0 1 3.4-1.6h.4l2-.5Zm-21.8 14c1.3 1.5 2.6 2.5 3.8 3a6 6 0 0 0 3.5.5c1-.1 2-.6 3-1 1-.5 1.9-1 2.9-1.3l-.7-1.9c-1.1.4-2.2 1-3 1.4l-2.5.9a4 4 0 0 1-2.4-.4 12 12 0 0 1-3.2-2.6l-1.4 1.4Zm12 .7c.7 1.5 1.4 4.3 1.7 8 .2 3.7 0 8-1 12.6-2 8.9-7 18-17.6 22.2l.8 1.8a31.3 31.3 0 0 0 18.8-23.6 51 51 0 0 0 1-13.1c-.3-3.8-1-7-2-8.8l-1.7 1ZM52.3 61.5a5227.3 5227.3 0 0 0 .9-60.1V1h-2v1.3a4268.6 4268.6 0 0 1-1 59l2 .1ZM53.2 1c0-.3 0-.6-.2-.9l-1.8 1h2ZM53 .1a2 2 0 0 0-.6-.7L51.2 1 53 .1Zm-.6-.7a2 2 0 0 0-.9-.4l-.3 2 1.2-1.6Zm-.9-.4a2 2 0 0 0-1 0l.7 2 .3-2Zm-.8 0C49-.6 47 .3 45 1.6s-4.3 3-6.6 5c-4.5 4-9.3 8.9-13.5 13.4l1.5 1.4c4.1-4.5 8.9-9.4 13.3-13.3C42 6 44.1 4.4 46 3.2c2-1.3 3.7-2 5-2.2l-.3-2Zm-26 22c1.3 2.1 2.7 3.3 4.3 3.8a7 7 0 0 0 4.5-.3c1.4-.5 2.8-1.4 4-2.1 1.3-.8 2.4-1.6 3.5-2l-.8-1.9-3.7 2.2c-1.3.7-2.5 1.5-3.7 2-1.2.4-2.3.5-3.2.2-1-.3-2-1.1-3.1-2.8l-1.7 1Zm15-1.5c0 1.1-1.2 22.8-.7 44.7h2c-.5-22 .6-43.4.6-44.7h-2Zm.2 43.7c-5.2.4-9-2-11.6-6-2.7-4-4.3-9.6-5.2-15.6-1.8-12-.5-25 .1-27.8l-2-.4c-.6 3-1.9 16.3-.1 28.5.9 6.1 2.6 12.1 5.5 16.5a14 14 0 0 0 13.5 6.8l-.2-2ZM23.2 13.7l-.1-1.2a2 2 0 0 0-1-1c-.7-.2-1.6 0-2.3.1a28 28 0 0 0-6.2 3.1 106 106 0 0 0-14.3 11L.7 27c3.7-3.5 9.4-7.8 14-10.7a26.4 26.4 0 0 1 6.4-3h.3l-.2-.1v.2l2 .2ZM-.8 27c.6 1.1 1.3 2 2.2 2.6a5 5 0 0 0 2.8 1c2 .1 4-.6 6-1.4l-.6-1.8c-2.1.8-3.8 1.3-5.2 1.2-.7 0-1.3-.2-1.9-.6-.5-.4-1-1-1.6-2l-1.8 1Zm9.6 1a41.8 41.8 0 0 0 8.4 28.3c5.7 7.5 14 12.3 22.9 12v-2a26 26 0 0 1-21.3-11.2 40 40 0 0 1-8-27H9ZM39 67.4c.3 10.7 1 21.3 2.5 29.5.7 4 1.6 7.5 2.7 10.1 1.1 2.6 2.6 4.6 4.7 5l.4-2c-1-.2-2.2-1.3-3.2-3.8-1-2.3-2-5.7-2.7-9.7-1.4-8-2-18.5-2.4-29.1h-2Zm9.8 44.6c.7.2 1.1-.3 1.2-.4l.2-.4.2-.9.3-2.8.5-10.2.9-32.3h-2a1859.2 1859.2 0 0 1-1.4 42.3 38 38 0 0 1-.4 3.2c0-.1.4-.6 1-.4l-.5 2Zm2.6-46a39.2 39.2 0 0 0 21.8-15.4 46 46 0 0 0 7-21.1 73 73 0 0 0-2.6-25.9l-.1-.4v-.1l-1 .2-1 .3a14.2 14.2 0 0 1 .2.6 51 51 0 0 1 1.6 7.1 71 71 0 0 1 .9 18A37.2 37.2 0 0 1 50.8 64l.6 2Z\"\n mask=\"url(#a)\"\n />\n </g>\n </g>\n </svg>\n);\n\nexport const Loader: FunctionComponent<LoaderProps> = ({ isVisible, label, portalId }) => {\n const [{ status, isMounted }, toggle] = useTransitionState({\n timeout: { enter: 250, exit: 250 },\n mountOnEnter: true,\n unmountOnExit: true,\n preEnter: true,\n });\n\n useEffect(() => {\n toggle(isVisible);\n }, [isVisible, toggle]);\n\n const entering = status === 'preEnter' || status === 'entering';\n const exiting = status === 'exiting';\n\n return (\n <Backdrop isVisible={isVisible} target={portalId} sweep>\n {isMounted && (\n <div\n className={clsx('flex flex-col items-center transition-all duration-500', {\n '-translate-x-full opacity-0': entering,\n 'translate-x-full opacity-100': exiting,\n })}\n role=\"alert\"\n >\n <div\n className=\"relative isolate\"\n style={{\n maskImage: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2'%3E%3Cellipse cx='1' cy='1' rx='1' ry='1'/%3E%3C/svg%3E\")`,\n WebkitMaskImage: `url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2'%3E%3Cellipse cx='1' cy='1' rx='1' ry='1'/%3E%3C/svg%3E\")`,\n }}\n >\n {loaderSVG}\n </div>\n <div\n className={clsx(\n 'mx-auto max-w-[320px] px-20 text-center text-b3 transition-all delay-100 duration-400',\n {\n '-translate-x-full opacity-0': entering,\n 'translate-x-full opacity-100': exiting,\n },\n )}\n >\n {label}\n </div>\n </div>\n )}\n </Backdrop>\n );\n};\n"],"mappings":";;;;;;AAcA,IAAM,IACJ,kBAAC,OAAD;CAAK,SAAQ;CAAc,OAAO;WAAlC,CACE,kBAAC,QAAD,EAAA,UACE,kBAAC,QAAD;EACE,IAAG;EACH,GAAE;EACF,CAAA,EACG,CAAA,EACP,kBAAC,KAAD;EAAG,MAAK;EAAO,UAAS;EAAU,WAAU;YAA5C,CACE,kBAAC,QAAD;GAAM,IAAG;GAAI,MAAK;aAChB,kBAAC,OAAD,EAAK,WAAU,MAAO,CAAA;GACjB,CAAA,EACP,kBAAC,KAAD;GAAG,MAAK;aAAR,CACE,kBAAC,QAAD;IACE,MAAK;IACL,UAAS;IACT,GAAE;IACF,WAAU;IACV,CAAA,EACF,kBAAC,QAAD;IACE,MAAK;IACL,UAAS;IACT,GAAE;IACF,MAAK;IACL,CAAA,CAAA;;;IAMG,KAA0C,EAAE,cAAW,UAAO,kBAAe;CACxF,IAAM,CAAC,EAAE,WAAQ,gBAAa,KAAU,EAAmB;EACzD,SAAS;GAAE,OAAO;GAAK,MAAM;GAAK;EAClC,cAAc;EACd,eAAe;EACf,UAAU;EACX,CAAC;AAEF,SAAgB;AACd,IAAO,EAAU;IAChB,CAAC,GAAW,EAAO,CAAC;CAEvB,IAAM,IAAW,MAAW,cAAc,MAAW,YAC/C,IAAU,MAAW;AAE3B,QACE,kBAAC,GAAD;EAAqB;EAAW,QAAQ;EAAU,OAAA;YAC/C,KACC,kBAAC,OAAD;GACE,WAAW,EAAK,0DAA0D;IACxE,+BAA+B;IAC/B,gCAAgC;IACjC,CAAC;GACF,MAAK;aALP,CAOE,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KACL,WAAW;KACX,iBAAiB;KAClB;cAEA;IACG,CAAA,EACN,kBAAC,OAAD;IACE,WAAW,EACT,yFACA;KACE,+BAA+B;KAC/B,gCAAgC;KACjC,CACF;cAEA;IACG,CAAA,CAAA;;EAGD,CAAA"}
|
package/ui/Popin.js
CHANGED
|
@@ -20,8 +20,8 @@ var c = ({ closeLabel: e, onClose: n }) => /* @__PURE__ */ o(t, {
|
|
|
20
20
|
onClose: d,
|
|
21
21
|
children: /* @__PURE__ */ o("div", {
|
|
22
22
|
className: r(e("border-lightGrey rounded-16 pointer-events-auto mx-20 w-full border bg-white origin-center will-change[transform,opacity]", {
|
|
23
|
-
"animate-
|
|
24
|
-
"animate-
|
|
23
|
+
"animate-zoom-in": f,
|
|
24
|
+
"animate-zoom-out": !f && b,
|
|
25
25
|
"opacity-0 scale-90": !f && !b
|
|
26
26
|
}), p),
|
|
27
27
|
children: /* @__PURE__ */ s("div", {
|
package/ui/Popin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popin.js","names":[],"sources":["../../lib/ui/Popin.tsx"],"sourcesContent":["import type { FunctionComponent, PropsWithChildren, ReactNode } from 'react';\nimport { useRef } from 'react';\nimport { twMerge } from './helpers/twMerge';\nimport { Backdrop, type BackdropProps } from './Backdrop';\nimport { Button } from './buttons/Button';\nimport clsx from 'clsx';\nimport { useSlots } from './hooks/useSlots';\n\nexport type ClosePopinCallback = () => void;\n\nexport interface PopinFooterProps {\n closeLabel?: string;\n onClose: ClosePopinCallback;\n}\n\nconst PopinFooter = ({ closeLabel, onClose }: PopinFooterProps) => {\n return (\n <Button\n color=\"black\"\n variant=\"circle\"\n icon=\"CrossDefault\"\n className=\"mx-auto\"\n aria-label={closeLabel}\n onClick={onClose}\n />\n );\n};\n\nexport interface PopinProps {\n title?: ReactNode;\n closeLabel?: string;\n onClose: ClosePopinCallback;\n isVisible: boolean;\n className?: string;\n bodyClassName?: string;\n showCloseButton?: boolean;\n target?: BackdropProps['target'];\n /**\n * @deprecated use popinFooter slot instead\n */\n Footer?: FunctionComponent<PopinFooterProps> | false;\n}\n\nexport const Popin: FunctionComponent<PropsWithChildren<PopinProps>> = ({\n title,\n children,\n closeLabel,\n onClose,\n isVisible,\n className = 'sm:w-360',\n bodyClassName,\n Footer = PopinFooter,\n}) => {\n const { children: popinBody, popinFooter } = useSlots(children, ['popinFooter']);\n\n // Prevent initial mount flash when closed: only animate leave if it was visible before\n const wasVisibleRef = useRef(isVisible);\n const wasVisible = wasVisibleRef.current;\n const isLeaving = !isVisible && wasVisible;\n\n // update ref for next render\n wasVisibleRef.current = isVisible;\n return (\n <Backdrop isVisible={isVisible} onClose={onClose}>\n <div\n className={twMerge(\n clsx(\n 'border-lightGrey rounded-16 pointer-events-auto mx-20 w-full border bg-white origin-center will-change[transform,opacity]',\n {\n 'animate-
|
|
1
|
+
{"version":3,"file":"Popin.js","names":[],"sources":["../../lib/ui/Popin.tsx"],"sourcesContent":["import type { FunctionComponent, PropsWithChildren, ReactNode } from 'react';\nimport { useRef } from 'react';\nimport { twMerge } from './helpers/twMerge';\nimport { Backdrop, type BackdropProps } from './Backdrop';\nimport { Button } from './buttons/Button';\nimport clsx from 'clsx';\nimport { useSlots } from './hooks/useSlots';\n\nexport type ClosePopinCallback = () => void;\n\nexport interface PopinFooterProps {\n closeLabel?: string;\n onClose: ClosePopinCallback;\n}\n\nconst PopinFooter = ({ closeLabel, onClose }: PopinFooterProps) => {\n return (\n <Button\n color=\"black\"\n variant=\"circle\"\n icon=\"CrossDefault\"\n className=\"mx-auto\"\n aria-label={closeLabel}\n onClick={onClose}\n />\n );\n};\n\nexport interface PopinProps {\n title?: ReactNode;\n closeLabel?: string;\n onClose: ClosePopinCallback;\n isVisible: boolean;\n className?: string;\n bodyClassName?: string;\n showCloseButton?: boolean;\n target?: BackdropProps['target'];\n /**\n * @deprecated use popinFooter slot instead\n */\n Footer?: FunctionComponent<PopinFooterProps> | false;\n}\n\nexport const Popin: FunctionComponent<PropsWithChildren<PopinProps>> = ({\n title,\n children,\n closeLabel,\n onClose,\n isVisible,\n className = 'sm:w-360',\n bodyClassName,\n Footer = PopinFooter,\n}) => {\n const { children: popinBody, popinFooter } = useSlots(children, ['popinFooter']);\n\n // Prevent initial mount flash when closed: only animate leave if it was visible before\n const wasVisibleRef = useRef(isVisible);\n const wasVisible = wasVisibleRef.current;\n const isLeaving = !isVisible && wasVisible;\n\n // update ref for next render\n wasVisibleRef.current = isVisible;\n return (\n <Backdrop isVisible={isVisible} onClose={onClose}>\n <div\n className={twMerge(\n clsx(\n 'border-lightGrey rounded-16 pointer-events-auto mx-20 w-full border bg-white origin-center will-change[transform,opacity]',\n {\n 'animate-zoom-in': isVisible,\n 'animate-zoom-out': !isVisible && isLeaving,\n 'opacity-0 scale-90': !isVisible && !isLeaving,\n },\n ),\n className,\n )}\n >\n <div\n className={twMerge('text-center max-h-[90vh] flex flex-col p-40 gap-40', bodyClassName)}\n >\n {title && <div className=\"text-h5 mt-0 -mb-20 text-start font-serif\">{title}</div>}\n <div className=\"text-start overflow-auto\">{popinBody}</div>\n {!popinFooter?.length && Footer && (\n <div>\n <Footer closeLabel={closeLabel} onClose={onClose} />\n </div>\n )}\n\n {popinFooter}\n </div>\n </div>\n </Backdrop>\n );\n};\n"],"mappings":";;;;;;;;AAeA,IAAM,KAAe,EAAE,eAAY,iBAE/B,kBAAC,GAAD;CACE,OAAM;CACN,SAAQ;CACR,MAAK;CACL,WAAU;CACV,cAAY;CACZ,SAAS;CACT,CAAA,EAmBO,KAA2D,EACtE,UACA,aACA,eACA,YACA,cACA,eAAY,YACZ,kBACA,YAAS,QACL;CACJ,IAAM,EAAE,UAAU,GAAW,mBAAgB,EAAS,GAAU,CAAC,cAAc,CAAC,EAG1E,IAAgB,EAAO,EAAU,EACjC,IAAa,EAAc,SAC3B,IAAY,CAAC,KAAa;AAIhC,QADA,EAAc,UAAU,GAEtB,kBAAC,GAAD;EAAqB;EAAoB;YACvC,kBAAC,OAAD;GACE,WAAW,EACT,EACE,6HACA;IACE,mBAAmB;IACnB,oBAAoB,CAAC,KAAa;IAClC,sBAAsB,CAAC,KAAa,CAAC;IACtC,CACF,EACD,EACD;aAED,kBAAC,OAAD;IACE,WAAW,EAAQ,sDAAsD,EAAc;cADzF;KAGG,KAAS,kBAAC,OAAD;MAAK,WAAU;gBAA6C;MAAY,CAAA;KAClF,kBAAC,OAAD;MAAK,WAAU;gBAA4B;MAAgB,CAAA;KAC1D,CAAC,GAAa,UAAU,KACvB,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;MAAoB;MAAqB;MAAW,CAAA,EAChD,CAAA;KAGP;KACG;;GACF,CAAA;EACG,CAAA"}
|