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.d.mts
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode, CSSProperties, ButtonHTMLAttributes, RefAttributes, ReactElement, ForwardRefExoticComponent } from 'react';
|
|
3
|
+
|
|
4
|
+
interface BubbleActivityValue {
|
|
5
|
+
isBusy: boolean;
|
|
6
|
+
run: <T>(task: () => Promise<T>) => Promise<T>;
|
|
7
|
+
}
|
|
8
|
+
declare const useBubbleActivity: () => BubbleActivityValue;
|
|
3
9
|
|
|
4
10
|
type BubbleToolbarTheme = 'light' | 'dark' | 'auto' | 'glass';
|
|
5
11
|
type BubbleToolbarPosition = 'bottom' | 'top' | 'static' | 'custom';
|
|
6
12
|
type BubbleToolbarSize = 'sm' | 'md' | 'lg' | number;
|
|
7
13
|
type BubbleShape = 'circle' | 'pill';
|
|
8
|
-
|
|
14
|
+
/** Activity appearance inherited by each bubble group. */
|
|
15
|
+
interface BubbleActivityProps {
|
|
16
|
+
/** Adds external activity; false does not hide pending local tasks. */
|
|
17
|
+
busy?: boolean;
|
|
18
|
+
/** Three CSS colors used by the rotating activity border. */
|
|
19
|
+
activityColors?: readonly [string, string, string];
|
|
20
|
+
/** Seconds per rotation. Defaults to 2.4. */
|
|
21
|
+
activityDuration?: number;
|
|
22
|
+
}
|
|
23
|
+
interface BubbleToolbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>, BubbleActivityProps {
|
|
9
24
|
/**
|
|
10
25
|
* Definition of items by groups.
|
|
11
26
|
* Example:
|
|
@@ -81,8 +96,13 @@ interface BubbleToolbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'child
|
|
|
81
96
|
* @default 'Toolbar'
|
|
82
97
|
*/
|
|
83
98
|
ariaLabel?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Controller from useBubbleLiveActivity. While an activity is shown, the groups collapse
|
|
101
|
+
* into a single pill (and then a card) and are restored afterwards, keeping their state.
|
|
102
|
+
*/
|
|
103
|
+
liveActivity?: BubbleLiveActivityController;
|
|
84
104
|
}
|
|
85
|
-
interface BubbleGroupProps extends HTMLAttributes<HTMLDivElement
|
|
105
|
+
interface BubbleGroupProps extends HTMLAttributes<HTMLDivElement>, BubbleActivityProps {
|
|
86
106
|
/**
|
|
87
107
|
* Elements inside this group.
|
|
88
108
|
* 1 node renders as a circle.
|
|
@@ -151,19 +171,234 @@ interface BubbleAreaProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
151
171
|
*/
|
|
152
172
|
maxWidth?: number | string;
|
|
153
173
|
}
|
|
174
|
+
/** A search result or suggestion. Its shape is fixed so the listbox layout stays intact. */
|
|
175
|
+
interface BubbleSearchItem {
|
|
176
|
+
/** Stable identifier, used as React key. */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Main line of the option. */
|
|
179
|
+
title: string;
|
|
180
|
+
/** Optional secondary line, e.g. a path. */
|
|
181
|
+
description?: string;
|
|
182
|
+
}
|
|
183
|
+
/** Visible and accessible texts of BubbleSearch. */
|
|
184
|
+
interface BubbleSearchLabels {
|
|
185
|
+
/** Accessible name of the search group. @default 'Search' */
|
|
186
|
+
group: string;
|
|
187
|
+
/** Accessible name of the search button. @default 'Search' */
|
|
188
|
+
button: string;
|
|
189
|
+
/** Accessible name of the combobox input. @default 'Search' */
|
|
190
|
+
input: string;
|
|
191
|
+
/** Accessible name of the results listbox. @default 'Results' */
|
|
192
|
+
listbox: string;
|
|
193
|
+
/** @default 'Search…' */
|
|
194
|
+
placeholder: string;
|
|
195
|
+
/** @default 'Searching…' */
|
|
196
|
+
searching: string;
|
|
197
|
+
/** @default 'No results. Try another term or explore a suggestion.' */
|
|
198
|
+
noResults: string;
|
|
199
|
+
/** @default 'Suggestions' */
|
|
200
|
+
suggestions: string;
|
|
201
|
+
/** @default (count) => '1 result' | `${count} results` */
|
|
202
|
+
results: (count: number) => string;
|
|
203
|
+
/** @default '↑ ↓ to explore · Enter to select · Esc to close' */
|
|
204
|
+
hint: string;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Visual tokens of BubbleSearch, written as CSS custom properties `--bubble-search-*`.
|
|
208
|
+
* Numbers are px for lengths and ms for `duration`. Structure and layout are not customizable.
|
|
209
|
+
*/
|
|
210
|
+
interface BubbleSearchTokens {
|
|
211
|
+
/** Expanded width, capped to the viewport. @default 360px */
|
|
212
|
+
width?: number | string;
|
|
213
|
+
/** Corner radius of the expanded search. @default 24px */
|
|
214
|
+
radius?: number | string;
|
|
215
|
+
/** Divider between the header and the results. @default rgb(128 128 128 / 18%) */
|
|
216
|
+
divider?: string;
|
|
217
|
+
/** Focus ring of the header. @default #818cf8 */
|
|
218
|
+
focusRing?: string;
|
|
219
|
+
/** Background of the hovered / active option. @default rgb(129 140 248 / 18%) */
|
|
220
|
+
optionActiveBg?: string;
|
|
221
|
+
/** @default 12px */
|
|
222
|
+
optionRadius?: number | string;
|
|
223
|
+
/** Option title size, clamped to 10–20px. @default 13px */
|
|
224
|
+
titleSize?: number | string;
|
|
225
|
+
/** @default 600 */
|
|
226
|
+
titleWeight?: number | string;
|
|
227
|
+
/** Size of descriptions, status and hint, clamped to 9–16px. @default 11px */
|
|
228
|
+
metaSize?: number | string;
|
|
229
|
+
/** Opacity of secondary texts, clamped to 0.4–1. @default 0.7 */
|
|
230
|
+
mutedOpacity?: number | string;
|
|
231
|
+
/** Results max height, capped to the viewport. @default 220px */
|
|
232
|
+
resultsMaxHeight?: number | string;
|
|
233
|
+
/** Panel padding, clamped to 0–16px. @default 8px */
|
|
234
|
+
panelPadding?: number | string;
|
|
235
|
+
/** Expand / collapse duration, clamped to 0–600ms. @default 180ms */
|
|
236
|
+
duration?: number | string;
|
|
237
|
+
/** @default ease */
|
|
238
|
+
easing?: string;
|
|
239
|
+
}
|
|
240
|
+
interface BubbleSearchProps<T extends BubbleSearchItem = BubbleSearchItem> {
|
|
241
|
+
/**
|
|
242
|
+
* Async search. Receives the trimmed, lower-cased query and an AbortSignal that is
|
|
243
|
+
* aborted when the query changes, the search closes or the component unmounts.
|
|
244
|
+
*/
|
|
245
|
+
onSearch: (query: string, signal: AbortSignal) => Promise<T[]>;
|
|
246
|
+
/** Called when an option is chosen. The search closes and focus returns to the button. */
|
|
247
|
+
onSelect: (item: T) => void;
|
|
248
|
+
/** Shown while the query is empty and when nothing matches. */
|
|
249
|
+
suggestions?: T[];
|
|
250
|
+
/** Receives errors from onSearch, except cancellations. The status then shows no results. */
|
|
251
|
+
onError?: (error: unknown) => void;
|
|
252
|
+
/** Controlled open state. */
|
|
253
|
+
open?: boolean;
|
|
254
|
+
/** @default false */
|
|
255
|
+
defaultOpen?: boolean;
|
|
256
|
+
onOpenChange?: (open: boolean) => void;
|
|
257
|
+
/** Wait before searching. 0 searches immediately. @default 0 */
|
|
258
|
+
debounceMs?: number;
|
|
259
|
+
labels?: Partial<BubbleSearchLabels>;
|
|
260
|
+
tokens?: BubbleSearchTokens;
|
|
261
|
+
/** Class for the search group, useful to scope tokens in CSS. */
|
|
262
|
+
className?: string;
|
|
263
|
+
}
|
|
264
|
+
/** A breadcrumb level. The last item is the current page. */
|
|
265
|
+
interface BubbleBreadcrumbItem {
|
|
266
|
+
label: string;
|
|
267
|
+
href?: string;
|
|
268
|
+
}
|
|
269
|
+
interface BubbleBreadcrumbSearchLabels extends BubbleSearchLabels {
|
|
270
|
+
/** Accessible name of the breadcrumb navigation. @default 'Breadcrumb' */
|
|
271
|
+
location: string;
|
|
272
|
+
}
|
|
273
|
+
/** BubbleSearch tokens plus `--bubble-breadcrumb-*` tokens. */
|
|
274
|
+
interface BubbleBreadcrumbSearchTokens extends BubbleSearchTokens {
|
|
275
|
+
/** Breadcrumb text size, clamped to 10–16px. @default 12px */
|
|
276
|
+
breadcrumbSize?: number | string;
|
|
277
|
+
/** @default currentColor */
|
|
278
|
+
breadcrumbSeparatorColor?: string;
|
|
279
|
+
/** Weight of the current page. @default 500 */
|
|
280
|
+
breadcrumbCurrentWeight?: number | string;
|
|
281
|
+
/** Opacity of parent levels, clamped to 0.4–1. @default 0.7 */
|
|
282
|
+
breadcrumbMutedOpacity?: number | string;
|
|
283
|
+
}
|
|
284
|
+
interface BubbleBreadcrumbSearchProps<T extends BubbleSearchItem = BubbleSearchItem> extends Omit<BubbleSearchProps<T>, 'labels' | 'tokens'> {
|
|
285
|
+
/** Current location, controlled by the app (usually its router). */
|
|
286
|
+
items: BubbleBreadcrumbItem[];
|
|
287
|
+
/** Text between levels. @default '/' */
|
|
288
|
+
separator?: string;
|
|
289
|
+
labels?: Partial<BubbleBreadcrumbSearchLabels>;
|
|
290
|
+
tokens?: BubbleBreadcrumbSearchTokens;
|
|
291
|
+
}
|
|
292
|
+
/** Content of a Live Activity. Its shape is fixed so the pill and the card keep their layout. */
|
|
293
|
+
interface BubbleLiveContent {
|
|
294
|
+
title: string;
|
|
295
|
+
description?: string;
|
|
296
|
+
/** Replaces the default spinner / outcome icon. */
|
|
297
|
+
icon?: ReactNode;
|
|
298
|
+
/** @default 'success' after a resolved task, 'error' after a rejected one, otherwise 'neutral' */
|
|
299
|
+
tone?: 'neutral' | 'success' | 'error';
|
|
300
|
+
}
|
|
301
|
+
type BubbleLiveState = 'idle' | 'compact' | 'expanded';
|
|
302
|
+
interface BubbleLiveRunOptions<T> {
|
|
303
|
+
/** Shown in the compact pill while the task runs. Defaults to `labels.pending`. */
|
|
304
|
+
pending?: BubbleLiveContent;
|
|
305
|
+
/** Card shown when the task resolves. Defaults to `labels.success`. */
|
|
306
|
+
success?: (value: T) => BubbleLiveContent;
|
|
307
|
+
/** Card shown when the task rejects. Defaults to `labels.error`. */
|
|
308
|
+
error?: (error: unknown) => BubbleLiveContent;
|
|
309
|
+
/** Milliseconds the card stays visible; 0 keeps it until dismissed. Defaults to the controller's. */
|
|
310
|
+
duration?: number;
|
|
311
|
+
}
|
|
312
|
+
/** Texts of the Live Activity. */
|
|
313
|
+
interface BubbleLiveLabels {
|
|
314
|
+
/** @default 'Working…' */
|
|
315
|
+
pending: string;
|
|
316
|
+
/** @default 'Done' */
|
|
317
|
+
success: string;
|
|
318
|
+
/** @default 'Something went wrong' */
|
|
319
|
+
error: string;
|
|
320
|
+
/** Accessible name of the close button. @default 'Dismiss' */
|
|
321
|
+
close: string;
|
|
322
|
+
/** Accessible name of the live group. @default 'Live activity' */
|
|
323
|
+
group: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Visual tokens of the Live Activity, written as `--bubble-live-*` custom properties.
|
|
327
|
+
* Numbers are px for lengths and ms for `duration`.
|
|
328
|
+
*/
|
|
329
|
+
interface BubbleLiveTokens {
|
|
330
|
+
/** Width of the compact pill, capped to the viewport. @default 200px */
|
|
331
|
+
compactWidth?: number | string;
|
|
332
|
+
/** Width of the card, capped to the viewport. @default 360px */
|
|
333
|
+
width?: number | string;
|
|
334
|
+
/** Corner radius of the card. @default 24px */
|
|
335
|
+
radius?: number | string;
|
|
336
|
+
/** Remaining-time bar. @default currentColor at 40% */
|
|
337
|
+
progressColor?: string;
|
|
338
|
+
/** @default #22c55e */
|
|
339
|
+
successColor?: string;
|
|
340
|
+
/** @default #ef4444 */
|
|
341
|
+
errorColor?: string;
|
|
342
|
+
/** Title size, clamped to 11–18px. @default 13px */
|
|
343
|
+
titleSize?: number | string;
|
|
344
|
+
/** Description size, clamped to 9–14px. @default 11px */
|
|
345
|
+
metaSize?: number | string;
|
|
346
|
+
/** Morph duration, clamped to 0–600ms. @default 320ms */
|
|
347
|
+
duration?: number | string;
|
|
348
|
+
}
|
|
349
|
+
interface BubbleLiveActivityOptions {
|
|
350
|
+
/** Default card duration in ms; 0 keeps cards until dismissed. @default 4000 */
|
|
351
|
+
duration?: number;
|
|
352
|
+
/** Minimum time the compact pill stays, so fast tasks do not flicker. @default 600 */
|
|
353
|
+
minPendingMs?: number;
|
|
354
|
+
labels?: Partial<BubbleLiveLabels>;
|
|
355
|
+
tokens?: BubbleLiveTokens;
|
|
356
|
+
}
|
|
357
|
+
/** Controller returned by useBubbleLiveActivity. Stable across renders; usable from anywhere. */
|
|
358
|
+
interface BubbleLiveActivityController {
|
|
359
|
+
/** Shows the task in the toolbar and returns its own promise (value or original error). */
|
|
360
|
+
run: <T>(task: () => Promise<T> | T, options?: BubbleLiveRunOptions<T>) => Promise<T>;
|
|
361
|
+
/** Queues a card without a task. */
|
|
362
|
+
show: (content: BubbleLiveContent, options?: {
|
|
363
|
+
duration?: number;
|
|
364
|
+
}) => void;
|
|
365
|
+
/** Closes the current activity and moves to the next queued one. */
|
|
366
|
+
dismiss: () => void;
|
|
367
|
+
/** Current state, for tests or custom UI. Not reactive; subscribe for updates. */
|
|
368
|
+
readonly state: BubbleLiveState;
|
|
369
|
+
subscribe: (listener: () => void) => () => void;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
declare const BubbleGroup: react.ForwardRefExoticComponent<BubbleGroupProps & react.RefAttributes<HTMLDivElement>>;
|
|
154
373
|
|
|
155
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Shows the current location as a breadcrumb and turns into a search when its button is pressed.
|
|
376
|
+
* The last item is the current page; it stays visible while parents truncate first.
|
|
377
|
+
*/
|
|
378
|
+
declare const BubbleBreadcrumbSearch: (<T extends BubbleSearchItem>(props: BubbleBreadcrumbSearchProps<T> & RefAttributes<HTMLDivElement>) => ReactElement | null) & {
|
|
379
|
+
displayName?: string;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Search bubble: a button that expands into a combobox with async results.
|
|
384
|
+
* Use it inside BubbleToolbar. Customize it through `labels` and `tokens`.
|
|
385
|
+
*/
|
|
386
|
+
declare const BubbleSearch: (<T extends BubbleSearchItem>(props: BubbleSearchProps<T> & RefAttributes<HTMLDivElement>) => ReactElement | null) & {
|
|
387
|
+
displayName?: string;
|
|
388
|
+
};
|
|
156
389
|
|
|
157
|
-
interface BubbleToolbarComponent extends
|
|
390
|
+
interface BubbleToolbarComponent extends ForwardRefExoticComponent<BubbleToolbarProps & RefAttributes<HTMLDivElement>> {
|
|
158
391
|
Group: typeof BubbleGroup;
|
|
392
|
+
Search: typeof BubbleSearch;
|
|
393
|
+
BreadcrumbSearch: typeof BubbleBreadcrumbSearch;
|
|
159
394
|
}
|
|
160
395
|
declare const BubbleToolbar: BubbleToolbarComponent;
|
|
161
396
|
|
|
162
|
-
declare const
|
|
397
|
+
declare const BubbleArea: react.ForwardRefExoticComponent<BubbleAreaProps & react.RefAttributes<HTMLDivElement>>;
|
|
163
398
|
|
|
164
|
-
declare const
|
|
399
|
+
declare const BubbleIconButton: react.ForwardRefExoticComponent<BubbleIconButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
165
400
|
|
|
166
|
-
interface BubbleToolbarContextValue {
|
|
401
|
+
interface BubbleToolbarContextValue extends BubbleActivityProps {
|
|
167
402
|
size: BubbleToolbarSize;
|
|
168
403
|
theme: BubbleToolbarTheme;
|
|
169
404
|
blurred: boolean;
|
|
@@ -171,13 +406,25 @@ interface BubbleToolbarContextValue {
|
|
|
171
406
|
itemGap: number | string;
|
|
172
407
|
bordered: boolean;
|
|
173
408
|
shadow: boolean | string;
|
|
409
|
+
/** Toolbar placement; undefined outside a BubbleToolbar. */
|
|
410
|
+
position?: BubbleToolbarPosition;
|
|
411
|
+
/** Live Activity controller of the toolbar, if any. */
|
|
412
|
+
liveActivity?: BubbleLiveActivityController;
|
|
174
413
|
}
|
|
175
|
-
declare const BubbleToolbarContext:
|
|
414
|
+
declare const BubbleToolbarContext: react.Context<BubbleToolbarContextValue>;
|
|
176
415
|
declare const useBubbleToolbar: () => BubbleToolbarContextValue;
|
|
177
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Creates a stable Live Activity controller. Pass it to `<BubbleToolbar liveActivity>` and call
|
|
419
|
+
* `run`, `show` or `dismiss` from anywhere. Options are read on every render.
|
|
420
|
+
*/
|
|
421
|
+
declare const useBubbleLiveActivity: (options?: BubbleLiveActivityOptions) => BubbleLiveActivityController;
|
|
422
|
+
/** Reads the controller of the surrounding BubbleToolbar. */
|
|
423
|
+
declare const useBubbleToolbarLiveActivity: () => BubbleLiveActivityController;
|
|
424
|
+
|
|
178
425
|
/**
|
|
179
426
|
* Returns an array of non-null, non-undefined, non-boolean child elements.
|
|
180
|
-
* Unpacks
|
|
427
|
+
* Unpacks Fragment if encountered at the top level.
|
|
181
428
|
*/
|
|
182
429
|
declare function getValidChildren(children: ReactNode): ReactNode[];
|
|
183
430
|
|
|
@@ -185,4 +432,4 @@ declare function resolveSize(size: BubbleToolbarSize): number;
|
|
|
185
432
|
declare function formatPx(val: number | string): string;
|
|
186
433
|
declare function getGlassStyles(theme: BubbleToolbarTheme, blurred: boolean, blurAmount: number | string, bordered: boolean, shadow: boolean | string): CSSProperties;
|
|
187
434
|
|
|
188
|
-
export { BubbleArea, type BubbleAreaProps, BubbleGroup, type BubbleGroupProps, BubbleIconButton, type BubbleIconButtonProps, type BubbleShape, BubbleToolbar, type BubbleToolbarComponent, BubbleToolbarContext, type BubbleToolbarPosition, type BubbleToolbarProps, type BubbleToolbarSize, type BubbleToolbarTheme, formatPx, getGlassStyles, getValidChildren, resolveSize, useBubbleToolbar };
|
|
435
|
+
export { type BubbleActivityProps, type BubbleActivityValue, BubbleArea, type BubbleAreaProps, type BubbleBreadcrumbItem, BubbleBreadcrumbSearch, type BubbleBreadcrumbSearchLabels, type BubbleBreadcrumbSearchProps, type BubbleBreadcrumbSearchTokens, BubbleGroup, type BubbleGroupProps, BubbleIconButton, type BubbleIconButtonProps, type BubbleLiveActivityController, type BubbleLiveActivityOptions, type BubbleLiveContent, type BubbleLiveLabels, type BubbleLiveRunOptions, type BubbleLiveState, type BubbleLiveTokens, BubbleSearch, type BubbleSearchItem, type BubbleSearchLabels, type BubbleSearchProps, type BubbleSearchTokens, type BubbleShape, BubbleToolbar, type BubbleToolbarComponent, BubbleToolbarContext, type BubbleToolbarPosition, type BubbleToolbarProps, type BubbleToolbarSize, type BubbleToolbarTheme, formatPx, getGlassStyles, getValidChildren, resolveSize, useBubbleActivity, useBubbleLiveActivity, useBubbleToolbar, useBubbleToolbarLiveActivity };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode, CSSProperties, ButtonHTMLAttributes, RefAttributes, ReactElement, ForwardRefExoticComponent } from 'react';
|
|
3
|
+
|
|
4
|
+
interface BubbleActivityValue {
|
|
5
|
+
isBusy: boolean;
|
|
6
|
+
run: <T>(task: () => Promise<T>) => Promise<T>;
|
|
7
|
+
}
|
|
8
|
+
declare const useBubbleActivity: () => BubbleActivityValue;
|
|
3
9
|
|
|
4
10
|
type BubbleToolbarTheme = 'light' | 'dark' | 'auto' | 'glass';
|
|
5
11
|
type BubbleToolbarPosition = 'bottom' | 'top' | 'static' | 'custom';
|
|
6
12
|
type BubbleToolbarSize = 'sm' | 'md' | 'lg' | number;
|
|
7
13
|
type BubbleShape = 'circle' | 'pill';
|
|
8
|
-
|
|
14
|
+
/** Activity appearance inherited by each bubble group. */
|
|
15
|
+
interface BubbleActivityProps {
|
|
16
|
+
/** Adds external activity; false does not hide pending local tasks. */
|
|
17
|
+
busy?: boolean;
|
|
18
|
+
/** Three CSS colors used by the rotating activity border. */
|
|
19
|
+
activityColors?: readonly [string, string, string];
|
|
20
|
+
/** Seconds per rotation. Defaults to 2.4. */
|
|
21
|
+
activityDuration?: number;
|
|
22
|
+
}
|
|
23
|
+
interface BubbleToolbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>, BubbleActivityProps {
|
|
9
24
|
/**
|
|
10
25
|
* Definition of items by groups.
|
|
11
26
|
* Example:
|
|
@@ -81,8 +96,13 @@ interface BubbleToolbarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'child
|
|
|
81
96
|
* @default 'Toolbar'
|
|
82
97
|
*/
|
|
83
98
|
ariaLabel?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Controller from useBubbleLiveActivity. While an activity is shown, the groups collapse
|
|
101
|
+
* into a single pill (and then a card) and are restored afterwards, keeping their state.
|
|
102
|
+
*/
|
|
103
|
+
liveActivity?: BubbleLiveActivityController;
|
|
84
104
|
}
|
|
85
|
-
interface BubbleGroupProps extends HTMLAttributes<HTMLDivElement
|
|
105
|
+
interface BubbleGroupProps extends HTMLAttributes<HTMLDivElement>, BubbleActivityProps {
|
|
86
106
|
/**
|
|
87
107
|
* Elements inside this group.
|
|
88
108
|
* 1 node renders as a circle.
|
|
@@ -151,19 +171,234 @@ interface BubbleAreaProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
151
171
|
*/
|
|
152
172
|
maxWidth?: number | string;
|
|
153
173
|
}
|
|
174
|
+
/** A search result or suggestion. Its shape is fixed so the listbox layout stays intact. */
|
|
175
|
+
interface BubbleSearchItem {
|
|
176
|
+
/** Stable identifier, used as React key. */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Main line of the option. */
|
|
179
|
+
title: string;
|
|
180
|
+
/** Optional secondary line, e.g. a path. */
|
|
181
|
+
description?: string;
|
|
182
|
+
}
|
|
183
|
+
/** Visible and accessible texts of BubbleSearch. */
|
|
184
|
+
interface BubbleSearchLabels {
|
|
185
|
+
/** Accessible name of the search group. @default 'Search' */
|
|
186
|
+
group: string;
|
|
187
|
+
/** Accessible name of the search button. @default 'Search' */
|
|
188
|
+
button: string;
|
|
189
|
+
/** Accessible name of the combobox input. @default 'Search' */
|
|
190
|
+
input: string;
|
|
191
|
+
/** Accessible name of the results listbox. @default 'Results' */
|
|
192
|
+
listbox: string;
|
|
193
|
+
/** @default 'Search…' */
|
|
194
|
+
placeholder: string;
|
|
195
|
+
/** @default 'Searching…' */
|
|
196
|
+
searching: string;
|
|
197
|
+
/** @default 'No results. Try another term or explore a suggestion.' */
|
|
198
|
+
noResults: string;
|
|
199
|
+
/** @default 'Suggestions' */
|
|
200
|
+
suggestions: string;
|
|
201
|
+
/** @default (count) => '1 result' | `${count} results` */
|
|
202
|
+
results: (count: number) => string;
|
|
203
|
+
/** @default '↑ ↓ to explore · Enter to select · Esc to close' */
|
|
204
|
+
hint: string;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Visual tokens of BubbleSearch, written as CSS custom properties `--bubble-search-*`.
|
|
208
|
+
* Numbers are px for lengths and ms for `duration`. Structure and layout are not customizable.
|
|
209
|
+
*/
|
|
210
|
+
interface BubbleSearchTokens {
|
|
211
|
+
/** Expanded width, capped to the viewport. @default 360px */
|
|
212
|
+
width?: number | string;
|
|
213
|
+
/** Corner radius of the expanded search. @default 24px */
|
|
214
|
+
radius?: number | string;
|
|
215
|
+
/** Divider between the header and the results. @default rgb(128 128 128 / 18%) */
|
|
216
|
+
divider?: string;
|
|
217
|
+
/** Focus ring of the header. @default #818cf8 */
|
|
218
|
+
focusRing?: string;
|
|
219
|
+
/** Background of the hovered / active option. @default rgb(129 140 248 / 18%) */
|
|
220
|
+
optionActiveBg?: string;
|
|
221
|
+
/** @default 12px */
|
|
222
|
+
optionRadius?: number | string;
|
|
223
|
+
/** Option title size, clamped to 10–20px. @default 13px */
|
|
224
|
+
titleSize?: number | string;
|
|
225
|
+
/** @default 600 */
|
|
226
|
+
titleWeight?: number | string;
|
|
227
|
+
/** Size of descriptions, status and hint, clamped to 9–16px. @default 11px */
|
|
228
|
+
metaSize?: number | string;
|
|
229
|
+
/** Opacity of secondary texts, clamped to 0.4–1. @default 0.7 */
|
|
230
|
+
mutedOpacity?: number | string;
|
|
231
|
+
/** Results max height, capped to the viewport. @default 220px */
|
|
232
|
+
resultsMaxHeight?: number | string;
|
|
233
|
+
/** Panel padding, clamped to 0–16px. @default 8px */
|
|
234
|
+
panelPadding?: number | string;
|
|
235
|
+
/** Expand / collapse duration, clamped to 0–600ms. @default 180ms */
|
|
236
|
+
duration?: number | string;
|
|
237
|
+
/** @default ease */
|
|
238
|
+
easing?: string;
|
|
239
|
+
}
|
|
240
|
+
interface BubbleSearchProps<T extends BubbleSearchItem = BubbleSearchItem> {
|
|
241
|
+
/**
|
|
242
|
+
* Async search. Receives the trimmed, lower-cased query and an AbortSignal that is
|
|
243
|
+
* aborted when the query changes, the search closes or the component unmounts.
|
|
244
|
+
*/
|
|
245
|
+
onSearch: (query: string, signal: AbortSignal) => Promise<T[]>;
|
|
246
|
+
/** Called when an option is chosen. The search closes and focus returns to the button. */
|
|
247
|
+
onSelect: (item: T) => void;
|
|
248
|
+
/** Shown while the query is empty and when nothing matches. */
|
|
249
|
+
suggestions?: T[];
|
|
250
|
+
/** Receives errors from onSearch, except cancellations. The status then shows no results. */
|
|
251
|
+
onError?: (error: unknown) => void;
|
|
252
|
+
/** Controlled open state. */
|
|
253
|
+
open?: boolean;
|
|
254
|
+
/** @default false */
|
|
255
|
+
defaultOpen?: boolean;
|
|
256
|
+
onOpenChange?: (open: boolean) => void;
|
|
257
|
+
/** Wait before searching. 0 searches immediately. @default 0 */
|
|
258
|
+
debounceMs?: number;
|
|
259
|
+
labels?: Partial<BubbleSearchLabels>;
|
|
260
|
+
tokens?: BubbleSearchTokens;
|
|
261
|
+
/** Class for the search group, useful to scope tokens in CSS. */
|
|
262
|
+
className?: string;
|
|
263
|
+
}
|
|
264
|
+
/** A breadcrumb level. The last item is the current page. */
|
|
265
|
+
interface BubbleBreadcrumbItem {
|
|
266
|
+
label: string;
|
|
267
|
+
href?: string;
|
|
268
|
+
}
|
|
269
|
+
interface BubbleBreadcrumbSearchLabels extends BubbleSearchLabels {
|
|
270
|
+
/** Accessible name of the breadcrumb navigation. @default 'Breadcrumb' */
|
|
271
|
+
location: string;
|
|
272
|
+
}
|
|
273
|
+
/** BubbleSearch tokens plus `--bubble-breadcrumb-*` tokens. */
|
|
274
|
+
interface BubbleBreadcrumbSearchTokens extends BubbleSearchTokens {
|
|
275
|
+
/** Breadcrumb text size, clamped to 10–16px. @default 12px */
|
|
276
|
+
breadcrumbSize?: number | string;
|
|
277
|
+
/** @default currentColor */
|
|
278
|
+
breadcrumbSeparatorColor?: string;
|
|
279
|
+
/** Weight of the current page. @default 500 */
|
|
280
|
+
breadcrumbCurrentWeight?: number | string;
|
|
281
|
+
/** Opacity of parent levels, clamped to 0.4–1. @default 0.7 */
|
|
282
|
+
breadcrumbMutedOpacity?: number | string;
|
|
283
|
+
}
|
|
284
|
+
interface BubbleBreadcrumbSearchProps<T extends BubbleSearchItem = BubbleSearchItem> extends Omit<BubbleSearchProps<T>, 'labels' | 'tokens'> {
|
|
285
|
+
/** Current location, controlled by the app (usually its router). */
|
|
286
|
+
items: BubbleBreadcrumbItem[];
|
|
287
|
+
/** Text between levels. @default '/' */
|
|
288
|
+
separator?: string;
|
|
289
|
+
labels?: Partial<BubbleBreadcrumbSearchLabels>;
|
|
290
|
+
tokens?: BubbleBreadcrumbSearchTokens;
|
|
291
|
+
}
|
|
292
|
+
/** Content of a Live Activity. Its shape is fixed so the pill and the card keep their layout. */
|
|
293
|
+
interface BubbleLiveContent {
|
|
294
|
+
title: string;
|
|
295
|
+
description?: string;
|
|
296
|
+
/** Replaces the default spinner / outcome icon. */
|
|
297
|
+
icon?: ReactNode;
|
|
298
|
+
/** @default 'success' after a resolved task, 'error' after a rejected one, otherwise 'neutral' */
|
|
299
|
+
tone?: 'neutral' | 'success' | 'error';
|
|
300
|
+
}
|
|
301
|
+
type BubbleLiveState = 'idle' | 'compact' | 'expanded';
|
|
302
|
+
interface BubbleLiveRunOptions<T> {
|
|
303
|
+
/** Shown in the compact pill while the task runs. Defaults to `labels.pending`. */
|
|
304
|
+
pending?: BubbleLiveContent;
|
|
305
|
+
/** Card shown when the task resolves. Defaults to `labels.success`. */
|
|
306
|
+
success?: (value: T) => BubbleLiveContent;
|
|
307
|
+
/** Card shown when the task rejects. Defaults to `labels.error`. */
|
|
308
|
+
error?: (error: unknown) => BubbleLiveContent;
|
|
309
|
+
/** Milliseconds the card stays visible; 0 keeps it until dismissed. Defaults to the controller's. */
|
|
310
|
+
duration?: number;
|
|
311
|
+
}
|
|
312
|
+
/** Texts of the Live Activity. */
|
|
313
|
+
interface BubbleLiveLabels {
|
|
314
|
+
/** @default 'Working…' */
|
|
315
|
+
pending: string;
|
|
316
|
+
/** @default 'Done' */
|
|
317
|
+
success: string;
|
|
318
|
+
/** @default 'Something went wrong' */
|
|
319
|
+
error: string;
|
|
320
|
+
/** Accessible name of the close button. @default 'Dismiss' */
|
|
321
|
+
close: string;
|
|
322
|
+
/** Accessible name of the live group. @default 'Live activity' */
|
|
323
|
+
group: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Visual tokens of the Live Activity, written as `--bubble-live-*` custom properties.
|
|
327
|
+
* Numbers are px for lengths and ms for `duration`.
|
|
328
|
+
*/
|
|
329
|
+
interface BubbleLiveTokens {
|
|
330
|
+
/** Width of the compact pill, capped to the viewport. @default 200px */
|
|
331
|
+
compactWidth?: number | string;
|
|
332
|
+
/** Width of the card, capped to the viewport. @default 360px */
|
|
333
|
+
width?: number | string;
|
|
334
|
+
/** Corner radius of the card. @default 24px */
|
|
335
|
+
radius?: number | string;
|
|
336
|
+
/** Remaining-time bar. @default currentColor at 40% */
|
|
337
|
+
progressColor?: string;
|
|
338
|
+
/** @default #22c55e */
|
|
339
|
+
successColor?: string;
|
|
340
|
+
/** @default #ef4444 */
|
|
341
|
+
errorColor?: string;
|
|
342
|
+
/** Title size, clamped to 11–18px. @default 13px */
|
|
343
|
+
titleSize?: number | string;
|
|
344
|
+
/** Description size, clamped to 9–14px. @default 11px */
|
|
345
|
+
metaSize?: number | string;
|
|
346
|
+
/** Morph duration, clamped to 0–600ms. @default 320ms */
|
|
347
|
+
duration?: number | string;
|
|
348
|
+
}
|
|
349
|
+
interface BubbleLiveActivityOptions {
|
|
350
|
+
/** Default card duration in ms; 0 keeps cards until dismissed. @default 4000 */
|
|
351
|
+
duration?: number;
|
|
352
|
+
/** Minimum time the compact pill stays, so fast tasks do not flicker. @default 600 */
|
|
353
|
+
minPendingMs?: number;
|
|
354
|
+
labels?: Partial<BubbleLiveLabels>;
|
|
355
|
+
tokens?: BubbleLiveTokens;
|
|
356
|
+
}
|
|
357
|
+
/** Controller returned by useBubbleLiveActivity. Stable across renders; usable from anywhere. */
|
|
358
|
+
interface BubbleLiveActivityController {
|
|
359
|
+
/** Shows the task in the toolbar and returns its own promise (value or original error). */
|
|
360
|
+
run: <T>(task: () => Promise<T> | T, options?: BubbleLiveRunOptions<T>) => Promise<T>;
|
|
361
|
+
/** Queues a card without a task. */
|
|
362
|
+
show: (content: BubbleLiveContent, options?: {
|
|
363
|
+
duration?: number;
|
|
364
|
+
}) => void;
|
|
365
|
+
/** Closes the current activity and moves to the next queued one. */
|
|
366
|
+
dismiss: () => void;
|
|
367
|
+
/** Current state, for tests or custom UI. Not reactive; subscribe for updates. */
|
|
368
|
+
readonly state: BubbleLiveState;
|
|
369
|
+
subscribe: (listener: () => void) => () => void;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
declare const BubbleGroup: react.ForwardRefExoticComponent<BubbleGroupProps & react.RefAttributes<HTMLDivElement>>;
|
|
154
373
|
|
|
155
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Shows the current location as a breadcrumb and turns into a search when its button is pressed.
|
|
376
|
+
* The last item is the current page; it stays visible while parents truncate first.
|
|
377
|
+
*/
|
|
378
|
+
declare const BubbleBreadcrumbSearch: (<T extends BubbleSearchItem>(props: BubbleBreadcrumbSearchProps<T> & RefAttributes<HTMLDivElement>) => ReactElement | null) & {
|
|
379
|
+
displayName?: string;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Search bubble: a button that expands into a combobox with async results.
|
|
384
|
+
* Use it inside BubbleToolbar. Customize it through `labels` and `tokens`.
|
|
385
|
+
*/
|
|
386
|
+
declare const BubbleSearch: (<T extends BubbleSearchItem>(props: BubbleSearchProps<T> & RefAttributes<HTMLDivElement>) => ReactElement | null) & {
|
|
387
|
+
displayName?: string;
|
|
388
|
+
};
|
|
156
389
|
|
|
157
|
-
interface BubbleToolbarComponent extends
|
|
390
|
+
interface BubbleToolbarComponent extends ForwardRefExoticComponent<BubbleToolbarProps & RefAttributes<HTMLDivElement>> {
|
|
158
391
|
Group: typeof BubbleGroup;
|
|
392
|
+
Search: typeof BubbleSearch;
|
|
393
|
+
BreadcrumbSearch: typeof BubbleBreadcrumbSearch;
|
|
159
394
|
}
|
|
160
395
|
declare const BubbleToolbar: BubbleToolbarComponent;
|
|
161
396
|
|
|
162
|
-
declare const
|
|
397
|
+
declare const BubbleArea: react.ForwardRefExoticComponent<BubbleAreaProps & react.RefAttributes<HTMLDivElement>>;
|
|
163
398
|
|
|
164
|
-
declare const
|
|
399
|
+
declare const BubbleIconButton: react.ForwardRefExoticComponent<BubbleIconButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
165
400
|
|
|
166
|
-
interface BubbleToolbarContextValue {
|
|
401
|
+
interface BubbleToolbarContextValue extends BubbleActivityProps {
|
|
167
402
|
size: BubbleToolbarSize;
|
|
168
403
|
theme: BubbleToolbarTheme;
|
|
169
404
|
blurred: boolean;
|
|
@@ -171,13 +406,25 @@ interface BubbleToolbarContextValue {
|
|
|
171
406
|
itemGap: number | string;
|
|
172
407
|
bordered: boolean;
|
|
173
408
|
shadow: boolean | string;
|
|
409
|
+
/** Toolbar placement; undefined outside a BubbleToolbar. */
|
|
410
|
+
position?: BubbleToolbarPosition;
|
|
411
|
+
/** Live Activity controller of the toolbar, if any. */
|
|
412
|
+
liveActivity?: BubbleLiveActivityController;
|
|
174
413
|
}
|
|
175
|
-
declare const BubbleToolbarContext:
|
|
414
|
+
declare const BubbleToolbarContext: react.Context<BubbleToolbarContextValue>;
|
|
176
415
|
declare const useBubbleToolbar: () => BubbleToolbarContextValue;
|
|
177
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Creates a stable Live Activity controller. Pass it to `<BubbleToolbar liveActivity>` and call
|
|
419
|
+
* `run`, `show` or `dismiss` from anywhere. Options are read on every render.
|
|
420
|
+
*/
|
|
421
|
+
declare const useBubbleLiveActivity: (options?: BubbleLiveActivityOptions) => BubbleLiveActivityController;
|
|
422
|
+
/** Reads the controller of the surrounding BubbleToolbar. */
|
|
423
|
+
declare const useBubbleToolbarLiveActivity: () => BubbleLiveActivityController;
|
|
424
|
+
|
|
178
425
|
/**
|
|
179
426
|
* Returns an array of non-null, non-undefined, non-boolean child elements.
|
|
180
|
-
* Unpacks
|
|
427
|
+
* Unpacks Fragment if encountered at the top level.
|
|
181
428
|
*/
|
|
182
429
|
declare function getValidChildren(children: ReactNode): ReactNode[];
|
|
183
430
|
|
|
@@ -185,4 +432,4 @@ declare function resolveSize(size: BubbleToolbarSize): number;
|
|
|
185
432
|
declare function formatPx(val: number | string): string;
|
|
186
433
|
declare function getGlassStyles(theme: BubbleToolbarTheme, blurred: boolean, blurAmount: number | string, bordered: boolean, shadow: boolean | string): CSSProperties;
|
|
187
434
|
|
|
188
|
-
export { BubbleArea, type BubbleAreaProps, BubbleGroup, type BubbleGroupProps, BubbleIconButton, type BubbleIconButtonProps, type BubbleShape, BubbleToolbar, type BubbleToolbarComponent, BubbleToolbarContext, type BubbleToolbarPosition, type BubbleToolbarProps, type BubbleToolbarSize, type BubbleToolbarTheme, formatPx, getGlassStyles, getValidChildren, resolveSize, useBubbleToolbar };
|
|
435
|
+
export { type BubbleActivityProps, type BubbleActivityValue, BubbleArea, type BubbleAreaProps, type BubbleBreadcrumbItem, BubbleBreadcrumbSearch, type BubbleBreadcrumbSearchLabels, type BubbleBreadcrumbSearchProps, type BubbleBreadcrumbSearchTokens, BubbleGroup, type BubbleGroupProps, BubbleIconButton, type BubbleIconButtonProps, type BubbleLiveActivityController, type BubbleLiveActivityOptions, type BubbleLiveContent, type BubbleLiveLabels, type BubbleLiveRunOptions, type BubbleLiveState, type BubbleLiveTokens, BubbleSearch, type BubbleSearchItem, type BubbleSearchLabels, type BubbleSearchProps, type BubbleSearchTokens, type BubbleShape, BubbleToolbar, type BubbleToolbarComponent, BubbleToolbarContext, type BubbleToolbarPosition, type BubbleToolbarProps, type BubbleToolbarSize, type BubbleToolbarTheme, formatPx, getGlassStyles, getValidChildren, resolveSize, useBubbleActivity, useBubbleLiveActivity, useBubbleToolbar, useBubbleToolbarLiveActivity };
|