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