sellmate-design-system-react 9.0.0-beta.89 → 9.0.0-beta.90
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/AGENTS.md +46 -2
- package/dist/components/SChatInput/README.md +3 -1
- package/dist/components/SChatInput/SChatInput.d.ts +18 -1
- package/dist/components/SChatMessage/README.md +1 -0
- package/dist/components/SChatMessage/SChatMessage.d.ts +12 -0
- package/dist/components/SCheckbox/README.md +1 -0
- package/dist/components/SCheckbox/SCheckbox.d.ts +9 -1
- package/dist/components/SChipInput/README.md +4 -1
- package/dist/components/SChipInput/SChipInput.d.ts +30 -0
- package/dist/components/SEditor/EditorBody.d.ts +12 -0
- package/dist/components/SEditor/README.md +2 -0
- package/dist/components/SField/README.md +3 -0
- package/dist/components/SField/SField.d.ts +19 -0
- package/dist/components/SField/index.d.ts +1 -1
- package/dist/components/SListItem/README.md +1 -1
- package/dist/components/SListItem/SListItem.d.ts +4 -0
- package/dist/components/SSlider/README.md +86 -0
- package/dist/components/SSlider/SSlider.d.ts +149 -0
- package/dist/components/SSlider/index.d.ts +1 -0
- package/dist/index.cjs +483 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +481 -17
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +143 -5
- package/dist/llms.txt +48 -4
- package/dist/styles.css +37 -0
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -14,6 +14,7 @@ var RDropdown5 = require('@radix-ui/react-dropdown-menu');
|
|
|
14
14
|
var RSwitch = require('@radix-ui/react-switch');
|
|
15
15
|
var RDialog = require('@radix-ui/react-dialog');
|
|
16
16
|
var Ariakit = require('@ariakit/react');
|
|
17
|
+
var RSlider = require('@radix-ui/react-slider');
|
|
17
18
|
|
|
18
19
|
function _interopNamespace(e) {
|
|
19
20
|
if (e && e.__esModule) return e;
|
|
@@ -40,6 +41,7 @@ var RDropdown5__namespace = /*#__PURE__*/_interopNamespace(RDropdown5);
|
|
|
40
41
|
var RSwitch__namespace = /*#__PURE__*/_interopNamespace(RSwitch);
|
|
41
42
|
var RDialog__namespace = /*#__PURE__*/_interopNamespace(RDialog);
|
|
42
43
|
var Ariakit__namespace = /*#__PURE__*/_interopNamespace(Ariakit);
|
|
44
|
+
var RSlider__namespace = /*#__PURE__*/_interopNamespace(RSlider);
|
|
43
45
|
|
|
44
46
|
var isSdSpacing = (value) => /^sd-\d+$/.test(value);
|
|
45
47
|
var SD_SPACING_GROUPS = [
|
|
@@ -4898,10 +4900,16 @@ var ALIGN = {
|
|
|
4898
4900
|
end: "flex-end"
|
|
4899
4901
|
};
|
|
4900
4902
|
var FOCUS_RING_SHADOW = "0px 0px 4px 0px #0071ff66";
|
|
4903
|
+
var fieldLabelId = (controlId) => `${controlId}-label`;
|
|
4904
|
+
function useFieldControlId(id) {
|
|
4905
|
+
const autoId = react.useId();
|
|
4906
|
+
return id ?? autoId;
|
|
4907
|
+
}
|
|
4901
4908
|
var cssLen = (v) => v === void 0 || v === "" || v === 0 ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
4902
4909
|
var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
4903
4910
|
name,
|
|
4904
4911
|
label = "",
|
|
4912
|
+
controlId,
|
|
4905
4913
|
subLabel = "",
|
|
4906
4914
|
icon,
|
|
4907
4915
|
iconColor,
|
|
@@ -5024,7 +5032,19 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
|
|
|
5024
5032
|
style: { marginRight: s.labelGap }
|
|
5025
5033
|
}
|
|
5026
5034
|
),
|
|
5027
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5035
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5036
|
+
"label",
|
|
5037
|
+
{
|
|
5038
|
+
id: controlId ? fieldLabelId(controlId) : void 0,
|
|
5039
|
+
htmlFor: controlId,
|
|
5040
|
+
className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap",
|
|
5041
|
+
onClick: () => {
|
|
5042
|
+
const control = controlId ? document.getElementById(controlId) : null;
|
|
5043
|
+
if (control && !("labels" in control)) control.focus();
|
|
5044
|
+
},
|
|
5045
|
+
children: label
|
|
5046
|
+
}
|
|
5047
|
+
),
|
|
5028
5048
|
subLabel !== "" && // field 라벨 토큰이 아니라 기본 타이포 토큰을 쓴다 — 보조 라벨은 굵기·색이 라벨과
|
|
5029
5049
|
// 따로 가므로 field 토큰에 묶지 않는다. 크기도 size 와 무관하게 body/sm 고정.
|
|
5030
5050
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5176,6 +5196,7 @@ var STextarea = /* @__PURE__ */ react.forwardRef(function STextarea2({
|
|
|
5176
5196
|
const minHeight = heightForRows(MIN_ROWS);
|
|
5177
5197
|
const maxHeight = autogrow && maxRows != null ? heightForRows(maxRows) : void 0;
|
|
5178
5198
|
const [ruleError, setRuleError] = react.useState("");
|
|
5199
|
+
const controlId = useFieldControlId(rest.id);
|
|
5179
5200
|
const innerRef = react.useRef(null);
|
|
5180
5201
|
const setRefs2 = react.useCallback(
|
|
5181
5202
|
(node) => {
|
|
@@ -5217,6 +5238,7 @@ var STextarea = /* @__PURE__ */ react.forwardRef(function STextarea2({
|
|
|
5217
5238
|
SField,
|
|
5218
5239
|
{
|
|
5219
5240
|
label,
|
|
5241
|
+
controlId,
|
|
5220
5242
|
labelPosition,
|
|
5221
5243
|
subLabel,
|
|
5222
5244
|
labelWidth,
|
|
@@ -5243,6 +5265,7 @@ var STextarea = /* @__PURE__ */ react.forwardRef(function STextarea2({
|
|
|
5243
5265
|
"textarea",
|
|
5244
5266
|
{
|
|
5245
5267
|
ref: setRefs2,
|
|
5268
|
+
id: controlId,
|
|
5246
5269
|
value: value ?? "",
|
|
5247
5270
|
rows,
|
|
5248
5271
|
disabled,
|
|
@@ -5293,7 +5316,9 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5293
5316
|
placeholder = DEFAULT_PLACEHOLDER,
|
|
5294
5317
|
disabled = false,
|
|
5295
5318
|
onSend,
|
|
5319
|
+
hasAttachments = false,
|
|
5296
5320
|
onAttach,
|
|
5321
|
+
onPasteFiles,
|
|
5297
5322
|
busy = false,
|
|
5298
5323
|
onStop,
|
|
5299
5324
|
footerAction,
|
|
@@ -5303,17 +5328,26 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5303
5328
|
textareaClassName,
|
|
5304
5329
|
...rest
|
|
5305
5330
|
}, ref) {
|
|
5306
|
-
const
|
|
5331
|
+
const hasText = value.trim() !== "";
|
|
5332
|
+
const canSend = !disabled && !busy && (hasText || hasAttachments);
|
|
5307
5333
|
const send = react.useCallback(() => {
|
|
5308
5334
|
if (!canSend) return;
|
|
5309
|
-
onSend?.(value);
|
|
5310
|
-
}, [canSend, onSend, value]);
|
|
5335
|
+
onSend?.(hasText ? value : "");
|
|
5336
|
+
}, [canSend, hasText, onSend, value]);
|
|
5311
5337
|
const handleKeyDown = (e) => {
|
|
5312
5338
|
rest.onKeyDown?.(e);
|
|
5313
5339
|
if (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing) return;
|
|
5314
5340
|
e.preventDefault();
|
|
5315
5341
|
send();
|
|
5316
5342
|
};
|
|
5343
|
+
const handlePaste = (e) => {
|
|
5344
|
+
rest.onPaste?.(e);
|
|
5345
|
+
if (onPasteFiles == null || e.defaultPrevented) return;
|
|
5346
|
+
const files = Array.from(e.clipboardData.files);
|
|
5347
|
+
if (files.length === 0) return;
|
|
5348
|
+
e.preventDefault();
|
|
5349
|
+
onPasteFiles(files);
|
|
5350
|
+
};
|
|
5317
5351
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col bg-(--cmp-chatInput-bg)", className), style, children: [
|
|
5318
5352
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-(--cmp-chatInput-gap) p-(--cmp-chatInput-padding)", children: [
|
|
5319
5353
|
onAttach != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5344,7 +5378,8 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5344
5378
|
textareaClassName,
|
|
5345
5379
|
textareaStyle: { minHeight: TEXTAREA_MIN_HEIGHT },
|
|
5346
5380
|
...rest,
|
|
5347
|
-
onKeyDown: handleKeyDown
|
|
5381
|
+
onKeyDown: handleKeyDown,
|
|
5382
|
+
onPaste: handlePaste
|
|
5348
5383
|
}
|
|
5349
5384
|
),
|
|
5350
5385
|
busy ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5605,6 +5640,7 @@ var SChatMessageImpl = /* @__PURE__ */ react.forwardRef(function SChatMessage({
|
|
|
5605
5640
|
readStatus,
|
|
5606
5641
|
avatarSrc,
|
|
5607
5642
|
avatarAlt,
|
|
5643
|
+
showAvatar = true,
|
|
5608
5644
|
continued = false,
|
|
5609
5645
|
variant = "default",
|
|
5610
5646
|
actions,
|
|
@@ -5635,7 +5671,7 @@ var SChatMessageImpl = /* @__PURE__ */ react.forwardRef(function SChatMessage({
|
|
|
5635
5671
|
),
|
|
5636
5672
|
...rest,
|
|
5637
5673
|
children: [
|
|
5638
|
-
!outgoing && /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: avatarSrc, alt: avatarAlt, placeholder: continued }),
|
|
5674
|
+
!outgoing && showAvatar && /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: avatarSrc, alt: avatarAlt, placeholder: continued }),
|
|
5639
5675
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5640
5676
|
"div",
|
|
5641
5677
|
{
|
|
@@ -6782,6 +6818,7 @@ var SListItemImpl = /* @__PURE__ */ react.forwardRef(function SListItem({
|
|
|
6782
6818
|
className,
|
|
6783
6819
|
onMouseEnter,
|
|
6784
6820
|
onMouseLeave,
|
|
6821
|
+
onKeyDown,
|
|
6785
6822
|
...rest
|
|
6786
6823
|
}, ref) {
|
|
6787
6824
|
const [hovered, setHovered] = react.useState(false);
|
|
@@ -6805,15 +6842,29 @@ var SListItemImpl = /* @__PURE__ */ react.forwardRef(function SListItem({
|
|
|
6805
6842
|
setHovered(false);
|
|
6806
6843
|
onMouseLeave?.(event);
|
|
6807
6844
|
};
|
|
6845
|
+
const pressable = isInteractive && rest.onClick != null;
|
|
6846
|
+
const handleKeyDown = (event) => {
|
|
6847
|
+
onKeyDown?.(event);
|
|
6848
|
+
if (!pressable || event.defaultPrevented || event.target !== event.currentTarget) return;
|
|
6849
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
6850
|
+
event.preventDefault();
|
|
6851
|
+
event.currentTarget.click();
|
|
6852
|
+
}
|
|
6853
|
+
};
|
|
6808
6854
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6809
6855
|
"div",
|
|
6810
6856
|
{
|
|
6811
6857
|
ref,
|
|
6812
6858
|
"aria-disabled": disabled || void 0,
|
|
6859
|
+
role: pressable ? "button" : void 0,
|
|
6860
|
+
tabIndex: pressable ? 0 : void 0,
|
|
6813
6861
|
onMouseEnter: handleMouseEnter,
|
|
6814
6862
|
onMouseLeave: handleMouseLeave,
|
|
6863
|
+
onKeyDown: handleKeyDown,
|
|
6815
6864
|
className: cn(
|
|
6816
6865
|
"group/list-item relative flex w-full items-center justify-between bg-(--cmp-listItem-bg-default) text-left text-(--cmp-listItem-text-default)",
|
|
6866
|
+
// 링을 안쪽으로 그린다 — bordered 항목은 overflow-hidden 이라 바깥 링이 잘린다
|
|
6867
|
+
pressable && "focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--sys-color-border-accent)",
|
|
6817
6868
|
titleTypo,
|
|
6818
6869
|
disabled ? "pointer-events-none cursor-not-allowed text-(--sys-color-disabled-text)" : isSelected ? cn(
|
|
6819
6870
|
"cursor-pointer text-(--cmp-listItem-text-selected)",
|
|
@@ -7497,6 +7548,7 @@ function SCheckbox({
|
|
|
7497
7548
|
val,
|
|
7498
7549
|
onValueChange,
|
|
7499
7550
|
label = "",
|
|
7551
|
+
ariaLabel,
|
|
7500
7552
|
disabled = false,
|
|
7501
7553
|
inverse = false,
|
|
7502
7554
|
className,
|
|
@@ -7537,6 +7589,7 @@ function SCheckbox({
|
|
|
7537
7589
|
checked: state2,
|
|
7538
7590
|
disabled,
|
|
7539
7591
|
onCheckedChange: handleChange,
|
|
7592
|
+
"aria-label": ariaLabel,
|
|
7540
7593
|
className: cn(
|
|
7541
7594
|
"flex h-[var(--cmp-checkbox-size)] w-[var(--cmp-checkbox-size)] items-center justify-center rounded-[var(--cmp-checkbox-radius)] border-[length:var(--cmp-checkbox-borderWidth)] border-solid bg-[var(--cb-bg)] border-[color:var(--cb-border)] outline-none",
|
|
7542
7595
|
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
@@ -15737,6 +15790,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
15737
15790
|
const baseId = react.useId();
|
|
15738
15791
|
const listboxId = `${baseId}-listbox`;
|
|
15739
15792
|
const activeOptionId = `${baseId}-active-option`;
|
|
15793
|
+
const triggerId = `${baseId}-trigger`;
|
|
15740
15794
|
const [win, setWin] = react.useState({ start: 0, end: 0, top: 0, bottom: 0 });
|
|
15741
15795
|
const winRef = react.useRef(win);
|
|
15742
15796
|
winRef.current = win;
|
|
@@ -16223,6 +16277,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16223
16277
|
SField,
|
|
16224
16278
|
{
|
|
16225
16279
|
label,
|
|
16280
|
+
controlId: triggerId,
|
|
16226
16281
|
labelPosition,
|
|
16227
16282
|
subLabel,
|
|
16228
16283
|
labelWidth,
|
|
@@ -16248,8 +16303,10 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16248
16303
|
"button",
|
|
16249
16304
|
{
|
|
16250
16305
|
ref: triggerRef,
|
|
16306
|
+
id: triggerId,
|
|
16251
16307
|
type: "button",
|
|
16252
16308
|
disabled: effectiveDisabled,
|
|
16309
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerId}` : void 0,
|
|
16253
16310
|
"aria-haspopup": "listbox",
|
|
16254
16311
|
"aria-expanded": open,
|
|
16255
16312
|
"aria-controls": open ? listboxId : void 0,
|
|
@@ -16345,7 +16402,12 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
|
|
|
16345
16402
|
event.preventDefault();
|
|
16346
16403
|
requestAnimationFrame(() => searchInputRef.current?.focus());
|
|
16347
16404
|
},
|
|
16348
|
-
onPointerDownOutside: () => {
|
|
16405
|
+
onPointerDownOutside: (event) => {
|
|
16406
|
+
const target = event.target;
|
|
16407
|
+
if (label && target?.closest?.(`[id="${fieldLabelId(triggerId)}"]`)) {
|
|
16408
|
+
event.preventDefault();
|
|
16409
|
+
return;
|
|
16410
|
+
}
|
|
16349
16411
|
dismissedByPointerRef.current = true;
|
|
16350
16412
|
},
|
|
16351
16413
|
onCloseAutoFocus: (event) => {
|
|
@@ -18265,6 +18327,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
18265
18327
|
}, ref) {
|
|
18266
18328
|
const [visible, setVisible] = react.useState(false);
|
|
18267
18329
|
const [ruleError, setRuleError] = react.useState("");
|
|
18330
|
+
const controlId = useFieldControlId(rest.id);
|
|
18268
18331
|
const f = FONT2[size];
|
|
18269
18332
|
const isPassword = type === "password";
|
|
18270
18333
|
const inputType = isPassword ? visible ? "text" : "password" : type;
|
|
@@ -18289,6 +18352,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
18289
18352
|
SField,
|
|
18290
18353
|
{
|
|
18291
18354
|
label,
|
|
18355
|
+
controlId,
|
|
18292
18356
|
labelPosition,
|
|
18293
18357
|
subLabel,
|
|
18294
18358
|
labelWidth,
|
|
@@ -18328,6 +18392,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
|
|
|
18328
18392
|
"input",
|
|
18329
18393
|
{
|
|
18330
18394
|
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
18395
|
+
id: controlId,
|
|
18331
18396
|
type: inputType,
|
|
18332
18397
|
value: value ?? "",
|
|
18333
18398
|
disabled,
|
|
@@ -18503,6 +18568,7 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
18503
18568
|
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|
|
18504
18569
|
const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
|
|
18505
18570
|
const [ruleError, setRuleError] = react.useState("");
|
|
18571
|
+
const controlId = useFieldControlId();
|
|
18506
18572
|
const [rangeError, setRangeError] = react.useState("");
|
|
18507
18573
|
const innerRef = react.useRef(null);
|
|
18508
18574
|
const valueTooltip = useTruncatedValueTooltip({ enabled: readOnly && !disabled, text: display });
|
|
@@ -18652,6 +18718,7 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
18652
18718
|
SField,
|
|
18653
18719
|
{
|
|
18654
18720
|
label,
|
|
18721
|
+
controlId,
|
|
18655
18722
|
labelPosition,
|
|
18656
18723
|
subLabel,
|
|
18657
18724
|
labelWidth,
|
|
@@ -18691,6 +18758,7 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
|
|
|
18691
18758
|
"input",
|
|
18692
18759
|
{
|
|
18693
18760
|
ref: setRefs2,
|
|
18761
|
+
id: controlId,
|
|
18694
18762
|
name,
|
|
18695
18763
|
type: "text",
|
|
18696
18764
|
inputMode: allowDecimal ? "decimal" : "numeric",
|
|
@@ -19392,6 +19460,8 @@ function SDatePicker({
|
|
|
19392
19460
|
}) {
|
|
19393
19461
|
const portalContainer = usePortalContainer();
|
|
19394
19462
|
const [open, setOpen] = react.useState(false);
|
|
19463
|
+
const triggerId = useFieldControlId();
|
|
19464
|
+
const triggerTextId = `${triggerId}-text`;
|
|
19395
19465
|
const [focused, setFocused] = react.useState(false);
|
|
19396
19466
|
const [ruleError, setRuleError] = react.useState("");
|
|
19397
19467
|
const hasValue = value != null && value !== "";
|
|
@@ -19448,6 +19518,7 @@ function SDatePicker({
|
|
|
19448
19518
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19449
19519
|
SField,
|
|
19450
19520
|
{
|
|
19521
|
+
controlId: triggerId,
|
|
19451
19522
|
label,
|
|
19452
19523
|
labelPosition,
|
|
19453
19524
|
subLabel,
|
|
@@ -19474,8 +19545,10 @@ function SDatePicker({
|
|
|
19474
19545
|
/* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19475
19546
|
"div",
|
|
19476
19547
|
{
|
|
19548
|
+
id: triggerId,
|
|
19477
19549
|
role: "button",
|
|
19478
19550
|
"aria-disabled": disabled,
|
|
19551
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerTextId}` : void 0,
|
|
19479
19552
|
tabIndex: disabled ? -1 : 0,
|
|
19480
19553
|
"data-name": name,
|
|
19481
19554
|
onFocus: () => setFocused(true),
|
|
@@ -19505,6 +19578,7 @@ function SDatePicker({
|
|
|
19505
19578
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19506
19579
|
"span",
|
|
19507
19580
|
{
|
|
19581
|
+
id: triggerTextId,
|
|
19508
19582
|
className: "flex-1 truncate text-center",
|
|
19509
19583
|
style: {
|
|
19510
19584
|
minWidth: dims.minW,
|
|
@@ -19931,6 +20005,8 @@ function SDateRangePicker({
|
|
|
19931
20005
|
}) {
|
|
19932
20006
|
const portalContainer = usePortalContainer();
|
|
19933
20007
|
const [open, setOpen] = react.useState(false);
|
|
20008
|
+
const triggerId = useFieldControlId();
|
|
20009
|
+
const triggerTextId = `${triggerId}-text`;
|
|
19934
20010
|
const [ruleError, setRuleError] = react.useState("");
|
|
19935
20011
|
const [pendingStart, setPendingStart] = react.useState(null);
|
|
19936
20012
|
const hasValue = value != null && value[0] !== "" && value[1] !== "";
|
|
@@ -19987,6 +20063,7 @@ function SDateRangePicker({
|
|
|
19987
20063
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19988
20064
|
SField,
|
|
19989
20065
|
{
|
|
20066
|
+
controlId: triggerId,
|
|
19990
20067
|
label,
|
|
19991
20068
|
labelPosition,
|
|
19992
20069
|
subLabel,
|
|
@@ -20022,8 +20099,10 @@ function SDateRangePicker({
|
|
|
20022
20099
|
/* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20023
20100
|
"div",
|
|
20024
20101
|
{
|
|
20102
|
+
id: triggerId,
|
|
20025
20103
|
role: "button",
|
|
20026
20104
|
"aria-disabled": disabled,
|
|
20105
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerTextId}` : void 0,
|
|
20027
20106
|
tabIndex: disabled ? -1 : 0,
|
|
20028
20107
|
"data-name": name,
|
|
20029
20108
|
onKeyDown: (event) => {
|
|
@@ -20051,6 +20130,7 @@ function SDateRangePicker({
|
|
|
20051
20130
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20052
20131
|
"span",
|
|
20053
20132
|
{
|
|
20133
|
+
id: triggerTextId,
|
|
20054
20134
|
className: cn(
|
|
20055
20135
|
"flex-1 items-center",
|
|
20056
20136
|
hasDisplay ? "flex" : "block truncate text-center"
|
|
@@ -20313,6 +20393,8 @@ function SFilePicker({
|
|
|
20313
20393
|
}) {
|
|
20314
20394
|
const autoId = react.useId();
|
|
20315
20395
|
const resolvedName = name ?? autoId;
|
|
20396
|
+
const triggerId = `${autoId}-trigger`;
|
|
20397
|
+
const displayTextId = `${autoId}-text`;
|
|
20316
20398
|
const inputRef = react.useRef(null);
|
|
20317
20399
|
const contentBoxRef = react.useRef(null);
|
|
20318
20400
|
const [ruleError, setRuleError] = react.useState("");
|
|
@@ -20413,10 +20495,12 @@ function SFilePicker({
|
|
|
20413
20495
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20414
20496
|
"button",
|
|
20415
20497
|
{
|
|
20498
|
+
id: triggerId,
|
|
20416
20499
|
type: "button",
|
|
20417
20500
|
disabled,
|
|
20418
20501
|
onClick: open,
|
|
20419
20502
|
"aria-label": placeholder,
|
|
20503
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${displayTextId}` : void 0,
|
|
20420
20504
|
className: cn(
|
|
20421
20505
|
"flex min-w-0 flex-1 items-center bg-transparent text-left",
|
|
20422
20506
|
gapCls,
|
|
@@ -20434,6 +20518,7 @@ function SFilePicker({
|
|
|
20434
20518
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20435
20519
|
"span",
|
|
20436
20520
|
{
|
|
20521
|
+
id: displayTextId,
|
|
20437
20522
|
className: cn(
|
|
20438
20523
|
"min-w-0 flex-1 truncate text-[12px]",
|
|
20439
20524
|
inlinePlaceholder && "text-[color:var(--cmp-filepicker-text-placeholder)] transition-colors group-hover/filepicker:text-[color:var(--cmp-filepicker-text-default)]"
|
|
@@ -20481,6 +20566,7 @@ function SFilePicker({
|
|
|
20481
20566
|
{
|
|
20482
20567
|
borderless: inline,
|
|
20483
20568
|
label,
|
|
20569
|
+
controlId: triggerId,
|
|
20484
20570
|
labelPosition,
|
|
20485
20571
|
subLabel,
|
|
20486
20572
|
labelWidth,
|
|
@@ -25037,8 +25123,12 @@ var EditorBody = /* @__PURE__ */ react.forwardRef(function EditorBody2({
|
|
|
25037
25123
|
bubbleMenu,
|
|
25038
25124
|
onImageUpload,
|
|
25039
25125
|
editorClassName,
|
|
25040
|
-
editorStyle
|
|
25126
|
+
editorStyle,
|
|
25127
|
+
controlId,
|
|
25128
|
+
labelled
|
|
25041
25129
|
}, ref) {
|
|
25130
|
+
const labelledRef = react.useRef(labelled);
|
|
25131
|
+
labelledRef.current = labelled;
|
|
25042
25132
|
const placeholderRef = react.useRef(placeholder);
|
|
25043
25133
|
placeholderRef.current = placeholder;
|
|
25044
25134
|
const handlers = react.useRef({ onInput, onFocusChange });
|
|
@@ -25053,6 +25143,10 @@ var EditorBody = /* @__PURE__ */ react.forwardRef(function EditorBody2({
|
|
|
25053
25143
|
editable,
|
|
25054
25144
|
// 소비 앱이 Next.js RSC 라면 첫 렌더가 서버에서 일어난다 — 즉시 렌더하면 하이드레이션이 어긋난다
|
|
25055
25145
|
immediatelyRender: false,
|
|
25146
|
+
// 본문은 contenteditable 이라 <label for> 가 닿지 않는다 — 레이블 id 로 이름을 잇는다
|
|
25147
|
+
editorProps: {
|
|
25148
|
+
attributes: () => labelledRef.current ? { "id": controlId, "aria-labelledby": fieldLabelId(controlId) } : { id: controlId }
|
|
25149
|
+
},
|
|
25056
25150
|
onUpdate: ({ editor: e }) => {
|
|
25057
25151
|
const html = e.isEmpty ? "" : e.getHTML();
|
|
25058
25152
|
htmlRef.current = html;
|
|
@@ -25271,6 +25365,7 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
|
|
|
25271
25365
|
}, ref) {
|
|
25272
25366
|
const [ruleError, setRuleError] = react.useState("");
|
|
25273
25367
|
const [selfFocused, setSelfFocused] = react.useState(false);
|
|
25368
|
+
const controlId = useFieldControlId();
|
|
25274
25369
|
const htmlRef = react.useRef(value ?? defaultValue ?? "");
|
|
25275
25370
|
const bodyRef = react.useRef(null);
|
|
25276
25371
|
const pendingFocusRef = react.useRef(false);
|
|
@@ -25341,6 +25436,7 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
|
|
|
25341
25436
|
{
|
|
25342
25437
|
name,
|
|
25343
25438
|
label,
|
|
25439
|
+
controlId,
|
|
25344
25440
|
labelPosition,
|
|
25345
25441
|
subLabel,
|
|
25346
25442
|
labelWidth,
|
|
@@ -25404,6 +25500,8 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
|
|
|
25404
25500
|
toolbar: resolvedToolbar,
|
|
25405
25501
|
bubbleMenu: resolvedBubbleMenu,
|
|
25406
25502
|
onImageUpload,
|
|
25503
|
+
controlId,
|
|
25504
|
+
labelled: !!label,
|
|
25407
25505
|
editorClassName,
|
|
25408
25506
|
editorStyle
|
|
25409
25507
|
}
|
|
@@ -25411,6 +25509,302 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
|
|
|
25411
25509
|
}
|
|
25412
25510
|
);
|
|
25413
25511
|
});
|
|
25512
|
+
var TRACK = 6;
|
|
25513
|
+
var THUMB = 16;
|
|
25514
|
+
var PRESS_SCALE = 1.2;
|
|
25515
|
+
var PRESS_GROW = THUMB * (PRESS_SCALE - 1) / 2;
|
|
25516
|
+
var SHADOW_Y = 2;
|
|
25517
|
+
var SHADOW_BLUR = 4;
|
|
25518
|
+
var KNOB_BLEED = Math.ceil(PRESS_GROW + SHADOW_BLUR);
|
|
25519
|
+
var MARK_DOT = 4;
|
|
25520
|
+
var BUBBLE_HEIGHT = 18;
|
|
25521
|
+
var BUBBLE_GAP = 4;
|
|
25522
|
+
var ROW_HEIGHT = { sm: 28, md: 36 };
|
|
25523
|
+
var COLOR = {
|
|
25524
|
+
track: "var(--sys-color-border-default)",
|
|
25525
|
+
trackDisabled: "var(--sys-color-disabled-bg)",
|
|
25526
|
+
range: "var(--sys-color-bg-accent)",
|
|
25527
|
+
rangeDisabled: "var(--color-brilliantblue-40)",
|
|
25528
|
+
thumbBg: "var(--sys-color-bg-frame)",
|
|
25529
|
+
markOn: "var(--sys-color-bg-frame)",
|
|
25530
|
+
markOff: "var(--sys-color-border-strong)",
|
|
25531
|
+
markOffDisabled: "var(--sys-color-disabled-border)",
|
|
25532
|
+
markLabel: "var(--sys-color-fg-tertiary)",
|
|
25533
|
+
bubbleBg: "var(--sys-color-bg-deep)",
|
|
25534
|
+
bubbleText: "var(--sys-color-fg-inverse)"
|
|
25535
|
+
};
|
|
25536
|
+
var thumbAlignedLeft = (pct) => `calc(${pct}% + ${THUMB / 2 * (1 - pct / 50)}px)`;
|
|
25537
|
+
var toPercent = (v, min, max) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
25538
|
+
var SSlider = /* @__PURE__ */ react.forwardRef(function SSlider2({
|
|
25539
|
+
value,
|
|
25540
|
+
onValueChange,
|
|
25541
|
+
onValueCommit,
|
|
25542
|
+
min = 0,
|
|
25543
|
+
max = 100,
|
|
25544
|
+
step = 1,
|
|
25545
|
+
marks,
|
|
25546
|
+
showValue = "drag",
|
|
25547
|
+
formatValue = String,
|
|
25548
|
+
size = "sm",
|
|
25549
|
+
rules,
|
|
25550
|
+
name,
|
|
25551
|
+
status,
|
|
25552
|
+
label,
|
|
25553
|
+
labelPosition,
|
|
25554
|
+
subLabel,
|
|
25555
|
+
labelWidth,
|
|
25556
|
+
icon,
|
|
25557
|
+
iconColor,
|
|
25558
|
+
labelTooltip,
|
|
25559
|
+
labelTooltipProps,
|
|
25560
|
+
hint,
|
|
25561
|
+
error,
|
|
25562
|
+
errorMessage,
|
|
25563
|
+
width,
|
|
25564
|
+
disabled = false,
|
|
25565
|
+
readOnly = false,
|
|
25566
|
+
className,
|
|
25567
|
+
style
|
|
25568
|
+
}, ref) {
|
|
25569
|
+
const isRange = Array.isArray(value);
|
|
25570
|
+
const values = isRange ? value : [value ?? min];
|
|
25571
|
+
const toOut = (v) => isRange ? [v[0], v[1]] : v[0];
|
|
25572
|
+
const [ruleError, setRuleError] = react.useState("");
|
|
25573
|
+
useFormField({
|
|
25574
|
+
name,
|
|
25575
|
+
validate: () => {
|
|
25576
|
+
const msg = runRules(value, rules);
|
|
25577
|
+
setRuleError(msg);
|
|
25578
|
+
return msg === "";
|
|
25579
|
+
},
|
|
25580
|
+
resetValidation: () => setRuleError("")
|
|
25581
|
+
});
|
|
25582
|
+
const resolvedError = error || ruleError !== "";
|
|
25583
|
+
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
25584
|
+
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
25585
|
+
const [dragging, setDragging] = react.useState(false);
|
|
25586
|
+
const [focusIndex, setFocusIndex] = react.useState(null);
|
|
25587
|
+
const thumbId = useFieldControlId();
|
|
25588
|
+
const wrapRef = react.useRef(null);
|
|
25589
|
+
const bubbleRefs = react.useRef([]);
|
|
25590
|
+
const layoutKey = `${values.join(",")}|${values.map(formatValue).join(",")}`;
|
|
25591
|
+
react.useLayoutEffect(() => {
|
|
25592
|
+
const wrap = wrapRef.current;
|
|
25593
|
+
if (!wrap) return;
|
|
25594
|
+
const layout = () => {
|
|
25595
|
+
const outer = wrap.clientWidth;
|
|
25596
|
+
const track = outer - KNOB_BLEED * 2;
|
|
25597
|
+
bubbleRefs.current.forEach((el, i) => {
|
|
25598
|
+
if (!el || values[i] === void 0) return;
|
|
25599
|
+
const pct = toPercent(values[i], min, max);
|
|
25600
|
+
const center = KNOB_BLEED + track * pct / 100 + THUMB / 2 * (1 - pct / 50);
|
|
25601
|
+
const half = el.offsetWidth / 2;
|
|
25602
|
+
const shift = center - half < 0 ? half - center : center + half > outer ? outer - half - center : 0;
|
|
25603
|
+
el.style.transform = `translateX(calc(-50% + ${shift}px))`;
|
|
25604
|
+
});
|
|
25605
|
+
};
|
|
25606
|
+
layout();
|
|
25607
|
+
const ro = new ResizeObserver(layout);
|
|
25608
|
+
ro.observe(wrap);
|
|
25609
|
+
return () => ro.disconnect();
|
|
25610
|
+
}, [layoutKey, min, max, showValue]);
|
|
25611
|
+
const rowHeight = ROW_HEIGHT[size];
|
|
25612
|
+
const rowGap = (rowHeight - THUMB) / 2;
|
|
25613
|
+
const topSpace = Math.max(
|
|
25614
|
+
0,
|
|
25615
|
+
KNOB_BLEED - rowGap,
|
|
25616
|
+
showValue === "none" ? 0 : BUBBLE_HEIGHT + BUBBLE_GAP + PRESS_GROW - rowGap
|
|
25617
|
+
);
|
|
25618
|
+
const bottomSpace = Math.max(0, KNOB_BLEED + SHADOW_Y - rowGap);
|
|
25619
|
+
const markList = marks === true ? Array.from({ length: Math.floor((max - min) / step) + 1 }, (_, i) => ({
|
|
25620
|
+
value: min + i * step
|
|
25621
|
+
})) : Array.isArray(marks) ? marks.filter((m) => m.value >= min && m.value <= max) : [];
|
|
25622
|
+
const hasMarkLabels = markList.some((m) => m.label);
|
|
25623
|
+
const [rangeStart, rangeEnd] = isRange ? [values[0], values[1]] : [min, values[0]];
|
|
25624
|
+
const interactive = !disabled && !readOnly;
|
|
25625
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25626
|
+
SField,
|
|
25627
|
+
{
|
|
25628
|
+
name,
|
|
25629
|
+
label,
|
|
25630
|
+
controlId: thumbId,
|
|
25631
|
+
labelPosition,
|
|
25632
|
+
subLabel,
|
|
25633
|
+
labelWidth,
|
|
25634
|
+
labelHeight: topSpace > 0 ? rowHeight + topSpace * 2 : void 0,
|
|
25635
|
+
icon,
|
|
25636
|
+
iconColor,
|
|
25637
|
+
labelTooltip,
|
|
25638
|
+
labelTooltipProps,
|
|
25639
|
+
hint,
|
|
25640
|
+
size,
|
|
25641
|
+
error: resolvedError,
|
|
25642
|
+
status: resolvedStatus,
|
|
25643
|
+
errorMessage: resolvedErrorMessage,
|
|
25644
|
+
width,
|
|
25645
|
+
disabled,
|
|
25646
|
+
readOnly,
|
|
25647
|
+
borderless: true,
|
|
25648
|
+
multiline: true,
|
|
25649
|
+
className,
|
|
25650
|
+
style,
|
|
25651
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
25652
|
+
"div",
|
|
25653
|
+
{
|
|
25654
|
+
ref: wrapRef,
|
|
25655
|
+
className: "flex w-full flex-col",
|
|
25656
|
+
style: { padding: `${topSpace}px ${KNOB_BLEED}px ${bottomSpace}px` },
|
|
25657
|
+
children: [
|
|
25658
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
25659
|
+
RSlider__namespace.Root,
|
|
25660
|
+
{
|
|
25661
|
+
ref,
|
|
25662
|
+
value: values,
|
|
25663
|
+
min,
|
|
25664
|
+
max,
|
|
25665
|
+
step,
|
|
25666
|
+
disabled,
|
|
25667
|
+
minStepsBetweenThumbs: 0,
|
|
25668
|
+
onValueChange: (v) => {
|
|
25669
|
+
if (!interactive) return;
|
|
25670
|
+
const next = toOut(v);
|
|
25671
|
+
onValueChange?.(next);
|
|
25672
|
+
if (ruleError !== "") setRuleError(runRules(next, rules));
|
|
25673
|
+
},
|
|
25674
|
+
onValueCommit: (v) => {
|
|
25675
|
+
if (!interactive) return;
|
|
25676
|
+
const next = toOut(v);
|
|
25677
|
+
onValueCommit?.(next);
|
|
25678
|
+
if (rules && rules.length > 0) setRuleError(runRules(next, rules));
|
|
25679
|
+
},
|
|
25680
|
+
onPointerDown: () => interactive && setDragging(true),
|
|
25681
|
+
onPointerUp: () => setDragging(false),
|
|
25682
|
+
onLostPointerCapture: () => setDragging(false),
|
|
25683
|
+
className: cn(
|
|
25684
|
+
"relative flex w-full touch-none items-center select-none",
|
|
25685
|
+
// 읽기 전용은 포인터로 잡히지 않게 한다 — 키보드 포커스는 남겨 값을 읽을 수 있게 한다
|
|
25686
|
+
readOnly && "pointer-events-none"
|
|
25687
|
+
),
|
|
25688
|
+
style: { height: rowHeight },
|
|
25689
|
+
children: [
|
|
25690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25691
|
+
RSlider__namespace.Track,
|
|
25692
|
+
{
|
|
25693
|
+
className: "relative grow overflow-hidden rounded-full",
|
|
25694
|
+
style: { height: TRACK, background: disabled ? COLOR.trackDisabled : COLOR.track },
|
|
25695
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
25696
|
+
RSlider__namespace.Range,
|
|
25697
|
+
{
|
|
25698
|
+
className: "absolute h-full",
|
|
25699
|
+
style: { background: disabled ? COLOR.rangeDisabled : COLOR.range }
|
|
25700
|
+
}
|
|
25701
|
+
)
|
|
25702
|
+
}
|
|
25703
|
+
),
|
|
25704
|
+
markList.map((m) => {
|
|
25705
|
+
const on = m.value >= rangeStart && m.value <= rangeEnd;
|
|
25706
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25707
|
+
"span",
|
|
25708
|
+
{
|
|
25709
|
+
"aria-hidden": true,
|
|
25710
|
+
className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",
|
|
25711
|
+
style: {
|
|
25712
|
+
left: thumbAlignedLeft(toPercent(m.value, min, max)),
|
|
25713
|
+
width: MARK_DOT,
|
|
25714
|
+
height: MARK_DOT,
|
|
25715
|
+
background: on ? COLOR.markOn : disabled ? COLOR.markOffDisabled : COLOR.markOff
|
|
25716
|
+
}
|
|
25717
|
+
},
|
|
25718
|
+
m.value
|
|
25719
|
+
);
|
|
25720
|
+
}),
|
|
25721
|
+
values.map((v, i) => {
|
|
25722
|
+
const pressed = interactive && dragging && focusIndex === i;
|
|
25723
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
25724
|
+
RSlider__namespace.Thumb,
|
|
25725
|
+
{
|
|
25726
|
+
id: i === 0 ? thumbId : void 0,
|
|
25727
|
+
"aria-label": isRange ? `${label ?? ""} ${i === 0 ? "\uCD5C\uC19F\uAC12" : "\uCD5C\uB313\uAC12"}`.trim() : label,
|
|
25728
|
+
"aria-valuetext": formatValue(v),
|
|
25729
|
+
"aria-readonly": readOnly || void 0,
|
|
25730
|
+
onFocus: () => setFocusIndex(i),
|
|
25731
|
+
onBlur: () => setFocusIndex(null),
|
|
25732
|
+
className: cn(
|
|
25733
|
+
"group/thumb relative block rounded-full outline-none",
|
|
25734
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--sys-color-field-border-focus)",
|
|
25735
|
+
interactive ? "cursor-grab active:cursor-grabbing" : disabled && "cursor-not-allowed"
|
|
25736
|
+
),
|
|
25737
|
+
style: { width: THUMB, height: THUMB },
|
|
25738
|
+
children: [
|
|
25739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25740
|
+
"span",
|
|
25741
|
+
{
|
|
25742
|
+
"aria-hidden": true,
|
|
25743
|
+
className: "absolute inset-0 rounded-full border-3 border-solid shadow-[0_2px_4px_rgba(0,0,0,0.16)] transition-transform duration-150 ease-out",
|
|
25744
|
+
style: {
|
|
25745
|
+
background: COLOR.thumbBg,
|
|
25746
|
+
borderColor: disabled ? COLOR.rangeDisabled : COLOR.range,
|
|
25747
|
+
transform: pressed ? `scale(${PRESS_SCALE})` : void 0
|
|
25748
|
+
}
|
|
25749
|
+
}
|
|
25750
|
+
),
|
|
25751
|
+
showValue !== "none" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
25752
|
+
"span",
|
|
25753
|
+
{
|
|
25754
|
+
ref: (el) => {
|
|
25755
|
+
bubbleRefs.current[i] = el;
|
|
25756
|
+
},
|
|
25757
|
+
"aria-hidden": true,
|
|
25758
|
+
className: cn(
|
|
25759
|
+
// 줄 높이로 가운데를 맞추면 줄 상자에 내림 획 자리가 들어 있어 숫자가 위로 1px 가까이 뜬다.
|
|
25760
|
+
// 글자 상자를 대문자 높이~기준선으로 잘라(text-box) 그 상자를 flex 로 가운데 둔다.
|
|
25761
|
+
"typo-body-xs-medium pointer-events-none absolute left-1/2 flex items-center rounded-[6px] px-[6px] whitespace-nowrap transition-opacity",
|
|
25762
|
+
showValue === "always" || pressed ? "opacity-100" : "opacity-0 group-hover/thumb:opacity-100 group-focus-visible/thumb:opacity-100",
|
|
25763
|
+
// 비활성·읽기 전용에서는 조작이 없으므로 drag 말풍선도 띄우지 않는다
|
|
25764
|
+
showValue === "drag" && !interactive && "hidden"
|
|
25765
|
+
),
|
|
25766
|
+
style: {
|
|
25767
|
+
bottom: `calc(100% + ${BUBBLE_GAP + (pressed ? PRESS_GROW : 0)}px)`,
|
|
25768
|
+
height: BUBBLE_HEIGHT,
|
|
25769
|
+
transform: "translateX(-50%)",
|
|
25770
|
+
background: COLOR.bubbleBg,
|
|
25771
|
+
color: COLOR.bubbleText
|
|
25772
|
+
},
|
|
25773
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "[text-box:trim-both_cap_alphabetic]", children: formatValue(v) })
|
|
25774
|
+
}
|
|
25775
|
+
)
|
|
25776
|
+
]
|
|
25777
|
+
},
|
|
25778
|
+
i
|
|
25779
|
+
);
|
|
25780
|
+
})
|
|
25781
|
+
]
|
|
25782
|
+
}
|
|
25783
|
+
),
|
|
25784
|
+
hasMarkLabels && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full", style: { height: BUBBLE_HEIGHT }, children: markList.map((m) => {
|
|
25785
|
+
if (!m.label) return null;
|
|
25786
|
+
const pct = toPercent(m.value, min, max);
|
|
25787
|
+
const align = pct <= 0 ? "translateX(0)" : pct >= 100 ? "translateX(-100%)" : "translateX(-50%)";
|
|
25788
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25789
|
+
"span",
|
|
25790
|
+
{
|
|
25791
|
+
className: "typo-body-xs-medium absolute top-0 whitespace-nowrap",
|
|
25792
|
+
style: {
|
|
25793
|
+
left: pct <= 0 ? 0 : pct >= 100 ? "100%" : thumbAlignedLeft(pct),
|
|
25794
|
+
transform: align,
|
|
25795
|
+
color: disabled ? "var(--sys-color-disabled-text)" : COLOR.markLabel
|
|
25796
|
+
},
|
|
25797
|
+
children: m.label
|
|
25798
|
+
},
|
|
25799
|
+
m.value
|
|
25800
|
+
);
|
|
25801
|
+
}) })
|
|
25802
|
+
]
|
|
25803
|
+
}
|
|
25804
|
+
)
|
|
25805
|
+
}
|
|
25806
|
+
);
|
|
25807
|
+
});
|
|
25414
25808
|
var CHIPFILTER_LISTBOX_WIDTH = 240;
|
|
25415
25809
|
var CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH = 246;
|
|
25416
25810
|
var EDITOR_LISTBOX_MAX_HEIGHT = "min(640px, var(--radix-popover-content-available-height))";
|
|
@@ -27291,6 +27685,24 @@ function EmptyItem({ children }) {
|
|
|
27291
27685
|
}
|
|
27292
27686
|
);
|
|
27293
27687
|
}
|
|
27688
|
+
function splitBySeparators(text, separators) {
|
|
27689
|
+
const seps = separators.filter((s) => s !== "");
|
|
27690
|
+
if (seps.length === 0) return { parts: [], rest: text };
|
|
27691
|
+
const pieces = [];
|
|
27692
|
+
let from = 0;
|
|
27693
|
+
for (let i = 0; i < text.length; ) {
|
|
27694
|
+
const sep = seps.find((s) => text.startsWith(s, i));
|
|
27695
|
+
if (sep) {
|
|
27696
|
+
pieces.push(text.slice(from, i));
|
|
27697
|
+
i += sep.length;
|
|
27698
|
+
from = i;
|
|
27699
|
+
} else {
|
|
27700
|
+
i += 1;
|
|
27701
|
+
}
|
|
27702
|
+
}
|
|
27703
|
+
const parts = pieces.map((p) => p.trim()).filter((p) => p !== "");
|
|
27704
|
+
return { parts, rest: text.slice(from) };
|
|
27705
|
+
}
|
|
27294
27706
|
var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
27295
27707
|
values = [],
|
|
27296
27708
|
onValueChange,
|
|
@@ -27301,7 +27713,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27301
27713
|
disabledChips = [],
|
|
27302
27714
|
size = "sm",
|
|
27303
27715
|
disabled = false,
|
|
27304
|
-
placeholder
|
|
27716
|
+
placeholder: placeholderProp,
|
|
27305
27717
|
name,
|
|
27306
27718
|
rules,
|
|
27307
27719
|
error,
|
|
@@ -27314,6 +27726,9 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27314
27726
|
recommendedItems = [],
|
|
27315
27727
|
loadingRecommendedItems = false,
|
|
27316
27728
|
dropdownMinWidth = 200,
|
|
27729
|
+
commitOnBlur = false,
|
|
27730
|
+
separators,
|
|
27731
|
+
ariaLabel,
|
|
27317
27732
|
label,
|
|
27318
27733
|
labelPosition,
|
|
27319
27734
|
subLabel,
|
|
@@ -27329,7 +27744,9 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27329
27744
|
className,
|
|
27330
27745
|
style
|
|
27331
27746
|
}, ref) {
|
|
27747
|
+
const placeholder = placeholderProp ?? (separators?.includes(",") ? "\uD0DC\uADF8 \uC785\uB825 (Enter\xB7\uCF64\uB9C8\uB85C \uB4F1\uB85D)" : "\uD0DC\uADF8 \uC785\uB825 (Enter\uB85C \uB4F1\uB85D)");
|
|
27332
27748
|
const autoId = react.useId();
|
|
27749
|
+
const controlId = `${autoId}-input`;
|
|
27333
27750
|
const resolvedName = name ?? autoId;
|
|
27334
27751
|
const listboxId = `${autoId}-listbox`;
|
|
27335
27752
|
const activeOptionId = `${autoId}-active-option`;
|
|
@@ -27376,12 +27793,17 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27376
27793
|
const isMax = maxCount != null && values.length >= maxCount;
|
|
27377
27794
|
const resolvedDropdownMinWidth = dropdownMinWidth == null ? void 0 : typeof dropdownMinWidth === "number" ? `${dropdownMinWidth}px` : dropdownMinWidth;
|
|
27378
27795
|
const commit = (next) => onValueChange?.(next);
|
|
27796
|
+
const addChips = (vs, rest = "") => {
|
|
27797
|
+
const room = maxCount == null ? vs.length : Math.max(maxCount - values.length, 0);
|
|
27798
|
+
const added = vs.slice(0, room);
|
|
27799
|
+
if (added.length > 0) commit([...values, ...added]);
|
|
27800
|
+
setInputValue(rest);
|
|
27801
|
+
setActiveIndex(-1);
|
|
27802
|
+
onInput?.(rest);
|
|
27803
|
+
};
|
|
27379
27804
|
const addChip = (v) => {
|
|
27380
27805
|
if (maxCount != null && values.length >= maxCount) return;
|
|
27381
|
-
|
|
27382
|
-
setInputValue("");
|
|
27383
|
-
setActiveIndex(-1);
|
|
27384
|
-
onInput?.("");
|
|
27806
|
+
addChips([v]);
|
|
27385
27807
|
inputRef.current?.focus();
|
|
27386
27808
|
};
|
|
27387
27809
|
const removeChip = (i) => {
|
|
@@ -27466,6 +27888,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27466
27888
|
SField,
|
|
27467
27889
|
{
|
|
27468
27890
|
label,
|
|
27891
|
+
controlId,
|
|
27469
27892
|
labelPosition,
|
|
27470
27893
|
subLabel,
|
|
27471
27894
|
labelWidth,
|
|
@@ -27564,7 +27987,9 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27564
27987
|
"input",
|
|
27565
27988
|
{
|
|
27566
27989
|
ref: inputRef,
|
|
27990
|
+
id: controlId,
|
|
27567
27991
|
name: resolvedName,
|
|
27992
|
+
"aria-label": ariaLabel,
|
|
27568
27993
|
size: 1,
|
|
27569
27994
|
role: "combobox",
|
|
27570
27995
|
"aria-expanded": showDropdown,
|
|
@@ -27588,8 +28013,24 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27588
28013
|
placeholder: values.length === 0 ? placeholder : "",
|
|
27589
28014
|
disabled,
|
|
27590
28015
|
value: inputValue,
|
|
28016
|
+
onPaste: (e) => {
|
|
28017
|
+
if (!separators) return;
|
|
28018
|
+
const pasted = e.clipboardData.getData("text");
|
|
28019
|
+
if (!separators.some((s) => s !== "" && pasted.includes(s))) return;
|
|
28020
|
+
e.preventDefault();
|
|
28021
|
+
const { parts, rest } = splitBySeparators(inputValue + pasted, separators);
|
|
28022
|
+
const tail = rest.trim();
|
|
28023
|
+
addChips(tail === "" ? parts : [...parts, tail]);
|
|
28024
|
+
},
|
|
27591
28025
|
onChange: (e) => {
|
|
27592
28026
|
const nextValue = e.target.value;
|
|
28027
|
+
if (separators && !isComposingRef.current) {
|
|
28028
|
+
const { parts, rest } = splitBySeparators(nextValue, separators);
|
|
28029
|
+
if (parts.length > 0 || rest !== nextValue) {
|
|
28030
|
+
addChips(parts, rest);
|
|
28031
|
+
return;
|
|
28032
|
+
}
|
|
28033
|
+
}
|
|
27593
28034
|
const wasEmpty = inputValue === "";
|
|
27594
28035
|
const isEmpty = nextValue === "";
|
|
27595
28036
|
if (wasEmpty !== isEmpty) {
|
|
@@ -27604,8 +28045,11 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27604
28045
|
onCompositionStart: () => {
|
|
27605
28046
|
isComposingRef.current = true;
|
|
27606
28047
|
},
|
|
27607
|
-
onCompositionEnd: () => {
|
|
28048
|
+
onCompositionEnd: (e) => {
|
|
27608
28049
|
isComposingRef.current = false;
|
|
28050
|
+
if (!separators) return;
|
|
28051
|
+
const { parts, rest } = splitBySeparators(e.currentTarget.value, separators);
|
|
28052
|
+
if (parts.length > 0 || rest !== e.currentTarget.value) addChips(parts, rest);
|
|
27609
28053
|
},
|
|
27610
28054
|
onFocus: () => {
|
|
27611
28055
|
setFocused(true);
|
|
@@ -27615,6 +28059,8 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
|
|
|
27615
28059
|
onBlur: () => {
|
|
27616
28060
|
setFocused(false);
|
|
27617
28061
|
setActiveIndex(-1);
|
|
28062
|
+
if (commitOnBlur && inputValue.trim() !== "" && !isMax)
|
|
28063
|
+
addChips([inputValue.trim()]);
|
|
27618
28064
|
onBlur?.();
|
|
27619
28065
|
}
|
|
27620
28066
|
}
|
|
@@ -27808,6 +28254,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
27808
28254
|
}, ref) {
|
|
27809
28255
|
const f = FONT3[size];
|
|
27810
28256
|
const [ruleError, setRuleError] = react.useState("");
|
|
28257
|
+
const controlId = useFieldControlId();
|
|
27811
28258
|
const hasValue = value !== void 0 && value !== null && String(value) !== "";
|
|
27812
28259
|
useFormField({
|
|
27813
28260
|
name,
|
|
@@ -27828,6 +28275,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
27828
28275
|
SField,
|
|
27829
28276
|
{
|
|
27830
28277
|
label,
|
|
28278
|
+
controlId,
|
|
27831
28279
|
labelPosition,
|
|
27832
28280
|
subLabel,
|
|
27833
28281
|
labelWidth,
|
|
@@ -27853,16 +28301,21 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
27853
28301
|
...style
|
|
27854
28302
|
},
|
|
27855
28303
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27856
|
-
"
|
|
28304
|
+
"div",
|
|
27857
28305
|
{
|
|
28306
|
+
role: "presentation",
|
|
27858
28307
|
className: "flex h-full w-full items-center",
|
|
27859
28308
|
style: { gap: f.gap, padding: `0 ${f.paddingX}` },
|
|
28309
|
+
onClick: (e) => {
|
|
28310
|
+
if (e.target === e.currentTarget) e.currentTarget.querySelector("input")?.focus();
|
|
28311
|
+
},
|
|
27860
28312
|
children: [
|
|
27861
28313
|
prefix,
|
|
27862
28314
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27863
28315
|
"input",
|
|
27864
28316
|
{
|
|
27865
28317
|
ref: mergeRefs(ref, valueTooltip.valueRef),
|
|
28318
|
+
id: controlId,
|
|
27866
28319
|
name,
|
|
27867
28320
|
type: "text",
|
|
27868
28321
|
value: value ?? "",
|
|
@@ -27900,7 +28353,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
|
|
|
27900
28353
|
{
|
|
27901
28354
|
icon: "close",
|
|
27902
28355
|
size: "xxs",
|
|
27903
|
-
ariaLabel: "
|
|
28356
|
+
ariaLabel: "\uC9C0\uC6B0\uAE30",
|
|
27904
28357
|
onClick: () => {
|
|
27905
28358
|
onValueChange?.("");
|
|
27906
28359
|
setRuleError(runRules("", rules));
|
|
@@ -28217,6 +28670,8 @@ function STimePicker({
|
|
|
28217
28670
|
const portalContainer = usePortalContainer();
|
|
28218
28671
|
const triggerRef = react.useRef(null);
|
|
28219
28672
|
const [open, setOpen] = react.useState(false);
|
|
28673
|
+
const triggerId = useFieldControlId();
|
|
28674
|
+
const triggerTextId = `${triggerId}-text`;
|
|
28220
28675
|
const [popoverAlignOffset, setPopoverAlignOffset] = react.useState(0);
|
|
28221
28676
|
const [focused, setFocused] = react.useState(false);
|
|
28222
28677
|
const [ruleError, setRuleError] = react.useState("");
|
|
@@ -28254,6 +28709,7 @@ function STimePicker({
|
|
|
28254
28709
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28255
28710
|
SField,
|
|
28256
28711
|
{
|
|
28712
|
+
controlId: triggerId,
|
|
28257
28713
|
label,
|
|
28258
28714
|
labelPosition,
|
|
28259
28715
|
subLabel,
|
|
@@ -28281,8 +28737,10 @@ function STimePicker({
|
|
|
28281
28737
|
"div",
|
|
28282
28738
|
{
|
|
28283
28739
|
ref: triggerRef,
|
|
28740
|
+
id: triggerId,
|
|
28284
28741
|
role: "button",
|
|
28285
28742
|
"aria-disabled": disabled,
|
|
28743
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerTextId}` : void 0,
|
|
28286
28744
|
tabIndex: disabled ? -1 : 0,
|
|
28287
28745
|
"data-name": name,
|
|
28288
28746
|
onFocus: () => setFocused(true),
|
|
@@ -28312,6 +28770,7 @@ function STimePicker({
|
|
|
28312
28770
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28313
28771
|
"span",
|
|
28314
28772
|
{
|
|
28773
|
+
id: triggerTextId,
|
|
28315
28774
|
className: "flex-1 truncate text-center",
|
|
28316
28775
|
style: {
|
|
28317
28776
|
minWidth: dims.minWidth,
|
|
@@ -28687,6 +29146,8 @@ function STimeRangePicker({
|
|
|
28687
29146
|
const portalContainer = usePortalContainer();
|
|
28688
29147
|
const triggerRef = react.useRef(null);
|
|
28689
29148
|
const [open, setOpen] = react.useState(false);
|
|
29149
|
+
const triggerId = useFieldControlId();
|
|
29150
|
+
const triggerTextId = `${triggerId}-text`;
|
|
28690
29151
|
const [popoverAlignOffset, setPopoverAlignOffset] = react.useState(0);
|
|
28691
29152
|
const [focused, setFocused] = react.useState(false);
|
|
28692
29153
|
const [ruleError, setRuleError] = react.useState("");
|
|
@@ -28726,6 +29187,7 @@ function STimeRangePicker({
|
|
|
28726
29187
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28727
29188
|
SField,
|
|
28728
29189
|
{
|
|
29190
|
+
controlId: triggerId,
|
|
28729
29191
|
label,
|
|
28730
29192
|
labelPosition,
|
|
28731
29193
|
subLabel,
|
|
@@ -28753,8 +29215,10 @@ function STimeRangePicker({
|
|
|
28753
29215
|
"div",
|
|
28754
29216
|
{
|
|
28755
29217
|
ref: triggerRef,
|
|
29218
|
+
id: triggerId,
|
|
28756
29219
|
role: "button",
|
|
28757
29220
|
"aria-disabled": disabled,
|
|
29221
|
+
"aria-labelledby": label ? `${fieldLabelId(triggerId)} ${triggerTextId}` : void 0,
|
|
28758
29222
|
tabIndex: disabled ? -1 : 0,
|
|
28759
29223
|
"data-name": name,
|
|
28760
29224
|
onFocus: () => setFocused(true),
|
|
@@ -28784,6 +29248,7 @@ function STimeRangePicker({
|
|
|
28784
29248
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28785
29249
|
"span",
|
|
28786
29250
|
{
|
|
29251
|
+
id: triggerTextId,
|
|
28787
29252
|
className: "flex-1 truncate text-center",
|
|
28788
29253
|
style: {
|
|
28789
29254
|
minWidth: dims.minWidth,
|
|
@@ -28990,6 +29455,7 @@ exports.SSearchInput = SSearchInput;
|
|
|
28990
29455
|
exports.SSectionHeaderCard = SSectionHeaderCard2;
|
|
28991
29456
|
exports.SSelect = SSelect2;
|
|
28992
29457
|
exports.SSkeleton = SSkeleton;
|
|
29458
|
+
exports.SSlider = SSlider;
|
|
28993
29459
|
exports.SSplitter = SSplitter2;
|
|
28994
29460
|
exports.SStepper = SStepper;
|
|
28995
29461
|
exports.SSwitch = SSwitch;
|
|
@@ -29023,6 +29489,7 @@ exports.TIMEPICKER_SIZES = TIMEPICKER_SIZES;
|
|
|
29023
29489
|
exports.TIMEPICKER_SIZE_CONFIG = TIMEPICKER_SIZE_CONFIG;
|
|
29024
29490
|
exports.buttonPreset = buttonPreset;
|
|
29025
29491
|
exports.cn = cn;
|
|
29492
|
+
exports.fieldLabelId = fieldLabelId;
|
|
29026
29493
|
exports.fieldWidthValue = fieldWidthValue;
|
|
29027
29494
|
exports.fileExtension = fileExtension;
|
|
29028
29495
|
exports.findGnbAncestors = findGnbAncestors;
|