@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 +115 -15
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +120 -15
- package/dist/index.js.map +1 -1
- package/dist/modal/body-scroll-lock.d.ts +27 -0
- package/dist/modal/modal.d.ts +1 -1
- package/package.json +3 -3
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__*/
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
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: "
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
})
|
|
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-
|
|
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
|
});
|