@designbasekorea/ui 0.2.34 → 0.2.36

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.umd.js CHANGED
@@ -4012,7 +4012,7 @@
4012
4012
  ModalBody.displayName = 'ModalBody';
4013
4013
  ModalFooter.displayName = 'ModalFooter';
4014
4014
 
4015
- const Label = ({ children, htmlFor, required = false, size = 'm', disabled = false, error = false, className, onClick, }) => {
4015
+ const Label = ({ children, htmlFor, required = false, size = 's', disabled = false, error = false, className, onClick, }) => {
4016
4016
  const classes = [
4017
4017
  'designbase-label',
4018
4018
  `designbase-label--${size}`,
@@ -4059,7 +4059,7 @@
4059
4059
  lg: 18,
4060
4060
  };
4061
4061
  const iconSize = iconSizeMap[size];
4062
- return (jsxRuntime.jsxs("div", { className: classes, children: [label && (jsxRuntime.jsx(Label, { htmlFor: inputId, required: required, error: error, disabled: disabled, size: size === 's' ? 'xs' : size === 'm' ? 's' : 'm', children: label })), jsxRuntime.jsxs("div", { className: "designbase-input__wrapper", children: [actualStartIcon && (jsxRuntime.jsx("div", { className: "designbase-input__start-icon", children: React.createElement(actualStartIcon, { size: iconSize }) })), jsxRuntime.jsx("input", { ...props, ref: forwardedRef, id: inputId, type: actualType, value: value, defaultValue: defaultValue, placeholder: placeholder, disabled: disabled, readOnly: readOnly, required: required, className: inputClasses, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "aria-describedby": clsx(helperText && helperTextId, error && errorMessage && errorMessageId), "aria-invalid": error }), isPassword && (jsxRuntime.jsx("button", { type: "button", className: "designbase-input__password-toggle", onClick: handlePasswordToggle, disabled: disabled, "aria-label": showPassword ? '비밀번호 숨기기' : '비밀번호 보기', children: React.createElement(PasswordIcon, { size: iconSize }) })), EndIcon && !isPassword && (jsxRuntime.jsx("div", { className: "designbase-input__end-icon", children: React.createElement(EndIcon, { size: iconSize }) }))] }), helperText && !error && (jsxRuntime.jsx("p", { id: helperTextId, className: "designbase-input__helper-text", children: helperText })), error && errorMessage && (jsxRuntime.jsx("p", { id: errorMessageId, className: "designbase-input__error-message", children: errorMessage }))] }));
4062
+ return (jsxRuntime.jsxs("div", { className: classes, children: [label && (jsxRuntime.jsx(Label, { htmlFor: inputId, required: required, error: error, disabled: disabled, size: size === 's' ? 's' : size === 'm' ? 'm' : 'l', children: label })), jsxRuntime.jsxs("div", { className: "designbase-input__wrapper", children: [actualStartIcon && (jsxRuntime.jsx("div", { className: "designbase-input__start-icon", children: React.createElement(actualStartIcon, { size: iconSize }) })), jsxRuntime.jsx("input", { ...props, ref: forwardedRef, id: inputId, type: actualType, value: value, defaultValue: defaultValue, placeholder: placeholder, disabled: disabled, readOnly: readOnly, required: required, className: inputClasses, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "aria-describedby": clsx(helperText && helperTextId, error && errorMessage && errorMessageId), "aria-invalid": error }), isPassword && (jsxRuntime.jsx("button", { type: "button", className: "designbase-input__password-toggle", onClick: handlePasswordToggle, disabled: disabled, "aria-label": showPassword ? '비밀번호 숨기기' : '비밀번호 보기', children: React.createElement(PasswordIcon, { size: iconSize }) })), EndIcon && !isPassword && (jsxRuntime.jsx("div", { className: "designbase-input__end-icon", children: React.createElement(EndIcon, { size: iconSize }) }))] }), helperText && !error && (jsxRuntime.jsx("p", { id: helperTextId, className: "designbase-input__helper-text", children: helperText })), error && errorMessage && (jsxRuntime.jsx("p", { id: errorMessageId, className: "designbase-input__error-message", children: errorMessage }))] }));
4063
4063
  });
4064
4064
  Input.displayName = 'Input';
4065
4065
 
@@ -5322,17 +5322,19 @@
5322
5322
 
5323
5323
  /* ----------------------- 유틸 ----------------------- */
5324
5324
  const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
5325
+ const normalizeHex = (s) => (s || '').trim().toUpperCase();
5326
+ /** #RRGGBB → {r,g,b} */
5325
5327
  const hexToRgb = (hex) => {
5326
5328
  const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex.trim());
5327
5329
  if (!m)
5328
5330
  return null;
5329
5331
  return { r: parseInt(m[1], 16), g: parseInt(m[2], 16), b: parseInt(m[3], 16) };
5330
5332
  };
5331
- const rgbToHex = (r, g, b) => {
5332
- const toHex = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, '0');
5333
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
5333
+ /** RGB HEX */
5334
+ const toHex = (r, g, b) => {
5335
+ const h = (x) => clamp(Math.round(x), 0, 255).toString(16).padStart(2, '0');
5336
+ return `#${h(r)}${h(g)}${h(b)}`.toUpperCase();
5334
5337
  };
5335
- /** RGB ↔ HSV (HSV: h[0-360], s[0-100], v[0-100]) */
5336
5338
  const rgbToHsv = (r, g, b) => {
5337
5339
  r /= 255;
5338
5340
  g /= 255;
@@ -5356,7 +5358,7 @@
5356
5358
  }
5357
5359
  const s = max === 0 ? 0 : d / max;
5358
5360
  const v = max;
5359
- return { h: Math.round(h * 100) / 100, s: Math.round(s * 10000) / 100, v: Math.round(v * 10000) / 100 };
5361
+ return { h, s: s * 100, v: v * 100 };
5360
5362
  };
5361
5363
  const hsvToRgb = (h, s, v) => {
5362
5364
  s /= 100;
@@ -5424,86 +5426,123 @@
5424
5426
  }
5425
5427
  h *= 60;
5426
5428
  }
5427
- return {
5428
- h: Math.round(h * 100) / 100,
5429
- s: Math.round(s * 10000) / 100,
5430
- l: Math.round(l * 10000) / 100,
5431
- };
5429
+ return { h, s: s * 100, l: l * 100 };
5432
5430
  };
5433
5431
  /* ----------------------- 컴포넌트 ----------------------- */
5434
- 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, }) => {
5435
- /** 내부 HSV + alpha */
5436
- const [h, setH] = React.useState(211);
5437
- const [s, setS] = React.useState(100);
5438
- const [v, setV] = React.useState(50);
5432
+ const ColorPicker = ({ size = 'm', type = 'dropdown', position = 'bottom-left', value, defaultValue = '#006FFF', showInput = true, showAlpha = true, showFormatSelector = true, showCopyButton = true, disabled = false, readonly = false, onChangeFormat = 'hex', fireOnInit = false, changeDebounceMs = 0, onChange, onApply, onCancel, className, }) => {
5433
+ /** 초기 HSV props에서 즉시 도출(StrictMode 안전) */
5434
+ const initialHex = normalizeHex(value || defaultValue) || '#006FFF';
5435
+ const initialRgb = hexToRgb(initialHex) || { r: 0, g: 111, b: 255 };
5436
+ const initialHsv = rgbToHsv(initialRgb.r, initialRgb.g, initialRgb.b);
5437
+ const [h, setH] = React.useState(() => initialHsv.h);
5438
+ const [s, setS] = React.useState(() => initialHsv.s);
5439
+ const [v, setV] = React.useState(() => initialHsv.v);
5439
5440
  const [a, setA] = React.useState(100);
5440
5441
  const [isOpen, setIsOpen] = React.useState(false);
5441
5442
  const [format, setFormat] = React.useState('hex');
5442
5443
  const [isCopied, setIsCopied] = React.useState(false);
5443
- const [colorInput, setColorInput] = React.useState('');
5444
+ const [colorInput, setColorInput] = React.useState(() => initialHex);
5444
5445
  const [alphaInput, setAlphaInput] = React.useState('100');
5445
5446
  const [tempColor, setTempColor] = React.useState('');
5446
5447
  const pickerRef = React.useRef(null);
5447
5448
  const areaRef = React.useRef(null);
5448
5449
  const dragging = React.useRef(false);
5449
- /** 초기값 세팅 */
5450
+ /** onChange 보호 상태 */
5451
+ const lastEmittedRef = React.useRef(normalizeHex(initialHex)); // ✅ 초기값 미리 기록
5452
+ const didMountRef = React.useRef(false); // ✅ 첫 렌더 감지
5453
+ const emitErrorCountRef = React.useRef(0);
5454
+ const emitBlockedUntilRef = React.useRef(0);
5455
+ /** 제어형(value) 변화 → HSV 반영 */
5450
5456
  React.useEffect(() => {
5451
- const initial = (value || defaultValue).toUpperCase();
5452
- const rgb = hexToRgb(initial);
5453
- if (rgb) {
5454
- const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
5455
- setH(h);
5456
- setS(s);
5457
- setV(v);
5458
- }
5459
- setColorInput(initial);
5460
- setAlphaInput('100');
5461
- }, []);
5462
- /** 제어형(value) → HSV */
5463
- React.useEffect(() => {
5464
- if (!value)
5457
+ if (value == null)
5465
5458
  return;
5466
- const rgb = hexToRgb(value);
5467
- if (rgb) {
5468
- const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
5469
- setH(h);
5470
- setS(s);
5471
- setV(v);
5472
- }
5459
+ const norm = normalizeHex(value);
5460
+ const rgb = hexToRgb(norm);
5461
+ if (!rgb)
5462
+ return;
5463
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
5464
+ setH(hsv.h);
5465
+ setS(hsv.s);
5466
+ setV(hsv.v);
5467
+ setColorInput(norm);
5473
5468
  }, [value]);
5474
- /** RGB/HSL 계산 */
5469
+ /** 파생값 */
5475
5470
  const rgb = React.useMemo(() => hsvToRgb(h, s, v), [h, s, v]);
5476
- const hex = React.useMemo(() => rgbToHex(rgb.r, rgb.g, rgb.b), [rgb]);
5471
+ const hex = React.useMemo(() => toHex(rgb.r, rgb.g, rgb.b), [rgb]);
5477
5472
  const hsl = React.useMemo(() => rgbToHsl(rgb.r, rgb.g, rgb.b), [rgb]);
5478
- /** 출력값 formatted */
5479
- const formatted = React.useMemo(() => {
5473
+ /** UI 표시 문자열 */
5474
+ const uiFormatted = React.useMemo(() => {
5480
5475
  const alpha = a / 100;
5481
5476
  switch (format) {
5482
5477
  case 'hex': return hex;
5483
5478
  case 'rgb': return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
5484
5479
  case 'rgba': return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha.toFixed(2)})`;
5485
- case 'hsl': return `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
5486
- case 'hsla': return `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${alpha.toFixed(2)})`;
5480
+ case 'hsl': return `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;
5481
+ case 'hsla': return `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%, ${alpha.toFixed(2)})`;
5487
5482
  default: return hex;
5488
5483
  }
5489
5484
  }, [format, hex, rgb, hsl, a]);
5490
- /** 무한 루프 방지: formatted이 부모 value랑 같으면 onChange 호출하지 않음 */
5485
+ /** 콜백으로 내보낼 문자열 */
5486
+ const outward = React.useMemo(() => {
5487
+ if (onChangeFormat === 'hex')
5488
+ return hex;
5489
+ return uiFormatted;
5490
+ }, [hex, uiFormatted, onChangeFormat]);
5491
+ /** 최초 렌더 스킵 + 동일값/레이트리밋 검사 후 onChange */
5491
5492
  React.useEffect(() => {
5492
- if (value !== undefined && value.toUpperCase() === formatted.toUpperCase())
5493
+ if (!onChange)
5494
+ return;
5495
+ // 첫 렌더는 기본 차단 (옵션으로 허용)
5496
+ if (!didMountRef.current) {
5497
+ didMountRef.current = true;
5498
+ if (!fireOnInit)
5499
+ return; // 기본: 초기 발사 금지
5500
+ }
5501
+ const now = Date.now();
5502
+ if (emitBlockedUntilRef.current > now)
5493
5503
  return;
5494
- onChange?.(formatted);
5504
+ const currentHexNorm = normalizeHex(outward);
5505
+ const last = lastEmittedRef.current;
5506
+ // 제어형: 부모 value와 동일하면 발사 금지
5507
+ if (value && normalizeHex(value) === currentHexNorm)
5508
+ return;
5509
+ // 직전 발사값과 동일하면 금지
5510
+ if (last === currentHexNorm)
5511
+ return;
5512
+ const fire = () => {
5513
+ try {
5514
+ lastEmittedRef.current = currentHexNorm;
5515
+ onChange(onChangeFormat === 'hex' ? currentHexNorm : outward);
5516
+ emitErrorCountRef.current = 0;
5517
+ }
5518
+ catch (e) {
5519
+ emitErrorCountRef.current += 1;
5520
+ if (emitErrorCountRef.current >= 20) {
5521
+ emitBlockedUntilRef.current = Date.now() + 3000;
5522
+ // eslint-disable-next-line no-console
5523
+ console.warn('[ColorPicker] onChange errors too frequent; temporarily muted.');
5524
+ }
5525
+ }
5526
+ };
5527
+ if (changeDebounceMs > 0) {
5528
+ const t = setTimeout(fire, changeDebounceMs);
5529
+ return () => clearTimeout(t);
5530
+ }
5531
+ fire();
5495
5532
  // eslint-disable-next-line react-hooks/exhaustive-deps
5496
- }, [formatted]); // onChangevalue 의존성에서 제거
5497
- /** formatted 변경시 colorInput 동기화 */
5533
+ }, [outward]); // 의도적으로 onChange/value 제외
5534
+ /** colorInput 동기화(표시 전용) */
5498
5535
  React.useEffect(() => {
5499
- setColorInput(formatted.toUpperCase());
5500
- }, [formatted]);
5536
+ const next = format === 'hex' ? normalizeHex(uiFormatted) : uiFormatted;
5537
+ if (colorInput !== next)
5538
+ setColorInput(next);
5539
+ // eslint-disable-next-line react-hooks/exhaustive-deps
5540
+ }, [uiFormatted, format]);
5501
5541
  /** 드롭다운 외부 클릭 닫기 */
5502
5542
  React.useEffect(() => {
5503
5543
  const handler = (e) => {
5504
- if (pickerRef.current && !pickerRef.current.contains(e.target)) {
5544
+ if (pickerRef.current && !pickerRef.current.contains(e.target))
5505
5545
  setIsOpen(false);
5506
- }
5507
5546
  };
5508
5547
  if (isOpen && type === 'dropdown')
5509
5548
  document.addEventListener('mousedown', handler);
@@ -5517,8 +5556,8 @@
5517
5556
  const rect = el.getBoundingClientRect();
5518
5557
  const x = clamp(clientX - rect.left, 0, rect.width);
5519
5558
  const y = clamp(clientY - rect.top, 0, rect.height);
5520
- const newS = Math.round((x / rect.width) * 100);
5521
- const newV = Math.round(100 - (y / rect.height) * 100);
5559
+ const newS = (x / rect.width) * 100;
5560
+ const newV = 100 - (y / rect.height) * 100;
5522
5561
  setS(newS);
5523
5562
  setV(newV);
5524
5563
  };
@@ -5532,13 +5571,13 @@
5532
5571
  return; const t = e.touches[0]; updateFromArea(t.clientX, t.clientY); };
5533
5572
  const onAreaTouchEnd = () => { dragging.current = false; };
5534
5573
  /** 슬라이더 */
5535
- const onHueChange = React.useCallback((e) => setH(parseInt(e.target.value, 10)), []);
5574
+ const onHueChange = React.useCallback((e) => setH(parseFloat(e.target.value)), []);
5536
5575
  const onAlphaChange = React.useCallback((e) => {
5537
5576
  const newAlpha = parseInt(e.target.value, 10);
5538
5577
  setA(newAlpha);
5539
5578
  setAlphaInput(String(newAlpha));
5540
5579
  }, []);
5541
- /** 컬러 인풋 (엔터 확정) */
5580
+ /** 컬러 인풋 확정 */
5542
5581
  const commitColorInput = React.useCallback(() => {
5543
5582
  const str = colorInput.trim();
5544
5583
  if (/^#([0-9A-Fa-f]{6})$/.test(str)) {
@@ -5547,7 +5586,7 @@
5547
5586
  setH(hsv.h);
5548
5587
  setS(hsv.s);
5549
5588
  setV(hsv.v);
5550
- setColorInput(str.toUpperCase());
5589
+ setColorInput(normalizeHex(str));
5551
5590
  return;
5552
5591
  }
5553
5592
  let m = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(str);
@@ -5559,7 +5598,7 @@
5559
5598
  setH(hsv.h);
5560
5599
  setS(hsv.s);
5561
5600
  setV(hsv.v);
5562
- setColorInput(`rgb(${r}, ${g}, ${b})`.toUpperCase());
5601
+ setColorInput(`rgb(${r}, ${g}, ${b})`);
5563
5602
  return;
5564
5603
  }
5565
5604
  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);
@@ -5574,42 +5613,47 @@
5574
5613
  setV(hsv.v);
5575
5614
  setA(Math.round(alpha * 100));
5576
5615
  setAlphaInput(String(Math.round(alpha * 100)));
5577
- setColorInput(`rgba(${r}, ${g}, ${b}, ${alpha})`.toUpperCase());
5616
+ setColorInput(`rgba(${r}, ${g}, ${b}, ${alpha})`);
5578
5617
  return;
5579
5618
  }
5580
- setColorInput(formatted.toUpperCase());
5581
- }, [colorInput, formatted]);
5582
- const onColorKeyDown = (e) => {
5583
- if (e.key === 'Enter')
5584
- commitColorInput();
5619
+ // 인식 실패 → 표시값으로 원복
5620
+ setColorInput(format === 'hex' ? normalizeHex(uiFormatted) : uiFormatted);
5621
+ }, [colorInput, uiFormatted, format]);
5622
+ const onColorKeyDown = (e) => { if (e.key === 'Enter')
5623
+ commitColorInput(); };
5624
+ const onColorBlur = () => {
5625
+ const next = format === 'hex' ? normalizeHex(uiFormatted) : uiFormatted;
5626
+ if (colorInput !== next)
5627
+ setColorInput(next);
5585
5628
  };
5586
- const onColorBlur = () => setColorInput(formatted.toUpperCase());
5587
- /** 알파 인풋 (엔터 확정) */
5629
+ /** 알파 인풋 확정 */
5588
5630
  const commitAlphaInput = React.useCallback(() => {
5589
5631
  const n = Number(alphaInput.trim());
5590
5632
  if (!Number.isNaN(n) && n >= 0 && n <= 100) {
5591
- setA(Math.round(n));
5592
- setAlphaInput(String(Math.round(n)));
5633
+ const rounded = Math.round(n);
5634
+ if (a !== rounded)
5635
+ setA(rounded);
5636
+ if (alphaInput !== String(rounded))
5637
+ setAlphaInput(String(rounded));
5593
5638
  return;
5594
5639
  }
5595
5640
  setAlphaInput(String(a));
5596
5641
  }, [alphaInput, a]);
5597
- const onAlphaInputKeyDown = (e) => {
5598
- if (e.key === 'Enter')
5599
- commitAlphaInput();
5600
- };
5601
- const onAlphaInputBlur = () => setAlphaInput(String(a));
5642
+ const onAlphaInputKeyDown = (e) => { if (e.key === 'Enter')
5643
+ commitAlphaInput(); };
5644
+ const onAlphaInputBlur = () => { if (alphaInput !== String(a))
5645
+ setAlphaInput(String(a)); };
5602
5646
  /** 복사 */
5603
5647
  const onCopy = React.useCallback(async () => {
5604
5648
  try {
5605
- await navigator.clipboard.writeText(formatted);
5649
+ await navigator.clipboard.writeText(uiFormatted);
5606
5650
  setIsCopied(true);
5607
5651
  setTimeout(() => setIsCopied(false), 1600);
5608
5652
  }
5609
5653
  catch (e) {
5610
5654
  console.error(e);
5611
5655
  }
5612
- }, [formatted]);
5656
+ }, [uiFormatted]);
5613
5657
  /** EyeDropper */
5614
5658
  const onEyedrop = React.useCallback(async () => {
5615
5659
  try {
@@ -5627,7 +5671,7 @@
5627
5671
  console.error(e);
5628
5672
  }
5629
5673
  }, []);
5630
- /** modal open(중요: formatted deps 제거) */
5674
+ /** 모달 */
5631
5675
  const handleModalOpen = React.useCallback(() => {
5632
5676
  if (type === 'modal')
5633
5677
  setTempColor(hex);
@@ -5635,10 +5679,11 @@
5635
5679
  }, [type, hex]);
5636
5680
  const handleModalApply = React.useCallback(() => {
5637
5681
  if (type === 'modal') {
5638
- onApply?.(formatted);
5682
+ const out = onChangeFormat === 'hex' ? hex : uiFormatted;
5683
+ onApply?.(out);
5639
5684
  setIsOpen(false);
5640
5685
  }
5641
- }, [type, formatted, onApply]);
5686
+ }, [type, hex, uiFormatted, onApply, onChangeFormat]);
5642
5687
  const handleModalCancel = React.useCallback(() => {
5643
5688
  if (type === 'modal') {
5644
5689
  const rgb = hexToRgb(tempColor);
@@ -5655,28 +5700,28 @@
5655
5700
  /** 스타일 */
5656
5701
  const hueTrackStyle = React.useMemo(() => ({
5657
5702
  background: `linear-gradient(to right,
5658
- hsl(0,100%,50%),
5659
- hsl(60,100%,50%),
5660
- hsl(120,100%,50%),
5661
- hsl(180,100%,50%),
5662
- hsl(240,100%,50%),
5663
- hsl(300,100%,50%),
5664
- hsl(360,100%,50%))`,
5703
+ hsl(0,100%,50%),
5704
+ hsl(60,100%,50%),
5705
+ hsl(120,100%,50%),
5706
+ hsl(180,100%,50%),
5707
+ hsl(240,100%,50%),
5708
+ hsl(300,100%,50%),
5709
+ hsl(360,100%,50%))`,
5665
5710
  }), []);
5666
5711
  const areaBackground = React.useMemo(() => ({
5667
5712
  backgroundImage: `
5668
- linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)),
5669
- linear-gradient(to right, #ffffff, hsl(${h}, 100%, 50%))
5670
- `,
5713
+ linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0)),
5714
+ linear-gradient(to right, #ffffff, hsl(${h}, 100%, 50%))
5715
+ `,
5671
5716
  }), [h]);
5672
5717
  const alphaTrackStyle = React.useMemo(() => ({
5673
5718
  backgroundImage: `
5674
- linear-gradient(45deg, var(--db-border-base) 25%, transparent 25%),
5675
- linear-gradient(-45deg, var(--db-border-base) 25%, transparent 25%),
5676
- linear-gradient(45deg, transparent 75%, var(--db-border-base) 75%),
5677
- linear-gradient(-45deg, transparent 75%, var(--db-border-base) 75%),
5678
- linear-gradient(to right, rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0), rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 1))
5679
- `,
5719
+ linear-gradient(45deg, var(--db-border-base) 25%, transparent 25%),
5720
+ linear-gradient(-45deg, var(--db-border-base) 25%, transparent 25%),
5721
+ linear-gradient(45deg, transparent 75%, var(--db-border-base) 75%),
5722
+ linear-gradient(-45deg, transparent 75%, var(--db-border-base) 75%),
5723
+ linear-gradient(to right, rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0), rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 1))
5724
+ `,
5680
5725
  backgroundSize: '8px 8px,8px 8px,8px 8px,8px 8px,100% 100%',
5681
5726
  backgroundPosition: '0 0,0 4px,4px -4px,-4px 0,0 0',
5682
5727
  backgroundColor: 'var(--db-surface-base)',
@@ -5688,9 +5733,7 @@
5688
5733
  'designbase-color-picker--no-input': !showInput,
5689
5734
  }, className);
5690
5735
  const Trigger = (jsxRuntime.jsxs("div", { className: "designbase-color-picker__trigger", onClick: () => !disabled && !readonly && (type === 'modal' ? handleModalOpen() : setIsOpen(v => !v)), children: [jsxRuntime.jsx("div", { className: "designbase-color-picker__color-display", children: jsxRuntime.jsx("div", { className: "designbase-color-picker__color-box", style: {
5691
- backgroundColor: showAlpha
5692
- ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a / 100})`
5693
- : hex
5736
+ backgroundColor: showAlpha ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a / 100})` : hex
5694
5737
  } }) }), showInput && (jsxRuntime.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 && (jsxRuntime.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 ? jsxRuntime.jsx(icons.DoneIcon, { size: 14 }) : jsxRuntime.jsx(icons.CopyIcon, { size: 14 }) })), jsxRuntime.jsx("button", { type: "button", className: "designbase-color-picker__toggle", disabled: disabled, "aria-label": "Toggle color picker", children: jsxRuntime.jsx(icons.ChevronDownIcon, { size: 16 }) })] }));
5695
5738
  const Selector = (jsxRuntime.jsxs("div", { className: "designbase-color-picker__selector", children: [jsxRuntime.jsx("div", { className: "designbase-color-picker__color-area", children: jsxRuntime.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: jsxRuntime.jsx("div", { className: "designbase-color-picker__color-pointer", style: { left: `${s}%`, top: `${100 - v}%`, backgroundColor: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` } }) }) }), jsxRuntime.jsxs("div", { className: "designbase-color-picker__controls", children: [jsxRuntime.jsx(Button, { variant: "tertiary", size: "m", iconOnly: true, onClick: onEyedrop, "aria-label": "Eyedropper tool", children: jsxRuntime.jsx(icons.EyedropperIcon, {}) }), jsxRuntime.jsxs("div", { className: "designbase-color-picker__slider-container", children: [jsxRuntime.jsx("div", { className: "designbase-color-picker__hue-slider", children: jsxRuntime.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 && (jsxRuntime.jsx("div", { className: "designbase-color-picker__alpha-slider", children: jsxRuntime.jsx("input", { type: "range", min: 0, max: 100, value: a, onChange: onAlphaChange, className: "designbase-color-picker__slider designbase-color-picker__slider--alpha", style: alphaTrackStyle }) }))] })] }), jsxRuntime.jsxs("div", { className: "designbase-color-picker__value-display", children: [showFormatSelector && (jsxRuntime.jsx(Select, { value: format, onChange: (v) => setFormat(v), showClearButton: false, options: [
5696
5739
  { label: 'HEX', value: 'hex' },
@@ -7002,7 +7045,7 @@
7002
7045
  }, className);
7003
7046
  const textareaClasses = clsx('designbase-textarea__field', textareaClassName);
7004
7047
  const isOverLimit = maxLength && currentLength > maxLength;
7005
- return (jsxRuntime.jsxs("div", { className: classes, children: [label && (jsxRuntime.jsx(Label, { htmlFor: textareaId, required: required, error: error, disabled: disabled, size: size === 's' ? 'xs' : size === 'm' ? 's' : 'm', children: label })), showCharacterCount && characterCountPosition === 'top' && (jsxRuntime.jsx("div", { className: "designbase-textarea__character-count designbase-textarea__character-count--top", children: jsxRuntime.jsxs("span", { className: clsx('designbase-textarea__character-count-text', {
7048
+ return (jsxRuntime.jsxs("div", { className: classes, children: [label && (jsxRuntime.jsx(Label, { htmlFor: textareaId, required: required, error: error, disabled: disabled, size: size === 's' ? 's' : size === 'm' ? 'm' : 'l', children: label })), showCharacterCount && characterCountPosition === 'top' && (jsxRuntime.jsx("div", { className: "designbase-textarea__character-count designbase-textarea__character-count--top", children: jsxRuntime.jsxs("span", { className: clsx('designbase-textarea__character-count-text', {
7006
7049
  'designbase-textarea__character-count-text--error': isOverLimit
7007
7050
  }), children: [currentLength, maxLength && ` / ${maxLength}`] }) })), jsxRuntime.jsx("div", { className: "designbase-textarea__wrapper", children: jsxRuntime.jsx("textarea", { ref: forwardedRef, id: textareaId, className: textareaClasses, placeholder: placeholder, defaultValue: defaultValue, value: value, rows: rows, maxLength: maxLength, disabled: disabled, readOnly: readOnly, required: required, "aria-describedby": clsx({
7008
7051
  [helperTextId]: helperText,