sellmate-design-system-react 9.0.0-beta.90 → 9.0.0-beta.91
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 +33 -13
- package/dist/components/SChatInput/README.md +8 -2
- package/dist/components/SChatInput/SChatInput.d.ts +54 -4
- package/dist/components/SDatePicker/README.md +1 -0
- package/dist/components/SDatePicker/SDatePicker.d.ts +9 -1
- package/dist/components/SDateRangePicker/README.md +1 -0
- package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +9 -1
- package/dist/components/SExpansionItem/README.md +1 -0
- package/dist/components/SExpansionItem/SExpansionItem.d.ts +10 -0
- package/dist/components/SGhostButton/README.md +3 -1
- package/dist/components/SGhostButton/SGhostButton.d.ts +18 -3
- package/dist/index.cjs +429 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +429 -167
- package/dist/index.js.map +1 -1
- package/dist/lib/date.d.ts +9 -0
- package/dist/llms-full.txt +47 -16
- package/dist/llms.txt +33 -13
- package/dist/styles.css +3 -6
- package/dist/theme.css +0 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4515,6 +4515,8 @@ var SGhostButton = /* @__PURE__ */ react.forwardRef(function SGhostButton2({
|
|
|
4515
4515
|
ariaExpanded,
|
|
4516
4516
|
tooltipText,
|
|
4517
4517
|
disabled = false,
|
|
4518
|
+
href,
|
|
4519
|
+
target,
|
|
4518
4520
|
onClick,
|
|
4519
4521
|
anchorClassName,
|
|
4520
4522
|
anchorStyle,
|
|
@@ -4538,51 +4540,74 @@ var SGhostButton = /* @__PURE__ */ react.forwardRef(function SGhostButton2({
|
|
|
4538
4540
|
cancelHide();
|
|
4539
4541
|
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
4540
4542
|
};
|
|
4541
|
-
const s = SIZE[size];
|
|
4542
|
-
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
4543
4543
|
const text = (tooltipText ?? "").trim();
|
|
4544
4544
|
const hasTooltip = text !== "";
|
|
4545
|
-
const
|
|
4545
|
+
const [prevHasTooltip, setPrevHasTooltip] = react.useState(hasTooltip);
|
|
4546
|
+
if (prevHasTooltip !== hasTooltip) {
|
|
4547
|
+
setPrevHasTooltip(hasTooltip);
|
|
4548
|
+
if (!hasTooltip) setOpen(false);
|
|
4549
|
+
}
|
|
4550
|
+
const s = SIZE[size];
|
|
4551
|
+
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
4552
|
+
const shared = {
|
|
4553
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
4554
|
+
"aria-label": ariaLabel.trim() || void 0,
|
|
4555
|
+
"tabIndex": disabled ? -1 : void 0,
|
|
4556
|
+
"onClick": (e) => {
|
|
4557
|
+
if (disabled) {
|
|
4558
|
+
e.preventDefault();
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
onClick?.(e);
|
|
4562
|
+
},
|
|
4563
|
+
"className": cn(
|
|
4564
|
+
"group/ghost-button relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
4565
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
4566
|
+
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
4567
|
+
className
|
|
4568
|
+
),
|
|
4569
|
+
"style": {
|
|
4570
|
+
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
4571
|
+
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
4572
|
+
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
4573
|
+
...style
|
|
4574
|
+
}
|
|
4575
|
+
};
|
|
4576
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4577
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4578
|
+
"span",
|
|
4579
|
+
{
|
|
4580
|
+
"aria-hidden": true,
|
|
4581
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
|
|
4582
|
+
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
4583
|
+
}
|
|
4584
|
+
),
|
|
4585
|
+
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
4586
|
+
] });
|
|
4587
|
+
const btn2 = href != null ? (
|
|
4588
|
+
// 비활성 링크는 주소를 뗀다 — `<a>` 에는 disabled 가 없어서 주소가 남으면 가운데 클릭으로 열린다.
|
|
4589
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4590
|
+
"a",
|
|
4591
|
+
{
|
|
4592
|
+
ref,
|
|
4593
|
+
href: disabled ? void 0 : href,
|
|
4594
|
+
target,
|
|
4595
|
+
rel: target === "_blank" ? "noopener noreferrer" : void 0,
|
|
4596
|
+
role: disabled ? "link" : void 0,
|
|
4597
|
+
...shared,
|
|
4598
|
+
children: content
|
|
4599
|
+
}
|
|
4600
|
+
)
|
|
4601
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4546
4602
|
"button",
|
|
4547
4603
|
{
|
|
4548
4604
|
ref,
|
|
4549
4605
|
type: "button",
|
|
4550
4606
|
disabled,
|
|
4551
|
-
"aria-disabled": disabled ? "true" : void 0,
|
|
4552
|
-
"aria-label": ariaLabel.trim() || void 0,
|
|
4553
4607
|
"aria-pressed": ariaPressed,
|
|
4554
4608
|
"aria-expanded": ariaExpanded,
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
if (disabled) {
|
|
4558
|
-
e.preventDefault();
|
|
4559
|
-
return;
|
|
4560
|
-
}
|
|
4561
|
-
onClick?.(e);
|
|
4562
|
-
},
|
|
4563
|
-
className: cn(
|
|
4564
|
-
"group/ghost-button relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
4565
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
4566
|
-
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
4567
|
-
className
|
|
4568
|
-
),
|
|
4569
|
-
style: {
|
|
4570
|
-
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
4571
|
-
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
4572
|
-
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
4573
|
-
...style
|
|
4574
|
-
},
|
|
4575
|
-
children: [
|
|
4576
|
-
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4577
|
-
"span",
|
|
4578
|
-
{
|
|
4579
|
-
"aria-hidden": true,
|
|
4580
|
-
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
|
|
4581
|
-
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
4582
|
-
}
|
|
4583
|
-
),
|
|
4584
|
-
/* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
4585
|
-
]
|
|
4609
|
+
...shared,
|
|
4610
|
+
children: content
|
|
4586
4611
|
}
|
|
4587
4612
|
);
|
|
4588
4613
|
if (!hasTooltip) return btn2;
|
|
@@ -5310,6 +5335,9 @@ var FIELD_BORDER = 1;
|
|
|
5310
5335
|
var TEXTAREA_MIN_HEIGHT = `calc(var(--cmp-chatInput-buttonFrame-height) - ${FIELD_BORDER * 2}px)`;
|
|
5311
5336
|
var BUTTON_BOTTOM_INSET = `calc((var(--cmp-chatInput-buttonFrame-height) - var(--cmp-ghostButton-md-size)) / 2)`;
|
|
5312
5337
|
var DEFAULT_MAX_ROWS = 5;
|
|
5338
|
+
function BarButton(props) {
|
|
5339
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { ...props, size: "md", style: { marginBottom: BUTTON_BOTTOM_INSET } });
|
|
5340
|
+
}
|
|
5313
5341
|
var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
5314
5342
|
value = "",
|
|
5315
5343
|
onValueChange,
|
|
@@ -5317,7 +5345,13 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5317
5345
|
disabled = false,
|
|
5318
5346
|
onSend,
|
|
5319
5347
|
hasAttachments = false,
|
|
5348
|
+
onAttachFiles,
|
|
5349
|
+
attachAccept,
|
|
5350
|
+
attachMultiple = true,
|
|
5320
5351
|
onAttach,
|
|
5352
|
+
attachDisabled = false,
|
|
5353
|
+
attachTooltip,
|
|
5354
|
+
sendDisabled = false,
|
|
5321
5355
|
onPasteFiles,
|
|
5322
5356
|
busy = false,
|
|
5323
5357
|
onStop,
|
|
@@ -5329,11 +5363,23 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5329
5363
|
...rest
|
|
5330
5364
|
}, ref) {
|
|
5331
5365
|
const hasText = value.trim() !== "";
|
|
5332
|
-
const canSend = !disabled && !busy && (hasText || hasAttachments);
|
|
5333
|
-
const send =
|
|
5366
|
+
const canSend = !disabled && !busy && !sendDisabled && (hasText || hasAttachments);
|
|
5367
|
+
const send = () => {
|
|
5334
5368
|
if (!canSend) return;
|
|
5335
5369
|
onSend?.(hasText ? value : "");
|
|
5336
|
-
}
|
|
5370
|
+
};
|
|
5371
|
+
const fileInputRef = react.useRef(null);
|
|
5372
|
+
const hasAttachButton = onAttachFiles != null || onAttach != null;
|
|
5373
|
+
const attachLocked = disabled || attachDisabled;
|
|
5374
|
+
const handleAttachClick = () => {
|
|
5375
|
+
if (onAttachFiles != null) fileInputRef.current?.click();
|
|
5376
|
+
else onAttach?.();
|
|
5377
|
+
};
|
|
5378
|
+
const handleFilesPicked = (e) => {
|
|
5379
|
+
const files = Array.from(e.target.files ?? []);
|
|
5380
|
+
e.target.value = "";
|
|
5381
|
+
if (files.length > 0) onAttachFiles?.(files);
|
|
5382
|
+
};
|
|
5337
5383
|
const handleKeyDown = (e) => {
|
|
5338
5384
|
rest.onKeyDown?.(e);
|
|
5339
5385
|
if (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing) return;
|
|
@@ -5346,19 +5392,31 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5346
5392
|
const files = Array.from(e.clipboardData.files);
|
|
5347
5393
|
if (files.length === 0) return;
|
|
5348
5394
|
e.preventDefault();
|
|
5395
|
+
if (attachDisabled) return;
|
|
5349
5396
|
onPasteFiles(files);
|
|
5350
5397
|
};
|
|
5351
5398
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col bg-(--cmp-chatInput-bg)", className), style, children: [
|
|
5352
5399
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-(--cmp-chatInput-gap) p-(--cmp-chatInput-padding)", children: [
|
|
5353
|
-
|
|
5354
|
-
|
|
5400
|
+
hasAttachButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5401
|
+
BarButton,
|
|
5355
5402
|
{
|
|
5356
5403
|
icon: "attachFile",
|
|
5357
|
-
size: "md",
|
|
5358
5404
|
ariaLabel: "\uD30C\uC77C \uCCA8\uBD80",
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5405
|
+
tooltipText: attachTooltip,
|
|
5406
|
+
disabled: attachLocked,
|
|
5407
|
+
onClick: handleAttachClick
|
|
5408
|
+
}
|
|
5409
|
+
),
|
|
5410
|
+
onAttachFiles != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5411
|
+
"input",
|
|
5412
|
+
{
|
|
5413
|
+
ref: fileInputRef,
|
|
5414
|
+
type: "file",
|
|
5415
|
+
className: "hidden",
|
|
5416
|
+
accept: attachAccept,
|
|
5417
|
+
multiple: attachMultiple,
|
|
5418
|
+
disabled: attachLocked,
|
|
5419
|
+
onChange: handleFilesPicked
|
|
5362
5420
|
}
|
|
5363
5421
|
),
|
|
5364
5422
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5382,26 +5440,26 @@ var SChatInputImpl = /* @__PURE__ */ react.forwardRef(function SChatInput({
|
|
|
5382
5440
|
onPaste: handlePaste
|
|
5383
5441
|
}
|
|
5384
5442
|
),
|
|
5385
|
-
busy ?
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5443
|
+
busy ? (
|
|
5444
|
+
// disabled 는 모두 잠근다 — 응답 도중 대화가 끝나면 정지도 할 수 없다
|
|
5445
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5446
|
+
BarButton,
|
|
5447
|
+
{
|
|
5448
|
+
icon: "stop",
|
|
5449
|
+
intent: "danger",
|
|
5450
|
+
ariaLabel: "\uC751\uB2F5 \uC911\uC9C0",
|
|
5451
|
+
disabled,
|
|
5452
|
+
onClick: onStop
|
|
5453
|
+
}
|
|
5454
|
+
)
|
|
5395
5455
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5396
|
-
|
|
5456
|
+
BarButton,
|
|
5397
5457
|
{
|
|
5398
5458
|
icon: "send",
|
|
5399
|
-
size: "md",
|
|
5400
5459
|
intent: "subAction",
|
|
5401
5460
|
ariaLabel: "\uC804\uC1A1",
|
|
5402
5461
|
disabled: !canSend,
|
|
5403
|
-
onClick: send
|
|
5404
|
-
style: { marginBottom: BUTTON_BOTTOM_INSET }
|
|
5462
|
+
onClick: send
|
|
5405
5463
|
}
|
|
5406
5464
|
)
|
|
5407
5465
|
] }),
|
|
@@ -6642,6 +6700,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
|
|
|
6642
6700
|
depth = 1,
|
|
6643
6701
|
leading,
|
|
6644
6702
|
trailing,
|
|
6703
|
+
headerAction,
|
|
6645
6704
|
bodyPadding = true,
|
|
6646
6705
|
bordered = false,
|
|
6647
6706
|
expanded,
|
|
@@ -6681,12 +6740,92 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
|
|
|
6681
6740
|
);
|
|
6682
6741
|
const leadingNode = typeof leading === "function" ? leading({ expanded: isExpanded, selected: isSelected, disabled }) : leading;
|
|
6683
6742
|
const hasSupportingText = supportingText != null && supportingText !== "";
|
|
6743
|
+
const hasHeaderAction = headerAction != null && headerAction !== false;
|
|
6684
6744
|
const id = react.useId();
|
|
6745
|
+
const surfaceClass = cn(
|
|
6746
|
+
isExpanded && "border-b border-(--cmp-listExpansionItem-title-border)",
|
|
6747
|
+
hasChevronInteraction ? "hover:bg-(--sys-color-bg-neutralBright)" : !isExpanded && "hover:bg-(--cmp-listExpansionItem-title-bg-hover)",
|
|
6748
|
+
// 펼침 배경(파랑)은 bordered 일 때만. 카드처럼 테두리로 경계가 잡힌
|
|
6749
|
+
// 아이템에서만 배경이 선택 상태를 나타낸다.
|
|
6750
|
+
// 테두리 없는 리스트에서는 accentStripe 가 그 역할을 하므로,
|
|
6751
|
+
// 배경까지 깔면 항목 경계가 없는 목록에서 선택 표시가 두 겹이 된다.
|
|
6752
|
+
isExpanded && isSelected && bordered && "bg-(--cmp-listExpansionItem-title-bg-expanded)"
|
|
6753
|
+
);
|
|
6754
|
+
const hoverHandlers = {
|
|
6755
|
+
onMouseEnter: () => setHovered(true),
|
|
6756
|
+
onMouseLeave: () => setHovered(false)
|
|
6757
|
+
};
|
|
6685
6758
|
react.useEffect(() => {
|
|
6686
6759
|
if (!isExpanded) return;
|
|
6687
6760
|
parentDescendantContext?.reportExpandedDescendant(1);
|
|
6688
6761
|
return () => parentDescendantContext?.reportExpandedDescendant(-1);
|
|
6689
6762
|
}, [isExpanded, parentDescendantContext]);
|
|
6763
|
+
const toggleButton = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6764
|
+
"button",
|
|
6765
|
+
{
|
|
6766
|
+
type: "button",
|
|
6767
|
+
disabled,
|
|
6768
|
+
"aria-expanded": isExpanded,
|
|
6769
|
+
"aria-controls": id,
|
|
6770
|
+
...hasHeaderAction ? {} : hoverHandlers,
|
|
6771
|
+
onClick: (event) => {
|
|
6772
|
+
if (disabled) return;
|
|
6773
|
+
const next = !isExpanded;
|
|
6774
|
+
if (expanded === void 0) setInternalExpanded(next);
|
|
6775
|
+
onToggle?.(next, event);
|
|
6776
|
+
},
|
|
6777
|
+
className: cn(
|
|
6778
|
+
"group/expansion-item-button flex w-full cursor-pointer items-center justify-between border-0 text-left text-(--cmp-listExpansionItem-title-text-default) focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent) disabled:cursor-not-allowed disabled:text-(--sys-color-disabled-text)",
|
|
6779
|
+
titleTypo,
|
|
6780
|
+
// 헤더 액션이 있으면 면은 바깥 줄이 그린다 — 버튼은 남은 폭만 차지한다
|
|
6781
|
+
hasHeaderAction ? "min-w-0 flex-1" : surfaceClass,
|
|
6782
|
+
// 높이는 세로 패딩과 내용이 정한다 — 제목 줄에 높이를 못 박지 않는다 (SListItem 과 동일)
|
|
6783
|
+
dense ? "py-(--cmp-listExpansionItem-title-paddingY-dense)" : "py-(--cmp-listExpansionItem-title-paddingY-normal)",
|
|
6784
|
+
"gap-(--cmp-listExpansionItem-title-gap)",
|
|
6785
|
+
// 헤더 액션이 있으면 오른쪽 끝 여백은 액션 칸이 갖고, 버튼은 액션과의 간격만 남긴다
|
|
6786
|
+
hasHeaderAction ? "pr-(--cmp-listExpansionItem-title-gap)" : "pr-(--cmp-listExpansionItem-title-paddingX)",
|
|
6787
|
+
depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
|
|
6788
|
+
isExpanded && "text-(--cmp-listExpansionItem-title-text-expanded)"
|
|
6789
|
+
),
|
|
6790
|
+
children: [
|
|
6791
|
+
!leading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6792
|
+
"span",
|
|
6793
|
+
{
|
|
6794
|
+
className: cn(
|
|
6795
|
+
"flex transition-transform duration-200 ease-out motion-reduce:transition-none",
|
|
6796
|
+
isExpanded && "rotate-180"
|
|
6797
|
+
),
|
|
6798
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12, color: "var(--sys-color-fg-quaternary)" })
|
|
6799
|
+
}
|
|
6800
|
+
),
|
|
6801
|
+
leadingNode,
|
|
6802
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6803
|
+
"span",
|
|
6804
|
+
{
|
|
6805
|
+
className: cn(
|
|
6806
|
+
"min-w-0 flex-1",
|
|
6807
|
+
supportingTextPosition === "bottom" ? "flex flex-col" : "flex items-center gap-[8px] whitespace-nowrap"
|
|
6808
|
+
),
|
|
6809
|
+
children: [
|
|
6810
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title }),
|
|
6811
|
+
hasSupportingText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6812
|
+
"span",
|
|
6813
|
+
{
|
|
6814
|
+
className: cn(
|
|
6815
|
+
"typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
|
|
6816
|
+
supportingTextPosition === "right" && "flex-1"
|
|
6817
|
+
),
|
|
6818
|
+
children: supportingText
|
|
6819
|
+
}
|
|
6820
|
+
)
|
|
6821
|
+
]
|
|
6822
|
+
}
|
|
6823
|
+
),
|
|
6824
|
+
trailing,
|
|
6825
|
+
showInteractionChevron && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "chevronRight", size: 12, color: interactionChevronColor })
|
|
6826
|
+
]
|
|
6827
|
+
}
|
|
6828
|
+
);
|
|
6690
6829
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6691
6830
|
"div",
|
|
6692
6831
|
{
|
|
@@ -6709,79 +6848,13 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
|
|
|
6709
6848
|
className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 z-[1] w-(--cmp-listItem-accentStripe-width) bg-(--cmp-listItem-accentStripe-color)"
|
|
6710
6849
|
}
|
|
6711
6850
|
),
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
{
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
onMouseEnter: () => setHovered(true),
|
|
6720
|
-
onMouseLeave: () => setHovered(false),
|
|
6721
|
-
onClick: (event) => {
|
|
6722
|
-
if (disabled) return;
|
|
6723
|
-
const next = !isExpanded;
|
|
6724
|
-
if (expanded === void 0) setInternalExpanded(next);
|
|
6725
|
-
onToggle?.(next, event);
|
|
6726
|
-
},
|
|
6727
|
-
className: cn(
|
|
6728
|
-
"group/expansion-item-button flex w-full cursor-pointer items-center justify-between border-0 text-left text-(--cmp-listExpansionItem-title-text-default) focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent) disabled:cursor-not-allowed disabled:text-(--sys-color-disabled-text)",
|
|
6729
|
-
titleTypo,
|
|
6730
|
-
isExpanded && "border-b border-(--cmp-listExpansionItem-title-border)",
|
|
6731
|
-
hasChevronInteraction ? "hover:bg-(--sys-color-bg-neutralBright)" : !isExpanded && "hover:bg-(--cmp-listExpansionItem-title-bg-hover)",
|
|
6732
|
-
// 높이는 세로 패딩과 내용이 정한다 — 제목 줄에 높이를 못 박지 않는다 (SListItem 과 동일)
|
|
6733
|
-
dense ? "py-(--cmp-listExpansionItem-title-paddingY-dense)" : "py-(--cmp-listExpansionItem-title-paddingY-normal)",
|
|
6734
|
-
"gap-(--cmp-listExpansionItem-title-gap)",
|
|
6735
|
-
"pr-(--cmp-listExpansionItem-title-paddingX)",
|
|
6736
|
-
depth === 2 ? "pl-[36px]" : depth === 3 ? "pl-[56px]" : "pl-[16px]",
|
|
6737
|
-
isExpanded && cn(
|
|
6738
|
-
"text-(--cmp-listExpansionItem-title-text-expanded)",
|
|
6739
|
-
// 펼침 배경(파랑)은 bordered 일 때만. 카드처럼 테두리로 경계가 잡힌
|
|
6740
|
-
// 아이템에서만 배경이 선택 상태를 나타낸다.
|
|
6741
|
-
// 테두리 없는 리스트에서는 accentStripe 가 그 역할을 하므로,
|
|
6742
|
-
// 배경까지 깔면 항목 경계가 없는 목록에서 선택 표시가 두 겹이 된다.
|
|
6743
|
-
isSelected && bordered && "bg-(--cmp-listExpansionItem-title-bg-expanded)"
|
|
6744
|
-
)
|
|
6745
|
-
),
|
|
6746
|
-
children: [
|
|
6747
|
-
!leading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6748
|
-
"span",
|
|
6749
|
-
{
|
|
6750
|
-
className: cn(
|
|
6751
|
-
"flex transition-transform duration-200 ease-out motion-reduce:transition-none",
|
|
6752
|
-
isExpanded && "rotate-180"
|
|
6753
|
-
),
|
|
6754
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12, color: "var(--sys-color-fg-quaternary)" })
|
|
6755
|
-
}
|
|
6756
|
-
),
|
|
6757
|
-
leadingNode,
|
|
6758
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6759
|
-
"span",
|
|
6760
|
-
{
|
|
6761
|
-
className: cn(
|
|
6762
|
-
"min-w-0 flex-1",
|
|
6763
|
-
supportingTextPosition === "bottom" ? "flex flex-col" : "flex items-center gap-[8px] whitespace-nowrap"
|
|
6764
|
-
),
|
|
6765
|
-
children: [
|
|
6766
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title }),
|
|
6767
|
-
hasSupportingText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6768
|
-
"span",
|
|
6769
|
-
{
|
|
6770
|
-
className: cn(
|
|
6771
|
-
"typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
|
|
6772
|
-
supportingTextPosition === "right" && "flex-1"
|
|
6773
|
-
),
|
|
6774
|
-
children: supportingText
|
|
6775
|
-
}
|
|
6776
|
-
)
|
|
6777
|
-
]
|
|
6778
|
-
}
|
|
6779
|
-
),
|
|
6780
|
-
trailing,
|
|
6781
|
-
showInteractionChevron && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "chevronRight", size: 12, color: interactionChevronColor })
|
|
6782
|
-
]
|
|
6783
|
-
}
|
|
6784
|
-
),
|
|
6851
|
+
hasHeaderAction ? (
|
|
6852
|
+
// 헤더 액션은 여닫는 버튼의 형제다 — 안에 넣으면 버튼이 중첩되고 누를 때마다 여닫힌다
|
|
6853
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center", surfaceClass), ...hoverHandlers, children: [
|
|
6854
|
+
toggleButton,
|
|
6855
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-(--cmp-listExpansionItem-title-gap) pr-(--cmp-listExpansionItem-title-paddingX)", children: headerAction })
|
|
6856
|
+
] })
|
|
6857
|
+
) : toggleButton,
|
|
6785
6858
|
/* @__PURE__ */ jsxRuntime.jsx(SExpansionItemDescendantContext.Provider, { value: descendantContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6786
6859
|
"div",
|
|
6787
6860
|
{
|
|
@@ -14673,12 +14746,25 @@ function monthCells(year, month) {
|
|
|
14673
14746
|
return cells;
|
|
14674
14747
|
}
|
|
14675
14748
|
var WEEK_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
|
|
14749
|
+
var WEEKDAY_SUFFIX_EM = 0.25 + 3 * 1;
|
|
14750
|
+
var weekdaySuffixWidth = (fontSize) => Math.ceil(fontSize * WEEKDAY_SUFFIX_EM);
|
|
14751
|
+
function withWeekday(value) {
|
|
14752
|
+
const [date = "", ...rest] = value.split(" ");
|
|
14753
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
|
|
14754
|
+
if (!match) return value;
|
|
14755
|
+
const day = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])).getDay();
|
|
14756
|
+
if (Number.isNaN(day)) return value;
|
|
14757
|
+
return [date, `${WEEK_LABELS[day]}\uC694\uC77C`, ...rest].join(" ");
|
|
14758
|
+
}
|
|
14676
14759
|
|
|
14677
14760
|
// src/components/SCalendarBoard/calendar-board-layout.ts
|
|
14678
14761
|
function eventEndDate(event) {
|
|
14679
14762
|
const end = event.endDate;
|
|
14680
14763
|
return end != null && end > event.date ? end : event.date;
|
|
14681
14764
|
}
|
|
14765
|
+
function compareDate(a, b) {
|
|
14766
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
14767
|
+
}
|
|
14682
14768
|
function layoutCalendarBoard({
|
|
14683
14769
|
cells,
|
|
14684
14770
|
events,
|
|
@@ -14724,7 +14810,7 @@ function layoutCalendarBoard({
|
|
|
14724
14810
|
flush(to);
|
|
14725
14811
|
});
|
|
14726
14812
|
runs.sort(
|
|
14727
|
-
(a, b) => a.startIndex - b.startIndex ||
|
|
14813
|
+
(a, b) => a.startIndex - b.startIndex || compareDate(a.event.date, b.event.date) || compareDate(eventEndDate(b.event), eventEndDate(a.event)) || a.order - b.order
|
|
14728
14814
|
);
|
|
14729
14815
|
const weekLanes = Array.from({ length: weekCount }, () => []);
|
|
14730
14816
|
for (const run of runs) {
|
|
@@ -17997,7 +18083,8 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ title, to
|
|
|
17997
18083
|
);
|
|
17998
18084
|
});
|
|
17999
18085
|
var NO_KEYS = /* @__PURE__ */ new Set();
|
|
18000
|
-
var
|
|
18086
|
+
var EXPAND_MOTION = { duration: 220, easing: "ease-out" };
|
|
18087
|
+
var COLLAPSE_MOTION = { duration: 140, easing: "ease-in" };
|
|
18001
18088
|
function STreeTable({
|
|
18002
18089
|
rows = [],
|
|
18003
18090
|
columns = [],
|
|
@@ -18044,32 +18131,88 @@ function STreeTable({
|
|
|
18044
18131
|
if (expandedKeys === void 0) setInnerExpandedKeys(next);
|
|
18045
18132
|
onExpandedChange?.(next, row);
|
|
18046
18133
|
};
|
|
18047
|
-
const visibleRows = react.useMemo(
|
|
18048
|
-
|
|
18049
|
-
|
|
18050
|
-
|
|
18051
|
-
|
|
18052
|
-
|
|
18053
|
-
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18134
|
+
const visibleRows = react.useMemo(
|
|
18135
|
+
() => flattenRows(rows, (row) => expandedSet.has(keyOf(row)), childrenOf),
|
|
18136
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18137
|
+
[rows, expandedSet, rowKey, childrenKey]
|
|
18138
|
+
);
|
|
18139
|
+
const tableRef = react.useRef(null);
|
|
18140
|
+
const [closingKeys, setClosingKeys] = react.useState(NO_KEYS);
|
|
18141
|
+
const [prevExpand, setPrevExpand] = react.useState({ rows, expandedSet });
|
|
18142
|
+
if (prevExpand.rows !== rows || prevExpand.expandedSet !== expandedSet) {
|
|
18143
|
+
setPrevExpand({ rows, expandedSet });
|
|
18144
|
+
let nextClosing = NO_KEYS;
|
|
18145
|
+
if (prevExpand.rows === rows && motionAllowed()) {
|
|
18146
|
+
const collapsed = [...prevExpand.expandedSet].filter((key) => !expandedSet.has(key));
|
|
18147
|
+
const expanded = [...expandedSet].filter((key) => !prevExpand.expandedSet.has(key));
|
|
18148
|
+
if (collapsed.length > 0 && expanded.length === 0) nextClosing = new Set(collapsed);
|
|
18149
|
+
}
|
|
18150
|
+
if (nextClosing !== closingKeys) setClosingKeys(nextClosing);
|
|
18151
|
+
}
|
|
18152
|
+
const renderedRows = react.useMemo(
|
|
18153
|
+
() => closingKeys.size === 0 ? visibleRows : flattenRows(
|
|
18154
|
+
rows,
|
|
18155
|
+
(row) => expandedSet.has(keyOf(row)) || closingKeys.has(keyOf(row)),
|
|
18156
|
+
childrenOf
|
|
18157
|
+
),
|
|
18158
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18159
|
+
[visibleRows, closingKeys]
|
|
18160
|
+
);
|
|
18161
|
+
const visibleKeys = react.useMemo(
|
|
18162
|
+
() => new Set(visibleRows.map(keyOf)),
|
|
18163
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18164
|
+
[visibleRows]
|
|
18165
|
+
);
|
|
18166
|
+
const motionRef = react.useRef(null);
|
|
18059
18167
|
const prevVisibleRef = react.useRef(null);
|
|
18060
18168
|
useIsomorphicLayoutEffect(() => {
|
|
18061
|
-
const keys = new Set(visibleRows.map(keyOf));
|
|
18062
18169
|
const prev = prevVisibleRef.current;
|
|
18063
|
-
prevVisibleRef.current = { rows, keys };
|
|
18064
|
-
|
|
18065
|
-
|
|
18066
|
-
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
if (
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18170
|
+
prevVisibleRef.current = { rows, keys: visibleKeys };
|
|
18171
|
+
const running = motionRef.current;
|
|
18172
|
+
if (running?.done) {
|
|
18173
|
+
running.cancel();
|
|
18174
|
+
motionRef.current = null;
|
|
18175
|
+
}
|
|
18176
|
+
if (!prev || prev.rows !== rows) {
|
|
18177
|
+
motionRef.current?.cancel();
|
|
18178
|
+
motionRef.current = null;
|
|
18179
|
+
return;
|
|
18180
|
+
}
|
|
18181
|
+
const added = new Set([...visibleKeys].filter((key) => !prev.keys.has(key)));
|
|
18182
|
+
const removed = new Set([...prev.keys].filter((key) => !visibleKeys.has(key)));
|
|
18183
|
+
if (added.size === 0 && removed.size === 0) return;
|
|
18184
|
+
let from = added.size > 0 ? 0 : 1;
|
|
18185
|
+
if (motionRef.current) {
|
|
18186
|
+
const current = motionRef.current;
|
|
18187
|
+
const reversing = current.to === 0 && sameKeys(added, current.keys) || current.to === 1 && sameKeys(removed, current.keys);
|
|
18188
|
+
if (reversing) from = current.openness();
|
|
18189
|
+
current.cancel();
|
|
18190
|
+
motionRef.current = null;
|
|
18191
|
+
}
|
|
18192
|
+
const scrollEl = tableRef.current?.getScrollElement();
|
|
18193
|
+
const keys = added.size > 0 ? added : removed;
|
|
18194
|
+
const canAnimate = scrollEl != null && motionAllowed() && (added.size === 0 || removed.size === 0);
|
|
18195
|
+
const motion = canAnimate ? startRowMotion({
|
|
18196
|
+
scrollEl,
|
|
18197
|
+
rowKeys: renderedRows.map(keyOf),
|
|
18198
|
+
blockKeys: keys,
|
|
18199
|
+
from,
|
|
18200
|
+
to: added.size > 0 ? 1 : 0
|
|
18201
|
+
}) : null;
|
|
18202
|
+
if (motion) {
|
|
18203
|
+
motionRef.current = motion;
|
|
18204
|
+
if (motion.to === 0) {
|
|
18205
|
+
void motion.finished.then((completed) => {
|
|
18206
|
+
if (!completed || motionRef.current !== motion) return;
|
|
18207
|
+
motion.done = true;
|
|
18208
|
+
setClosingKeys(NO_KEYS);
|
|
18209
|
+
});
|
|
18210
|
+
}
|
|
18211
|
+
} else if (closingKeys.size > 0) {
|
|
18212
|
+
setClosingKeys(NO_KEYS);
|
|
18213
|
+
}
|
|
18214
|
+
}, [renderedRows]);
|
|
18215
|
+
react.useEffect(() => () => motionRef.current?.cancel(), []);
|
|
18073
18216
|
const collectSelectable = (row) => canSelectRow(row) ? [row, ...childrenOf(row).flatMap(collectSelectable)] : [];
|
|
18074
18217
|
const selectionOf = (keys) => {
|
|
18075
18218
|
const state2 = /* @__PURE__ */ new Map();
|
|
@@ -18165,8 +18308,9 @@ function STreeTable({
|
|
|
18165
18308
|
STable2,
|
|
18166
18309
|
{
|
|
18167
18310
|
...rest,
|
|
18311
|
+
ref: tableRef,
|
|
18168
18312
|
columns: tableColumns,
|
|
18169
|
-
rows:
|
|
18313
|
+
rows: renderedRows,
|
|
18170
18314
|
rowKey,
|
|
18171
18315
|
resizable,
|
|
18172
18316
|
selectable,
|
|
@@ -18174,14 +18318,113 @@ function STreeTable({
|
|
|
18174
18318
|
isRowIndeterminate: selectionState ? (row) => !!selectionState.get(keyOf(row))?.indeterminate : void 0,
|
|
18175
18319
|
rowClassName: (row) => cn(
|
|
18176
18320
|
rowClassName?.(row),
|
|
18177
|
-
//
|
|
18178
|
-
|
|
18321
|
+
// 접히는 중인 행은 이미 접힌 행이다 — 사라지는 동안 눌리지 않게 한다
|
|
18322
|
+
!visibleKeys.has(keyOf(row)) && "pointer-events-none"
|
|
18179
18323
|
) || void 0,
|
|
18180
18324
|
selected: tableSelected,
|
|
18181
18325
|
onSelectedChange: handleSelectedChange
|
|
18182
18326
|
}
|
|
18183
18327
|
);
|
|
18184
18328
|
}
|
|
18329
|
+
function flattenRows(nodes, isOpen, childrenOf) {
|
|
18330
|
+
const out = [];
|
|
18331
|
+
const walk = (list) => {
|
|
18332
|
+
list.forEach((row) => {
|
|
18333
|
+
out.push(row);
|
|
18334
|
+
if (isOpen(row)) walk(childrenOf(row));
|
|
18335
|
+
});
|
|
18336
|
+
};
|
|
18337
|
+
walk(nodes);
|
|
18338
|
+
return out;
|
|
18339
|
+
}
|
|
18340
|
+
function sameKeys(a, b) {
|
|
18341
|
+
return a.size === b.size && [...a].every((key) => b.has(key));
|
|
18342
|
+
}
|
|
18343
|
+
function motionAllowed() {
|
|
18344
|
+
if (typeof window === "undefined" || typeof Element.prototype.animate !== "function")
|
|
18345
|
+
return false;
|
|
18346
|
+
return !window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
18347
|
+
}
|
|
18348
|
+
function startRowMotion({
|
|
18349
|
+
scrollEl,
|
|
18350
|
+
rowKeys,
|
|
18351
|
+
blockKeys,
|
|
18352
|
+
from,
|
|
18353
|
+
to
|
|
18354
|
+
}) {
|
|
18355
|
+
const spec = to === 1 ? EXPAND_MOTION : COLLAPSE_MOTION;
|
|
18356
|
+
const duration = spec.duration * Math.abs(to - from);
|
|
18357
|
+
if (duration < 1) return null;
|
|
18358
|
+
const trs = [...scrollEl.querySelectorAll("tr[data-row-index]")].map((tr) => {
|
|
18359
|
+
const key = rowKeys[Number(tr.dataset.rowIndex)];
|
|
18360
|
+
return {
|
|
18361
|
+
tr,
|
|
18362
|
+
inBlock: key !== void 0 && blockKeys.has(key),
|
|
18363
|
+
height: tr.getBoundingClientRect().height
|
|
18364
|
+
};
|
|
18365
|
+
});
|
|
18366
|
+
const viewBottom = scrollEl.scrollTop + scrollEl.clientHeight;
|
|
18367
|
+
const openAt = (offset) => from + (to - from) * offset;
|
|
18368
|
+
const translate = (shift2, s) => `translateY(${-shift2 * (1 - s)}px)`;
|
|
18369
|
+
const timing = {
|
|
18370
|
+
duration,
|
|
18371
|
+
easing: spec.easing,
|
|
18372
|
+
// 접힘은 남겨 둔 행이 빠질 때까지 끝 위치를 붙잡는다 — 놓으면 그 사이 한 프레임 제자리로 튄다
|
|
18373
|
+
fill: to === 0 ? "forwards" : "none"
|
|
18374
|
+
};
|
|
18375
|
+
const animations = [];
|
|
18376
|
+
let shift = 0;
|
|
18377
|
+
let blockHeight = 0;
|
|
18378
|
+
let y = 0;
|
|
18379
|
+
trs.forEach(({ tr, inBlock, height }, i) => {
|
|
18380
|
+
if (inBlock && !trs[i - 1]?.inBlock) {
|
|
18381
|
+
blockHeight = 0;
|
|
18382
|
+
for (let j = i; j < trs.length && trs[j].inBlock; j++) blockHeight += trs[j].height;
|
|
18383
|
+
shift += blockHeight;
|
|
18384
|
+
y = 0;
|
|
18385
|
+
}
|
|
18386
|
+
if (shift === 0 || tr.offsetTop - shift > viewBottom) return;
|
|
18387
|
+
if (!inBlock) {
|
|
18388
|
+
animations.push(
|
|
18389
|
+
tr.animate(
|
|
18390
|
+
[{ transform: translate(shift, from) }, { transform: translate(shift, to) }],
|
|
18391
|
+
timing
|
|
18392
|
+
)
|
|
18393
|
+
);
|
|
18394
|
+
return;
|
|
18395
|
+
}
|
|
18396
|
+
const rowY = y;
|
|
18397
|
+
const clipAt = (s) => Math.min(height, Math.max(0, blockHeight * (1 - s) - rowY));
|
|
18398
|
+
const bends = [1 - rowY / blockHeight, 1 - (rowY + height) / blockHeight].map((s) => (s - from) / (to - from)).filter((offset) => offset > 0 && offset < 1);
|
|
18399
|
+
const offsets = [0, ...bends, 1].sort((a, b) => a - b);
|
|
18400
|
+
animations.push(
|
|
18401
|
+
tr.animate(
|
|
18402
|
+
offsets.map((offset) => ({
|
|
18403
|
+
offset,
|
|
18404
|
+
transform: translate(shift, openAt(offset)),
|
|
18405
|
+
clipPath: `inset(${clipAt(openAt(offset))}px 0 0 0)`
|
|
18406
|
+
})),
|
|
18407
|
+
timing
|
|
18408
|
+
)
|
|
18409
|
+
);
|
|
18410
|
+
y += height;
|
|
18411
|
+
});
|
|
18412
|
+
if (animations.length === 0) return null;
|
|
18413
|
+
return {
|
|
18414
|
+
keys: blockKeys,
|
|
18415
|
+
to,
|
|
18416
|
+
done: false,
|
|
18417
|
+
finished: Promise.all(animations.map((animation) => animation.finished)).then(
|
|
18418
|
+
() => true,
|
|
18419
|
+
() => false
|
|
18420
|
+
),
|
|
18421
|
+
openness: () => {
|
|
18422
|
+
const progress = animations[0].effect?.getComputedTiming().progress;
|
|
18423
|
+
return progress == null ? to : openAt(progress);
|
|
18424
|
+
},
|
|
18425
|
+
cancel: () => animations.forEach((animation) => animation.cancel())
|
|
18426
|
+
};
|
|
18427
|
+
}
|
|
18185
18428
|
var OWN_CONTROL_SELECTOR = 'a, button, input, select, textarea, label, [role="button"], [role="checkbox"], [contenteditable="true"]';
|
|
18186
18429
|
function isOwnControl(target, cell) {
|
|
18187
18430
|
if (!(target instanceof Element)) return false;
|
|
@@ -19436,6 +19679,7 @@ function SDatePicker({
|
|
|
19436
19679
|
placeholder,
|
|
19437
19680
|
selectable,
|
|
19438
19681
|
disabled = false,
|
|
19682
|
+
showWeekday = false,
|
|
19439
19683
|
clearable = false,
|
|
19440
19684
|
width,
|
|
19441
19685
|
maxWidth,
|
|
@@ -19465,6 +19709,7 @@ function SDatePicker({
|
|
|
19465
19709
|
const [focused, setFocused] = react.useState(false);
|
|
19466
19710
|
const [ruleError, setRuleError] = react.useState("");
|
|
19467
19711
|
const hasValue = value != null && value !== "";
|
|
19712
|
+
const weekday = showWeekday && mode === "date";
|
|
19468
19713
|
const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
|
|
19469
19714
|
useFormField({
|
|
19470
19715
|
name,
|
|
@@ -19477,7 +19722,7 @@ function SDatePicker({
|
|
|
19477
19722
|
});
|
|
19478
19723
|
const resolvedError = error || ruleError !== "";
|
|
19479
19724
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
19480
|
-
const
|
|
19725
|
+
const baseDims = size === "md" ? {
|
|
19481
19726
|
padX: 16,
|
|
19482
19727
|
gap: 12,
|
|
19483
19728
|
icon: 20,
|
|
@@ -19502,6 +19747,13 @@ function SDatePicker({
|
|
|
19502
19747
|
lineHeight: 20,
|
|
19503
19748
|
radius: 4
|
|
19504
19749
|
};
|
|
19750
|
+
const weekdayW = weekday ? weekdaySuffixWidth(baseDims.fontSize) : 0;
|
|
19751
|
+
const dims = {
|
|
19752
|
+
...baseDims,
|
|
19753
|
+
minW: baseDims.minW + weekdayW,
|
|
19754
|
+
fieldMinW: baseDims.fieldMinW + weekdayW,
|
|
19755
|
+
fieldMaxW: weekdayW ? `calc(${fieldWidthValue(baseDims.fieldMaxW)} + ${weekdayW}px)` : baseDims.fieldMaxW
|
|
19756
|
+
};
|
|
19505
19757
|
const select = (date) => {
|
|
19506
19758
|
onValueChange?.(date);
|
|
19507
19759
|
if (rules && rules.length > 0) setRuleError(runRules(date, rules));
|
|
@@ -19586,7 +19838,7 @@ function SDatePicker({
|
|
|
19586
19838
|
lineHeight: `${dims.lineHeight}px`,
|
|
19587
19839
|
color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
|
|
19588
19840
|
},
|
|
19589
|
-
children: hasValue ? value : resolvedPlaceholder
|
|
19841
|
+
children: hasValue ? weekday ? withWeekday(value) : value : resolvedPlaceholder
|
|
19590
19842
|
}
|
|
19591
19843
|
),
|
|
19592
19844
|
clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -19980,6 +20232,7 @@ function SDateRangePicker({
|
|
|
19980
20232
|
selectable,
|
|
19981
20233
|
maxRange,
|
|
19982
20234
|
showTimePicker = false,
|
|
20235
|
+
showWeekday = false,
|
|
19983
20236
|
disabled = false,
|
|
19984
20237
|
clearable = false,
|
|
19985
20238
|
width,
|
|
@@ -20011,8 +20264,10 @@ function SDateRangePicker({
|
|
|
20011
20264
|
const [pendingStart, setPendingStart] = react.useState(null);
|
|
20012
20265
|
const hasValue = value != null && value[0] !== "" && value[1] !== "";
|
|
20013
20266
|
const hasDisplay = pendingStart != null || hasValue;
|
|
20014
|
-
const
|
|
20015
|
-
const
|
|
20267
|
+
const rawStart = pendingStart ?? (hasValue ? value[0] : "");
|
|
20268
|
+
const rawEnd = pendingStart ? "" : hasValue ? value[1] : "";
|
|
20269
|
+
const startText = showWeekday && rawStart ? withWeekday(rawStart) : rawStart;
|
|
20270
|
+
const endText = showWeekday && rawEnd ? withWeekday(rawEnd) : rawEnd;
|
|
20016
20271
|
useFormField({
|
|
20017
20272
|
name,
|
|
20018
20273
|
validate: () => {
|
|
@@ -20024,7 +20279,7 @@ function SDateRangePicker({
|
|
|
20024
20279
|
});
|
|
20025
20280
|
const resolvedError = error || ruleError !== "";
|
|
20026
20281
|
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
20027
|
-
const
|
|
20282
|
+
const baseDims = size === "md" ? {
|
|
20028
20283
|
padX: 16,
|
|
20029
20284
|
gap: 12,
|
|
20030
20285
|
icon: 20,
|
|
@@ -20048,6 +20303,13 @@ function SDateRangePicker({
|
|
|
20048
20303
|
lineHeight: 20,
|
|
20049
20304
|
radius: 4
|
|
20050
20305
|
};
|
|
20306
|
+
const weekdayW = showWeekday ? weekdaySuffixWidth(baseDims.fontSize) * 2 : 0;
|
|
20307
|
+
const dims = {
|
|
20308
|
+
...baseDims,
|
|
20309
|
+
minW: baseDims.minW + weekdayW,
|
|
20310
|
+
fieldMinW: baseDims.fieldMinW + weekdayW,
|
|
20311
|
+
fieldMaxW: weekdayW ? `calc(${fieldWidthValue(baseDims.fieldMaxW)} + ${weekdayW}px)` : baseDims.fieldMaxW
|
|
20312
|
+
};
|
|
20051
20313
|
const select = (r3) => {
|
|
20052
20314
|
setPendingStart(null);
|
|
20053
20315
|
onValueChange?.(r3);
|
|
@@ -26049,7 +26311,7 @@ var isAtResetTarget = (field, value) => {
|
|
|
26049
26311
|
var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
|
|
26050
26312
|
var isFixedField = (field) => field.fixed === true || field.required === true;
|
|
26051
26313
|
var isAddableField = (field) => !isFixedField(field);
|
|
26052
|
-
var
|
|
26314
|
+
var sameKeys2 = (a, b) => a.length === b.length && a.every((key, index) => key === b[index]);
|
|
26053
26315
|
var isGroupSatisfied = (group, values) => {
|
|
26054
26316
|
if (!group.rule) return true;
|
|
26055
26317
|
const keys = group.fields.map((f) => f.key);
|
|
@@ -26232,7 +26494,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
|
|
|
26232
26494
|
const kept = current.filter((key) => known.has(key));
|
|
26233
26495
|
const additions = fields.filter((field) => isFixedField(field) && !kept.includes(field.key)).map((field) => field.key);
|
|
26234
26496
|
const next = [...kept, ...additions];
|
|
26235
|
-
return
|
|
26497
|
+
return sameKeys2(current, next) ? current : next;
|
|
26236
26498
|
});
|
|
26237
26499
|
}, [fields, values]);
|
|
26238
26500
|
react.useEffect(() => {
|