@designbasekorea/ui 0.2.27 → 0.2.29

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
@@ -5277,7 +5277,7 @@ const Chip = ({ label, size = 'm', variant = 'default', color = 'primary', delet
5277
5277
  };
5278
5278
  Chip.displayName = 'Chip';
5279
5279
 
5280
- /** 유틸 */
5280
+ /* ----------------------- 유틸 ----------------------- */
5281
5281
  const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
5282
5282
  const hexToRgb = (hex) => {
5283
5283
  const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim());
@@ -5289,6 +5289,7 @@ const rgbToHex = (r, g, b) => {
5289
5289
  const toHex = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, '0');
5290
5290
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
5291
5291
  };
5292
+ /** RGB ↔ HSV (HSV: h[0-360], s[0-100], v[0-100]) */
5292
5293
  const rgbToHsv = (r, g, b) => {
5293
5294
  r /= 255;
5294
5295
  g /= 255;
@@ -5378,6 +5379,7 @@ const rgbToHsl = (r, g, b) => {
5378
5379
  }
5379
5380
  return { h: Math.round(h * 100) / 100, s: Math.round(s * 10000) / 100, l: Math.round(l * 10000) / 100 };
5380
5381
  };
5382
+ /* ----------------------- 컴포넌트 ----------------------- */
5381
5383
  const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left', value, defaultValue = '#006FFF', showInput = true, showAlpha = true, showFormatSelector = true, showCopyButton = true, disabled = false, readonly = false, onChange, onApply, onCancel, className, }) => {
5382
5384
  /** 내부 상태 (HSV + alpha%) */
5383
5385
  const [h, setH] = useState(211);
@@ -5387,10 +5389,10 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5387
5389
  const [isOpen, setIsOpen] = useState(false);
5388
5390
  const [format, setFormat] = useState('hex');
5389
5391
  const [isCopied, setIsCopied] = useState(false);
5390
- // 하단 컬러 인풋(문자열), 알파 인풋(문자열) – 엔터로만 확정
5392
+ // 하단 인풋(문자열) 엔터로만 확정
5391
5393
  const [colorInput, setColorInput] = useState('');
5392
5394
  const [alphaInput, setAlphaInput] = useState('100');
5393
- // 모달용 임시 상태 (적용/취소 버튼용)
5395
+ // 모달용 임시 상태 (취소 시 되돌리기)
5394
5396
  const [tempColor, setTempColor] = useState('');
5395
5397
  const pickerRef = useRef(null);
5396
5398
  const areaRef = useRef(null);
@@ -5404,12 +5406,13 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5404
5406
  setH(h);
5405
5407
  setS(s);
5406
5408
  setV(v);
5407
- setColorInput(initial);
5408
- setAlphaInput('100');
5409
5409
  }
5410
+ // 인풋 초기 표현
5411
+ setColorInput(initial);
5412
+ setAlphaInput('100');
5410
5413
  // eslint-disable-next-line react-hooks/exhaustive-deps
5411
5414
  }, []);
5412
- /** 외부 value 변화 */
5415
+ /** 외부 value 변화 시(제어형)만 HSV 반영 */
5413
5416
  useEffect(() => {
5414
5417
  if (!value)
5415
5418
  return;
@@ -5425,7 +5428,7 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5425
5428
  const rgb = useMemo(() => hsvToRgb(h, s, v), [h, s, v]);
5426
5429
  const hex = useMemo(() => rgbToHex(rgb.r, rgb.g, rgb.b), [rgb]);
5427
5430
  const hsl = useMemo(() => rgbToHsl(rgb.r, rgb.g, rgb.b), [rgb]);
5428
- /** 표시 문자열 */
5431
+ /** 포맷 출력 문자열 */
5429
5432
  const formatted = useMemo(() => {
5430
5433
  const alpha = a / 100;
5431
5434
  switch (format) {
@@ -5437,11 +5440,9 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5437
5440
  default: return hex;
5438
5441
  }
5439
5442
  }, [format, hex, rgb, hsl, a]);
5440
- /** 외부 onChange 인풋 동기화 */
5443
+ /** 외부 onChange 알림만 (입력창 동기화는 여기서 하지 않음!) */
5441
5444
  useEffect(() => {
5442
5445
  onChange?.(formatted);
5443
- setColorInput(formatted.toUpperCase());
5444
- setAlphaInput(String(a));
5445
5446
  // eslint-disable-next-line react-hooks/exhaustive-deps
5446
5447
  }, [formatted]);
5447
5448
  /** 드롭다운 외부 클릭 닫기 */
@@ -5454,7 +5455,7 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5454
5455
  document.addEventListener('mousedown', handler);
5455
5456
  return () => document.removeEventListener('mousedown', handler);
5456
5457
  }, [isOpen, type]);
5457
- /** 컬러 필드 핸들링 */
5458
+ /** 컬러 영역 (S x V) 마우스/터치 */
5458
5459
  const updateFromArea = (clientX, clientY) => {
5459
5460
  const el = areaRef.current;
5460
5461
  if (!el)
@@ -5477,25 +5478,26 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5477
5478
  return; const t = e.touches[0]; updateFromArea(t.clientX, t.clientY); };
5478
5479
  const onAreaTouchEnd = () => { dragging.current = false; };
5479
5480
  /** 슬라이더 */
5480
- const onHueChange = (e) => setH(parseInt(e.target.value, 10));
5481
- const onAlphaChange = (e) => {
5481
+ const onHueChange = useCallback((e) => setH(parseInt(e.target.value, 10)), []);
5482
+ const onAlphaChange = useCallback((e) => {
5482
5483
  const newAlpha = parseInt(e.target.value, 10);
5483
5484
  setA(newAlpha);
5484
- setAlphaInput(String(newAlpha)); // 실시간 동기화
5485
- };
5486
- /** 컬러 인풋: 엔터로만 확정 */
5487
- const tryCommitColorInput = () => {
5485
+ setAlphaInput(String(newAlpha)); // 슬라이더 ↔ 인풋 동기화(표시만)
5486
+ }, []);
5487
+ /** 컬러 텍스트 인풋: 엔터로만 확정 */
5488
+ const commitColorInput = useCallback(() => {
5488
5489
  const str = colorInput.trim();
5489
- // HEX
5490
+ // HEX (#RRGGBB)
5490
5491
  if (/^#([0-9A-Fa-f]{6})$/.test(str)) {
5491
5492
  const rgb = hexToRgb(str);
5492
5493
  const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
5493
5494
  setH(hsv.h);
5494
5495
  setS(hsv.s);
5495
5496
  setV(hsv.v);
5497
+ setColorInput(str.toUpperCase());
5496
5498
  return;
5497
5499
  }
5498
- // rgb()
5500
+ // rgb(r,g,b)
5499
5501
  let m = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(str);
5500
5502
  if (m) {
5501
5503
  const r = clamp(parseInt(m[1], 10), 0, 255);
@@ -5505,9 +5507,10 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5505
5507
  setH(hsv.h);
5506
5508
  setS(hsv.s);
5507
5509
  setV(hsv.v);
5510
+ setColorInput(`rgb(${r}, ${g}, ${b})`.toUpperCase());
5508
5511
  return;
5509
5512
  }
5510
- // rgba()
5513
+ // rgba(r,g,b,a)
5511
5514
  m = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)$/i.exec(str);
5512
5515
  if (m) {
5513
5516
  const r = clamp(parseInt(m[1], 10), 0, 255);
@@ -5519,39 +5522,42 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5519
5522
  setS(hsv.s);
5520
5523
  setV(hsv.v);
5521
5524
  setA(Math.round(alpha * 100));
5525
+ setAlphaInput(String(Math.round(alpha * 100)));
5526
+ setColorInput(`rgba(${r}, ${g}, ${b}, ${alpha})`.toUpperCase());
5522
5527
  return;
5523
5528
  }
5524
- // 실패원래 값으로 복구
5529
+ // 잘못된 원복
5525
5530
  setColorInput(formatted.toUpperCase());
5526
- };
5531
+ }, [colorInput, formatted]);
5527
5532
  const onColorKeyDown = (e) => {
5528
5533
  if (e.key === 'Enter')
5529
- tryCommitColorInput();
5534
+ commitColorInput();
5530
5535
  };
5531
5536
  const onColorBlur = () => {
5532
- // 요구사항: 엔터로만 변경. 블러 시에는 값 복구만.
5537
+ // 요구사항: 엔터로만 반영, 블러 시엔 원복
5533
5538
  setColorInput(formatted.toUpperCase());
5534
5539
  };
5535
- /** 알파 인풋: 엔터로만 확정 (0-100) */
5536
- const tryCommitAlphaInput = () => {
5540
+ /** 알파 인풋: 엔터로만 확정 (0~100) */
5541
+ const commitAlphaInput = useCallback(() => {
5537
5542
  const n = Number(alphaInput.trim());
5538
5543
  if (!Number.isNaN(n) && n >= 0 && n <= 100) {
5539
5544
  setA(Math.round(n));
5545
+ setAlphaInput(String(Math.round(n)));
5540
5546
  return;
5541
5547
  }
5542
- // 실패복구
5548
+ // 잘못된 원복
5543
5549
  setAlphaInput(String(a));
5544
- };
5550
+ }, [alphaInput, a]);
5545
5551
  const onAlphaInputKeyDown = (e) => {
5546
5552
  if (e.key === 'Enter')
5547
- tryCommitAlphaInput();
5553
+ commitAlphaInput();
5548
5554
  };
5549
5555
  const onAlphaInputBlur = () => {
5550
- // 엔터로만 반영. 블러 시 복원.
5556
+ // 엔터로만 반영, 블러 시 원복
5551
5557
  setAlphaInput(String(a));
5552
5558
  };
5553
5559
  /** 복사 */
5554
- const onCopy = async () => {
5560
+ const onCopy = useCallback(async () => {
5555
5561
  try {
5556
5562
  await navigator.clipboard.writeText(formatted);
5557
5563
  setIsCopied(true);
@@ -5560,9 +5566,9 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5560
5566
  catch (e) {
5561
5567
  console.error(e);
5562
5568
  }
5563
- };
5569
+ }, [formatted]);
5564
5570
  /** EyeDropper */
5565
- const onEyedrop = async () => {
5571
+ const onEyedrop = useCallback(async () => {
5566
5572
  try {
5567
5573
  if ('EyeDropper' in window) {
5568
5574
  const eye = new window.EyeDropper();
@@ -5580,23 +5586,21 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5580
5586
  catch (e) {
5581
5587
  console.error(e);
5582
5588
  }
5583
- };
5584
- /** 모달용 핸들러 */
5585
- const handleModalOpen = () => {
5586
- if (type === 'modal') {
5587
- setTempColor(formatted);
5588
- }
5589
+ }, []);
5590
+ /** 모달 열기/적용/취소 (deps에서 formatted 제거 → 재생성 방지) */
5591
+ const handleModalOpen = useCallback(() => {
5592
+ if (type === 'modal')
5593
+ setTempColor(hex); // 현재 HEX 저장
5589
5594
  setIsOpen(true);
5590
- };
5591
- const handleModalApply = () => {
5595
+ }, [type, hex]);
5596
+ const handleModalApply = useCallback(() => {
5592
5597
  if (type === 'modal') {
5593
5598
  onApply?.(formatted);
5594
5599
  setIsOpen(false);
5595
5600
  }
5596
- };
5597
- const handleModalCancel = () => {
5601
+ }, [type, formatted, onApply]);
5602
+ const handleModalCancel = useCallback(() => {
5598
5603
  if (type === 'modal') {
5599
- // 원래 색상으로 복원
5600
5604
  const rgb = hexToRgb(tempColor);
5601
5605
  if (rgb) {
5602
5606
  const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
@@ -5607,9 +5611,9 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5607
5611
  onCancel?.();
5608
5612
  setIsOpen(false);
5609
5613
  }
5610
- };
5611
- /** 배경 스타일 */
5612
- const hueTrackStyle = {
5614
+ }, [type, tempColor, onCancel]);
5615
+ /** 배경 스타일들 */
5616
+ const hueTrackStyle = useMemo(() => ({
5613
5617
  background: `linear-gradient(to right,
5614
5618
  hsl(0,100%,50%),
5615
5619
  hsl(60,100%,50%),
@@ -5618,15 +5622,16 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5618
5622
  hsl(240,100%,50%),
5619
5623
  hsl(300,100%,50%),
5620
5624
  hsl(360,100%,50%))`,
5621
- };
5622
- const areaBackground = {
5625
+ }), []);
5626
+ // 상단 좌→우: 채도 증가 / 상단→하단: 밝기 감소
5627
+ const areaBackground = useMemo(() => ({
5623
5628
  backgroundImage: `
5624
5629
  linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)),
5625
5630
  linear-gradient(to right, #ffffff, hsl(${h}, 100%, 50%))
5626
5631
  `,
5627
- };
5628
- /** ✔︎ 알파 트랙: 색상 무관, 고정 흑백 그라디언트 */
5629
- const alphaTrackStyle = {
5632
+ }), [h]);
5633
+ // 고정 흑백 알파 트랙 (색상 무관)
5634
+ const alphaTrackStyle = useMemo(() => ({
5630
5635
  backgroundImage: `
5631
5636
  linear-gradient(45deg, var(--db-border-base) 25%, transparent 25%),
5632
5637
  linear-gradient(-45deg, var(--db-border-base) 25%, transparent 25%),
@@ -5637,22 +5642,22 @@ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left',
5637
5642
  backgroundSize: '8px 8px,8px 8px,8px 8px,8px 8px,100% 100%',
5638
5643
  backgroundPosition: '0 0,0 4px,4px -4px,-4px 0,0 0',
5639
5644
  backgroundColor: 'var(--db-surface-base)',
5640
- };
5645
+ }), []);
5641
5646
  const classes = clsx('designbase-color-picker', `designbase-color-picker--${size}`, `designbase-color-picker--${position}`, {
5642
5647
  'designbase-color-picker--disabled': disabled,
5643
5648
  'designbase-color-picker--readonly': readonly,
5644
5649
  'designbase-color-picker--open': isOpen,
5645
5650
  'designbase-color-picker--no-input': !showInput,
5646
5651
  }, className);
5647
- const Trigger = (jsxs("div", { className: "designbase-color-picker__trigger", onClick: () => !disabled && !readonly && handleModalOpen(), children: [jsx("div", { className: "designbase-color-picker__color-display", children: jsx("div", { className: "designbase-color-picker__color-box", style: { backgroundColor: showAlpha ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a / 100})` : hex } }) }), showInput && (jsx("input", { type: "text", value: colorInput, onChange: (e) => setColorInput(e.target.value), onKeyDown: onColorKeyDown, onBlur: onColorBlur, onClick: (e) => e.stopPropagation(), disabled: disabled, readOnly: readonly, className: "designbase-color-picker__input", placeholder: "#000000" })), showInput && showCopyButton && (jsx("button", { type: "button", className: "designbase-color-picker__copy-button-inline", onClick: (e) => { e.stopPropagation(); onCopy(); }, disabled: disabled, "aria-label": "Copy color value", children: isCopied ? jsx(DoneIcon$1, { size: 14 }) : jsx(CopyIcon, { size: 14 }) })), jsx("button", { type: "button", className: "designbase-color-picker__toggle", disabled: disabled, "aria-label": "Toggle color picker", children: jsx(ChevronDownIcon, { size: 16 }) })] }));
5648
- const Selector = (jsxs("div", { className: "designbase-color-picker__selector", children: [jsx("div", { className: "designbase-color-picker__color-area", children: jsx("div", { ref: areaRef, className: "designbase-color-picker__color-field", style: areaBackground, onMouseDown: onAreaMouseDown, onMouseMove: onAreaMouseMove, onMouseUp: onAreaMouseUp, onMouseLeave: onAreaLeave, onTouchStart: onAreaTouchStart, onTouchMove: onAreaTouchMove, onTouchEnd: onAreaTouchEnd, children: jsx("div", { className: "designbase-color-picker__color-pointer", style: { left: `${s}%`, top: `${100 - v}%`, backgroundColor: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` } }) }) }), jsxs("div", { className: "designbase-color-picker__controls", children: [jsx(Button, { variant: "tertiary", size: "m", iconOnly: true, onClick: onEyedrop, "aria-label": "Eyedropper tool", children: jsx(EyedropperIcon, {}) }), jsxs("div", { className: "designbase-color-picker__slider-container", children: [jsx("div", { className: "designbase-color-picker__hue-slider", children: jsx("input", { type: "range", min: 0, max: 360, value: h, onChange: onHueChange, className: "designbase-color-picker__slider designbase-color-picker__slider--hue", style: hueTrackStyle }) }), showAlpha && (jsx("div", { className: "designbase-color-picker__alpha-slider", children: jsx("input", { type: "range", min: 0, max: 100, value: a, onChange: onAlphaChange, className: "designbase-color-picker__slider designbase-color-picker__slider--alpha", style: alphaTrackStyle }) }))] })] }), jsxs("div", { className: "designbase-color-picker__value-display", children: [showFormatSelector && (jsx(Select, { value: format, onChange: (v) => setFormat(v), showClearButton: false, position: "top", options: [
5652
+ const Trigger = (jsxs("div", { className: "designbase-color-picker__trigger", onClick: () => !disabled && !readonly && (type === 'modal' ? handleModalOpen() : setIsOpen(v => !v)), children: [jsx("div", { className: "designbase-color-picker__color-display", children: jsx("div", { className: "designbase-color-picker__color-box", style: { backgroundColor: showAlpha ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a / 100})` : hex } }) }), showInput && (jsx("input", { type: "text", value: colorInput, onChange: (e) => setColorInput(e.target.value), onKeyDown: onColorKeyDown, onBlur: onColorBlur, onClick: (e) => e.stopPropagation(), disabled: disabled, readOnly: readonly, className: "designbase-color-picker__input", placeholder: "#000000" })), showInput && showCopyButton && (jsx("button", { type: "button", className: "designbase-color-picker__copy-button-inline", onClick: (e) => { e.stopPropagation(); onCopy(); }, disabled: disabled, "aria-label": "Copy color value", children: isCopied ? jsx(DoneIcon$1, { size: 14 }) : jsx(CopyIcon, { size: 14 }) })), jsx("button", { type: "button", className: "designbase-color-picker__toggle", disabled: disabled, "aria-label": "Toggle color picker", children: jsx(ChevronDownIcon, { size: 16 }) })] }));
5653
+ const Selector = (jsxs("div", { className: "designbase-color-picker__selector", children: [jsx("div", { className: "designbase-color-picker__color-area", children: jsx("div", { ref: areaRef, className: "designbase-color-picker__color-field", style: areaBackground, onMouseDown: onAreaMouseDown, onMouseMove: onAreaMouseMove, onMouseUp: onAreaMouseUp, onMouseLeave: onAreaLeave, onTouchStart: onAreaTouchStart, onTouchMove: onAreaTouchMove, onTouchEnd: onAreaTouchEnd, children: jsx("div", { className: "designbase-color-picker__color-pointer", style: { left: `${s}%`, top: `${100 - v}%`, backgroundColor: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` } }) }) }), jsxs("div", { className: "designbase-color-picker__controls", children: [jsx(Button, { variant: "tertiary", size: "m", iconOnly: true, onClick: onEyedrop, "aria-label": "Eyedropper tool", children: jsx(EyedropperIcon, {}) }), jsxs("div", { className: "designbase-color-picker__slider-container", children: [jsx("div", { className: "designbase-color-picker__hue-slider", children: jsx("input", { type: "range", min: 0, max: 360, value: h, onChange: onHueChange, className: "designbase-color-picker__slider designbase-color-picker__slider--hue", style: hueTrackStyle }) }), showAlpha && (jsx("div", { className: "designbase-color-picker__alpha-slider", children: jsx("input", { type: "range", min: 0, max: 100, value: a, onChange: onAlphaChange, className: "designbase-color-picker__slider designbase-color-picker__slider--alpha", style: alphaTrackStyle }) }))] })] }), jsxs("div", { className: "designbase-color-picker__value-display", children: [showFormatSelector && (jsx(Select, { value: format, onChange: (v) => setFormat(v), showClearButton: false, options: [
5649
5654
  { label: 'HEX', value: 'hex' },
5650
5655
  { label: 'RGB', value: 'rgb' },
5651
5656
  { label: 'RGBA', value: 'rgba' },
5652
5657
  { label: 'HSL', value: 'hsl' },
5653
5658
  { label: 'HSLA', value: 'hsla' },
5654
- ], size: "s" })), jsx(Input, { type: "text", value: colorInput, onChange: setColorInput, onKeyDown: onColorKeyDown, onBlur: onColorBlur, placeholder: "#000000", size: "s", className: "designbase-color-picker__value-input" }), showAlpha && (jsxs("div", { className: "designbase-color-picker__alpha-input-wrap", children: [jsx(Input, { type: "text", inputMode: "numeric", value: alphaInput, onChange: (value) => setAlphaInput(value.replace(/[^\d]/g, '').slice(0, 3)), onKeyDown: onAlphaInputKeyDown, onBlur: onAlphaInputBlur, placeholder: "100", size: "s", className: "designbase-color-picker__alpha-input", "aria-label": "Alpha percent" }), jsx("span", { className: "designbase-color-picker__alpha-suffix", children: "%" })] })), showCopyButton && (jsx(Button, { variant: "tertiary", size: "m", iconOnly: true, onClick: onCopy, "aria-label": "Copy color value", children: isCopied ? jsx(DoneIcon$1, {}) : jsx(CopyIcon, {}) }))] })] }));
5655
- return (jsxs("div", { ref: pickerRef, className: classes, children: [Trigger, type === 'dropdown' && isOpen && (jsx("div", { className: "designbase-color-picker__dropdown", onClick: (e) => e.stopPropagation(), children: Selector })), type === 'modal' && (jsxs(Modal, { isOpen: isOpen, onClose: handleModalCancel, title: "\uC0C9\uC0C1 \uC120\uD0DD", size: "s", children: [jsx(ModalBody, { children: Selector }), jsx(ModalFooter, { children: jsxs("div", { style: { display: 'flex', gap: '8px', justifyContent: 'flex-end' }, children: [jsx(Button, { variant: "tertiary", size: "s", onClick: handleModalCancel, children: "\uCDE8\uC18C" }), jsx(Button, { variant: "primary", size: "s", onClick: handleModalApply, children: "\uC801\uC6A9" })] }) })] }))] }));
5659
+ ], size: "s", position: "top" })), jsx(Input, { type: "text", value: colorInput, onChange: setColorInput, onKeyDown: onColorKeyDown, onBlur: onColorBlur, placeholder: "#000000", size: "s", className: "designbase-color-picker__value-input" }), showAlpha && (jsxs("div", { className: "designbase-color-picker__alpha-input-wrap", children: [jsx(Input, { type: "text", inputMode: "numeric", value: alphaInput, onChange: (value) => setAlphaInput(value.replace(/[^\d]/g, '').slice(0, 3)), onKeyDown: onAlphaInputKeyDown, onBlur: onAlphaInputBlur, placeholder: "100", size: "s", className: "designbase-color-picker__alpha-input", "aria-label": "Alpha percent" }), jsx("span", { className: "designbase-color-picker__alpha-suffix", children: "%" })] })), showCopyButton && (jsx(Button, { variant: "tertiary", size: "m", iconOnly: true, onClick: onCopy, "aria-label": "Copy color value", children: isCopied ? jsx(DoneIcon$1, {}) : jsx(CopyIcon, {}) }))] })] }));
5660
+ return (jsxs("div", { ref: pickerRef, className: classes, children: [Trigger, type === 'dropdown' && isOpen && (jsx("div", { className: "designbase-color-picker__dropdown", onClick: (e) => e.stopPropagation(), children: Selector })), type === 'modal' && (jsxs(Modal, { isOpen: isOpen, onClose: handleModalCancel, title: "\uC0C9\uC0C1 \uC120\uD0DD", size: "s", children: [jsx(ModalBody, { children: Selector }), jsx(ModalFooter, { children: jsxs("div", { style: { display: 'flex', gap: 8, justifyContent: 'flex-end' }, children: [jsx(Button, { variant: "tertiary", size: "s", onClick: handleModalCancel, children: "\uCDE8\uC18C" }), jsx(Button, { variant: "primary", size: "s", onClick: handleModalApply, children: "\uC801\uC6A9" })] }) })] }))] }));
5656
5661
  };
5657
5662
  ColorPicker.displayName = 'ColorPicker';
5658
5663