@zenkigen-inc/component-ui 1.14.4 → 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/README.md +0 -5
- package/dist/hooks/use-outside-click.d.ts +1 -1
- package/dist/index.esm.js +128 -29
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +137 -32
- 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 +4 -4
package/README.md
CHANGED
|
@@ -44,11 +44,6 @@ yarn generate-component
|
|
|
44
44
|
|
|
45
45
|
使用する側の import を簡略化させるため root にある [packages/component-ui/src/index.ts](https://github.com/zenkigen/zenkigen-component/blob/main/packages/components/src/index.ts) に実装したコンポーネントを export してください。
|
|
46
46
|
|
|
47
|
-
### コーディングガイドライン(社内のみ)
|
|
48
|
-
|
|
49
|
-
開発する際は以下を参照してください。
|
|
50
|
-
https://www.notion.so/zenkigen/5d4ebd0d93b74124a533cf167b852ec0
|
|
51
|
-
|
|
52
47
|
## ライセンス
|
|
53
48
|
|
|
54
49
|
@zenkigen-inc/component-ui は MIT ライセンスに基づいています。
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { RefObject } from 'react';
|
|
2
|
-
export declare const useOutsideClick: <T extends HTMLElement = HTMLElement>(ref: RefObject<T>, handler: (event: Event) => void, enabled?: boolean) => void;
|
|
2
|
+
export declare const useOutsideClick: <T extends HTMLElement = HTMLElement>(ref: RefObject<T | null>, handler: (event: Event) => void, enabled?: boolean) => void;
|
package/dist/index.esm.js
CHANGED
|
@@ -18,7 +18,7 @@ function _objectWithoutPropertiesLoose(r, e) {
|
|
|
18
18
|
if (null == r) return {};
|
|
19
19
|
var t = {};
|
|
20
20
|
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
21
|
-
if (e.
|
|
21
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
22
22
|
t[n] = r[n];
|
|
23
23
|
}
|
|
24
24
|
return t;
|
|
@@ -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;
|
|
@@ -1602,15 +1702,18 @@ var TextInput = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
1602
1702
|
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
1603
1703
|
onClickClearButton = _ref.onClickClearButton,
|
|
1604
1704
|
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
1705
|
+
var isShowClearButton = !!onClickClearButton && props.value.length !== 0 && !disabled;
|
|
1605
1706
|
var inputWrapClasses = clsx('relative flex items-center gap-2 overflow-hidden rounded border', {
|
|
1606
1707
|
'border-uiBorder02': !isError && !disabled,
|
|
1607
1708
|
'border-supportError': isError && !disabled,
|
|
1608
1709
|
'hover:border-hoverInput': !disabled && !isError,
|
|
1609
1710
|
'hover:focus-within:border-activeInput': !isError,
|
|
1610
1711
|
'focus-within:border-activeInput': !isError,
|
|
1611
|
-
'bg-disabled02 border-disabled01': disabled
|
|
1712
|
+
'bg-disabled02 border-disabled01': disabled,
|
|
1713
|
+
'pr-2': size === 'medium' && isShowClearButton,
|
|
1714
|
+
'pr-3': size === 'large' && isShowClearButton
|
|
1612
1715
|
});
|
|
1613
|
-
var inputClasses = clsx('flex-1
|
|
1716
|
+
var inputClasses = clsx('flex-1 outline-0 placeholder:text-textPlaceholder disabled:text-textPlaceholder', (_clsx = {}, _clsx['typography-label14regular min-h-8 px-2'] = size === 'medium', _clsx['typography-label16regular min-h-10 px-3'] = size === 'large', _clsx['text-text01'] = !isError, _clsx['text-supportError'] = isError, _clsx['pr-0'] = isShowClearButton, _clsx));
|
|
1614
1717
|
return /*#__PURE__*/jsxs("div", {
|
|
1615
1718
|
className: inputWrapClasses,
|
|
1616
1719
|
children: [/*#__PURE__*/jsx("input", _extends({
|
|
@@ -1619,15 +1722,11 @@ var TextInput = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
1619
1722
|
className: inputClasses,
|
|
1620
1723
|
disabled: disabled,
|
|
1621
1724
|
onChange: props.onChange
|
|
1622
|
-
}, props)),
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
size: "small",
|
|
1628
|
-
isNoPadding: true,
|
|
1629
|
-
onClick: onClickClearButton
|
|
1630
|
-
})
|
|
1725
|
+
}, props)), isShowClearButton && /*#__PURE__*/jsx(IconButton, {
|
|
1726
|
+
variant: "text",
|
|
1727
|
+
icon: "close",
|
|
1728
|
+
size: "small",
|
|
1729
|
+
onClick: onClickClearButton
|
|
1631
1730
|
})]
|
|
1632
1731
|
});
|
|
1633
1732
|
});
|
|
@@ -1745,7 +1844,7 @@ var ToastProvider = function ToastProvider(_ref) {
|
|
|
1745
1844
|
addToast: addToast,
|
|
1746
1845
|
removeToast: removeToast
|
|
1747
1846
|
},
|
|
1748
|
-
children: [children, isClientRender && /*#__PURE__*/createPortal(
|
|
1847
|
+
children: [children, isClientRender && /*#__PURE__*/createPortal(/*#__PURE__*/jsx("div", {
|
|
1749
1848
|
className: "pointer-events-none fixed bottom-0 left-0 z-toast mb-4 ml-4 flex w-full flex-col-reverse gap-[16px]",
|
|
1750
1849
|
children: toasts.map(function (_ref3) {
|
|
1751
1850
|
var id = _ref3.id,
|
|
@@ -1784,7 +1883,7 @@ function Toggle(_ref) {
|
|
|
1784
1883
|
'bg-disabledOn': isDisabled && isChecked,
|
|
1785
1884
|
'bg-disabled01': isDisabled && !isChecked,
|
|
1786
1885
|
'bg-interactive01 peer-hover:bg-hover01': !isDisabled && isChecked,
|
|
1787
|
-
'bg-interactive02 peer-hover:bg-
|
|
1886
|
+
'bg-interactive02 peer-hover:bg-hoverGray': !isDisabled && !isChecked,
|
|
1788
1887
|
'w-8 h-4 px-[3px]': size === 'small',
|
|
1789
1888
|
'w-12 h-6 px-1': size === 'medium' || size === 'large'
|
|
1790
1889
|
});
|
|
@@ -2032,7 +2131,7 @@ function Tooltip(_ref) {
|
|
|
2032
2131
|
verticalPosition: verticalPosition,
|
|
2033
2132
|
horizontalAlign: horizontalAlign,
|
|
2034
2133
|
tooltipPosition: tooltipPosition
|
|
2035
|
-
}) : (
|
|
2134
|
+
}) : (/*#__PURE__*/createPortal(/*#__PURE__*/jsx(TooltipContent, {
|
|
2036
2135
|
isPortal: true,
|
|
2037
2136
|
content: content,
|
|
2038
2137
|
size: size,
|