@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.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.css.map +1 -1
- package/dist/index.esm.js +144 -101
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +144 -101
- 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 +144 -101
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
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 = '
|
|
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' ? '
|
|
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
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
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
|
|
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
|
-
/**
|
|
5436
|
-
const
|
|
5437
|
-
const
|
|
5438
|
-
const
|
|
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
|
-
|
|
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
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
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
|
-
/**
|
|
5469
|
+
/** 파생값 */
|
|
5475
5470
|
const rgb = React.useMemo(() => hsvToRgb(h, s, v), [h, s, v]);
|
|
5476
|
-
const hex = React.useMemo(() =>
|
|
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
|
-
/**
|
|
5479
|
-
const
|
|
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
|
-
/**
|
|
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 (
|
|
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
|
-
|
|
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
|
-
}, [
|
|
5497
|
-
/**
|
|
5533
|
+
}, [outward]); // 의도적으로 onChange/value 제외
|
|
5534
|
+
/** colorInput 동기화(표시 전용) */
|
|
5498
5535
|
React.useEffect(() => {
|
|
5499
|
-
|
|
5500
|
-
|
|
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 =
|
|
5521
|
-
const newV =
|
|
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(
|
|
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
|
|
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})
|
|
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})
|
|
5616
|
+
setColorInput(`rgba(${r}, ${g}, ${b}, ${alpha})`);
|
|
5578
5617
|
return;
|
|
5579
5618
|
}
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5592
|
-
|
|
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
|
-
|
|
5599
|
-
|
|
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(
|
|
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
|
-
}, [
|
|
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
|
-
/**
|
|
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
|
-
|
|
5682
|
+
const out = onChangeFormat === 'hex' ? hex : uiFormatted;
|
|
5683
|
+
onApply?.(out);
|
|
5639
5684
|
setIsOpen(false);
|
|
5640
5685
|
}
|
|
5641
|
-
}, [type,
|
|
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
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
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
|
-
|
|
5669
|
-
|
|
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
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
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' ? '
|
|
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,
|