bubble-toolbar 0.1.0 → 1.1.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/CHANGELOG.md +3 -0
- package/README.md +407 -120
- package/dist/index.d.mts +259 -12
- package/dist/index.d.ts +259 -12
- package/dist/index.js +1347 -196
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1352 -188
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +299 -8
- package/package.json +87 -54
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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":["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":"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","names":["forwardRef","jsx","forwardRef","forwardRef","jsx","jsxs","forwardRef","jsx","forwardRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/activity.ts","../src/BubbleGroup.tsx","../src/context.ts","../src/utils/children.ts","../src/utils/styles.ts","../src/BubbleToolbar.tsx","../src/live/BubbleLiveActivity.tsx","../src/components/BubbleIconButton.tsx","../src/utils/tokens.ts","../src/live/useBubbleLiveActivity.ts","../src/live/controller.ts","../src/search/BubbleBreadcrumbSearch.tsx","../src/search/SearchBase.tsx","../src/components/BubbleArea.tsx","../src/search/tokens.ts","../src/search/useBubbleSearch.ts","../src/search/BubbleSearch.tsx"],"sourcesContent":["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 {\n BubbleActivityProps,\n BubbleLiveActivityController,\n BubbleToolbarPosition,\n BubbleToolbarSize,\n BubbleToolbarTheme,\n} 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 /** Toolbar placement; undefined outside a BubbleToolbar. */\n position?: BubbleToolbarPosition;\n /** Live Activity controller of the toolbar, if any. */\n liveActivity?: BubbleLiveActivityController;\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 // Every color reads a token first; fallbacks are the original values.\n let background: string;\n let borderColor: string;\n let color: string;\n\n switch (theme) {\n case 'dark':\n background = blurred\n ? 'var(--bubble-dark-bg, rgba(24, 24, 27, 0.72))'\n : 'var(--bubble-dark-bg-solid, rgba(24, 24, 27, 0.95))';\n borderColor = 'var(--bubble-dark-border, rgba(255, 255, 255, 0.12))';\n color = 'var(--bubble-dark-fg, #f4f4f5)';\n break;\n case 'light':\n background = blurred\n ? 'var(--bubble-light-bg, rgba(255, 255, 255, 0.75))'\n : 'var(--bubble-light-bg-solid, rgba(255, 255, 255, 0.95))';\n borderColor = 'var(--bubble-light-border, rgba(0, 0, 0, 0.08))';\n color = 'var(--bubble-light-fg, #18181b)';\n break;\n case 'auto':\n background = 'var(--bubble-bg, var(--bubble-light-bg, rgba(255, 255, 255, 0.75)))';\n borderColor = 'var(--bubble-border, var(--bubble-light-border, rgba(0, 0, 0, 0.08)))';\n color = 'var(--bubble-fg, var(--bubble-light-fg, #18181b))';\n break;\n default:\n // Neutral luminous frosted glass\n background = blurred\n ? 'var(--bubble-glass-bg, rgba(255, 255, 255, 0.65))'\n : 'var(--bubble-glass-bg-solid, rgba(255, 255, 255, 0.92))';\n borderColor = 'var(--bubble-glass-border, rgba(255, 255, 255, 0.4))';\n color = 'var(--bubble-glass-fg, #09090b)';\n break;\n }\n\n const boxShadow =\n typeof shadow === 'string'\n ? shadow\n : shadow\n ? 'var(--bubble-glass-shadow, 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, useCallback, useMemo, useRef } from 'react';\nimport { BubbleGroup } from './BubbleGroup';\nimport type { BubbleToolbarContextValue } from './context';\nimport { BubbleToolbarContext } from './context';\nimport { LiveSlot } from './live/BubbleLiveActivity';\nimport { BubbleBreadcrumbSearch } from './search/BubbleBreadcrumbSearch';\nimport { BubbleSearch } from './search/BubbleSearch';\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 Search: typeof BubbleSearch;\n BreadcrumbSearch: typeof BubbleBreadcrumbSearch;\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 liveActivity,\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 position,\n liveActivity,\n busy,\n activityColors,\n activityDuration,\n }),\n [\n size,\n theme,\n blurred,\n blurAmount,\n itemGap,\n bordered,\n shadow,\n position,\n liveActivity,\n busy,\n activityColors,\n activityDuration,\n ],\n );\n\n const toolbarRef = useRef<HTMLDivElement | null>(null);\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n toolbarRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref],\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 const content = (\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 </>\n );\n\n return (\n <BubbleToolbarContext.Provider value={contextValue}>\n <div\n ref={setRef}\n role=\"toolbar\"\n aria-label={ariaLabel}\n className={combinedClassName}\n style={containerStyles}\n {...rest}\n >\n {liveActivity ? (\n <LiveSlot controller={liveActivity} toolbarRef={toolbarRef}>\n {content}\n </LiveSlot>\n ) : (\n content\n )}\n </div>\n </BubbleToolbarContext.Provider>\n );\n },\n) as BubbleToolbarComponent;\n\nBubbleToolbar.displayName = 'BubbleToolbar';\nBubbleToolbar.Group = BubbleGroup;\nBubbleToolbar.Search = BubbleSearch;\nBubbleToolbar.BreadcrumbSearch = BubbleBreadcrumbSearch;\n","import type { CSSProperties, ReactNode, RefObject } from 'react';\nimport { useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { BubbleGroup } from '../BubbleGroup';\nimport { BubbleIconButton } from '../components/BubbleIconButton';\nimport { useBubbleToolbar } from '../context';\nimport type { BubbleLiveActivityController, BubbleLiveLabels, BubbleLiveTokens } from '../types';\nimport { resolveSize } from '../utils/styles';\nimport type { TokenMap } from '../utils/tokens';\nimport { createTokenStyle } from '../utils/tokens';\nimport { asInternals } from './useBubbleLiveActivity';\n\nconst LIVE_TOKENS: TokenMap<keyof BubbleLiveTokens> = {\n compactWidth: ['--bubble-live-compact-width', 'px'],\n width: ['--bubble-live-width', 'px'],\n radius: ['--bubble-live-radius', 'px'],\n progressColor: ['--bubble-live-progress-color', ''],\n successColor: ['--bubble-live-success-color', ''],\n errorColor: ['--bubble-live-error-color', ''],\n titleSize: ['--bubble-live-title-size', 'px'],\n metaSize: ['--bubble-live-meta-size', 'px'],\n duration: ['--bubble-live-duration', 'ms'],\n};\n\nexport const liveTokensToStyle = createTokenStyle(LIVE_TOKENS);\n\nexport const defaultLiveLabels: BubbleLiveLabels = {\n pending: 'Working…',\n success: 'Done',\n error: 'Something went wrong',\n close: 'Dismiss',\n group: 'Live activity',\n};\n\n/** Fallback when transitionend never fires (no CSS, hidden tab, jsdom). */\nconst LEAVE_FALLBACK_MS = 650;\nconst MORPH = 'clamp(0ms, var(--bubble-live-duration, 320ms), 600ms) cubic-bezier(0.16, 1, 0.3, 1)';\nconst VISUALLY_HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\nconst svg = (children: ReactNode, className?: string) => (\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n className={className}\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 {children}\n </svg>\n);\n\nconst ICONS = {\n pending: svg(<path d=\"M21 12a9 9 0 1 1-6.22-8.56\" />, 'bubble-live__spinner'),\n success: svg(<polyline points=\"20 6 9 17 4 12\" />),\n error: svg(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </>,\n ),\n neutral: null,\n};\n\nconst prefersReducedMotion = () =>\n typeof window !== 'undefined' &&\n Boolean(window.matchMedia?.('(prefers-reduced-motion: reduce)').matches);\n\ntype Visual = 'idle' | 'enter' | 'live' | 'leave';\n\ninterface LiveSlotProps {\n controller: BubbleLiveActivityController;\n toolbarRef: RefObject<HTMLDivElement | null>;\n children: ReactNode;\n}\n\n/**\n * Keeps the toolbar groups mounted (hidden and inert while live) and morphs a single group\n * from the toolbar width into the compact pill, then the card, and back.\n */\nexport const LiveSlot = ({ controller, toolbarRef, children }: LiveSlotProps) => {\n const live = asInternals(controller);\n const context = useBubbleToolbar();\n const snapshot = useSyncExternalStore(live.subscribe, live.getSnapshot, live.getSnapshot);\n const [visual, setVisual] = useState<Visual>('idle');\n const fromWidth = useRef(0);\n const savedFocus = useRef<HTMLElement | null>(null);\n const groupsRef = useRef<HTMLDivElement>(null);\n const liveRef = useRef<HTMLDivElement>(null);\n const interaction = useRef({ hover: false, focus: false });\n const active = snapshot.state !== 'idle';\n const labels = { ...defaultLiveLabels, ...live.options.labels };\n\n useEffect(() => live.connect(), [live]);\n\n useLayoutEffect(() => {\n if (active && (visual === 'idle' || visual === 'leave')) {\n if (visual === 'idle') {\n const toolbar = toolbarRef.current;\n fromWidth.current = toolbar ? Math.max(0, toolbar.getBoundingClientRect().width - 8) : 0;\n const focused = document.activeElement;\n savedFocus.current =\n focused instanceof HTMLElement && groupsRef.current?.contains(focused) ? focused : null;\n }\n setVisual(prefersReducedMotion() || !fromWidth.current ? 'live' : 'enter');\n } else if (!active && (visual === 'enter' || visual === 'live')) {\n setVisual(prefersReducedMotion() || !fromWidth.current ? 'idle' : 'leave');\n }\n }, [active, visual, toolbarRef]);\n\n useLayoutEffect(() => {\n if (groupsRef.current) {\n groupsRef.current.inert = visual !== 'idle';\n }\n }, [visual]);\n\n // Paint the measured width first, then let the transition shrink it.\n useEffect(() => {\n if (visual !== 'enter') {\n return;\n }\n let second = 0;\n const first = requestAnimationFrame(() => {\n second = requestAnimationFrame(() => setVisual('live'));\n });\n return () => {\n cancelAnimationFrame(first);\n cancelAnimationFrame(second);\n };\n }, [visual]);\n\n useEffect(() => {\n if (visual !== 'leave') {\n return;\n }\n const timer = setTimeout(() => setVisual('idle'), LEAVE_FALLBACK_MS);\n return () => clearTimeout(timer);\n }, [visual]);\n\n useEffect(() => {\n if (visual === 'idle') {\n interaction.current = { hover: false, focus: false };\n if (savedFocus.current?.isConnected) {\n savedFocus.current.focus();\n }\n savedFocus.current = null;\n } else if (savedFocus.current && !liveRef.current?.contains(document.activeElement)) {\n liveRef.current?.focus();\n }\n }, [visual]);\n\n const syncPause = () => {\n const { hover, focus } = interaction.current;\n if (hover || focus) {\n live.pause();\n } else {\n live.resume();\n }\n };\n\n const size = resolveSize(context.size);\n const expanded = snapshot.state === 'expanded' && visual === 'live';\n const { outcome } = snapshot;\n const tone = snapshot.content?.tone ?? (outcome === 'pending' ? 'neutral' : outcome);\n const title =\n snapshot.content?.title ??\n (outcome === 'pending'\n ? labels.pending\n : outcome === 'error'\n ? labels.error\n : outcome === 'success'\n ? labels.success\n : '');\n const description = snapshot.content?.description;\n const icon = snapshot.content?.icon ?? ICONS[outcome === 'pending' ? 'pending' : tone];\n const announcement = active\n ? [title, expanded ? description : ''].filter(Boolean).join('. ')\n : '';\n\n const width =\n visual === 'enter' || visual === 'leave'\n ? `${fromWidth.current}px`\n : snapshot.state === 'expanded'\n ? 'min(var(--bubble-live-width, 360px), calc(100vw - 32px))'\n : 'min(var(--bubble-live-compact-width, 200px), calc(100vw - 32px))';\n\n const groupStyle: CSSProperties = {\n ...liveTokensToStyle(live.options.tokens),\n width,\n minWidth: `${size}px`,\n height: snapshot.state === 'expanded' ? 'auto' : `${size}px`,\n minHeight: `${size}px`,\n padding: 0,\n gap: 0,\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'center',\n position: 'relative',\n overflow: 'hidden',\n borderRadius: snapshot.state === 'expanded' ? 'var(--bubble-live-radius, 24px)' : '9999px',\n transition: `width ${MORPH}, border-radius ${MORPH}`,\n };\n\n return (\n <>\n <div ref={groupsRef} style={{ display: visual === 'idle' ? 'contents' : 'none' }}>\n {children}\n </div>\n {visual === 'idle' ? null : (\n <BubbleGroup\n ref={liveRef}\n className=\"bubble-live\"\n shape=\"pill\"\n busy={snapshot.state === 'compact'}\n aria-label={labels.group}\n data-state={visual === 'leave' ? 'leaving' : snapshot.state}\n data-tone={tone}\n tabIndex={-1}\n style={groupStyle}\n onTransitionEnd={(event) => {\n if (\n visual === 'leave' &&\n event.target === liveRef.current &&\n event.propertyName === 'width'\n ) {\n setVisual('idle');\n }\n }}\n onMouseEnter={() => {\n interaction.current.hover = true;\n syncPause();\n }}\n onMouseLeave={() => {\n interaction.current.hover = false;\n syncPause();\n }}\n onFocus={() => {\n interaction.current.focus = true;\n syncPause();\n }}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n interaction.current.focus = false;\n syncPause();\n }\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape' && snapshot.state === 'expanded') {\n event.preventDefault();\n live.dismiss();\n }\n }}\n >\n {active ? (\n <div\n key={snapshot.id}\n className=\"bubble-live__body\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n minWidth: 0,\n minHeight: `${size - (context.bordered ? 2 : 0)}px`,\n padding: expanded ? '10px 6px 10px 14px' : '0 14px',\n boxSizing: 'border-box',\n }}\n >\n {icon ? (\n <span\n className=\"bubble-live__icon\"\n aria-hidden=\"true\"\n style={{\n display: 'inline-flex',\n flexShrink: 0,\n color:\n tone === 'success'\n ? 'var(--bubble-live-success-color, #22c55e)'\n : tone === 'error'\n ? 'var(--bubble-live-error-color, #ef4444)'\n : 'inherit',\n }}\n >\n {icon}\n </span>\n ) : null}\n <span\n className=\"bubble-live__text\"\n style={{ display: 'flex', flexDirection: 'column', flex: '1 1 auto', minWidth: 0 }}\n >\n <span\n className=\"bubble-live__title\"\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n fontSize: 'clamp(11px, var(--bubble-live-title-size, 13px), 18px)',\n fontWeight: 600,\n }}\n >\n {title}\n </span>\n {expanded && description ? (\n <span\n className=\"bubble-live__description\"\n style={{\n fontSize: 'clamp(9px, var(--bubble-live-meta-size, 11px), 14px)',\n lineHeight: 1.4,\n opacity: 0.75,\n overflowWrap: 'anywhere',\n }}\n >\n {description}\n </span>\n ) : null}\n </span>\n {snapshot.state === 'compact' && snapshot.queued > 0 ? (\n <span\n className=\"bubble-live__queued\"\n style={{ flexShrink: 0, fontSize: 11, opacity: 0.7 }}\n >\n +{snapshot.queued}\n </span>\n ) : null}\n {expanded ? (\n <BubbleIconButton name=\"close\" ariaLabel={labels.close} onClick={live.dismiss} />\n ) : null}\n </div>\n ) : null}\n {expanded && snapshot.duration > 0 ? (\n <span\n key={`progress-${snapshot.id}`}\n className=\"bubble-live__progress\"\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: 2,\n animationDuration: `${snapshot.duration}ms`,\n animationPlayState: snapshot.paused ? 'paused' : 'running',\n }}\n />\n ) : null}\n </BubbleGroup>\n )}\n <span\n role=\"status\"\n aria-live=\"polite\"\n className=\"bubble-live__announcer\"\n style={VISUALLY_HIDDEN}\n >\n {tone === 'error' ? '' : announcement}\n </span>\n <span role=\"alert\" className=\"bubble-live__announcer\" style={VISUALLY_HIDDEN}>\n {tone === 'error' ? announcement : ''}\n </span>\n </>\n );\n};\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 ? 'var(--bubble-button-active-bg, rgba(0, 0, 0, 0.08))'\n : isHovered\n ? 'var(--bubble-button-hover-bg, rgba(0, 0, 0, 0.05))'\n : 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n padding: 0,\n margin: 0,\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","import type { CSSProperties } from 'react';\n\nexport type TokenUnit = 'px' | 'ms' | '';\nexport type TokenMap<K extends string> = Record<K, readonly [cssVar: string, unit: TokenUnit]>;\n\n/**\n * Builds a converter from typed tokens to CSS custom properties.\n * Numbers get the token's unit; unknown, inherited and empty keys are ignored.\n */\nexport const createTokenStyle =\n <K extends string>(map: TokenMap<K>) =>\n (tokens: Partial<Record<K, number | string>> | undefined): CSSProperties => {\n const style: Record<string, string> = {};\n if (!tokens) {\n return style;\n }\n for (const [key, value] of Object.entries(tokens)) {\n if (!Object.hasOwn(map, key) || value === undefined || value === null) {\n continue;\n }\n const [name, unit] = map[key as K];\n style[name] = typeof value === 'number' && unit ? `${value}${unit}` : String(value);\n }\n return style;\n };\n","import { useContext, useState } from 'react';\nimport { BubbleToolbarContext } from '../context';\nimport type { BubbleLiveActivityController, BubbleLiveActivityOptions } from '../types';\nimport type { LiveControllerInternals } from './controller';\nimport { createLiveController } from './controller';\n\n/**\n * Creates a stable Live Activity controller. Pass it to `<BubbleToolbar liveActivity>` and call\n * `run`, `show` or `dismiss` from anywhere. Options are read on every render.\n */\nexport const useBubbleLiveActivity = (\n options: BubbleLiveActivityOptions = {},\n): BubbleLiveActivityController => {\n const [controller] = useState(() => createLiveController(options));\n controller.options = options;\n return controller;\n};\n\n/** Reads the controller of the surrounding BubbleToolbar. */\nexport const useBubbleToolbarLiveActivity = (): BubbleLiveActivityController => {\n const controller = useContext(BubbleToolbarContext).liveActivity;\n if (!controller) {\n throw new Error(\n 'useBubbleToolbarLiveActivity must be used inside a <BubbleToolbar liveActivity={…}>.',\n );\n }\n return controller;\n};\n\nexport const asInternals = (controller: BubbleLiveActivityController) =>\n controller as LiveControllerInternals;\n","import type {\n BubbleLiveActivityController,\n BubbleLiveActivityOptions,\n BubbleLiveContent,\n BubbleLiveRunOptions,\n BubbleLiveState,\n} from '../types';\n\nexport type LiveOutcome = 'pending' | 'success' | 'error' | 'neutral';\n\nexport interface LiveSnapshot {\n state: BubbleLiveState;\n /** Increments for every activity shown, so the UI can restart animations. */\n id: number;\n /** Explicit content; undefined means \"use the label for this outcome\". */\n content?: BubbleLiveContent;\n outcome: LiveOutcome;\n /** Card duration in ms; 0 means until dismissed. */\n duration: number;\n paused: boolean;\n /** Activities waiting after the current one. */\n queued: number;\n}\n\n/** Methods the toolbar needs; not part of the public controller type. */\nexport interface LiveControllerInternals extends BubbleLiveActivityController {\n getSnapshot: () => LiveSnapshot;\n /** Registers a toolbar rendering this controller. Returns the disconnect function. */\n connect: () => () => void;\n pause: () => void;\n resume: () => void;\n options: BubbleLiveActivityOptions;\n}\n\ntype Settled = { ok: true; value: unknown } | { ok: false; error: unknown };\n\ninterface Job {\n options: BubbleLiveRunOptions<unknown>;\n /** Null while the task runs; always set for `show`. */\n settled: Settled | null;\n content?: BubbleLiveContent;\n}\n\nconst IDLE: LiveSnapshot = {\n state: 'idle',\n id: 0,\n outcome: 'neutral',\n duration: 0,\n paused: false,\n queued: 0,\n};\n\nconst isDevelopment = () =>\n (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV !==\n 'production';\n\nexport const createLiveController = (\n initialOptions: BubbleLiveActivityOptions = {},\n): LiveControllerInternals => {\n const listeners = new Set<() => void>();\n const queue: Job[] = [];\n let snapshot = IDLE;\n let current: Job | null = null;\n let connections = 0;\n let warned = false;\n let compactSince = 0;\n let expandTimer: ReturnType<typeof setTimeout> | undefined;\n let closeTimer: ReturnType<typeof setTimeout> | undefined;\n let remaining = 0;\n let closeStartedAt = 0;\n\n const update = (next: Partial<LiveSnapshot>) => {\n snapshot = { ...snapshot, ...next, queued: queue.length };\n for (const listener of listeners) {\n listener();\n }\n };\n\n const clearTimers = () => {\n clearTimeout(expandTimer);\n clearTimeout(closeTimer);\n expandTimer = undefined;\n closeTimer = undefined;\n };\n\n const startCloseTimer = (ms: number) => {\n remaining = ms;\n closeStartedAt = Date.now();\n closeTimer = setTimeout(controller.dismiss, ms);\n };\n\n const expand = (job: Job) => {\n const { settled, options } = job;\n let { content } = job;\n let outcome: LiveOutcome = 'neutral';\n if (settled?.ok && !job.content) {\n outcome = 'success';\n content = options.success?.(settled.value);\n } else if (settled && !settled.ok) {\n outcome = 'error';\n content = options.error?.(settled.error);\n }\n const duration = Math.max(0, options.duration ?? controller.options.duration ?? 4000);\n update({ state: 'expanded', content, outcome, duration, paused: false });\n if (duration > 0) {\n startCloseTimer(duration);\n }\n };\n\n const next = () => {\n clearTimers();\n current = queue.shift() ?? null;\n if (!current) {\n update({ ...IDLE, id: snapshot.id });\n return;\n }\n if (current.settled) {\n update({ id: snapshot.id + 1 });\n expand(current);\n return;\n }\n compactSince = Date.now();\n update({\n state: 'compact',\n id: snapshot.id + 1,\n content: current.options.pending,\n outcome: 'pending',\n duration: 0,\n paused: false,\n });\n };\n\n const enqueue = (job: Job) => {\n queue.push(job);\n if (!current) {\n next();\n } else {\n update({});\n }\n };\n\n const onSettled = (job: Job) => {\n if (job !== current || snapshot.state !== 'compact') {\n return;\n }\n const minPending = controller.options.minPendingMs ?? 600;\n const wait = Math.max(0, minPending - (Date.now() - compactSince));\n expandTimer = setTimeout(() => expand(job), wait);\n };\n\n const controller: LiveControllerInternals = {\n options: initialOptions,\n\n run<T>(task: () => Promise<T> | T, options: BubbleLiveRunOptions<T> = {}) {\n if (connections === 0 && !warned && isDevelopment()) {\n warned = true;\n console.warn(\n 'useBubbleLiveActivity: the controller is not passed to any <BubbleToolbar liveActivity>; activities will not be shown.',\n );\n }\n let promise: Promise<T>;\n try {\n promise = Promise.resolve(task());\n } catch (error) {\n promise = Promise.reject(error);\n }\n const job: Job = { options: options as BubbleLiveRunOptions<unknown>, settled: null };\n void (async () => {\n try {\n job.settled = { ok: true, value: await promise };\n } catch (error) {\n job.settled = { ok: false, error };\n }\n onSettled(job);\n })();\n enqueue(job);\n return promise;\n },\n\n show(content, options = {}) {\n enqueue({ options, settled: { ok: true, value: undefined }, content });\n },\n\n dismiss() {\n if (current) {\n next();\n }\n },\n\n get state() {\n return snapshot.state;\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n\n getSnapshot: () => snapshot,\n\n connect() {\n connections += 1;\n return () => {\n connections -= 1;\n };\n },\n\n pause() {\n if (snapshot.state !== 'expanded' || snapshot.paused || !closeTimer) {\n return;\n }\n clearTimeout(closeTimer);\n closeTimer = undefined;\n remaining = Math.max(0, remaining - (Date.now() - closeStartedAt));\n update({ paused: true });\n },\n\n resume() {\n if (snapshot.state !== 'expanded' || !snapshot.paused) {\n return;\n }\n update({ paused: false });\n startCloseTimer(remaining);\n },\n };\n\n return controller;\n};\n","import type { ReactElement, RefAttributes } from 'react';\nimport { forwardRef } from 'react';\nimport type { BubbleBreadcrumbItem, BubbleBreadcrumbSearchProps, BubbleSearchItem } from '../types';\nimport { defaultSearchLabels, SearchBase } from './SearchBase';\n\nconst BreadcrumbLevel = ({ item, current }: { item: BubbleBreadcrumbItem; current: boolean }) =>\n item.href ? (\n <a href={item.href} aria-current={current ? 'page' : undefined}>\n {item.label}\n </a>\n ) : (\n <span aria-current={current ? 'page' : undefined}>{item.label}</span>\n );\n\nconst Breadcrumb = ({\n items,\n separator,\n label,\n}: {\n items: BubbleBreadcrumbItem[];\n separator: string;\n label: string;\n}) => {\n const parents = items.slice(0, -1);\n const current = items[items.length - 1];\n const divider = (\n <span className=\"bubble-breadcrumb__separator\" aria-hidden=\"true\">\n {` ${separator} `}\n </span>\n );\n\n return (\n <nav\n aria-label={label}\n className=\"bubble-breadcrumb\"\n title={items.map((item) => item.label).join(` ${separator} `)}\n >\n {parents.length > 0 ? (\n <>\n <span className=\"bubble-breadcrumb__parents\">\n {parents.map((item, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: Breadcrumb levels are identified by position.\n <span key={index}>\n <BreadcrumbLevel item={item} current={false} />\n {index < parents.length - 1 ? divider : null}\n </span>\n ))}\n </span>\n {divider}\n </>\n ) : null}\n {current ? (\n <span className=\"bubble-breadcrumb__current\">\n <BreadcrumbLevel item={current} current />\n </span>\n ) : null}\n </nav>\n );\n};\n\nconst BubbleBreadcrumbSearchInner = forwardRef<HTMLDivElement, BubbleBreadcrumbSearchProps>(\n ({ items, separator = '/', labels, ...props }, ref) => {\n const { location = 'Breadcrumb', ...searchLabels } = labels ?? {};\n return (\n <SearchBase\n {...props}\n labels={{ ...defaultSearchLabels, ...searchLabels }}\n idleContent={<Breadcrumb items={items} separator={separator} label={location} />}\n forwardedRef={ref}\n />\n );\n },\n);\n\nBubbleBreadcrumbSearchInner.displayName = 'BubbleBreadcrumbSearch';\n\n/**\n * Shows the current location as a breadcrumb and turns into a search when its button is pressed.\n * The last item is the current page; it stays visible while parents truncate first.\n */\nexport const BubbleBreadcrumbSearch = BubbleBreadcrumbSearchInner as (<T extends BubbleSearchItem>(\n props: BubbleBreadcrumbSearchProps<T> & RefAttributes<HTMLDivElement>,\n) => ReactElement | null) & { displayName?: string };\n","import type {\n CSSProperties,\n ForwardedRef,\n MutableRefObject,\n ReactNode,\n Ref,\n RefObject,\n} from 'react';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { BubbleGroup } from '../BubbleGroup';\nimport { BubbleArea } from '../components/BubbleArea';\nimport { BubbleIconButton } from '../components/BubbleIconButton';\nimport { useBubbleToolbar } from '../context';\nimport type {\n BubbleBreadcrumbSearchTokens,\n BubbleSearchItem,\n BubbleSearchLabels,\n BubbleSearchProps,\n} from '../types';\nimport { resolveSize } from '../utils/styles';\nimport { tokensToStyle } from './tokens';\nimport { useBubbleSearch } from './useBubbleSearch';\n\nexport const defaultSearchLabels: BubbleSearchLabels = {\n group: 'Search',\n button: 'Search',\n input: 'Search',\n listbox: 'Results',\n placeholder: 'Search…',\n searching: 'Searching…',\n noResults: 'No results. Try another term or explore a suggestion.',\n suggestions: 'Suggestions',\n results: (count) => `${count} ${count === 1 ? 'result' : 'results'}`,\n hint: '↑ ↓ to explore · Enter to select · Esc to close',\n};\n\nconst mergeRefs =\n <V,>(...refs: (Ref<V> | undefined)[]) =>\n (value: V | null) => {\n for (const ref of refs) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref) {\n // React 18 types mark RefObject.current as read-only; refs are mutable at runtime.\n (ref as MutableRefObject<V | null>).current = value;\n }\n }\n };\n\ninterface SearchBaseProps<T extends BubbleSearchItem>\n extends Omit<BubbleSearchProps<T>, 'labels' | 'tokens'> {\n labels: BubbleSearchLabels;\n tokens?: BubbleBreadcrumbSearchTokens;\n /** Content shown next to the button while closed. Without it, the closed search is a circle. */\n idleContent?: ReactNode;\n forwardedRef: ForwardedRef<HTMLDivElement>;\n}\n\ntype SearchBodyProps<T extends BubbleSearchItem> = Omit<\n SearchBaseProps<T>,\n 'open' | 'defaultOpen' | 'onOpenChange' | 'tokens' | 'className' | 'forwardedRef'\n> & {\n open: boolean;\n setOpen: (open: boolean) => void;\n groupRef: RefObject<HTMLDivElement | null>;\n headerHeight: number;\n /** Bottom toolbars open the panel upward, away from the screen edge. */\n upward: boolean;\n};\n\nconst SearchBody = <T extends BubbleSearchItem>({\n open,\n setOpen,\n groupRef,\n headerHeight,\n upward,\n labels,\n idleContent,\n onSearch,\n onSelect,\n onError,\n suggestions,\n debounceMs = 0,\n}: SearchBodyProps<T>) => {\n const search = useBubbleSearch({\n open,\n setOpen,\n groupRef,\n onSearch,\n onSelect,\n onError,\n suggestions,\n debounceMs,\n });\n const { options, activeIndex, listId, hintId } = search;\n const compact = !open && idleContent === undefined;\n\n return (\n <div\n className=\"bubble-search__body\"\n data-placement={upward ? 'top' : 'bottom'}\n style={{ display: 'flex', flexDirection: upward ? 'column-reverse' : 'column', minWidth: 0 }}\n onBlurCapture={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n search.close();\n }\n }}\n >\n <div\n className=\"bubble-search__header\"\n data-compact={compact}\n style={{ height: `${headerHeight}px` }}\n >\n <BubbleIconButton\n ref={search.buttonRef}\n name=\"search\"\n ariaLabel={labels.button}\n aria-expanded={open}\n aria-controls={open ? listId : undefined}\n active={open}\n onKeyDown={(event) => {\n if (event.key === 'Escape' && open) {\n event.preventDefault();\n search.close(true);\n }\n }}\n onClick={() => {\n if (!open) {\n setOpen(true);\n } else {\n search.inputRef.current?.focus();\n }\n }}\n />\n {compact ? null : (\n <BubbleArea minWidth={0} className=\"bubble-search__area\">\n {open ? (\n <input\n ref={search.inputRef}\n className=\"bubble-search__input\"\n type=\"text\"\n role=\"combobox\"\n aria-label={labels.input}\n aria-autocomplete=\"list\"\n aria-expanded={open}\n aria-controls={listId}\n aria-describedby={hintId}\n aria-activedescendant={search.activeDescendant}\n autoComplete=\"off\"\n placeholder={labels.placeholder}\n value={search.query}\n onChange={(event) => search.changeQuery(event.target.value)}\n onKeyDown={search.handleInputKeyDown}\n />\n ) : (\n idleContent\n )}\n </BubbleArea>\n )}\n </div>\n {/* Collapse is inline so it works without styles.css and cannot be overridden. */}\n <div\n className=\"bubble-search__expansion\"\n data-open={open}\n aria-hidden={!open}\n style={{\n display: 'grid',\n gridTemplateRows: open ? '1fr' : '0fr',\n visibility: open ? 'visible' : 'hidden',\n opacity: open ? 1 : 0,\n }}\n >\n <div\n className=\"bubble-search__expansion-inner\"\n style={{ minHeight: 0, overflow: 'hidden' }}\n >\n <div className=\"bubble-search__panel\">\n <div className=\"bubble-search__status\" role=\"status\" aria-live=\"polite\">\n {search.pending\n ? labels.searching\n : search.noResults\n ? labels.noResults\n : search.normalizedQuery\n ? labels.results(options.length)\n : labels.suggestions}\n </div>\n <div\n id={listId}\n role=\"listbox\"\n aria-label={labels.listbox}\n className=\"bubble-search__results\"\n >\n {options.map((item, index) => (\n <div\n key={item.id}\n id={search.optionId(index)}\n role=\"option\"\n tabIndex={-1}\n aria-selected={activeIndex === index}\n className=\"bubble-search__option\"\n onPointerDown={(event) => event.preventDefault()}\n onMouseMove={() => search.setActiveIndex(index)}\n onClick={() => search.select(item)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n search.select(item);\n }\n }}\n >\n <span className=\"bubble-search__option-title\">{item.title}</span>\n {item.description ? (\n <span className=\"bubble-search__option-description\">{item.description}</span>\n ) : null}\n </div>\n ))}\n </div>\n <p id={hintId} className=\"bubble-search__hint\">\n {labels.hint}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\n/** Group, open state and structural layout. Only tokens change the look. */\nexport const SearchBase = <T extends BubbleSearchItem>({\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n tokens,\n className = '',\n forwardedRef,\n ...bodyProps\n}: SearchBaseProps<T>) => {\n const context = useBubbleToolbar();\n const groupRef = useRef<HTMLDivElement>(null);\n const [innerOpen, setInnerOpen] = useState(defaultOpen);\n const controlled = openProp !== undefined;\n const open = controlled ? openProp : innerOpen;\n const onOpenChangeRef = useRef(onOpenChange);\n onOpenChangeRef.current = onOpenChange;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!controlled) {\n setInnerOpen(next);\n }\n onOpenChangeRef.current?.(next);\n },\n [controlled],\n );\n\n const ref = useMemo(() => mergeRefs(groupRef, forwardedRef), [forwardedRef]);\n const size = resolveSize(context.size);\n const compact = !open && bodyProps.idleContent === undefined;\n const style: CSSProperties = {\n ...tokensToStyle(tokens),\n height: 'auto',\n width: compact ? `${size}px` : 'min(var(--bubble-search-width, 360px), calc(100vw - 96px))',\n minWidth: 0,\n padding: 0,\n gap: 0,\n flexDirection: 'column',\n alignItems: 'stretch',\n borderRadius: 'var(--bubble-search-radius, 24px)',\n };\n\n return (\n <BubbleGroup\n ref={ref}\n aria-label={bodyProps.labels.group}\n shape=\"pill\"\n className={`bubble-search ${className}`.trim()}\n data-expanded={open}\n data-compact={compact}\n style={style}\n >\n <SearchBody\n {...bodyProps}\n open={open}\n setOpen={setOpen}\n groupRef={groupRef}\n headerHeight={size - (context.bordered ? 2 : 0)}\n upward={context.position === 'bottom'}\n />\n </BubbleGroup>\n );\n};\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 { BubbleBreadcrumbSearchTokens } from '../types';\nimport type { TokenMap } from '../utils/tokens';\nimport { createTokenStyle } from '../utils/tokens';\n\nconst TOKENS: TokenMap<keyof BubbleBreadcrumbSearchTokens> = {\n width: ['--bubble-search-width', 'px'],\n radius: ['--bubble-search-radius', 'px'],\n divider: ['--bubble-search-divider', ''],\n focusRing: ['--bubble-search-focus-ring', ''],\n optionActiveBg: ['--bubble-search-option-active-bg', ''],\n optionRadius: ['--bubble-search-option-radius', 'px'],\n titleSize: ['--bubble-search-title-size', 'px'],\n titleWeight: ['--bubble-search-title-weight', ''],\n metaSize: ['--bubble-search-meta-size', 'px'],\n mutedOpacity: ['--bubble-search-muted-opacity', ''],\n resultsMaxHeight: ['--bubble-search-results-max-height', 'px'],\n panelPadding: ['--bubble-search-panel-padding', 'px'],\n duration: ['--bubble-search-duration', 'ms'],\n easing: ['--bubble-search-easing', ''],\n breadcrumbSize: ['--bubble-breadcrumb-size', 'px'],\n breadcrumbSeparatorColor: ['--bubble-breadcrumb-separator-color', ''],\n breadcrumbCurrentWeight: ['--bubble-breadcrumb-current-weight', ''],\n breadcrumbMutedOpacity: ['--bubble-breadcrumb-muted-opacity', ''],\n};\n\n/** Converts known search tokens to CSS custom properties; unknown keys are ignored. */\nexport const tokensToStyle = createTokenStyle(TOKENS);\n","import type { KeyboardEvent, RefObject } from 'react';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { useBubbleActivity } from '../activity';\nimport type { BubbleSearchItem, BubbleSearchProps } from '../types';\n\nexport const normalizeQuery = (query: string): string => query.trim().toLowerCase();\n\nconst useLatest = <V>(value: V) => {\n const ref = useRef(value);\n ref.current = value;\n return ref;\n};\n\ninterface UseBubbleSearchOptions<T extends BubbleSearchItem>\n extends Pick<BubbleSearchProps<T>, 'onSearch' | 'onSelect' | 'onError' | 'suggestions'> {\n open: boolean;\n setOpen: (open: boolean) => void;\n groupRef: RefObject<HTMLDivElement | null>;\n debounceMs: number;\n}\n\n/** Search state, async lifecycle, keyboard and focus handling shared by the search components. */\nexport function useBubbleSearch<T extends BubbleSearchItem>({\n open,\n setOpen,\n groupRef,\n onSearch,\n onSelect,\n onError,\n suggestions = [],\n debounceMs,\n}: UseBubbleSearchOptions<T>) {\n const { run } = useBubbleActivity();\n const [query, setQuery] = useState('');\n const [result, setResult] = useState<{ query: string; items: T[] } | null>(null);\n const [activeIndex, setActiveIndex] = useState(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const listId = useId();\n const hintId = useId();\n const onSearchRef = useLatest(onSearch);\n const onSelectRef = useLatest(onSelect);\n const onErrorRef = useLatest(onError);\n\n const normalizedQuery = normalizeQuery(query);\n const pending = Boolean(normalizedQuery && result?.query !== normalizedQuery);\n const noResults = Boolean(normalizedQuery && !pending && result?.items.length === 0);\n const options = pending\n ? []\n : normalizedQuery && !noResults\n ? (result?.items ?? [])\n : suggestions;\n const optionId = (index: number) => `${listId}-option-${index}`;\n\n const close = useCallback(\n (restoreFocus = false) => {\n setOpen(false);\n if (restoreFocus) {\n buttonRef.current?.focus();\n }\n },\n [setOpen],\n );\n\n // Closing, from inside or from a controlled `open`, always starts the next search clean.\n useEffect(() => {\n if (open) {\n inputRef.current?.focus();\n } else {\n setQuery('');\n setResult(null);\n setActiveIndex(-1);\n }\n }, [open]);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n const handlePointerDown = (event: PointerEvent) => {\n if (event.target instanceof Node && !groupRef.current?.contains(event.target)) {\n close();\n }\n };\n document.addEventListener('pointerdown', handlePointerDown);\n return () => document.removeEventListener('pointerdown', handlePointerDown);\n }, [open, close, groupRef]);\n\n useEffect(() => {\n if (!open || !normalizedQuery) {\n return;\n }\n const controller = new AbortController();\n const search = async () => {\n try {\n const items = await run(() => onSearchRef.current(normalizedQuery, controller.signal));\n if (!controller.signal.aborted) {\n setResult({ query: normalizedQuery, items });\n }\n } catch (error) {\n if (!controller.signal.aborted) {\n onErrorRef.current?.(error);\n setResult({ query: normalizedQuery, items: [] });\n }\n }\n };\n if (debounceMs > 0) {\n const timer = setTimeout(() => void search(), debounceMs);\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }\n void search();\n return () => controller.abort();\n }, [open, normalizedQuery, run, debounceMs, onSearchRef, onErrorRef]);\n\n useEffect(() => {\n if (activeIndex >= 0) {\n document\n .getElementById(listId)\n ?.children[activeIndex]?.scrollIntoView?.({ block: 'nearest' });\n }\n }, [activeIndex, listId]);\n\n const select = (item: T) => {\n onSelectRef.current(item);\n close(true);\n };\n\n const changeQuery = (value: string) => {\n setQuery(value);\n if (normalizeQuery(value) !== normalizedQuery) {\n setResult(null);\n }\n setActiveIndex(-1);\n };\n\n const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n close(true);\n } else if ((event.key === 'ArrowDown' || event.key === 'ArrowUp') && options.length) {\n event.preventDefault();\n const direction = event.key === 'ArrowDown' ? 1 : -1;\n setActiveIndex((index) =>\n index < 0\n ? direction === 1\n ? 0\n : options.length - 1\n : (index + direction + options.length) % options.length,\n );\n } else if (event.key === 'Enter' && options[activeIndex]) {\n event.preventDefault();\n select(options[activeIndex]);\n }\n };\n\n return {\n query,\n changeQuery,\n normalizedQuery,\n pending,\n noResults,\n options,\n activeIndex,\n setActiveIndex,\n activeDescendant: activeIndex >= 0 && options[activeIndex] ? optionId(activeIndex) : undefined,\n optionId,\n listId,\n hintId,\n inputRef,\n buttonRef,\n close,\n select,\n handleInputKeyDown,\n };\n}\n","import type { ReactElement, RefAttributes } from 'react';\nimport { forwardRef } from 'react';\nimport type { BubbleSearchItem, BubbleSearchProps } from '../types';\nimport { defaultSearchLabels, SearchBase } from './SearchBase';\n\nconst BubbleSearchInner = forwardRef<HTMLDivElement, BubbleSearchProps>(\n ({ labels, ...props }, ref) => (\n <SearchBase {...props} labels={{ ...defaultSearchLabels, ...labels }} forwardedRef={ref} />\n ),\n);\n\nBubbleSearchInner.displayName = 'BubbleSearch';\n\n/**\n * Search bubble: a button that expands into a combobox with async results.\n * Use it inside BubbleToolbar. Customize it through `labels` and `tokens`.\n */\nexport const BubbleSearch = BubbleSearchInner as (<T extends BubbleSearchItem>(\n props: BubbleSearchProps<T> & RefAttributes<HTMLDivElement>,\n) => ReactElement | null) & { displayName?: string };\n"],"mappings":"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","names":["createContext","useContext","forwardRef","useCallback","useMemo","useRef","useEffect","useRef","useState","forwardRef","useState","jsx","useContext","useState","next","useState","useContext","Fragment","jsx","jsxs","ICONS","useState","useRef","useEffect","forwardRef","useCallback","useMemo","useRef","useState","forwardRef","jsx","forwardRef","useCallback","useEffect","useRef","useState","useRef","useState","useCallback","useEffect","jsx","jsxs","useRef","useState","useCallback","useMemo","Fragment","jsx","jsxs","forwardRef","forwardRef","jsx","forwardRef","Fragment","jsx","jsxs","forwardRef","useMemo","useRef","useCallback"]}
|
package/dist/styles.css
CHANGED
|
@@ -7,11 +7,26 @@
|
|
|
7
7
|
--bubble-size-md: 48px;
|
|
8
8
|
--bubble-size-lg: 56px;
|
|
9
9
|
--bubble-blur: 16px;
|
|
10
|
+
/* Glass theme */
|
|
10
11
|
--bubble-glass-bg: rgba(255, 255, 255, 0.65);
|
|
11
|
-
--bubble-glass-
|
|
12
|
-
--bubble-glass-
|
|
12
|
+
--bubble-glass-bg-solid: rgba(255, 255, 255, 0.92);
|
|
13
|
+
--bubble-glass-border: rgba(255, 255, 255, 0.4);
|
|
14
|
+
--bubble-glass-fg: #09090b;
|
|
15
|
+
--bubble-glass-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.06);
|
|
16
|
+
/* Light theme */
|
|
17
|
+
--bubble-light-bg: rgba(255, 255, 255, 0.75);
|
|
18
|
+
--bubble-light-bg-solid: rgba(255, 255, 255, 0.95);
|
|
19
|
+
--bubble-light-border: rgba(0, 0, 0, 0.08);
|
|
20
|
+
--bubble-light-fg: #18181b;
|
|
21
|
+
/* Dark theme */
|
|
13
22
|
--bubble-dark-bg: rgba(24, 24, 27, 0.72);
|
|
23
|
+
--bubble-dark-bg-solid: rgba(24, 24, 27, 0.95);
|
|
14
24
|
--bubble-dark-border: rgba(255, 255, 255, 0.12);
|
|
25
|
+
--bubble-dark-fg: #f4f4f5;
|
|
26
|
+
/* Icon buttons */
|
|
27
|
+
--bubble-button-hover-bg: rgba(0, 0, 0, 0.05);
|
|
28
|
+
--bubble-button-active-bg: rgba(0, 0, 0, 0.08);
|
|
29
|
+
--bubble-focus-ring: #3b82f6;
|
|
15
30
|
}
|
|
16
31
|
|
|
17
32
|
/* Toolbar container */
|
|
@@ -57,7 +72,9 @@
|
|
|
57
72
|
box-sizing: border-box;
|
|
58
73
|
display: inline-flex;
|
|
59
74
|
align-items: center;
|
|
60
|
-
transition:
|
|
75
|
+
transition:
|
|
76
|
+
transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
|
|
77
|
+
box-shadow 0.2s ease;
|
|
61
78
|
}
|
|
62
79
|
|
|
63
80
|
.bubble-group:hover {
|
|
@@ -87,7 +104,10 @@
|
|
|
87
104
|
background: transparent;
|
|
88
105
|
cursor: pointer;
|
|
89
106
|
border-radius: 50%;
|
|
90
|
-
transition:
|
|
107
|
+
transition:
|
|
108
|
+
background-color 0.15s ease,
|
|
109
|
+
transform 0.15s ease,
|
|
110
|
+
color 0.15s ease;
|
|
91
111
|
}
|
|
92
112
|
|
|
93
113
|
.bubble-icon-button:hover {
|
|
@@ -99,7 +119,7 @@
|
|
|
99
119
|
}
|
|
100
120
|
|
|
101
121
|
.bubble-icon-button:focus-visible {
|
|
102
|
-
outline: 2px solid #3b82f6;
|
|
122
|
+
outline: 2px solid var(--bubble-focus-ring, #3b82f6);
|
|
103
123
|
outline-offset: 2px;
|
|
104
124
|
}
|
|
105
125
|
|
|
@@ -113,9 +133,9 @@
|
|
|
113
133
|
/* Media Query: Auto Dark Theme */
|
|
114
134
|
@media (prefers-color-scheme: dark) {
|
|
115
135
|
.bubble-toolbar--auto .bubble-group {
|
|
116
|
-
|
|
117
|
-
border
|
|
118
|
-
|
|
136
|
+
--bubble-bg: var(--bubble-dark-bg);
|
|
137
|
+
--bubble-border: var(--bubble-dark-border);
|
|
138
|
+
--bubble-fg: var(--bubble-dark-fg);
|
|
119
139
|
}
|
|
120
140
|
|
|
121
141
|
.bubble-toolbar--auto .bubble-icon-button:hover {
|
|
@@ -123,3 +143,274 @@
|
|
|
123
143
|
}
|
|
124
144
|
}
|
|
125
145
|
|
|
146
|
+
/* Activity rotates the gradient angle, never the bubble or its content. */
|
|
147
|
+
@property --bubble-activity-angle {
|
|
148
|
+
syntax: "<angle>";
|
|
149
|
+
inherits: false;
|
|
150
|
+
initial-value: 0deg;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.bubble-group--busy {
|
|
154
|
+
position: relative;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.bubble-group--busy::before,
|
|
158
|
+
.bubble-group--busy::after {
|
|
159
|
+
content: "";
|
|
160
|
+
position: absolute;
|
|
161
|
+
inset: 0;
|
|
162
|
+
border-radius: inherit;
|
|
163
|
+
pointer-events: none;
|
|
164
|
+
z-index: 1;
|
|
165
|
+
/* A visible static border remains when CSS masking is unsupported. */
|
|
166
|
+
border: 2px solid var(--bubble-activity-color-1, #22d3ee);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.bubble-group--busy::after {
|
|
170
|
+
inset: 1px;
|
|
171
|
+
filter: blur(1.5px);
|
|
172
|
+
opacity: 0.65;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@supports (mask-composite: exclude) or (-webkit-mask-composite: xor) {
|
|
176
|
+
.bubble-group--busy::before,
|
|
177
|
+
.bubble-group--busy::after {
|
|
178
|
+
border: 0;
|
|
179
|
+
padding: 2px;
|
|
180
|
+
background: conic-gradient(
|
|
181
|
+
from var(--bubble-activity-angle),
|
|
182
|
+
var(--bubble-activity-color-1, #22d3ee),
|
|
183
|
+
var(--bubble-activity-color-2, #8b5cf6),
|
|
184
|
+
var(--bubble-activity-color-3, #ec4899),
|
|
185
|
+
var(--bubble-activity-color-1, #22d3ee)
|
|
186
|
+
);
|
|
187
|
+
-webkit-mask:
|
|
188
|
+
linear-gradient(#fff 0 0) content-box,
|
|
189
|
+
linear-gradient(#fff 0 0);
|
|
190
|
+
-webkit-mask-composite: xor;
|
|
191
|
+
mask:
|
|
192
|
+
linear-gradient(#fff 0 0) content-box,
|
|
193
|
+
linear-gradient(#fff 0 0);
|
|
194
|
+
mask-composite: exclude;
|
|
195
|
+
animation: bubble-activity-orbit var(--bubble-activity-duration, 2.4s) linear infinite;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@keyframes bubble-activity-orbit {
|
|
200
|
+
to {
|
|
201
|
+
--bubble-activity-angle: 360deg;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@media (prefers-reduced-motion: reduce) {
|
|
206
|
+
.bubble-group--busy::before,
|
|
207
|
+
.bubble-group--busy::after {
|
|
208
|
+
animation: none;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/*
|
|
213
|
+
* Search & breadcrumb search.
|
|
214
|
+
* Layout is fixed; only the --bubble-search-* / --bubble-breadcrumb-* tokens are meant to change.
|
|
215
|
+
* Risky tokens are clamped so a bad value cannot break the layout.
|
|
216
|
+
*/
|
|
217
|
+
.bubble-group.bubble-search:hover {
|
|
218
|
+
transform: none;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.bubble-search__header {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
gap: 8px;
|
|
225
|
+
padding: 0 5px;
|
|
226
|
+
box-sizing: border-box;
|
|
227
|
+
border-radius: var(--bubble-search-radius, 24px);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.bubble-search__header[data-compact="true"] {
|
|
231
|
+
justify-content: center;
|
|
232
|
+
padding: 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.bubble-search__header:focus-within {
|
|
236
|
+
box-shadow: inset 0 0 0 2px var(--bubble-search-focus-ring, #818cf8);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.bubble-search__header .bubble-icon-button:focus-visible {
|
|
240
|
+
outline: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.bubble-search__area {
|
|
244
|
+
min-width: 0;
|
|
245
|
+
overflow: hidden;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.bubble-search__input {
|
|
249
|
+
width: 100%;
|
|
250
|
+
min-width: 0;
|
|
251
|
+
padding: 4px 0;
|
|
252
|
+
border: none;
|
|
253
|
+
background: transparent;
|
|
254
|
+
color: inherit;
|
|
255
|
+
font: inherit;
|
|
256
|
+
outline: none;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.bubble-search__expansion {
|
|
260
|
+
transition:
|
|
261
|
+
grid-template-rows clamp(0ms, var(--bubble-search-duration, 180ms), 600ms)
|
|
262
|
+
var(--bubble-search-easing, ease),
|
|
263
|
+
opacity clamp(0ms, var(--bubble-search-duration, 180ms), 600ms)
|
|
264
|
+
var(--bubble-search-easing, ease);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.bubble-search__panel {
|
|
268
|
+
padding: clamp(0px, var(--bubble-search-panel-padding, 8px), 16px);
|
|
269
|
+
border-top: 1px solid var(--bubble-search-divider, rgb(128 128 128 / 18%));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.bubble-search__body[data-placement="top"] .bubble-search__panel {
|
|
273
|
+
border-top: none;
|
|
274
|
+
border-bottom: 1px solid var(--bubble-search-divider, rgb(128 128 128 / 18%));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.bubble-search__status,
|
|
278
|
+
.bubble-search__hint {
|
|
279
|
+
padding: 4px 8px;
|
|
280
|
+
margin: 0;
|
|
281
|
+
font-size: clamp(9px, var(--bubble-search-meta-size, 11px), 16px);
|
|
282
|
+
line-height: 1.6;
|
|
283
|
+
opacity: clamp(0.4, var(--bubble-search-muted-opacity, 0.7), 1);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.bubble-search__results {
|
|
287
|
+
max-height: min(var(--bubble-search-results-max-height, 220px), calc(100dvh - 208px));
|
|
288
|
+
overflow-y: auto;
|
|
289
|
+
overscroll-behavior: contain;
|
|
290
|
+
margin: 6px 0;
|
|
291
|
+
padding: 0;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.bubble-search__option {
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-direction: column;
|
|
297
|
+
gap: 4px;
|
|
298
|
+
padding: 10px 12px;
|
|
299
|
+
border-radius: var(--bubble-search-option-radius, 12px);
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.bubble-search__option:hover,
|
|
304
|
+
.bubble-search__option[aria-selected="true"] {
|
|
305
|
+
background: var(--bubble-search-option-active-bg, rgb(129 140 248 / 18%));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.bubble-search__option-title {
|
|
309
|
+
font-size: clamp(10px, var(--bubble-search-title-size, 13px), 20px);
|
|
310
|
+
font-weight: var(--bubble-search-title-weight, 600);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.bubble-search__option-description {
|
|
314
|
+
font-size: clamp(9px, var(--bubble-search-meta-size, 11px), 16px);
|
|
315
|
+
line-height: 1.4;
|
|
316
|
+
opacity: clamp(0.4, var(--bubble-search-muted-opacity, 0.7), 1);
|
|
317
|
+
overflow-wrap: anywhere;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* Breadcrumb: parents shrink first so the current page stays visible. */
|
|
321
|
+
.bubble-breadcrumb {
|
|
322
|
+
display: flex;
|
|
323
|
+
min-width: 0;
|
|
324
|
+
white-space: nowrap;
|
|
325
|
+
font-size: clamp(10px, var(--bubble-breadcrumb-size, 12px), 16px);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.bubble-breadcrumb a {
|
|
329
|
+
color: inherit;
|
|
330
|
+
text-decoration: none;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.bubble-breadcrumb a:hover {
|
|
334
|
+
text-decoration: underline;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.bubble-breadcrumb__parents {
|
|
338
|
+
flex: 0 1000 auto;
|
|
339
|
+
min-width: 0;
|
|
340
|
+
overflow: hidden;
|
|
341
|
+
text-overflow: ellipsis;
|
|
342
|
+
opacity: clamp(0.4, var(--bubble-breadcrumb-muted-opacity, 0.7), 1);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.bubble-breadcrumb__separator {
|
|
346
|
+
flex-shrink: 0;
|
|
347
|
+
white-space: pre;
|
|
348
|
+
color: var(--bubble-breadcrumb-separator-color, currentColor);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.bubble-breadcrumb__current {
|
|
352
|
+
flex: 0 1 auto;
|
|
353
|
+
min-width: 0;
|
|
354
|
+
overflow: hidden;
|
|
355
|
+
text-overflow: ellipsis;
|
|
356
|
+
font-weight: var(--bubble-breadcrumb-current-weight, 500);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@media (prefers-reduced-motion: reduce) {
|
|
360
|
+
.bubble-search__expansion {
|
|
361
|
+
transition: none;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* Live Activity. Structure is inline; this only adds motion and the --bubble-live-* look.
|
|
367
|
+
*/
|
|
368
|
+
.bubble-group.bubble-live:hover {
|
|
369
|
+
transform: none;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.bubble-live:focus-visible {
|
|
373
|
+
outline: 2px solid var(--bubble-focus-ring, #3b82f6);
|
|
374
|
+
outline-offset: 2px;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.bubble-live__body {
|
|
378
|
+
animation: bubble-live-fade-in clamp(0ms, var(--bubble-live-duration, 320ms), 600ms) ease both;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.bubble-live__spinner {
|
|
382
|
+
animation: bubble-live-spin 0.8s linear infinite;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.bubble-live__progress {
|
|
386
|
+
background: var(--bubble-live-progress-color, color-mix(in srgb, currentColor 40%, transparent));
|
|
387
|
+
transform-origin: left center;
|
|
388
|
+
animation-name: bubble-live-progress;
|
|
389
|
+
animation-timing-function: linear;
|
|
390
|
+
animation-fill-mode: forwards;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@keyframes bubble-live-fade-in {
|
|
394
|
+
from {
|
|
395
|
+
opacity: 0;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
@keyframes bubble-live-spin {
|
|
400
|
+
to {
|
|
401
|
+
transform: rotate(360deg);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
@keyframes bubble-live-progress {
|
|
406
|
+
to {
|
|
407
|
+
transform: scaleX(0);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
@media (prefers-reduced-motion: reduce) {
|
|
412
|
+
.bubble-live__body,
|
|
413
|
+
.bubble-live__spinner {
|
|
414
|
+
animation: none;
|
|
415
|
+
}
|
|
416
|
+
}
|