@versini/ui-bubble 8.0.9 → 9.0.1

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/README.md CHANGED
@@ -37,7 +37,7 @@ npm install @versini/ui-bubble
37
37
  ### Basic Bubbles
38
38
 
39
39
  ```tsx
40
- import { Bubble } from "@versini/ui-bubble";
40
+ import { Bubble } from "@versini/ui-bubble/bubble";
41
41
 
42
42
  function App() {
43
43
  return (
@@ -57,7 +57,7 @@ function App() {
57
57
  ### Bubble with Footer
58
58
 
59
59
  ```tsx
60
- import { Bubble } from "@versini/ui-bubble";
60
+ import { Bubble } from "@versini/ui-bubble/bubble";
61
61
 
62
62
  function App() {
63
63
  return (
@@ -79,7 +79,7 @@ function App() {
79
79
  ### Copy to Clipboard
80
80
 
81
81
  ```tsx
82
- import { Bubble } from "@versini/ui-bubble";
82
+ import { Bubble } from "@versini/ui-bubble/bubble";
83
83
 
84
84
  function App() {
85
85
  return (
@@ -111,7 +111,7 @@ function App() {
111
111
  ### Chat Interface
112
112
 
113
113
  ```tsx
114
- import { Bubble } from "@versini/ui-bubble";
114
+ import { Bubble } from "@versini/ui-bubble/bubble";
115
115
 
116
116
  function ChatExample() {
117
117
  const messages = [
@@ -151,7 +151,8 @@ function ChatExample() {
151
151
  ### Advanced Footer Usage
152
152
 
153
153
  ```tsx
154
- import { Bubble } from "@versini/ui-bubble";
154
+ import { Bubble } from "@versini/ui-bubble/bubble";
155
+ import { BUBBLE_FOOTER_EMPTY } from "@versini/ui-bubble/constants";
155
156
 
156
157
  function AdvancedFooterExample() {
157
158
  return (
@@ -163,7 +164,7 @@ function AdvancedFooterExample() {
163
164
  footer={{
164
165
  "Message ID": "msg-123",
165
166
  Sent: "2:30 PM",
166
- Status: Bubble.FOOTER_EMPTY, // Empty row that maintains height
167
+ Status: BUBBLE_FOOTER_EMPTY, // Empty row that maintains height
167
168
  Delivered: "2:31 PM",
168
169
  Read: "2:35 PM"
169
170
  }}
@@ -191,7 +192,7 @@ function AdvancedFooterExample() {
191
192
  ### Custom Width Control
192
193
 
193
194
  ```tsx
194
- import { Bubble } from "@versini/ui-bubble";
195
+ import { Bubble } from "@versini/ui-bubble/bubble";
195
196
 
196
197
  function CustomWidthExample() {
197
198
  return (
@@ -220,7 +221,7 @@ function CustomWidthExample() {
220
221
  ### Copy Functionality Variations
221
222
 
222
223
  ```tsx
223
- import { Bubble } from "@versini/ui-bubble";
224
+ import { Bubble } from "@versini/ui-bubble/bubble";
224
225
 
225
226
  function CopyFunctionalityExample() {
226
227
  const handleCustomCopy = (text: any) => {
@@ -281,4 +282,4 @@ function CopyFunctionalityExample() {
281
282
 
282
283
  ### Special Values
283
284
 
284
- - `Bubble.FOOTER_EMPTY` - Use in footer to create an empty row that maintains height
285
+ - `BUBBLE_FOOTER_EMPTY` - Import from `@versini/ui-bubble/constants` to create an empty footer row that maintains height
@@ -0,0 +1 @@
1
+ export declare const BUBBLE_CLASSNAME = "av-bubble";
@@ -0,0 +1,22 @@
1
+ /*!
2
+ @versini/ui-bubble v9.0.1
3
+ © 2025 gizmette.com
4
+ */
5
+ try {
6
+ if (!window.__VERSINI_UI_BUBBLE__) {
7
+ window.__VERSINI_UI_BUBBLE__ = {
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
+ homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
16
+ }
17
+
18
+
19
+ ;// CONCATENATED MODULE: ./src/common/constants.ts
20
+ const BUBBLE_CLASSNAME = "av-bubble";
21
+
22
+ export { BUBBLE_CLASSNAME };
@@ -0,0 +1,3 @@
1
+ import type { BubbleProps } from "./BubbleTypes";
2
+ export type { BubbleProps } from "./BubbleTypes";
3
+ export declare const Bubble: ({ children, kind, className, contentClassName, footer, rawFooter, copyToClipboard, copyToClipboardFocusMode, copyToClipboardMode, noMaxWidth, tail, gradient, }: BubbleProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,12 @@
1
1
  /*!
2
- @versini/ui-bubble v8.0.9
2
+ @versini/ui-bubble v9.0.1
3
3
  © 2025 gizmette.com
4
4
  */
5
5
  try {
6
6
  if (!window.__VERSINI_UI_BUBBLE__) {
7
7
  window.__VERSINI_UI_BUBBLE__ = {
8
- version: "8.0.9",
9
- buildTime: "12/16/2025 06:22 PM EST",
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
10
  homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
11
  license: "MIT",
12
12
  };
@@ -19,10 +19,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
19
19
  import { ButtonIcon } from "@versini/ui-button/button-icon";
20
20
  import { IconCopied, IconCopy } from "@versini/ui-icons";
21
21
  import { useEffect, useState } from "react";
22
- import clsx from "clsx";
23
-
24
- ;// CONCATENATED MODULE: ./src/common/constants.ts
25
- const BUBBLE_CLASSNAME = "av-bubble";
22
+ import { BUBBLE_FOOTER_EMPTY } from "../BubbleConstants/BubbleConstants.js";
23
+ import { getBubbleClasses } from "./utilities.js";
26
24
 
27
25
  ;// CONCATENATED MODULE: external "react/jsx-runtime"
28
26
 
@@ -32,93 +30,9 @@ const BUBBLE_CLASSNAME = "av-bubble";
32
30
 
33
31
  ;// CONCATENATED MODULE: external "react"
34
32
 
35
- ;// CONCATENATED MODULE: external "clsx"
36
-
37
- ;// CONCATENATED MODULE: ./src/components/Bubble/utilities.ts
33
+ ;// CONCATENATED MODULE: external "../BubbleConstants/BubbleConstants.js"
38
34
 
39
-
40
- const getBubbleSizesClasses = ({ kind, noMaxWidth })=>{
41
- return clsx("px-4 py-2", {
42
- "max-w-xs sm:max-w-md md:max-w-2xl": !noMaxWidth,
43
- "lg:max-w-3xl": kind === "left" && !noMaxWidth
44
- });
45
- };
46
- const getBubbleColorClasses = ({ kind, gradient })=>{
47
- // No gradient - solid colors
48
- if (!gradient) {
49
- return clsx({
50
- "bg-surface-light dark:bg-surface-dark": kind === "left",
51
- "bg-surface-accent": kind === "right"
52
- });
53
- }
54
- // Gradient presets based on intensity
55
- if (gradient === "light") {
56
- return clsx({
57
- "bg-gradient-to-b from-surface-light/80 to-surface-light dark:from-surface-dark/80 dark:to-surface-dark": kind === "left",
58
- "bg-gradient-to-b from-surface-accent/80 to-surface-accent": kind === "right"
59
- });
60
- }
61
- if (gradient === "medium") {
62
- return clsx({
63
- "bg-gradient-to-b from-surface-light/65 to-surface-light dark:from-surface-dark/65 dark:to-surface-dark": kind === "left",
64
- "bg-gradient-to-b from-surface-accent/65 to-surface-accent": kind === "right"
65
- });
66
- }
67
- // gradient === "strong"
68
- return clsx({
69
- "bg-gradient-to-b from-surface-light/50 to-surface-light dark:from-surface-dark/50 dark:to-surface-dark": kind === "left",
70
- "bg-gradient-to-b from-surface-accent/50 to-surface-accent": kind === "right"
71
- });
72
- };
73
- const getBubbleTypographyClasses = ({ kind })=>{
74
- return clsx("prose prose-dark dark:prose-lighter", "prose-blockquote:my-1", "prose-ol:my-1 prose-ul:my-1", {
75
- "text-copy-lighter": kind === "right"
76
- });
77
- };
78
- const getBubbleBorderClasses = ({ kind, tail })=>{
79
- if (tail) {
80
- return clsx(`${BUBBLE_CLASSNAME}-${kind}-tail`, "rounded-3xl", "relative", "before:content-['']", "before:w-3", "before:h-2", "before:absolute", "before:bottom-0", {
81
- "last-bubble-right:before:right-[2px] last-bubble-right:before:border-l-[8px] last-bubble-right:before:border-l-surface-accent last-bubble-right:before:rounded-bl-[100%]": kind === "right",
82
- "last-bubble-left:before:left-[2px] last-bubble-left:before:border-r-[8px] last-bubble-left:before:border-r-surface-light last-bubble-left:dark:before:border-r-surface-dark last-bubble-left:before:rounded-br-[100%]": kind === "left"
83
- });
84
- }
85
- if (!tail) {
86
- return clsx("rounded-b-xl", {
87
- "rounded-tr-xl": kind === "left",
88
- "rounded-tl-xl": kind === "right"
89
- });
90
- }
91
- };
92
- const getBubbleClasses = ({ kind, className, contentClassName, noMaxWidth, tail, gradient })=>{
93
- const wrapper = clsx(BUBBLE_CLASSNAME, `${BUBBLE_CLASSNAME}-${kind}`, "flex items-start", {
94
- "flex-row-reverse": kind === "right"
95
- }, className);
96
- const main = clsx(`${BUBBLE_CLASSNAME}-content`, "flex flex-col empty:hidden", getBubbleSizesClasses({
97
- kind,
98
- noMaxWidth
99
- }), getBubbleTypographyClasses({
100
- kind
101
- }), getBubbleColorClasses({
102
- kind,
103
- gradient
104
- }), getBubbleBorderClasses({
105
- kind,
106
- tail
107
- }), contentClassName);
108
- const footer = "pr-2 pt-1 text-end text-xs text-copy-light";
109
- const copyButton = clsx("flex flex-col-reverse sm:flex-row", {
110
- "ml-2": kind === "left" && !tail,
111
- "mr-2": kind === "right" && !tail,
112
- "ml-1": kind === "left" && tail,
113
- "mr-1": kind === "right" && tail
114
- });
115
- return {
116
- wrapper,
117
- main,
118
- footer,
119
- copyButton
120
- };
121
- };
35
+ ;// CONCATENATED MODULE: external "./utilities.js"
122
36
 
123
37
  ;// CONCATENATED MODULE: ./src/components/Bubble/Bubble.tsx
124
38
 
@@ -126,8 +40,7 @@ const getBubbleClasses = ({ kind, className, contentClassName, noMaxWidth, tail,
126
40
 
127
41
 
128
42
 
129
- // Special symbol to represent an empty footer row that should maintain its height
130
- const BUBBLE_FOOTER_EMPTY = "FOOTER_EMPTY";
43
+
131
44
  const Bubble = ({ children, kind = "left", className, contentClassName, footer, rawFooter, copyToClipboard, copyToClipboardFocusMode = "system", copyToClipboardMode = "system", noMaxWidth = false, tail = false, gradient })=>{
132
45
  const [copied, setCopied] = useState(false);
133
46
  const bubbleClasses = getBubbleClasses({
@@ -227,8 +140,4 @@ const Bubble = ({ children, kind = "left", className, contentClassName, footer,
227
140
  });
228
141
  };
229
142
 
230
- ;// CONCATENATED MODULE: ./src/components/index.ts
231
-
232
-
233
-
234
- export { BUBBLE_CLASSNAME, BUBBLE_FOOTER_EMPTY, Bubble };
143
+ export { Bubble };
@@ -1,109 +1,101 @@
1
- import { JSX } from 'react/jsx-runtime';
2
-
3
- export declare const Bubble: ({ children, kind, className, contentClassName, footer, rawFooter, copyToClipboard, copyToClipboardFocusMode, copyToClipboardMode, noMaxWidth, tail, gradient, }: BubbleProps) => JSX.Element;
4
-
5
- export declare const BUBBLE_CLASSNAME = "av-bubble";
6
-
7
- export declare const BUBBLE_FOOTER_EMPTY = "FOOTER_EMPTY";
8
-
9
- export declare type BubbleProps = {
10
- /**
11
- * The text to render in the bubble.
12
- */
13
- children: React.ReactNode;
14
- /**
15
- * CSS class(es) to add to the main component wrapper.
16
- * Bubble is made of a wrapper, a main content, and a footer. This prop
17
- * allows you to add classes to the main component wrapper.
18
- */
19
- className?: string;
20
- /**
21
- * CSS class(es) to add to the content wrapper.
22
- * Bubble is made of a wrapper, a main content, and a footer. This prop
23
- * allows you to add classes to the content wrapper.
24
- */
25
- contentClassName?: string;
26
- /**
27
- * Whether or not to show a "copy/paste" icon next to the Bubble.
28
- * - If a function is passed, it will be called with the text to copy.
29
- * - If a string is passed, that string will be copied.
30
- * - If a boolean is passed, the children will be copied, but only if they
31
- * are of type string.
32
- */
33
- copyToClipboard?: boolean | string | ((text: any) => void);
34
- /**
35
- * The type of focus for the Copy Button. This will change the color
36
- * of the focus ring around the Button.
37
- */
38
- copyToClipboardFocusMode?: "dark" | "light" | "system" | "alt-system";
39
- /**
40
- * The mode of Copy Button. This will change the color of the Button.
41
- */
42
- copyToClipboardMode?: "dark" | "light" | "system" | "alt-system";
43
- /**
44
- * Object depicting the extra rows for the Bubble.
45
- * @example
46
- * ```tsx
47
- * <Bubble
48
- * footer={{
49
- * "Sent": "12:00 PM",
50
- * "Delivered": "12:01 PM",
51
- * "Verified": Bubble.FOOTER_EMPTY,
52
- * "Read": "12:02 PM",
53
- * }}
54
- * >Hello World</Bubble>
55
- * ```
56
- * This will create a footer with 4 rows, with the row before last being
57
- * empty but taking the full height of a normal row.
58
- *
59
- */
60
- footer?: {
61
- [key: string]: string | number | undefined | null;
62
- };
63
- /**
64
- * The gradient intensity applied to the Bubble background.
65
- * - "light": Subtle gradient with 80% opacity at the top
66
- * - "medium": Medium gradient with 65% opacity at the top
67
- * - "strong": Strong gradient with 50% opacity at the top
68
- * - undefined: No gradient, solid background color
69
- *
70
- * @default undefined
71
- */
72
- gradient?: "light" | "medium" | "strong";
73
- /**
74
- * The type of Bubble. This will change the color of the Bubble
75
- * as well as the chevron location.
76
- */
77
- kind?: "left" | "right";
78
- /**
79
- * Same as "footer" but accepts raw JSX.
80
- */
81
- rawFooter?: React.ReactNode;
82
- /**
83
- * Whether or not the Bubble should have a default max-width.
84
- * By default, bubble width will be responsive to the viewport,
85
- * but in some cases, it may be useful to disable this behavior
86
- * and allow the Bubble to grow to its content.
87
- * You can also provide your own container class to control the width,
88
- * based on the container's width.
89
- * @see https://css-tricks.com/css-container-queries/#aa-container-length-units
90
- *
91
- * @example
92
- * ```tsx
93
- * <div> // this div should be declared as a container
94
- * <Bubble kind="left" noMaxWidth className="max-w-[95qcw]">
95
- * Hello World
96
- * </Bubble>
97
- * </div>
98
- * ```
99
- * @default false
100
- */
101
- noMaxWidth?: boolean;
102
- /**
103
- * Whether or not the Bubble should have a tail.
104
- * @default false
105
- */
106
- tail?: boolean;
107
- };
108
-
109
- export { }
1
+ export type BubbleProps = {
2
+ /**
3
+ * The text to render in the bubble.
4
+ */
5
+ children: React.ReactNode;
6
+ /**
7
+ * CSS class(es) to add to the main component wrapper.
8
+ * Bubble is made of a wrapper, a main content, and a footer. This prop
9
+ * allows you to add classes to the main component wrapper.
10
+ */
11
+ className?: string;
12
+ /**
13
+ * CSS class(es) to add to the content wrapper.
14
+ * Bubble is made of a wrapper, a main content, and a footer. This prop
15
+ * allows you to add classes to the content wrapper.
16
+ */
17
+ contentClassName?: string;
18
+ /**
19
+ * Whether or not to show a "copy/paste" icon next to the Bubble.
20
+ * - If a function is passed, it will be called with the text to copy.
21
+ * - If a string is passed, that string will be copied.
22
+ * - If a boolean is passed, the children will be copied, but only if they
23
+ * are of type string.
24
+ */
25
+ copyToClipboard?: boolean | string | ((text: any) => void);
26
+ /**
27
+ * The type of focus for the Copy Button. This will change the color
28
+ * of the focus ring around the Button.
29
+ */
30
+ copyToClipboardFocusMode?: "dark" | "light" | "system" | "alt-system";
31
+ /**
32
+ * The mode of Copy Button. This will change the color of the Button.
33
+ */
34
+ copyToClipboardMode?: "dark" | "light" | "system" | "alt-system";
35
+ /**
36
+ * Object depicting the extra rows for the Bubble.
37
+ * @example
38
+ * ```tsx
39
+ * import { BUBBLE_FOOTER_EMPTY } from "@versini/ui-bubble/constants";
40
+ *
41
+ * <Bubble
42
+ * footer={{
43
+ * "Sent": "12:00 PM",
44
+ * "Delivered": "12:01 PM",
45
+ * "Verified": BUBBLE_FOOTER_EMPTY,
46
+ * "Read": "12:02 PM",
47
+ * }}
48
+ * >Hello World</Bubble>
49
+ * ```
50
+ * This will create a footer with 4 rows, with the row before last being
51
+ * empty but taking the full height of a normal row.
52
+ *
53
+ */
54
+ footer?: {
55
+ [key: string]: string | number | undefined | null;
56
+ };
57
+ /**
58
+ * The gradient intensity applied to the Bubble background.
59
+ * - "light": Subtle gradient with 80% opacity at the top
60
+ * - "medium": Medium gradient with 65% opacity at the top
61
+ * - "strong": Strong gradient with 50% opacity at the top
62
+ * - undefined: No gradient, solid background color
63
+ *
64
+ * @default undefined
65
+ */
66
+ gradient?: "light" | "medium" | "strong";
67
+ /**
68
+ * The type of Bubble. This will change the color of the Bubble
69
+ * as well as the chevron location.
70
+ */
71
+ kind?: "left" | "right";
72
+ /**
73
+ * Same as "footer" but accepts raw JSX.
74
+ */
75
+ rawFooter?: React.ReactNode;
76
+ /**
77
+ * Whether or not the Bubble should have a default max-width.
78
+ * By default, bubble width will be responsive to the viewport,
79
+ * but in some cases, it may be useful to disable this behavior
80
+ * and allow the Bubble to grow to its content.
81
+ * You can also provide your own container class to control the width,
82
+ * based on the container's width.
83
+ * @see https://css-tricks.com/css-container-queries/#aa-container-length-units
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <div> // this div should be declared as a container
88
+ * <Bubble kind="left" noMaxWidth className="max-w-[95qcw]">
89
+ * Hello World
90
+ * </Bubble>
91
+ * </div>
92
+ * ```
93
+ * @default false
94
+ */
95
+ noMaxWidth?: boolean;
96
+ /**
97
+ * Whether or not the Bubble should have a tail.
98
+ * @default false
99
+ */
100
+ tail?: boolean;
101
+ };
@@ -0,0 +1,21 @@
1
+ /*!
2
+ @versini/ui-bubble v9.0.1
3
+ © 2025 gizmette.com
4
+ */
5
+ try {
6
+ if (!window.__VERSINI_UI_BUBBLE__) {
7
+ window.__VERSINI_UI_BUBBLE__ = {
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
+ homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
16
+ }
17
+
18
+
19
+ ;// CONCATENATED MODULE: ./src/components/Bubble/BubbleTypes.ts
20
+
21
+
@@ -0,0 +1,9 @@
1
+ import type { BubbleProps } from "./BubbleTypes";
2
+ type PickedBubbleProps = Pick<BubbleProps, "kind" | "className" | "contentClassName" | "noMaxWidth" | "tail" | "gradient">;
3
+ export declare const getBubbleClasses: ({ kind, className, contentClassName, noMaxWidth, tail, gradient, }: PickedBubbleProps) => {
4
+ wrapper: string;
5
+ main: string;
6
+ footer: string;
7
+ copyButton: string;
8
+ };
9
+ export {};
@@ -0,0 +1,111 @@
1
+ /*!
2
+ @versini/ui-bubble v9.0.1
3
+ © 2025 gizmette.com
4
+ */
5
+ try {
6
+ if (!window.__VERSINI_UI_BUBBLE__) {
7
+ window.__VERSINI_UI_BUBBLE__ = {
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
+ homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
16
+ }
17
+
18
+ import clsx from "clsx";
19
+ import { BUBBLE_CLASSNAME } from "../../common/constants.js";
20
+
21
+ ;// CONCATENATED MODULE: external "clsx"
22
+
23
+ ;// CONCATENATED MODULE: external "../../common/constants.js"
24
+
25
+ ;// CONCATENATED MODULE: ./src/components/Bubble/utilities.ts
26
+
27
+
28
+ const getBubbleSizesClasses = ({ kind, noMaxWidth })=>{
29
+ return clsx("px-4 py-2", {
30
+ "max-w-xs sm:max-w-md md:max-w-2xl": !noMaxWidth,
31
+ "lg:max-w-3xl": kind === "left" && !noMaxWidth
32
+ });
33
+ };
34
+ const getBubbleColorClasses = ({ kind, gradient })=>{
35
+ // No gradient - solid colors
36
+ if (!gradient) {
37
+ return clsx({
38
+ "bg-surface-light dark:bg-surface-dark": kind === "left",
39
+ "bg-surface-accent": kind === "right"
40
+ });
41
+ }
42
+ // Gradient presets based on intensity
43
+ if (gradient === "light") {
44
+ return clsx({
45
+ "bg-gradient-to-b from-surface-light/80 to-surface-light dark:from-surface-dark/80 dark:to-surface-dark": kind === "left",
46
+ "bg-gradient-to-b from-surface-accent/80 to-surface-accent": kind === "right"
47
+ });
48
+ }
49
+ if (gradient === "medium") {
50
+ return clsx({
51
+ "bg-gradient-to-b from-surface-light/65 to-surface-light dark:from-surface-dark/65 dark:to-surface-dark": kind === "left",
52
+ "bg-gradient-to-b from-surface-accent/65 to-surface-accent": kind === "right"
53
+ });
54
+ }
55
+ // gradient === "strong"
56
+ return clsx({
57
+ "bg-gradient-to-b from-surface-light/50 to-surface-light dark:from-surface-dark/50 dark:to-surface-dark": kind === "left",
58
+ "bg-gradient-to-b from-surface-accent/50 to-surface-accent": kind === "right"
59
+ });
60
+ };
61
+ const getBubbleTypographyClasses = ({ kind })=>{
62
+ return clsx("prose prose-dark dark:prose-lighter", "prose-blockquote:my-1", "prose-ol:my-1 prose-ul:my-1", {
63
+ "text-copy-lighter": kind === "right"
64
+ });
65
+ };
66
+ const getBubbleBorderClasses = ({ kind, tail })=>{
67
+ if (tail) {
68
+ return clsx(`${BUBBLE_CLASSNAME}-${kind}-tail`, "rounded-3xl", "relative", "before:content-['']", "before:w-3", "before:h-2", "before:absolute", "before:bottom-0", {
69
+ "last-bubble-right:before:right-[2px] last-bubble-right:before:border-l-[8px] last-bubble-right:before:border-l-surface-accent last-bubble-right:before:rounded-bl-[100%]": kind === "right",
70
+ "last-bubble-left:before:left-[2px] last-bubble-left:before:border-r-[8px] last-bubble-left:before:border-r-surface-light last-bubble-left:dark:before:border-r-surface-dark last-bubble-left:before:rounded-br-[100%]": kind === "left"
71
+ });
72
+ }
73
+ if (!tail) {
74
+ return clsx("rounded-b-xl", {
75
+ "rounded-tr-xl": kind === "left",
76
+ "rounded-tl-xl": kind === "right"
77
+ });
78
+ }
79
+ };
80
+ const getBubbleClasses = ({ kind, className, contentClassName, noMaxWidth, tail, gradient })=>{
81
+ const wrapper = clsx(BUBBLE_CLASSNAME, `${BUBBLE_CLASSNAME}-${kind}`, "flex items-start", {
82
+ "flex-row-reverse": kind === "right"
83
+ }, className);
84
+ const main = clsx(`${BUBBLE_CLASSNAME}-content`, "flex flex-col empty:hidden", getBubbleSizesClasses({
85
+ kind,
86
+ noMaxWidth
87
+ }), getBubbleTypographyClasses({
88
+ kind
89
+ }), getBubbleColorClasses({
90
+ kind,
91
+ gradient
92
+ }), getBubbleBorderClasses({
93
+ kind,
94
+ tail
95
+ }), contentClassName);
96
+ const footer = "pr-2 pt-1 text-end text-xs text-copy-light";
97
+ const copyButton = clsx("flex flex-col-reverse sm:flex-row", {
98
+ "ml-2": kind === "left" && !tail,
99
+ "mr-2": kind === "right" && !tail,
100
+ "ml-1": kind === "left" && tail,
101
+ "mr-1": kind === "right" && tail
102
+ });
103
+ return {
104
+ wrapper,
105
+ main,
106
+ footer,
107
+ copyButton
108
+ };
109
+ };
110
+
111
+ export { getBubbleClasses };
@@ -0,0 +1 @@
1
+ export declare const BUBBLE_FOOTER_EMPTY = "FOOTER_EMPTY";
@@ -0,0 +1,23 @@
1
+ /*!
2
+ @versini/ui-bubble v9.0.1
3
+ © 2025 gizmette.com
4
+ */
5
+ try {
6
+ if (!window.__VERSINI_UI_BUBBLE__) {
7
+ window.__VERSINI_UI_BUBBLE__ = {
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
+ homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
16
+ }
17
+
18
+
19
+ ;// CONCATENATED MODULE: ./src/components/BubbleConstants/BubbleConstants.tsx
20
+ // Side-effect free constants for ui-bubble.
21
+ const BUBBLE_FOOTER_EMPTY = "FOOTER_EMPTY";
22
+
23
+ export { BUBBLE_FOOTER_EMPTY };
@@ -0,0 +1,4 @@
1
+ export * from "../common/constants";
2
+ export * from "./Bubble/Bubble";
3
+ export type * from "./Bubble/BubbleTypes";
4
+ export { BUBBLE_FOOTER_EMPTY } from "./BubbleConstants/BubbleConstants";
@@ -0,0 +1,30 @@
1
+ /*!
2
+ @versini/ui-bubble v9.0.1
3
+ © 2025 gizmette.com
4
+ */
5
+ try {
6
+ if (!window.__VERSINI_UI_BUBBLE__) {
7
+ window.__VERSINI_UI_BUBBLE__ = {
8
+ version: "9.0.1",
9
+ buildTime: "12/22/2025 10:34 AM EST",
10
+ homepage: "https://www.npmjs.com/package/@versini/ui-bubble",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
16
+ }
17
+
18
+ import { BUBBLE_FOOTER_EMPTY } from "./BubbleConstants/BubbleConstants.js";
19
+ export * from "../common/constants.js";
20
+ export * from "./Bubble/Bubble.js";
21
+
22
+ ;// CONCATENATED MODULE: external "./BubbleConstants/BubbleConstants.js"
23
+
24
+ ;// CONCATENATED MODULE: ./src/components/index.ts
25
+
26
+
27
+ // Export constants through a dedicated module entry for better tree-shaking.
28
+
29
+
30
+ export { BUBBLE_FOOTER_EMPTY };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versini/ui-bubble",
3
- "version": "8.0.9",
3
+ "version": "9.0.1",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "publishConfig": {
@@ -12,8 +12,16 @@
12
12
  "url": "git@github.com:aversini/ui-components.git"
13
13
  },
14
14
  "type": "module",
15
- "main": "dist/index.js",
16
- "types": "dist/index.d.ts",
15
+ "exports": {
16
+ "./bubble": {
17
+ "types": "./dist/components/Bubble/Bubble.d.ts",
18
+ "import": "./dist/components/Bubble/Bubble.js"
19
+ },
20
+ "./constants": {
21
+ "types": "./dist/components/BubbleConstants/BubbleConstants.d.ts",
22
+ "import": "./dist/components/BubbleConstants/BubbleConstants.js"
23
+ }
24
+ },
17
25
  "files": [
18
26
  "dist",
19
27
  "README.md"
@@ -50,5 +58,5 @@
50
58
  "sideEffects": [
51
59
  "**/*.css"
52
60
  ],
53
- "gitHead": "30d86d13d4369cc841fc267c970cca423d27bf2f"
61
+ "gitHead": "934b8175b9c5408b0bb8fb5d15a1b198d36be6b9"
54
62
  }