@designbasekorea/ui 0.2.9 → 0.2.12
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.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +114 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +114 -2
- package/dist/index.js.map +1 -1
- package/dist/index.umd.css +1 -1
- package/dist/index.umd.css.map +1 -1
- package/dist/index.umd.js +114 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10855,8 +10855,11 @@ Table.displayName = 'Table';
|
|
|
10855
10855
|
const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal', size = 'm', fullWidth = false, variant = 'default', className, onTabChange, ...props }) => {
|
|
10856
10856
|
const [activeTabId, setActiveTabId] = React.useState(selectedId ?? defaultSelectedId ?? items[0]?.id ?? '');
|
|
10857
10857
|
const [focusedTabId, setFocusedTabId] = React.useState('');
|
|
10858
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
10858
10859
|
const tabListRef = React.useRef(null);
|
|
10859
10860
|
const tabRefs = React.useRef(new Map());
|
|
10861
|
+
const dragStartRef = React.useRef(null);
|
|
10862
|
+
const clickStartRef = React.useRef(null);
|
|
10860
10863
|
// 제어 컴포넌트 처리
|
|
10861
10864
|
React.useEffect(() => {
|
|
10862
10865
|
if (selectedId !== undefined) {
|
|
@@ -10928,18 +10931,126 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
|
|
|
10928
10931
|
}
|
|
10929
10932
|
}, [items, orientation]);
|
|
10930
10933
|
const handleTabSelect = React.useCallback((tabId) => {
|
|
10934
|
+
// 드래그 중이면 탭 선택 무시
|
|
10935
|
+
if (isDragging)
|
|
10936
|
+
return;
|
|
10931
10937
|
const tab = items.find(item => item.id === tabId);
|
|
10932
10938
|
if (tab && !tab.disabled) {
|
|
10933
10939
|
setActiveTabId(tabId);
|
|
10934
10940
|
onTabChange?.(tabId);
|
|
10935
10941
|
}
|
|
10936
|
-
}, [items, onTabChange]);
|
|
10942
|
+
}, [items, onTabChange, isDragging]);
|
|
10937
10943
|
const handleTabFocus = React.useCallback((tabId) => {
|
|
10938
10944
|
setFocusedTabId(tabId);
|
|
10939
10945
|
}, []);
|
|
10940
10946
|
const handleTabBlur = React.useCallback(() => {
|
|
10941
10947
|
setFocusedTabId('');
|
|
10942
10948
|
}, []);
|
|
10949
|
+
// 드래그 스크롤 핸들러들
|
|
10950
|
+
const handleMouseDown = React.useCallback((e) => {
|
|
10951
|
+
if (orientation !== 'horizontal' || !tabListRef.current)
|
|
10952
|
+
return;
|
|
10953
|
+
// 클릭 시작 위치와 시간 기록
|
|
10954
|
+
clickStartRef.current = {
|
|
10955
|
+
x: e.pageX,
|
|
10956
|
+
y: e.pageY,
|
|
10957
|
+
time: Date.now()
|
|
10958
|
+
};
|
|
10959
|
+
dragStartRef.current = {
|
|
10960
|
+
x: e.pageX - tabListRef.current.offsetLeft,
|
|
10961
|
+
scrollLeft: tabListRef.current.scrollLeft
|
|
10962
|
+
};
|
|
10963
|
+
}, [orientation]);
|
|
10964
|
+
const handleMouseMove = React.useCallback((e) => {
|
|
10965
|
+
if (!dragStartRef.current || !tabListRef.current)
|
|
10966
|
+
return;
|
|
10967
|
+
// 아직 드래그가 시작되지 않았다면 드래그 시작 여부 판단
|
|
10968
|
+
if (!isDragging && clickStartRef.current) {
|
|
10969
|
+
const deltaX = Math.abs(e.pageX - clickStartRef.current.x);
|
|
10970
|
+
const deltaY = Math.abs(e.pageY - clickStartRef.current.y);
|
|
10971
|
+
const deltaTime = Date.now() - clickStartRef.current.time;
|
|
10972
|
+
// 5px 이상 이동하거나 200ms 이상 지났으면 드래그 시작
|
|
10973
|
+
if (deltaX > 5 || deltaY > 5 || deltaTime > 200) {
|
|
10974
|
+
setIsDragging(true);
|
|
10975
|
+
}
|
|
10976
|
+
}
|
|
10977
|
+
if (!isDragging || !dragStartRef.current)
|
|
10978
|
+
return;
|
|
10979
|
+
e.preventDefault();
|
|
10980
|
+
const x = e.pageX - tabListRef.current.offsetLeft;
|
|
10981
|
+
const walk = (x - dragStartRef.current.x) * 2; // 스크롤 속도 조절
|
|
10982
|
+
tabListRef.current.scrollLeft = dragStartRef.current.scrollLeft - walk;
|
|
10983
|
+
}, [isDragging]);
|
|
10984
|
+
const handleMouseUp = React.useCallback(() => {
|
|
10985
|
+
setIsDragging(false);
|
|
10986
|
+
dragStartRef.current = null;
|
|
10987
|
+
clickStartRef.current = null;
|
|
10988
|
+
}, []);
|
|
10989
|
+
const handleMouseLeave = React.useCallback(() => {
|
|
10990
|
+
setIsDragging(false);
|
|
10991
|
+
dragStartRef.current = null;
|
|
10992
|
+
clickStartRef.current = null;
|
|
10993
|
+
}, []);
|
|
10994
|
+
// 터치 이벤트 핸들러들
|
|
10995
|
+
const handleTouchStart = React.useCallback((e) => {
|
|
10996
|
+
if (orientation !== 'horizontal' || !tabListRef.current)
|
|
10997
|
+
return;
|
|
10998
|
+
const touch = e.touches[0];
|
|
10999
|
+
// 클릭 시작 위치와 시간 기록
|
|
11000
|
+
clickStartRef.current = {
|
|
11001
|
+
x: touch.pageX,
|
|
11002
|
+
y: touch.pageY,
|
|
11003
|
+
time: Date.now()
|
|
11004
|
+
};
|
|
11005
|
+
dragStartRef.current = {
|
|
11006
|
+
x: touch.pageX - tabListRef.current.offsetLeft,
|
|
11007
|
+
scrollLeft: tabListRef.current.scrollLeft
|
|
11008
|
+
};
|
|
11009
|
+
}, [orientation]);
|
|
11010
|
+
const handleTouchMove = React.useCallback((e) => {
|
|
11011
|
+
if (!dragStartRef.current || !tabListRef.current)
|
|
11012
|
+
return;
|
|
11013
|
+
// 아직 드래그가 시작되지 않았다면 드래그 시작 여부 판단
|
|
11014
|
+
if (!isDragging && clickStartRef.current) {
|
|
11015
|
+
const touch = e.touches[0];
|
|
11016
|
+
const deltaX = Math.abs(touch.pageX - clickStartRef.current.x);
|
|
11017
|
+
const deltaY = Math.abs(touch.pageY - clickStartRef.current.y);
|
|
11018
|
+
const deltaTime = Date.now() - clickStartRef.current.time;
|
|
11019
|
+
// 5px 이상 이동하거나 200ms 이상 지났으면 드래그 시작
|
|
11020
|
+
if (deltaX > 5 || deltaY > 5 || deltaTime > 200) {
|
|
11021
|
+
setIsDragging(true);
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11024
|
+
if (!isDragging || !dragStartRef.current)
|
|
11025
|
+
return;
|
|
11026
|
+
e.preventDefault();
|
|
11027
|
+
const touch = e.touches[0];
|
|
11028
|
+
const x = touch.pageX - tabListRef.current.offsetLeft;
|
|
11029
|
+
const walk = (x - dragStartRef.current.x) * 2; // 스크롤 속도 조절
|
|
11030
|
+
tabListRef.current.scrollLeft = dragStartRef.current.scrollLeft - walk;
|
|
11031
|
+
}, [isDragging]);
|
|
11032
|
+
const handleTouchEnd = React.useCallback(() => {
|
|
11033
|
+
setIsDragging(false);
|
|
11034
|
+
dragStartRef.current = null;
|
|
11035
|
+
clickStartRef.current = null;
|
|
11036
|
+
}, []);
|
|
11037
|
+
// 드래그 이벤트 리스너 등록/해제
|
|
11038
|
+
React.useEffect(() => {
|
|
11039
|
+
if (isDragging) {
|
|
11040
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
11041
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
11042
|
+
document.addEventListener('mouseleave', handleMouseLeave);
|
|
11043
|
+
document.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
11044
|
+
document.addEventListener('touchend', handleTouchEnd);
|
|
11045
|
+
}
|
|
11046
|
+
return () => {
|
|
11047
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
11048
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
11049
|
+
document.removeEventListener('mouseleave', handleMouseLeave);
|
|
11050
|
+
document.removeEventListener('touchmove', handleTouchMove);
|
|
11051
|
+
document.removeEventListener('touchend', handleTouchEnd);
|
|
11052
|
+
};
|
|
11053
|
+
}, [isDragging, handleMouseMove, handleMouseUp, handleMouseLeave, handleTouchMove, handleTouchEnd]);
|
|
10943
11054
|
const activeTab = items.find(item => item.id === activeTabId);
|
|
10944
11055
|
items.findIndex(item => item.id === activeTabId);
|
|
10945
11056
|
const classes = clsx('designbase-tabs', `designbase-tabs--${orientation}`, `designbase-tabs--${size}`, `designbase-tabs--${variant}`, {
|
|
@@ -10947,8 +11058,9 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
|
|
|
10947
11058
|
}, className);
|
|
10948
11059
|
const tabListClasses = clsx('designbase-tabs__list', `designbase-tabs__list--${orientation}`, {
|
|
10949
11060
|
'designbase-tabs__list--full-width': fullWidth,
|
|
11061
|
+
'designbase-tabs__list--dragging': isDragging,
|
|
10950
11062
|
});
|
|
10951
|
-
return (jsxRuntime.jsxs("div", { className: classes, ...props, children: [jsxRuntime.jsx("div", { ref: tabListRef, className: tabListClasses, role: "tablist", "aria-orientation": orientation, "aria-label": "\uD0ED \uBAA9\uB85D", children: items.map((item, index) => {
|
|
11063
|
+
return (jsxRuntime.jsxs("div", { className: classes, ...props, children: [jsxRuntime.jsx("div", { ref: tabListRef, className: tabListClasses, role: "tablist", "aria-orientation": orientation, "aria-label": "\uD0ED \uBAA9\uB85D", onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, children: items.map((item, index) => {
|
|
10952
11064
|
const isSelected = item.id === activeTabId;
|
|
10953
11065
|
const isFocused = item.id === focusedTabId;
|
|
10954
11066
|
const isDisabled = item.disabled;
|