@zenkigen-inc/component-ui 1.14.5 → 1.15.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/dist/index.esm.js CHANGED
@@ -628,6 +628,104 @@ function Loading(_ref) {
628
628
  });
629
629
  }
630
630
 
631
+ /**
632
+ * モーダル表示時にバックグラウンドのスクロールを防止するコンポーネント。
633
+ * コンポーネントがマウントされている間、position: fixedアプローチを使用して
634
+ * body要素にスクロールロックを適用します。
635
+ * 縦横両方のスクロール位置を保存し、コンポーネントのアンマウント時に復元します。
636
+ * スクロールバーの有無を検出し、その幅を考慮してレイアウトシフトを防止します。
637
+ * position、top、left、width、overflow、padding-rightを変更し、
638
+ * 最小限の変更でスクロールを防止します。
639
+ * グローバルCSSに依存せず、すべてインラインスタイルで実装されています。
640
+ * このコンポーネントは実際のDOM要素をレンダリングせず、効果のみを適用します。
641
+ *
642
+ * @example
643
+ * // モーダルコンポーネント内で使用する例
644
+ * const Modal = ({ isOpen, children }) => {
645
+ * return (
646
+ * <>
647
+ * {isOpen && <BodyScrollLock />}
648
+ * {isOpen && (
649
+ * <div className="modal">
650
+ * {children}
651
+ * </div>
652
+ * )}
653
+ * </>
654
+ * );
655
+ * };
656
+ */
657
+ var BodyScrollLock = function BodyScrollLock() {
658
+ useLayoutEffect(function () {
659
+ // 現在の縦横スクロール位置を記録
660
+ var _window = window,
661
+ scrollX = _window.scrollX,
662
+ scrollY = _window.scrollY;
663
+ var _document = document,
664
+ body = _document.body;
665
+ // スクロールバーの有無と幅を検出
666
+ var hasVerticalScrollbar = document.documentElement.scrollHeight > document.documentElement.clientHeight;
667
+ var scrollbarWidth = hasVerticalScrollbar ? window.innerWidth - document.documentElement.clientWidth : 0;
668
+ // 元のインラインスタイルの値を保存
669
+ var originalInlineStyles = {
670
+ position: body.style.position,
671
+ top: body.style.top,
672
+ left: body.style.left,
673
+ width: body.style.width,
674
+ overflow: body.style.overflow,
675
+ paddingRight: body.style.paddingRight
676
+ };
677
+ // スクロールロックスタイルを適用
678
+ body.style.position = 'fixed';
679
+ body.style.top = "-" + scrollY + "px";
680
+ body.style.left = "-" + scrollX + "px";
681
+ body.style.width = '100%';
682
+ body.style.overflow = 'hidden';
683
+ // スクロールバーがある場合、その幅分だけpadding-rightを調整
684
+ if (hasVerticalScrollbar && scrollbarWidth > 0) {
685
+ // 現在のpadding-rightの値を取得
686
+ var _window$getComputedSt = window.getComputedStyle(body),
687
+ paddingRight = _window$getComputedSt.paddingRight;
688
+ var paddingRightValue = paddingRight !== '' ? parseInt(paddingRight, 10) : 0;
689
+ // スクロールバーの幅を加算
690
+ body.style.paddingRight = paddingRightValue + scrollbarWidth + "px";
691
+ }
692
+ // クリーンアップ関数
693
+ return function () {
694
+ // 元のスタイル値を取得
695
+ var position = originalInlineStyles.position,
696
+ top = originalInlineStyles.top,
697
+ left = originalInlineStyles.left,
698
+ width = originalInlineStyles.width,
699
+ overflow = originalInlineStyles.overflow,
700
+ paddingRight = originalInlineStyles.paddingRight;
701
+ // プロパティごとに元の値を復元
702
+ restoreProperty(body, 'position', position);
703
+ restoreProperty(body, 'top', top);
704
+ restoreProperty(body, 'left', left);
705
+ restoreProperty(body, 'width', width);
706
+ restoreProperty(body, 'overflow', overflow);
707
+ restoreProperty(body, 'padding-right', paddingRight);
708
+ // スクロール位置を復元
709
+ window.scrollTo(scrollX, scrollY);
710
+ };
711
+ }, []); // 空の依存配列を指定して初回のみ実行
712
+ // DOM要素をレンダリングせず、nullを返す
713
+ return null;
714
+ };
715
+ /**
716
+ * 元のスタイル値を復元するヘルパー関数
717
+ * @param element スタイルを復元する要素
718
+ * @param property 復元するCSSプロパティ名
719
+ * @param value 復元する値
720
+ */
721
+ function restoreProperty(element, property, value) {
722
+ if (value !== '') {
723
+ element.style.setProperty(property, value);
724
+ } else {
725
+ element.style.removeProperty(property);
726
+ }
727
+ }
728
+
631
729
  function ModalBody(_ref) {
632
730
  var children = _ref.children;
633
731
  return /*#__PURE__*/jsx("div", {
@@ -697,22 +795,24 @@ function Modal(_ref) {
697
795
  useEffect(function () {
698
796
  setIsMounted(true);
699
797
  }, []);
700
- return isMounted && isOpen ? /*#__PURE__*/createPortal(/*#__PURE__*/jsx(ModalContext.Provider, {
701
- value: {
702
- onClose: onClose
703
- },
704
- children: /*#__PURE__*/jsx("div", {
705
- className: "fixed left-0 top-0 z-overlay flex size-full items-center justify-center bg-backgroundOverlayBlack py-4",
798
+ return isMounted && isOpen ? /*#__PURE__*/jsxs(Fragment, {
799
+ children: [/*#__PURE__*/jsx(BodyScrollLock, {}), /*#__PURE__*/createPortal(/*#__PURE__*/jsx(ModalContext.Provider, {
800
+ value: {
801
+ onClose: onClose
802
+ },
706
803
  children: /*#__PURE__*/jsx("div", {
707
- className: "grid max-h-full min-h-[120px] grid-rows-[max-content_1fr_max-content] flex-col rounded-lg bg-uiBackground01 shadow-modalShadow",
708
- style: {
709
- width: renderWidth,
710
- height: renderHeight
711
- },
712
- children: children
804
+ className: "fixed left-0 top-0 z-overlay flex size-full items-center justify-center bg-backgroundOverlayBlack py-4",
805
+ children: /*#__PURE__*/jsx("div", {
806
+ className: "grid max-h-full min-h-[120px] grid-rows-[max-content_1fr_max-content] flex-col rounded-lg bg-uiBackground01 shadow-modalShadow",
807
+ style: {
808
+ width: renderWidth,
809
+ height: renderHeight
810
+ },
811
+ children: children
812
+ })
713
813
  })
714
- })
715
- }), (portalTargetRef == null ? void 0 : portalTargetRef.current) != null ? portalTargetRef.current : document.body) : null;
814
+ }), (portalTargetRef == null ? void 0 : portalTargetRef.current) != null ? portalTargetRef.current : document.body)]
815
+ }) : null;
716
816
  }
717
817
  Modal.Body = ModalBody;
718
818
  Modal.Header = ModalHeader;
@@ -1783,7 +1883,7 @@ function Toggle(_ref) {
1783
1883
  'bg-disabledOn': isDisabled && isChecked,
1784
1884
  'bg-disabled01': isDisabled && !isChecked,
1785
1885
  'bg-interactive01 peer-hover:bg-hover01': !isDisabled && isChecked,
1786
- 'bg-interactive02 peer-hover:bg-hover02Dark': !isDisabled && !isChecked,
1886
+ 'bg-interactive02 peer-hover:bg-hoverGray': !isDisabled && !isChecked,
1787
1887
  'w-8 h-4 px-[3px]': size === 'small',
1788
1888
  'w-12 h-6 px-1': size === 'medium' || size === 'large'
1789
1889
  });