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