x-ui-design 0.8.16 → 0.8.18

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.
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
2
  import { PopoverProps } from "../../types/popover";
3
3
  import './style.css';
4
- declare const Popover: ({ prefixCls, content, children, trigger, placement, open, visible, title, overlayClassName, overlayStyle, onVisibleChange, getPopupContainer }: PopoverProps) => React.JSX.Element;
4
+ declare const Popover: ({ prefixCls, content, children, trigger, placement, open, visible, title, style, overlayClassName, overlayStyle, onVisibleChange, getPopupContainer }: PopoverProps) => React.JSX.Element;
5
5
  export default Popover;
@@ -9,7 +9,7 @@ type TPosition = {
9
9
  offset?: number;
10
10
  };
11
11
  export declare const usePosition: ({ isOpen, offset, popupRef, placement, triggerRef, getPopupContainer }: TPosition) => {
12
- shouldShowAbove: boolean;
12
+ showPlacement: string;
13
13
  dropdownPosition: CSSProperties;
14
14
  };
15
15
  export {};
@@ -1,6 +1,6 @@
1
1
  import { CSSProperties, ReactNode } from "react";
2
- export interface PopoverProps {
3
- prefixCls?: string;
2
+ import { DefaultProps } from ".";
3
+ export type PopoverProps = DefaultProps & {
4
4
  content: ReactNode;
5
5
  children: ReactNode;
6
6
  trigger?: "click" | "hover";
@@ -12,4 +12,4 @@ export interface PopoverProps {
12
12
  visible?: boolean;
13
13
  onVisibleChange?: ((open: boolean) => void) | undefined;
14
14
  getPopupContainer?: ((node: HTMLElement) => HTMLElement) | undefined;
15
- }
15
+ };
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import require$$1 from 'react/jsx-runtime';
2
- import React, { useRef, useState, Children, isValidElement, Fragment, Suspense, useEffect, useContext, useMemo, useCallback, createContext, useImperativeHandle, useLayoutEffect } from 'react';
2
+ import React, { useRef, useState, Children, isValidElement, Fragment, Suspense, useEffect, useContext, useMemo, useCallback, createContext, useImperativeHandle, useLayoutEffect, cloneElement } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
  import ReactDOMServer from 'react-dom/server';
5
5
 
@@ -2594,6 +2594,15 @@ function getScrollParent(el, includeSelf = false) {
2594
2594
  }
2595
2595
  return document.scrollingElement;
2596
2596
  }
2597
+ const clampWithinContainer = (left, popupWidth, containerRect) => {
2598
+ const minLeft = containerRect.left + document.documentElement.scrollLeft;
2599
+ const maxLeft = containerRect.right + document.documentElement.scrollLeft - popupWidth;
2600
+ return {
2601
+ minLeft,
2602
+ maxLeft,
2603
+ leftPosition: Math.min(Math.max(left, minLeft), maxLeft)
2604
+ };
2605
+ };
2597
2606
  const usePosition = ({
2598
2607
  isOpen,
2599
2608
  offset = 4,
@@ -2602,7 +2611,7 @@ const usePosition = ({
2602
2611
  triggerRef,
2603
2612
  getPopupContainer
2604
2613
  }) => {
2605
- const [shouldShowAbove, setShouldShowAbove] = useState(false);
2614
+ const [showPlacement, setShowPlacement] = useState('');
2606
2615
  const [_dropdownPosition, setDropdownPosition] = useState({});
2607
2616
  const dropdownPosition = useCallback(() => {
2608
2617
  if (!triggerRef.current) {
@@ -2615,9 +2624,14 @@ const usePosition = ({
2615
2624
  const spaceBelow = containerRect.bottom - inputRect.bottom;
2616
2625
  const _shouldShowAbove = spaceBelow < dropdownHeight && spaceAbove > dropdownHeight;
2617
2626
  const hasRight = placement?.includes('Right');
2618
- setShouldShowAbove(_shouldShowAbove);
2619
2627
  if (getPopupContainer) {
2620
- const leftPosition = hasRight ? (inputRect.left || 0) + (triggerRef.current?.offsetWidth || 0) - (popupRef.current?.offsetWidth || 0) : (inputRect.left || 0) + document.documentElement.scrollLeft;
2628
+ const {
2629
+ minLeft,
2630
+ maxLeft,
2631
+ leftPosition
2632
+ } = clampWithinContainer(hasRight ? (inputRect.left || 0) + (triggerRef.current?.offsetWidth || 0) - (popupRef.current?.offsetWidth || 0) : (inputRect.left || 0) + document.documentElement.scrollLeft, popupRef.current?.offsetWidth || 0, containerRect);
2633
+ const _center = minLeft + maxLeft < (popupRef.current?.offsetWidth || 0) ? 'center' : '';
2634
+ setShowPlacement(_shouldShowAbove ? `bottom ${_center}` : `${_center}`);
2621
2635
  const _top = (inputRect.top || 0) + document.documentElement.scrollTop;
2622
2636
  if (_shouldShowAbove) {
2623
2637
  setDropdownPosition({
@@ -2634,9 +2648,27 @@ const usePosition = ({
2634
2648
  setDropdownPosition({
2635
2649
  top: (_shouldShowAbove ? triggerRef.current.offsetTop - (popupRef.current?.offsetHeight || dropdownHeight) - offset * 2 : triggerRef.current.offsetTop + triggerRef.current?.offsetHeight) + offset,
2636
2650
  ...(hasRight ? {
2637
- left: triggerRef.current.offsetLeft + (triggerRef.current?.offsetWidth || 0) - (popupRef.current?.offsetWidth || 0)
2651
+ left: (() => {
2652
+ const {
2653
+ minLeft,
2654
+ maxLeft,
2655
+ leftPosition
2656
+ } = clampWithinContainer(triggerRef.current.offsetLeft + (triggerRef.current?.offsetWidth || 0) - (popupRef.current?.offsetWidth || dropdownHeight), popupRef.current?.offsetWidth || dropdownHeight, containerRect);
2657
+ const _center = minLeft + maxLeft < (popupRef.current?.offsetWidth || 0) ? 'center' : '';
2658
+ setShowPlacement(_shouldShowAbove ? `bottom ${_center}` : `${_center}`);
2659
+ return leftPosition;
2660
+ })()
2638
2661
  } : {
2639
- left: triggerRef.current.offsetLeft
2662
+ left: (() => {
2663
+ const {
2664
+ minLeft,
2665
+ maxLeft,
2666
+ leftPosition
2667
+ } = clampWithinContainer(triggerRef.current.offsetLeft, popupRef.current?.offsetWidth || dropdownHeight, containerRect);
2668
+ const _center = minLeft + maxLeft < (popupRef.current?.offsetWidth || 0) ? 'center' : '';
2669
+ setShowPlacement(_shouldShowAbove ? `bottom ${_center}` : `${_center}`);
2670
+ return leftPosition;
2671
+ })()
2640
2672
  })
2641
2673
  });
2642
2674
  }
@@ -2663,7 +2695,7 @@ const usePosition = ({
2663
2695
  };
2664
2696
  }, [isOpen, triggerRef, getPopupContainer, dropdownPosition]);
2665
2697
  return {
2666
- shouldShowAbove,
2698
+ showPlacement,
2667
2699
  dropdownPosition: {
2668
2700
  ..._dropdownPosition,
2669
2701
  opacity: Object.keys(_dropdownPosition).length ? 1 : 0
@@ -5321,7 +5353,7 @@ var Menu$1 = /*#__PURE__*/Object.freeze({
5321
5353
  default: Menu
5322
5354
  });
5323
5355
 
5324
- var css_248z$2 = ".xUi-dropdown-overlay{background:var(--xui-menu-inline-bg);border:1px solid var(--xui-border-color);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.08);min-width:160px;padding:4px 0;position:absolute;&:before{content:\"\";height:10px;position:absolute;top:-15px;width:100%;z-index:1}}.xUi-dropdown-overlay>div,.xUi-dropdown-overlay>select,.xUi-dropdown-overlay>ul{box-shadow:unset}.xUi-dropdown-overlay .xUi-dropdown-menu{margin:0;padding:0 4px;position:relative;&:before{content:\"\";height:10px;position:absolute;top:-15px;width:100%;z-index:1}}.xUi-dropdown-overlay .xUi-dropdown-item{border-radius:8px;color:var(--xui-text-color);cursor:pointer;font-size:14px;list-style:none;padding:8px 12px;user-select:none}.xUi-dropdown-overlay .xUi-dropdown-item:focus,.xUi-dropdown-overlay .xUi-dropdown-item:hover{background:var(--xui-color-hover);outline:none}.xUi-dropdown-overlay .xUi-dropdown-item.disabled{cursor:not-allowed;opacity:.5}.xUi-dropdown-overlay .xUi-dropdown-item.danger{color:var(--xui-error-color-light);&:hover{background-color:var(--xui-error-color-light);color:var(--xui-background-color)}}.xUi-dropdown-arrow{background:var(--xui-background-color);border-left:.5px solid var(--xui-border-color);border-top:.5px solid var(--xui-border-color);height:10px;left:12px;position:absolute;top:-6px;transform:rotate(45deg);width:10px}.xUi-dropdown-arrow.bottom{border-bottom:.5px solid var(--xui-border-color);border-left:unset;border-right:.5px solid var(--xui-border-color);border-top:unset;bottom:-6px;top:unset}";
5356
+ var css_248z$2 = ".xUi-dropdown-overlay{background:var(--xui-menu-inline-bg);border:1px solid var(--xui-border-color);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.08);min-width:160px;padding:4px 0;position:absolute;&:before{content:\"\";height:10px;position:absolute;top:-15px;width:100%;z-index:1}}.xUi-dropdown-overlay>div,.xUi-dropdown-overlay>select,.xUi-dropdown-overlay>ul{box-shadow:unset}.xUi-dropdown-overlay .xUi-dropdown-menu{margin:0;padding:0 4px;position:relative;&:before{content:\"\";height:10px;position:absolute;top:-15px;width:100%;z-index:1}}.xUi-dropdown-overlay .xUi-dropdown-item{border-radius:8px;color:var(--xui-text-color);cursor:pointer;font-size:14px;list-style:none;padding:8px 12px;user-select:none}.xUi-dropdown-overlay .xUi-dropdown-item:focus,.xUi-dropdown-overlay .xUi-dropdown-item:hover{background:var(--xui-color-hover);outline:none}.xUi-dropdown-overlay .xUi-dropdown-item.disabled{cursor:not-allowed;opacity:.5}.xUi-dropdown-overlay .xUi-dropdown-item.danger{color:var(--xui-error-color-light);&:hover{background-color:var(--xui-error-color-light);color:var(--xui-background-color)}}.xUi-dropdown-arrow{background:var(--xui-background-color);border-left:.5px solid var(--xui-border-color);border-top:.5px solid var(--xui-border-color);height:10px;left:12px;position:absolute;top:-6px;transform:rotate(45deg);width:10px}.xUi-dropdown-bottomRight .xUi-dropdown-arrow,.xUi-dropdown-right .xUi-dropdown-arrow,.xUi-dropdown-topRight .xUi-dropdown-arrow{left:unset;right:12px}.xUi-dropdown-arrow.bottom{border-bottom:.5px solid var(--xui-border-color);border-left:unset;border-right:.5px solid var(--xui-border-color);border-top:unset;bottom:-6px;top:unset}.xUi-dropdown-arrow.center{left:0;margin:0 auto;right:0}";
5325
5357
  styleInject(css_248z$2);
5326
5358
 
5327
5359
  const Dropdown = ({
@@ -5351,7 +5383,7 @@ const Dropdown = ({
5351
5383
  const popupRef = useRef(null);
5352
5384
  const menuRef = useRef(null);
5353
5385
  const {
5354
- shouldShowAbove,
5386
+ showPlacement,
5355
5387
  dropdownPosition
5356
5388
  } = usePosition({
5357
5389
  popupRef,
@@ -5421,14 +5453,14 @@ const Dropdown = ({
5421
5453
  wrapper: element => getPopupContainer ? /*#__PURE__*/createPortal(element, getPopupContainer(popupRef.current)) : /*#__PURE__*/React.createElement(React.Fragment, null, element)
5422
5454
  }, /*#__PURE__*/React.createElement("div", {
5423
5455
  ref: popupRef,
5424
- className: `${prefixCls}-overlay ${overlayClassName}`,
5456
+ className: `${prefixCls}-overlay ${prefixCls}-${placement} ${overlayClassName}`,
5425
5457
  style: {
5426
5458
  zIndex: _hover ? 1000 : 0,
5427
5459
  ...overlayStyle,
5428
5460
  ...dropdownPosition
5429
5461
  }
5430
5462
  }, arrow && /*#__PURE__*/React.createElement("div", {
5431
- className: `${prefixCls}-arrow ${shouldShowAbove ? 'bottom' : ''}`
5463
+ className: `${prefixCls}-arrow ${showPlacement ? 'bottom' : ''}`
5432
5464
  }), overlay ? typeof overlay === 'function' ? overlay() : overlay : popupRender ? popupRender(menu ? /*#__PURE__*/React.createElement(MenuInner, {
5433
5465
  prefixCls: prefixCls,
5434
5466
  items: menu.items,
@@ -5497,7 +5529,7 @@ var Dropdown$1 = /*#__PURE__*/Object.freeze({
5497
5529
  default: Dropdown
5498
5530
  });
5499
5531
 
5500
- var css_248z$1 = ".xUi-popover{&:before{content:\"\";height:8px;left:0;position:absolute;top:-8px;width:100%;z-index:10000}}.xUi-popover-wrapper{display:inline-block;position:relative}.xUi-popover-wrapper-content{cursor:pointer}.xUi-popover{background:var(--xui-background-color);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);padding:8px 12px;width:max-content;z-index:1000}.xUi-popover-title{padding:4px}.xUi-popover-inner{color:var(--xui-text-color);font-size:14px}.xUi-popover-arrow{background:var(--xui-background-color);border-left:.5px solid var(--xui-border-color);border-top:.5px solid var(--xui-border-color);height:10px;left:12px;position:absolute;top:-6px;transform:rotate(45deg);width:10px}.xUi-popover-arrow.bottom{border-bottom:.5px solid var(--xui-border-color);border-left:unset;border-right:.5px solid var(--xui-border-color);border-top:unset;bottom:-6px;top:unset}";
5532
+ var css_248z$1 = ".xUi-popover{&:before{content:\"\";height:10px;left:0;position:absolute;top:-10px;width:100%;z-index:10000}}.xUi-popover-wrapper-content{cursor:pointer;max-width:fit-content;width:-webkit-fill-available}.xUi-popover{background:var(--xui-background-color);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);padding:8px 12px;width:max-content;z-index:1000}.xUi-popover-title{padding:4px}.xUi-popover-inner{color:var(--xui-text-color);font-size:14px}.xUi-popover-arrow{background:var(--xui-background-color);border-left:.5px solid var(--xui-border-color);border-top:.5px solid var(--xui-border-color);height:10px;left:12px;position:absolute;top:-6px;transform:rotate(45deg);width:10px}.xUi-popover-bottomRight .xUi-popover-arrow,.xUi-popover-right .xUi-popover-arrow,.xUi-popover-topRight .xUi-popover-arrow{left:unset;right:12px}.xUi-popover-arrow.bottom{border-bottom:.5px solid var(--xui-border-color);border-left:unset;border-right:.5px solid var(--xui-border-color);border-top:unset;bottom:-6px;top:unset}.xUi-popover-arrow.center{left:0;margin:0 auto;right:0}";
5501
5533
  styleInject(css_248z$1);
5502
5534
 
5503
5535
  const Popover = ({
@@ -5509,6 +5541,7 @@ const Popover = ({
5509
5541
  open,
5510
5542
  visible,
5511
5543
  title,
5544
+ style = {},
5512
5545
  overlayClassName = '',
5513
5546
  overlayStyle = {},
5514
5547
  onVisibleChange,
@@ -5521,7 +5554,7 @@ const Popover = ({
5521
5554
  const isOpen = visible !== undefined ? visible : open !== undefined ? open : innerOpen;
5522
5555
  const {
5523
5556
  dropdownPosition,
5524
- shouldShowAbove
5557
+ showPlacement
5525
5558
  } = usePosition({
5526
5559
  isOpen,
5527
5560
  offset: 10,
@@ -5530,41 +5563,62 @@ const Popover = ({
5530
5563
  triggerRef,
5531
5564
  getPopupContainer: getPopupContainer?.(triggerRef.current)
5532
5565
  });
5533
- const toggle = () => {
5566
+ useEffect(() => {
5567
+ const handleClickOutside = e => {
5568
+ if (popupRef.current && !popupRef.current.contains(e.target) && triggerRef.current && !triggerRef.current.contains(e.target)) {
5569
+ setInnerOpen(false);
5570
+ onVisibleChange?.(false);
5571
+ }
5572
+ };
5573
+ document.addEventListener('mousedown', handleClickOutside);
5574
+ return () => {
5575
+ document.removeEventListener('mousedown', handleClickOutside);
5576
+ };
5577
+ }, []);
5578
+ const handleOnClick = useCallback(() => {
5534
5579
  const newState = !isOpen;
5535
5580
  onVisibleChange?.(newState);
5536
5581
  setInnerOpen(newState);
5537
- };
5538
- const show = () => {
5582
+ }, [isOpen, trigger]);
5583
+ const handleOnMouseEnter = useCallback(() => {
5539
5584
  setHover(true);
5540
5585
  if (trigger === "hover") {
5541
5586
  onVisibleChange?.(true);
5542
5587
  setInnerOpen(true);
5543
5588
  }
5544
- };
5545
- const hide = () => {
5589
+ }, [trigger]);
5590
+ const handleOnMouseLeave = useCallback(() => {
5546
5591
  setHover(false);
5547
5592
  if (trigger === "hover") {
5548
5593
  onVisibleChange?.(false);
5549
5594
  setInnerOpen(false);
5550
5595
  }
5551
- };
5552
- const childProps = trigger === "click" ? {
5553
- onClick: toggle
5596
+ }, [trigger]);
5597
+ const childProps = useMemo(() => trigger === "click" ? {
5598
+ onClick: handleOnClick
5554
5599
  } : {
5555
- onMouseEnter: show,
5556
- onMouseLeave: hide
5557
- };
5558
- return /*#__PURE__*/React.createElement("div", {
5559
- className: `${prefixCls}-wrapper`
5560
- }, /*#__PURE__*/React.createElement("div", _extends({
5561
- ref: triggerRef,
5562
- className: `${prefixCls}-wrapper-content`
5563
- }, childProps), children), isOpen && /*#__PURE__*/React.createElement(ConditionalWrapper, {
5600
+ onMouseEnter: handleOnMouseEnter,
5601
+ onMouseLeave: handleOnMouseLeave
5602
+ }, [trigger]);
5603
+ return /*#__PURE__*/React.createElement(React.Fragment, null, Children.map(children, (child, index) => {
5604
+ if (! /*#__PURE__*/isValidElement(child)) {
5605
+ child = /*#__PURE__*/React.createElement("div", null, child);
5606
+ }
5607
+ return /*#__PURE__*/cloneElement(child, {
5608
+ key: index,
5609
+ ...childProps,
5610
+ ...(index === 0 ? {
5611
+ ref: triggerRef,
5612
+ style,
5613
+ className: `${prefixCls}-wrapper-content`
5614
+ } : {})
5615
+ });
5616
+ }), isOpen && /*#__PURE__*/React.createElement(ConditionalWrapper, {
5564
5617
  condition: !!getPopupContainer,
5565
5618
  wrapper: element => getPopupContainer ? /*#__PURE__*/createPortal(element, getPopupContainer(popupRef.current)) : /*#__PURE__*/React.createElement(React.Fragment, null, element)
5566
- }, /*#__PURE__*/React.createElement("div", {
5567
- ref: popupRef,
5619
+ }, /*#__PURE__*/React.createElement("div", _extends({
5620
+ ref: popupRef
5621
+ }, childProps, {
5568
5622
  className: clsx(prefixCls, `${prefixCls}-${placement}`, overlayClassName),
5569
5623
  style: {
5570
5624
  zIndex: hover ? 1000 : 1,
@@ -5572,12 +5626,12 @@ const Popover = ({
5572
5626
  ...overlayStyle,
5573
5627
  ...dropdownPosition
5574
5628
  }
5575
- }, title && /*#__PURE__*/React.createElement("div", {
5629
+ }), title && /*#__PURE__*/React.createElement("div", {
5576
5630
  className: `${prefixCls}-title`
5577
5631
  }, title), /*#__PURE__*/React.createElement("div", {
5578
5632
  className: `${prefixCls}-inner`
5579
5633
  }, content), /*#__PURE__*/React.createElement("div", {
5580
- className: `${prefixCls}-arrow ${shouldShowAbove ? 'bottom' : ''}`
5634
+ className: `${prefixCls}-arrow ${showPlacement}`
5581
5635
  }))));
5582
5636
  };
5583
5637