bubble-toolbar 0.0.0-stage → 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 ADDED
@@ -0,0 +1,615 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BubbleArea: () => BubbleArea,
24
+ BubbleGroup: () => BubbleGroup,
25
+ BubbleIconButton: () => BubbleIconButton,
26
+ BubbleToolbar: () => BubbleToolbar,
27
+ BubbleToolbarContext: () => BubbleToolbarContext,
28
+ formatPx: () => formatPx,
29
+ getGlassStyles: () => getGlassStyles,
30
+ getValidChildren: () => getValidChildren,
31
+ resolveSize: () => resolveSize,
32
+ useBubbleActivity: () => useBubbleActivity,
33
+ useBubbleToolbar: () => useBubbleToolbar
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/activity.ts
38
+ var import_react = require("react");
39
+ var BubbleActivityContext = (0, import_react.createContext)(null);
40
+ var useBubbleActivity = () => {
41
+ const activity = (0, import_react.useContext)(BubbleActivityContext);
42
+ if (!activity) {
43
+ throw new Error("useBubbleActivity must be used inside a BubbleGroup or BubbleToolbar.Group.");
44
+ }
45
+ return activity;
46
+ };
47
+ var useGroupActivity = (externalBusy) => {
48
+ const [pending, setPending] = (0, import_react.useState)(0);
49
+ const mounted = (0, import_react.useRef)(true);
50
+ (0, import_react.useEffect)(() => {
51
+ mounted.current = true;
52
+ return () => {
53
+ mounted.current = false;
54
+ };
55
+ }, []);
56
+ const run = (0, import_react.useCallback)(async (task) => {
57
+ if (mounted.current) {
58
+ setPending((count) => count + 1);
59
+ }
60
+ try {
61
+ return await task();
62
+ } finally {
63
+ if (mounted.current) {
64
+ setPending((count) => count - 1);
65
+ }
66
+ }
67
+ }, []);
68
+ const isBusy = externalBusy || pending > 0;
69
+ return (0, import_react.useMemo)(() => ({ isBusy, run }), [isBusy, run]);
70
+ };
71
+
72
+ // src/BubbleGroup.tsx
73
+ var import_react4 = require("react");
74
+
75
+ // src/context.ts
76
+ var import_react2 = require("react");
77
+ var defaultContextValue = {
78
+ size: "md",
79
+ theme: "glass",
80
+ blurred: true,
81
+ blurAmount: 16,
82
+ itemGap: 8,
83
+ bordered: true,
84
+ shadow: true
85
+ };
86
+ var BubbleToolbarContext = (0, import_react2.createContext)(defaultContextValue);
87
+ var useBubbleToolbar = () => {
88
+ return (0, import_react2.useContext)(BubbleToolbarContext);
89
+ };
90
+
91
+ // src/utils/children.ts
92
+ var import_react3 = require("react");
93
+ function getValidChildren(children) {
94
+ const result = [];
95
+ import_react3.Children.forEach(children, (child) => {
96
+ if (child === null || child === void 0 || typeof child === "boolean") {
97
+ return;
98
+ }
99
+ if ((0, import_react3.isValidElement)(child) && child.type === import_react3.Fragment) {
100
+ const fragmentChildren = getValidChildren(child.props.children);
101
+ result.push(...fragmentChildren);
102
+ } else {
103
+ result.push(child);
104
+ }
105
+ });
106
+ return result;
107
+ }
108
+
109
+ // src/utils/styles.ts
110
+ function resolveSize(size) {
111
+ if (typeof size === "number") {
112
+ return size;
113
+ }
114
+ switch (size) {
115
+ case "sm":
116
+ return 40;
117
+ case "lg":
118
+ return 56;
119
+ default:
120
+ return 48;
121
+ }
122
+ }
123
+ function formatPx(val) {
124
+ return typeof val === "number" ? `${val}px` : val;
125
+ }
126
+ function getGlassStyles(theme, blurred, blurAmount, bordered, shadow) {
127
+ const blurVal = formatPx(blurAmount);
128
+ let background;
129
+ let borderColor;
130
+ let color;
131
+ switch (theme) {
132
+ case "dark":
133
+ background = blurred ? "rgba(24, 24, 27, 0.72)" : "rgba(24, 24, 27, 0.95)";
134
+ borderColor = "rgba(255, 255, 255, 0.12)";
135
+ color = "#f4f4f5";
136
+ break;
137
+ case "light":
138
+ background = blurred ? "rgba(255, 255, 255, 0.75)" : "rgba(255, 255, 255, 0.95)";
139
+ borderColor = "rgba(0, 0, 0, 0.08)";
140
+ color = "#18181b";
141
+ break;
142
+ case "auto":
143
+ background = "var(--bubble-bg, rgba(255, 255, 255, 0.75))";
144
+ borderColor = "var(--bubble-border, rgba(0, 0, 0, 0.08))";
145
+ color = "var(--bubble-fg, #18181b)";
146
+ break;
147
+ default:
148
+ background = blurred ? "rgba(255, 255, 255, 0.65)" : "rgba(255, 255, 255, 0.92)";
149
+ borderColor = "rgba(255, 255, 255, 0.4)";
150
+ color = "#09090b";
151
+ break;
152
+ }
153
+ const boxShadow = typeof shadow === "string" ? shadow : shadow ? "0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.06)" : "none";
154
+ return {
155
+ backgroundColor: background,
156
+ backdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : void 0,
157
+ WebkitBackdropFilter: blurred ? `blur(${blurVal}) saturate(180%)` : void 0,
158
+ border: bordered ? `1px solid ${borderColor}` : "none",
159
+ boxShadow,
160
+ color,
161
+ transition: "all 0.25s cubic-bezier(0.16, 1, 0.3, 1)"
162
+ };
163
+ }
164
+
165
+ // src/BubbleGroup.tsx
166
+ var import_jsx_runtime = require("react/jsx-runtime");
167
+ var BubbleGroup = (0, import_react4.forwardRef)(
168
+ ({
169
+ children,
170
+ shape: explicitShape,
171
+ size: explicitSize,
172
+ itemGap: explicitItemGap,
173
+ busy = false,
174
+ activityColors,
175
+ activityDuration,
176
+ className = "",
177
+ style,
178
+ ...rest
179
+ }, ref) => {
180
+ const context = useBubbleToolbar();
181
+ const activity = useGroupActivity(Boolean(context.busy || busy));
182
+ const colors = activityColors ?? context.activityColors ?? ["#22d3ee", "#8b5cf6", "#ec4899"];
183
+ const duration = activityDuration ?? context.activityDuration ?? 2.4;
184
+ const validChildren = getValidChildren(children);
185
+ const count = validChildren.length;
186
+ const computedShape = explicitShape || (count <= 1 ? "circle" : "pill");
187
+ const effectiveSize = resolveSize(explicitSize || context.size);
188
+ const effectiveItemGap = explicitItemGap !== void 0 ? explicitItemGap : context.itemGap;
189
+ const glassStyles = getGlassStyles(
190
+ context.theme,
191
+ context.blurred,
192
+ context.blurAmount,
193
+ context.bordered,
194
+ context.shadow
195
+ );
196
+ const isCircle = computedShape === "circle";
197
+ const groupStyles = {
198
+ "--bubble-activity-color-1": colors[0],
199
+ "--bubble-activity-color-2": colors[1],
200
+ "--bubble-activity-color-3": colors[2],
201
+ "--bubble-activity-duration": `${Number.isFinite(duration) && duration > 0 ? duration : 2.4}s`,
202
+ ...glassStyles,
203
+ height: `${effectiveSize}px`,
204
+ boxSizing: "border-box",
205
+ display: "inline-flex",
206
+ alignItems: "center",
207
+ flexShrink: 0,
208
+ userSelect: "none",
209
+ ...isCircle ? {
210
+ width: `${effectiveSize}px`,
211
+ minWidth: `${effectiveSize}px`,
212
+ borderRadius: "9999px",
213
+ justifyContent: "center",
214
+ padding: 0
215
+ } : {
216
+ width: "auto",
217
+ minWidth: `${effectiveSize}px`,
218
+ borderRadius: "9999px",
219
+ flexDirection: "row",
220
+ justifyContent: "flex-start",
221
+ paddingLeft: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,
222
+ paddingRight: `${Math.max(12, Math.round(effectiveSize * 0.28))}px`,
223
+ gap: formatPx(effectiveItemGap)
224
+ },
225
+ ...style
226
+ };
227
+ const combinedClassName = [
228
+ "bubble-group",
229
+ `bubble-group--${computedShape}`,
230
+ activity.isBusy && "bubble-group--busy",
231
+ className
232
+ ].filter(Boolean).join(" ");
233
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BubbleActivityContext.Provider, { value: activity, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
234
+ "div",
235
+ {
236
+ ref,
237
+ role: "group",
238
+ className: combinedClassName,
239
+ style: groupStyles,
240
+ "data-shape": computedShape,
241
+ "data-items-count": count,
242
+ ...rest,
243
+ "aria-busy": activity.isBusy,
244
+ children: validChildren
245
+ }
246
+ ) });
247
+ }
248
+ );
249
+ BubbleGroup.displayName = "BubbleGroup";
250
+
251
+ // src/BubbleToolbar.tsx
252
+ var import_react5 = require("react");
253
+ var import_jsx_runtime2 = require("react/jsx-runtime");
254
+ var BubbleToolbar = (0, import_react5.forwardRef)(
255
+ ({
256
+ groups,
257
+ children,
258
+ position = "bottom",
259
+ theme = "glass",
260
+ size = "md",
261
+ blurred = true,
262
+ blurAmount = 16,
263
+ groupGap = 8,
264
+ itemGap = 8,
265
+ bordered = true,
266
+ shadow = true,
267
+ busy = false,
268
+ activityColors,
269
+ activityDuration,
270
+ className = "",
271
+ style,
272
+ ariaLabel = "Toolbar",
273
+ ...rest
274
+ }, ref) => {
275
+ const contextValue = (0, import_react5.useMemo)(
276
+ () => ({
277
+ size,
278
+ theme,
279
+ blurred,
280
+ blurAmount,
281
+ itemGap,
282
+ bordered,
283
+ shadow,
284
+ busy,
285
+ activityColors,
286
+ activityDuration
287
+ }),
288
+ [
289
+ size,
290
+ theme,
291
+ blurred,
292
+ blurAmount,
293
+ itemGap,
294
+ bordered,
295
+ shadow,
296
+ busy,
297
+ activityColors,
298
+ activityDuration
299
+ ]
300
+ );
301
+ const getPositionStyles = () => {
302
+ switch (position) {
303
+ case "bottom":
304
+ return {
305
+ position: "fixed",
306
+ bottom: "24px",
307
+ left: "50%",
308
+ transform: "translateX(-50%)",
309
+ zIndex: 1e3
310
+ };
311
+ case "top":
312
+ return {
313
+ position: "fixed",
314
+ top: "24px",
315
+ left: "50%",
316
+ transform: "translateX(-50%)",
317
+ zIndex: 1e3
318
+ };
319
+ case "static":
320
+ return {
321
+ position: "relative"
322
+ };
323
+ default:
324
+ return {};
325
+ }
326
+ };
327
+ const containerStyles = {
328
+ ...getPositionStyles(),
329
+ display: "inline-flex",
330
+ alignItems: "center",
331
+ gap: formatPx(groupGap),
332
+ maxWidth: "calc(100vw - 32px)",
333
+ overflowX: "auto",
334
+ overflowY: "hidden",
335
+ padding: "4px",
336
+ boxSizing: "border-box",
337
+ scrollbarWidth: "none",
338
+ // Firefox
339
+ msOverflowStyle: "none",
340
+ // IE/Edge
341
+ WebkitOverflowScrolling: "touch",
342
+ pointerEvents: "auto",
343
+ ...style
344
+ };
345
+ const combinedClassName = [
346
+ "bubble-toolbar",
347
+ `bubble-toolbar--${position}`,
348
+ `bubble-toolbar--${theme}`,
349
+ className
350
+ ].filter(Boolean).join(" ");
351
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BubbleToolbarContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
352
+ "div",
353
+ {
354
+ ref,
355
+ role: "toolbar",
356
+ "aria-label": ariaLabel,
357
+ className: combinedClassName,
358
+ style: containerStyles,
359
+ ...rest,
360
+ children: [
361
+ groups && groups.length > 0 ? groups.map((groupItems, index) => (
362
+ // biome-ignore lint/suspicious/noArrayIndexKey: The groups array API identifies groups by position; use compound children for keyed groups.
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BubbleGroup, { children: groupItems }, index)
364
+ )) : null,
365
+ children
366
+ ]
367
+ }
368
+ ) });
369
+ }
370
+ );
371
+ BubbleToolbar.displayName = "BubbleToolbar";
372
+ BubbleToolbar.Group = BubbleGroup;
373
+
374
+ // src/components/BubbleArea.tsx
375
+ var import_react6 = require("react");
376
+ var import_jsx_runtime3 = require("react/jsx-runtime");
377
+ var BubbleArea = (0, import_react6.forwardRef)(
378
+ ({ children, minWidth = 120, maxWidth, className = "", style, ...rest }, ref) => {
379
+ const areaStyles = {
380
+ display: "inline-flex",
381
+ alignItems: "center",
382
+ minWidth: formatPx(minWidth),
383
+ maxWidth: maxWidth ? formatPx(maxWidth) : void 0,
384
+ flex: "1 1 auto",
385
+ fontSize: "14px",
386
+ color: "inherit",
387
+ ...style
388
+ };
389
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref, className: `bubble-area ${className}`.trim(), style: areaStyles, ...rest, children });
390
+ }
391
+ );
392
+ BubbleArea.displayName = "BubbleArea";
393
+
394
+ // src/components/BubbleIconButton.tsx
395
+ var import_react7 = require("react");
396
+ var import_jsx_runtime4 = require("react/jsx-runtime");
397
+ var ICONS = {
398
+ search: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
399
+ "svg",
400
+ {
401
+ "aria-hidden": "true",
402
+ focusable: "false",
403
+ width: "18",
404
+ height: "18",
405
+ viewBox: "0 0 24 24",
406
+ fill: "none",
407
+ stroke: "currentColor",
408
+ strokeWidth: "2",
409
+ strokeLinecap: "round",
410
+ strokeLinejoin: "round",
411
+ children: [
412
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "11", cy: "11", r: "8" }),
413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
414
+ ]
415
+ }
416
+ ),
417
+ theme: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
418
+ "svg",
419
+ {
420
+ "aria-hidden": "true",
421
+ focusable: "false",
422
+ width: "18",
423
+ height: "18",
424
+ viewBox: "0 0 24 24",
425
+ fill: "none",
426
+ stroke: "currentColor",
427
+ strokeWidth: "2",
428
+ strokeLinecap: "round",
429
+ strokeLinejoin: "round",
430
+ children: [
431
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
432
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
434
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
435
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
436
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
437
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
438
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
439
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
440
+ ]
441
+ }
442
+ ),
443
+ chat: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
444
+ "svg",
445
+ {
446
+ "aria-hidden": "true",
447
+ focusable: "false",
448
+ width: "18",
449
+ height: "18",
450
+ viewBox: "0 0 24 24",
451
+ fill: "none",
452
+ stroke: "currentColor",
453
+ strokeWidth: "2",
454
+ strokeLinecap: "round",
455
+ strokeLinejoin: "round",
456
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
457
+ }
458
+ ),
459
+ notifications: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
460
+ "svg",
461
+ {
462
+ "aria-hidden": "true",
463
+ focusable: "false",
464
+ width: "18",
465
+ height: "18",
466
+ viewBox: "0 0 24 24",
467
+ fill: "none",
468
+ stroke: "currentColor",
469
+ strokeWidth: "2",
470
+ strokeLinecap: "round",
471
+ strokeLinejoin: "round",
472
+ children: [
473
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
474
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
475
+ ]
476
+ }
477
+ ),
478
+ logo: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
479
+ "svg",
480
+ {
481
+ "aria-hidden": "true",
482
+ focusable: "false",
483
+ width: "20",
484
+ height: "20",
485
+ viewBox: "0 0 24 24",
486
+ fill: "none",
487
+ stroke: "currentColor",
488
+ strokeWidth: "2",
489
+ strokeLinecap: "round",
490
+ strokeLinejoin: "round",
491
+ children: [
492
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
493
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "2 17 12 22 22 17" }),
494
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "2 12 12 17 22 12" })
495
+ ]
496
+ }
497
+ ),
498
+ close: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
499
+ "svg",
500
+ {
501
+ "aria-hidden": "true",
502
+ focusable: "false",
503
+ width: "18",
504
+ height: "18",
505
+ viewBox: "0 0 24 24",
506
+ fill: "none",
507
+ stroke: "currentColor",
508
+ strokeWidth: "2",
509
+ strokeLinecap: "round",
510
+ strokeLinejoin: "round",
511
+ children: [
512
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
513
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
514
+ ]
515
+ }
516
+ )
517
+ };
518
+ var BubbleIconButton = (0, import_react7.forwardRef)(
519
+ ({
520
+ name,
521
+ icon,
522
+ active = false,
523
+ badge,
524
+ tooltip,
525
+ children,
526
+ className = "",
527
+ style,
528
+ onMouseEnter,
529
+ onMouseLeave,
530
+ ariaLabel,
531
+ ...rest
532
+ }, ref) => {
533
+ const [isHovered, setIsHovered] = (0, import_react7.useState)(false);
534
+ const iconContent = icon || (name ? ICONS[name] : null) || children;
535
+ const computedAriaLabel = ariaLabel || tooltip || (name ? `${name} button` : "button");
536
+ const buttonStyles = {
537
+ position: "relative",
538
+ display: "inline-flex",
539
+ alignItems: "center",
540
+ justifyContent: "center",
541
+ width: "36px",
542
+ height: "36px",
543
+ borderRadius: "50%",
544
+ border: "none",
545
+ background: active ? "rgba(0, 0, 0, 0.08)" : isHovered ? "rgba(0, 0, 0, 0.05)" : "transparent",
546
+ color: "inherit",
547
+ cursor: "pointer",
548
+ padding: 0,
549
+ margin: 0,
550
+ outline: "none",
551
+ transition: "background-color 0.15s ease, transform 0.15s ease",
552
+ transform: isHovered ? "scale(1.06)" : "scale(1)",
553
+ flexShrink: 0,
554
+ ...style
555
+ };
556
+ const badgeStyles = {
557
+ position: "absolute",
558
+ top: "4px",
559
+ right: "4px",
560
+ minWidth: "7px",
561
+ height: "7px",
562
+ padding: typeof badge === "number" || typeof badge === "string" ? "1px 3px" : 0,
563
+ borderRadius: "9999px",
564
+ backgroundColor: "#ef4444",
565
+ color: "#ffffff",
566
+ fontSize: "9px",
567
+ fontWeight: "bold",
568
+ lineHeight: "1",
569
+ display: "flex",
570
+ alignItems: "center",
571
+ justifyContent: "center",
572
+ boxShadow: "0 0 0 1.5px rgba(255, 255, 255, 0.9)"
573
+ };
574
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
575
+ "button",
576
+ {
577
+ ref,
578
+ type: "button",
579
+ title: tooltip,
580
+ "aria-label": computedAriaLabel,
581
+ className: `bubble-icon-button ${active ? "bubble-icon-button--active" : ""} ${className}`.trim(),
582
+ style: buttonStyles,
583
+ onMouseEnter: (e) => {
584
+ setIsHovered(true);
585
+ onMouseEnter?.(e);
586
+ },
587
+ onMouseLeave: (e) => {
588
+ setIsHovered(false);
589
+ onMouseLeave?.(e);
590
+ },
591
+ ...rest,
592
+ children: [
593
+ iconContent,
594
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "bubble-icon-button__badge", style: badgeStyles, children: typeof badge !== "boolean" ? badge : null }) : null
595
+ ]
596
+ }
597
+ );
598
+ }
599
+ );
600
+ BubbleIconButton.displayName = "BubbleIconButton";
601
+ // Annotate the CommonJS export names for ESM import in node:
602
+ 0 && (module.exports = {
603
+ BubbleArea,
604
+ BubbleGroup,
605
+ BubbleIconButton,
606
+ BubbleToolbar,
607
+ BubbleToolbarContext,
608
+ formatPx,
609
+ getGlassStyles,
610
+ getValidChildren,
611
+ resolveSize,
612
+ useBubbleActivity,
613
+ useBubbleToolbar
614
+ });
615
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
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"]}