@jobber/components 8.21.1 → 8.23.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/Dialog.d.ts +1 -0
- package/Dialog.js +17 -0
- package/dist/BottomSheet-cjs.js +34 -7
- package/dist/BottomSheet-es.js +34 -8
- package/dist/CSPContext-cjs.js +69 -0
- package/dist/CSPContext-es.js +46 -0
- package/dist/Card/index.cjs +3 -0
- package/dist/Card/index.mjs +3 -0
- package/dist/ComboboxChipRemove-cjs.js +54 -211
- package/dist/ComboboxChipRemove-es.js +8 -164
- package/dist/DataDump/index.cjs +3 -0
- package/dist/DataDump/index.mjs +3 -0
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.types.d.ts +205 -0
- package/dist/Dialog/DialogBottomSheet.d.ts +28 -0
- package/dist/Dialog/DialogModal.d.ts +20 -0
- package/dist/Dialog/constants.d.ts +1 -0
- package/dist/Dialog/dialogComposableShared.d.ts +53 -0
- package/dist/Dialog/dialogReturnFocus.d.ts +43 -0
- package/dist/Dialog/index.cjs +33 -0
- package/dist/Dialog/index.d.ts +4 -0
- package/dist/Dialog/index.mjs +25 -0
- package/dist/DrawerDescription-cjs.js +410 -0
- package/dist/DrawerDescription-es.js +383 -0
- package/dist/DrawerTitle-cjs.js +116 -0
- package/dist/DrawerTitle-es.js +92 -0
- package/dist/InputNumberExperimental-cjs.js +24 -23
- package/dist/InputNumberExperimental-es.js +3 -2
- package/dist/InternalBackdrop-es.js +3 -3
- package/dist/Menu/index.cjs +3 -0
- package/dist/Menu/index.mjs +3 -0
- package/dist/Menu-cjs.js +6 -4
- package/dist/Menu-es.js +6 -4
- package/dist/MenuSubmenuTrigger-cjs.js +53 -103
- package/dist/MenuSubmenuTrigger-es.js +55 -103
- package/dist/NumberFieldInput-cjs.js +9 -9
- package/dist/NumberFieldInput-es.js +3 -3
- package/dist/Page/index.cjs +3 -0
- package/dist/Page/index.mjs +3 -0
- package/dist/ScrollAreaViewport-cjs.js +921 -960
- package/dist/ScrollAreaViewport-es.js +917 -958
- package/dist/SelectGroupLabel-cjs.js +1924 -0
- package/dist/SelectGroupLabel-es.js +1888 -0
- package/dist/SelectPrimitive-cjs.js +112 -0
- package/dist/SelectPrimitive-es.js +110 -0
- package/dist/ToolbarRootContext-cjs.js +35 -0
- package/dist/ToolbarRootContext-es.js +14 -0
- package/dist/dialogReturnFocus-cjs.js +427 -0
- package/dist/dialogReturnFocus-es.js +423 -0
- package/dist/docs/SelectPrimitive/SelectPrimitive.md +326 -0
- package/dist/docs/index.md +1 -0
- package/dist/floating-ui.react-dom-cjs.js +1 -0
- package/dist/floating-ui.react-dom-es.js +2 -2
- package/dist/floating-ui.utils.dom-es.js +1 -1
- package/dist/index.cjs +15 -7
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +12 -7
- package/dist/primitives/BottomSheet/BottomSheet.d.ts +19 -1
- package/dist/primitives/BottomSheet/BottomSheet.types.d.ts +8 -0
- package/dist/primitives/BottomSheet/index.cjs +2 -0
- package/dist/primitives/BottomSheet/index.d.ts +1 -1
- package/dist/primitives/BottomSheet/index.mjs +2 -1
- package/dist/primitives/ComboboxPrimitive/index.cjs +3 -1
- package/dist/primitives/ComboboxPrimitive/index.mjs +3 -1
- package/dist/primitives/InputNumberExperimental/index.cjs +2 -1
- package/dist/primitives/InputNumberExperimental/index.mjs +2 -1
- package/dist/primitives/SelectPrimitive/SelectPrimitive.d.ts +63 -0
- package/dist/primitives/SelectPrimitive/index.cjs +29 -0
- package/dist/primitives/SelectPrimitive/index.d.ts +2 -0
- package/dist/primitives/SelectPrimitive/index.mjs +23 -0
- package/dist/primitives/SelectPrimitive/types.d.ts +16 -0
- package/dist/primitives/index.cjs +9 -1
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.mjs +8 -2
- package/dist/primitives/mergeClassName.d.ts +12 -0
- package/dist/resolveAriaLabelledBy-cjs.js +195 -0
- package/dist/resolveAriaLabelledBy-es.js +162 -0
- package/dist/styles.css +685 -0
- package/dist/unstyledPrimitives/index.cjs +434 -259
- package/dist/unstyledPrimitives/index.d.ts +2 -0
- package/dist/unstyledPrimitives/index.mjs +425 -252
- package/dist/useButton-cjs.js +2 -0
- package/dist/useButton-es.js +3 -2
- package/dist/useCompositeListItem-es.js +4 -4
- package/dist/useLabel-cjs.js +3 -329
- package/dist/useLabel-es.js +4 -299
- package/dist/useLabelableId-cjs.js +332 -0
- package/dist/useLabelableId-es.js +300 -0
- package/dist/useRenderElement-cjs.js +3 -0
- package/dist/useRenderElement-es.js +4 -1
- package/dist/utils/meta/meta.json +11 -1
- package/package.json +2 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { E as EMPTY_OBJECT, a as useRefWithInit, f as formatErrorMessage, u as useRenderElement } from './useRenderElement-es.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { a as FloatingRootStore, P as PopupTriggerMap, o as createSelector, u as useFloatingParentNodeId, y as FloatingPortal, I as InternalBackdrop, A as inertValue, q as useOpenInteractionType, t as useDismiss, z as useScrollLock, v as useInteractions, R as ReactStore, w as useOnFirstRender, s as useClick, E as CLICK_TRIGGER_IDENTIFIER, G as triggerOpenStateMapping, p as popupStateMapping, C as CommonPopupDataAttributes, F as FloatingFocusManager, n as useDirection } from './InternalBackdrop-es.js';
|
|
4
|
+
import { b as useStableCallback, a as useIsoLayoutEffect, k as useTransitionStatus, f as useOpenChangeComplete, l as useId, m as getFloatingFocusElement, d as createChangeEventDetails, i as imperativeAction, g as getTarget, r as contains, u as useBaseUiId, c as useButton, t as transitionStatusMapping, o as ownerDocument, E as useControlled, G as none, _ as isAndroid, $ as closeWatcher, h as useTimeout, X as isWebKit } from './useButton-es.js';
|
|
5
|
+
import { C as COMPOSITE_KEYS, u as useCSPContext, s as styleDisableScrollbar } from './CSPContext-es.js';
|
|
5
6
|
import { c as clamp } from './clamp-es.js';
|
|
6
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
-
import { b as isElement,
|
|
8
|
+
import { b as isElement, o as getWindow } from './floating-ui.utils.dom-es.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Returns a callback ref that registers/unregisters the trigger element in the store.
|
|
@@ -393,179 +394,6 @@ function useDialogRootContext(optional) {
|
|
|
393
394
|
return dialogRootContext;
|
|
394
395
|
}
|
|
395
396
|
|
|
396
|
-
let DrawerPopupCssVars = /*#__PURE__*/function (DrawerPopupCssVars) {
|
|
397
|
-
/**
|
|
398
|
-
* The number of nested drawers that are currently open.
|
|
399
|
-
* @type {number}
|
|
400
|
-
*/
|
|
401
|
-
DrawerPopupCssVars["nestedDrawers"] = "--nested-drawers";
|
|
402
|
-
/**
|
|
403
|
-
* The height of the drawer popup.
|
|
404
|
-
* @type {CSS length}
|
|
405
|
-
*/
|
|
406
|
-
DrawerPopupCssVars["height"] = "--drawer-height";
|
|
407
|
-
/**
|
|
408
|
-
* The height of the frontmost open drawer in the current nested drawer stack.
|
|
409
|
-
* @type {CSS length}
|
|
410
|
-
*/
|
|
411
|
-
DrawerPopupCssVars["frontmostHeight"] = "--drawer-frontmost-height";
|
|
412
|
-
/**
|
|
413
|
-
* The swipe movement on the X axis.
|
|
414
|
-
* @type {CSS length}
|
|
415
|
-
*/
|
|
416
|
-
DrawerPopupCssVars["swipeMovementX"] = "--drawer-swipe-movement-x";
|
|
417
|
-
/**
|
|
418
|
-
* The swipe movement on the Y axis.
|
|
419
|
-
* @type {CSS length}
|
|
420
|
-
*/
|
|
421
|
-
DrawerPopupCssVars["swipeMovementY"] = "--drawer-swipe-movement-y";
|
|
422
|
-
/**
|
|
423
|
-
* The snap point offset used for translating the drawer.
|
|
424
|
-
* @type {CSS length}
|
|
425
|
-
*/
|
|
426
|
-
DrawerPopupCssVars["snapPointOffset"] = "--drawer-snap-point-offset";
|
|
427
|
-
/**
|
|
428
|
-
* A scalar (0.1-1) used to scale the swipe release transition duration in CSS.
|
|
429
|
-
* @type {number}
|
|
430
|
-
*/
|
|
431
|
-
DrawerPopupCssVars["swipeStrength"] = "--drawer-swipe-strength";
|
|
432
|
-
return DrawerPopupCssVars;
|
|
433
|
-
}({});
|
|
434
|
-
|
|
435
|
-
let DrawerBackdropCssVars = /*#__PURE__*/function (DrawerBackdropCssVars) {
|
|
436
|
-
/**
|
|
437
|
-
* The swipe progress of the drawer gesture.
|
|
438
|
-
* @type {number}
|
|
439
|
-
*/
|
|
440
|
-
DrawerBackdropCssVars["swipeProgress"] = "--drawer-swipe-progress";
|
|
441
|
-
return DrawerBackdropCssVars;
|
|
442
|
-
}({});
|
|
443
|
-
|
|
444
|
-
const stateAttributesMapping$1 = {
|
|
445
|
-
...popupStateMapping,
|
|
446
|
-
...transitionStatusMapping
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* An overlay displayed beneath the popup.
|
|
451
|
-
* Renders a `<div>` element.
|
|
452
|
-
*
|
|
453
|
-
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
454
|
-
*/
|
|
455
|
-
const DrawerBackdrop = /*#__PURE__*/React.forwardRef(function DrawerBackdrop(componentProps, forwardedRef) {
|
|
456
|
-
const {
|
|
457
|
-
render,
|
|
458
|
-
className,
|
|
459
|
-
forceRender = false,
|
|
460
|
-
...elementProps
|
|
461
|
-
} = componentProps;
|
|
462
|
-
const {
|
|
463
|
-
store
|
|
464
|
-
} = useDialogRootContext();
|
|
465
|
-
const open = store.useState('open');
|
|
466
|
-
const nested = store.useState('nested');
|
|
467
|
-
const mounted = store.useState('mounted');
|
|
468
|
-
const transitionStatus = store.useState('transitionStatus');
|
|
469
|
-
const state = {
|
|
470
|
-
open,
|
|
471
|
-
transitionStatus
|
|
472
|
-
};
|
|
473
|
-
return useRenderElement('div', componentProps, {
|
|
474
|
-
state,
|
|
475
|
-
ref: [store.context.backdropRef, forwardedRef],
|
|
476
|
-
stateAttributesMapping: stateAttributesMapping$1,
|
|
477
|
-
props: [{
|
|
478
|
-
role: 'presentation',
|
|
479
|
-
hidden: !mounted,
|
|
480
|
-
style: {
|
|
481
|
-
pointerEvents: !open ? 'none' : undefined,
|
|
482
|
-
userSelect: 'none',
|
|
483
|
-
WebkitUserSelect: 'none',
|
|
484
|
-
[DrawerBackdropCssVars.swipeProgress]: '0',
|
|
485
|
-
[DrawerPopupCssVars.swipeStrength]: '1'
|
|
486
|
-
}
|
|
487
|
-
}, elementProps],
|
|
488
|
-
enabled: forceRender || !nested
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
if (process.env.NODE_ENV !== "production") DrawerBackdrop.displayName = "DrawerBackdrop";
|
|
492
|
-
|
|
493
|
-
const DRAWER_CONTENT_ATTRIBUTE = 'data-drawer-content';
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* A container for the drawer contents.
|
|
497
|
-
* Renders a `<div>` element.
|
|
498
|
-
*
|
|
499
|
-
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
500
|
-
*/
|
|
501
|
-
const DrawerContent = /*#__PURE__*/React.forwardRef(function DrawerContent(componentProps, forwardedRef) {
|
|
502
|
-
const {
|
|
503
|
-
render,
|
|
504
|
-
className,
|
|
505
|
-
...elementProps
|
|
506
|
-
} = componentProps;
|
|
507
|
-
useDialogRootContext();
|
|
508
|
-
return useRenderElement('div', componentProps, {
|
|
509
|
-
ref: forwardedRef,
|
|
510
|
-
props: [{
|
|
511
|
-
[DRAWER_CONTENT_ATTRIBUTE]: ''
|
|
512
|
-
}, elementProps]
|
|
513
|
-
});
|
|
514
|
-
});
|
|
515
|
-
if (process.env.NODE_ENV !== "production") DrawerContent.displayName = "DrawerContent";
|
|
516
|
-
|
|
517
|
-
const DrawerProviderContext = /*#__PURE__*/React.createContext(undefined);
|
|
518
|
-
if (process.env.NODE_ENV !== "production") DrawerProviderContext.displayName = "DrawerProviderContext";
|
|
519
|
-
function useDrawerProviderContext(optional) {
|
|
520
|
-
const context = React.useContext(DrawerProviderContext);
|
|
521
|
-
return context;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
let DrawerPopupDataAttributes = function (DrawerPopupDataAttributes) {
|
|
525
|
-
/**
|
|
526
|
-
* Present when the drawer is open.
|
|
527
|
-
*/
|
|
528
|
-
DrawerPopupDataAttributes[DrawerPopupDataAttributes["open"] = CommonPopupDataAttributes.open] = "open";
|
|
529
|
-
/**
|
|
530
|
-
* Present when the drawer is closed.
|
|
531
|
-
*/
|
|
532
|
-
DrawerPopupDataAttributes[DrawerPopupDataAttributes["closed"] = CommonPopupDataAttributes.closed] = "closed";
|
|
533
|
-
/**
|
|
534
|
-
* Present when the drawer is animating in.
|
|
535
|
-
*/
|
|
536
|
-
DrawerPopupDataAttributes[DrawerPopupDataAttributes["startingStyle"] = CommonPopupDataAttributes.startingStyle] = "startingStyle";
|
|
537
|
-
/**
|
|
538
|
-
* Present when the drawer is animating out.
|
|
539
|
-
*/
|
|
540
|
-
DrawerPopupDataAttributes[DrawerPopupDataAttributes["endingStyle"] = CommonPopupDataAttributes.endingStyle] = "endingStyle";
|
|
541
|
-
/**
|
|
542
|
-
* Present when the drawer is at the expanded (full-height) snap point.
|
|
543
|
-
*/
|
|
544
|
-
DrawerPopupDataAttributes["expanded"] = "data-expanded";
|
|
545
|
-
/**
|
|
546
|
-
* Present when a nested drawer is open.
|
|
547
|
-
*/
|
|
548
|
-
DrawerPopupDataAttributes["nestedDrawerOpen"] = "data-nested-drawer-open";
|
|
549
|
-
/**
|
|
550
|
-
* Present when a nested drawer is being swiped.
|
|
551
|
-
*/
|
|
552
|
-
DrawerPopupDataAttributes["nestedDrawerSwiping"] = "data-nested-drawer-swiping";
|
|
553
|
-
/**
|
|
554
|
-
* Present when the drawer is dismissed by swiping.
|
|
555
|
-
*/
|
|
556
|
-
DrawerPopupDataAttributes["swipeDismiss"] = "data-swipe-dismiss";
|
|
557
|
-
/**
|
|
558
|
-
* Indicates the swipe direction.
|
|
559
|
-
* @type {'up' | 'down' | 'left' | 'right'}
|
|
560
|
-
*/
|
|
561
|
-
DrawerPopupDataAttributes["swipeDirection"] = "data-swipe-direction";
|
|
562
|
-
/**
|
|
563
|
-
* Present when the drawer is being swiped.
|
|
564
|
-
*/
|
|
565
|
-
DrawerPopupDataAttributes["swiping"] = "data-swiping";
|
|
566
|
-
return DrawerPopupDataAttributes;
|
|
567
|
-
}({});
|
|
568
|
-
|
|
569
397
|
const DialogPortalContext = /*#__PURE__*/React.createContext(undefined);
|
|
570
398
|
if (process.env.NODE_ENV !== "production") DialogPortalContext.displayName = "DialogPortalContext";
|
|
571
399
|
function useDialogPortalContext() {
|
|
@@ -576,77 +404,598 @@ function useDialogPortalContext() {
|
|
|
576
404
|
return value;
|
|
577
405
|
}
|
|
578
406
|
|
|
579
|
-
const
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const END = 'End';
|
|
585
|
-
const HORIZONTAL_KEYS = new Set([ARROW_LEFT, ARROW_RIGHT]);
|
|
586
|
-
const VERTICAL_KEYS = new Set([ARROW_UP, ARROW_DOWN]);
|
|
587
|
-
const ARROW_KEYS = new Set([...HORIZONTAL_KEYS, ...VERTICAL_KEYS]);
|
|
588
|
-
new Set([...ARROW_KEYS, HOME, END]);
|
|
589
|
-
const COMPOSITE_KEYS = new Set([ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, HOME, END]);
|
|
590
|
-
|
|
591
|
-
const DrawerRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
592
|
-
if (process.env.NODE_ENV !== "production") DrawerRootContext.displayName = "DrawerRootContext";
|
|
593
|
-
function useDrawerRootContext(optional) {
|
|
594
|
-
const drawerRootContext = React.useContext(DrawerRootContext);
|
|
595
|
-
if (optional === false && drawerRootContext === undefined) {
|
|
596
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: DrawerRootContext is missing. Drawer parts must be placed within <Drawer.Root>.' : formatErrorMessage(90));
|
|
597
|
-
}
|
|
598
|
-
return drawerRootContext;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
function resolveSnapPointValue(snapPoint, viewportHeight, rootFontSize) {
|
|
602
|
-
if (!Number.isFinite(viewportHeight) || viewportHeight <= 0) {
|
|
603
|
-
return null;
|
|
604
|
-
}
|
|
605
|
-
if (typeof snapPoint === 'number') {
|
|
606
|
-
if (!Number.isFinite(snapPoint)) {
|
|
607
|
-
return null;
|
|
608
|
-
}
|
|
609
|
-
if (snapPoint <= 1) {
|
|
610
|
-
return clamp(snapPoint, 0, 1) * viewportHeight;
|
|
611
|
-
}
|
|
612
|
-
return snapPoint;
|
|
613
|
-
}
|
|
614
|
-
const trimmed = snapPoint.trim();
|
|
615
|
-
if (trimmed.endsWith('px')) {
|
|
616
|
-
const value = Number.parseFloat(trimmed);
|
|
617
|
-
return Number.isFinite(value) ? value : null;
|
|
618
|
-
}
|
|
619
|
-
if (trimmed.endsWith('rem')) {
|
|
620
|
-
const value = Number.parseFloat(trimmed);
|
|
621
|
-
return Number.isFinite(value) ? value * rootFontSize : null;
|
|
622
|
-
}
|
|
623
|
-
return null;
|
|
624
|
-
}
|
|
625
|
-
function findClosestSnapPoint(height, points) {
|
|
626
|
-
let closest = null;
|
|
627
|
-
let closestDistance = Infinity;
|
|
628
|
-
for (const point of points) {
|
|
629
|
-
const distance = Math.abs(point.height - height);
|
|
630
|
-
if (distance < closestDistance) {
|
|
631
|
-
closestDistance = distance;
|
|
632
|
-
closest = point;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
return closest;
|
|
636
|
-
}
|
|
637
|
-
function useDrawerSnapPoints() {
|
|
407
|
+
const DialogPortal = /*#__PURE__*/React.forwardRef(function DialogPortal(props, forwardedRef) {
|
|
408
|
+
const {
|
|
409
|
+
keepMounted = false,
|
|
410
|
+
...portalProps
|
|
411
|
+
} = props;
|
|
638
412
|
const {
|
|
639
413
|
store
|
|
640
414
|
} = useDialogRootContext();
|
|
415
|
+
const mounted = store.useState('mounted');
|
|
416
|
+
const modal = store.useState('modal');
|
|
417
|
+
const open = store.useState('open');
|
|
418
|
+
const shouldRender = mounted || keepMounted;
|
|
419
|
+
if (!shouldRender) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
return /*#__PURE__*/jsx(DialogPortalContext.Provider, {
|
|
423
|
+
value: keepMounted,
|
|
424
|
+
children: /*#__PURE__*/jsxs(FloatingPortal, {
|
|
425
|
+
ref: forwardedRef,
|
|
426
|
+
...portalProps,
|
|
427
|
+
children: [mounted && modal === true && /*#__PURE__*/jsx(InternalBackdrop, {
|
|
428
|
+
ref: store.context.internalBackdropRef,
|
|
429
|
+
inert: inertValue(!open)
|
|
430
|
+
}), props.children]
|
|
431
|
+
})
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
if (process.env.NODE_ENV !== "production") DialogPortal.displayName = "DialogPortal";
|
|
435
|
+
|
|
436
|
+
function useDialogRoot(params) {
|
|
641
437
|
const {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
const
|
|
648
|
-
const
|
|
649
|
-
const
|
|
438
|
+
store,
|
|
439
|
+
parentContext,
|
|
440
|
+
actionsRef
|
|
441
|
+
} = params;
|
|
442
|
+
const open = store.useState('open');
|
|
443
|
+
const disablePointerDismissal = store.useState('disablePointerDismissal');
|
|
444
|
+
const modal = store.useState('modal');
|
|
445
|
+
const popupElement = store.useState('popupElement');
|
|
446
|
+
const {
|
|
447
|
+
openMethod,
|
|
448
|
+
triggerProps
|
|
449
|
+
} = useOpenInteractionType(open);
|
|
450
|
+
useImplicitActiveTrigger(store);
|
|
451
|
+
const {
|
|
452
|
+
forceUnmount
|
|
453
|
+
} = useOpenStateTransitions(open, store);
|
|
454
|
+
const createDialogEventDetails = useStableCallback(reason => {
|
|
455
|
+
const details = createChangeEventDetails(reason);
|
|
456
|
+
details.preventUnmountOnClose = () => {
|
|
457
|
+
store.set('preventUnmountingOnClose', true);
|
|
458
|
+
};
|
|
459
|
+
return details;
|
|
460
|
+
});
|
|
461
|
+
const handleImperativeClose = React.useCallback(() => {
|
|
462
|
+
store.setOpen(false, createDialogEventDetails(imperativeAction));
|
|
463
|
+
}, [store, createDialogEventDetails]);
|
|
464
|
+
React.useImperativeHandle(actionsRef, () => ({
|
|
465
|
+
unmount: forceUnmount,
|
|
466
|
+
close: handleImperativeClose
|
|
467
|
+
}), [forceUnmount, handleImperativeClose]);
|
|
468
|
+
const floatingRootContext = useSyncedFloatingRootContext({
|
|
469
|
+
popupStore: store,
|
|
470
|
+
onOpenChange: store.setOpen,
|
|
471
|
+
treatPopupAsFloatingElement: true,
|
|
472
|
+
noEmit: true
|
|
473
|
+
});
|
|
474
|
+
const [ownNestedOpenDialogs, setOwnNestedOpenDialogs] = React.useState(0);
|
|
475
|
+
const isTopmost = ownNestedOpenDialogs === 0;
|
|
476
|
+
const role = useRole(floatingRootContext);
|
|
477
|
+
const dismiss = useDismiss(floatingRootContext, {
|
|
478
|
+
outsidePressEvent() {
|
|
479
|
+
if (store.context.internalBackdropRef.current || store.context.backdropRef.current) {
|
|
480
|
+
return 'intentional';
|
|
481
|
+
}
|
|
482
|
+
// Ensure `aria-hidden` on outside elements is removed immediately
|
|
483
|
+
// on outside press when trapping focus.
|
|
484
|
+
return {
|
|
485
|
+
mouse: modal === 'trap-focus' ? 'sloppy' : 'intentional',
|
|
486
|
+
touch: 'sloppy'
|
|
487
|
+
};
|
|
488
|
+
},
|
|
489
|
+
outsidePress(event) {
|
|
490
|
+
if (!store.context.outsidePressEnabledRef.current) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// For mouse events, only accept left button (button 0)
|
|
495
|
+
// For touch events, a single touch is equivalent to left button
|
|
496
|
+
if ('button' in event && event.button !== 0) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
if ('touches' in event && event.touches.length !== 1) {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
const target = getTarget(event);
|
|
503
|
+
if (isTopmost && !disablePointerDismissal) {
|
|
504
|
+
const eventTarget = target;
|
|
505
|
+
// Only close if the click occurred on the dialog's owning backdrop.
|
|
506
|
+
// This supports multiple modal dialogs that aren't nested in the React tree:
|
|
507
|
+
// https://github.com/mui/base-ui/issues/1320
|
|
508
|
+
if (modal) {
|
|
509
|
+
return store.context.internalBackdropRef.current || store.context.backdropRef.current ? store.context.internalBackdropRef.current === eventTarget || store.context.backdropRef.current === eventTarget || contains(eventTarget, popupElement) && !eventTarget?.hasAttribute('data-base-ui-portal') : true;
|
|
510
|
+
}
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
return false;
|
|
514
|
+
},
|
|
515
|
+
escapeKey: isTopmost
|
|
516
|
+
});
|
|
517
|
+
useScrollLock(open && modal === true, popupElement);
|
|
518
|
+
const {
|
|
519
|
+
getReferenceProps,
|
|
520
|
+
getFloatingProps,
|
|
521
|
+
getTriggerProps
|
|
522
|
+
} = useInteractions([role, dismiss]);
|
|
523
|
+
|
|
524
|
+
// Listen for nested open/close events on this store to maintain the count
|
|
525
|
+
store.useContextCallback('onNestedDialogOpen', ownChildrenCount => {
|
|
526
|
+
setOwnNestedOpenDialogs(ownChildrenCount + 1);
|
|
527
|
+
});
|
|
528
|
+
store.useContextCallback('onNestedDialogClose', () => {
|
|
529
|
+
setOwnNestedOpenDialogs(0);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// Notify parent of our open/close state using parent callbacks, if any
|
|
533
|
+
React.useEffect(() => {
|
|
534
|
+
if (parentContext?.onNestedDialogOpen && open) {
|
|
535
|
+
parentContext.onNestedDialogOpen(ownNestedOpenDialogs);
|
|
536
|
+
}
|
|
537
|
+
if (parentContext?.onNestedDialogClose && !open) {
|
|
538
|
+
parentContext.onNestedDialogClose();
|
|
539
|
+
}
|
|
540
|
+
return () => {
|
|
541
|
+
if (parentContext?.onNestedDialogClose && open) {
|
|
542
|
+
parentContext.onNestedDialogClose();
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
}, [open, parentContext, ownNestedOpenDialogs]);
|
|
546
|
+
const activeTriggerProps = React.useMemo(() => getReferenceProps(triggerProps), [getReferenceProps, triggerProps]);
|
|
547
|
+
const inactiveTriggerProps = React.useMemo(() => getTriggerProps(triggerProps), [getTriggerProps, triggerProps]);
|
|
548
|
+
const popupProps = React.useMemo(() => getFloatingProps(), [getFloatingProps]);
|
|
549
|
+
store.useSyncedValues({
|
|
550
|
+
openMethod,
|
|
551
|
+
activeTriggerProps,
|
|
552
|
+
inactiveTriggerProps,
|
|
553
|
+
popupProps,
|
|
554
|
+
floatingRootContext,
|
|
555
|
+
nestedOpenDialogCount: ownNestedOpenDialogs
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const selectors = {
|
|
560
|
+
...popupStoreSelectors,
|
|
561
|
+
modal: createSelector(state => state.modal),
|
|
562
|
+
nested: createSelector(state => state.nested),
|
|
563
|
+
nestedOpenDialogCount: createSelector(state => state.nestedOpenDialogCount),
|
|
564
|
+
disablePointerDismissal: createSelector(state => state.disablePointerDismissal),
|
|
565
|
+
openMethod: createSelector(state => state.openMethod),
|
|
566
|
+
descriptionElementId: createSelector(state => state.descriptionElementId),
|
|
567
|
+
titleElementId: createSelector(state => state.titleElementId),
|
|
568
|
+
viewportElement: createSelector(state => state.viewportElement),
|
|
569
|
+
role: createSelector(state => state.role)
|
|
570
|
+
};
|
|
571
|
+
class DialogStore extends ReactStore {
|
|
572
|
+
constructor(initialState) {
|
|
573
|
+
super(createInitialState(initialState), {
|
|
574
|
+
popupRef: /*#__PURE__*/React.createRef(),
|
|
575
|
+
backdropRef: /*#__PURE__*/React.createRef(),
|
|
576
|
+
internalBackdropRef: /*#__PURE__*/React.createRef(),
|
|
577
|
+
outsidePressEnabledRef: {
|
|
578
|
+
current: true
|
|
579
|
+
},
|
|
580
|
+
triggerElements: new PopupTriggerMap(),
|
|
581
|
+
onOpenChange: undefined,
|
|
582
|
+
onOpenChangeComplete: undefined
|
|
583
|
+
}, selectors);
|
|
584
|
+
}
|
|
585
|
+
setOpen = (nextOpen, eventDetails) => {
|
|
586
|
+
eventDetails.preventUnmountOnClose = () => {
|
|
587
|
+
this.set('preventUnmountingOnClose', true);
|
|
588
|
+
};
|
|
589
|
+
if (!nextOpen && eventDetails.trigger == null && this.state.activeTriggerId != null) {
|
|
590
|
+
// When closing the dialog, pass the old trigger to the onOpenChange event
|
|
591
|
+
// so it's not reset too early (potentially causing focus issues in controlled scenarios).
|
|
592
|
+
eventDetails.trigger = this.state.activeTriggerElement ?? undefined;
|
|
593
|
+
}
|
|
594
|
+
this.context.onOpenChange?.(nextOpen, eventDetails);
|
|
595
|
+
if (eventDetails.isCanceled) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const details = {
|
|
599
|
+
open: nextOpen,
|
|
600
|
+
nativeEvent: eventDetails.event,
|
|
601
|
+
reason: eventDetails.reason,
|
|
602
|
+
nested: this.state.nested
|
|
603
|
+
};
|
|
604
|
+
this.state.floatingRootContext.context.events?.emit('openchange', details);
|
|
605
|
+
const updatedState = {
|
|
606
|
+
open: nextOpen
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// If a popup is closing, the `trigger` may be null.
|
|
610
|
+
// We want to keep the previous value so that exit animations are played and focus is returned correctly.
|
|
611
|
+
const newTriggerId = eventDetails.trigger?.id ?? null;
|
|
612
|
+
if (newTriggerId || nextOpen) {
|
|
613
|
+
updatedState.activeTriggerId = newTriggerId;
|
|
614
|
+
updatedState.activeTriggerElement = eventDetails.trigger ?? null;
|
|
615
|
+
}
|
|
616
|
+
this.update(updatedState);
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function createInitialState(initialState = {}) {
|
|
620
|
+
return {
|
|
621
|
+
...createInitialPopupStoreState(),
|
|
622
|
+
modal: true,
|
|
623
|
+
disablePointerDismissal: false,
|
|
624
|
+
popupElement: null,
|
|
625
|
+
viewportElement: null,
|
|
626
|
+
descriptionElementId: undefined,
|
|
627
|
+
titleElementId: undefined,
|
|
628
|
+
openMethod: null,
|
|
629
|
+
nested: false,
|
|
630
|
+
nestedOpenDialogCount: 0,
|
|
631
|
+
role: 'dialog',
|
|
632
|
+
...initialState
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Groups all parts of the dialog.
|
|
638
|
+
* Doesn’t render its own HTML element.
|
|
639
|
+
*
|
|
640
|
+
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
641
|
+
*/
|
|
642
|
+
function DialogRoot(props) {
|
|
643
|
+
const {
|
|
644
|
+
children,
|
|
645
|
+
open: openProp,
|
|
646
|
+
defaultOpen = false,
|
|
647
|
+
onOpenChange,
|
|
648
|
+
onOpenChangeComplete,
|
|
649
|
+
disablePointerDismissal = false,
|
|
650
|
+
modal = true,
|
|
651
|
+
actionsRef,
|
|
652
|
+
handle,
|
|
653
|
+
triggerId: triggerIdProp,
|
|
654
|
+
defaultTriggerId: defaultTriggerIdProp = null
|
|
655
|
+
} = props;
|
|
656
|
+
const parentDialogRootContext = useDialogRootContext(true);
|
|
657
|
+
const nested = Boolean(parentDialogRootContext);
|
|
658
|
+
const store = useRefWithInit(() => {
|
|
659
|
+
return handle?.store ?? new DialogStore({
|
|
660
|
+
open: defaultOpen,
|
|
661
|
+
openProp,
|
|
662
|
+
activeTriggerId: defaultTriggerIdProp,
|
|
663
|
+
triggerIdProp,
|
|
664
|
+
modal,
|
|
665
|
+
disablePointerDismissal,
|
|
666
|
+
nested
|
|
667
|
+
});
|
|
668
|
+
}).current;
|
|
669
|
+
|
|
670
|
+
// Support initially open state when uncontrolled
|
|
671
|
+
useOnFirstRender(() => {
|
|
672
|
+
if (openProp === undefined && store.state.open === false && defaultOpen === true) {
|
|
673
|
+
store.update({
|
|
674
|
+
open: true,
|
|
675
|
+
activeTriggerId: defaultTriggerIdProp
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
store.useControlledProp('openProp', openProp);
|
|
680
|
+
store.useControlledProp('triggerIdProp', triggerIdProp);
|
|
681
|
+
store.useSyncedValues({
|
|
682
|
+
disablePointerDismissal,
|
|
683
|
+
nested,
|
|
684
|
+
modal
|
|
685
|
+
});
|
|
686
|
+
store.useContextCallback('onOpenChange', onOpenChange);
|
|
687
|
+
store.useContextCallback('onOpenChangeComplete', onOpenChangeComplete);
|
|
688
|
+
const payload = store.useState('payload');
|
|
689
|
+
useDialogRoot({
|
|
690
|
+
store,
|
|
691
|
+
actionsRef,
|
|
692
|
+
parentContext: parentDialogRootContext?.store.context,
|
|
693
|
+
onOpenChange,
|
|
694
|
+
triggerIdProp
|
|
695
|
+
});
|
|
696
|
+
const contextValue = React.useMemo(() => ({
|
|
697
|
+
store
|
|
698
|
+
}), [store]);
|
|
699
|
+
return /*#__PURE__*/jsx(DialogRootContext.Provider, {
|
|
700
|
+
value: contextValue,
|
|
701
|
+
children: typeof children === 'function' ? children({
|
|
702
|
+
payload
|
|
703
|
+
}) : children
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* A button that opens the dialog.
|
|
709
|
+
* Renders a `<button>` element.
|
|
710
|
+
*
|
|
711
|
+
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
712
|
+
*/
|
|
713
|
+
const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(componentProps, forwardedRef) {
|
|
714
|
+
const {
|
|
715
|
+
render,
|
|
716
|
+
className,
|
|
717
|
+
disabled = false,
|
|
718
|
+
nativeButton = true,
|
|
719
|
+
id: idProp,
|
|
720
|
+
payload,
|
|
721
|
+
handle,
|
|
722
|
+
...elementProps
|
|
723
|
+
} = componentProps;
|
|
724
|
+
const dialogRootContext = useDialogRootContext(true);
|
|
725
|
+
const store = handle?.store ?? dialogRootContext?.store;
|
|
726
|
+
if (!store) {
|
|
727
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Trigger> must be used within <Dialog.Root> or provided with a handle.' : formatErrorMessage(79));
|
|
728
|
+
}
|
|
729
|
+
const thisTriggerId = useBaseUiId(idProp);
|
|
730
|
+
const floatingContext = store.useState('floatingRootContext');
|
|
731
|
+
const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
|
|
732
|
+
const triggerElementRef = React.useRef(null);
|
|
733
|
+
const {
|
|
734
|
+
registerTrigger,
|
|
735
|
+
isMountedByThisTrigger
|
|
736
|
+
} = useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
|
|
737
|
+
payload
|
|
738
|
+
});
|
|
739
|
+
const {
|
|
740
|
+
getButtonProps,
|
|
741
|
+
buttonRef
|
|
742
|
+
} = useButton({
|
|
743
|
+
disabled,
|
|
744
|
+
native: nativeButton
|
|
745
|
+
});
|
|
746
|
+
const click = useClick(floatingContext, {
|
|
747
|
+
enabled: floatingContext != null
|
|
748
|
+
});
|
|
749
|
+
const localInteractionProps = useInteractions([click]);
|
|
750
|
+
const state = {
|
|
751
|
+
disabled,
|
|
752
|
+
open: isOpenedByThisTrigger
|
|
753
|
+
};
|
|
754
|
+
const rootTriggerProps = store.useState('triggerProps', isMountedByThisTrigger);
|
|
755
|
+
return useRenderElement('button', componentProps, {
|
|
756
|
+
state,
|
|
757
|
+
ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
|
|
758
|
+
props: [localInteractionProps.getReferenceProps(), rootTriggerProps, {
|
|
759
|
+
[CLICK_TRIGGER_IDENTIFIER]: '',
|
|
760
|
+
id: thisTriggerId
|
|
761
|
+
}, elementProps, getButtonProps],
|
|
762
|
+
stateAttributesMapping: triggerOpenStateMapping
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
if (process.env.NODE_ENV !== "production") DialogTrigger.displayName = "DialogTrigger";
|
|
766
|
+
|
|
767
|
+
let DrawerPopupCssVars = /*#__PURE__*/function (DrawerPopupCssVars) {
|
|
768
|
+
/**
|
|
769
|
+
* The number of nested drawers that are currently open.
|
|
770
|
+
* @type {number}
|
|
771
|
+
*/
|
|
772
|
+
DrawerPopupCssVars["nestedDrawers"] = "--nested-drawers";
|
|
773
|
+
/**
|
|
774
|
+
* The height of the drawer popup.
|
|
775
|
+
* @type {CSS length}
|
|
776
|
+
*/
|
|
777
|
+
DrawerPopupCssVars["height"] = "--drawer-height";
|
|
778
|
+
/**
|
|
779
|
+
* The height of the frontmost open drawer in the current nested drawer stack.
|
|
780
|
+
* @type {CSS length}
|
|
781
|
+
*/
|
|
782
|
+
DrawerPopupCssVars["frontmostHeight"] = "--drawer-frontmost-height";
|
|
783
|
+
/**
|
|
784
|
+
* The swipe movement on the X axis.
|
|
785
|
+
* @type {CSS length}
|
|
786
|
+
*/
|
|
787
|
+
DrawerPopupCssVars["swipeMovementX"] = "--drawer-swipe-movement-x";
|
|
788
|
+
/**
|
|
789
|
+
* The swipe movement on the Y axis.
|
|
790
|
+
* @type {CSS length}
|
|
791
|
+
*/
|
|
792
|
+
DrawerPopupCssVars["swipeMovementY"] = "--drawer-swipe-movement-y";
|
|
793
|
+
/**
|
|
794
|
+
* The snap point offset used for translating the drawer.
|
|
795
|
+
* @type {CSS length}
|
|
796
|
+
*/
|
|
797
|
+
DrawerPopupCssVars["snapPointOffset"] = "--drawer-snap-point-offset";
|
|
798
|
+
/**
|
|
799
|
+
* A scalar (0.1-1) used to scale the swipe release transition duration in CSS.
|
|
800
|
+
* @type {number}
|
|
801
|
+
*/
|
|
802
|
+
DrawerPopupCssVars["swipeStrength"] = "--drawer-swipe-strength";
|
|
803
|
+
return DrawerPopupCssVars;
|
|
804
|
+
}({});
|
|
805
|
+
|
|
806
|
+
let DrawerBackdropCssVars = /*#__PURE__*/function (DrawerBackdropCssVars) {
|
|
807
|
+
/**
|
|
808
|
+
* The swipe progress of the drawer gesture.
|
|
809
|
+
* @type {number}
|
|
810
|
+
*/
|
|
811
|
+
DrawerBackdropCssVars["swipeProgress"] = "--drawer-swipe-progress";
|
|
812
|
+
return DrawerBackdropCssVars;
|
|
813
|
+
}({});
|
|
814
|
+
|
|
815
|
+
const stateAttributesMapping$1 = {
|
|
816
|
+
...popupStateMapping,
|
|
817
|
+
...transitionStatusMapping
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* An overlay displayed beneath the popup.
|
|
822
|
+
* Renders a `<div>` element.
|
|
823
|
+
*
|
|
824
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
825
|
+
*/
|
|
826
|
+
const DrawerBackdrop = /*#__PURE__*/React.forwardRef(function DrawerBackdrop(componentProps, forwardedRef) {
|
|
827
|
+
const {
|
|
828
|
+
render,
|
|
829
|
+
className,
|
|
830
|
+
forceRender = false,
|
|
831
|
+
...elementProps
|
|
832
|
+
} = componentProps;
|
|
833
|
+
const {
|
|
834
|
+
store
|
|
835
|
+
} = useDialogRootContext();
|
|
836
|
+
const open = store.useState('open');
|
|
837
|
+
const nested = store.useState('nested');
|
|
838
|
+
const mounted = store.useState('mounted');
|
|
839
|
+
const transitionStatus = store.useState('transitionStatus');
|
|
840
|
+
const state = {
|
|
841
|
+
open,
|
|
842
|
+
transitionStatus
|
|
843
|
+
};
|
|
844
|
+
return useRenderElement('div', componentProps, {
|
|
845
|
+
state,
|
|
846
|
+
ref: [store.context.backdropRef, forwardedRef],
|
|
847
|
+
stateAttributesMapping: stateAttributesMapping$1,
|
|
848
|
+
props: [{
|
|
849
|
+
role: 'presentation',
|
|
850
|
+
hidden: !mounted,
|
|
851
|
+
style: {
|
|
852
|
+
pointerEvents: !open ? 'none' : undefined,
|
|
853
|
+
userSelect: 'none',
|
|
854
|
+
WebkitUserSelect: 'none',
|
|
855
|
+
[DrawerBackdropCssVars.swipeProgress]: '0',
|
|
856
|
+
[DrawerPopupCssVars.swipeStrength]: '1'
|
|
857
|
+
}
|
|
858
|
+
}, elementProps],
|
|
859
|
+
enabled: forceRender || !nested
|
|
860
|
+
});
|
|
861
|
+
});
|
|
862
|
+
if (process.env.NODE_ENV !== "production") DrawerBackdrop.displayName = "DrawerBackdrop";
|
|
863
|
+
|
|
864
|
+
const DRAWER_CONTENT_ATTRIBUTE = 'data-drawer-content';
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* A container for the drawer contents.
|
|
868
|
+
* Renders a `<div>` element.
|
|
869
|
+
*
|
|
870
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
871
|
+
*/
|
|
872
|
+
const DrawerContent = /*#__PURE__*/React.forwardRef(function DrawerContent(componentProps, forwardedRef) {
|
|
873
|
+
const {
|
|
874
|
+
render,
|
|
875
|
+
className,
|
|
876
|
+
...elementProps
|
|
877
|
+
} = componentProps;
|
|
878
|
+
useDialogRootContext();
|
|
879
|
+
return useRenderElement('div', componentProps, {
|
|
880
|
+
ref: forwardedRef,
|
|
881
|
+
props: [{
|
|
882
|
+
[DRAWER_CONTENT_ATTRIBUTE]: ''
|
|
883
|
+
}, elementProps]
|
|
884
|
+
});
|
|
885
|
+
});
|
|
886
|
+
if (process.env.NODE_ENV !== "production") DrawerContent.displayName = "DrawerContent";
|
|
887
|
+
|
|
888
|
+
const DrawerProviderContext = /*#__PURE__*/React.createContext(undefined);
|
|
889
|
+
if (process.env.NODE_ENV !== "production") DrawerProviderContext.displayName = "DrawerProviderContext";
|
|
890
|
+
function useDrawerProviderContext(optional) {
|
|
891
|
+
const context = React.useContext(DrawerProviderContext);
|
|
892
|
+
return context;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
let DrawerPopupDataAttributes = function (DrawerPopupDataAttributes) {
|
|
896
|
+
/**
|
|
897
|
+
* Present when the drawer is open.
|
|
898
|
+
*/
|
|
899
|
+
DrawerPopupDataAttributes[DrawerPopupDataAttributes["open"] = CommonPopupDataAttributes.open] = "open";
|
|
900
|
+
/**
|
|
901
|
+
* Present when the drawer is closed.
|
|
902
|
+
*/
|
|
903
|
+
DrawerPopupDataAttributes[DrawerPopupDataAttributes["closed"] = CommonPopupDataAttributes.closed] = "closed";
|
|
904
|
+
/**
|
|
905
|
+
* Present when the drawer is animating in.
|
|
906
|
+
*/
|
|
907
|
+
DrawerPopupDataAttributes[DrawerPopupDataAttributes["startingStyle"] = CommonPopupDataAttributes.startingStyle] = "startingStyle";
|
|
908
|
+
/**
|
|
909
|
+
* Present when the drawer is animating out.
|
|
910
|
+
*/
|
|
911
|
+
DrawerPopupDataAttributes[DrawerPopupDataAttributes["endingStyle"] = CommonPopupDataAttributes.endingStyle] = "endingStyle";
|
|
912
|
+
/**
|
|
913
|
+
* Present when the drawer is at the expanded (full-height) snap point.
|
|
914
|
+
*/
|
|
915
|
+
DrawerPopupDataAttributes["expanded"] = "data-expanded";
|
|
916
|
+
/**
|
|
917
|
+
* Present when a nested drawer is open.
|
|
918
|
+
*/
|
|
919
|
+
DrawerPopupDataAttributes["nestedDrawerOpen"] = "data-nested-drawer-open";
|
|
920
|
+
/**
|
|
921
|
+
* Present when a nested drawer is being swiped.
|
|
922
|
+
*/
|
|
923
|
+
DrawerPopupDataAttributes["nestedDrawerSwiping"] = "data-nested-drawer-swiping";
|
|
924
|
+
/**
|
|
925
|
+
* Present when the drawer is dismissed by swiping.
|
|
926
|
+
*/
|
|
927
|
+
DrawerPopupDataAttributes["swipeDismiss"] = "data-swipe-dismiss";
|
|
928
|
+
/**
|
|
929
|
+
* Indicates the swipe direction.
|
|
930
|
+
* @type {'up' | 'down' | 'left' | 'right'}
|
|
931
|
+
*/
|
|
932
|
+
DrawerPopupDataAttributes["swipeDirection"] = "data-swipe-direction";
|
|
933
|
+
/**
|
|
934
|
+
* Present when the drawer is being swiped.
|
|
935
|
+
*/
|
|
936
|
+
DrawerPopupDataAttributes["swiping"] = "data-swiping";
|
|
937
|
+
return DrawerPopupDataAttributes;
|
|
938
|
+
}({});
|
|
939
|
+
|
|
940
|
+
const DrawerRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
941
|
+
if (process.env.NODE_ENV !== "production") DrawerRootContext.displayName = "DrawerRootContext";
|
|
942
|
+
function useDrawerRootContext(optional) {
|
|
943
|
+
const drawerRootContext = React.useContext(DrawerRootContext);
|
|
944
|
+
if (optional === false && drawerRootContext === undefined) {
|
|
945
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: DrawerRootContext is missing. Drawer parts must be placed within <Drawer.Root>.' : formatErrorMessage(90));
|
|
946
|
+
}
|
|
947
|
+
return drawerRootContext;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
function resolveSnapPointValue(snapPoint, viewportHeight, rootFontSize) {
|
|
951
|
+
if (!Number.isFinite(viewportHeight) || viewportHeight <= 0) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
if (typeof snapPoint === 'number') {
|
|
955
|
+
if (!Number.isFinite(snapPoint)) {
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
if (snapPoint <= 1) {
|
|
959
|
+
return clamp(snapPoint, 0, 1) * viewportHeight;
|
|
960
|
+
}
|
|
961
|
+
return snapPoint;
|
|
962
|
+
}
|
|
963
|
+
const trimmed = snapPoint.trim();
|
|
964
|
+
if (trimmed.endsWith('px')) {
|
|
965
|
+
const value = Number.parseFloat(trimmed);
|
|
966
|
+
return Number.isFinite(value) ? value : null;
|
|
967
|
+
}
|
|
968
|
+
if (trimmed.endsWith('rem')) {
|
|
969
|
+
const value = Number.parseFloat(trimmed);
|
|
970
|
+
return Number.isFinite(value) ? value * rootFontSize : null;
|
|
971
|
+
}
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
974
|
+
function findClosestSnapPoint(height, points) {
|
|
975
|
+
let closest = null;
|
|
976
|
+
let closestDistance = Infinity;
|
|
977
|
+
for (const point of points) {
|
|
978
|
+
const distance = Math.abs(point.height - height);
|
|
979
|
+
if (distance < closestDistance) {
|
|
980
|
+
closestDistance = distance;
|
|
981
|
+
closest = point;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
return closest;
|
|
985
|
+
}
|
|
986
|
+
function useDrawerSnapPoints() {
|
|
987
|
+
const {
|
|
988
|
+
store
|
|
989
|
+
} = useDialogRootContext();
|
|
990
|
+
const {
|
|
991
|
+
snapPoints,
|
|
992
|
+
activeSnapPoint,
|
|
993
|
+
setActiveSnapPoint,
|
|
994
|
+
popupHeight
|
|
995
|
+
} = useDrawerRootContext();
|
|
996
|
+
const viewportElement = store.useState('viewportElement');
|
|
997
|
+
const [viewportHeight, setViewportHeight] = React.useState(0);
|
|
998
|
+
const [rootFontSize, setRootFontSize] = React.useState(16);
|
|
650
999
|
const measureViewportHeight = useStableCallback(() => {
|
|
651
1000
|
const doc = ownerDocument(viewportElement);
|
|
652
1001
|
const html = doc.documentElement;
|
|
@@ -716,724 +1065,364 @@ function useDrawerSnapPoints() {
|
|
|
716
1065
|
if (activeSnapPoint === null) {
|
|
717
1066
|
return undefined;
|
|
718
1067
|
}
|
|
719
|
-
const exactMatch = resolvedSnapPoints.find(point => Object.is(point.value, activeSnapPoint));
|
|
720
|
-
if (exactMatch) {
|
|
721
|
-
return exactMatch;
|
|
722
|
-
}
|
|
723
|
-
const maxHeight = Math.min(popupHeight, viewportHeight);
|
|
724
|
-
const resolvedHeight = resolveSnapPointValue(activeSnapPoint, viewportHeight, rootFontSize);
|
|
725
|
-
if (resolvedHeight === null || !Number.isFinite(resolvedHeight)) {
|
|
726
|
-
return undefined;
|
|
727
|
-
}
|
|
728
|
-
const clampedHeight = clamp(resolvedHeight, 0, maxHeight);
|
|
729
|
-
return findClosestSnapPoint(clampedHeight, resolvedSnapPoints) ?? undefined;
|
|
730
|
-
}, [activeSnapPoint, popupHeight, resolvedSnapPoints, rootFontSize, viewportHeight]);
|
|
731
|
-
return {
|
|
732
|
-
snapPoints,
|
|
733
|
-
activeSnapPoint,
|
|
734
|
-
setActiveSnapPoint,
|
|
735
|
-
popupHeight,
|
|
736
|
-
viewportHeight,
|
|
737
|
-
resolvedSnapPoints,
|
|
738
|
-
activeSnapPointOffset: resolvedActiveSnapPoint?.offset ?? null
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
const DrawerViewportContext = /*#__PURE__*/React.createContext(null);
|
|
743
|
-
if (process.env.NODE_ENV !== "production") DrawerViewportContext.displayName = "DrawerViewportContext";
|
|
744
|
-
function useDrawerViewportContext(optional) {
|
|
745
|
-
const context = React.useContext(DrawerViewportContext);
|
|
746
|
-
return context;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
let drawerSwipeVarsRegistered = false;
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* Removes inheritance of high-frequency drawer swipe CSS variables, which
|
|
753
|
-
* reduces style recalculation cost in complex drawers with deep subtrees.
|
|
754
|
-
* Child elements that need these values can still opt-in by using `inherit`.
|
|
755
|
-
* See https://motion.dev/blog/web-animation-performance-tier-list
|
|
756
|
-
* under the "Improving CSS variable performance" section.
|
|
757
|
-
*/
|
|
758
|
-
function removeCSSVariableInheritance$1() {
|
|
759
|
-
if (drawerSwipeVarsRegistered) {
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
// Intentionally keep inheritance disabled on WebKit as well. Safari doesn't support
|
|
764
|
-
// opting descendants back in via `--var: inherit` for custom properties registered
|
|
765
|
-
// with `inherits: false`, but Drawer does not rely on descendant access to these vars
|
|
766
|
-
// (unlike ScrollArea), so we keep the performance optimization enabled.
|
|
767
|
-
if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
|
|
768
|
-
[DrawerPopupCssVars.swipeMovementX, DrawerPopupCssVars.swipeMovementY, DrawerPopupCssVars.snapPointOffset].forEach(name => {
|
|
769
|
-
try {
|
|
770
|
-
CSS.registerProperty({
|
|
771
|
-
name,
|
|
772
|
-
syntax: '<length>',
|
|
773
|
-
inherits: false,
|
|
774
|
-
initialValue: '0px'
|
|
775
|
-
});
|
|
776
|
-
} catch {
|
|
777
|
-
/* ignore already-registered */
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
[{
|
|
781
|
-
name: DrawerBackdropCssVars.swipeProgress,
|
|
782
|
-
initialValue: '0'
|
|
783
|
-
}, {
|
|
784
|
-
name: DrawerPopupCssVars.swipeStrength,
|
|
785
|
-
initialValue: '1'
|
|
786
|
-
}].forEach(({
|
|
787
|
-
name,
|
|
788
|
-
initialValue
|
|
789
|
-
}) => {
|
|
790
|
-
try {
|
|
791
|
-
CSS.registerProperty({
|
|
792
|
-
name,
|
|
793
|
-
syntax: '<number>',
|
|
794
|
-
inherits: false,
|
|
795
|
-
initialValue
|
|
796
|
-
});
|
|
797
|
-
} catch {
|
|
798
|
-
/* ignore already-registered */
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
drawerSwipeVarsRegistered = true;
|
|
803
|
-
}
|
|
804
|
-
const stateAttributesMapping = {
|
|
805
|
-
...popupStateMapping,
|
|
806
|
-
...transitionStatusMapping,
|
|
807
|
-
expanded(value) {
|
|
808
|
-
return value ? {
|
|
809
|
-
[DrawerPopupDataAttributes.expanded]: ''
|
|
810
|
-
} : null;
|
|
811
|
-
},
|
|
812
|
-
nestedDrawerOpen(value) {
|
|
813
|
-
return value ? {
|
|
814
|
-
[DrawerPopupDataAttributes.nestedDrawerOpen]: ''
|
|
815
|
-
} : null;
|
|
816
|
-
},
|
|
817
|
-
nestedDrawerSwiping(value) {
|
|
818
|
-
return value ? {
|
|
819
|
-
[DrawerPopupDataAttributes.nestedDrawerSwiping]: ''
|
|
820
|
-
} : null;
|
|
821
|
-
},
|
|
822
|
-
swipeDirection(value) {
|
|
823
|
-
return value ? {
|
|
824
|
-
[DrawerPopupDataAttributes.swipeDirection]: value
|
|
825
|
-
} : null;
|
|
826
|
-
},
|
|
827
|
-
swiping(value) {
|
|
828
|
-
return value ? {
|
|
829
|
-
[DrawerPopupDataAttributes.swiping]: ''
|
|
830
|
-
} : null;
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
|
|
834
|
-
/**
|
|
835
|
-
* A container for the drawer contents.
|
|
836
|
-
* Renders a `<div>` element.
|
|
837
|
-
*
|
|
838
|
-
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
839
|
-
*/
|
|
840
|
-
const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(componentProps, forwardedRef) {
|
|
841
|
-
const {
|
|
842
|
-
className,
|
|
843
|
-
finalFocus,
|
|
844
|
-
initialFocus,
|
|
845
|
-
render,
|
|
846
|
-
...elementProps
|
|
847
|
-
} = componentProps;
|
|
848
|
-
const {
|
|
849
|
-
store
|
|
850
|
-
} = useDialogRootContext();
|
|
851
|
-
const {
|
|
852
|
-
swipeDirection,
|
|
853
|
-
frontmostHeight,
|
|
854
|
-
hasNestedDrawer,
|
|
855
|
-
nestedSwiping,
|
|
856
|
-
nestedSwipeProgressStore,
|
|
857
|
-
onPopupHeightChange,
|
|
858
|
-
notifyParentFrontmostHeight,
|
|
859
|
-
notifyParentHasNestedDrawer
|
|
860
|
-
} = useDrawerRootContext();
|
|
861
|
-
const descriptionElementId = store.useState('descriptionElementId');
|
|
862
|
-
const disablePointerDismissal = store.useState('disablePointerDismissal');
|
|
863
|
-
const floatingRootContext = store.useState('floatingRootContext');
|
|
864
|
-
const rootPopupProps = store.useState('popupProps');
|
|
865
|
-
const modal = store.useState('modal');
|
|
866
|
-
const mounted = store.useState('mounted');
|
|
867
|
-
const nested = store.useState('nested');
|
|
868
|
-
const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
|
|
869
|
-
const transitionStatus = store.useState('transitionStatus');
|
|
870
|
-
const open = store.useState('open');
|
|
871
|
-
const openMethod = store.useState('openMethod');
|
|
872
|
-
const titleElementId = store.useState('titleElementId');
|
|
873
|
-
const role = store.useState('role');
|
|
874
|
-
const nestedDrawerOpen = nestedOpenDialogCount > 0;
|
|
875
|
-
const swipe = useDrawerViewportContext();
|
|
876
|
-
const swiping = swipe?.swiping ?? false;
|
|
877
|
-
const swipeStrength = swipe?.swipeStrength ?? null;
|
|
878
|
-
const {
|
|
879
|
-
snapPoints,
|
|
880
|
-
activeSnapPoint,
|
|
881
|
-
activeSnapPointOffset
|
|
882
|
-
} = useDrawerSnapPoints();
|
|
883
|
-
useDialogPortalContext();
|
|
884
|
-
const [popupHeight, setPopupHeight] = React.useState(0);
|
|
885
|
-
const popupHeightRef = React.useRef(0);
|
|
886
|
-
const measureHeight = useStableCallback(() => {
|
|
887
|
-
const popupElement = store.context.popupRef.current;
|
|
888
|
-
if (!popupElement) {
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
const offsetHeight = popupElement.offsetHeight;
|
|
892
|
-
|
|
893
|
-
// Only skip while the element is still actually stretched beyond its last measured height.
|
|
894
|
-
if (popupHeightRef.current > 0 && frontmostHeight > popupHeightRef.current && offsetHeight > popupHeightRef.current) {
|
|
895
|
-
return;
|
|
896
|
-
}
|
|
897
|
-
const keepHeightWhileNested = popupHeightRef.current > 0 && hasNestedDrawer;
|
|
898
|
-
if (keepHeightWhileNested) {
|
|
899
|
-
const oldHeight = popupHeightRef.current;
|
|
900
|
-
setPopupHeight(oldHeight);
|
|
901
|
-
onPopupHeightChange(oldHeight);
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
const nextHeight = offsetHeight;
|
|
905
|
-
if (nextHeight === popupHeightRef.current) {
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
popupHeightRef.current = nextHeight;
|
|
909
|
-
setPopupHeight(nextHeight);
|
|
910
|
-
onPopupHeightChange(nextHeight);
|
|
911
|
-
});
|
|
912
|
-
useIsoLayoutEffect(() => {
|
|
913
|
-
if (!mounted) {
|
|
914
|
-
popupHeightRef.current = 0;
|
|
915
|
-
setPopupHeight(0);
|
|
916
|
-
onPopupHeightChange(0);
|
|
917
|
-
return undefined;
|
|
918
|
-
}
|
|
919
|
-
const popupElement = store.context.popupRef.current;
|
|
920
|
-
if (!popupElement) {
|
|
921
|
-
return undefined;
|
|
922
|
-
}
|
|
923
|
-
removeCSSVariableInheritance$1();
|
|
924
|
-
measureHeight();
|
|
925
|
-
if (typeof ResizeObserver !== 'function') {
|
|
926
|
-
return undefined;
|
|
927
|
-
}
|
|
928
|
-
const resizeObserver = new ResizeObserver(measureHeight);
|
|
929
|
-
resizeObserver.observe(popupElement);
|
|
930
|
-
return () => {
|
|
931
|
-
resizeObserver.disconnect();
|
|
932
|
-
};
|
|
933
|
-
}, [measureHeight, mounted, nestedDrawerOpen, onPopupHeightChange, store.context.popupRef]);
|
|
934
|
-
useIsoLayoutEffect(() => {
|
|
935
|
-
const popupRef = store.context.popupRef;
|
|
936
|
-
const syncNestedSwipeProgress = () => {
|
|
937
|
-
const popupElement = popupRef.current;
|
|
938
|
-
if (!popupElement) {
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
const progress = nestedSwipeProgressStore.getSnapshot();
|
|
942
|
-
if (progress > 0) {
|
|
943
|
-
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, `${progress}`);
|
|
944
|
-
} else {
|
|
945
|
-
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
|
|
946
|
-
}
|
|
947
|
-
};
|
|
948
|
-
syncNestedSwipeProgress();
|
|
949
|
-
const unsubscribe = nestedSwipeProgressStore.subscribe(syncNestedSwipeProgress);
|
|
950
|
-
return () => {
|
|
951
|
-
unsubscribe();
|
|
952
|
-
const popupElement = popupRef.current;
|
|
953
|
-
if (popupElement) {
|
|
954
|
-
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
|
|
955
|
-
}
|
|
956
|
-
};
|
|
957
|
-
}, [nestedSwipeProgressStore, store.context.popupRef]);
|
|
958
|
-
React.useEffect(() => {
|
|
959
|
-
if (!open) {
|
|
960
|
-
return undefined;
|
|
961
|
-
}
|
|
962
|
-
notifyParentFrontmostHeight?.(frontmostHeight);
|
|
963
|
-
return () => {
|
|
964
|
-
notifyParentFrontmostHeight?.(0);
|
|
965
|
-
};
|
|
966
|
-
}, [frontmostHeight, open, notifyParentFrontmostHeight]);
|
|
967
|
-
React.useEffect(() => {
|
|
968
|
-
if (!notifyParentHasNestedDrawer) {
|
|
969
|
-
return undefined;
|
|
970
|
-
}
|
|
971
|
-
const present = open || transitionStatus === 'ending';
|
|
972
|
-
notifyParentHasNestedDrawer(present);
|
|
973
|
-
return () => {
|
|
974
|
-
notifyParentHasNestedDrawer(false);
|
|
975
|
-
};
|
|
976
|
-
}, [notifyParentHasNestedDrawer, open, transitionStatus]);
|
|
977
|
-
useOpenChangeComplete({
|
|
978
|
-
open,
|
|
979
|
-
ref: store.context.popupRef,
|
|
980
|
-
onComplete() {
|
|
981
|
-
if (open) {
|
|
982
|
-
store.context.onOpenChangeComplete?.(true);
|
|
983
|
-
}
|
|
1068
|
+
const exactMatch = resolvedSnapPoints.find(point => Object.is(point.value, activeSnapPoint));
|
|
1069
|
+
if (exactMatch) {
|
|
1070
|
+
return exactMatch;
|
|
984
1071
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
nested,
|
|
990
|
-
transitionStatus,
|
|
991
|
-
expanded: activeSnapPoint === 1,
|
|
992
|
-
nestedDrawerOpen,
|
|
993
|
-
nestedDrawerSwiping: nestedSwiping,
|
|
994
|
-
swipeDirection,
|
|
995
|
-
swiping
|
|
996
|
-
};
|
|
997
|
-
let popupHeightCssVarValue;
|
|
998
|
-
const shouldUseAutoHeight = !hasNestedDrawer && transitionStatus !== 'ending';
|
|
999
|
-
if (popupHeight && !shouldUseAutoHeight) {
|
|
1000
|
-
popupHeightCssVarValue = `${popupHeight}px`;
|
|
1001
|
-
}
|
|
1002
|
-
const shouldApplySnapPoints = snapPoints && snapPoints.length > 0 && (swipeDirection === 'down' || swipeDirection === 'up');
|
|
1003
|
-
let snapPointOffsetValue = null;
|
|
1004
|
-
if (shouldApplySnapPoints && activeSnapPointOffset !== null) {
|
|
1005
|
-
snapPointOffsetValue = swipeDirection === 'up' ? -activeSnapPointOffset : activeSnapPointOffset;
|
|
1006
|
-
}
|
|
1007
|
-
let dragStyles = swipe ? swipe.getDragStyles() : EMPTY_OBJECT;
|
|
1008
|
-
if (shouldApplySnapPoints && swipeDirection === 'down') {
|
|
1009
|
-
const baseOffset = activeSnapPointOffset ?? 0;
|
|
1010
|
-
const movementValue = Number.parseFloat(String(dragStyles[DrawerPopupCssVars.swipeMovementY] ?? 0));
|
|
1011
|
-
const nextOffset = Number.isFinite(movementValue) ? baseOffset + movementValue : baseOffset;
|
|
1012
|
-
const shouldDamp = nextOffset < 0;
|
|
1013
|
-
if (swiping && shouldDamp && Number.isFinite(movementValue)) {
|
|
1014
|
-
const overshoot = Math.abs(nextOffset);
|
|
1015
|
-
const dampedOffset = -Math.sqrt(overshoot);
|
|
1016
|
-
const dampedMovement = dampedOffset - baseOffset;
|
|
1017
|
-
dragStyles = {
|
|
1018
|
-
...dragStyles,
|
|
1019
|
-
transform: undefined,
|
|
1020
|
-
[DrawerPopupCssVars.swipeMovementY]: `${dampedMovement}px`
|
|
1021
|
-
};
|
|
1022
|
-
} else {
|
|
1023
|
-
dragStyles = {
|
|
1024
|
-
...dragStyles,
|
|
1025
|
-
transform: undefined
|
|
1026
|
-
};
|
|
1072
|
+
const maxHeight = Math.min(popupHeight, viewportHeight);
|
|
1073
|
+
const resolvedHeight = resolveSnapPointValue(activeSnapPoint, viewportHeight, rootFontSize);
|
|
1074
|
+
if (resolvedHeight === null || !Number.isFinite(resolvedHeight)) {
|
|
1075
|
+
return undefined;
|
|
1027
1076
|
}
|
|
1077
|
+
const clampedHeight = clamp(resolvedHeight, 0, maxHeight);
|
|
1078
|
+
return findClosestSnapPoint(clampedHeight, resolvedSnapPoints) ?? undefined;
|
|
1079
|
+
}, [activeSnapPoint, popupHeight, resolvedSnapPoints, rootFontSize, viewportHeight]);
|
|
1080
|
+
return {
|
|
1081
|
+
snapPoints,
|
|
1082
|
+
activeSnapPoint,
|
|
1083
|
+
setActiveSnapPoint,
|
|
1084
|
+
popupHeight,
|
|
1085
|
+
viewportHeight,
|
|
1086
|
+
resolvedSnapPoints,
|
|
1087
|
+
activeSnapPointOffset: resolvedActiveSnapPoint?.offset ?? null
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
const DrawerViewportContext = /*#__PURE__*/React.createContext(null);
|
|
1092
|
+
if (process.env.NODE_ENV !== "production") DrawerViewportContext.displayName = "DrawerViewportContext";
|
|
1093
|
+
function useDrawerViewportContext(optional) {
|
|
1094
|
+
const context = React.useContext(DrawerViewportContext);
|
|
1095
|
+
return context;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
let drawerSwipeVarsRegistered = false;
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Removes inheritance of high-frequency drawer swipe CSS variables, which
|
|
1102
|
+
* reduces style recalculation cost in complex drawers with deep subtrees.
|
|
1103
|
+
* Child elements that need these values can still opt-in by using `inherit`.
|
|
1104
|
+
* See https://motion.dev/blog/web-animation-performance-tier-list
|
|
1105
|
+
* under the "Improving CSS variable performance" section.
|
|
1106
|
+
*/
|
|
1107
|
+
function removeCSSVariableInheritance$1() {
|
|
1108
|
+
if (drawerSwipeVarsRegistered) {
|
|
1109
|
+
return;
|
|
1028
1110
|
}
|
|
1029
|
-
const element = useRenderElement('div', componentProps, {
|
|
1030
|
-
state,
|
|
1031
|
-
props: [rootPopupProps, {
|
|
1032
|
-
'aria-labelledby': titleElementId,
|
|
1033
|
-
'aria-describedby': descriptionElementId,
|
|
1034
|
-
role,
|
|
1035
|
-
tabIndex: -1,
|
|
1036
|
-
hidden: !mounted,
|
|
1037
|
-
onKeyDown(event) {
|
|
1038
|
-
if (COMPOSITE_KEYS.has(event.key)) {
|
|
1039
|
-
event.stopPropagation();
|
|
1040
|
-
}
|
|
1041
|
-
},
|
|
1042
|
-
style: {
|
|
1043
|
-
...dragStyles,
|
|
1044
|
-
[DrawerBackdropCssVars.swipeProgress]: '0',
|
|
1045
|
-
[DrawerPopupCssVars.nestedDrawers]: nestedOpenDialogCount,
|
|
1046
|
-
[DrawerPopupCssVars.height]: popupHeightCssVarValue,
|
|
1047
|
-
[DrawerPopupCssVars.snapPointOffset]: typeof snapPointOffsetValue === 'number' ? `${snapPointOffsetValue}px` : '0px',
|
|
1048
|
-
[DrawerPopupCssVars.frontmostHeight]: frontmostHeight ? `${frontmostHeight}px` : undefined,
|
|
1049
|
-
[DrawerPopupCssVars.swipeStrength]: typeof swipeStrength === 'number' && Number.isFinite(swipeStrength) && swipeStrength > 0 ? `${swipeStrength}` : '1'
|
|
1050
|
-
}
|
|
1051
|
-
}, elementProps],
|
|
1052
|
-
ref: [forwardedRef, store.context.popupRef, store.useStateSetter('popupElement')],
|
|
1053
|
-
stateAttributesMapping
|
|
1054
|
-
});
|
|
1055
|
-
return /*#__PURE__*/jsx(FloatingFocusManager, {
|
|
1056
|
-
context: floatingRootContext,
|
|
1057
|
-
openInteractionType: openMethod,
|
|
1058
|
-
disabled: !mounted,
|
|
1059
|
-
closeOnFocusOut: !disablePointerDismissal,
|
|
1060
|
-
initialFocus: resolvedInitialFocus,
|
|
1061
|
-
returnFocus: finalFocus,
|
|
1062
|
-
modal: modal !== false,
|
|
1063
|
-
restoreFocus: "popup",
|
|
1064
|
-
children: element
|
|
1065
|
-
});
|
|
1066
|
-
});
|
|
1067
|
-
if (process.env.NODE_ENV !== "production") DrawerPopup.displayName = "DrawerPopup";
|
|
1068
1111
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1112
|
+
// Intentionally keep inheritance disabled on WebKit as well. Safari doesn't support
|
|
1113
|
+
// opting descendants back in via `--var: inherit` for custom properties registered
|
|
1114
|
+
// with `inherits: false`, but Drawer does not rely on descendant access to these vars
|
|
1115
|
+
// (unlike ScrollArea), so we keep the performance optimization enabled.
|
|
1116
|
+
if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
|
|
1117
|
+
[DrawerPopupCssVars.swipeMovementX, DrawerPopupCssVars.swipeMovementY, DrawerPopupCssVars.snapPointOffset].forEach(name => {
|
|
1118
|
+
try {
|
|
1119
|
+
CSS.registerProperty({
|
|
1120
|
+
name,
|
|
1121
|
+
syntax: '<length>',
|
|
1122
|
+
inherits: false,
|
|
1123
|
+
initialValue: '0px'
|
|
1124
|
+
});
|
|
1125
|
+
} catch {
|
|
1126
|
+
/* ignore already-registered */
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
[{
|
|
1130
|
+
name: DrawerBackdropCssVars.swipeProgress,
|
|
1131
|
+
initialValue: '0'
|
|
1132
|
+
}, {
|
|
1133
|
+
name: DrawerPopupCssVars.swipeStrength,
|
|
1134
|
+
initialValue: '1'
|
|
1135
|
+
}].forEach(({
|
|
1136
|
+
name,
|
|
1137
|
+
initialValue
|
|
1138
|
+
}) => {
|
|
1139
|
+
try {
|
|
1140
|
+
CSS.registerProperty({
|
|
1141
|
+
name,
|
|
1142
|
+
syntax: '<number>',
|
|
1143
|
+
inherits: false,
|
|
1144
|
+
initialValue
|
|
1145
|
+
});
|
|
1146
|
+
} catch {
|
|
1147
|
+
/* ignore already-registered */
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1083
1150
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1151
|
+
drawerSwipeVarsRegistered = true;
|
|
1152
|
+
}
|
|
1153
|
+
const stateAttributesMapping = {
|
|
1154
|
+
...popupStateMapping,
|
|
1155
|
+
...transitionStatusMapping,
|
|
1156
|
+
expanded(value) {
|
|
1157
|
+
return value ? {
|
|
1158
|
+
[DrawerPopupDataAttributes.expanded]: ''
|
|
1159
|
+
} : null;
|
|
1160
|
+
},
|
|
1161
|
+
nestedDrawerOpen(value) {
|
|
1162
|
+
return value ? {
|
|
1163
|
+
[DrawerPopupDataAttributes.nestedDrawerOpen]: ''
|
|
1164
|
+
} : null;
|
|
1165
|
+
},
|
|
1166
|
+
nestedDrawerSwiping(value) {
|
|
1167
|
+
return value ? {
|
|
1168
|
+
[DrawerPopupDataAttributes.nestedDrawerSwiping]: ''
|
|
1169
|
+
} : null;
|
|
1170
|
+
},
|
|
1171
|
+
swipeDirection(value) {
|
|
1172
|
+
return value ? {
|
|
1173
|
+
[DrawerPopupDataAttributes.swipeDirection]: value
|
|
1174
|
+
} : null;
|
|
1175
|
+
},
|
|
1176
|
+
swiping(value) {
|
|
1177
|
+
return value ? {
|
|
1178
|
+
[DrawerPopupDataAttributes.swiping]: ''
|
|
1179
|
+
} : null;
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1097
1182
|
|
|
1098
1183
|
/**
|
|
1099
|
-
* A
|
|
1100
|
-
* By default, the portal element is appended to `<body>`.
|
|
1184
|
+
* A container for the drawer contents.
|
|
1101
1185
|
* Renders a `<div>` element.
|
|
1102
1186
|
*
|
|
1103
1187
|
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
1104
1188
|
*/
|
|
1105
|
-
const
|
|
1106
|
-
|
|
1107
|
-
function useDialogRoot(params) {
|
|
1189
|
+
const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(componentProps, forwardedRef) {
|
|
1108
1190
|
const {
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1191
|
+
className,
|
|
1192
|
+
finalFocus,
|
|
1193
|
+
initialFocus,
|
|
1194
|
+
render,
|
|
1195
|
+
...elementProps
|
|
1196
|
+
} = componentProps;
|
|
1197
|
+
const {
|
|
1198
|
+
store
|
|
1199
|
+
} = useDialogRootContext();
|
|
1200
|
+
const {
|
|
1201
|
+
swipeDirection,
|
|
1202
|
+
frontmostHeight,
|
|
1203
|
+
hasNestedDrawer,
|
|
1204
|
+
nestedSwiping,
|
|
1205
|
+
nestedSwipeProgressStore,
|
|
1206
|
+
onPopupHeightChange,
|
|
1207
|
+
notifyParentFrontmostHeight,
|
|
1208
|
+
notifyParentHasNestedDrawer
|
|
1209
|
+
} = useDrawerRootContext();
|
|
1210
|
+
const descriptionElementId = store.useState('descriptionElementId');
|
|
1114
1211
|
const disablePointerDismissal = store.useState('disablePointerDismissal');
|
|
1212
|
+
const floatingRootContext = store.useState('floatingRootContext');
|
|
1213
|
+
const rootPopupProps = store.useState('popupProps');
|
|
1115
1214
|
const modal = store.useState('modal');
|
|
1116
|
-
const
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
const
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
store.set('preventUnmountingOnClose', true);
|
|
1129
|
-
};
|
|
1130
|
-
return details;
|
|
1131
|
-
});
|
|
1132
|
-
const handleImperativeClose = React.useCallback(() => {
|
|
1133
|
-
store.setOpen(false, createDialogEventDetails(imperativeAction));
|
|
1134
|
-
}, [store, createDialogEventDetails]);
|
|
1135
|
-
React.useImperativeHandle(actionsRef, () => ({
|
|
1136
|
-
unmount: forceUnmount,
|
|
1137
|
-
close: handleImperativeClose
|
|
1138
|
-
}), [forceUnmount, handleImperativeClose]);
|
|
1139
|
-
const floatingRootContext = useSyncedFloatingRootContext({
|
|
1140
|
-
popupStore: store,
|
|
1141
|
-
onOpenChange: store.setOpen,
|
|
1142
|
-
treatPopupAsFloatingElement: true,
|
|
1143
|
-
noEmit: true
|
|
1144
|
-
});
|
|
1145
|
-
const [ownNestedOpenDialogs, setOwnNestedOpenDialogs] = React.useState(0);
|
|
1146
|
-
const isTopmost = ownNestedOpenDialogs === 0;
|
|
1147
|
-
const role = useRole(floatingRootContext);
|
|
1148
|
-
const dismiss = useDismiss(floatingRootContext, {
|
|
1149
|
-
outsidePressEvent() {
|
|
1150
|
-
if (store.context.internalBackdropRef.current || store.context.backdropRef.current) {
|
|
1151
|
-
return 'intentional';
|
|
1152
|
-
}
|
|
1153
|
-
// Ensure `aria-hidden` on outside elements is removed immediately
|
|
1154
|
-
// on outside press when trapping focus.
|
|
1155
|
-
return {
|
|
1156
|
-
mouse: modal === 'trap-focus' ? 'sloppy' : 'intentional',
|
|
1157
|
-
touch: 'sloppy'
|
|
1158
|
-
};
|
|
1159
|
-
},
|
|
1160
|
-
outsidePress(event) {
|
|
1161
|
-
if (!store.context.outsidePressEnabledRef.current) {
|
|
1162
|
-
return false;
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
// For mouse events, only accept left button (button 0)
|
|
1166
|
-
// For touch events, a single touch is equivalent to left button
|
|
1167
|
-
if ('button' in event && event.button !== 0) {
|
|
1168
|
-
return false;
|
|
1169
|
-
}
|
|
1170
|
-
if ('touches' in event && event.touches.length !== 1) {
|
|
1171
|
-
return false;
|
|
1172
|
-
}
|
|
1173
|
-
const target = getTarget(event);
|
|
1174
|
-
if (isTopmost && !disablePointerDismissal) {
|
|
1175
|
-
const eventTarget = target;
|
|
1176
|
-
// Only close if the click occurred on the dialog's owning backdrop.
|
|
1177
|
-
// This supports multiple modal dialogs that aren't nested in the React tree:
|
|
1178
|
-
// https://github.com/mui/base-ui/issues/1320
|
|
1179
|
-
if (modal) {
|
|
1180
|
-
return store.context.internalBackdropRef.current || store.context.backdropRef.current ? store.context.internalBackdropRef.current === eventTarget || store.context.backdropRef.current === eventTarget || contains(eventTarget, popupElement) && !eventTarget?.hasAttribute('data-base-ui-portal') : true;
|
|
1181
|
-
}
|
|
1182
|
-
return true;
|
|
1183
|
-
}
|
|
1184
|
-
return false;
|
|
1185
|
-
},
|
|
1186
|
-
escapeKey: isTopmost
|
|
1187
|
-
});
|
|
1188
|
-
useScrollLock(open && modal === true, popupElement);
|
|
1215
|
+
const mounted = store.useState('mounted');
|
|
1216
|
+
const nested = store.useState('nested');
|
|
1217
|
+
const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
|
|
1218
|
+
const transitionStatus = store.useState('transitionStatus');
|
|
1219
|
+
const open = store.useState('open');
|
|
1220
|
+
const openMethod = store.useState('openMethod');
|
|
1221
|
+
const titleElementId = store.useState('titleElementId');
|
|
1222
|
+
const role = store.useState('role');
|
|
1223
|
+
const nestedDrawerOpen = nestedOpenDialogCount > 0;
|
|
1224
|
+
const swipe = useDrawerViewportContext();
|
|
1225
|
+
const swiping = swipe?.swiping ?? false;
|
|
1226
|
+
const swipeStrength = swipe?.swipeStrength ?? null;
|
|
1189
1227
|
const {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
} =
|
|
1228
|
+
snapPoints,
|
|
1229
|
+
activeSnapPoint,
|
|
1230
|
+
activeSnapPointOffset
|
|
1231
|
+
} = useDrawerSnapPoints();
|
|
1232
|
+
useDialogPortalContext();
|
|
1233
|
+
const [popupHeight, setPopupHeight] = React.useState(0);
|
|
1234
|
+
const popupHeightRef = React.useRef(0);
|
|
1235
|
+
const measureHeight = useStableCallback(() => {
|
|
1236
|
+
const popupElement = store.context.popupRef.current;
|
|
1237
|
+
if (!popupElement) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
const offsetHeight = popupElement.offsetHeight;
|
|
1194
1241
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1242
|
+
// Only skip while the element is still actually stretched beyond its last measured height.
|
|
1243
|
+
if (popupHeightRef.current > 0 && frontmostHeight > popupHeightRef.current && offsetHeight > popupHeightRef.current) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
const keepHeightWhileNested = popupHeightRef.current > 0 && hasNestedDrawer;
|
|
1247
|
+
if (keepHeightWhileNested) {
|
|
1248
|
+
const oldHeight = popupHeightRef.current;
|
|
1249
|
+
setPopupHeight(oldHeight);
|
|
1250
|
+
onPopupHeightChange(oldHeight);
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const nextHeight = offsetHeight;
|
|
1254
|
+
if (nextHeight === popupHeightRef.current) {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
popupHeightRef.current = nextHeight;
|
|
1258
|
+
setPopupHeight(nextHeight);
|
|
1259
|
+
onPopupHeightChange(nextHeight);
|
|
1201
1260
|
});
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1261
|
+
useIsoLayoutEffect(() => {
|
|
1262
|
+
if (!mounted) {
|
|
1263
|
+
popupHeightRef.current = 0;
|
|
1264
|
+
setPopupHeight(0);
|
|
1265
|
+
onPopupHeightChange(0);
|
|
1266
|
+
return undefined;
|
|
1207
1267
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1268
|
+
const popupElement = store.context.popupRef.current;
|
|
1269
|
+
if (!popupElement) {
|
|
1270
|
+
return undefined;
|
|
1271
|
+
}
|
|
1272
|
+
removeCSSVariableInheritance$1();
|
|
1273
|
+
measureHeight();
|
|
1274
|
+
if (typeof ResizeObserver !== 'function') {
|
|
1275
|
+
return undefined;
|
|
1210
1276
|
}
|
|
1277
|
+
const resizeObserver = new ResizeObserver(measureHeight);
|
|
1278
|
+
resizeObserver.observe(popupElement);
|
|
1211
1279
|
return () => {
|
|
1212
|
-
|
|
1213
|
-
|
|
1280
|
+
resizeObserver.disconnect();
|
|
1281
|
+
};
|
|
1282
|
+
}, [measureHeight, mounted, nestedDrawerOpen, onPopupHeightChange, store.context.popupRef]);
|
|
1283
|
+
useIsoLayoutEffect(() => {
|
|
1284
|
+
const popupRef = store.context.popupRef;
|
|
1285
|
+
const syncNestedSwipeProgress = () => {
|
|
1286
|
+
const popupElement = popupRef.current;
|
|
1287
|
+
if (!popupElement) {
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
const progress = nestedSwipeProgressStore.getSnapshot();
|
|
1291
|
+
if (progress > 0) {
|
|
1292
|
+
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, `${progress}`);
|
|
1293
|
+
} else {
|
|
1294
|
+
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
|
|
1214
1295
|
}
|
|
1215
1296
|
};
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
popupProps,
|
|
1225
|
-
floatingRootContext,
|
|
1226
|
-
nestedOpenDialogCount: ownNestedOpenDialogs
|
|
1227
|
-
});
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
const selectors = {
|
|
1231
|
-
...popupStoreSelectors,
|
|
1232
|
-
modal: createSelector(state => state.modal),
|
|
1233
|
-
nested: createSelector(state => state.nested),
|
|
1234
|
-
nestedOpenDialogCount: createSelector(state => state.nestedOpenDialogCount),
|
|
1235
|
-
disablePointerDismissal: createSelector(state => state.disablePointerDismissal),
|
|
1236
|
-
openMethod: createSelector(state => state.openMethod),
|
|
1237
|
-
descriptionElementId: createSelector(state => state.descriptionElementId),
|
|
1238
|
-
titleElementId: createSelector(state => state.titleElementId),
|
|
1239
|
-
viewportElement: createSelector(state => state.viewportElement),
|
|
1240
|
-
role: createSelector(state => state.role)
|
|
1241
|
-
};
|
|
1242
|
-
class DialogStore extends ReactStore {
|
|
1243
|
-
constructor(initialState) {
|
|
1244
|
-
super(createInitialState(initialState), {
|
|
1245
|
-
popupRef: /*#__PURE__*/React.createRef(),
|
|
1246
|
-
backdropRef: /*#__PURE__*/React.createRef(),
|
|
1247
|
-
internalBackdropRef: /*#__PURE__*/React.createRef(),
|
|
1248
|
-
outsidePressEnabledRef: {
|
|
1249
|
-
current: true
|
|
1250
|
-
},
|
|
1251
|
-
triggerElements: new PopupTriggerMap(),
|
|
1252
|
-
onOpenChange: undefined,
|
|
1253
|
-
onOpenChangeComplete: undefined
|
|
1254
|
-
}, selectors);
|
|
1255
|
-
}
|
|
1256
|
-
setOpen = (nextOpen, eventDetails) => {
|
|
1257
|
-
eventDetails.preventUnmountOnClose = () => {
|
|
1258
|
-
this.set('preventUnmountingOnClose', true);
|
|
1297
|
+
syncNestedSwipeProgress();
|
|
1298
|
+
const unsubscribe = nestedSwipeProgressStore.subscribe(syncNestedSwipeProgress);
|
|
1299
|
+
return () => {
|
|
1300
|
+
unsubscribe();
|
|
1301
|
+
const popupElement = popupRef.current;
|
|
1302
|
+
if (popupElement) {
|
|
1303
|
+
popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
|
|
1304
|
+
}
|
|
1259
1305
|
};
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
}
|
|
1265
|
-
this.context.onOpenChange?.(nextOpen, eventDetails);
|
|
1266
|
-
if (eventDetails.isCanceled) {
|
|
1267
|
-
return;
|
|
1306
|
+
}, [nestedSwipeProgressStore, store.context.popupRef]);
|
|
1307
|
+
React.useEffect(() => {
|
|
1308
|
+
if (!open) {
|
|
1309
|
+
return undefined;
|
|
1268
1310
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
open: nextOpen
|
|
1278
|
-
};
|
|
1279
|
-
|
|
1280
|
-
// If a popup is closing, the `trigger` may be null.
|
|
1281
|
-
// We want to keep the previous value so that exit animations are played and focus is returned correctly.
|
|
1282
|
-
const newTriggerId = eventDetails.trigger?.id ?? null;
|
|
1283
|
-
if (newTriggerId || nextOpen) {
|
|
1284
|
-
updatedState.activeTriggerId = newTriggerId;
|
|
1285
|
-
updatedState.activeTriggerElement = eventDetails.trigger ?? null;
|
|
1311
|
+
notifyParentFrontmostHeight?.(frontmostHeight);
|
|
1312
|
+
return () => {
|
|
1313
|
+
notifyParentFrontmostHeight?.(0);
|
|
1314
|
+
};
|
|
1315
|
+
}, [frontmostHeight, open, notifyParentFrontmostHeight]);
|
|
1316
|
+
React.useEffect(() => {
|
|
1317
|
+
if (!notifyParentHasNestedDrawer) {
|
|
1318
|
+
return undefined;
|
|
1286
1319
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
nested: false,
|
|
1301
|
-
nestedOpenDialogCount: 0,
|
|
1302
|
-
role: 'dialog',
|
|
1303
|
-
...initialState
|
|
1304
|
-
};
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
/**
|
|
1308
|
-
* Groups all parts of the dialog.
|
|
1309
|
-
* Doesn’t render its own HTML element.
|
|
1310
|
-
*
|
|
1311
|
-
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
1312
|
-
*/
|
|
1313
|
-
function DialogRoot(props) {
|
|
1314
|
-
const {
|
|
1315
|
-
children,
|
|
1316
|
-
open: openProp,
|
|
1317
|
-
defaultOpen = false,
|
|
1318
|
-
onOpenChange,
|
|
1319
|
-
onOpenChangeComplete,
|
|
1320
|
-
disablePointerDismissal = false,
|
|
1321
|
-
modal = true,
|
|
1322
|
-
actionsRef,
|
|
1323
|
-
handle,
|
|
1324
|
-
triggerId: triggerIdProp,
|
|
1325
|
-
defaultTriggerId: defaultTriggerIdProp = null
|
|
1326
|
-
} = props;
|
|
1327
|
-
const parentDialogRootContext = useDialogRootContext(true);
|
|
1328
|
-
const nested = Boolean(parentDialogRootContext);
|
|
1329
|
-
const store = useRefWithInit(() => {
|
|
1330
|
-
return handle?.store ?? new DialogStore({
|
|
1331
|
-
open: defaultOpen,
|
|
1332
|
-
openProp,
|
|
1333
|
-
activeTriggerId: defaultTriggerIdProp,
|
|
1334
|
-
triggerIdProp,
|
|
1335
|
-
modal,
|
|
1336
|
-
disablePointerDismissal,
|
|
1337
|
-
nested
|
|
1338
|
-
});
|
|
1339
|
-
}).current;
|
|
1340
|
-
|
|
1341
|
-
// Support initially open state when uncontrolled
|
|
1342
|
-
useOnFirstRender(() => {
|
|
1343
|
-
if (openProp === undefined && store.state.open === false && defaultOpen === true) {
|
|
1344
|
-
store.update({
|
|
1345
|
-
open: true,
|
|
1346
|
-
activeTriggerId: defaultTriggerIdProp
|
|
1347
|
-
});
|
|
1320
|
+
const present = open || transitionStatus === 'ending';
|
|
1321
|
+
notifyParentHasNestedDrawer(present);
|
|
1322
|
+
return () => {
|
|
1323
|
+
notifyParentHasNestedDrawer(false);
|
|
1324
|
+
};
|
|
1325
|
+
}, [notifyParentHasNestedDrawer, open, transitionStatus]);
|
|
1326
|
+
useOpenChangeComplete({
|
|
1327
|
+
open,
|
|
1328
|
+
ref: store.context.popupRef,
|
|
1329
|
+
onComplete() {
|
|
1330
|
+
if (open) {
|
|
1331
|
+
store.context.onOpenChangeComplete?.(true);
|
|
1332
|
+
}
|
|
1348
1333
|
}
|
|
1349
1334
|
});
|
|
1350
|
-
store.
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
disablePointerDismissal,
|
|
1335
|
+
const resolvedInitialFocus = initialFocus === undefined ? store.context.popupRef : initialFocus;
|
|
1336
|
+
const state = {
|
|
1337
|
+
open,
|
|
1354
1338
|
nested,
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1339
|
+
transitionStatus,
|
|
1340
|
+
expanded: activeSnapPoint === 1,
|
|
1341
|
+
nestedDrawerOpen,
|
|
1342
|
+
nestedDrawerSwiping: nestedSwiping,
|
|
1343
|
+
swipeDirection,
|
|
1344
|
+
swiping
|
|
1345
|
+
};
|
|
1346
|
+
let popupHeightCssVarValue;
|
|
1347
|
+
const shouldUseAutoHeight = !hasNestedDrawer && transitionStatus !== 'ending';
|
|
1348
|
+
if (popupHeight && !shouldUseAutoHeight) {
|
|
1349
|
+
popupHeightCssVarValue = `${popupHeight}px`;
|
|
1350
|
+
}
|
|
1351
|
+
const shouldApplySnapPoints = snapPoints && snapPoints.length > 0 && (swipeDirection === 'down' || swipeDirection === 'up');
|
|
1352
|
+
let snapPointOffsetValue = null;
|
|
1353
|
+
if (shouldApplySnapPoints && activeSnapPointOffset !== null) {
|
|
1354
|
+
snapPointOffsetValue = swipeDirection === 'up' ? -activeSnapPointOffset : activeSnapPointOffset;
|
|
1355
|
+
}
|
|
1356
|
+
let dragStyles = swipe ? swipe.getDragStyles() : EMPTY_OBJECT;
|
|
1357
|
+
if (shouldApplySnapPoints && swipeDirection === 'down') {
|
|
1358
|
+
const baseOffset = activeSnapPointOffset ?? 0;
|
|
1359
|
+
const movementValue = Number.parseFloat(String(dragStyles[DrawerPopupCssVars.swipeMovementY] ?? 0));
|
|
1360
|
+
const nextOffset = Number.isFinite(movementValue) ? baseOffset + movementValue : baseOffset;
|
|
1361
|
+
const shouldDamp = nextOffset < 0;
|
|
1362
|
+
if (swiping && shouldDamp && Number.isFinite(movementValue)) {
|
|
1363
|
+
const overshoot = Math.abs(nextOffset);
|
|
1364
|
+
const dampedOffset = -Math.sqrt(overshoot);
|
|
1365
|
+
const dampedMovement = dampedOffset - baseOffset;
|
|
1366
|
+
dragStyles = {
|
|
1367
|
+
...dragStyles,
|
|
1368
|
+
transform: undefined,
|
|
1369
|
+
[DrawerPopupCssVars.swipeMovementY]: `${dampedMovement}px`
|
|
1370
|
+
};
|
|
1371
|
+
} else {
|
|
1372
|
+
dragStyles = {
|
|
1373
|
+
...dragStyles,
|
|
1374
|
+
transform: undefined
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
const element = useRenderElement('div', componentProps, {
|
|
1379
|
+
state,
|
|
1380
|
+
props: [rootPopupProps, {
|
|
1381
|
+
'aria-labelledby': titleElementId,
|
|
1382
|
+
'aria-describedby': descriptionElementId,
|
|
1383
|
+
role,
|
|
1384
|
+
tabIndex: -1,
|
|
1385
|
+
hidden: !mounted,
|
|
1386
|
+
onKeyDown(event) {
|
|
1387
|
+
if (COMPOSITE_KEYS.has(event.key)) {
|
|
1388
|
+
event.stopPropagation();
|
|
1389
|
+
}
|
|
1390
|
+
},
|
|
1391
|
+
style: {
|
|
1392
|
+
...dragStyles,
|
|
1393
|
+
[DrawerBackdropCssVars.swipeProgress]: '0',
|
|
1394
|
+
[DrawerPopupCssVars.nestedDrawers]: nestedOpenDialogCount,
|
|
1395
|
+
[DrawerPopupCssVars.height]: popupHeightCssVarValue,
|
|
1396
|
+
[DrawerPopupCssVars.snapPointOffset]: typeof snapPointOffsetValue === 'number' ? `${snapPointOffsetValue}px` : '0px',
|
|
1397
|
+
[DrawerPopupCssVars.frontmostHeight]: frontmostHeight ? `${frontmostHeight}px` : undefined,
|
|
1398
|
+
[DrawerPopupCssVars.swipeStrength]: typeof swipeStrength === 'number' && Number.isFinite(swipeStrength) && swipeStrength > 0 ? `${swipeStrength}` : '1'
|
|
1399
|
+
}
|
|
1400
|
+
}, elementProps],
|
|
1401
|
+
ref: [forwardedRef, store.context.popupRef, store.useStateSetter('popupElement')],
|
|
1402
|
+
stateAttributesMapping
|
|
1366
1403
|
});
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1404
|
+
return /*#__PURE__*/jsx(FloatingFocusManager, {
|
|
1405
|
+
context: floatingRootContext,
|
|
1406
|
+
openInteractionType: openMethod,
|
|
1407
|
+
disabled: !mounted,
|
|
1408
|
+
closeOnFocusOut: !disablePointerDismissal,
|
|
1409
|
+
initialFocus: resolvedInitialFocus,
|
|
1410
|
+
returnFocus: finalFocus,
|
|
1411
|
+
modal: modal !== false,
|
|
1412
|
+
restoreFocus: "popup",
|
|
1413
|
+
children: element
|
|
1375
1414
|
});
|
|
1376
|
-
}
|
|
1415
|
+
});
|
|
1416
|
+
if (process.env.NODE_ENV !== "production") DrawerPopup.displayName = "DrawerPopup";
|
|
1377
1417
|
|
|
1378
1418
|
/**
|
|
1379
|
-
* A
|
|
1380
|
-
*
|
|
1419
|
+
* A portal element that moves the popup to a different part of the DOM.
|
|
1420
|
+
* By default, the portal element is appended to `<body>`.
|
|
1421
|
+
* Renders a `<div>` element.
|
|
1381
1422
|
*
|
|
1382
|
-
* Documentation: [Base UI
|
|
1423
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
1383
1424
|
*/
|
|
1384
|
-
const
|
|
1385
|
-
const {
|
|
1386
|
-
render,
|
|
1387
|
-
className,
|
|
1388
|
-
disabled = false,
|
|
1389
|
-
nativeButton = true,
|
|
1390
|
-
id: idProp,
|
|
1391
|
-
payload,
|
|
1392
|
-
handle,
|
|
1393
|
-
...elementProps
|
|
1394
|
-
} = componentProps;
|
|
1395
|
-
const dialogRootContext = useDialogRootContext(true);
|
|
1396
|
-
const store = handle?.store ?? dialogRootContext?.store;
|
|
1397
|
-
if (!store) {
|
|
1398
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Trigger> must be used within <Dialog.Root> or provided with a handle.' : formatErrorMessage(79));
|
|
1399
|
-
}
|
|
1400
|
-
const thisTriggerId = useBaseUiId(idProp);
|
|
1401
|
-
const floatingContext = store.useState('floatingRootContext');
|
|
1402
|
-
const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
|
|
1403
|
-
const triggerElementRef = React.useRef(null);
|
|
1404
|
-
const {
|
|
1405
|
-
registerTrigger,
|
|
1406
|
-
isMountedByThisTrigger
|
|
1407
|
-
} = useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
|
|
1408
|
-
payload
|
|
1409
|
-
});
|
|
1410
|
-
const {
|
|
1411
|
-
getButtonProps,
|
|
1412
|
-
buttonRef
|
|
1413
|
-
} = useButton({
|
|
1414
|
-
disabled,
|
|
1415
|
-
native: nativeButton
|
|
1416
|
-
});
|
|
1417
|
-
const click = useClick(floatingContext, {
|
|
1418
|
-
enabled: floatingContext != null
|
|
1419
|
-
});
|
|
1420
|
-
const localInteractionProps = useInteractions([click]);
|
|
1421
|
-
const state = {
|
|
1422
|
-
disabled,
|
|
1423
|
-
open: isOpenedByThisTrigger
|
|
1424
|
-
};
|
|
1425
|
-
const rootTriggerProps = store.useState('triggerProps', isMountedByThisTrigger);
|
|
1426
|
-
return useRenderElement('button', componentProps, {
|
|
1427
|
-
state,
|
|
1428
|
-
ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
|
|
1429
|
-
props: [localInteractionProps.getReferenceProps(), rootTriggerProps, {
|
|
1430
|
-
[CLICK_TRIGGER_IDENTIFIER]: '',
|
|
1431
|
-
id: thisTriggerId
|
|
1432
|
-
}, elementProps, getButtonProps],
|
|
1433
|
-
stateAttributesMapping: triggerOpenStateMapping
|
|
1434
|
-
});
|
|
1435
|
-
});
|
|
1436
|
-
if (process.env.NODE_ENV !== "production") DialogTrigger.displayName = "DialogTrigger";
|
|
1425
|
+
const DrawerPortal = DialogPortal;
|
|
1437
1426
|
|
|
1438
1427
|
var _DrawerProviderReport, _DrawerProviderReport2;
|
|
1439
1428
|
/**
|
|
@@ -1745,20 +1734,6 @@ let ScrollAreaScrollbarDataAttributes = /*#__PURE__*/function (ScrollAreaScrollb
|
|
|
1745
1734
|
return ScrollAreaScrollbarDataAttributes;
|
|
1746
1735
|
}({});
|
|
1747
1736
|
|
|
1748
|
-
const DISABLE_SCROLLBAR_CLASS_NAME = 'base-ui-disable-scrollbar';
|
|
1749
|
-
const styleDisableScrollbar = {
|
|
1750
|
-
className: DISABLE_SCROLLBAR_CLASS_NAME,
|
|
1751
|
-
getElement(nonce) {
|
|
1752
|
-
return /*#__PURE__*/jsx("style", {
|
|
1753
|
-
nonce: nonce,
|
|
1754
|
-
href: DISABLE_SCROLLBAR_CLASS_NAME,
|
|
1755
|
-
precedence: "base-ui:low",
|
|
1756
|
-
children: `.${DISABLE_SCROLLBAR_CLASS_NAME}{scrollbar-width:none}.${DISABLE_SCROLLBAR_CLASS_NAME}::-webkit-scrollbar{display:none}`
|
|
1757
|
-
});
|
|
1758
|
-
}
|
|
1759
|
-
};
|
|
1760
|
-
if (process.env.NODE_ENV !== "production") styleDisableScrollbar.getElement.displayName = "styleDisableScrollbar.getElement";
|
|
1761
|
-
|
|
1762
1737
|
let ScrollAreaRootDataAttributes = /*#__PURE__*/function (ScrollAreaRootDataAttributes) {
|
|
1763
1738
|
/**
|
|
1764
1739
|
* Present when the user scrolls inside the scroll area.
|
|
@@ -1813,22 +1788,6 @@ const scrollAreaStateAttributesMapping = {
|
|
|
1813
1788
|
cornerHidden: () => null
|
|
1814
1789
|
};
|
|
1815
1790
|
|
|
1816
|
-
/**
|
|
1817
|
-
* @internal
|
|
1818
|
-
*/
|
|
1819
|
-
const CSPContext = /*#__PURE__*/React.createContext(undefined);
|
|
1820
|
-
if (process.env.NODE_ENV !== "production") CSPContext.displayName = "CSPContext";
|
|
1821
|
-
const DEFAULT_CSP_CONTEXT_VALUE = {
|
|
1822
|
-
disableStyleElements: false
|
|
1823
|
-
};
|
|
1824
|
-
|
|
1825
|
-
/**
|
|
1826
|
-
* @internal
|
|
1827
|
-
*/
|
|
1828
|
-
function useCSPContext() {
|
|
1829
|
-
return React.useContext(CSPContext) ?? DEFAULT_CSP_CONTEXT_VALUE;
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
1791
|
const DEFAULT_COORDS = {
|
|
1833
1792
|
x: 0,
|
|
1834
1793
|
y: 0
|
|
@@ -2511,4 +2470,4 @@ function mergeHiddenState(prevState, nextState) {
|
|
|
2511
2470
|
return nextState;
|
|
2512
2471
|
}
|
|
2513
2472
|
|
|
2514
|
-
export {
|
|
2473
|
+
export { useDrawerSnapPoints as A, DrawerViewportContext as B, DRAWER_CONTENT_ATTRIBUTE as C, DrawerTrigger as D, useScrollAreaRootContext as E, getOffset as F, ScrollAreaRootCssVars as G, scrollAreaStateAttributesMapping as H, useScrollAreaViewportContext as I, ScrollAreaRoot as S, DrawerRoot as a, DrawerPortal as b, DrawerBackdrop as c, DrawerPopup as d, ScrollAreaViewport as e, DrawerContent as f, DialogRoot as g, DialogTrigger as h, DialogPortal as i, useDialogPortalContext as j, DialogStore as k, createInitialPopupStoreState as l, useImplicitActiveTrigger as m, useOpenStateTransitions as n, useSyncedFloatingRootContext as o, popupStoreSelectors as p, useRole as q, useTriggerDataForwarding as r, useTriggerRegistration as s, useDrawerProviderContext as t, useDialogRootContext as u, DrawerBackdropCssVars as v, DrawerPopupCssVars as w, DrawerProviderContext as x, useDrawerRootContext as y, DrawerPopupDataAttributes as z };
|