@designbasekorea/ui 0.2.10 → 0.2.13
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.d.ts +3 -0
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +121 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +121 -4
- 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 +121 -4
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5279,7 +5279,7 @@ const Chip = ({ label, size = 'm', variant = 'default', color = 'primary', delet
|
|
|
5279
5279
|
};
|
|
5280
5280
|
Chip.displayName = 'Chip';
|
|
5281
5281
|
|
|
5282
|
-
const ColorPicker = ({ size = 'm', type = 'dropdown', value, defaultValue = '#006FFF', showInput = true, showAlpha = false, showFormatSelector = true, showCopyButton = true, disabled = false, readonly = false, onChange, className, }) => {
|
|
5282
|
+
const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left', value, defaultValue = '#006FFF', showInput = true, showAlpha = false, showFormatSelector = true, showCopyButton = true, disabled = false, readonly = false, onChange, className, }) => {
|
|
5283
5283
|
const [selectedColor, setSelectedColor] = React.useState(value || defaultValue);
|
|
5284
5284
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
5285
5285
|
const [hue, setHue] = React.useState(211);
|
|
@@ -5425,6 +5425,11 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', value, defaultValue = '#00
|
|
|
5425
5425
|
const handleInputChange = (e) => {
|
|
5426
5426
|
const newValue = e.target.value.trim();
|
|
5427
5427
|
setInputValue(newValue);
|
|
5428
|
+
// HEX 값이 유효하면 실시간으로 색상 업데이트
|
|
5429
|
+
if (/^#[0-9A-F]{6}$/i.test(newValue)) {
|
|
5430
|
+
handleColorChange(newValue.toUpperCase());
|
|
5431
|
+
updateHSLFromHex(newValue);
|
|
5432
|
+
}
|
|
5428
5433
|
};
|
|
5429
5434
|
// 입력 필드에서 포커스 아웃 시 검증 및 적용
|
|
5430
5435
|
const handleInputBlur = () => {
|
|
@@ -5512,7 +5517,7 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', value, defaultValue = '#00
|
|
|
5512
5517
|
return;
|
|
5513
5518
|
setIsOpen(!isOpen);
|
|
5514
5519
|
};
|
|
5515
|
-
const classes = clsx('designbase-color-picker', `designbase-color-picker--${size}`, {
|
|
5520
|
+
const classes = clsx('designbase-color-picker', `designbase-color-picker--${size}`, `designbase-color-picker--${position}`, {
|
|
5516
5521
|
'designbase-color-picker--disabled': disabled,
|
|
5517
5522
|
'designbase-color-picker--readonly': readonly,
|
|
5518
5523
|
'designbase-color-picker--open': isOpen,
|
|
@@ -10855,8 +10860,11 @@ Table.displayName = 'Table';
|
|
|
10855
10860
|
const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal', size = 'm', fullWidth = false, variant = 'default', className, onTabChange, ...props }) => {
|
|
10856
10861
|
const [activeTabId, setActiveTabId] = React.useState(selectedId ?? defaultSelectedId ?? items[0]?.id ?? '');
|
|
10857
10862
|
const [focusedTabId, setFocusedTabId] = React.useState('');
|
|
10863
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
10858
10864
|
const tabListRef = React.useRef(null);
|
|
10859
10865
|
const tabRefs = React.useRef(new Map());
|
|
10866
|
+
const dragStartRef = React.useRef(null);
|
|
10867
|
+
const clickStartRef = React.useRef(null);
|
|
10860
10868
|
// 제어 컴포넌트 처리
|
|
10861
10869
|
React.useEffect(() => {
|
|
10862
10870
|
if (selectedId !== undefined) {
|
|
@@ -10928,18 +10936,126 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
|
|
|
10928
10936
|
}
|
|
10929
10937
|
}, [items, orientation]);
|
|
10930
10938
|
const handleTabSelect = React.useCallback((tabId) => {
|
|
10939
|
+
// 드래그 중이면 탭 선택 무시
|
|
10940
|
+
if (isDragging)
|
|
10941
|
+
return;
|
|
10931
10942
|
const tab = items.find(item => item.id === tabId);
|
|
10932
10943
|
if (tab && !tab.disabled) {
|
|
10933
10944
|
setActiveTabId(tabId);
|
|
10934
10945
|
onTabChange?.(tabId);
|
|
10935
10946
|
}
|
|
10936
|
-
}, [items, onTabChange]);
|
|
10947
|
+
}, [items, onTabChange, isDragging]);
|
|
10937
10948
|
const handleTabFocus = React.useCallback((tabId) => {
|
|
10938
10949
|
setFocusedTabId(tabId);
|
|
10939
10950
|
}, []);
|
|
10940
10951
|
const handleTabBlur = React.useCallback(() => {
|
|
10941
10952
|
setFocusedTabId('');
|
|
10942
10953
|
}, []);
|
|
10954
|
+
// 드래그 스크롤 핸들러들
|
|
10955
|
+
const handleMouseDown = React.useCallback((e) => {
|
|
10956
|
+
if (orientation !== 'horizontal' || !tabListRef.current)
|
|
10957
|
+
return;
|
|
10958
|
+
// 클릭 시작 위치와 시간 기록
|
|
10959
|
+
clickStartRef.current = {
|
|
10960
|
+
x: e.pageX,
|
|
10961
|
+
y: e.pageY,
|
|
10962
|
+
time: Date.now()
|
|
10963
|
+
};
|
|
10964
|
+
dragStartRef.current = {
|
|
10965
|
+
x: e.pageX - tabListRef.current.offsetLeft,
|
|
10966
|
+
scrollLeft: tabListRef.current.scrollLeft
|
|
10967
|
+
};
|
|
10968
|
+
}, [orientation]);
|
|
10969
|
+
const handleMouseMove = React.useCallback((e) => {
|
|
10970
|
+
if (!dragStartRef.current || !tabListRef.current)
|
|
10971
|
+
return;
|
|
10972
|
+
// 아직 드래그가 시작되지 않았다면 드래그 시작 여부 판단
|
|
10973
|
+
if (!isDragging && clickStartRef.current) {
|
|
10974
|
+
const deltaX = Math.abs(e.pageX - clickStartRef.current.x);
|
|
10975
|
+
const deltaY = Math.abs(e.pageY - clickStartRef.current.y);
|
|
10976
|
+
const deltaTime = Date.now() - clickStartRef.current.time;
|
|
10977
|
+
// 5px 이상 이동하거나 200ms 이상 지났으면 드래그 시작
|
|
10978
|
+
if (deltaX > 5 || deltaY > 5 || deltaTime > 200) {
|
|
10979
|
+
setIsDragging(true);
|
|
10980
|
+
}
|
|
10981
|
+
}
|
|
10982
|
+
if (!isDragging || !dragStartRef.current)
|
|
10983
|
+
return;
|
|
10984
|
+
e.preventDefault();
|
|
10985
|
+
const x = e.pageX - tabListRef.current.offsetLeft;
|
|
10986
|
+
const walk = (x - dragStartRef.current.x) * 2; // 스크롤 속도 조절
|
|
10987
|
+
tabListRef.current.scrollLeft = dragStartRef.current.scrollLeft - walk;
|
|
10988
|
+
}, [isDragging]);
|
|
10989
|
+
const handleMouseUp = React.useCallback(() => {
|
|
10990
|
+
setIsDragging(false);
|
|
10991
|
+
dragStartRef.current = null;
|
|
10992
|
+
clickStartRef.current = null;
|
|
10993
|
+
}, []);
|
|
10994
|
+
const handleMouseLeave = React.useCallback(() => {
|
|
10995
|
+
setIsDragging(false);
|
|
10996
|
+
dragStartRef.current = null;
|
|
10997
|
+
clickStartRef.current = null;
|
|
10998
|
+
}, []);
|
|
10999
|
+
// 터치 이벤트 핸들러들
|
|
11000
|
+
const handleTouchStart = React.useCallback((e) => {
|
|
11001
|
+
if (orientation !== 'horizontal' || !tabListRef.current)
|
|
11002
|
+
return;
|
|
11003
|
+
const touch = e.touches[0];
|
|
11004
|
+
// 클릭 시작 위치와 시간 기록
|
|
11005
|
+
clickStartRef.current = {
|
|
11006
|
+
x: touch.pageX,
|
|
11007
|
+
y: touch.pageY,
|
|
11008
|
+
time: Date.now()
|
|
11009
|
+
};
|
|
11010
|
+
dragStartRef.current = {
|
|
11011
|
+
x: touch.pageX - tabListRef.current.offsetLeft,
|
|
11012
|
+
scrollLeft: tabListRef.current.scrollLeft
|
|
11013
|
+
};
|
|
11014
|
+
}, [orientation]);
|
|
11015
|
+
const handleTouchMove = React.useCallback((e) => {
|
|
11016
|
+
if (!dragStartRef.current || !tabListRef.current)
|
|
11017
|
+
return;
|
|
11018
|
+
// 아직 드래그가 시작되지 않았다면 드래그 시작 여부 판단
|
|
11019
|
+
if (!isDragging && clickStartRef.current) {
|
|
11020
|
+
const touch = e.touches[0];
|
|
11021
|
+
const deltaX = Math.abs(touch.pageX - clickStartRef.current.x);
|
|
11022
|
+
const deltaY = Math.abs(touch.pageY - clickStartRef.current.y);
|
|
11023
|
+
const deltaTime = Date.now() - clickStartRef.current.time;
|
|
11024
|
+
// 5px 이상 이동하거나 200ms 이상 지났으면 드래그 시작
|
|
11025
|
+
if (deltaX > 5 || deltaY > 5 || deltaTime > 200) {
|
|
11026
|
+
setIsDragging(true);
|
|
11027
|
+
}
|
|
11028
|
+
}
|
|
11029
|
+
if (!isDragging || !dragStartRef.current)
|
|
11030
|
+
return;
|
|
11031
|
+
e.preventDefault();
|
|
11032
|
+
const touch = e.touches[0];
|
|
11033
|
+
const x = touch.pageX - tabListRef.current.offsetLeft;
|
|
11034
|
+
const walk = (x - dragStartRef.current.x) * 2; // 스크롤 속도 조절
|
|
11035
|
+
tabListRef.current.scrollLeft = dragStartRef.current.scrollLeft - walk;
|
|
11036
|
+
}, [isDragging]);
|
|
11037
|
+
const handleTouchEnd = React.useCallback(() => {
|
|
11038
|
+
setIsDragging(false);
|
|
11039
|
+
dragStartRef.current = null;
|
|
11040
|
+
clickStartRef.current = null;
|
|
11041
|
+
}, []);
|
|
11042
|
+
// 드래그 이벤트 리스너 등록/해제
|
|
11043
|
+
React.useEffect(() => {
|
|
11044
|
+
if (isDragging) {
|
|
11045
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
11046
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
11047
|
+
document.addEventListener('mouseleave', handleMouseLeave);
|
|
11048
|
+
document.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
11049
|
+
document.addEventListener('touchend', handleTouchEnd);
|
|
11050
|
+
}
|
|
11051
|
+
return () => {
|
|
11052
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
11053
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
11054
|
+
document.removeEventListener('mouseleave', handleMouseLeave);
|
|
11055
|
+
document.removeEventListener('touchmove', handleTouchMove);
|
|
11056
|
+
document.removeEventListener('touchend', handleTouchEnd);
|
|
11057
|
+
};
|
|
11058
|
+
}, [isDragging, handleMouseMove, handleMouseUp, handleMouseLeave, handleTouchMove, handleTouchEnd]);
|
|
10943
11059
|
const activeTab = items.find(item => item.id === activeTabId);
|
|
10944
11060
|
items.findIndex(item => item.id === activeTabId);
|
|
10945
11061
|
const classes = clsx('designbase-tabs', `designbase-tabs--${orientation}`, `designbase-tabs--${size}`, `designbase-tabs--${variant}`, {
|
|
@@ -10947,8 +11063,9 @@ const Tabs = ({ items, defaultSelectedId, selectedId, orientation = 'horizontal'
|
|
|
10947
11063
|
}, className);
|
|
10948
11064
|
const tabListClasses = clsx('designbase-tabs__list', `designbase-tabs__list--${orientation}`, {
|
|
10949
11065
|
'designbase-tabs__list--full-width': fullWidth,
|
|
11066
|
+
'designbase-tabs__list--dragging': isDragging,
|
|
10950
11067
|
});
|
|
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) => {
|
|
11068
|
+
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
11069
|
const isSelected = item.id === activeTabId;
|
|
10953
11070
|
const isFocused = item.id === focusedTabId;
|
|
10954
11071
|
const isDisabled = item.disabled;
|