bubble-toolbar 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/BubbleToolbar.tsx","../src/context.ts","../src/BubbleGroup.tsx","../src/utils/children.ts","../src/utils/styles.ts","../src/components/BubbleIconButton.tsx","../src/components/BubbleArea.tsx"],"sourcesContent":["export { BubbleToolbar } from './BubbleToolbar';\nexport type { BubbleToolbarComponent } from './BubbleToolbar';\nexport { BubbleGroup } from './BubbleGroup';\nexport { BubbleIconButton } from './components/BubbleIconButton';\nexport { BubbleArea } from './components/BubbleArea';\nexport { BubbleToolbarContext, useBubbleToolbar } from './context';\nexport { getValidChildren } from './utils/children';\nexport { resolveSize, formatPx, getGlassStyles } from './utils/styles';\n\nexport type {\n BubbleToolbarProps,\n BubbleGroupProps,\n BubbleIconButtonProps,\n BubbleAreaProps,\n BubbleToolbarTheme,\n BubbleToolbarPosition,\n BubbleToolbarSize,\n BubbleShape,\n} from './types';\n\n","import React, { forwardRef, useMemo } from 'react';\nimport type { BubbleToolbarProps } from './types';\nimport { BubbleToolbarContext, BubbleToolbarContextValue } from './context';\nimport { BubbleGroup } from './BubbleGroup';\nimport { formatPx } from './utils/styles';\n\nexport interface BubbleToolbarComponent\n extends React.ForwardRefExoticComponent<\n BubbleToolbarProps & React.RefAttributes<HTMLDivElement>\n > {\n Group: typeof BubbleGroup;\n}\n\nexport const BubbleToolbar = forwardRef<HTMLDivElement, BubbleToolbarProps>(\n (\n {\n groups,\n children,\n position = 'bottom',\n theme = 'glass',\n size = 'md',\n blurred = true,\n blurAmount = 16,\n groupGap = 8,\n itemGap = 8,\n bordered = true,\n shadow = true,\n className = '',\n style,\n ariaLabel = 'Toolbar',\n ...rest\n },\n ref\n ) => {\n const contextValue = useMemo<BubbleToolbarContextValue>(\n () => ({\n size,\n theme,\n blurred,\n blurAmount,\n itemGap,\n bordered,\n shadow,\n }),\n [size, theme, blurred, blurAmount, itemGap, bordered, shadow]\n );\n\n // Compute positioning styles\n const getPositionStyles = (): React.CSSProperties => {\n switch (position) {\n case 'bottom':\n return {\n position: 'fixed',\n bottom: '24px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 1000,\n };\n case 'top':\n return {\n position: 'fixed',\n top: '24px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 1000,\n };\n case 'static':\n return {\n position: 'relative',\n };\n case 'custom':\n default:\n return {};\n }\n };\n\n const containerStyles: React.CSSProperties = {\n ...getPositionStyles(),\n display: 'inline-flex',\n alignItems: 'center',\n gap: formatPx(groupGap),\n maxWidth: 'calc(100vw - 32px)',\n overflowX: 'auto',\n overflowY: 'hidden',\n padding: '4px',\n boxSizing: 'border-box',\n scrollbarWidth: 'none', // Firefox\n msOverflowStyle: 'none', // IE/Edge\n WebkitOverflowScrolling: 'touch',\n pointerEvents: 'auto',\n ...style,\n };\n\n const combinedClassName = [\n 'bubble-toolbar',\n `bubble-toolbar--${position}`,\n `bubble-toolbar--${theme}`,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <BubbleToolbarContext.Provider value={contextValue}>\n <div\n ref={ref}\n role=\"toolbar\"\n aria-label={ariaLabel}\n className={combinedClassName}\n style={containerStyles}\n {...rest}\n >\n {groups && groups.length > 0\n ? groups.map((groupItems, index) => (\n <BubbleGroup key={index}>\n {groupItems}\n </BubbleGroup>\n ))\n : null}\n {children}\n </div>\n </BubbleToolbarContext.Provider>\n );\n }\n) as BubbleToolbarComponent;\n\nBubbleToolbar.displayName = 'BubbleToolbar';\nBubbleToolbar.Group = BubbleGroup;\n\n","import { createContext, useContext } from 'react';\nimport type { BubbleToolbarTheme, BubbleToolbarSize } from './types';\n\nexport interface BubbleToolbarContextValue {\n size: BubbleToolbarSize;\n theme: BubbleToolbarTheme;\n blurred: boolean;\n blurAmount: number | string;\n itemGap: number | string;\n bordered: boolean;\n shadow: boolean | string;\n}\n\nexport const defaultContextValue: BubbleToolbarContextValue = {\n size: 'md',\n theme: 'glass',\n blurred: true,\n blurAmount: 16,\n itemGap: 8,\n bordered: true,\n shadow: true,\n};\n\nexport const BubbleToolbarContext = createContext<BubbleToolbarContextValue>(defaultContextValue);\n\nexport const useBubbleToolbar = (): BubbleToolbarContextValue => {\n return useContext(BubbleToolbarContext);\n};\n\n","import React, { forwardRef } from 'react';\nimport type { BubbleGroupProps, BubbleShape } from './types';\nimport { useBubbleToolbar } from './context';\nimport { getValidChildren } from './utils/children';\nimport { resolveSize, formatPx, getGlassStyles } from './utils/styles';\n\nexport const BubbleGroup = forwardRef<HTMLDivElement, BubbleGroupProps>(\n (\n {\n children,\n shape: explicitShape,\n size: explicitSize,\n itemGap: explicitItemGap,\n className = '',\n style,\n ...rest\n },\n ref\n ) => {\n const context = useBubbleToolbar();\n\n const validChildren = getValidChildren(children);\n const count = validChildren.length;\n\n // Morphological logic:\n // 1 node => circle\n // > 1 node => pill / rounded rectangle\n const computedShape: BubbleShape =\n explicitShape || (count <= 1 ? 'circle' : 'pill');\n\n const effectiveSize = resolveSize(explicitSize || context.size);\n const effectiveItemGap =\n explicitItemGap !== undefined ? explicitItemGap : context.itemGap;\n\n const glassStyles = getGlassStyles(\n context.theme,\n context.blurred,\n context.blurAmount,\n context.bordered,\n context.shadow\n );\n\n const isCircle = computedShape === 'circle';\n\n const groupStyles: React.CSSProperties = {\n ...glassStyles,\n height: `${effectiveSize}px`,\n boxSizing: 'border-box',\n display: 'inline-flex',\n alignItems: 'center',\n flexShrink: 0,\n userSelect: 'none',\n ...(isCircle\n ? {\n width: `${effectiveSize}px`,\n minWidth: `${effectiveSize}px`,\n borderRadius: '9999px',\n justifyContent: 'center',\n padding: 0,\n }\n : {\n width: 'auto',\n minWidth: `${effectiveSize}px`,\n borderRadius: '9999px',\n flexDirection: 'row',\n justifyContent: 'flex-start',\n paddingLeft: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,\n paddingRight: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,\n gap: formatPx(effectiveItemGap),\n }),\n ...style,\n };\n\n const combinedClassName = [\n 'bubble-group',\n `bubble-group--${computedShape}`,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n ref={ref}\n role=\"group\"\n className={combinedClassName}\n style={groupStyles}\n data-shape={computedShape}\n data-items-count={count}\n {...rest}\n >\n {validChildren}\n </div>\n );\n }\n);\n\nBubbleGroup.displayName = 'BubbleGroup';\n\n","import React, { ReactNode } from 'react';\n\n/**\n * Returns an array of non-null, non-undefined, non-boolean child elements.\n * Unpacks React.Fragment if encountered at the top level.\n */\nexport function getValidChildren(children: ReactNode): ReactNode[] {\n const result: ReactNode[] = [];\n\n React.Children.forEach(children, (child) => {\n if (child === null || child === undefined || typeof child === 'boolean') {\n return;\n }\n\n if (React.isValidElement(child) && child.type === React.Fragment) {\n const fragmentChildren = getValidChildren(\n (child.props as { children?: ReactNode }).children\n );\n result.push(...fragmentChildren);\n } else {\n result.push(child);\n }\n });\n\n return result;\n}\n\n","import type { CSSProperties } from 'react';\nimport type { BubbleToolbarTheme, BubbleToolbarSize } from '../types';\n\nexport function resolveSize(size: BubbleToolbarSize): number {\n if (typeof size === 'number') return size;\n switch (size) {\n case 'sm':\n return 40;\n case 'lg':\n return 56;\n case 'md':\n default:\n return 48;\n }\n}\n\nexport function formatPx(val: number | string): string {\n return typeof val === 'number' ? `${val}px` : val;\n}\n\nexport function getGlassStyles(\n theme: BubbleToolbarTheme,\n blurred: boolean,\n blurAmount: number | string,\n bordered: boolean,\n shadow: boolean | string\n): CSSProperties {\n const blurVal = formatPx(blurAmount);\n\n // Background and border tint based on theme\n let background: string;\n let borderColor: string;\n let color: string;\n\n switch (theme) {\n case 'dark':\n background = blurred ? 'rgba(24, 24, 27, 0.72)' : 'rgba(24, 24, 27, 0.95)';\n borderColor = 'rgba(255, 255, 255, 0.12)';\n color = '#f4f4f5';\n break;\n case 'light':\n background = blurred ? 'rgba(255, 255, 255, 0.75)' : 'rgba(255, 255, 255, 0.95)';\n borderColor = 'rgba(0, 0, 0, 0.08)';\n color = '#18181b';\n break;\n case 'auto':\n background = 'var(--bubble-bg, rgba(255, 255, 255, 0.75))';\n borderColor = 'var(--bubble-border, rgba(0, 0, 0, 0.08))';\n color = 'var(--bubble-fg, #18181b)';\n break;\n case 'glass':\n default:\n // Neutral luminous frosted glass\n background = blurred ? 'rgba(255, 255, 255, 0.65)' : 'rgba(255, 255, 255, 0.92)';\n borderColor = 'rgba(255, 255, 255, 0.4)';\n color = '#09090b';\n break;\n }\n\n const boxShadow =\n typeof shadow === 'string'\n ? shadow\n : shadow\n ? '0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.06)'\n : 'none';\n\n return {\n backgroundColor: background,\n backdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : undefined,\n WebkitBackdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : undefined,\n border: bordered ? `1px solid ${borderColor}` : 'none',\n boxShadow,\n color,\n transition: 'all 0.25s cubic-bezier(0.16, 1, 0.3, 1)',\n };\n}\n\n","import React, { forwardRef, useState } from 'react';\nimport type { BubbleIconButtonProps } from '../types';\n\n/**\n * Standard inline SVG icons for quick prototyping out-of-the-box\n */\nconst ICONS: Record<string, React.ReactNode> = {\n search: (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n ),\n theme: (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"5\" />\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\" />\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\" />\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\" />\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\" />\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\" />\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\" />\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\" />\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\" />\n </svg>\n ),\n chat: (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n ),\n notifications: (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\" />\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\" />\n </svg>\n ),\n logo: (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polygon points=\"12 2 2 7 12 12 22 7 12 2\" />\n <polyline points=\"2 17 12 22 22 17\" />\n <polyline points=\"2 12 12 17 22 12\" />\n </svg>\n ),\n close: (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n ),\n};\n\nexport const BubbleIconButton = forwardRef<HTMLButtonElement, BubbleIconButtonProps>(\n (\n {\n name,\n icon,\n active = false,\n badge,\n tooltip,\n children,\n className = '',\n style,\n onMouseEnter,\n onMouseLeave,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = useState(false);\n\n const iconContent = icon || (name ? ICONS[name] : null) || children;\n const computedAriaLabel = ariaLabel || tooltip || (name ? `${name} button` : 'button');\n\n const buttonStyles: React.CSSProperties = {\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n border: 'none',\n background: active\n ? 'rgba(0, 0, 0, 0.08)'\n : isHovered\n ? 'rgba(0, 0, 0, 0.05)'\n : 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n transition: 'background-color 0.15s ease, transform 0.15s ease',\n transform: isHovered ? 'scale(1.06)' : 'scale(1)',\n flexShrink: 0,\n ...style,\n };\n\n const badgeStyles: React.CSSProperties = {\n position: 'absolute',\n top: '4px',\n right: '4px',\n minWidth: '7px',\n height: '7px',\n padding: typeof badge === 'number' || typeof badge === 'string' ? '1px 3px' : 0,\n borderRadius: '9999px',\n backgroundColor: '#ef4444',\n color: '#ffffff',\n fontSize: '9px',\n fontWeight: 'bold',\n lineHeight: '1',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: '0 0 0 1.5px rgba(255, 255, 255, 0.9)',\n };\n\n return (\n <button\n ref={ref}\n type=\"button\"\n title={tooltip}\n aria-label={computedAriaLabel}\n className={`bubble-icon-button ${active ? 'bubble-icon-button--active' : ''} ${className}`.trim()}\n style={buttonStyles}\n onMouseEnter={(e) => {\n setIsHovered(true);\n onMouseEnter?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHovered(false);\n onMouseLeave?.(e);\n }}\n {...rest}\n >\n {iconContent}\n {badge ? (\n <span className=\"bubble-icon-button__badge\" style={badgeStyles}>\n {typeof badge !== 'boolean' ? badge : null}\n </span>\n ) : null}\n </button>\n );\n }\n);\n\nBubbleIconButton.displayName = 'BubbleIconButton';\n\n","import React, { forwardRef } from 'react';\nimport type { BubbleAreaProps } from '../types';\nimport { formatPx } from '../utils/styles';\n\nexport const BubbleArea = forwardRef<HTMLDivElement, BubbleAreaProps>(\n (\n {\n children,\n minWidth = 120,\n maxWidth,\n className = '',\n style,\n ...rest\n },\n ref\n ) => {\n const areaStyles: React.CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n minWidth: formatPx(minWidth),\n maxWidth: maxWidth ? formatPx(maxWidth) : undefined,\n flex: '1 1 auto',\n fontSize: '14px',\n color: 'inherit',\n ...style,\n };\n\n return (\n <div\n ref={ref}\n className={`bubble-area ${className}`.trim()}\n style={areaStyles}\n {...rest}\n >\n {children}\n </div>\n );\n }\n);\n\nBubbleArea.displayName = 'BubbleArea';\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAA2C;;;ACA3C,mBAA0C;AAanC,IAAM,sBAAiD;AAAA,EAC5D,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AACV;AAEO,IAAM,2BAAuB,4BAAyC,mBAAmB;AAEzF,IAAM,mBAAmB,MAAiC;AAC/D,aAAO,yBAAW,oBAAoB;AACxC;;;AC3BA,IAAAC,gBAAkC;;;ACAlC,IAAAC,gBAAiC;AAM1B,SAAS,iBAAiB,UAAkC;AACjE,QAAM,SAAsB,CAAC;AAE7B,gBAAAC,QAAM,SAAS,QAAQ,UAAU,CAAC,UAAU;AAC1C,QAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,UAAU,WAAW;AACvE;AAAA,IACF;AAEA,QAAI,cAAAA,QAAM,eAAe,KAAK,KAAK,MAAM,SAAS,cAAAA,QAAM,UAAU;AAChE,YAAM,mBAAmB;AAAA,QACtB,MAAM,MAAmC;AAAA,MAC5C;AACA,aAAO,KAAK,GAAG,gBAAgB;AAAA,IACjC,OAAO;AACL,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ACtBO,SAAS,YAAY,MAAiC;AAC3D,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,SAAS,KAA8B;AACrD,SAAO,OAAO,QAAQ,WAAW,GAAG,GAAG,OAAO;AAChD;AAEO,SAAS,eACd,OACA,SACA,YACA,UACA,QACe;AACf,QAAM,UAAU,SAAS,UAAU;AAGnC,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,mBAAa,UAAU,2BAA2B;AAClD,oBAAc;AACd,cAAQ;AACR;AAAA,IACF,KAAK;AACH,mBAAa,UAAU,8BAA8B;AACrD,oBAAc;AACd,cAAQ;AACR;AAAA,IACF,KAAK;AACH,mBAAa;AACb,oBAAc;AACd,cAAQ;AACR;AAAA,IACF,KAAK;AAAA,IACL;AAEE,mBAAa,UAAU,8BAA8B;AACrD,oBAAc;AACd,cAAQ;AACR;AAAA,EACJ;AAEA,QAAM,YACJ,OAAO,WAAW,WACd,SACA,SACA,6EACA;AAEN,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,gBAAgB,UAAU,QAAQ,OAAO,qBAAqB;AAAA,IAC9D,sBAAsB,UAAU,QAAQ,OAAO,qBAAqB;AAAA,IACpE,QAAQ,WAAW,aAAa,WAAW,KAAK;AAAA,IAChD;AAAA,IACA;AAAA,IACA,YAAY;AAAA,EACd;AACF;;;AFOM;AA5EC,IAAM,kBAAc;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,UAAU,iBAAiB;AAEjC,UAAM,gBAAgB,iBAAiB,QAAQ;AAC/C,UAAM,QAAQ,cAAc;AAK5B,UAAM,gBACJ,kBAAkB,SAAS,IAAI,WAAW;AAE5C,UAAM,gBAAgB,YAAY,gBAAgB,QAAQ,IAAI;AAC9D,UAAM,mBACJ,oBAAoB,SAAY,kBAAkB,QAAQ;AAE5D,UAAM,cAAc;AAAA,MAClB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,UAAM,WAAW,kBAAkB;AAEnC,UAAM,cAAmC;AAAA,MACvC,GAAG;AAAA,MACH,QAAQ,GAAG,aAAa;AAAA,MACxB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,GAAI,WACA;AAAA,QACE,OAAO,GAAG,aAAa;AAAA,QACvB,UAAU,GAAG,aAAa;AAAA,QAC1B,cAAc;AAAA,QACd,gBAAgB;AAAA,QAChB,SAAS;AAAA,MACX,IACA;AAAA,QACE,OAAO;AAAA,QACP,UAAU,GAAG,aAAa;AAAA,QAC1B,cAAc;AAAA,QACd,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,aAAa,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,gBAAgB,IAAI,CAAC,CAAC;AAAA,QAC9D,cAAc,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,gBAAgB,IAAI,CAAC,CAAC;AAAA,QAC/D,KAAK,SAAS,gBAAgB;AAAA,MAChC;AAAA,MACJ,GAAG;AAAA,IACL;AAEA,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,iBAAiB,aAAa;AAAA,MAC9B;AAAA,IACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW;AAAA,QACX,OAAO;AAAA,QACP,cAAY;AAAA,QACZ,oBAAkB;AAAA,QACjB,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,YAAY,cAAc;;;AFOlB,IAAAC,sBAAA;AA3FD,IAAM,oBAAgB;AAAA,EAC3B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,IACV,aAAa;AAAA,IACb,WAAW;AAAA,IACX,UAAU;AAAA,IACV,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,IACZ,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,mBAAe;AAAA,MACnB,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,CAAC,MAAM,OAAO,SAAS,YAAY,SAAS,UAAU,MAAM;AAAA,IAC9D;AAGA,UAAM,oBAAoB,MAA2B;AACnD,cAAQ,UAAU;AAAA,QAChB,KAAK;AACH,iBAAO;AAAA,YACL,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,WAAW;AAAA,YACX,QAAQ;AAAA,UACV;AAAA,QACF,KAAK;AACH,iBAAO;AAAA,YACL,UAAU;AAAA,YACV,KAAK;AAAA,YACL,MAAM;AAAA,YACN,WAAW;AAAA,YACX,QAAQ;AAAA,UACV;AAAA,QACF,KAAK;AACH,iBAAO;AAAA,YACL,UAAU;AAAA,UACZ;AAAA,QACF,KAAK;AAAA,QACL;AACE,iBAAO,CAAC;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,kBAAuC;AAAA,MAC3C,GAAG,kBAAkB;AAAA,MACrB,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK,SAAS,QAAQ;AAAA,MACtB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,MACT,WAAW;AAAA,MACX,gBAAgB;AAAA;AAAA,MAChB,iBAAiB;AAAA;AAAA,MACjB,yBAAyB;AAAA,MACzB,eAAe;AAAA,MACf,GAAG;AAAA,IACL;AAEA,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA,mBAAmB,QAAQ;AAAA,MAC3B,mBAAmB,KAAK;AAAA,MACxB;AAAA,IACF,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WACE,6CAAC,qBAAqB,UAArB,EAA8B,OAAO,cACpC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,WAAW;AAAA,QACX,OAAO;AAAA,QACN,GAAG;AAAA,QAEH;AAAA,oBAAU,OAAO,SAAS,IACvB,OAAO,IAAI,CAAC,YAAY,UACtB,6CAAC,eACE,wBADe,KAElB,CACD,IACD;AAAA,UACH;AAAA;AAAA;AAAA,IACH,GACF;AAAA,EAEJ;AACF;AAEA,cAAc,cAAc;AAC5B,cAAc,QAAQ;;;AK/HtB,IAAAC,gBAA4C;AAQxC,IAAAC,sBAAA;AAFJ,IAAM,QAAyC;AAAA,EAC7C,QACE,8CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,iDAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,IAC9B,6CAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,SAAQ,IAAG,SAAQ;AAAA,KAC9C;AAAA,EAEF,OACE,8CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,iDAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,IAC9B,6CAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI;AAAA,IACpC,6CAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA,IACtC,6CAAC,UAAK,IAAG,QAAO,IAAG,QAAO,IAAG,QAAO,IAAG,QAAO;AAAA,IAC9C,6CAAC,UAAK,IAAG,SAAQ,IAAG,SAAQ,IAAG,SAAQ,IAAG,SAAQ;AAAA,IAClD,6CAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK;AAAA,IACpC,6CAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA,IACtC,6CAAC,UAAK,IAAG,QAAO,IAAG,SAAQ,IAAG,QAAO,IAAG,SAAQ;AAAA,IAChD,6CAAC,UAAK,IAAG,SAAQ,IAAG,QAAO,IAAG,SAAQ,IAAG,QAAO;AAAA,KAClD;AAAA,EAEF,MACE,6CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI,uDAAC,UAAK,GAAE,iEAAgE,GAC1E;AAAA,EAEF,eACE,8CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,iDAAC,UAAK,GAAE,+CAA8C;AAAA,IACtD,6CAAC,UAAK,GAAE,8BAA6B;AAAA,KACvC;AAAA,EAEF,MACE,8CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,iDAAC,aAAQ,QAAO,4BAA2B;AAAA,IAC3C,6CAAC,cAAS,QAAO,oBAAmB;AAAA,IACpC,6CAAC,cAAS,QAAO,oBAAmB;AAAA,KACtC;AAAA,EAEF,OACE,8CAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,iDAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,IACpC,6CAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,KACtC;AAEJ;AAEO,IAAM,uBAAmB;AAAA,EAC9B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAEhD,UAAM,cAAc,SAAS,OAAO,MAAM,IAAI,IAAI,SAAS;AAC3D,UAAM,oBAAoB,aAAa,YAAY,OAAO,GAAG,IAAI,YAAY;AAE7E,UAAM,eAAoC;AAAA,MACxC,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY,SACR,wBACA,YACA,wBACA;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,WAAW,YAAY,gBAAgB;AAAA,MACvC,YAAY;AAAA,MACZ,GAAG;AAAA,IACL;AAEA,UAAM,cAAmC;AAAA,MACvC,UAAU;AAAA,MACV,KAAK;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW,YAAY;AAAA,MAC9E,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,WAAW;AAAA,IACb;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,OAAO;AAAA,QACP,cAAY;AAAA,QACZ,WAAW,sBAAsB,SAAS,+BAA+B,EAAE,IAAI,SAAS,GAAG,KAAK;AAAA,QAChG,OAAO;AAAA,QACP,cAAc,CAAC,MAAM;AACnB,uBAAa,IAAI;AACjB,yBAAe,CAAC;AAAA,QAClB;AAAA,QACA,cAAc,CAAC,MAAM;AACnB,uBAAa,KAAK;AAClB,yBAAe,CAAC;AAAA,QAClB;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,QACC,6CAAC,UAAK,WAAU,6BAA4B,OAAO,aAChD,iBAAO,UAAU,YAAY,QAAQ,MACxC,IACE;AAAA;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,iBAAiB,cAAc;;;ACpJ/B,IAAAC,gBAAkC;AA4B5B,IAAAC,sBAAA;AAxBC,IAAM,iBAAa;AAAA,EACxB,CACE;AAAA,IACE;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,aAAkC;AAAA,MACtC,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,UAAU,SAAS,QAAQ;AAAA,MAC3B,UAAU,WAAW,SAAS,QAAQ,IAAI;AAAA,MAC1C,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,MACP,GAAG;AAAA,IACL;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,eAAe,SAAS,GAAG,KAAK;AAAA,QAC3C,OAAO;AAAA,QACN,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,WAAW,cAAc;","names":["import_react","import_react","import_react","React","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/activity.ts","../src/BubbleGroup.tsx","../src/context.ts","../src/utils/children.ts","../src/utils/styles.ts","../src/BubbleToolbar.tsx","../src/components/BubbleArea.tsx","../src/components/BubbleIconButton.tsx"],"sourcesContent":["export type { BubbleActivityValue } from './activity';\nexport { useBubbleActivity } from './activity';\nexport { BubbleGroup } from './BubbleGroup';\nexport type { BubbleToolbarComponent } from './BubbleToolbar';\nexport { BubbleToolbar } from './BubbleToolbar';\nexport { BubbleArea } from './components/BubbleArea';\nexport { BubbleIconButton } from './components/BubbleIconButton';\nexport { BubbleToolbarContext, useBubbleToolbar } from './context';\nexport type {\n BubbleActivityProps,\n BubbleAreaProps,\n BubbleGroupProps,\n BubbleIconButtonProps,\n BubbleShape,\n BubbleToolbarPosition,\n BubbleToolbarProps,\n BubbleToolbarSize,\n BubbleToolbarTheme,\n} from './types';\nexport { getValidChildren } from './utils/children';\nexport { formatPx, getGlassStyles, resolveSize } from './utils/styles';\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nexport interface BubbleActivityValue {\n isBusy: boolean;\n run: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport const BubbleActivityContext = createContext<BubbleActivityValue | null>(null);\n\nexport const useBubbleActivity = (): BubbleActivityValue => {\n const activity = useContext(BubbleActivityContext);\n if (!activity) {\n throw new Error('useBubbleActivity must be used inside a BubbleGroup or BubbleToolbar.Group.');\n }\n return activity;\n};\n\nexport const useGroupActivity = (externalBusy: boolean): BubbleActivityValue => {\n const [pending, setPending] = useState(0);\n const mounted = useRef(true);\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const run = useCallback(async <T>(task: () => Promise<T>): Promise<T> => {\n if (mounted.current) {\n setPending((count) => count + 1);\n }\n try {\n return await task();\n } finally {\n if (mounted.current) {\n setPending((count) => count - 1);\n }\n }\n }, []);\n\n const isBusy = externalBusy || pending > 0;\n return useMemo(() => ({ isBusy, run }), [isBusy, run]);\n};\n","import type { CSSProperties } from 'react';\nimport { forwardRef } from 'react';\nimport { BubbleActivityContext, useGroupActivity } from './activity';\nimport { useBubbleToolbar } from './context';\nimport type { BubbleGroupProps, BubbleShape } from './types';\nimport { getValidChildren } from './utils/children';\nimport { formatPx, getGlassStyles, resolveSize } from './utils/styles';\n\nexport const BubbleGroup = forwardRef<HTMLDivElement, BubbleGroupProps>(\n (\n {\n children,\n shape: explicitShape,\n size: explicitSize,\n itemGap: explicitItemGap,\n busy = false,\n activityColors,\n activityDuration,\n className = '',\n style,\n ...rest\n },\n ref,\n ) => {\n const context = useBubbleToolbar();\n const activity = useGroupActivity(Boolean(context.busy || busy));\n const colors = activityColors ?? context.activityColors ?? ['#22d3ee', '#8b5cf6', '#ec4899'];\n const duration = activityDuration ?? context.activityDuration ?? 2.4;\n\n const validChildren = getValidChildren(children);\n const count = validChildren.length;\n\n // Morphological logic:\n // 1 node => circle\n // > 1 node => pill / rounded rectangle\n const computedShape: BubbleShape = explicitShape || (count <= 1 ? 'circle' : 'pill');\n\n const effectiveSize = resolveSize(explicitSize || context.size);\n const effectiveItemGap = explicitItemGap !== undefined ? explicitItemGap : context.itemGap;\n\n const glassStyles = getGlassStyles(\n context.theme,\n context.blurred,\n context.blurAmount,\n context.bordered,\n context.shadow,\n );\n\n const isCircle = computedShape === 'circle';\n\n const groupStyles: CSSProperties & Record<`--bubble-activity-${string}`, string> = {\n '--bubble-activity-color-1': colors[0],\n '--bubble-activity-color-2': colors[1],\n '--bubble-activity-color-3': colors[2],\n '--bubble-activity-duration': `${Number.isFinite(duration) && duration > 0 ? duration : 2.4}s`,\n ...glassStyles,\n height: `${effectiveSize}px`,\n boxSizing: 'border-box',\n display: 'inline-flex',\n alignItems: 'center',\n flexShrink: 0,\n userSelect: 'none',\n ...(isCircle\n ? {\n width: `${effectiveSize}px`,\n minWidth: `${effectiveSize}px`,\n borderRadius: '9999px',\n justifyContent: 'center',\n padding: 0,\n }\n : {\n width: 'auto',\n minWidth: `${effectiveSize}px`,\n borderRadius: '9999px',\n flexDirection: 'row',\n justifyContent: 'flex-start',\n paddingLeft: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,\n paddingRight: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,\n gap: formatPx(effectiveItemGap),\n }),\n ...style,\n };\n\n const combinedClassName = [\n 'bubble-group',\n `bubble-group--${computedShape}`,\n activity.isBusy && 'bubble-group--busy',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <BubbleActivityContext.Provider value={activity}>\n {/* biome-ignore lint/a11y/useSemanticElements: This toolbar group is not a form fieldset and exposes an HTMLDivElement ref. */}\n <div\n ref={ref}\n role=\"group\"\n className={combinedClassName}\n style={groupStyles}\n data-shape={computedShape}\n data-items-count={count}\n {...rest}\n aria-busy={activity.isBusy}\n >\n {validChildren}\n </div>\n </BubbleActivityContext.Provider>\n );\n },\n);\n\nBubbleGroup.displayName = 'BubbleGroup';\n","import { createContext, useContext } from 'react';\nimport type { BubbleActivityProps, BubbleToolbarSize, BubbleToolbarTheme } from './types';\n\nexport interface BubbleToolbarContextValue extends BubbleActivityProps {\n size: BubbleToolbarSize;\n theme: BubbleToolbarTheme;\n blurred: boolean;\n blurAmount: number | string;\n itemGap: number | string;\n bordered: boolean;\n shadow: boolean | string;\n}\n\nexport const defaultContextValue: BubbleToolbarContextValue = {\n size: 'md',\n theme: 'glass',\n blurred: true,\n blurAmount: 16,\n itemGap: 8,\n bordered: true,\n shadow: true,\n};\n\nexport const BubbleToolbarContext = createContext<BubbleToolbarContextValue>(defaultContextValue);\n\nexport const useBubbleToolbar = (): BubbleToolbarContextValue => {\n return useContext(BubbleToolbarContext);\n};\n","import type { ReactNode } from 'react';\nimport { Children, Fragment, isValidElement } from 'react';\n\n/**\n * Returns an array of non-null, non-undefined, non-boolean child elements.\n * Unpacks Fragment if encountered at the top level.\n */\nexport function getValidChildren(children: ReactNode): ReactNode[] {\n const result: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (child === null || child === undefined || typeof child === 'boolean') {\n return;\n }\n\n if (isValidElement(child) && child.type === Fragment) {\n const fragmentChildren = getValidChildren((child.props as { children?: ReactNode }).children);\n result.push(...fragmentChildren);\n } else {\n result.push(child);\n }\n });\n\n return result;\n}\n","import type { CSSProperties } from 'react';\nimport type { BubbleToolbarSize, BubbleToolbarTheme } from '../types';\n\nexport function resolveSize(size: BubbleToolbarSize): number {\n if (typeof size === 'number') {\n return size;\n }\n switch (size) {\n case 'sm':\n return 40;\n case 'lg':\n return 56;\n default:\n return 48;\n }\n}\n\nexport function formatPx(val: number | string): string {\n return typeof val === 'number' ? `${val}px` : val;\n}\n\nexport function getGlassStyles(\n theme: BubbleToolbarTheme,\n blurred: boolean,\n blurAmount: number | string,\n bordered: boolean,\n shadow: boolean | string,\n): CSSProperties {\n const blurVal = formatPx(blurAmount);\n\n // Background and border tint based on theme\n let background: string;\n let borderColor: string;\n let color: string;\n\n switch (theme) {\n case 'dark':\n background = blurred ? 'rgba(24, 24, 27, 0.72)' : 'rgba(24, 24, 27, 0.95)';\n borderColor = 'rgba(255, 255, 255, 0.12)';\n color = '#f4f4f5';\n break;\n case 'light':\n background = blurred ? 'rgba(255, 255, 255, 0.75)' : 'rgba(255, 255, 255, 0.95)';\n borderColor = 'rgba(0, 0, 0, 0.08)';\n color = '#18181b';\n break;\n case 'auto':\n background = 'var(--bubble-bg, rgba(255, 255, 255, 0.75))';\n borderColor = 'var(--bubble-border, rgba(0, 0, 0, 0.08))';\n color = 'var(--bubble-fg, #18181b)';\n break;\n default:\n // Neutral luminous frosted glass\n background = blurred ? 'rgba(255, 255, 255, 0.65)' : 'rgba(255, 255, 255, 0.92)';\n borderColor = 'rgba(255, 255, 255, 0.4)';\n color = '#09090b';\n break;\n }\n\n const boxShadow =\n typeof shadow === 'string'\n ? shadow\n : shadow\n ? '0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.06)'\n : 'none';\n\n return {\n backgroundColor: background,\n backdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : undefined,\n WebkitBackdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : undefined,\n border: bordered ? `1px solid ${borderColor}` : 'none',\n boxShadow,\n color,\n transition: 'all 0.25s cubic-bezier(0.16, 1, 0.3, 1)',\n };\n}\n","import type { CSSProperties, ForwardRefExoticComponent, RefAttributes } from 'react';\nimport { forwardRef, useMemo } from 'react';\nimport { BubbleGroup } from './BubbleGroup';\nimport type { BubbleToolbarContextValue } from './context';\nimport { BubbleToolbarContext } from './context';\nimport type { BubbleToolbarProps } from './types';\nimport { formatPx } from './utils/styles';\n\nexport interface BubbleToolbarComponent\n extends ForwardRefExoticComponent<BubbleToolbarProps & RefAttributes<HTMLDivElement>> {\n Group: typeof BubbleGroup;\n}\n\nexport const BubbleToolbar = forwardRef<HTMLDivElement, BubbleToolbarProps>(\n (\n {\n groups,\n children,\n position = 'bottom',\n theme = 'glass',\n size = 'md',\n blurred = true,\n blurAmount = 16,\n groupGap = 8,\n itemGap = 8,\n bordered = true,\n shadow = true,\n busy = false,\n activityColors,\n activityDuration,\n className = '',\n style,\n ariaLabel = 'Toolbar',\n ...rest\n },\n ref,\n ) => {\n const contextValue = useMemo<BubbleToolbarContextValue>(\n () => ({\n size,\n theme,\n blurred,\n blurAmount,\n itemGap,\n bordered,\n shadow,\n busy,\n activityColors,\n activityDuration,\n }),\n [\n size,\n theme,\n blurred,\n blurAmount,\n itemGap,\n bordered,\n shadow,\n busy,\n activityColors,\n activityDuration,\n ],\n );\n\n // Compute positioning styles\n const getPositionStyles = (): CSSProperties => {\n switch (position) {\n case 'bottom':\n return {\n position: 'fixed',\n bottom: '24px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 1000,\n };\n case 'top':\n return {\n position: 'fixed',\n top: '24px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: 1000,\n };\n case 'static':\n return {\n position: 'relative',\n };\n default:\n return {};\n }\n };\n\n const containerStyles: CSSProperties = {\n ...getPositionStyles(),\n display: 'inline-flex',\n alignItems: 'center',\n gap: formatPx(groupGap),\n maxWidth: 'calc(100vw - 32px)',\n overflowX: 'auto',\n overflowY: 'hidden',\n padding: '4px',\n boxSizing: 'border-box',\n scrollbarWidth: 'none', // Firefox\n msOverflowStyle: 'none', // IE/Edge\n WebkitOverflowScrolling: 'touch',\n pointerEvents: 'auto',\n ...style,\n };\n\n const combinedClassName = [\n 'bubble-toolbar',\n `bubble-toolbar--${position}`,\n `bubble-toolbar--${theme}`,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <BubbleToolbarContext.Provider value={contextValue}>\n <div\n ref={ref}\n role=\"toolbar\"\n aria-label={ariaLabel}\n className={combinedClassName}\n style={containerStyles}\n {...rest}\n >\n {groups && groups.length > 0\n ? groups.map((groupItems, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: The groups array API identifies groups by position; use compound children for keyed groups.\n <BubbleGroup key={index}>{groupItems}</BubbleGroup>\n ))\n : null}\n {children}\n </div>\n </BubbleToolbarContext.Provider>\n );\n },\n) as BubbleToolbarComponent;\n\nBubbleToolbar.displayName = 'BubbleToolbar';\nBubbleToolbar.Group = BubbleGroup;\n","import type { CSSProperties } from 'react';\nimport { forwardRef } from 'react';\nimport type { BubbleAreaProps } from '../types';\nimport { formatPx } from '../utils/styles';\n\nexport const BubbleArea = forwardRef<HTMLDivElement, BubbleAreaProps>(\n ({ children, minWidth = 120, maxWidth, className = '', style, ...rest }, ref) => {\n const areaStyles: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n minWidth: formatPx(minWidth),\n maxWidth: maxWidth ? formatPx(maxWidth) : undefined,\n flex: '1 1 auto',\n fontSize: '14px',\n color: 'inherit',\n ...style,\n };\n\n return (\n <div ref={ref} className={`bubble-area ${className}`.trim()} style={areaStyles} {...rest}>\n {children}\n </div>\n );\n },\n);\n\nBubbleArea.displayName = 'BubbleArea';\n","import type { CSSProperties, ReactNode } from 'react';\nimport { forwardRef, useState } from 'react';\nimport type { BubbleIconButtonProps } from '../types';\n\n/**\n * Standard inline SVG icons for quick prototyping out-of-the-box\n */\nconst ICONS: Record<string, ReactNode> = {\n search: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n </svg>\n ),\n theme: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"5\" />\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\" />\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\" />\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\" />\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\" />\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\" />\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\" />\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\" />\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\" />\n </svg>\n ),\n chat: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n ),\n notifications: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\" />\n <path d=\"M13.73 21a2 2 0 0 1-3.46 0\" />\n </svg>\n ),\n logo: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polygon points=\"12 2 2 7 12 12 22 7 12 2\" />\n <polyline points=\"2 17 12 22 22 17\" />\n <polyline points=\"2 12 12 17 22 12\" />\n </svg>\n ),\n close: (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n ),\n};\n\nexport const BubbleIconButton = forwardRef<HTMLButtonElement, BubbleIconButtonProps>(\n (\n {\n name,\n icon,\n active = false,\n badge,\n tooltip,\n children,\n className = '',\n style,\n onMouseEnter,\n onMouseLeave,\n ariaLabel,\n ...rest\n },\n ref,\n ) => {\n const [isHovered, setIsHovered] = useState(false);\n\n const iconContent = icon || (name ? ICONS[name] : null) || children;\n const computedAriaLabel = ariaLabel || tooltip || (name ? `${name} button` : 'button');\n\n const buttonStyles: CSSProperties = {\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n border: 'none',\n background: active\n ? 'rgba(0, 0, 0, 0.08)'\n : isHovered\n ? 'rgba(0, 0, 0, 0.05)'\n : 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n padding: 0,\n margin: 0,\n outline: 'none',\n transition: 'background-color 0.15s ease, transform 0.15s ease',\n transform: isHovered ? 'scale(1.06)' : 'scale(1)',\n flexShrink: 0,\n ...style,\n };\n\n const badgeStyles: CSSProperties = {\n position: 'absolute',\n top: '4px',\n right: '4px',\n minWidth: '7px',\n height: '7px',\n padding: typeof badge === 'number' || typeof badge === 'string' ? '1px 3px' : 0,\n borderRadius: '9999px',\n backgroundColor: '#ef4444',\n color: '#ffffff',\n fontSize: '9px',\n fontWeight: 'bold',\n lineHeight: '1',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: '0 0 0 1.5px rgba(255, 255, 255, 0.9)',\n };\n\n return (\n <button\n ref={ref}\n type=\"button\"\n title={tooltip}\n aria-label={computedAriaLabel}\n className={`bubble-icon-button ${active ? 'bubble-icon-button--active' : ''} ${className}`.trim()}\n style={buttonStyles}\n onMouseEnter={(e) => {\n setIsHovered(true);\n onMouseEnter?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHovered(false);\n onMouseLeave?.(e);\n }}\n {...rest}\n >\n {iconContent}\n {badge ? (\n <span className=\"bubble-icon-button__badge\" style={badgeStyles}>\n {typeof badge !== 'boolean' ? badge : null}\n </span>\n ) : null}\n </button>\n );\n },\n);\n\nBubbleIconButton.displayName = 'BubbleIconButton';\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
package/dist/index.mjs CHANGED
@@ -1,8 +1,51 @@
1
- // src/BubbleToolbar.tsx
2
- import { forwardRef as forwardRef2, useMemo } from "react";
1
+ // src/activity.ts
2
+ import {
3
+ createContext,
4
+ useCallback,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+ var BubbleActivityContext = createContext(null);
12
+ var useBubbleActivity = () => {
13
+ const activity = useContext(BubbleActivityContext);
14
+ if (!activity) {
15
+ throw new Error("useBubbleActivity must be used inside a BubbleGroup or BubbleToolbar.Group.");
16
+ }
17
+ return activity;
18
+ };
19
+ var useGroupActivity = (externalBusy) => {
20
+ const [pending, setPending] = useState(0);
21
+ const mounted = useRef(true);
22
+ useEffect(() => {
23
+ mounted.current = true;
24
+ return () => {
25
+ mounted.current = false;
26
+ };
27
+ }, []);
28
+ const run = useCallback(async (task) => {
29
+ if (mounted.current) {
30
+ setPending((count) => count + 1);
31
+ }
32
+ try {
33
+ return await task();
34
+ } finally {
35
+ if (mounted.current) {
36
+ setPending((count) => count - 1);
37
+ }
38
+ }
39
+ }, []);
40
+ const isBusy = externalBusy || pending > 0;
41
+ return useMemo(() => ({ isBusy, run }), [isBusy, run]);
42
+ };
43
+
44
+ // src/BubbleGroup.tsx
45
+ import { forwardRef } from "react";
3
46
 
4
47
  // src/context.ts
5
- import { createContext, useContext } from "react";
48
+ import { createContext as createContext2, useContext as useContext2 } from "react";
6
49
  var defaultContextValue = {
7
50
  size: "md",
8
51
  theme: "glass",
@@ -12,26 +55,21 @@ var defaultContextValue = {
12
55
  bordered: true,
13
56
  shadow: true
14
57
  };
15
- var BubbleToolbarContext = createContext(defaultContextValue);
58
+ var BubbleToolbarContext = createContext2(defaultContextValue);
16
59
  var useBubbleToolbar = () => {
17
- return useContext(BubbleToolbarContext);
60
+ return useContext2(BubbleToolbarContext);
18
61
  };
19
62
 
20
- // src/BubbleGroup.tsx
21
- import { forwardRef } from "react";
22
-
23
63
  // src/utils/children.ts
24
- import React from "react";
64
+ import { Children, Fragment, isValidElement } from "react";
25
65
  function getValidChildren(children) {
26
66
  const result = [];
27
- React.Children.forEach(children, (child) => {
67
+ Children.forEach(children, (child) => {
28
68
  if (child === null || child === void 0 || typeof child === "boolean") {
29
69
  return;
30
70
  }
31
- if (React.isValidElement(child) && child.type === React.Fragment) {
32
- const fragmentChildren = getValidChildren(
33
- child.props.children
34
- );
71
+ if (isValidElement(child) && child.type === Fragment) {
72
+ const fragmentChildren = getValidChildren(child.props.children);
35
73
  result.push(...fragmentChildren);
36
74
  } else {
37
75
  result.push(child);
@@ -42,13 +80,14 @@ function getValidChildren(children) {
42
80
 
43
81
  // src/utils/styles.ts
44
82
  function resolveSize(size) {
45
- if (typeof size === "number") return size;
83
+ if (typeof size === "number") {
84
+ return size;
85
+ }
46
86
  switch (size) {
47
87
  case "sm":
48
88
  return 40;
49
89
  case "lg":
50
90
  return 56;
51
- case "md":
52
91
  default:
53
92
  return 48;
54
93
  }
@@ -77,7 +116,6 @@ function getGlassStyles(theme, blurred, blurAmount, bordered, shadow) {
77
116
  borderColor = "var(--bubble-border, rgba(0, 0, 0, 0.08))";
78
117
  color = "var(--bubble-fg, #18181b)";
79
118
  break;
80
- case "glass":
81
119
  default:
82
120
  background = blurred ? "rgba(255, 255, 255, 0.65)" : "rgba(255, 255, 255, 0.92)";
83
121
  borderColor = "rgba(255, 255, 255, 0.4)";
@@ -104,11 +142,17 @@ var BubbleGroup = forwardRef(
104
142
  shape: explicitShape,
105
143
  size: explicitSize,
106
144
  itemGap: explicitItemGap,
145
+ busy = false,
146
+ activityColors,
147
+ activityDuration,
107
148
  className = "",
108
149
  style,
109
150
  ...rest
110
151
  }, ref) => {
111
152
  const context = useBubbleToolbar();
153
+ const activity = useGroupActivity(Boolean(context.busy || busy));
154
+ const colors = activityColors ?? context.activityColors ?? ["#22d3ee", "#8b5cf6", "#ec4899"];
155
+ const duration = activityDuration ?? context.activityDuration ?? 2.4;
112
156
  const validChildren = getValidChildren(children);
113
157
  const count = validChildren.length;
114
158
  const computedShape = explicitShape || (count <= 1 ? "circle" : "pill");
@@ -123,6 +167,10 @@ var BubbleGroup = forwardRef(
123
167
  );
124
168
  const isCircle = computedShape === "circle";
125
169
  const groupStyles = {
170
+ "--bubble-activity-color-1": colors[0],
171
+ "--bubble-activity-color-2": colors[1],
172
+ "--bubble-activity-color-3": colors[2],
173
+ "--bubble-activity-duration": `${Number.isFinite(duration) && duration > 0 ? duration : 2.4}s`,
126
174
  ...glassStyles,
127
175
  height: `${effectiveSize}px`,
128
176
  boxSizing: "border-box",
@@ -151,9 +199,10 @@ var BubbleGroup = forwardRef(
151
199
  const combinedClassName = [
152
200
  "bubble-group",
153
201
  `bubble-group--${computedShape}`,
202
+ activity.isBusy && "bubble-group--busy",
154
203
  className
155
204
  ].filter(Boolean).join(" ");
156
- return /* @__PURE__ */ jsx(
205
+ return /* @__PURE__ */ jsx(BubbleActivityContext.Provider, { value: activity, children: /* @__PURE__ */ jsx(
157
206
  "div",
158
207
  {
159
208
  ref,
@@ -163,14 +212,16 @@ var BubbleGroup = forwardRef(
163
212
  "data-shape": computedShape,
164
213
  "data-items-count": count,
165
214
  ...rest,
215
+ "aria-busy": activity.isBusy,
166
216
  children: validChildren
167
217
  }
168
- );
218
+ ) });
169
219
  }
170
220
  );
171
221
  BubbleGroup.displayName = "BubbleGroup";
172
222
 
173
223
  // src/BubbleToolbar.tsx
224
+ import { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
174
225
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
175
226
  var BubbleToolbar = forwardRef2(
176
227
  ({
@@ -185,12 +236,15 @@ var BubbleToolbar = forwardRef2(
185
236
  itemGap = 8,
186
237
  bordered = true,
187
238
  shadow = true,
239
+ busy = false,
240
+ activityColors,
241
+ activityDuration,
188
242
  className = "",
189
243
  style,
190
244
  ariaLabel = "Toolbar",
191
245
  ...rest
192
246
  }, ref) => {
193
- const contextValue = useMemo(
247
+ const contextValue = useMemo2(
194
248
  () => ({
195
249
  size,
196
250
  theme,
@@ -198,9 +252,23 @@ var BubbleToolbar = forwardRef2(
198
252
  blurAmount,
199
253
  itemGap,
200
254
  bordered,
201
- shadow
255
+ shadow,
256
+ busy,
257
+ activityColors,
258
+ activityDuration
202
259
  }),
203
- [size, theme, blurred, blurAmount, itemGap, bordered, shadow]
260
+ [
261
+ size,
262
+ theme,
263
+ blurred,
264
+ blurAmount,
265
+ itemGap,
266
+ bordered,
267
+ shadow,
268
+ busy,
269
+ activityColors,
270
+ activityDuration
271
+ ]
204
272
  );
205
273
  const getPositionStyles = () => {
206
274
  switch (position) {
@@ -224,7 +292,6 @@ var BubbleToolbar = forwardRef2(
224
292
  return {
225
293
  position: "relative"
226
294
  };
227
- case "custom":
228
295
  default:
229
296
  return {};
230
297
  }
@@ -263,7 +330,10 @@ var BubbleToolbar = forwardRef2(
263
330
  style: containerStyles,
264
331
  ...rest,
265
332
  children: [
266
- groups && groups.length > 0 ? groups.map((groupItems, index) => /* @__PURE__ */ jsx2(BubbleGroup, { children: groupItems }, index)) : null,
333
+ groups && groups.length > 0 ? groups.map((groupItems, index) => (
334
+ // biome-ignore lint/suspicious/noArrayIndexKey: The groups array API identifies groups by position; use compound children for keyed groups.
335
+ /* @__PURE__ */ jsx2(BubbleGroup, { children: groupItems }, index)
336
+ )) : null,
267
337
  children
268
338
  ]
269
339
  }
@@ -273,41 +343,151 @@ var BubbleToolbar = forwardRef2(
273
343
  BubbleToolbar.displayName = "BubbleToolbar";
274
344
  BubbleToolbar.Group = BubbleGroup;
275
345
 
346
+ // src/components/BubbleArea.tsx
347
+ import { forwardRef as forwardRef3 } from "react";
348
+ import { jsx as jsx3 } from "react/jsx-runtime";
349
+ var BubbleArea = forwardRef3(
350
+ ({ children, minWidth = 120, maxWidth, className = "", style, ...rest }, ref) => {
351
+ const areaStyles = {
352
+ display: "inline-flex",
353
+ alignItems: "center",
354
+ minWidth: formatPx(minWidth),
355
+ maxWidth: maxWidth ? formatPx(maxWidth) : void 0,
356
+ flex: "1 1 auto",
357
+ fontSize: "14px",
358
+ color: "inherit",
359
+ ...style
360
+ };
361
+ return /* @__PURE__ */ jsx3("div", { ref, className: `bubble-area ${className}`.trim(), style: areaStyles, ...rest, children });
362
+ }
363
+ );
364
+ BubbleArea.displayName = "BubbleArea";
365
+
276
366
  // src/components/BubbleIconButton.tsx
277
- import { forwardRef as forwardRef3, useState } from "react";
278
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
367
+ import { forwardRef as forwardRef4, useState as useState2 } from "react";
368
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
279
369
  var ICONS = {
280
- search: /* @__PURE__ */ jsxs2("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
281
- /* @__PURE__ */ jsx3("circle", { cx: "11", cy: "11", r: "8" }),
282
- /* @__PURE__ */ jsx3("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
283
- ] }),
284
- theme: /* @__PURE__ */ jsxs2("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
285
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "5" }),
286
- /* @__PURE__ */ jsx3("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
287
- /* @__PURE__ */ jsx3("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
288
- /* @__PURE__ */ jsx3("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
289
- /* @__PURE__ */ jsx3("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
290
- /* @__PURE__ */ jsx3("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
291
- /* @__PURE__ */ jsx3("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
292
- /* @__PURE__ */ jsx3("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
293
- /* @__PURE__ */ jsx3("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
294
- ] }),
295
- chat: /* @__PURE__ */ jsx3("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx3("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }),
296
- notifications: /* @__PURE__ */ jsxs2("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
297
- /* @__PURE__ */ jsx3("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
298
- /* @__PURE__ */ jsx3("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
299
- ] }),
300
- logo: /* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
301
- /* @__PURE__ */ jsx3("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
302
- /* @__PURE__ */ jsx3("polyline", { points: "2 17 12 22 22 17" }),
303
- /* @__PURE__ */ jsx3("polyline", { points: "2 12 12 17 22 12" })
304
- ] }),
305
- close: /* @__PURE__ */ jsxs2("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
306
- /* @__PURE__ */ jsx3("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
307
- /* @__PURE__ */ jsx3("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
308
- ] })
370
+ search: /* @__PURE__ */ jsxs2(
371
+ "svg",
372
+ {
373
+ "aria-hidden": "true",
374
+ focusable: "false",
375
+ width: "18",
376
+ height: "18",
377
+ viewBox: "0 0 24 24",
378
+ fill: "none",
379
+ stroke: "currentColor",
380
+ strokeWidth: "2",
381
+ strokeLinecap: "round",
382
+ strokeLinejoin: "round",
383
+ children: [
384
+ /* @__PURE__ */ jsx4("circle", { cx: "11", cy: "11", r: "8" }),
385
+ /* @__PURE__ */ jsx4("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
386
+ ]
387
+ }
388
+ ),
389
+ theme: /* @__PURE__ */ jsxs2(
390
+ "svg",
391
+ {
392
+ "aria-hidden": "true",
393
+ focusable: "false",
394
+ width: "18",
395
+ height: "18",
396
+ viewBox: "0 0 24 24",
397
+ fill: "none",
398
+ stroke: "currentColor",
399
+ strokeWidth: "2",
400
+ strokeLinecap: "round",
401
+ strokeLinejoin: "round",
402
+ children: [
403
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "5" }),
404
+ /* @__PURE__ */ jsx4("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
405
+ /* @__PURE__ */ jsx4("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
406
+ /* @__PURE__ */ jsx4("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
407
+ /* @__PURE__ */ jsx4("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
408
+ /* @__PURE__ */ jsx4("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
409
+ /* @__PURE__ */ jsx4("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
410
+ /* @__PURE__ */ jsx4("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
411
+ /* @__PURE__ */ jsx4("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
412
+ ]
413
+ }
414
+ ),
415
+ chat: /* @__PURE__ */ jsx4(
416
+ "svg",
417
+ {
418
+ "aria-hidden": "true",
419
+ focusable: "false",
420
+ width: "18",
421
+ height: "18",
422
+ viewBox: "0 0 24 24",
423
+ fill: "none",
424
+ stroke: "currentColor",
425
+ strokeWidth: "2",
426
+ strokeLinecap: "round",
427
+ strokeLinejoin: "round",
428
+ children: /* @__PURE__ */ jsx4("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
429
+ }
430
+ ),
431
+ notifications: /* @__PURE__ */ jsxs2(
432
+ "svg",
433
+ {
434
+ "aria-hidden": "true",
435
+ focusable: "false",
436
+ width: "18",
437
+ height: "18",
438
+ viewBox: "0 0 24 24",
439
+ fill: "none",
440
+ stroke: "currentColor",
441
+ strokeWidth: "2",
442
+ strokeLinecap: "round",
443
+ strokeLinejoin: "round",
444
+ children: [
445
+ /* @__PURE__ */ jsx4("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
446
+ /* @__PURE__ */ jsx4("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
447
+ ]
448
+ }
449
+ ),
450
+ logo: /* @__PURE__ */ jsxs2(
451
+ "svg",
452
+ {
453
+ "aria-hidden": "true",
454
+ focusable: "false",
455
+ width: "20",
456
+ height: "20",
457
+ viewBox: "0 0 24 24",
458
+ fill: "none",
459
+ stroke: "currentColor",
460
+ strokeWidth: "2",
461
+ strokeLinecap: "round",
462
+ strokeLinejoin: "round",
463
+ children: [
464
+ /* @__PURE__ */ jsx4("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
465
+ /* @__PURE__ */ jsx4("polyline", { points: "2 17 12 22 22 17" }),
466
+ /* @__PURE__ */ jsx4("polyline", { points: "2 12 12 17 22 12" })
467
+ ]
468
+ }
469
+ ),
470
+ close: /* @__PURE__ */ jsxs2(
471
+ "svg",
472
+ {
473
+ "aria-hidden": "true",
474
+ focusable: "false",
475
+ width: "18",
476
+ height: "18",
477
+ viewBox: "0 0 24 24",
478
+ fill: "none",
479
+ stroke: "currentColor",
480
+ strokeWidth: "2",
481
+ strokeLinecap: "round",
482
+ strokeLinejoin: "round",
483
+ children: [
484
+ /* @__PURE__ */ jsx4("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
485
+ /* @__PURE__ */ jsx4("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
486
+ ]
487
+ }
488
+ )
309
489
  };
310
- var BubbleIconButton = forwardRef3(
490
+ var BubbleIconButton = forwardRef4(
311
491
  ({
312
492
  name,
313
493
  icon,
@@ -322,7 +502,7 @@ var BubbleIconButton = forwardRef3(
322
502
  ariaLabel,
323
503
  ...rest
324
504
  }, ref) => {
325
- const [isHovered, setIsHovered] = useState(false);
505
+ const [isHovered, setIsHovered] = useState2(false);
326
506
  const iconContent = icon || (name ? ICONS[name] : null) || children;
327
507
  const computedAriaLabel = ariaLabel || tooltip || (name ? `${name} button` : "button");
328
508
  const buttonStyles = {
@@ -383,49 +563,13 @@ var BubbleIconButton = forwardRef3(
383
563
  ...rest,
384
564
  children: [
385
565
  iconContent,
386
- badge ? /* @__PURE__ */ jsx3("span", { className: "bubble-icon-button__badge", style: badgeStyles, children: typeof badge !== "boolean" ? badge : null }) : null
566
+ badge ? /* @__PURE__ */ jsx4("span", { className: "bubble-icon-button__badge", style: badgeStyles, children: typeof badge !== "boolean" ? badge : null }) : null
387
567
  ]
388
568
  }
389
569
  );
390
570
  }
391
571
  );
392
572
  BubbleIconButton.displayName = "BubbleIconButton";
393
-
394
- // src/components/BubbleArea.tsx
395
- import { forwardRef as forwardRef4 } from "react";
396
- import { jsx as jsx4 } from "react/jsx-runtime";
397
- var BubbleArea = forwardRef4(
398
- ({
399
- children,
400
- minWidth = 120,
401
- maxWidth,
402
- className = "",
403
- style,
404
- ...rest
405
- }, ref) => {
406
- const areaStyles = {
407
- display: "inline-flex",
408
- alignItems: "center",
409
- minWidth: formatPx(minWidth),
410
- maxWidth: maxWidth ? formatPx(maxWidth) : void 0,
411
- flex: "1 1 auto",
412
- fontSize: "14px",
413
- color: "inherit",
414
- ...style
415
- };
416
- return /* @__PURE__ */ jsx4(
417
- "div",
418
- {
419
- ref,
420
- className: `bubble-area ${className}`.trim(),
421
- style: areaStyles,
422
- ...rest,
423
- children
424
- }
425
- );
426
- }
427
- );
428
- BubbleArea.displayName = "BubbleArea";
429
573
  export {
430
574
  BubbleArea,
431
575
  BubbleGroup,
@@ -436,6 +580,7 @@ export {
436
580
  getGlassStyles,
437
581
  getValidChildren,
438
582
  resolveSize,
583
+ useBubbleActivity,
439
584
  useBubbleToolbar
440
585
  };
441
586
  //# sourceMappingURL=index.mjs.map