sellmate-design-system-react 9.0.0-beta.45 → 9.0.0-beta.46
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 +48 -4
- package/dist/components/SButton/README.md +2 -0
- package/dist/components/SChatInput/README.md +44 -0
- package/dist/components/SChatInput/SChatInput.d.ts +60 -0
- package/dist/components/SChatInput/index.d.ts +1 -0
- package/dist/components/SChatMessage/README.md +81 -0
- package/dist/components/SChatMessage/SChatMessage.d.ts +102 -0
- package/dist/components/SChatMessage/index.d.ts +1 -0
- package/dist/components/SGhostButton/README.md +2 -0
- package/dist/components/SIcon/README.md +2 -0
- package/dist/components/SIcon/icons.gen.d.ts +1 -0
- package/dist/components/SImage/README.md +5 -0
- package/dist/components/SLoginCard/README.md +34 -0
- package/dist/components/SLoginCard/SLoginCard.d.ts +28 -0
- package/dist/components/SLoginCard/index.d.ts +1 -0
- package/dist/components/SLoginCard/sellmate-wordmark.d.ts +13 -0
- package/dist/components/STextarea/README.md +2 -0
- package/dist/index.cjs +2417 -2091
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2413 -2093
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +204 -4
- package/dist/llms.txt +50 -6
- package/dist/styles.css +86 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
4
|
-
import { forwardRef, useState, useRef, useEffect, createContext,
|
|
4
|
+
import { forwardRef, useState, useRef, useEffect, createContext, useCallback, useImperativeHandle, useLayoutEffect, useContext, useMemo, useId, Children, cloneElement, Fragment as Fragment$1, isValidElement, useSyncExternalStore, Component } from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import * as RPopover12 from '@radix-ui/react-popover';
|
|
6
7
|
import { createPortal } from 'react-dom';
|
|
7
8
|
import * as RCheckbox from '@radix-ui/react-checkbox';
|
|
8
|
-
import * as RPopover12 from '@radix-ui/react-popover';
|
|
9
9
|
import { createRoot } from 'react-dom/client';
|
|
10
10
|
import * as RTooltip from '@radix-ui/react-tooltip';
|
|
11
11
|
import * as RDropdown2 from '@radix-ui/react-dropdown-menu';
|
|
@@ -2729,6 +2729,38 @@ var Icon_star = (p) => {
|
|
|
2729
2729
|
}
|
|
2730
2730
|
);
|
|
2731
2731
|
};
|
|
2732
|
+
var Icon_stop = (p) => {
|
|
2733
|
+
const { size = 24, ...rest } = p;
|
|
2734
|
+
return /* @__PURE__ */ jsxs(
|
|
2735
|
+
"svg",
|
|
2736
|
+
{
|
|
2737
|
+
width: size,
|
|
2738
|
+
height: size,
|
|
2739
|
+
viewBox: "0 0 24 24",
|
|
2740
|
+
fill: "none",
|
|
2741
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2742
|
+
...rest,
|
|
2743
|
+
children: [
|
|
2744
|
+
/* @__PURE__ */ jsx(
|
|
2745
|
+
"path",
|
|
2746
|
+
{
|
|
2747
|
+
d: "M15.5 7.5C16.0523 7.5 16.5 7.94772 16.5 8.5V15.5C16.5 16.0523 16.0523 16.5 15.5 16.5H8.5C7.94772 16.5 7.5 16.0523 7.5 15.5V8.5C7.5 7.94772 7.94772 7.5 8.5 7.5H15.5Z",
|
|
2748
|
+
fill: "currentColor"
|
|
2749
|
+
}
|
|
2750
|
+
),
|
|
2751
|
+
/* @__PURE__ */ jsx(
|
|
2752
|
+
"path",
|
|
2753
|
+
{
|
|
2754
|
+
fillRule: "evenodd",
|
|
2755
|
+
clipRule: "evenodd",
|
|
2756
|
+
d: "M12 1.0498C18.0474 1.04991 22.9501 5.95263 22.9502 12C22.9501 18.0474 18.0474 22.9501 12 22.9502C5.95266 22.9501 1.04991 18.0473 1.0498 12C1.0499 5.95265 5.95266 1.04994 12 1.0498ZM12 2.5498C6.78108 2.54994 2.5499 6.78108 2.5498 12C2.54991 17.2189 6.78109 21.4501 12 21.4502C17.2189 21.4501 21.4501 17.2189 21.4502 12C21.4501 6.78106 17.2189 2.54991 12 2.5498Z",
|
|
2757
|
+
fill: "currentColor"
|
|
2758
|
+
}
|
|
2759
|
+
)
|
|
2760
|
+
]
|
|
2761
|
+
}
|
|
2762
|
+
);
|
|
2763
|
+
};
|
|
2732
2764
|
var Icon_store = (p) => {
|
|
2733
2765
|
const { size = 24, ...rest } = p;
|
|
2734
2766
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3228,6 +3260,7 @@ var ICONS = {
|
|
|
3228
3260
|
shield: Icon_shield,
|
|
3229
3261
|
sidebar: Icon_sidebar,
|
|
3230
3262
|
star: Icon_star,
|
|
3263
|
+
stop: Icon_stop,
|
|
3231
3264
|
store: Icon_store,
|
|
3232
3265
|
synchronize: Icon_synchronize,
|
|
3233
3266
|
thumbsDown: Icon_thumbsDown,
|
|
@@ -3738,409 +3771,1474 @@ function withDisplayName(component, name) {
|
|
|
3738
3771
|
return component;
|
|
3739
3772
|
}
|
|
3740
3773
|
|
|
3741
|
-
// src/lib/
|
|
3742
|
-
var
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3774
|
+
// src/lib/floating-anim.ts
|
|
3775
|
+
var FLOATING_SLIDE_ANIM = [
|
|
3776
|
+
"data-[state=open]:data-[side=top]:animate-floating-in-top",
|
|
3777
|
+
"data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
|
|
3778
|
+
"data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
|
|
3779
|
+
"data-[state=closed]:data-[side=top]:animate-floating-out-top",
|
|
3780
|
+
"data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
3781
|
+
"data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
3782
|
+
"data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
3783
|
+
"data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
|
|
3784
|
+
"data-[state=open]:data-[side=left]:animate-floating-in-left",
|
|
3785
|
+
"data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
|
|
3786
|
+
"data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
|
|
3787
|
+
"data-[state=closed]:data-[side=left]:animate-floating-out-left",
|
|
3788
|
+
"data-[state=open]:data-[side=right]:animate-floating-in-right",
|
|
3789
|
+
"data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
|
|
3790
|
+
"data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
|
|
3791
|
+
"data-[state=closed]:data-[side=right]:animate-floating-out-right"
|
|
3792
|
+
].join(" ");
|
|
3793
|
+
var PortalContainerContext = /* @__PURE__ */ createContext(null);
|
|
3794
|
+
var InsideModalContext = /* @__PURE__ */ createContext(false);
|
|
3795
|
+
var PortalContainerProvider = PortalContainerContext.Provider;
|
|
3796
|
+
var InsideModalProvider = InsideModalContext.Provider;
|
|
3797
|
+
function usePortalContainer() {
|
|
3798
|
+
return useContext(PortalContainerContext) ?? void 0;
|
|
3799
|
+
}
|
|
3800
|
+
function useInsideModal() {
|
|
3801
|
+
return useContext(InsideModalContext);
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
// src/components/STag/tag.config.ts
|
|
3805
|
+
var TAG_SHAPES = ["square", "pill"];
|
|
3806
|
+
var TAG_SIZES = ["xs", "sm", "md"];
|
|
3807
|
+
var TAG_COLORS = [
|
|
3808
|
+
"grey",
|
|
3809
|
+
"red",
|
|
3810
|
+
"orange",
|
|
3811
|
+
"yellow",
|
|
3812
|
+
"green",
|
|
3813
|
+
"blue",
|
|
3814
|
+
"darkblue",
|
|
3815
|
+
"indigo"
|
|
3816
|
+
];
|
|
3817
|
+
var TAG_SIZE_CONFIG = {
|
|
3818
|
+
xs: {
|
|
3819
|
+
height: 20,
|
|
3820
|
+
paddingX: 8,
|
|
3821
|
+
gap: 4,
|
|
3822
|
+
radius: 6,
|
|
3823
|
+
iconSize: 12,
|
|
3824
|
+
fontSize: 11,
|
|
3825
|
+
fontWeight: 500,
|
|
3826
|
+
lineHeight: 18
|
|
3827
|
+
},
|
|
3828
|
+
sm: {
|
|
3829
|
+
height: 24,
|
|
3830
|
+
paddingX: 8,
|
|
3831
|
+
gap: 4,
|
|
3832
|
+
radius: 6,
|
|
3833
|
+
iconSize: 16,
|
|
3834
|
+
fontSize: 12,
|
|
3835
|
+
fontWeight: 700,
|
|
3836
|
+
lineHeight: 20
|
|
3837
|
+
},
|
|
3838
|
+
md: {
|
|
3839
|
+
height: 28,
|
|
3840
|
+
paddingX: 12,
|
|
3841
|
+
gap: 6,
|
|
3842
|
+
radius: 8,
|
|
3843
|
+
iconSize: 16,
|
|
3844
|
+
fontSize: 14,
|
|
3845
|
+
fontWeight: 700,
|
|
3846
|
+
lineHeight: 24
|
|
3847
|
+
}
|
|
3748
3848
|
};
|
|
3749
|
-
var
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3849
|
+
var STag = /* @__PURE__ */ forwardRef(function STag2({
|
|
3850
|
+
shape = "square",
|
|
3851
|
+
size = "sm",
|
|
3852
|
+
color = "grey",
|
|
3853
|
+
deep = false,
|
|
3854
|
+
label = "",
|
|
3855
|
+
icon,
|
|
3856
|
+
iconLeft = true,
|
|
3857
|
+
width,
|
|
3858
|
+
className,
|
|
3859
|
+
style,
|
|
3860
|
+
...rest
|
|
3861
|
+
}, ref) {
|
|
3862
|
+
const s = TAG_SIZE_CONFIG[size];
|
|
3863
|
+
const contentColor = deep ? `var(--cmp-tag-${color}-deep-content, var(--cmp-tag-deep-content))` : `var(--cmp-tag-${color}-content)`;
|
|
3864
|
+
const bgColor = deep ? `var(--cmp-tag-${color}-deep-bg)` : `var(--cmp-tag-${color}-bg)`;
|
|
3865
|
+
const iconNode = icon ? /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
3866
|
+
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
3867
|
+
return /* @__PURE__ */ jsxs(
|
|
3868
|
+
"span",
|
|
3869
|
+
{
|
|
3870
|
+
ref,
|
|
3871
|
+
"aria-label": label || "tag",
|
|
3872
|
+
className: cn(
|
|
3873
|
+
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
3874
|
+
className
|
|
3875
|
+
),
|
|
3876
|
+
style: {
|
|
3877
|
+
minHeight: s.height,
|
|
3878
|
+
padding: `0 ${s.paddingX}px`,
|
|
3879
|
+
gap: s.gap,
|
|
3880
|
+
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
3881
|
+
fontSize: s.fontSize,
|
|
3882
|
+
fontWeight: s.fontWeight,
|
|
3883
|
+
lineHeight: `${s.lineHeight}px`,
|
|
3884
|
+
background: bgColor,
|
|
3885
|
+
color: contentColor,
|
|
3886
|
+
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
3887
|
+
...style
|
|
3888
|
+
},
|
|
3889
|
+
...rest,
|
|
3890
|
+
children: [
|
|
3891
|
+
icon && iconLeft && iconNode,
|
|
3892
|
+
label && // leading-none: 태그는 min-height 로 높이가 정해지고 flex 가 세로 중앙 정렬하므로
|
|
3893
|
+
// 레이블에 line-height 가 필요 없다. 오히려 line-height 를 주면 브라우저가
|
|
3894
|
+
// 폰트 ascent/descent 를 정수 px 로 반올림한 뒤 남는 half-leading 을 내림 처리해
|
|
3895
|
+
// 베이스라인이 최대 1px 위로 밀린다(xs 에서 특히 눈에 띈다).
|
|
3896
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex min-w-0 items-center justify-center leading-none", children: label }),
|
|
3897
|
+
icon && !iconLeft && iconNode
|
|
3898
|
+
]
|
|
3757
3899
|
}
|
|
3758
|
-
|
|
3900
|
+
);
|
|
3901
|
+
});
|
|
3902
|
+
var SIZE = {
|
|
3903
|
+
xxs: { icon: 12, radius: "sm" },
|
|
3904
|
+
xs: { icon: 16, radius: "sm" },
|
|
3905
|
+
sm: { icon: 20, radius: "sm" },
|
|
3906
|
+
md: { icon: 24, radius: "md" },
|
|
3907
|
+
lg: { icon: 32, radius: "md" }
|
|
3759
3908
|
};
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
var SDraggableItemView = /* @__PURE__ */ forwardRef(
|
|
3764
|
-
function SDraggableItemView2({
|
|
3765
|
-
title,
|
|
3766
|
-
supportingText,
|
|
3767
|
-
supportingTextPosition,
|
|
3768
|
-
trailing,
|
|
3769
|
-
depth,
|
|
3770
|
-
accentStripe,
|
|
3771
|
-
bordered,
|
|
3772
|
-
selected,
|
|
3773
|
-
dense,
|
|
3774
|
-
size,
|
|
3775
|
-
dragging,
|
|
3776
|
-
disabled,
|
|
3777
|
-
hovered,
|
|
3778
|
-
dragHandleProps,
|
|
3779
|
-
onDragHandleMouseDown,
|
|
3780
|
-
className,
|
|
3781
|
-
style,
|
|
3782
|
-
...rest
|
|
3783
|
-
}, ref) {
|
|
3784
|
-
const renderState = { hovered, dragging, disabled };
|
|
3785
|
-
const titleNode = renderSlot(title, renderState);
|
|
3786
|
-
const supportingTextNode = renderSlot(supportingText, renderState);
|
|
3787
|
-
const hasSupportingText = supportingTextNode != null && supportingTextNode !== "";
|
|
3788
|
-
const trailingNode = renderSlot(trailing, renderState);
|
|
3789
|
-
const titleTypo = size === "sm" ? selected ? "typo-item-sm-selected" : "typo-item-sm-default" : selected ? "typo-item-md-selected" : "typo-item-md-default";
|
|
3790
|
-
const paddingYClass = dense ? size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-dense)" : "py-(--cmp-listDraggableItem-paddingY-md-dense)" : size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-normal)" : "py-(--cmp-listDraggableItem-paddingY-md-normal)";
|
|
3791
|
-
const normalizedDepth = Math.max(1, Math.floor(depth));
|
|
3792
|
-
const depthOffset = (normalizedDepth - 1) * 20;
|
|
3793
|
-
const depthStyle = depthOffset === 0 ? style : bordered ? {
|
|
3794
|
-
...style,
|
|
3795
|
-
marginLeft: depthOffset,
|
|
3796
|
-
width: `calc(100% - ${depthOffset}px)`
|
|
3797
|
-
} : {
|
|
3798
|
-
...style,
|
|
3799
|
-
paddingLeft: `calc(var(--cmp-listDraggableItem-paddingX) + ${depthOffset}px)`
|
|
3800
|
-
};
|
|
3801
|
-
return /* @__PURE__ */ jsxs(
|
|
3802
|
-
"div",
|
|
3803
|
-
{
|
|
3804
|
-
ref,
|
|
3805
|
-
"aria-disabled": disabled || void 0,
|
|
3806
|
-
"data-dragging": dragging || void 0,
|
|
3807
|
-
style: depthStyle,
|
|
3808
|
-
className: cn(
|
|
3809
|
-
"relative flex w-full items-center gap-(--cmp-listDraggableItem-gap) overflow-hidden px-(--cmp-listDraggableItem-paddingX)",
|
|
3810
|
-
titleTypo,
|
|
3811
|
-
disabled ? "bg-(--cmp-listDraggableItem-bg-default) text-(--sys-color-disabled-text)" : selected ? "bg-(--cmp-listDraggableItem-bg-selected) text-(--cmp-listDraggableItem-text-selected)" : "bg-(--cmp-listDraggableItem-bg-default) text-(--cmp-listDraggableItem-text-default)",
|
|
3812
|
-
!disabled && !selected && !dragging && cn(
|
|
3813
|
-
"hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
3814
|
-
// 리스트가 드래그 중이면(SDraggableList 가 data-drag-active 를 붙인다) hover 를 무효화한다.
|
|
3815
|
-
"[[data-drag-active]_&]:hover:bg-(--cmp-listDraggableItem-bg-default)"
|
|
3816
|
-
),
|
|
3817
|
-
// 높이는 세로 패딩과 내용이 정한다 — 항목에 높이를 못 박지 않는다 (SListItem 과 동일)
|
|
3818
|
-
paddingYClass,
|
|
3819
|
-
// 항목 사이 구분선은 리스트가 그린다.
|
|
3820
|
-
bordered && cn(
|
|
3821
|
-
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
3822
|
-
!disabled && !selected && !dragging && cn(
|
|
3823
|
-
"hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
3824
|
-
"[[data-drag-active]_&]:hover:border-(--cmp-listDraggableItem-border-default)"
|
|
3825
|
-
),
|
|
3826
|
-
!disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected) bg-(--cmp-listDraggableItem-bordered-bg-selected)",
|
|
3827
|
-
!disabled && selected && dragging && "border-(--cmp-listDraggableItem-bordered-dragging-border-color) bg-(--cmp-listDraggableItem-bordered-dragging-bg)"
|
|
3828
|
-
),
|
|
3829
|
-
disabled && "cursor-not-allowed",
|
|
3830
|
-
className
|
|
3831
|
-
),
|
|
3832
|
-
...rest,
|
|
3833
|
-
children: [
|
|
3834
|
-
accentStripe && selected && !bordered && !disabled && /* @__PURE__ */ jsx(
|
|
3835
|
-
"span",
|
|
3836
|
-
{
|
|
3837
|
-
"aria-hidden": "true",
|
|
3838
|
-
className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 w-(--cmp-listDraggableItem-accentStripe-width) bg-(--cmp-listDraggableItem-accentStripe-color)"
|
|
3839
|
-
}
|
|
3840
|
-
),
|
|
3841
|
-
/* @__PURE__ */ jsx(
|
|
3842
|
-
"div",
|
|
3843
|
-
{
|
|
3844
|
-
...dragHandleProps,
|
|
3845
|
-
role: dragHandleProps?.role ?? "button",
|
|
3846
|
-
tabIndex: dragHandleProps?.tabIndex ?? (disabled ? -1 : 0),
|
|
3847
|
-
"aria-label": dragHandleProps?.["aria-label"] ?? "\uB4DC\uB798\uADF8 \uD578\uB4E4",
|
|
3848
|
-
"aria-disabled": disabled || void 0,
|
|
3849
|
-
onMouseDown: onDragHandleMouseDown,
|
|
3850
|
-
className: cn(
|
|
3851
|
-
"flex size-[24px] shrink-0 select-none items-center justify-center rounded-[4px]",
|
|
3852
|
-
disabled ? "cursor-not-allowed opacity-0" : "cursor-grab hover:bg-black/5 active:cursor-grabbing",
|
|
3853
|
-
!disabled && !dragging && "[[data-drag-active]_&]:hover:bg-transparent",
|
|
3854
|
-
dragging && "bg-black/5",
|
|
3855
|
-
dragHandleProps?.className
|
|
3856
|
-
),
|
|
3857
|
-
children: /* @__PURE__ */ jsx(SIcon, { name: "drag", size: 16, color: "grey_65" })
|
|
3858
|
-
}
|
|
3859
|
-
),
|
|
3860
|
-
/* @__PURE__ */ jsxs(
|
|
3861
|
-
"div",
|
|
3862
|
-
{
|
|
3863
|
-
className: cn(
|
|
3864
|
-
"flex min-w-0 flex-1 items-center gap-[8px]",
|
|
3865
|
-
dragging && "opacity-(--cmp-listDraggableItem-dragging-content-opacity)"
|
|
3866
|
-
),
|
|
3867
|
-
children: [
|
|
3868
|
-
/* @__PURE__ */ jsxs(
|
|
3869
|
-
"span",
|
|
3870
|
-
{
|
|
3871
|
-
className: cn(
|
|
3872
|
-
"min-w-0 flex-1",
|
|
3873
|
-
supportingTextPosition === "bottom" ? "flex flex-col" : "flex items-center gap-[8px] whitespace-nowrap"
|
|
3874
|
-
),
|
|
3875
|
-
children: [
|
|
3876
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: titleNode }),
|
|
3877
|
-
hasSupportingText && /* @__PURE__ */ jsx(
|
|
3878
|
-
"span",
|
|
3879
|
-
{
|
|
3880
|
-
className: cn(
|
|
3881
|
-
"typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
|
|
3882
|
-
supportingTextPosition === "right" && "flex-1"
|
|
3883
|
-
),
|
|
3884
|
-
children: supportingTextNode
|
|
3885
|
-
}
|
|
3886
|
-
)
|
|
3887
|
-
]
|
|
3888
|
-
}
|
|
3889
|
-
),
|
|
3890
|
-
trailingNode
|
|
3891
|
-
]
|
|
3892
|
-
}
|
|
3893
|
-
)
|
|
3894
|
-
]
|
|
3895
|
-
}
|
|
3896
|
-
);
|
|
3897
|
-
}
|
|
3898
|
-
);
|
|
3899
|
-
var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
|
|
3900
|
-
title,
|
|
3901
|
-
supportingText,
|
|
3902
|
-
supportingTextPosition = "right",
|
|
3903
|
-
trailing,
|
|
3904
|
-
depth = 1,
|
|
3905
|
-
accentStripe = false,
|
|
3906
|
-
bordered = false,
|
|
3907
|
-
selected = false,
|
|
3908
|
-
dragging = false,
|
|
3909
|
-
dense = false,
|
|
3909
|
+
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
3910
|
+
function SGhostButton({
|
|
3911
|
+
icon,
|
|
3910
3912
|
size = "sm",
|
|
3913
|
+
intent = "default",
|
|
3914
|
+
ariaLabel = "",
|
|
3915
|
+
ariaPressed,
|
|
3916
|
+
ariaExpanded,
|
|
3917
|
+
tooltipText,
|
|
3911
3918
|
disabled = false,
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
onDragHandleMouseDown,
|
|
3919
|
+
onClick,
|
|
3920
|
+
anchorClassName,
|
|
3921
|
+
anchorStyle,
|
|
3916
3922
|
className,
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
const
|
|
3922
|
-
const
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
onMouseEnter?.(event);
|
|
3923
|
+
style
|
|
3924
|
+
}) {
|
|
3925
|
+
const portalContainer = usePortalContainer();
|
|
3926
|
+
const [open, setOpen] = useState(false);
|
|
3927
|
+
const hideTimer = useRef(void 0);
|
|
3928
|
+
const cancelHide = () => {
|
|
3929
|
+
if (hideTimer.current) {
|
|
3930
|
+
clearTimeout(hideTimer.current);
|
|
3931
|
+
hideTimer.current = void 0;
|
|
3932
|
+
}
|
|
3928
3933
|
};
|
|
3929
|
-
const
|
|
3930
|
-
|
|
3931
|
-
|
|
3934
|
+
const openNow = () => {
|
|
3935
|
+
cancelHide();
|
|
3936
|
+
setOpen(true);
|
|
3932
3937
|
};
|
|
3933
|
-
const
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
if (dragOverlay && rect) {
|
|
3937
|
-
setOverlay({
|
|
3938
|
-
offsetX: event.clientX - rect.left,
|
|
3939
|
-
offsetY: event.clientY - rect.top,
|
|
3940
|
-
rect,
|
|
3941
|
-
x: event.clientX,
|
|
3942
|
-
y: event.clientY
|
|
3943
|
-
});
|
|
3944
|
-
}
|
|
3945
|
-
dragHandleProps?.onMouseDown?.(event);
|
|
3946
|
-
onDragHandleMouseDown?.(event);
|
|
3938
|
+
const startHide = () => {
|
|
3939
|
+
cancelHide();
|
|
3940
|
+
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
3947
3941
|
};
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
x: event.clientX,
|
|
3955
|
-
y: event.clientY
|
|
3956
|
-
} : current
|
|
3957
|
-
);
|
|
3958
|
-
};
|
|
3959
|
-
const handleMouseUp = () => {
|
|
3960
|
-
setOverlay(null);
|
|
3961
|
-
};
|
|
3962
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
3963
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
3964
|
-
return () => {
|
|
3965
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
3966
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
3967
|
-
};
|
|
3968
|
-
}, [overlayVisible]);
|
|
3969
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3970
|
-
/* @__PURE__ */ jsx(
|
|
3971
|
-
SDraggableItemView,
|
|
3972
|
-
{
|
|
3973
|
-
ref: (node) => setRefs([rootRef, ref], node),
|
|
3974
|
-
title,
|
|
3975
|
-
supportingText,
|
|
3976
|
-
supportingTextPosition,
|
|
3977
|
-
trailing,
|
|
3978
|
-
depth,
|
|
3979
|
-
accentStripe,
|
|
3980
|
-
bordered,
|
|
3981
|
-
selected,
|
|
3982
|
-
dense,
|
|
3983
|
-
size,
|
|
3984
|
-
dragging: dragging || overlayVisible,
|
|
3985
|
-
disabled,
|
|
3986
|
-
hovered,
|
|
3987
|
-
dragHandleProps,
|
|
3988
|
-
onDragHandleMouseDown: handleDragMouseDown,
|
|
3989
|
-
onMouseEnter: handleMouseEnter,
|
|
3990
|
-
onMouseLeave: handleMouseLeave,
|
|
3991
|
-
className,
|
|
3992
|
-
...rest
|
|
3993
|
-
}
|
|
3994
|
-
),
|
|
3995
|
-
overlay && typeof document !== "undefined" && createPortal(
|
|
3996
|
-
/* @__PURE__ */ jsx(
|
|
3997
|
-
"div",
|
|
3998
|
-
{
|
|
3999
|
-
className: "pointer-events-none fixed",
|
|
4000
|
-
style: {
|
|
4001
|
-
left: overlay.x - overlay.offsetX,
|
|
4002
|
-
opacity: dragOverlayOpacity,
|
|
4003
|
-
top: overlay.y - overlay.offsetY,
|
|
4004
|
-
width: overlay.rect.width,
|
|
4005
|
-
zIndex: Z_INDEX.drag
|
|
4006
|
-
},
|
|
4007
|
-
children: /* @__PURE__ */ jsx(
|
|
4008
|
-
SDraggableItemView,
|
|
4009
|
-
{
|
|
4010
|
-
title,
|
|
4011
|
-
supportingText,
|
|
4012
|
-
supportingTextPosition,
|
|
4013
|
-
trailing,
|
|
4014
|
-
depth,
|
|
4015
|
-
accentStripe,
|
|
4016
|
-
bordered,
|
|
4017
|
-
selected,
|
|
4018
|
-
dense,
|
|
4019
|
-
size,
|
|
4020
|
-
dragging: true,
|
|
4021
|
-
disabled,
|
|
4022
|
-
hovered: true,
|
|
4023
|
-
dragHandleProps,
|
|
4024
|
-
className
|
|
4025
|
-
}
|
|
4026
|
-
)
|
|
4027
|
-
}
|
|
4028
|
-
),
|
|
4029
|
-
document.body
|
|
4030
|
-
)
|
|
4031
|
-
] });
|
|
4032
|
-
});
|
|
4033
|
-
var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
|
|
4034
|
-
var SDivider = /* @__PURE__ */ forwardRef(function SDivider2({ vertical = false, height, className, style, ...rest }, ref) {
|
|
4035
|
-
const fixedHeight = vertical && height !== void 0;
|
|
4036
|
-
return /* @__PURE__ */ jsx(
|
|
4037
|
-
"hr",
|
|
3942
|
+
const s = SIZE[size];
|
|
3943
|
+
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
3944
|
+
const text = (tooltipText ?? "").trim();
|
|
3945
|
+
const hasTooltip = text !== "";
|
|
3946
|
+
const btn2 = /* @__PURE__ */ jsxs(
|
|
3947
|
+
"button",
|
|
4038
3948
|
{
|
|
4039
|
-
|
|
4040
|
-
|
|
3949
|
+
type: "button",
|
|
3950
|
+
disabled,
|
|
3951
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
3952
|
+
"aria-label": ariaLabel.trim() || void 0,
|
|
3953
|
+
"aria-pressed": ariaPressed,
|
|
3954
|
+
"aria-expanded": ariaExpanded,
|
|
3955
|
+
tabIndex: disabled ? -1 : void 0,
|
|
3956
|
+
onClick: (e) => {
|
|
3957
|
+
if (disabled) {
|
|
3958
|
+
e.preventDefault();
|
|
3959
|
+
return;
|
|
3960
|
+
}
|
|
3961
|
+
onClick?.(e);
|
|
3962
|
+
},
|
|
4041
3963
|
className: cn(
|
|
4042
|
-
"
|
|
4043
|
-
|
|
3964
|
+
"group/ghost-button relative box-border inline-flex items-center justify-center border-none bg-transparent p-0 transition-shadow",
|
|
3965
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
3966
|
+
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
4044
3967
|
className
|
|
4045
3968
|
),
|
|
4046
3969
|
style: {
|
|
4047
|
-
|
|
4048
|
-
|
|
3970
|
+
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
3971
|
+
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
3972
|
+
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
4049
3973
|
...style
|
|
4050
3974
|
},
|
|
4051
|
-
|
|
4052
|
-
|
|
3975
|
+
children: [
|
|
3976
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
3977
|
+
"span",
|
|
3978
|
+
{
|
|
3979
|
+
"aria-hidden": true,
|
|
3980
|
+
className: "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-200 group-hover/ghost-button:opacity-5",
|
|
3981
|
+
style: { background: `var(--cmp-ghostButton-${intent}-hover-bg)` }
|
|
3982
|
+
}
|
|
3983
|
+
),
|
|
3984
|
+
/* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: contentColor })
|
|
3985
|
+
]
|
|
3986
|
+
}
|
|
4053
3987
|
);
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
3988
|
+
if (!hasTooltip) return btn2;
|
|
3989
|
+
return /* @__PURE__ */ jsxs(RPopover12.Root, { open, onOpenChange: setOpen, children: [
|
|
3990
|
+
/* @__PURE__ */ jsx(RPopover12.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3991
|
+
"span",
|
|
3992
|
+
{
|
|
3993
|
+
className: cn("inline-flex", anchorClassName),
|
|
3994
|
+
style: anchorStyle,
|
|
3995
|
+
onMouseEnter: openNow,
|
|
3996
|
+
onMouseLeave: startHide,
|
|
3997
|
+
onFocus: openNow,
|
|
3998
|
+
onBlur: startHide,
|
|
3999
|
+
children: btn2
|
|
4000
|
+
}
|
|
4001
|
+
) }),
|
|
4002
|
+
/* @__PURE__ */ jsx(RPopover12.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
4003
|
+
RPopover12.Content,
|
|
4004
|
+
{
|
|
4005
|
+
side: "top",
|
|
4006
|
+
sideOffset: 4,
|
|
4007
|
+
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
4008
|
+
"aria-hidden": true,
|
|
4009
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
4010
|
+
onMouseEnter: cancelHide,
|
|
4011
|
+
onMouseLeave: startHide,
|
|
4012
|
+
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
4013
|
+
}
|
|
4014
|
+
) })
|
|
4015
|
+
] });
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
// src/lib/sanitize-inline-html.ts
|
|
4019
|
+
var ALLOWED_INLINE_TAGS = /* @__PURE__ */ new Set(["A", "B", "STRONG", "I", "EM", "BR", "SPAN"]);
|
|
4020
|
+
var ALLOWED_ATTRS_BY_TAG = {
|
|
4021
|
+
A: /* @__PURE__ */ new Set(["href", "target", "rel", "class"])
|
|
4058
4022
|
};
|
|
4059
|
-
var
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4023
|
+
var COMMON_ALLOWED_ATTRS = /* @__PURE__ */ new Set(["class"]);
|
|
4024
|
+
var SAFE_HREF_RE = /^(https?:|mailto:|tel:|\/|#|\.)/i;
|
|
4025
|
+
var DROP_CONTENT_TAGS = /* @__PURE__ */ new Set([
|
|
4026
|
+
"SCRIPT",
|
|
4027
|
+
"STYLE",
|
|
4028
|
+
"IFRAME",
|
|
4029
|
+
"OBJECT",
|
|
4030
|
+
"EMBED",
|
|
4031
|
+
"META",
|
|
4032
|
+
"LINK",
|
|
4033
|
+
"BASE",
|
|
4034
|
+
"NOSCRIPT",
|
|
4035
|
+
// SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
|
|
4036
|
+
// 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
|
|
4037
|
+
"SVG",
|
|
4038
|
+
"MATH",
|
|
4039
|
+
"TEMPLATE"
|
|
4040
|
+
]);
|
|
4041
|
+
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4042
|
+
var sanitizeNode = (node) => {
|
|
4043
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
4044
|
+
node.remove();
|
|
4045
|
+
return;
|
|
4046
|
+
}
|
|
4047
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
4048
|
+
const element = node;
|
|
4049
|
+
const tagName = element.tagName.toUpperCase();
|
|
4050
|
+
if (DROP_CONTENT_TAGS.has(tagName)) {
|
|
4051
|
+
element.remove();
|
|
4052
|
+
return;
|
|
4053
|
+
}
|
|
4054
|
+
Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
|
|
4055
|
+
if (ALLOWED_INLINE_TAGS.has(tagName)) {
|
|
4056
|
+
if (element.hasAttribute("className")) {
|
|
4057
|
+
const val = element.getAttribute("className");
|
|
4058
|
+
element.removeAttribute("className");
|
|
4059
|
+
if (!element.hasAttribute("class")) element.setAttribute("class", val);
|
|
4067
4060
|
}
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
}
|
|
4061
|
+
const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
|
|
4062
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
4063
|
+
if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
|
|
4072
4064
|
});
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4065
|
+
if (tagName === "A") {
|
|
4066
|
+
const href = element.getAttribute("href");
|
|
4067
|
+
if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
|
|
4068
|
+
if (element.hasAttribute("target")) {
|
|
4069
|
+
element.setAttribute("rel", "noopener noreferrer");
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
const parent = element.parentNode;
|
|
4075
|
+
if (parent == null) return;
|
|
4076
|
+
while (element.firstChild) parent.insertBefore(element.firstChild, element);
|
|
4077
|
+
parent.removeChild(element);
|
|
4078
|
+
};
|
|
4079
|
+
var sanitizeInlineHtml = (value) => {
|
|
4080
|
+
if (typeof document === "undefined") return escapeHtml(value);
|
|
4081
|
+
const template = document.createElement("template");
|
|
4082
|
+
template.innerHTML = value;
|
|
4083
|
+
Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
|
|
4084
|
+
return template.innerHTML;
|
|
4085
|
+
};
|
|
4086
|
+
var HIDE_DELAY_MS = 100;
|
|
4087
|
+
function useBody(content, message = []) {
|
|
4088
|
+
if (content != null) return content;
|
|
4089
|
+
if (message.length === 0) return null;
|
|
4090
|
+
const singleLine = message.length === 1;
|
|
4091
|
+
return /* @__PURE__ */ jsx(Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsx(
|
|
4087
4092
|
"div",
|
|
4088
4093
|
{
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
),
|
|
4095
|
-
...rest,
|
|
4096
|
-
children: showDivider ? withDividers(children) : children
|
|
4097
|
-
}
|
|
4098
|
-
);
|
|
4099
|
-
});
|
|
4100
|
-
var SList2 = /* @__PURE__ */ withDisplayName(SListImpl, "SList");
|
|
4101
|
-
var DraggableGroupContext = /* @__PURE__ */ createContext(null);
|
|
4102
|
-
function useSDraggableGroup() {
|
|
4103
|
-
return useContext(DraggableGroupContext);
|
|
4094
|
+
className: singleLine ? "leading-[24px]" : void 0,
|
|
4095
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(line) }
|
|
4096
|
+
},
|
|
4097
|
+
i
|
|
4098
|
+
)) });
|
|
4104
4099
|
}
|
|
4105
|
-
function
|
|
4100
|
+
var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
4101
|
+
content,
|
|
4102
|
+
message = [],
|
|
4103
|
+
open: openProp,
|
|
4104
|
+
onOpenChange,
|
|
4105
|
+
trigger = "hover",
|
|
4106
|
+
placement = "top",
|
|
4107
|
+
sideOffset = 8,
|
|
4108
|
+
tooltipType = "default",
|
|
4109
|
+
showClose = false,
|
|
4110
|
+
disabled = false,
|
|
4106
4111
|
children,
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
const
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4112
|
+
icon = "helpOutline",
|
|
4113
|
+
iconSize = 12,
|
|
4114
|
+
color = "#01BB4B",
|
|
4115
|
+
ariaLabel,
|
|
4116
|
+
className,
|
|
4117
|
+
triggerClassName,
|
|
4118
|
+
style,
|
|
4119
|
+
contentProps
|
|
4120
|
+
}, ref) {
|
|
4121
|
+
const portalContainer = usePortalContainer();
|
|
4122
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
4123
|
+
const isControlled = openProp !== void 0;
|
|
4124
|
+
const open = isControlled ? openProp : internalOpen;
|
|
4125
|
+
const hideTimer = useRef(void 0);
|
|
4126
|
+
const cancelHide = useCallback(() => {
|
|
4127
|
+
if (hideTimer.current) {
|
|
4128
|
+
clearTimeout(hideTimer.current);
|
|
4129
|
+
hideTimer.current = void 0;
|
|
4130
|
+
}
|
|
4131
|
+
}, []);
|
|
4132
|
+
const setOpenState = useCallback(
|
|
4133
|
+
(next) => {
|
|
4134
|
+
if (!isControlled) setInternalOpen(next);
|
|
4135
|
+
onOpenChange?.(next);
|
|
4123
4136
|
},
|
|
4124
|
-
[]
|
|
4137
|
+
[isControlled, onOpenChange]
|
|
4125
4138
|
);
|
|
4126
|
-
const
|
|
4127
|
-
(
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4139
|
+
const openNow = () => {
|
|
4140
|
+
cancelHide();
|
|
4141
|
+
setOpenState(true);
|
|
4142
|
+
};
|
|
4143
|
+
const startHide = () => {
|
|
4144
|
+
if (showClose) return;
|
|
4145
|
+
cancelHide();
|
|
4146
|
+
hideTimer.current = setTimeout(() => setOpenState(false), HIDE_DELAY_MS);
|
|
4147
|
+
};
|
|
4148
|
+
useImperativeHandle(
|
|
4149
|
+
ref,
|
|
4150
|
+
() => ({
|
|
4151
|
+
show: () => {
|
|
4152
|
+
cancelHide();
|
|
4153
|
+
setOpenState(true);
|
|
4154
|
+
},
|
|
4155
|
+
hide: () => {
|
|
4156
|
+
cancelHide();
|
|
4157
|
+
setOpenState(false);
|
|
4158
|
+
}
|
|
4159
|
+
}),
|
|
4160
|
+
[cancelHide, setOpenState]
|
|
4133
4161
|
);
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4162
|
+
const isHover = trigger === "hover";
|
|
4163
|
+
const isNone = trigger === "none";
|
|
4164
|
+
if (isNone && children == null && typeof console !== "undefined") {
|
|
4165
|
+
console.warn(
|
|
4166
|
+
'[STooltip] trigger="none" \uC740 \uC704\uCE58 \uAE30\uC900\uC774 \uB420 children \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC544\uC774\uCF58 \uD2B8\uB9AC\uAC70\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.'
|
|
4167
|
+
);
|
|
4168
|
+
}
|
|
4169
|
+
const body = useBody(content, message);
|
|
4170
|
+
const bg = `var(--cmp-tooltip-${tooltipType}-bg)`;
|
|
4171
|
+
const fg = `var(--cmp-tooltip-${tooltipType}-content)`;
|
|
4172
|
+
const triggerNode = children ?? /* @__PURE__ */ jsx("span", { className: cn("inline-flex cursor-pointer", triggerClassName), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(SIcon, { name: icon, size: iconSize, color }) });
|
|
4173
|
+
if (disabled || body == null) return /* @__PURE__ */ jsx(Fragment, { children: triggerNode });
|
|
4174
|
+
const {
|
|
4175
|
+
className: contentPropsClassName,
|
|
4176
|
+
style: contentPropsStyle,
|
|
4177
|
+
...restContentProps
|
|
4178
|
+
} = contentProps ?? {};
|
|
4179
|
+
const contentClass = cn(
|
|
4180
|
+
"z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
|
|
4181
|
+
FLOATING_SLIDE_ANIM,
|
|
4182
|
+
className,
|
|
4183
|
+
contentPropsClassName
|
|
4184
|
+
);
|
|
4185
|
+
const contentStyle = {
|
|
4186
|
+
background: bg,
|
|
4187
|
+
color: fg,
|
|
4188
|
+
fontWeight: tooltipType === "default" ? 500 : 700,
|
|
4189
|
+
...style,
|
|
4190
|
+
...contentPropsStyle
|
|
4191
|
+
};
|
|
4192
|
+
return /* @__PURE__ */ jsxs(RPopover12.Root, { open, onOpenChange: setOpenState, children: [
|
|
4193
|
+
isNone ? (
|
|
4194
|
+
// 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
|
|
4195
|
+
// mouse/focus 핸들러가 없으므로 showClose 없이도 자동 닫힘이 발생하지 않는다.
|
|
4196
|
+
/* @__PURE__ */ jsx(RPopover12.Anchor, { asChild: true, children: triggerNode })
|
|
4197
|
+
) : isHover ? (
|
|
4198
|
+
// hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
|
|
4199
|
+
/* @__PURE__ */ jsx(RPopover12.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
4200
|
+
"span",
|
|
4201
|
+
{
|
|
4202
|
+
className: "inline-flex",
|
|
4203
|
+
onMouseEnter: openNow,
|
|
4204
|
+
onMouseLeave: startHide,
|
|
4205
|
+
onFocus: openNow,
|
|
4206
|
+
onBlur: startHide,
|
|
4207
|
+
children: triggerNode
|
|
4208
|
+
}
|
|
4209
|
+
) })
|
|
4210
|
+
) : /* @__PURE__ */ jsx(RPopover12.Trigger, { asChild: true, children: triggerNode }),
|
|
4211
|
+
/* @__PURE__ */ jsx(RPopover12.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxs(
|
|
4212
|
+
RPopover12.Content,
|
|
4213
|
+
{
|
|
4214
|
+
side: placement,
|
|
4215
|
+
sideOffset,
|
|
4216
|
+
className: contentClass,
|
|
4217
|
+
style: contentStyle,
|
|
4218
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
4219
|
+
onInteractOutside: (e) => {
|
|
4220
|
+
if (showClose || isNone) e.preventDefault();
|
|
4221
|
+
},
|
|
4222
|
+
onEscapeKeyDown: (e) => {
|
|
4223
|
+
if (showClose || isNone) e.preventDefault();
|
|
4224
|
+
},
|
|
4225
|
+
onMouseEnter: isHover ? cancelHide : void 0,
|
|
4226
|
+
onMouseLeave: isHover ? startHide : void 0,
|
|
4227
|
+
...restContentProps,
|
|
4228
|
+
children: [
|
|
4229
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-[12px]", children: [
|
|
4230
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: body }),
|
|
4231
|
+
showClose && !isNone && /* @__PURE__ */ jsx(
|
|
4232
|
+
SGhostButton,
|
|
4233
|
+
{
|
|
4234
|
+
icon: "close",
|
|
4235
|
+
size: "xs",
|
|
4236
|
+
intent: tooltipType === "default" ? "inverse" : "default",
|
|
4237
|
+
ariaLabel: "\uB2EB\uAE30",
|
|
4238
|
+
className: "shrink-0",
|
|
4239
|
+
onClick: () => {
|
|
4240
|
+
cancelHide();
|
|
4241
|
+
setOpenState(false);
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
)
|
|
4245
|
+
] }),
|
|
4246
|
+
/* @__PURE__ */ jsx(RPopover12.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
4247
|
+
]
|
|
4248
|
+
}
|
|
4249
|
+
) })
|
|
4250
|
+
] });
|
|
4251
|
+
});
|
|
4252
|
+
var STooltip2 = /* @__PURE__ */ withDisplayName(STooltipImpl, "STooltip");
|
|
4253
|
+
function runRules(value, rules) {
|
|
4254
|
+
if (!rules || rules.length === 0) return "";
|
|
4255
|
+
for (const rule of rules) {
|
|
4256
|
+
const result = rule(value ?? "");
|
|
4257
|
+
if (result !== true) return typeof result === "string" ? result : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC12\uC785\uB2C8\uB2E4.";
|
|
4258
|
+
}
|
|
4259
|
+
return "";
|
|
4260
|
+
}
|
|
4261
|
+
var FormContext = /* @__PURE__ */ createContext(null);
|
|
4262
|
+
function useFormContext() {
|
|
4263
|
+
return useContext(FormContext);
|
|
4264
|
+
}
|
|
4265
|
+
function useFormField(field) {
|
|
4266
|
+
const ctx = useFormContext();
|
|
4267
|
+
const cbRef = useRef(field);
|
|
4268
|
+
cbRef.current = field;
|
|
4269
|
+
const name = field.name ?? "";
|
|
4270
|
+
useEffect(() => {
|
|
4271
|
+
if (!ctx) return;
|
|
4272
|
+
return ctx.register({
|
|
4273
|
+
name,
|
|
4274
|
+
validate: () => cbRef.current.validate(),
|
|
4275
|
+
resetValidation: () => cbRef.current.resetValidation()
|
|
4276
|
+
});
|
|
4277
|
+
}, [ctx, name]);
|
|
4278
|
+
}
|
|
4279
|
+
var FIELD_SIZE = {
|
|
4280
|
+
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
4281
|
+
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
4282
|
+
};
|
|
4283
|
+
var ALIGN = {
|
|
4284
|
+
start: "flex-start",
|
|
4285
|
+
center: "center",
|
|
4286
|
+
end: "flex-end"
|
|
4287
|
+
};
|
|
4288
|
+
var FOCUS_RING_SHADOW = "0px 0px 4px 0px #0071ff66";
|
|
4289
|
+
var cssLen = (v) => v === void 0 || v === "" || v === 0 ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
4290
|
+
var SField = /* @__PURE__ */ forwardRef(function SField2({
|
|
4291
|
+
name,
|
|
4292
|
+
label = "",
|
|
4293
|
+
icon,
|
|
4294
|
+
iconColor,
|
|
4295
|
+
labelTooltip = "",
|
|
4296
|
+
labelTooltipProps,
|
|
4297
|
+
labelWidth,
|
|
4298
|
+
labelHeight,
|
|
4299
|
+
size = "sm",
|
|
4300
|
+
addonLabel = "",
|
|
4301
|
+
addonAlign = "start",
|
|
4302
|
+
error = false,
|
|
4303
|
+
errorMessage = "",
|
|
4304
|
+
status,
|
|
4305
|
+
focused = false,
|
|
4306
|
+
hovered = false,
|
|
4307
|
+
rules: _rules,
|
|
4308
|
+
hint = "",
|
|
4309
|
+
disabled = false,
|
|
4310
|
+
readOnly = false,
|
|
4311
|
+
width,
|
|
4312
|
+
minWidth,
|
|
4313
|
+
maxWidth,
|
|
4314
|
+
multiline = false,
|
|
4315
|
+
borderless = false,
|
|
4316
|
+
children,
|
|
4317
|
+
className,
|
|
4318
|
+
style,
|
|
4319
|
+
onMouseEnter,
|
|
4320
|
+
onMouseLeave
|
|
4321
|
+
}, ref) {
|
|
4322
|
+
const rootRef = useRef(null);
|
|
4323
|
+
useImperativeHandle(
|
|
4324
|
+
ref,
|
|
4325
|
+
() => ({
|
|
4326
|
+
focus: () => {
|
|
4327
|
+
const root = rootRef.current;
|
|
4328
|
+
if (!root) return;
|
|
4329
|
+
const focusable = root.querySelector(
|
|
4330
|
+
"input,textarea,select,button,[tabindex]"
|
|
4331
|
+
);
|
|
4332
|
+
focusable?.focus();
|
|
4333
|
+
root.scrollIntoView({ block: "nearest" });
|
|
4334
|
+
}
|
|
4335
|
+
}),
|
|
4336
|
+
[]
|
|
4337
|
+
);
|
|
4338
|
+
const s = FIELD_SIZE[size];
|
|
4339
|
+
if (label !== "" && addonLabel !== "" && typeof console !== "undefined") {
|
|
4340
|
+
console.warn(
|
|
4341
|
+
"[SField] label \uACFC addonLabel \uC740 \uD568\uAED8 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. addonLabel \uC744 \uBB34\uC2DC\uD569\uB2C8\uB2E4."
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
const effectiveAddonLabel = label !== "" ? "" : addonLabel;
|
|
4345
|
+
const resolvedError = status === "error" || status === void 0 && error;
|
|
4346
|
+
const resolvedSuccess = status === "pass";
|
|
4347
|
+
const showError = resolvedError && errorMessage !== "";
|
|
4348
|
+
const interactive = !disabled && !readOnly;
|
|
4349
|
+
const isPercentWidth = typeof width === "string" && width.trim().endsWith("%");
|
|
4350
|
+
const resolvedWidth = fieldWidthValue(width);
|
|
4351
|
+
const hug = resolvedWidth !== void 0 && !isPercentWidth;
|
|
4352
|
+
const addonWidth = effectiveAddonLabel !== "" ? cssLen(labelWidth) : void 0;
|
|
4353
|
+
const maxWidthValue = fieldWidthValue(maxWidth);
|
|
4354
|
+
const resolvedMaxWidth = maxWidthValue === void 0 || effectiveAddonLabel === "" ? maxWidthValue : addonWidth ? `calc(${maxWidthValue} + ${addonWidth})` : void 0;
|
|
4355
|
+
const borderColor = borderless ? "transparent" : disabled ? "var(--color-grey-45)" : (
|
|
4356
|
+
// focus·hover(제어 prop) 가 error/pass 보다 우선 — 실제 :hover/:focus-within 클래스도
|
|
4357
|
+
// 같은 순서로 --field-bc 를 덮으므로, prop 으로 흉내 낸 상태도 그와 같게 둔다.
|
|
4358
|
+
interactive && (focused || hovered) ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)"
|
|
4359
|
+
);
|
|
4360
|
+
const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
|
|
4361
|
+
const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
|
|
4362
|
+
return /* @__PURE__ */ jsx(
|
|
4363
|
+
"div",
|
|
4364
|
+
{
|
|
4365
|
+
ref: rootRef,
|
|
4366
|
+
"data-name": name || void 0,
|
|
4367
|
+
className: cn(
|
|
4368
|
+
"h-fit flex-col",
|
|
4369
|
+
// hug 시 inline-flex 를 유지하면 기존에 세로로 쌓여 있던 필드들이 한 줄에 붙어버리므로
|
|
4370
|
+
// 블록 레벨(flex)로 두어 쌓임은 그대로 유지한다. 나란히 놓으려면 부모를 flex 로.
|
|
4371
|
+
hug ? "flex w-fit max-w-full" : "inline-flex w-full",
|
|
4372
|
+
className
|
|
4373
|
+
),
|
|
4374
|
+
style,
|
|
4375
|
+
onMouseEnter,
|
|
4376
|
+
onMouseLeave,
|
|
4377
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-start", children: [
|
|
4378
|
+
label !== "" && /* @__PURE__ */ jsxs(
|
|
4379
|
+
"div",
|
|
4380
|
+
{
|
|
4381
|
+
className: "flex shrink-0 items-center font-bold text-(--sys-color-field-text-default)",
|
|
4382
|
+
style: {
|
|
4383
|
+
height: cssLen(labelHeight) ?? s.height,
|
|
4384
|
+
marginRight: s.fieldGap,
|
|
4385
|
+
width: cssLen(labelWidth),
|
|
4386
|
+
fontSize: s.fontSize,
|
|
4387
|
+
lineHeight: `${s.lineHeight}px`
|
|
4388
|
+
},
|
|
4389
|
+
children: [
|
|
4390
|
+
icon && /* @__PURE__ */ jsx(
|
|
4391
|
+
SIcon,
|
|
4392
|
+
{
|
|
4393
|
+
name: icon,
|
|
4394
|
+
size: s.icon,
|
|
4395
|
+
color: iconColor,
|
|
4396
|
+
style: { marginRight: s.labelGap }
|
|
4397
|
+
}
|
|
4398
|
+
),
|
|
4399
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
4400
|
+
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0 flex items-center", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
4401
|
+
STooltip2,
|
|
4402
|
+
{
|
|
4403
|
+
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
4404
|
+
iconSize: s.icon,
|
|
4405
|
+
...labelTooltipProps
|
|
4406
|
+
}
|
|
4407
|
+
) })
|
|
4408
|
+
]
|
|
4409
|
+
}
|
|
4410
|
+
),
|
|
4411
|
+
/* @__PURE__ */ jsxs(
|
|
4412
|
+
"div",
|
|
4413
|
+
{
|
|
4414
|
+
className: cn("flex min-w-0 flex-col", !hug && !isPercentWidth && "flex-1"),
|
|
4415
|
+
style: {
|
|
4416
|
+
width: resolvedWidth,
|
|
4417
|
+
minWidth: fieldWidthValue(minWidth),
|
|
4418
|
+
maxWidth: resolvedMaxWidth
|
|
4419
|
+
},
|
|
4420
|
+
children: [
|
|
4421
|
+
/* @__PURE__ */ jsxs(
|
|
4422
|
+
"div",
|
|
4423
|
+
{
|
|
4424
|
+
className: cn(
|
|
4425
|
+
"relative box-border flex min-w-0 items-stretch border border-solid border-(--field-bc)",
|
|
4426
|
+
// 둘 다 넘친 것을 잘라 내지만 clip 은 스크롤 상자를 만들지 않는다. hidden 이면
|
|
4427
|
+
// 이 상자가 스크롤포트가 되어 안쪽의 position:sticky 가 페이지 스크롤을 따라가지
|
|
4428
|
+
// 못한다 (SEditor 의 고정 툴바). 여러 줄 필드에서만 바꿔 파급을 좁힌다.
|
|
4429
|
+
multiline ? "overflow-clip" : "overflow-hidden",
|
|
4430
|
+
interactive && !borderless && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
|
|
4431
|
+
disabled && "cursor-not-allowed"
|
|
4432
|
+
),
|
|
4433
|
+
style: {
|
|
4434
|
+
// @ts-expect-error CSS 변수
|
|
4435
|
+
"--field-bc": borderColor,
|
|
4436
|
+
// focused/hovered prop이 명시된 경우 강조를 즉시 반영
|
|
4437
|
+
...interactive && !borderless && (focused || hovered) ? { boxShadow: FOCUS_RING_SHADOW } : {},
|
|
4438
|
+
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
4439
|
+
"borderRadius": s.radius,
|
|
4440
|
+
"background": bgColor,
|
|
4441
|
+
"color": textColor
|
|
4442
|
+
},
|
|
4443
|
+
"data-focused": focused || void 0,
|
|
4444
|
+
"data-hovered": hovered || void 0,
|
|
4445
|
+
children: [
|
|
4446
|
+
effectiveAddonLabel !== "" && /* @__PURE__ */ jsxs(
|
|
4447
|
+
"div",
|
|
4448
|
+
{
|
|
4449
|
+
className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-sd-20",
|
|
4450
|
+
style: {
|
|
4451
|
+
// 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
|
|
4452
|
+
width: cssLen(labelWidth),
|
|
4453
|
+
justifyContent: ALIGN[addonAlign],
|
|
4454
|
+
background: "var(--cmp-field-addonLabel-bg)",
|
|
4455
|
+
borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
|
|
4456
|
+
borderTopLeftRadius: s.radius - 1,
|
|
4457
|
+
borderBottomLeftRadius: s.radius - 1
|
|
4458
|
+
},
|
|
4459
|
+
children: [
|
|
4460
|
+
icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: iconColor }),
|
|
4461
|
+
effectiveAddonLabel
|
|
4462
|
+
]
|
|
4463
|
+
}
|
|
4464
|
+
),
|
|
4465
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 flex-1", multiline && "bg-inherit"), children })
|
|
4466
|
+
]
|
|
4467
|
+
}
|
|
4468
|
+
),
|
|
4469
|
+
showError ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) text-12 font-normal leading-sd-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) px-(--cmp-field-message-paddingX) text-12 font-normal leading-sd-20 text-(--cmp-field-hint-color)", children: hint }) : null
|
|
4470
|
+
]
|
|
4471
|
+
}
|
|
4472
|
+
)
|
|
4473
|
+
] })
|
|
4474
|
+
}
|
|
4475
|
+
);
|
|
4476
|
+
});
|
|
4477
|
+
|
|
4478
|
+
// src/lib/autofill.ts
|
|
4479
|
+
var AUTOFILL_RESET_CLASS = "autofill:[-webkit-text-fill-color:currentColor] autofill:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] autofill:[transition:background-color_5000s_ease-in-out_0s] [&:-webkit-autofill]:[-webkit-text-fill-color:currentColor] [&:-webkit-autofill]:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] [&:-webkit-autofill]:[transition:background-color_5000s_ease-in-out_0s]";
|
|
4480
|
+
var TEXTAREA_SIZE = {
|
|
4481
|
+
sm: {
|
|
4482
|
+
fontSize: 12,
|
|
4483
|
+
lineHeight: 20,
|
|
4484
|
+
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
4485
|
+
paddingY: "var(--cmp-textinput-sm-paddingY)"
|
|
4486
|
+
},
|
|
4487
|
+
md: {
|
|
4488
|
+
fontSize: 14,
|
|
4489
|
+
lineHeight: 24,
|
|
4490
|
+
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
4491
|
+
paddingY: "var(--cmp-textinput-md-paddingY)"
|
|
4492
|
+
}
|
|
4493
|
+
};
|
|
4494
|
+
var MIN_ROWS = 2;
|
|
4495
|
+
var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
4496
|
+
value,
|
|
4497
|
+
onValueChange,
|
|
4498
|
+
onChange,
|
|
4499
|
+
size = "sm",
|
|
4500
|
+
rows = MIN_ROWS,
|
|
4501
|
+
autogrow = false,
|
|
4502
|
+
maxRows,
|
|
4503
|
+
rules,
|
|
4504
|
+
status,
|
|
4505
|
+
focused,
|
|
4506
|
+
hovered,
|
|
4507
|
+
textareaClassName,
|
|
4508
|
+
textareaStyle,
|
|
4509
|
+
label,
|
|
4510
|
+
labelWidth,
|
|
4511
|
+
icon,
|
|
4512
|
+
iconColor,
|
|
4513
|
+
labelTooltip,
|
|
4514
|
+
labelTooltipProps,
|
|
4515
|
+
addonLabel,
|
|
4516
|
+
addonAlign,
|
|
4517
|
+
hint,
|
|
4518
|
+
error,
|
|
4519
|
+
errorMessage,
|
|
4520
|
+
width,
|
|
4521
|
+
disabled = false,
|
|
4522
|
+
readOnly = false,
|
|
4523
|
+
placeholder = "\uC785\uB825\uD574 \uC8FC\uC138\uC694.",
|
|
4524
|
+
onBlur,
|
|
4525
|
+
className,
|
|
4526
|
+
style,
|
|
4527
|
+
...rest
|
|
4528
|
+
}, ref) {
|
|
4529
|
+
const p = TEXTAREA_SIZE[size];
|
|
4530
|
+
const heightForRows = (n) => `calc(${p.lineHeight * n}px + ${p.paddingY} * 2)`;
|
|
4531
|
+
const minHeight = heightForRows(MIN_ROWS);
|
|
4532
|
+
const maxHeight = autogrow && maxRows != null ? heightForRows(maxRows) : void 0;
|
|
4533
|
+
const [ruleError, setRuleError] = useState("");
|
|
4534
|
+
const innerRef = useRef(null);
|
|
4535
|
+
const setRefs2 = useCallback(
|
|
4536
|
+
(node) => {
|
|
4537
|
+
innerRef.current = node;
|
|
4538
|
+
if (typeof ref === "function") ref(node);
|
|
4539
|
+
else if (ref) ref.current = node;
|
|
4540
|
+
},
|
|
4541
|
+
[ref]
|
|
4542
|
+
);
|
|
4543
|
+
useLayoutEffect(() => {
|
|
4544
|
+
const el = innerRef.current;
|
|
4545
|
+
if (el == null) return;
|
|
4546
|
+
if (!autogrow) {
|
|
4547
|
+
el.style.height = "";
|
|
4548
|
+
return;
|
|
4549
|
+
}
|
|
4550
|
+
el.style.height = "auto";
|
|
4551
|
+
el.style.height = `${el.scrollHeight}px`;
|
|
4552
|
+
}, [autogrow, maxHeight, minHeight, rows, value]);
|
|
4553
|
+
useFormField({
|
|
4554
|
+
name: rest.name,
|
|
4555
|
+
validate: () => {
|
|
4556
|
+
const msg = runRules(value, rules);
|
|
4557
|
+
setRuleError(msg);
|
|
4558
|
+
return msg === "";
|
|
4559
|
+
},
|
|
4560
|
+
resetValidation: () => setRuleError("")
|
|
4561
|
+
});
|
|
4562
|
+
const resolvedError = error || ruleError !== "";
|
|
4563
|
+
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
4564
|
+
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
4565
|
+
return /* @__PURE__ */ jsx(
|
|
4566
|
+
SField,
|
|
4567
|
+
{
|
|
4568
|
+
label,
|
|
4569
|
+
labelWidth,
|
|
4570
|
+
icon,
|
|
4571
|
+
iconColor,
|
|
4572
|
+
labelTooltip,
|
|
4573
|
+
labelTooltipProps,
|
|
4574
|
+
addonLabel,
|
|
4575
|
+
addonAlign,
|
|
4576
|
+
hint,
|
|
4577
|
+
size,
|
|
4578
|
+
error: resolvedError,
|
|
4579
|
+
status: resolvedStatus,
|
|
4580
|
+
focused,
|
|
4581
|
+
hovered,
|
|
4582
|
+
errorMessage: resolvedErrorMessage,
|
|
4583
|
+
width,
|
|
4584
|
+
disabled,
|
|
4585
|
+
readOnly,
|
|
4586
|
+
multiline: true,
|
|
4587
|
+
className,
|
|
4588
|
+
style,
|
|
4589
|
+
children: /* @__PURE__ */ jsx(
|
|
4590
|
+
"textarea",
|
|
4591
|
+
{
|
|
4592
|
+
ref: setRefs2,
|
|
4593
|
+
value: value ?? "",
|
|
4594
|
+
rows,
|
|
4595
|
+
disabled,
|
|
4596
|
+
readOnly,
|
|
4597
|
+
placeholder,
|
|
4598
|
+
onChange: (e) => {
|
|
4599
|
+
onChange?.(e);
|
|
4600
|
+
onValueChange?.(e.target.value);
|
|
4601
|
+
if (ruleError !== "") setRuleError(runRules(e.target.value, rules));
|
|
4602
|
+
},
|
|
4603
|
+
onBlur: (e) => {
|
|
4604
|
+
onBlur?.(e);
|
|
4605
|
+
if (rules && rules.length > 0) setRuleError(runRules(e.target.value, rules));
|
|
4606
|
+
},
|
|
4607
|
+
className: cn(
|
|
4608
|
+
"w-full border-0 bg-transparent outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed",
|
|
4609
|
+
// autogrow 와 끌어서 늘리기는 같은 높이를 두고 다투므로 함께 두지 않는다
|
|
4610
|
+
autogrow ? "resize-none" : "resize-y",
|
|
4611
|
+
AUTOFILL_RESET_CLASS,
|
|
4612
|
+
textareaClassName
|
|
4613
|
+
),
|
|
4614
|
+
style: {
|
|
4615
|
+
minHeight,
|
|
4616
|
+
maxHeight,
|
|
4617
|
+
// 상한이 있으면 거기 닿았을 때 안에서 스크롤한다. 상한이 없으면 높이가 늘 내용과
|
|
4618
|
+
// 같으므로 스크롤바가 나올 일이 없고, 반올림으로 1px 이 넘쳐 깜빡이는 것만 막는다.
|
|
4619
|
+
overflowY: autogrow ? maxRows != null ? "auto" : "hidden" : void 0,
|
|
4620
|
+
padding: `${p.paddingY} ${p.paddingX}`,
|
|
4621
|
+
fontSize: p.fontSize,
|
|
4622
|
+
lineHeight: `${p.lineHeight}px`,
|
|
4623
|
+
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
4624
|
+
...textareaStyle
|
|
4625
|
+
},
|
|
4626
|
+
...rest
|
|
4627
|
+
}
|
|
4628
|
+
)
|
|
4629
|
+
}
|
|
4630
|
+
);
|
|
4631
|
+
});
|
|
4632
|
+
var DEFAULT_PLACEHOLDER = "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD574 \uC8FC\uC138\uC694...";
|
|
4633
|
+
var FIELD_MIN_HEIGHT = 48;
|
|
4634
|
+
var FIELD_BORDER = 1;
|
|
4635
|
+
var TEXTAREA_MIN_HEIGHT = FIELD_MIN_HEIGHT - FIELD_BORDER * 2;
|
|
4636
|
+
var BUTTON_BOTTOM_INSET = `calc((${FIELD_MIN_HEIGHT}px - var(--cmp-ghostButton-md-size)) / 2)`;
|
|
4637
|
+
var DEFAULT_MAX_ROWS = 5;
|
|
4638
|
+
var SChatInputImpl = /* @__PURE__ */ forwardRef(function SChatInput({
|
|
4639
|
+
value = "",
|
|
4640
|
+
onValueChange,
|
|
4641
|
+
placeholder = DEFAULT_PLACEHOLDER,
|
|
4642
|
+
disabled = false,
|
|
4643
|
+
onSend,
|
|
4644
|
+
onAttach,
|
|
4645
|
+
busy = false,
|
|
4646
|
+
onStop,
|
|
4647
|
+
footerAction,
|
|
4648
|
+
maxRows = DEFAULT_MAX_ROWS,
|
|
4649
|
+
className,
|
|
4650
|
+
style,
|
|
4651
|
+
textareaClassName,
|
|
4652
|
+
...rest
|
|
4653
|
+
}, ref) {
|
|
4654
|
+
const canSend = !disabled && !busy && value.trim() !== "";
|
|
4655
|
+
const send = useCallback(() => {
|
|
4656
|
+
if (!canSend) return;
|
|
4657
|
+
onSend?.(value);
|
|
4658
|
+
}, [canSend, onSend, value]);
|
|
4659
|
+
const handleKeyDown = (e) => {
|
|
4660
|
+
rest.onKeyDown?.(e);
|
|
4661
|
+
if (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing) return;
|
|
4662
|
+
e.preventDefault();
|
|
4663
|
+
send();
|
|
4664
|
+
};
|
|
4665
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col bg-(--sys-color-field-bg-default)", className), style, children: [
|
|
4666
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-sd-8 p-sd-12", children: [
|
|
4667
|
+
onAttach != null && /* @__PURE__ */ jsx(
|
|
4668
|
+
SGhostButton,
|
|
4669
|
+
{
|
|
4670
|
+
icon: "attachFile",
|
|
4671
|
+
size: "md",
|
|
4672
|
+
ariaLabel: "\uD30C\uC77C \uCCA8\uBD80",
|
|
4673
|
+
disabled,
|
|
4674
|
+
onClick: onAttach,
|
|
4675
|
+
style: { marginBottom: BUTTON_BOTTOM_INSET }
|
|
4676
|
+
}
|
|
4677
|
+
),
|
|
4678
|
+
/* @__PURE__ */ jsx(
|
|
4679
|
+
STextarea,
|
|
4680
|
+
{
|
|
4681
|
+
ref,
|
|
4682
|
+
size: "md",
|
|
4683
|
+
rows: 1,
|
|
4684
|
+
autogrow: true,
|
|
4685
|
+
maxRows,
|
|
4686
|
+
width: "100%",
|
|
4687
|
+
value,
|
|
4688
|
+
onValueChange,
|
|
4689
|
+
placeholder,
|
|
4690
|
+
disabled,
|
|
4691
|
+
className: "min-w-0 flex-1",
|
|
4692
|
+
textareaClassName,
|
|
4693
|
+
textareaStyle: { minHeight: TEXTAREA_MIN_HEIGHT },
|
|
4694
|
+
...rest,
|
|
4695
|
+
onKeyDown: handleKeyDown
|
|
4696
|
+
}
|
|
4697
|
+
),
|
|
4698
|
+
busy ? /* @__PURE__ */ jsx(
|
|
4699
|
+
SGhostButton,
|
|
4700
|
+
{
|
|
4701
|
+
icon: "stop",
|
|
4702
|
+
size: "md",
|
|
4703
|
+
intent: "danger",
|
|
4704
|
+
ariaLabel: "\uC751\uB2F5 \uC911\uC9C0",
|
|
4705
|
+
onClick: onStop,
|
|
4706
|
+
style: { marginBottom: BUTTON_BOTTOM_INSET }
|
|
4707
|
+
}
|
|
4708
|
+
) : /* @__PURE__ */ jsx(
|
|
4709
|
+
SGhostButton,
|
|
4710
|
+
{
|
|
4711
|
+
icon: "send",
|
|
4712
|
+
size: "md",
|
|
4713
|
+
intent: "subAction",
|
|
4714
|
+
ariaLabel: "\uC804\uC1A1",
|
|
4715
|
+
disabled: !canSend,
|
|
4716
|
+
onClick: send,
|
|
4717
|
+
style: { marginBottom: BUTTON_BOTTOM_INSET }
|
|
4718
|
+
}
|
|
4719
|
+
)
|
|
4720
|
+
] }),
|
|
4721
|
+
footerAction != null && // 보조 액션은 입력창 아래 가운데에 선다 — 주 동작(전송)과 층이 다름을 자리로 드러낸다.
|
|
4722
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center", children: footerAction })
|
|
4723
|
+
] });
|
|
4724
|
+
});
|
|
4725
|
+
var SChatInput2 = /* @__PURE__ */ withDisplayName(SChatInputImpl, "SChatInput");
|
|
4726
|
+
var CHAT_MESSAGE_DIRECTIONS = ["incoming", "outgoing"];
|
|
4727
|
+
var CHAT_MESSAGE_VARIANTS = ["default", "template"];
|
|
4728
|
+
var BUBBLE_SURFACE = {
|
|
4729
|
+
incoming: "bg-(--sys-color-bg-screen) text-(--sys-color-fg-primary)",
|
|
4730
|
+
outgoing: "bg-(--sys-color-bg-brand) text-(--sys-color-fg-inverse)",
|
|
4731
|
+
template: "bg-(--sys-color-bg-accentFaint) text-(--sys-color-fg-deep)"
|
|
4732
|
+
};
|
|
4733
|
+
var CHAT_MESSAGE_READ_STATUSES = ["read", "unread"];
|
|
4734
|
+
var READ_STATUS_LABEL = {
|
|
4735
|
+
read: "\uC77D\uC74C",
|
|
4736
|
+
unread: "\uC548 \uC77D\uC74C"
|
|
4737
|
+
};
|
|
4738
|
+
var READ_STATUS_COLOR = {
|
|
4739
|
+
read: "text-(--sys-color-fg-tertiary)",
|
|
4740
|
+
unread: "text-(--sys-color-fg-warning)"
|
|
4741
|
+
};
|
|
4742
|
+
var AVATAR_SIZE = 32;
|
|
4743
|
+
var AVATAR_ROW_HEIGHT = 40;
|
|
4744
|
+
var AVATAR_ICON_SIZE = 40;
|
|
4745
|
+
function Avatar({ src, alt, placeholder }) {
|
|
4746
|
+
if (placeholder) {
|
|
4747
|
+
return /* @__PURE__ */ jsx("div", { className: "shrink-0", style: { width: AVATAR_SIZE, height: AVATAR_ROW_HEIGHT } });
|
|
4748
|
+
}
|
|
4749
|
+
return /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center", style: { height: AVATAR_ROW_HEIGHT }, children: /* @__PURE__ */ jsx(
|
|
4750
|
+
"div",
|
|
4751
|
+
{
|
|
4752
|
+
className: "relative overflow-hidden rounded-full bg-(--sys-color-bg-screen)",
|
|
4753
|
+
style: { width: AVATAR_SIZE, height: AVATAR_SIZE },
|
|
4754
|
+
children: src != null ? /* @__PURE__ */ jsx(SImage, { src, alt: alt ?? "", fit: "cover", className: "h-full w-full" }) : (
|
|
4755
|
+
// 원 밖으로 나가는 만큼을 좌우로 나눠 가운데를 맞추고, 아래는 원이 자른다.
|
|
4756
|
+
/* @__PURE__ */ jsx(
|
|
4757
|
+
SIcon,
|
|
4758
|
+
{
|
|
4759
|
+
name: "user",
|
|
4760
|
+
size: AVATAR_ICON_SIZE,
|
|
4761
|
+
color: "var(--sys-color-fg-quaternary)",
|
|
4762
|
+
className: "absolute top-0",
|
|
4763
|
+
style: { left: (AVATAR_SIZE - AVATAR_ICON_SIZE) / 2 }
|
|
4764
|
+
}
|
|
4765
|
+
)
|
|
4766
|
+
)
|
|
4767
|
+
}
|
|
4768
|
+
) });
|
|
4769
|
+
}
|
|
4770
|
+
var SChatMessageImpl = /* @__PURE__ */ forwardRef(function SChatMessage({
|
|
4771
|
+
direction = "incoming",
|
|
4772
|
+
sender,
|
|
4773
|
+
time,
|
|
4774
|
+
readStatus,
|
|
4775
|
+
avatarSrc,
|
|
4776
|
+
avatarAlt,
|
|
4777
|
+
continued = false,
|
|
4778
|
+
variant = "default",
|
|
4779
|
+
actions,
|
|
4780
|
+
messages,
|
|
4781
|
+
className,
|
|
4782
|
+
...rest
|
|
4783
|
+
}, ref) {
|
|
4784
|
+
const outgoing = direction === "outgoing";
|
|
4785
|
+
const surface = variant === "template" ? "template" : direction;
|
|
4786
|
+
const bubbles = messages ?? [];
|
|
4787
|
+
return /* @__PURE__ */ jsxs(
|
|
4788
|
+
"div",
|
|
4789
|
+
{
|
|
4790
|
+
ref,
|
|
4791
|
+
className: cn(
|
|
4792
|
+
// 아바타와 본문 열이 같은 줄에 서고, 보낸 메시지는 좌우를 뒤집는다.
|
|
4793
|
+
// items-start 라 이름이 있든 없든 아바타는 언제나 첫 줄에 붙는다.
|
|
4794
|
+
"flex items-start gap-sd-12",
|
|
4795
|
+
outgoing && "flex-row-reverse",
|
|
4796
|
+
className
|
|
4797
|
+
),
|
|
4798
|
+
...rest,
|
|
4799
|
+
children: [
|
|
4800
|
+
!outgoing && /* @__PURE__ */ jsx(Avatar, { src: avatarSrc, alt: avatarAlt, placeholder: continued }),
|
|
4801
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col gap-sd-4", outgoing ? "items-end" : "items-start"), children: [
|
|
4802
|
+
!outgoing && !continued && sender != null && /* @__PURE__ */ jsx("span", { className: "typo-body-sm-default px-sd-8 text-(--sys-color-fg-secondary)", children: sender }),
|
|
4803
|
+
bubbles.length > 0 && // 말풍선끼리는 이름·시각과의 간격(4px)보다 벌려 한 덩어리 안의 여러 발화로 읽히게 한다.
|
|
4804
|
+
/* @__PURE__ */ jsx(
|
|
4805
|
+
"div",
|
|
4806
|
+
{
|
|
4807
|
+
className: cn("flex min-w-0 flex-col gap-sd-8", outgoing ? "items-end" : "items-start"),
|
|
4808
|
+
children: bubbles.map((message, index) => /* @__PURE__ */ jsx(
|
|
4809
|
+
"div",
|
|
4810
|
+
{
|
|
4811
|
+
className: cn(
|
|
4812
|
+
// 라운드 12px 은 대응 토큰이 없어 값으로 둔다 (디자인팀 토큰 추가 요청 대상).
|
|
4813
|
+
"typo-body-md-default max-w-full rounded-[12px] px-sd-16 py-sd-8",
|
|
4814
|
+
// 한글은 기본 규칙으로 두면 어절 한가운데서도 줄이 바뀐다 — 띄어쓰기에서만 끊고,
|
|
4815
|
+
// 끊을 자리가 없는 긴 토큰(URL·주문번호)만 흘려보낸다.
|
|
4816
|
+
"break-keep wrap-break-word",
|
|
4817
|
+
BUBBLE_SURFACE[surface]
|
|
4818
|
+
),
|
|
4819
|
+
children: message
|
|
4820
|
+
},
|
|
4821
|
+
index
|
|
4822
|
+
))
|
|
4823
|
+
}
|
|
4824
|
+
),
|
|
4825
|
+
(readStatus != null || time != null) && // 읽음 표시와 시각은 한 줄에 선다 — 읽음이 먼저, 시각이 뒤다.
|
|
4826
|
+
/* @__PURE__ */ jsxs("div", { className: "typo-body-sm-default flex items-center gap-sd-4 px-sd-8", children: [
|
|
4827
|
+
readStatus != null && /* @__PURE__ */ jsx("span", { className: READ_STATUS_COLOR[readStatus], children: READ_STATUS_LABEL[readStatus] }),
|
|
4828
|
+
time != null && /* @__PURE__ */ jsx("span", { className: "text-(--sys-color-fg-tertiary)", children: time })
|
|
4829
|
+
] }),
|
|
4830
|
+
actions != null && // 버튼이 많아 한 줄에 안 들어가면 감싼다 — 넘쳐서 잘리는 것보다 낫다.
|
|
4831
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-sd-8 px-sd-8", outgoing && "justify-end"), children: actions })
|
|
4832
|
+
] })
|
|
4833
|
+
]
|
|
4834
|
+
}
|
|
4835
|
+
);
|
|
4836
|
+
});
|
|
4837
|
+
var SChatMessage2 = /* @__PURE__ */ withDisplayName(SChatMessageImpl, "SChatMessage");
|
|
4838
|
+
|
|
4839
|
+
// src/lib/z-index.ts
|
|
4840
|
+
var Z_INDEX = {
|
|
4841
|
+
baseFloating: 50,
|
|
4842
|
+
modalHost: 1e3,
|
|
4843
|
+
toast: 1100,
|
|
4844
|
+
loading: 1200,
|
|
4845
|
+
drag: 1300
|
|
4846
|
+
};
|
|
4847
|
+
var setRefs = (refs, value) => {
|
|
4848
|
+
refs.forEach((ref) => {
|
|
4849
|
+
if (typeof ref === "function") {
|
|
4850
|
+
ref(value);
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4853
|
+
if (ref) {
|
|
4854
|
+
ref.current = value;
|
|
4855
|
+
}
|
|
4856
|
+
});
|
|
4857
|
+
};
|
|
4858
|
+
function renderSlot(slot, state2) {
|
|
4859
|
+
return typeof slot === "function" ? slot(state2) : slot;
|
|
4860
|
+
}
|
|
4861
|
+
var SDraggableItemView = /* @__PURE__ */ forwardRef(
|
|
4862
|
+
function SDraggableItemView2({
|
|
4863
|
+
title,
|
|
4864
|
+
supportingText,
|
|
4865
|
+
supportingTextPosition,
|
|
4866
|
+
trailing,
|
|
4867
|
+
depth,
|
|
4868
|
+
accentStripe,
|
|
4869
|
+
bordered,
|
|
4870
|
+
selected,
|
|
4871
|
+
dense,
|
|
4872
|
+
size,
|
|
4873
|
+
dragging,
|
|
4874
|
+
disabled,
|
|
4875
|
+
hovered,
|
|
4876
|
+
dragHandleProps,
|
|
4877
|
+
onDragHandleMouseDown,
|
|
4878
|
+
className,
|
|
4879
|
+
style,
|
|
4880
|
+
...rest
|
|
4881
|
+
}, ref) {
|
|
4882
|
+
const renderState = { hovered, dragging, disabled };
|
|
4883
|
+
const titleNode = renderSlot(title, renderState);
|
|
4884
|
+
const supportingTextNode = renderSlot(supportingText, renderState);
|
|
4885
|
+
const hasSupportingText = supportingTextNode != null && supportingTextNode !== "";
|
|
4886
|
+
const trailingNode = renderSlot(trailing, renderState);
|
|
4887
|
+
const titleTypo = size === "sm" ? selected ? "typo-item-sm-selected" : "typo-item-sm-default" : selected ? "typo-item-md-selected" : "typo-item-md-default";
|
|
4888
|
+
const paddingYClass = dense ? size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-dense)" : "py-(--cmp-listDraggableItem-paddingY-md-dense)" : size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-normal)" : "py-(--cmp-listDraggableItem-paddingY-md-normal)";
|
|
4889
|
+
const normalizedDepth = Math.max(1, Math.floor(depth));
|
|
4890
|
+
const depthOffset = (normalizedDepth - 1) * 20;
|
|
4891
|
+
const depthStyle = depthOffset === 0 ? style : bordered ? {
|
|
4892
|
+
...style,
|
|
4893
|
+
marginLeft: depthOffset,
|
|
4894
|
+
width: `calc(100% - ${depthOffset}px)`
|
|
4895
|
+
} : {
|
|
4896
|
+
...style,
|
|
4897
|
+
paddingLeft: `calc(var(--cmp-listDraggableItem-paddingX) + ${depthOffset}px)`
|
|
4898
|
+
};
|
|
4899
|
+
return /* @__PURE__ */ jsxs(
|
|
4900
|
+
"div",
|
|
4901
|
+
{
|
|
4902
|
+
ref,
|
|
4903
|
+
"aria-disabled": disabled || void 0,
|
|
4904
|
+
"data-dragging": dragging || void 0,
|
|
4905
|
+
style: depthStyle,
|
|
4906
|
+
className: cn(
|
|
4907
|
+
"relative flex w-full items-center gap-(--cmp-listDraggableItem-gap) overflow-hidden px-(--cmp-listDraggableItem-paddingX)",
|
|
4908
|
+
titleTypo,
|
|
4909
|
+
disabled ? "bg-(--cmp-listDraggableItem-bg-default) text-(--sys-color-disabled-text)" : selected ? "bg-(--cmp-listDraggableItem-bg-selected) text-(--cmp-listDraggableItem-text-selected)" : "bg-(--cmp-listDraggableItem-bg-default) text-(--cmp-listDraggableItem-text-default)",
|
|
4910
|
+
!disabled && !selected && !dragging && cn(
|
|
4911
|
+
"hover:bg-(--cmp-listDraggableItem-bg-hover)",
|
|
4912
|
+
// 리스트가 드래그 중이면(SDraggableList 가 data-drag-active 를 붙인다) hover 를 무효화한다.
|
|
4913
|
+
"[[data-drag-active]_&]:hover:bg-(--cmp-listDraggableItem-bg-default)"
|
|
4914
|
+
),
|
|
4915
|
+
// 높이는 세로 패딩과 내용이 정한다 — 항목에 높이를 못 박지 않는다 (SListItem 과 동일)
|
|
4916
|
+
paddingYClass,
|
|
4917
|
+
// 항목 사이 구분선은 리스트가 그린다.
|
|
4918
|
+
bordered && cn(
|
|
4919
|
+
"rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
|
|
4920
|
+
!disabled && !selected && !dragging && cn(
|
|
4921
|
+
"hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
|
|
4922
|
+
"[[data-drag-active]_&]:hover:border-(--cmp-listDraggableItem-border-default)"
|
|
4923
|
+
),
|
|
4924
|
+
!disabled && selected && !dragging && "border-(--cmp-listDraggableItem-bordered-border-selected) bg-(--cmp-listDraggableItem-bordered-bg-selected)",
|
|
4925
|
+
!disabled && selected && dragging && "border-(--cmp-listDraggableItem-bordered-dragging-border-color) bg-(--cmp-listDraggableItem-bordered-dragging-bg)"
|
|
4926
|
+
),
|
|
4927
|
+
disabled && "cursor-not-allowed",
|
|
4928
|
+
className
|
|
4929
|
+
),
|
|
4930
|
+
...rest,
|
|
4931
|
+
children: [
|
|
4932
|
+
accentStripe && selected && !bordered && !disabled && /* @__PURE__ */ jsx(
|
|
4933
|
+
"span",
|
|
4934
|
+
{
|
|
4935
|
+
"aria-hidden": "true",
|
|
4936
|
+
className: "pointer-events-none absolute bottom-[-1px] left-0 top-0 w-(--cmp-listDraggableItem-accentStripe-width) bg-(--cmp-listDraggableItem-accentStripe-color)"
|
|
4937
|
+
}
|
|
4938
|
+
),
|
|
4939
|
+
/* @__PURE__ */ jsx(
|
|
4940
|
+
"div",
|
|
4941
|
+
{
|
|
4942
|
+
...dragHandleProps,
|
|
4943
|
+
role: dragHandleProps?.role ?? "button",
|
|
4944
|
+
tabIndex: dragHandleProps?.tabIndex ?? (disabled ? -1 : 0),
|
|
4945
|
+
"aria-label": dragHandleProps?.["aria-label"] ?? "\uB4DC\uB798\uADF8 \uD578\uB4E4",
|
|
4946
|
+
"aria-disabled": disabled || void 0,
|
|
4947
|
+
onMouseDown: onDragHandleMouseDown,
|
|
4948
|
+
className: cn(
|
|
4949
|
+
"flex size-[24px] shrink-0 select-none items-center justify-center rounded-[4px]",
|
|
4950
|
+
disabled ? "cursor-not-allowed opacity-0" : "cursor-grab hover:bg-black/5 active:cursor-grabbing",
|
|
4951
|
+
!disabled && !dragging && "[[data-drag-active]_&]:hover:bg-transparent",
|
|
4952
|
+
dragging && "bg-black/5",
|
|
4953
|
+
dragHandleProps?.className
|
|
4954
|
+
),
|
|
4955
|
+
children: /* @__PURE__ */ jsx(SIcon, { name: "drag", size: 16, color: "grey_65" })
|
|
4956
|
+
}
|
|
4957
|
+
),
|
|
4958
|
+
/* @__PURE__ */ jsxs(
|
|
4959
|
+
"div",
|
|
4960
|
+
{
|
|
4961
|
+
className: cn(
|
|
4962
|
+
"flex min-w-0 flex-1 items-center gap-[8px]",
|
|
4963
|
+
dragging && "opacity-(--cmp-listDraggableItem-dragging-content-opacity)"
|
|
4964
|
+
),
|
|
4965
|
+
children: [
|
|
4966
|
+
/* @__PURE__ */ jsxs(
|
|
4967
|
+
"span",
|
|
4968
|
+
{
|
|
4969
|
+
className: cn(
|
|
4970
|
+
"min-w-0 flex-1",
|
|
4971
|
+
supportingTextPosition === "bottom" ? "flex flex-col" : "flex items-center gap-[8px] whitespace-nowrap"
|
|
4972
|
+
),
|
|
4973
|
+
children: [
|
|
4974
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: titleNode }),
|
|
4975
|
+
hasSupportingText && /* @__PURE__ */ jsx(
|
|
4976
|
+
"span",
|
|
4977
|
+
{
|
|
4978
|
+
className: cn(
|
|
4979
|
+
"typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
|
|
4980
|
+
supportingTextPosition === "right" && "flex-1"
|
|
4981
|
+
),
|
|
4982
|
+
children: supportingTextNode
|
|
4983
|
+
}
|
|
4984
|
+
)
|
|
4985
|
+
]
|
|
4986
|
+
}
|
|
4987
|
+
),
|
|
4988
|
+
trailingNode
|
|
4989
|
+
]
|
|
4990
|
+
}
|
|
4991
|
+
)
|
|
4992
|
+
]
|
|
4993
|
+
}
|
|
4994
|
+
);
|
|
4995
|
+
}
|
|
4996
|
+
);
|
|
4997
|
+
var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
|
|
4998
|
+
title,
|
|
4999
|
+
supportingText,
|
|
5000
|
+
supportingTextPosition = "right",
|
|
5001
|
+
trailing,
|
|
5002
|
+
depth = 1,
|
|
5003
|
+
accentStripe = false,
|
|
5004
|
+
bordered = false,
|
|
5005
|
+
selected = false,
|
|
5006
|
+
dragging = false,
|
|
5007
|
+
dense = false,
|
|
5008
|
+
size = "sm",
|
|
5009
|
+
disabled = false,
|
|
5010
|
+
dragOverlay = true,
|
|
5011
|
+
dragOverlayOpacity = 0.75,
|
|
5012
|
+
dragHandleProps,
|
|
5013
|
+
onDragHandleMouseDown,
|
|
5014
|
+
className,
|
|
5015
|
+
onMouseEnter,
|
|
5016
|
+
onMouseLeave,
|
|
5017
|
+
...rest
|
|
5018
|
+
}, ref) {
|
|
5019
|
+
const [hovered, setHovered] = useState(false);
|
|
5020
|
+
const [overlay, setOverlay] = useState(null);
|
|
5021
|
+
const rootRef = useRef(null);
|
|
5022
|
+
const overlayVisible = overlay != null;
|
|
5023
|
+
const handleMouseEnter = (event) => {
|
|
5024
|
+
if (!disabled) setHovered(true);
|
|
5025
|
+
onMouseEnter?.(event);
|
|
5026
|
+
};
|
|
5027
|
+
const handleMouseLeave = (event) => {
|
|
5028
|
+
setHovered(false);
|
|
5029
|
+
onMouseLeave?.(event);
|
|
5030
|
+
};
|
|
5031
|
+
const handleDragMouseDown = (event) => {
|
|
5032
|
+
if (disabled) return;
|
|
5033
|
+
const rect = rootRef.current?.getBoundingClientRect();
|
|
5034
|
+
if (dragOverlay && rect) {
|
|
5035
|
+
setOverlay({
|
|
5036
|
+
offsetX: event.clientX - rect.left,
|
|
5037
|
+
offsetY: event.clientY - rect.top,
|
|
5038
|
+
rect,
|
|
5039
|
+
x: event.clientX,
|
|
5040
|
+
y: event.clientY
|
|
5041
|
+
});
|
|
5042
|
+
}
|
|
5043
|
+
dragHandleProps?.onMouseDown?.(event);
|
|
5044
|
+
onDragHandleMouseDown?.(event);
|
|
5045
|
+
};
|
|
5046
|
+
useEffect(() => {
|
|
5047
|
+
if (!overlayVisible) return void 0;
|
|
5048
|
+
const handleMouseMove = (event) => {
|
|
5049
|
+
setOverlay(
|
|
5050
|
+
(current) => current ? {
|
|
5051
|
+
...current,
|
|
5052
|
+
x: event.clientX,
|
|
5053
|
+
y: event.clientY
|
|
5054
|
+
} : current
|
|
5055
|
+
);
|
|
5056
|
+
};
|
|
5057
|
+
const handleMouseUp = () => {
|
|
5058
|
+
setOverlay(null);
|
|
5059
|
+
};
|
|
5060
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
5061
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
5062
|
+
return () => {
|
|
5063
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
5064
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
5065
|
+
};
|
|
5066
|
+
}, [overlayVisible]);
|
|
5067
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5068
|
+
/* @__PURE__ */ jsx(
|
|
5069
|
+
SDraggableItemView,
|
|
5070
|
+
{
|
|
5071
|
+
ref: (node) => setRefs([rootRef, ref], node),
|
|
5072
|
+
title,
|
|
5073
|
+
supportingText,
|
|
5074
|
+
supportingTextPosition,
|
|
5075
|
+
trailing,
|
|
5076
|
+
depth,
|
|
5077
|
+
accentStripe,
|
|
5078
|
+
bordered,
|
|
5079
|
+
selected,
|
|
5080
|
+
dense,
|
|
5081
|
+
size,
|
|
5082
|
+
dragging: dragging || overlayVisible,
|
|
5083
|
+
disabled,
|
|
5084
|
+
hovered,
|
|
5085
|
+
dragHandleProps,
|
|
5086
|
+
onDragHandleMouseDown: handleDragMouseDown,
|
|
5087
|
+
onMouseEnter: handleMouseEnter,
|
|
5088
|
+
onMouseLeave: handleMouseLeave,
|
|
5089
|
+
className,
|
|
5090
|
+
...rest
|
|
5091
|
+
}
|
|
5092
|
+
),
|
|
5093
|
+
overlay && typeof document !== "undefined" && createPortal(
|
|
5094
|
+
/* @__PURE__ */ jsx(
|
|
5095
|
+
"div",
|
|
5096
|
+
{
|
|
5097
|
+
className: "pointer-events-none fixed",
|
|
5098
|
+
style: {
|
|
5099
|
+
left: overlay.x - overlay.offsetX,
|
|
5100
|
+
opacity: dragOverlayOpacity,
|
|
5101
|
+
top: overlay.y - overlay.offsetY,
|
|
5102
|
+
width: overlay.rect.width,
|
|
5103
|
+
zIndex: Z_INDEX.drag
|
|
5104
|
+
},
|
|
5105
|
+
children: /* @__PURE__ */ jsx(
|
|
5106
|
+
SDraggableItemView,
|
|
5107
|
+
{
|
|
5108
|
+
title,
|
|
5109
|
+
supportingText,
|
|
5110
|
+
supportingTextPosition,
|
|
5111
|
+
trailing,
|
|
5112
|
+
depth,
|
|
5113
|
+
accentStripe,
|
|
5114
|
+
bordered,
|
|
5115
|
+
selected,
|
|
5116
|
+
dense,
|
|
5117
|
+
size,
|
|
5118
|
+
dragging: true,
|
|
5119
|
+
disabled,
|
|
5120
|
+
hovered: true,
|
|
5121
|
+
dragHandleProps,
|
|
5122
|
+
className
|
|
5123
|
+
}
|
|
5124
|
+
)
|
|
5125
|
+
}
|
|
5126
|
+
),
|
|
5127
|
+
document.body
|
|
5128
|
+
)
|
|
5129
|
+
] });
|
|
5130
|
+
});
|
|
5131
|
+
var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
|
|
5132
|
+
var SDivider = /* @__PURE__ */ forwardRef(function SDivider2({ vertical = false, height, className, style, ...rest }, ref) {
|
|
5133
|
+
const fixedHeight = vertical && height !== void 0;
|
|
5134
|
+
return /* @__PURE__ */ jsx(
|
|
5135
|
+
"hr",
|
|
5136
|
+
{
|
|
5137
|
+
ref,
|
|
5138
|
+
"aria-orientation": vertical ? "vertical" : "horizontal",
|
|
5139
|
+
className: cn(
|
|
5140
|
+
"shrink-0 border-0",
|
|
5141
|
+
vertical ? cn("inline-block w-px", fixedHeight ? "self-center" : "h-auto self-stretch") : "block h-px w-full",
|
|
5142
|
+
className
|
|
5143
|
+
),
|
|
5144
|
+
style: {
|
|
5145
|
+
backgroundColor: "var(--sys-color-divider-default, #E1E1E1)",
|
|
5146
|
+
...fixedHeight ? { height: typeof height === "number" ? `${height}px` : height } : null,
|
|
5147
|
+
...style
|
|
5148
|
+
},
|
|
5149
|
+
...rest
|
|
5150
|
+
}
|
|
5151
|
+
);
|
|
5152
|
+
});
|
|
5153
|
+
var PADDING_CLASS = {
|
|
5154
|
+
default: "p-(--cmp-list-group-padding)",
|
|
5155
|
+
none: ""
|
|
5156
|
+
};
|
|
5157
|
+
var dividerStyle = { backgroundColor: "var(--cmp-listItem-border-default)" };
|
|
5158
|
+
function hasBorderedChild(children) {
|
|
5159
|
+
let bordered = false;
|
|
5160
|
+
Children.forEach(children, (child) => {
|
|
5161
|
+
if (!isValidElement(child)) return;
|
|
5162
|
+
if (child.props.bordered === true) {
|
|
5163
|
+
bordered = true;
|
|
5164
|
+
return;
|
|
5165
|
+
}
|
|
5166
|
+
Children.forEach(child.props.children, (wrapped) => {
|
|
5167
|
+
if (isValidElement(wrapped) && wrapped.props.bordered === true) {
|
|
5168
|
+
bordered = true;
|
|
5169
|
+
}
|
|
5170
|
+
});
|
|
5171
|
+
});
|
|
5172
|
+
return bordered;
|
|
5173
|
+
}
|
|
5174
|
+
function withDividers(children) {
|
|
5175
|
+
return Children.toArray(children).flatMap(
|
|
5176
|
+
(child, index) => index === 0 ? [child] : [
|
|
5177
|
+
/* @__PURE__ */ jsx(SDivider, { "aria-hidden": "true", style: dividerStyle }, `s-list-divider-${index}`),
|
|
5178
|
+
child
|
|
5179
|
+
]
|
|
5180
|
+
);
|
|
5181
|
+
}
|
|
5182
|
+
var SListImpl = /* @__PURE__ */ forwardRef(function SList({ className, children, gap = false, padding = "none", ...rest }, ref) {
|
|
5183
|
+
const showDivider = !gap && !hasBorderedChild(children);
|
|
5184
|
+
return /* @__PURE__ */ jsx(
|
|
5185
|
+
"div",
|
|
5186
|
+
{
|
|
5187
|
+
ref,
|
|
5188
|
+
className: cn(
|
|
5189
|
+
gap && "flex flex-col gap-(--cmp-list-group-gap)",
|
|
5190
|
+
PADDING_CLASS[padding],
|
|
5191
|
+
className
|
|
5192
|
+
),
|
|
5193
|
+
...rest,
|
|
5194
|
+
children: showDivider ? withDividers(children) : children
|
|
5195
|
+
}
|
|
5196
|
+
);
|
|
5197
|
+
});
|
|
5198
|
+
var SList2 = /* @__PURE__ */ withDisplayName(SListImpl, "SList");
|
|
5199
|
+
var DraggableGroupContext = /* @__PURE__ */ createContext(null);
|
|
5200
|
+
function useSDraggableGroup() {
|
|
5201
|
+
return useContext(DraggableGroupContext);
|
|
5202
|
+
}
|
|
5203
|
+
function SDraggableProviderInternal({
|
|
5204
|
+
children,
|
|
5205
|
+
defaultGroup,
|
|
5206
|
+
legacyOnMove
|
|
5207
|
+
}) {
|
|
5208
|
+
const listsRef = useRef(/* @__PURE__ */ new Map());
|
|
5209
|
+
const legacyOnMoveRef = useRef(legacyOnMove);
|
|
5210
|
+
const pointerRef = useRef(null);
|
|
5211
|
+
const [dragging, setDragging] = useState(null);
|
|
5212
|
+
const [drop, setDrop] = useState(null);
|
|
5213
|
+
const dropRef = useRef(drop);
|
|
5214
|
+
legacyOnMoveRef.current = legacyOnMove;
|
|
5215
|
+
dropRef.current = drop;
|
|
5216
|
+
const registerList = useCallback(
|
|
5217
|
+
(group, listId, element, items, onChange) => {
|
|
5218
|
+
const key = `${group}:${listId}`;
|
|
5219
|
+
if (element) listsRef.current.set(key, { element, items, onChange });
|
|
5220
|
+
else listsRef.current.delete(key);
|
|
5221
|
+
},
|
|
5222
|
+
[]
|
|
5223
|
+
);
|
|
5224
|
+
const startDrag = useCallback(
|
|
5225
|
+
(event, group, listId, index, itemKey) => {
|
|
5226
|
+
event.preventDefault();
|
|
5227
|
+
setDragging({ group, listId, index, itemKey });
|
|
5228
|
+
setDrop({ group, listId, index });
|
|
5229
|
+
},
|
|
5230
|
+
[]
|
|
5231
|
+
);
|
|
5232
|
+
useEffect(() => {
|
|
5233
|
+
if (!dragging) return void 0;
|
|
5234
|
+
let autoScrollFrame = null;
|
|
5235
|
+
const findListAtPointer = (clientX, clientY) => {
|
|
5236
|
+
const element = document.elementFromPoint(clientX, clientY);
|
|
5237
|
+
const listElement = element?.closest("[data-draggable-list-id]");
|
|
5238
|
+
const group = listElement?.dataset.draggableGroup;
|
|
5239
|
+
const listId = listElement?.dataset.draggableListId;
|
|
5240
|
+
const list = group && listId ? listsRef.current.get(`${group}:${listId}`) : void 0;
|
|
5241
|
+
return group && listId && list ? { group, listId, list } : null;
|
|
4144
5242
|
};
|
|
4145
5243
|
const updateDropTarget = (clientX, clientY) => {
|
|
4146
5244
|
const target = findListAtPointer(clientX, clientY);
|
|
@@ -4885,23 +5983,104 @@ var SExpansionListImpl = /* @__PURE__ */ forwardRef(function SExpansionList({ ch
|
|
|
4885
5983
|
if (isListItemElement(child)) {
|
|
4886
5984
|
return cloneElement(child, { clickable: child.props.clickable ?? true });
|
|
4887
5985
|
}
|
|
4888
|
-
if (!isExpansionItemElement(child)) return child;
|
|
4889
|
-
const depth = child.props.depth ?? 1;
|
|
4890
|
-
const itemKey = String(child.key ?? index);
|
|
4891
|
-
return cloneElement(child, {
|
|
4892
|
-
expanded: openKeys[depth] === itemKey,
|
|
4893
|
-
onToggle: (next, event) => {
|
|
4894
|
-
setOpenKeys((current) => ({
|
|
4895
|
-
...current,
|
|
4896
|
-
[depth]: next ? itemKey : current[depth] === itemKey ? void 0 : current[depth]
|
|
4897
|
-
}));
|
|
4898
|
-
child.props.onToggle?.(next, event);
|
|
4899
|
-
}
|
|
4900
|
-
});
|
|
4901
|
-
});
|
|
4902
|
-
return /* @__PURE__ */ jsx(SList2, { ref, ...rest, children: listChildren });
|
|
5986
|
+
if (!isExpansionItemElement(child)) return child;
|
|
5987
|
+
const depth = child.props.depth ?? 1;
|
|
5988
|
+
const itemKey = String(child.key ?? index);
|
|
5989
|
+
return cloneElement(child, {
|
|
5990
|
+
expanded: openKeys[depth] === itemKey,
|
|
5991
|
+
onToggle: (next, event) => {
|
|
5992
|
+
setOpenKeys((current) => ({
|
|
5993
|
+
...current,
|
|
5994
|
+
[depth]: next ? itemKey : current[depth] === itemKey ? void 0 : current[depth]
|
|
5995
|
+
}));
|
|
5996
|
+
child.props.onToggle?.(next, event);
|
|
5997
|
+
}
|
|
5998
|
+
});
|
|
5999
|
+
});
|
|
6000
|
+
return /* @__PURE__ */ jsx(SList2, { ref, ...rest, children: listChildren });
|
|
6001
|
+
});
|
|
6002
|
+
var SExpansionList2 = /* @__PURE__ */ withDisplayName(SExpansionListImpl, "SExpansionList");
|
|
6003
|
+
function SellmateWordmark({ className }) {
|
|
6004
|
+
return /* @__PURE__ */ jsxs(
|
|
6005
|
+
"svg",
|
|
6006
|
+
{
|
|
6007
|
+
className,
|
|
6008
|
+
width: "276",
|
|
6009
|
+
height: "40",
|
|
6010
|
+
viewBox: "0 0 276 40",
|
|
6011
|
+
fill: "#00275F",
|
|
6012
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
6013
|
+
role: "img",
|
|
6014
|
+
"aria-label": "Sellmate",
|
|
6015
|
+
children: [
|
|
6016
|
+
/* @__PURE__ */ jsx("path", { d: "M22.6953 15.17H13.0352C10.9045 15.17 9.36459 14.8464 8.56779 14.2353C7.81576 13.6602 7.47556 12.7615 7.47556 11.3325C7.47556 9.90362 7.81576 8.98695 8.56779 8.4028C9.5526 7.62992 10.8418 7.48613 13.0352 7.48613H33.7072V0H13.1516C4.91507 0 0 4.23285 0 11.3325C0 18.4322 4.91507 22.6561 13.1516 22.6561H22.8206C24.1187 22.6292 26.0973 22.6561 27.2701 23.5908C27.9953 24.1659 28.3713 25.2444 28.3713 26.7811C28.3713 28.2011 28.0669 29.0908 27.3955 29.6569C26.1331 30.7174 23.6711 31.2476 20.0721 31.2476C6.75038 31.2476 0.877371 27.2125 0.823654 27.1676L0 26.5834V34.2852L0.196961 34.438C0.402874 34.5998 5.29108 38.3743 19.9557 38.3743C30.3499 38.3743 35.8469 34.3661 35.8469 26.7721C35.8469 19.1782 30.9318 15.17 22.6953 15.17Z" }),
|
|
6017
|
+
/* @__PURE__ */ jsx("path", { d: "M94.6954 0H87.4258V38.3833H94.6954V0Z" }),
|
|
6018
|
+
/* @__PURE__ */ jsx("path", { d: "M109.874 0H102.604V38.3833H109.874V0Z" }),
|
|
6019
|
+
/* @__PURE__ */ jsx("path", { d: "M160.887 10.728C158.675 8.97557 153.885 8.35547 150.466 8.35547C147.314 8.35547 143.035 9.04746 140.752 10.5483C138.558 9.03848 134.261 8.35547 131.056 8.35547C127.394 8.35547 122.631 9.17328 120.635 10.728C118.54 12.3636 117.475 14.844 117.475 18.1063V38.7224H124.744V18.1063C124.744 17.3514 125.058 16.7762 125.702 16.3539C126.669 15.7158 129.203 15.4911 131.083 15.4911C134.395 15.4911 137.135 15.6888 137.135 18.1063V38.7224H144.405V18.1063C144.405 15.9135 146.625 15.4911 150.457 15.4911C152.552 15.4911 155.067 15.7787 155.81 16.3359C156.482 16.8302 156.786 17.3963 156.786 18.1063V38.7224H164.056V18.1063C164.056 14.871 162.99 12.3906 160.896 10.728H160.887Z" }),
|
|
6020
|
+
/* @__PURE__ */ jsx("path", { d: "M195.015 8.35547H174.648V15.4911H194.854C197.074 15.4911 198.453 15.599 199.348 16.1741C199.895 16.5246 200.208 17.1537 200.289 18.0704H183.314C175.095 18.0704 171.264 21.3506 171.264 28.3964C171.264 34.9569 175.865 38.7224 183.887 38.7224H195.024C209.053 38.7224 207.639 35.9454 207.639 28.9715V18.1063C207.639 11.5458 203.512 8.35547 195.024 8.35547H195.015ZM200.369 28.9715C200.369 29.6276 200.441 30.5982 199.689 31.1194C198.847 31.7036 196.895 31.5867 194.854 31.5867H184.048C180.288 31.5867 178.533 30.5443 178.533 28.2975C178.533 25.4217 181.255 25.188 184.048 25.188H200.369V28.9715Z" }),
|
|
6021
|
+
/* @__PURE__ */ jsx("path", { d: "M227.692 0.521243L227.683 0H220.413V8.01636H212.866V15.143H220.413V37.862L220.422 38.3833H227.692V15.143H235.239V8.01636H227.692V0.521243Z" }),
|
|
6022
|
+
/* @__PURE__ */ jsx("path", { d: "M75.2766 10.728C73.2801 9.15531 70.084 8.35547 65.7688 8.35547H56.3146C47.9438 8.35547 43.7002 11.6357 43.7002 18.1063V29.2052C43.7002 34.4536 47.9528 38.7224 53.1812 38.7224H76.6553V31.6856H54.4793C52.5366 31.6856 50.9609 30.1039 50.9609 28.1537V27.4527H74.9006C76.2793 27.4527 77.1925 27.1472 77.7117 26.5181C78.1683 25.9519 78.3922 25.0802 78.3922 23.858V18.0973C78.3922 14.844 77.3447 12.3547 75.2766 10.719V10.728ZM50.9609 18.1063C50.9609 17.4233 51.31 16.8751 52.0621 16.3628C52.9126 15.7877 54.4346 15.4821 56.4758 15.4821H65.6076C67.6936 15.4821 69.2335 15.7607 70.075 16.282C70.7913 16.7223 71.1225 17.2975 71.1225 18.0973V20.416H50.9609V18.0973V18.1063Z" }),
|
|
6023
|
+
/* @__PURE__ */ jsx("path", { d: "M271.48 10.728C269.483 9.15531 266.287 8.35547 261.972 8.35547H252.518C244.147 8.35547 239.895 11.6357 239.895 18.1063V29.2052C239.895 34.4536 244.147 38.7224 249.376 38.7224H272.85V31.6856H250.674C248.731 31.6856 247.155 30.1039 247.155 28.1537V27.4527H271.095C272.474 27.4527 273.387 27.1472 273.906 26.5181C274.363 25.9519 274.586 25.0802 274.586 23.858V18.0973C274.586 14.844 273.539 12.3547 271.471 10.719L271.48 10.728ZM247.164 20.416V18.0973C247.164 17.4143 247.513 16.8661 248.265 16.3539C249.116 15.7787 250.638 15.4731 252.679 15.4731H261.811C263.897 15.4731 265.437 15.7517 266.278 16.273C266.995 16.7133 267.326 17.2885 267.326 18.0883V20.407H247.164V20.416Z" })
|
|
6024
|
+
]
|
|
6025
|
+
}
|
|
6026
|
+
);
|
|
6027
|
+
}
|
|
6028
|
+
var BUTTON_LABEL = "\uD1B5\uD569 \uACC4\uC815\uC73C\uB85C \uB85C\uADF8\uC778";
|
|
6029
|
+
var SLoginCardImpl = /* @__PURE__ */ forwardRef(function SLoginCard({ product, title, description, onLogin, footerNote, className, ...rest }, ref) {
|
|
6030
|
+
const hasIntro = title != null || description != null;
|
|
6031
|
+
return /* @__PURE__ */ jsxs(
|
|
6032
|
+
"div",
|
|
6033
|
+
{
|
|
6034
|
+
ref,
|
|
6035
|
+
className: cn(
|
|
6036
|
+
// 폭도 높이도 부모가 준 만큼 채우고, 그 안에서 내용을 가운데 세운다.
|
|
6037
|
+
// 폭에만 상하한이 있다 — 640px 을 넘으면 소개 문장의 읽기 폭이 늘어지고, 368px 아래로
|
|
6038
|
+
// 내려가면 버튼(320px)이 안쪽 여백을 밀어낸다. 그 사이에서는 부모를 그대로 따른다.
|
|
6039
|
+
// 부모가 높이를 주지 않으면 h-full 이 auto 로 풀려 카드가 내용 높이로 줄어든다 —
|
|
6040
|
+
// 로그인 화면 밖(모달·스토리)에서도 그대로 쓸 수 있는 이유다.
|
|
6041
|
+
"flex h-full w-full max-w-[640px] min-w-[368px] shrink-0 flex-col items-center justify-center gap-sd-60",
|
|
6042
|
+
// 라운드 24px·폭 상하한(640/368px)은 대응 토큰이 없어 값으로 둔다 (디자인팀 토큰 추가 요청 대상).
|
|
6043
|
+
"rounded-[24px] bg-(--sys-color-bg-frame) p-sd-24 text-center",
|
|
6044
|
+
// 한글은 기본 규칙으로 두면 어절 한가운데서도 줄이 바뀐다 — `break-keep` 으로 띄어쓰기에서만
|
|
6045
|
+
// 끊는다. 끊을 자리가 아예 없는 긴 토큰(URL·주문번호)만 `wrap-break-word` 로 흘려보낸다.
|
|
6046
|
+
"break-keep wrap-break-word",
|
|
6047
|
+
className
|
|
6048
|
+
),
|
|
6049
|
+
...rest,
|
|
6050
|
+
children: [
|
|
6051
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-sd-32", children: [
|
|
6052
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-sd-8", children: [
|
|
6053
|
+
/* @__PURE__ */ jsx(SellmateWordmark, {}),
|
|
6054
|
+
product != null && // 24px 는 typo 프리셋(최대 18px)에 없는 등급이다 — 제품명은 로고의 일부처럼 읽혀야
|
|
6055
|
+
// 해서 본문 스케일 위에 선다. 여기만 값으로 두고, 프리셋이 생기면 갈아탄다.
|
|
6056
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-[24px] leading-[36px] font-bold text-(--sys-color-fg-accentLight)", children: product })
|
|
6057
|
+
] }),
|
|
6058
|
+
hasIntro && // 소개와 보조 설명은 한 문단으로 읽힌다.
|
|
6059
|
+
// `text-balance` 는 상속되므로 여기 한 번만 걸어 둘을 함께 덮는다 — 가운데 정렬에서는
|
|
6060
|
+
// 마지막 줄에 한 어절만 남는 모양이 가장 눈에 띄어서, 줄 길이를 고르게 나눠야 한다.
|
|
6061
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-sd-4 text-balance", children: [
|
|
6062
|
+
title != null && /* @__PURE__ */ jsx("p", { className: "typo-body-lg-medium m-0 text-(--sys-color-fg-secondary)", children: title }),
|
|
6063
|
+
description != null && /* @__PURE__ */ jsx("p", { className: "typo-body-md-default m-0 text-(--sys-color-fg-tertiary)", children: description })
|
|
6064
|
+
] })
|
|
6065
|
+
] }),
|
|
6066
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-sd-12", children: [
|
|
6067
|
+
/* @__PURE__ */ jsx(
|
|
6068
|
+
SButton,
|
|
6069
|
+
{
|
|
6070
|
+
color: "secondary",
|
|
6071
|
+
size: "lg",
|
|
6072
|
+
label: BUTTON_LABEL,
|
|
6073
|
+
onClick: onLogin,
|
|
6074
|
+
className: "w-[320px]"
|
|
6075
|
+
}
|
|
6076
|
+
),
|
|
6077
|
+
footerNote != null && /* @__PURE__ */ jsx("p", { className: "typo-body-sm-default m-0 text-(--sys-color-fg-tertiary)", children: footerNote })
|
|
6078
|
+
] })
|
|
6079
|
+
]
|
|
6080
|
+
}
|
|
6081
|
+
);
|
|
4903
6082
|
});
|
|
4904
|
-
var
|
|
6083
|
+
var SLoginCard2 = /* @__PURE__ */ withDisplayName(SLoginCardImpl, "SLoginCard");
|
|
4905
6084
|
function SCheckbox({
|
|
4906
6085
|
value = false,
|
|
4907
6086
|
val,
|
|
@@ -4929,292 +6108,48 @@ function SCheckbox({
|
|
|
4929
6108
|
};
|
|
4930
6109
|
const boxBg = disabled ? "var(--cmp-checkbox-bg-disabled)" : inverse ? "transparent" : isChecked ? "var(--cmp-checkbox-checked-bg-default)" : "var(--cmp-checkbox-unchecked-bg-default)";
|
|
4931
6110
|
const boxBorder = disabled ? "var(--cmp-checkbox-border-disabled)" : inverse ? "var(--cmp-checkbox-checked-border-inverse)" : isChecked ? "var(--cmp-checkbox-checked-bg-default)" : "var(--cmp-checkbox-unchecked-border-default)";
|
|
4932
|
-
const iconColor = disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)";
|
|
4933
|
-
const labelColor = disabled ? "var(--cmp-checkbox-label-disabled)" : inverse ? "var(--cmp-checkbox-label-inverse)" : "var(--cmp-checkbox-label-default)";
|
|
4934
|
-
return /* @__PURE__ */ jsxs(
|
|
4935
|
-
"label",
|
|
4936
|
-
{
|
|
4937
|
-
className: cn(
|
|
4938
|
-
"inline-flex items-center gap-[var(--cmp-checkbox-gap)] align-middle",
|
|
4939
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
4940
|
-
className
|
|
4941
|
-
),
|
|
4942
|
-
style,
|
|
4943
|
-
children: [
|
|
4944
|
-
/* @__PURE__ */ jsx(
|
|
4945
|
-
RCheckbox.Root,
|
|
4946
|
-
{
|
|
4947
|
-
checked: state2,
|
|
4948
|
-
disabled,
|
|
4949
|
-
onCheckedChange: handleChange,
|
|
4950
|
-
className: cn(
|
|
4951
|
-
"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",
|
|
4952
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
4953
|
-
!disabled && !isChecked && !inverse && "hover:border-[color:var(--cmp-checkbox-unchecked-border-hover)] hover:bg-[var(--cmp-checkbox-unchecked-bg-hover)]"
|
|
4954
|
-
),
|
|
4955
|
-
style: { "--cb-bg": boxBg, "--cb-border": boxBorder },
|
|
4956
|
-
children: /* @__PURE__ */ jsx(RCheckbox.Indicator, { className: "flex items-center justify-center leading-none", children: /* @__PURE__ */ jsx(
|
|
4957
|
-
SIcon,
|
|
4958
|
-
{
|
|
4959
|
-
name: state2 === "indeterminate" ? "checkboxIndeterminate" : "checkboxCheck",
|
|
4960
|
-
size: 12,
|
|
4961
|
-
color: iconColor
|
|
4962
|
-
}
|
|
4963
|
-
) })
|
|
4964
|
-
}
|
|
4965
|
-
),
|
|
4966
|
-
label && // 고스트(500) 텍스트로 너비를 고정 → 두께 400↔500 전환 시 레이아웃이 밀리지 않음
|
|
4967
|
-
/* @__PURE__ */ jsxs("span", { className: "grid text-nowrap text-[12px] leading-[20px]", style: { color: labelColor }, children: [
|
|
4968
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible font-medium", style: { gridArea: "1 / 1" }, children: label }),
|
|
4969
|
-
/* @__PURE__ */ jsx("span", { style: { gridArea: "1 / 1", fontWeight: isChecked ? 500 : 400 }, children: label })
|
|
4970
|
-
] })
|
|
4971
|
-
]
|
|
4972
|
-
}
|
|
4973
|
-
);
|
|
4974
|
-
}
|
|
4975
|
-
|
|
4976
|
-
// src/lib/floating-anim.ts
|
|
4977
|
-
var FLOATING_SLIDE_ANIM = [
|
|
4978
|
-
"data-[state=open]:data-[side=top]:animate-floating-in-top",
|
|
4979
|
-
"data-[state=delayed-open]:data-[side=top]:animate-floating-in-top",
|
|
4980
|
-
"data-[state=instant-open]:data-[side=top]:animate-floating-in-top",
|
|
4981
|
-
"data-[state=closed]:data-[side=top]:animate-floating-out-top",
|
|
4982
|
-
"data-[state=open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
4983
|
-
"data-[state=delayed-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
4984
|
-
"data-[state=instant-open]:data-[side=bottom]:animate-floating-in-bottom",
|
|
4985
|
-
"data-[state=closed]:data-[side=bottom]:animate-floating-out-bottom",
|
|
4986
|
-
"data-[state=open]:data-[side=left]:animate-floating-in-left",
|
|
4987
|
-
"data-[state=delayed-open]:data-[side=left]:animate-floating-in-left",
|
|
4988
|
-
"data-[state=instant-open]:data-[side=left]:animate-floating-in-left",
|
|
4989
|
-
"data-[state=closed]:data-[side=left]:animate-floating-out-left",
|
|
4990
|
-
"data-[state=open]:data-[side=right]:animate-floating-in-right",
|
|
4991
|
-
"data-[state=delayed-open]:data-[side=right]:animate-floating-in-right",
|
|
4992
|
-
"data-[state=instant-open]:data-[side=right]:animate-floating-in-right",
|
|
4993
|
-
"data-[state=closed]:data-[side=right]:animate-floating-out-right"
|
|
4994
|
-
].join(" ");
|
|
4995
|
-
var PortalContainerContext = /* @__PURE__ */ createContext(null);
|
|
4996
|
-
var InsideModalContext = /* @__PURE__ */ createContext(false);
|
|
4997
|
-
var PortalContainerProvider = PortalContainerContext.Provider;
|
|
4998
|
-
var InsideModalProvider = InsideModalContext.Provider;
|
|
4999
|
-
function usePortalContainer() {
|
|
5000
|
-
return useContext(PortalContainerContext) ?? void 0;
|
|
5001
|
-
}
|
|
5002
|
-
function useInsideModal() {
|
|
5003
|
-
return useContext(InsideModalContext);
|
|
5004
|
-
}
|
|
5005
|
-
|
|
5006
|
-
// src/components/STag/tag.config.ts
|
|
5007
|
-
var TAG_SHAPES = ["square", "pill"];
|
|
5008
|
-
var TAG_SIZES = ["xs", "sm", "md"];
|
|
5009
|
-
var TAG_COLORS = [
|
|
5010
|
-
"grey",
|
|
5011
|
-
"red",
|
|
5012
|
-
"orange",
|
|
5013
|
-
"yellow",
|
|
5014
|
-
"green",
|
|
5015
|
-
"blue",
|
|
5016
|
-
"darkblue",
|
|
5017
|
-
"indigo"
|
|
5018
|
-
];
|
|
5019
|
-
var TAG_SIZE_CONFIG = {
|
|
5020
|
-
xs: {
|
|
5021
|
-
height: 20,
|
|
5022
|
-
paddingX: 8,
|
|
5023
|
-
gap: 4,
|
|
5024
|
-
radius: 6,
|
|
5025
|
-
iconSize: 12,
|
|
5026
|
-
fontSize: 11,
|
|
5027
|
-
fontWeight: 500,
|
|
5028
|
-
lineHeight: 18
|
|
5029
|
-
},
|
|
5030
|
-
sm: {
|
|
5031
|
-
height: 24,
|
|
5032
|
-
paddingX: 8,
|
|
5033
|
-
gap: 4,
|
|
5034
|
-
radius: 6,
|
|
5035
|
-
iconSize: 16,
|
|
5036
|
-
fontSize: 12,
|
|
5037
|
-
fontWeight: 700,
|
|
5038
|
-
lineHeight: 20
|
|
5039
|
-
},
|
|
5040
|
-
md: {
|
|
5041
|
-
height: 28,
|
|
5042
|
-
paddingX: 12,
|
|
5043
|
-
gap: 6,
|
|
5044
|
-
radius: 8,
|
|
5045
|
-
iconSize: 16,
|
|
5046
|
-
fontSize: 14,
|
|
5047
|
-
fontWeight: 700,
|
|
5048
|
-
lineHeight: 24
|
|
5049
|
-
}
|
|
5050
|
-
};
|
|
5051
|
-
var STag = /* @__PURE__ */ forwardRef(function STag2({
|
|
5052
|
-
shape = "square",
|
|
5053
|
-
size = "sm",
|
|
5054
|
-
color = "grey",
|
|
5055
|
-
deep = false,
|
|
5056
|
-
label = "",
|
|
5057
|
-
icon,
|
|
5058
|
-
iconLeft = true,
|
|
5059
|
-
width,
|
|
5060
|
-
className,
|
|
5061
|
-
style,
|
|
5062
|
-
...rest
|
|
5063
|
-
}, ref) {
|
|
5064
|
-
const s = TAG_SIZE_CONFIG[size];
|
|
5065
|
-
const contentColor = deep ? `var(--cmp-tag-${color}-deep-content, var(--cmp-tag-deep-content))` : `var(--cmp-tag-${color}-content)`;
|
|
5066
|
-
const bgColor = deep ? `var(--cmp-tag-${color}-deep-bg)` : `var(--cmp-tag-${color}-bg)`;
|
|
5067
|
-
const iconNode = icon ? /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.iconSize, color: contentColor }) : null;
|
|
5068
|
-
const resolvedWidth = typeof width === "number" ? `${width}px` : width;
|
|
5069
|
-
return /* @__PURE__ */ jsxs(
|
|
5070
|
-
"span",
|
|
5071
|
-
{
|
|
5072
|
-
ref,
|
|
5073
|
-
"aria-label": label || "tag",
|
|
5074
|
-
className: cn(
|
|
5075
|
-
"box-border inline-flex w-fit select-none items-center justify-center whitespace-nowrap",
|
|
5076
|
-
className
|
|
5077
|
-
),
|
|
5078
|
-
style: {
|
|
5079
|
-
minHeight: s.height,
|
|
5080
|
-
padding: `0 ${s.paddingX}px`,
|
|
5081
|
-
gap: s.gap,
|
|
5082
|
-
borderRadius: shape === "pill" ? 999 : s.radius,
|
|
5083
|
-
fontSize: s.fontSize,
|
|
5084
|
-
fontWeight: s.fontWeight,
|
|
5085
|
-
lineHeight: `${s.lineHeight}px`,
|
|
5086
|
-
background: bgColor,
|
|
5087
|
-
color: contentColor,
|
|
5088
|
-
...resolvedWidth != null ? { width: resolvedWidth } : {},
|
|
5089
|
-
...style
|
|
5090
|
-
},
|
|
5091
|
-
...rest,
|
|
5092
|
-
children: [
|
|
5093
|
-
icon && iconLeft && iconNode,
|
|
5094
|
-
label && // leading-none: 태그는 min-height 로 높이가 정해지고 flex 가 세로 중앙 정렬하므로
|
|
5095
|
-
// 레이블에 line-height 가 필요 없다. 오히려 line-height 를 주면 브라우저가
|
|
5096
|
-
// 폰트 ascent/descent 를 정수 px 로 반올림한 뒤 남는 half-leading 을 내림 처리해
|
|
5097
|
-
// 베이스라인이 최대 1px 위로 밀린다(xs 에서 특히 눈에 띈다).
|
|
5098
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex min-w-0 items-center justify-center leading-none", children: label }),
|
|
5099
|
-
icon && !iconLeft && iconNode
|
|
5100
|
-
]
|
|
5101
|
-
}
|
|
5102
|
-
);
|
|
5103
|
-
});
|
|
5104
|
-
var SIZE = {
|
|
5105
|
-
xxs: { icon: 12, radius: "sm" },
|
|
5106
|
-
xs: { icon: 16, radius: "sm" },
|
|
5107
|
-
sm: { icon: 20, radius: "sm" },
|
|
5108
|
-
md: { icon: 24, radius: "md" },
|
|
5109
|
-
lg: { icon: 32, radius: "md" }
|
|
5110
|
-
};
|
|
5111
|
-
var TOOLTIP_HIDE_DELAY_MS = 100;
|
|
5112
|
-
function SGhostButton({
|
|
5113
|
-
icon,
|
|
5114
|
-
size = "sm",
|
|
5115
|
-
intent = "default",
|
|
5116
|
-
ariaLabel = "",
|
|
5117
|
-
ariaPressed,
|
|
5118
|
-
ariaExpanded,
|
|
5119
|
-
tooltipText,
|
|
5120
|
-
disabled = false,
|
|
5121
|
-
onClick,
|
|
5122
|
-
anchorClassName,
|
|
5123
|
-
anchorStyle,
|
|
5124
|
-
className,
|
|
5125
|
-
style
|
|
5126
|
-
}) {
|
|
5127
|
-
const portalContainer = usePortalContainer();
|
|
5128
|
-
const [open, setOpen] = useState(false);
|
|
5129
|
-
const hideTimer = useRef(void 0);
|
|
5130
|
-
const cancelHide = () => {
|
|
5131
|
-
if (hideTimer.current) {
|
|
5132
|
-
clearTimeout(hideTimer.current);
|
|
5133
|
-
hideTimer.current = void 0;
|
|
5134
|
-
}
|
|
5135
|
-
};
|
|
5136
|
-
const openNow = () => {
|
|
5137
|
-
cancelHide();
|
|
5138
|
-
setOpen(true);
|
|
5139
|
-
};
|
|
5140
|
-
const startHide = () => {
|
|
5141
|
-
cancelHide();
|
|
5142
|
-
hideTimer.current = setTimeout(() => setOpen(false), TOOLTIP_HIDE_DELAY_MS);
|
|
5143
|
-
};
|
|
5144
|
-
const s = SIZE[size];
|
|
5145
|
-
const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
|
|
5146
|
-
const text = (tooltipText ?? "").trim();
|
|
5147
|
-
const hasTooltip = text !== "";
|
|
5148
|
-
const btn2 = /* @__PURE__ */ jsxs(
|
|
5149
|
-
"button",
|
|
5150
|
-
{
|
|
5151
|
-
type: "button",
|
|
5152
|
-
disabled,
|
|
5153
|
-
"aria-disabled": disabled ? "true" : void 0,
|
|
5154
|
-
"aria-label": ariaLabel.trim() || void 0,
|
|
5155
|
-
"aria-pressed": ariaPressed,
|
|
5156
|
-
"aria-expanded": ariaExpanded,
|
|
5157
|
-
tabIndex: disabled ? -1 : void 0,
|
|
5158
|
-
onClick: (e) => {
|
|
5159
|
-
if (disabled) {
|
|
5160
|
-
e.preventDefault();
|
|
5161
|
-
return;
|
|
5162
|
-
}
|
|
5163
|
-
onClick?.(e);
|
|
5164
|
-
},
|
|
6111
|
+
const iconColor = disabled ? "var(--cmp-checkbox-checked-icon-disabled)" : "var(--cmp-checkbox-checked-icon-default)";
|
|
6112
|
+
const labelColor = disabled ? "var(--cmp-checkbox-label-disabled)" : inverse ? "var(--cmp-checkbox-label-inverse)" : "var(--cmp-checkbox-label-default)";
|
|
6113
|
+
return /* @__PURE__ */ jsxs(
|
|
6114
|
+
"label",
|
|
6115
|
+
{
|
|
5165
6116
|
className: cn(
|
|
5166
|
-
"
|
|
6117
|
+
"inline-flex items-center gap-[var(--cmp-checkbox-gap)] align-middle",
|
|
5167
6118
|
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
5168
|
-
"focus-visible:outline-none focus-visible:shadow-[0_0_0_2px_var(--cmp-ghostButton-action-hover-bg)]",
|
|
5169
6119
|
className
|
|
5170
6120
|
),
|
|
5171
|
-
style
|
|
5172
|
-
width: `var(--cmp-ghostButton-${size}-size)`,
|
|
5173
|
-
height: `var(--cmp-ghostButton-${size}-size)`,
|
|
5174
|
-
borderRadius: `var(--cmp-ghostButton-radius-${s.radius})`,
|
|
5175
|
-
...style
|
|
5176
|
-
},
|
|
6121
|
+
style,
|
|
5177
6122
|
children: [
|
|
5178
|
-
|
|
5179
|
-
|
|
6123
|
+
/* @__PURE__ */ jsx(
|
|
6124
|
+
RCheckbox.Root,
|
|
5180
6125
|
{
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
6126
|
+
checked: state2,
|
|
6127
|
+
disabled,
|
|
6128
|
+
onCheckedChange: handleChange,
|
|
6129
|
+
className: cn(
|
|
6130
|
+
"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",
|
|
6131
|
+
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
|
6132
|
+
!disabled && !isChecked && !inverse && "hover:border-[color:var(--cmp-checkbox-unchecked-border-hover)] hover:bg-[var(--cmp-checkbox-unchecked-bg-hover)]"
|
|
6133
|
+
),
|
|
6134
|
+
style: { "--cb-bg": boxBg, "--cb-border": boxBorder },
|
|
6135
|
+
children: /* @__PURE__ */ jsx(RCheckbox.Indicator, { className: "flex items-center justify-center leading-none", children: /* @__PURE__ */ jsx(
|
|
6136
|
+
SIcon,
|
|
6137
|
+
{
|
|
6138
|
+
name: state2 === "indeterminate" ? "checkboxIndeterminate" : "checkboxCheck",
|
|
6139
|
+
size: 12,
|
|
6140
|
+
color: iconColor
|
|
6141
|
+
}
|
|
6142
|
+
) })
|
|
5184
6143
|
}
|
|
5185
6144
|
),
|
|
5186
|
-
|
|
6145
|
+
label && // 고스트(500) 텍스트로 너비를 고정 → 두께 400↔500 전환 시 레이아웃이 밀리지 않음
|
|
6146
|
+
/* @__PURE__ */ jsxs("span", { className: "grid text-nowrap text-[12px] leading-[20px]", style: { color: labelColor }, children: [
|
|
6147
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible font-medium", style: { gridArea: "1 / 1" }, children: label }),
|
|
6148
|
+
/* @__PURE__ */ jsx("span", { style: { gridArea: "1 / 1", fontWeight: isChecked ? 500 : 400 }, children: label })
|
|
6149
|
+
] })
|
|
5187
6150
|
]
|
|
5188
6151
|
}
|
|
5189
6152
|
);
|
|
5190
|
-
if (!hasTooltip) return btn2;
|
|
5191
|
-
return /* @__PURE__ */ jsxs(RPopover12.Root, { open, onOpenChange: setOpen, children: [
|
|
5192
|
-
/* @__PURE__ */ jsx(RPopover12.Anchor, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
5193
|
-
"span",
|
|
5194
|
-
{
|
|
5195
|
-
className: cn("inline-flex", anchorClassName),
|
|
5196
|
-
style: anchorStyle,
|
|
5197
|
-
onMouseEnter: openNow,
|
|
5198
|
-
onMouseLeave: startHide,
|
|
5199
|
-
onFocus: openNow,
|
|
5200
|
-
onBlur: startHide,
|
|
5201
|
-
children: btn2
|
|
5202
|
-
}
|
|
5203
|
-
) }),
|
|
5204
|
-
/* @__PURE__ */ jsx(RPopover12.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
5205
|
-
RPopover12.Content,
|
|
5206
|
-
{
|
|
5207
|
-
side: "top",
|
|
5208
|
-
sideOffset: 4,
|
|
5209
|
-
className: cn("z-50", FLOATING_SLIDE_ANIM),
|
|
5210
|
-
"aria-hidden": true,
|
|
5211
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
5212
|
-
onMouseEnter: cancelHide,
|
|
5213
|
-
onMouseLeave: startHide,
|
|
5214
|
-
children: /* @__PURE__ */ jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
|
|
5215
|
-
}
|
|
5216
|
-
) })
|
|
5217
|
-
] });
|
|
5218
6153
|
}
|
|
5219
6154
|
var TREE_LABEL_TYPOGRAPHY = {
|
|
5220
6155
|
sm: {
|
|
@@ -5402,443 +6337,207 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
|
|
|
5402
6337
|
"group/tree-item box-border flex w-full items-center gap-(--cmp-tree-item-rowGap) overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left",
|
|
5403
6338
|
typography.rowHeight,
|
|
5404
6339
|
border && "border-b border-(--cmp-tree-item-border-default)",
|
|
5405
|
-
!node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
|
|
5406
|
-
node.disabled && "cursor-not-allowed opacity-60",
|
|
5407
|
-
!node.disabled && hasChildren && "cursor-pointer",
|
|
5408
|
-
className
|
|
5409
|
-
),
|
|
5410
|
-
...rest,
|
|
5411
|
-
children: [
|
|
5412
|
-
/* @__PURE__ */ jsx(
|
|
5413
|
-
TreeConnector,
|
|
5414
|
-
{
|
|
5415
|
-
guideline,
|
|
5416
|
-
size,
|
|
5417
|
-
depth,
|
|
5418
|
-
hasChildren,
|
|
5419
|
-
isLast: last,
|
|
5420
|
-
ancestorLast
|
|
5421
|
-
}
|
|
5422
|
-
),
|
|
5423
|
-
/* @__PURE__ */ jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
5424
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
5425
|
-
SGhostButton,
|
|
5426
|
-
{
|
|
5427
|
-
icon: expanded ? "caretDown" : "caretRight",
|
|
5428
|
-
size: "xxs",
|
|
5429
|
-
ariaLabel: expanded ? "collapse tree item" : "expand tree item",
|
|
5430
|
-
ariaExpanded: expanded,
|
|
5431
|
-
disabled: node.disabled,
|
|
5432
|
-
onClick: (event) => {
|
|
5433
|
-
event.stopPropagation();
|
|
5434
|
-
if (node.disabled) return;
|
|
5435
|
-
onToggle?.(node, event);
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
|
-
) : /* @__PURE__ */ jsx("span", { className: "size-(--cmp-tree-item-arrow-icon) shrink-0", "aria-hidden": "true" }),
|
|
5439
|
-
leadingNode,
|
|
5440
|
-
selectable && /* @__PURE__ */ jsx(
|
|
5441
|
-
"span",
|
|
5442
|
-
{
|
|
5443
|
-
onClick: (event) => event.stopPropagation(),
|
|
5444
|
-
className: "flex shrink-0",
|
|
5445
|
-
"aria-hidden": node.disabled ? "true" : void 0,
|
|
5446
|
-
children: /* @__PURE__ */ jsx(
|
|
5447
|
-
SCheckbox,
|
|
5448
|
-
{
|
|
5449
|
-
value: checkboxValue,
|
|
5450
|
-
disabled: node.disabled,
|
|
5451
|
-
onValueChange: () => handleSelect()
|
|
5452
|
-
}
|
|
5453
|
-
)
|
|
5454
|
-
}
|
|
5455
|
-
),
|
|
5456
|
-
/* @__PURE__ */ jsx(
|
|
5457
|
-
"span",
|
|
5458
|
-
{
|
|
5459
|
-
onClick: (event) => {
|
|
5460
|
-
if (!selectable) return;
|
|
5461
|
-
event.stopPropagation();
|
|
5462
|
-
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
5463
|
-
},
|
|
5464
|
-
className: cn(
|
|
5465
|
-
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
5466
|
-
labelTypo,
|
|
5467
|
-
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
5468
|
-
),
|
|
5469
|
-
children: node.label
|
|
5470
|
-
}
|
|
5471
|
-
),
|
|
5472
|
-
trailingNode
|
|
5473
|
-
] })
|
|
5474
|
-
]
|
|
5475
|
-
}
|
|
5476
|
-
);
|
|
5477
|
-
});
|
|
5478
|
-
var STreeItem2 = /* @__PURE__ */ withDisplayName(STreeItemImpl, "STreeItem");
|
|
5479
|
-
var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
5480
|
-
items,
|
|
5481
|
-
value,
|
|
5482
|
-
defaultValue,
|
|
5483
|
-
expandedIds,
|
|
5484
|
-
defaultExpandedIds,
|
|
5485
|
-
selectable = true,
|
|
5486
|
-
size = "sm",
|
|
5487
|
-
showSelectAll = false,
|
|
5488
|
-
cascadeSelection = true,
|
|
5489
|
-
guideline = true,
|
|
5490
|
-
border = true,
|
|
5491
|
-
leading,
|
|
5492
|
-
trailing,
|
|
5493
|
-
onValueChange,
|
|
5494
|
-
onExpandedChange,
|
|
5495
|
-
className,
|
|
5496
|
-
...rest
|
|
5497
|
-
}, ref) {
|
|
5498
|
-
const [internalValue, setInternalValue] = useState(defaultValue ?? []);
|
|
5499
|
-
const [internalExpandedIds, setInternalExpandedIds] = useState(
|
|
5500
|
-
defaultExpandedIds ?? items.filter((item4) => item4.children?.length).map((item4) => item4.id)
|
|
5501
|
-
);
|
|
5502
|
-
const currentValue = value ?? internalValue;
|
|
5503
|
-
const currentExpandedIds = expandedIds ?? internalExpandedIds;
|
|
5504
|
-
const selectedSet = useMemo(() => toSelectedSet(currentValue), [currentValue]);
|
|
5505
|
-
const expandedSet = useMemo(() => new Set(currentExpandedIds), [currentExpandedIds]);
|
|
5506
|
-
const selectableIds = useMemo(() => items.flatMap(collectSelectableIds), [items]);
|
|
5507
|
-
const allSelected = selectableIds.length > 0 && selectableIds.every((id) => selectedSet.has(id));
|
|
5508
|
-
const someSelected = selectableIds.some((id) => selectedSet.has(id));
|
|
5509
|
-
const allIndeterminate = someSelected && !allSelected;
|
|
5510
|
-
const showAllItem = selectable && showSelectAll;
|
|
5511
|
-
const updateExpanded = (node) => {
|
|
5512
|
-
const next = new Set(currentExpandedIds);
|
|
5513
|
-
if (next.has(node.id)) next.delete(node.id);
|
|
5514
|
-
else next.add(node.id);
|
|
5515
|
-
const nextValue = Array.from(next);
|
|
5516
|
-
if (expandedIds === void 0) setInternalExpandedIds(nextValue);
|
|
5517
|
-
onExpandedChange?.(nextValue, node);
|
|
5518
|
-
};
|
|
5519
|
-
const updateSelected = (node) => {
|
|
5520
|
-
if (node.disabled) return;
|
|
5521
|
-
const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
|
|
5522
|
-
const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
|
|
5523
|
-
const next = new Set(selectedSet);
|
|
5524
|
-
targetIds.forEach((id) => {
|
|
5525
|
-
if (everySelected) next.delete(id);
|
|
5526
|
-
else next.add(id);
|
|
5527
|
-
});
|
|
5528
|
-
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
5529
|
-
if (value === void 0) setInternalValue(orderedIds);
|
|
5530
|
-
onValueChange?.(orderedIds, node);
|
|
5531
|
-
};
|
|
5532
|
-
const updateAllSelected = (event) => {
|
|
5533
|
-
event?.stopPropagation();
|
|
5534
|
-
if (selectableIds.length === 0) return;
|
|
5535
|
-
const next = new Set(selectedSet);
|
|
5536
|
-
selectableIds.forEach((id) => {
|
|
5537
|
-
if (allSelected) next.delete(id);
|
|
5538
|
-
else next.add(id);
|
|
5539
|
-
});
|
|
5540
|
-
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
5541
|
-
if (value === void 0) setInternalValue(orderedIds);
|
|
5542
|
-
onValueChange?.(orderedIds, TREE_ALL_NODE);
|
|
5543
|
-
};
|
|
5544
|
-
const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
|
|
5545
|
-
const isLast = index === nodes.length - 1;
|
|
5546
|
-
const isExpanded = expandedSet.has(node.id);
|
|
5547
|
-
const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
|
|
5548
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5549
|
-
/* @__PURE__ */ jsx(
|
|
5550
|
-
STreeItem2,
|
|
5551
|
-
{
|
|
5552
|
-
node,
|
|
5553
|
-
depth,
|
|
5554
|
-
last: isLast,
|
|
5555
|
-
ancestorLast,
|
|
5556
|
-
expanded: isExpanded,
|
|
5557
|
-
selected,
|
|
5558
|
-
indeterminate,
|
|
5559
|
-
selectable,
|
|
5560
|
-
size,
|
|
5561
|
-
guideline,
|
|
5562
|
-
border,
|
|
5563
|
-
leading,
|
|
5564
|
-
trailing,
|
|
5565
|
-
onToggle: updateExpanded,
|
|
5566
|
-
onTreeSelect: updateSelected
|
|
5567
|
-
}
|
|
5568
|
-
),
|
|
5569
|
-
node.children?.length ? /* @__PURE__ */ jsx(
|
|
5570
|
-
"div",
|
|
5571
|
-
{
|
|
5572
|
-
"aria-hidden": !isExpanded,
|
|
5573
|
-
className: cn(
|
|
5574
|
-
"grid w-full overflow-hidden transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
|
|
5575
|
-
isExpanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
|
|
5576
|
-
),
|
|
5577
|
-
children: /* @__PURE__ */ jsx("div", { className: "min-h-0 overflow-hidden", children: renderNodes(node.children, depth + 1, [...ancestorLast, isLast]) })
|
|
5578
|
-
}
|
|
5579
|
-
) : null
|
|
5580
|
-
] }, node.id);
|
|
5581
|
-
});
|
|
5582
|
-
return /* @__PURE__ */ jsxs(
|
|
5583
|
-
"div",
|
|
5584
|
-
{
|
|
5585
|
-
ref,
|
|
5586
|
-
role: "tree",
|
|
5587
|
-
className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
|
|
6340
|
+
!node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
|
|
6341
|
+
node.disabled && "cursor-not-allowed opacity-60",
|
|
6342
|
+
!node.disabled && hasChildren && "cursor-pointer",
|
|
6343
|
+
className
|
|
6344
|
+
),
|
|
5588
6345
|
...rest,
|
|
5589
6346
|
children: [
|
|
5590
|
-
|
|
5591
|
-
|
|
6347
|
+
/* @__PURE__ */ jsx(
|
|
6348
|
+
TreeConnector,
|
|
5592
6349
|
{
|
|
5593
|
-
|
|
5594
|
-
indeterminate: allIndeterminate,
|
|
5595
|
-
border,
|
|
6350
|
+
guideline,
|
|
5596
6351
|
size,
|
|
5597
|
-
|
|
6352
|
+
depth,
|
|
6353
|
+
hasChildren,
|
|
6354
|
+
isLast: last,
|
|
6355
|
+
ancestorLast
|
|
5598
6356
|
}
|
|
5599
6357
|
),
|
|
5600
|
-
|
|
6358
|
+
/* @__PURE__ */ jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
|
|
6359
|
+
hasChildren ? /* @__PURE__ */ jsx(
|
|
6360
|
+
SGhostButton,
|
|
6361
|
+
{
|
|
6362
|
+
icon: expanded ? "caretDown" : "caretRight",
|
|
6363
|
+
size: "xxs",
|
|
6364
|
+
ariaLabel: expanded ? "collapse tree item" : "expand tree item",
|
|
6365
|
+
ariaExpanded: expanded,
|
|
6366
|
+
disabled: node.disabled,
|
|
6367
|
+
onClick: (event) => {
|
|
6368
|
+
event.stopPropagation();
|
|
6369
|
+
if (node.disabled) return;
|
|
6370
|
+
onToggle?.(node, event);
|
|
6371
|
+
}
|
|
6372
|
+
}
|
|
6373
|
+
) : /* @__PURE__ */ jsx("span", { className: "size-(--cmp-tree-item-arrow-icon) shrink-0", "aria-hidden": "true" }),
|
|
6374
|
+
leadingNode,
|
|
6375
|
+
selectable && /* @__PURE__ */ jsx(
|
|
6376
|
+
"span",
|
|
6377
|
+
{
|
|
6378
|
+
onClick: (event) => event.stopPropagation(),
|
|
6379
|
+
className: "flex shrink-0",
|
|
6380
|
+
"aria-hidden": node.disabled ? "true" : void 0,
|
|
6381
|
+
children: /* @__PURE__ */ jsx(
|
|
6382
|
+
SCheckbox,
|
|
6383
|
+
{
|
|
6384
|
+
value: checkboxValue,
|
|
6385
|
+
disabled: node.disabled,
|
|
6386
|
+
onValueChange: () => handleSelect()
|
|
6387
|
+
}
|
|
6388
|
+
)
|
|
6389
|
+
}
|
|
6390
|
+
),
|
|
6391
|
+
/* @__PURE__ */ jsx(
|
|
6392
|
+
"span",
|
|
6393
|
+
{
|
|
6394
|
+
onClick: (event) => {
|
|
6395
|
+
if (!selectable) return;
|
|
6396
|
+
event.stopPropagation();
|
|
6397
|
+
if (!node.disabled && selectable) onTreeSelect?.(node, event);
|
|
6398
|
+
},
|
|
6399
|
+
className: cn(
|
|
6400
|
+
"block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
|
|
6401
|
+
labelTypo,
|
|
6402
|
+
node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
|
|
6403
|
+
),
|
|
6404
|
+
children: node.label
|
|
6405
|
+
}
|
|
6406
|
+
),
|
|
6407
|
+
trailingNode
|
|
6408
|
+
] })
|
|
5601
6409
|
]
|
|
5602
6410
|
}
|
|
5603
6411
|
);
|
|
5604
6412
|
});
|
|
5605
|
-
var
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
"BASE",
|
|
5623
|
-
"NOSCRIPT",
|
|
5624
|
-
// SVG/MATH 는 foreign-content 파싱 모드로 전환되어 재직렬화 시 다른 트리로
|
|
5625
|
-
// 재파싱될 수 있다(mXSS 벡터). 인라인 라벨에 필요 없으므로 통째로 제거한다.
|
|
5626
|
-
"SVG",
|
|
5627
|
-
"MATH",
|
|
5628
|
-
"TEMPLATE"
|
|
5629
|
-
]);
|
|
5630
|
-
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5631
|
-
var sanitizeNode = (node) => {
|
|
5632
|
-
if (node.nodeType === Node.COMMENT_NODE) {
|
|
5633
|
-
node.remove();
|
|
5634
|
-
return;
|
|
5635
|
-
}
|
|
5636
|
-
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
5637
|
-
const element = node;
|
|
5638
|
-
const tagName = element.tagName.toUpperCase();
|
|
5639
|
-
if (DROP_CONTENT_TAGS.has(tagName)) {
|
|
5640
|
-
element.remove();
|
|
5641
|
-
return;
|
|
5642
|
-
}
|
|
5643
|
-
Array.from(element.childNodes).forEach((child) => sanitizeNode(child));
|
|
5644
|
-
if (ALLOWED_INLINE_TAGS.has(tagName)) {
|
|
5645
|
-
if (element.hasAttribute("className")) {
|
|
5646
|
-
const val = element.getAttribute("className");
|
|
5647
|
-
element.removeAttribute("className");
|
|
5648
|
-
if (!element.hasAttribute("class")) element.setAttribute("class", val);
|
|
5649
|
-
}
|
|
5650
|
-
const allowedAttrs = ALLOWED_ATTRS_BY_TAG[tagName] ?? COMMON_ALLOWED_ATTRS;
|
|
5651
|
-
Array.from(element.attributes).forEach((attr) => {
|
|
5652
|
-
if (!allowedAttrs.has(attr.name)) element.removeAttribute(attr.name);
|
|
5653
|
-
});
|
|
5654
|
-
if (tagName === "A") {
|
|
5655
|
-
const href = element.getAttribute("href");
|
|
5656
|
-
if (href !== null && href !== "" && !SAFE_HREF_RE.test(href)) element.removeAttribute("href");
|
|
5657
|
-
if (element.hasAttribute("target")) {
|
|
5658
|
-
element.setAttribute("rel", "noopener noreferrer");
|
|
5659
|
-
}
|
|
5660
|
-
}
|
|
5661
|
-
return;
|
|
5662
|
-
}
|
|
5663
|
-
const parent = element.parentNode;
|
|
5664
|
-
if (parent == null) return;
|
|
5665
|
-
while (element.firstChild) parent.insertBefore(element.firstChild, element);
|
|
5666
|
-
parent.removeChild(element);
|
|
5667
|
-
};
|
|
5668
|
-
var sanitizeInlineHtml = (value) => {
|
|
5669
|
-
if (typeof document === "undefined") return escapeHtml(value);
|
|
5670
|
-
const template = document.createElement("template");
|
|
5671
|
-
template.innerHTML = value;
|
|
5672
|
-
Array.from(template.content.childNodes).forEach((child) => sanitizeNode(child));
|
|
5673
|
-
return template.innerHTML;
|
|
5674
|
-
};
|
|
5675
|
-
var HIDE_DELAY_MS = 100;
|
|
5676
|
-
function useBody(content, message = []) {
|
|
5677
|
-
if (content != null) return content;
|
|
5678
|
-
if (message.length === 0) return null;
|
|
5679
|
-
const singleLine = message.length === 1;
|
|
5680
|
-
return /* @__PURE__ */ jsx(Fragment, { children: message.map((line, i) => /* @__PURE__ */ jsx(
|
|
5681
|
-
"div",
|
|
5682
|
-
{
|
|
5683
|
-
className: singleLine ? "leading-[24px]" : void 0,
|
|
5684
|
-
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(line) }
|
|
5685
|
-
},
|
|
5686
|
-
i
|
|
5687
|
-
)) });
|
|
5688
|
-
}
|
|
5689
|
-
var STooltipImpl = /* @__PURE__ */ forwardRef(function STooltip({
|
|
5690
|
-
content,
|
|
5691
|
-
message = [],
|
|
5692
|
-
open: openProp,
|
|
5693
|
-
onOpenChange,
|
|
5694
|
-
trigger = "hover",
|
|
5695
|
-
placement = "top",
|
|
5696
|
-
sideOffset = 8,
|
|
5697
|
-
tooltipType = "default",
|
|
5698
|
-
showClose = false,
|
|
5699
|
-
disabled = false,
|
|
5700
|
-
children,
|
|
5701
|
-
icon = "helpOutline",
|
|
5702
|
-
iconSize = 12,
|
|
5703
|
-
color = "#01BB4B",
|
|
5704
|
-
ariaLabel,
|
|
6413
|
+
var STreeItem2 = /* @__PURE__ */ withDisplayName(STreeItemImpl, "STreeItem");
|
|
6414
|
+
var STreeImpl = /* @__PURE__ */ forwardRef(function STree({
|
|
6415
|
+
items,
|
|
6416
|
+
value,
|
|
6417
|
+
defaultValue,
|
|
6418
|
+
expandedIds,
|
|
6419
|
+
defaultExpandedIds,
|
|
6420
|
+
selectable = true,
|
|
6421
|
+
size = "sm",
|
|
6422
|
+
showSelectAll = false,
|
|
6423
|
+
cascadeSelection = true,
|
|
6424
|
+
guideline = true,
|
|
6425
|
+
border = true,
|
|
6426
|
+
leading,
|
|
6427
|
+
trailing,
|
|
6428
|
+
onValueChange,
|
|
6429
|
+
onExpandedChange,
|
|
5705
6430
|
className,
|
|
5706
|
-
|
|
5707
|
-
style,
|
|
5708
|
-
contentProps
|
|
6431
|
+
...rest
|
|
5709
6432
|
}, ref) {
|
|
5710
|
-
const
|
|
5711
|
-
const [
|
|
5712
|
-
|
|
5713
|
-
const open = isControlled ? openProp : internalOpen;
|
|
5714
|
-
const hideTimer = useRef(void 0);
|
|
5715
|
-
const cancelHide = useCallback(() => {
|
|
5716
|
-
if (hideTimer.current) {
|
|
5717
|
-
clearTimeout(hideTimer.current);
|
|
5718
|
-
hideTimer.current = void 0;
|
|
5719
|
-
}
|
|
5720
|
-
}, []);
|
|
5721
|
-
const setOpenState = useCallback(
|
|
5722
|
-
(next) => {
|
|
5723
|
-
if (!isControlled) setInternalOpen(next);
|
|
5724
|
-
onOpenChange?.(next);
|
|
5725
|
-
},
|
|
5726
|
-
[isControlled, onOpenChange]
|
|
5727
|
-
);
|
|
5728
|
-
const openNow = () => {
|
|
5729
|
-
cancelHide();
|
|
5730
|
-
setOpenState(true);
|
|
5731
|
-
};
|
|
5732
|
-
const startHide = () => {
|
|
5733
|
-
if (showClose) return;
|
|
5734
|
-
cancelHide();
|
|
5735
|
-
hideTimer.current = setTimeout(() => setOpenState(false), HIDE_DELAY_MS);
|
|
5736
|
-
};
|
|
5737
|
-
useImperativeHandle(
|
|
5738
|
-
ref,
|
|
5739
|
-
() => ({
|
|
5740
|
-
show: () => {
|
|
5741
|
-
cancelHide();
|
|
5742
|
-
setOpenState(true);
|
|
5743
|
-
},
|
|
5744
|
-
hide: () => {
|
|
5745
|
-
cancelHide();
|
|
5746
|
-
setOpenState(false);
|
|
5747
|
-
}
|
|
5748
|
-
}),
|
|
5749
|
-
[cancelHide, setOpenState]
|
|
5750
|
-
);
|
|
5751
|
-
const isHover = trigger === "hover";
|
|
5752
|
-
const isNone = trigger === "none";
|
|
5753
|
-
if (isNone && children == null && typeof console !== "undefined") {
|
|
5754
|
-
console.warn(
|
|
5755
|
-
'[STooltip] trigger="none" \uC740 \uC704\uCE58 \uAE30\uC900\uC774 \uB420 children \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC544\uC774\uCF58 \uD2B8\uB9AC\uAC70\uB85C \uD3F4\uBC31\uD569\uB2C8\uB2E4.'
|
|
5756
|
-
);
|
|
5757
|
-
}
|
|
5758
|
-
const body = useBody(content, message);
|
|
5759
|
-
const bg = `var(--cmp-tooltip-${tooltipType}-bg)`;
|
|
5760
|
-
const fg = `var(--cmp-tooltip-${tooltipType}-content)`;
|
|
5761
|
-
const triggerNode = children ?? /* @__PURE__ */ jsx("span", { className: cn("inline-flex cursor-pointer", triggerClassName), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(SIcon, { name: icon, size: iconSize, color }) });
|
|
5762
|
-
if (disabled || body == null) return /* @__PURE__ */ jsx(Fragment, { children: triggerNode });
|
|
5763
|
-
const {
|
|
5764
|
-
className: contentPropsClassName,
|
|
5765
|
-
style: contentPropsStyle,
|
|
5766
|
-
...restContentProps
|
|
5767
|
-
} = contentProps ?? {};
|
|
5768
|
-
const contentClass = cn(
|
|
5769
|
-
"z-50 w-fit max-w-[var(--radix-popover-content-available-width)] rounded-[6px] px-[16px] py-[12px] text-[12px] leading-[20px] shadow-normal-sm",
|
|
5770
|
-
FLOATING_SLIDE_ANIM,
|
|
5771
|
-
className,
|
|
5772
|
-
contentPropsClassName
|
|
6433
|
+
const [internalValue, setInternalValue] = useState(defaultValue ?? []);
|
|
6434
|
+
const [internalExpandedIds, setInternalExpandedIds] = useState(
|
|
6435
|
+
defaultExpandedIds ?? items.filter((item4) => item4.children?.length).map((item4) => item4.id)
|
|
5773
6436
|
);
|
|
5774
|
-
const
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
6437
|
+
const currentValue = value ?? internalValue;
|
|
6438
|
+
const currentExpandedIds = expandedIds ?? internalExpandedIds;
|
|
6439
|
+
const selectedSet = useMemo(() => toSelectedSet(currentValue), [currentValue]);
|
|
6440
|
+
const expandedSet = useMemo(() => new Set(currentExpandedIds), [currentExpandedIds]);
|
|
6441
|
+
const selectableIds = useMemo(() => items.flatMap(collectSelectableIds), [items]);
|
|
6442
|
+
const allSelected = selectableIds.length > 0 && selectableIds.every((id) => selectedSet.has(id));
|
|
6443
|
+
const someSelected = selectableIds.some((id) => selectedSet.has(id));
|
|
6444
|
+
const allIndeterminate = someSelected && !allSelected;
|
|
6445
|
+
const showAllItem = selectable && showSelectAll;
|
|
6446
|
+
const updateExpanded = (node) => {
|
|
6447
|
+
const next = new Set(currentExpandedIds);
|
|
6448
|
+
if (next.has(node.id)) next.delete(node.id);
|
|
6449
|
+
else next.add(node.id);
|
|
6450
|
+
const nextValue = Array.from(next);
|
|
6451
|
+
if (expandedIds === void 0) setInternalExpandedIds(nextValue);
|
|
6452
|
+
onExpandedChange?.(nextValue, node);
|
|
5780
6453
|
};
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
)
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
6454
|
+
const updateSelected = (node) => {
|
|
6455
|
+
if (node.disabled) return;
|
|
6456
|
+
const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
|
|
6457
|
+
const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
|
|
6458
|
+
const next = new Set(selectedSet);
|
|
6459
|
+
targetIds.forEach((id) => {
|
|
6460
|
+
if (everySelected) next.delete(id);
|
|
6461
|
+
else next.add(id);
|
|
6462
|
+
});
|
|
6463
|
+
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
6464
|
+
if (value === void 0) setInternalValue(orderedIds);
|
|
6465
|
+
onValueChange?.(orderedIds, node);
|
|
6466
|
+
};
|
|
6467
|
+
const updateAllSelected = (event) => {
|
|
6468
|
+
event?.stopPropagation();
|
|
6469
|
+
if (selectableIds.length === 0) return;
|
|
6470
|
+
const next = new Set(selectedSet);
|
|
6471
|
+
selectableIds.forEach((id) => {
|
|
6472
|
+
if (allSelected) next.delete(id);
|
|
6473
|
+
else next.add(id);
|
|
6474
|
+
});
|
|
6475
|
+
const orderedIds = collectIds(items).filter((id) => next.has(id));
|
|
6476
|
+
if (value === void 0) setInternalValue(orderedIds);
|
|
6477
|
+
onValueChange?.(orderedIds, TREE_ALL_NODE);
|
|
6478
|
+
};
|
|
6479
|
+
const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
|
|
6480
|
+
const isLast = index === nodes.length - 1;
|
|
6481
|
+
const isExpanded = expandedSet.has(node.id);
|
|
6482
|
+
const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
|
|
6483
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6484
|
+
/* @__PURE__ */ jsx(
|
|
6485
|
+
STreeItem2,
|
|
5790
6486
|
{
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
6487
|
+
node,
|
|
6488
|
+
depth,
|
|
6489
|
+
last: isLast,
|
|
6490
|
+
ancestorLast,
|
|
6491
|
+
expanded: isExpanded,
|
|
6492
|
+
selected,
|
|
6493
|
+
indeterminate,
|
|
6494
|
+
selectable,
|
|
6495
|
+
size,
|
|
6496
|
+
guideline,
|
|
6497
|
+
border,
|
|
6498
|
+
leading,
|
|
6499
|
+
trailing,
|
|
6500
|
+
onToggle: updateExpanded,
|
|
6501
|
+
onTreeSelect: updateSelected
|
|
5797
6502
|
}
|
|
5798
|
-
)
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
] }),
|
|
5835
|
-
/* @__PURE__ */ jsx(RPopover12.Arrow, { width: 16, height: 12, style: { fill: bg } })
|
|
5836
|
-
]
|
|
5837
|
-
}
|
|
5838
|
-
) })
|
|
5839
|
-
] });
|
|
6503
|
+
),
|
|
6504
|
+
node.children?.length ? /* @__PURE__ */ jsx(
|
|
6505
|
+
"div",
|
|
6506
|
+
{
|
|
6507
|
+
"aria-hidden": !isExpanded,
|
|
6508
|
+
className: cn(
|
|
6509
|
+
"grid w-full overflow-hidden transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none",
|
|
6510
|
+
isExpanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
|
|
6511
|
+
),
|
|
6512
|
+
children: /* @__PURE__ */ jsx("div", { className: "min-h-0 overflow-hidden", children: renderNodes(node.children, depth + 1, [...ancestorLast, isLast]) })
|
|
6513
|
+
}
|
|
6514
|
+
) : null
|
|
6515
|
+
] }, node.id);
|
|
6516
|
+
});
|
|
6517
|
+
return /* @__PURE__ */ jsxs(
|
|
6518
|
+
"div",
|
|
6519
|
+
{
|
|
6520
|
+
ref,
|
|
6521
|
+
role: "tree",
|
|
6522
|
+
className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
|
|
6523
|
+
...rest,
|
|
6524
|
+
children: [
|
|
6525
|
+
showAllItem && /* @__PURE__ */ jsx(
|
|
6526
|
+
STreeAllItem,
|
|
6527
|
+
{
|
|
6528
|
+
selected: allSelected,
|
|
6529
|
+
indeterminate: allIndeterminate,
|
|
6530
|
+
border,
|
|
6531
|
+
size,
|
|
6532
|
+
onSelect: updateAllSelected
|
|
6533
|
+
}
|
|
6534
|
+
),
|
|
6535
|
+
renderNodes(items)
|
|
6536
|
+
]
|
|
6537
|
+
}
|
|
6538
|
+
);
|
|
5840
6539
|
});
|
|
5841
|
-
var
|
|
6540
|
+
var STree2 = /* @__PURE__ */ withDisplayName(STreeImpl, "STree");
|
|
5842
6541
|
var BODY_PADDING_CLASS = {
|
|
5843
6542
|
default: "p-(--sys-space-panel-padding-default)",
|
|
5844
6543
|
wide: "p-(--sys-space-panel-padding-wide)",
|
|
@@ -11642,931 +12341,704 @@ var SStepper = /* @__PURE__ */ forwardRef(function SStepper2({
|
|
|
11642
12341
|
]
|
|
11643
12342
|
},
|
|
11644
12343
|
`${groupKey}-${group.startIndex}`
|
|
11645
|
-
);
|
|
11646
|
-
})
|
|
11647
|
-
]
|
|
11648
|
-
}
|
|
11649
|
-
);
|
|
11650
|
-
}
|
|
11651
|
-
return /* @__PURE__ */ jsx(
|
|
11652
|
-
"div",
|
|
11653
|
-
{
|
|
11654
|
-
role: "list",
|
|
11655
|
-
"aria-label": ariaLabel,
|
|
11656
|
-
className: cn("inline-flex items-center", className),
|
|
11657
|
-
style: {
|
|
11658
|
-
gap: STEPPER_LAYOUT.containerGap,
|
|
11659
|
-
fontSize: config.fontSize,
|
|
11660
|
-
lineHeight: config.lineHeight,
|
|
11661
|
-
...style
|
|
11662
|
-
},
|
|
11663
|
-
children: items.map((item4, index) => {
|
|
11664
|
-
const state2 = getState(item4, index);
|
|
11665
|
-
const content = isClickable ? /* @__PURE__ */ jsx("span", { role: "listitem", "aria-current": state2 === "active" ? "step" : void 0, children: renderClickableStepContent(item4, index) }) : renderStepContent(item4, index);
|
|
11666
|
-
return /* @__PURE__ */ jsxs(
|
|
11667
|
-
"span",
|
|
11668
|
-
{
|
|
11669
|
-
className: "inline-flex items-center",
|
|
11670
|
-
style: { gap: STEPPER_LAYOUT.containerGap },
|
|
11671
|
-
children: [
|
|
11672
|
-
content,
|
|
11673
|
-
index < items.length - 1 && /* @__PURE__ */ jsx(
|
|
11674
|
-
"span",
|
|
11675
|
-
{
|
|
11676
|
-
"aria-hidden": true,
|
|
11677
|
-
className: "inline-flex h-px shrink-0 items-center",
|
|
11678
|
-
style: { width: STEPPER_LAYOUT.dashWidth, color: STEPPER_COLORS.dash },
|
|
11679
|
-
children: /* @__PURE__ */ jsxs(
|
|
11680
|
-
"svg",
|
|
11681
|
-
{
|
|
11682
|
-
width: "20",
|
|
11683
|
-
height: "1",
|
|
11684
|
-
viewBox: "0 0 20 1",
|
|
11685
|
-
fill: "none",
|
|
11686
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
11687
|
-
children: [
|
|
11688
|
-
/* @__PURE__ */ jsx("rect", { width: "1.6", height: "1", fill: "currentColor" }),
|
|
11689
|
-
/* @__PURE__ */ jsx("rect", { x: "5", width: "3.3", height: "1", fill: "currentColor" }),
|
|
11690
|
-
/* @__PURE__ */ jsx("rect", { x: "11.7", width: "3.3", height: "1", fill: "currentColor" }),
|
|
11691
|
-
/* @__PURE__ */ jsx("rect", { x: "18.4", width: "1.6", height: "1", fill: "currentColor" })
|
|
11692
|
-
]
|
|
11693
|
-
}
|
|
11694
|
-
)
|
|
11695
|
-
}
|
|
11696
|
-
)
|
|
11697
|
-
]
|
|
11698
|
-
},
|
|
11699
|
-
getItemValue(item4, index)
|
|
11700
|
-
);
|
|
11701
|
-
})
|
|
11702
|
-
}
|
|
11703
|
-
);
|
|
11704
|
-
});
|
|
11705
|
-
|
|
11706
|
-
// src/lib/date.ts
|
|
11707
|
-
function todayStr() {
|
|
11708
|
-
const d = /* @__PURE__ */ new Date();
|
|
11709
|
-
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
11710
|
-
}
|
|
11711
|
-
function formatDate(year, month, day) {
|
|
11712
|
-
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
11713
|
-
}
|
|
11714
|
-
function calcYearMonth(year, month, dir) {
|
|
11715
|
-
if (dir === "prev")
|
|
11716
|
-
return month === 1 ? { year: year - 1, month: 12 } : { year, month: month - 1 };
|
|
11717
|
-
return month === 12 ? { year: year + 1, month: 1 } : { year, month: month + 1 };
|
|
11718
|
-
}
|
|
11719
|
-
function monthCells(year, month) {
|
|
11720
|
-
const firstDayIndex = new Date(year, month - 1, 1).getDay();
|
|
11721
|
-
const daysInCurrent = new Date(year, month, 0).getDate();
|
|
11722
|
-
const prev = calcYearMonth(year, month, "prev");
|
|
11723
|
-
const daysInPrev = new Date(prev.year, prev.month, 0).getDate();
|
|
11724
|
-
const next = calcYearMonth(year, month, "next");
|
|
11725
|
-
const cells = [];
|
|
11726
|
-
for (let i = firstDayIndex - 1; i >= 0; i--) {
|
|
11727
|
-
const day = daysInPrev - i;
|
|
11728
|
-
cells.push({ date: formatDate(prev.year, prev.month, day), day, inCurrentMonth: false });
|
|
11729
|
-
}
|
|
11730
|
-
for (let day = 1; day <= daysInCurrent; day++) {
|
|
11731
|
-
cells.push({ date: formatDate(year, month, day), day, inCurrentMonth: true });
|
|
11732
|
-
}
|
|
11733
|
-
const remaining = (7 - cells.length % 7) % 7;
|
|
11734
|
-
for (let day = 1; day <= remaining; day++) {
|
|
11735
|
-
cells.push({ date: formatDate(next.year, next.month, day), day, inCurrentMonth: false });
|
|
12344
|
+
);
|
|
12345
|
+
})
|
|
12346
|
+
]
|
|
12347
|
+
}
|
|
12348
|
+
);
|
|
11736
12349
|
}
|
|
11737
|
-
return
|
|
11738
|
-
}
|
|
11739
|
-
var WEEK_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
|
|
11740
|
-
|
|
11741
|
-
// src/components/SCalendarBoard/calendarBoard.config.ts
|
|
11742
|
-
var CALENDAR_BOARD_EVENT_COLORS = [
|
|
11743
|
-
"default",
|
|
11744
|
-
"blue",
|
|
11745
|
-
"oceanBlue",
|
|
11746
|
-
"lightBlue",
|
|
11747
|
-
"green",
|
|
11748
|
-
"yellow",
|
|
11749
|
-
"orange",
|
|
11750
|
-
"red",
|
|
11751
|
-
"white"
|
|
11752
|
-
];
|
|
11753
|
-
var BG = (name) => `var(--cmp-calendarBoard-eventButton-bg-${name})`;
|
|
11754
|
-
var CALENDAR_BOARD_EVENT_PRESETS = {
|
|
11755
|
-
default: { bg: BG("default"), dot: "indigo" },
|
|
11756
|
-
blue: { bg: BG("blue"), dot: "blue" },
|
|
11757
|
-
oceanBlue: { bg: BG("oceanBlue"), dot: "darkblue" },
|
|
11758
|
-
lightBlue: { bg: BG("lightBlue"), dot: "lightblue" },
|
|
11759
|
-
green: { bg: BG("green"), dot: "green" },
|
|
11760
|
-
yellow: { bg: BG("yellow"), dot: "yellow" },
|
|
11761
|
-
orange: { bg: BG("orange"), dot: "orange" },
|
|
11762
|
-
red: { bg: BG("red"), dot: "red" },
|
|
11763
|
-
white: { bg: BG("white"), dot: "grey" }
|
|
11764
|
-
};
|
|
11765
|
-
var CALENDAR_BOARD_MAX_VISIBLE_EVENTS = 4;
|
|
11766
|
-
var CALENDAR_BOARD_DAY_COLORS = [
|
|
11767
|
-
"default",
|
|
11768
|
-
"danger",
|
|
11769
|
-
"accent",
|
|
11770
|
-
"complete",
|
|
11771
|
-
"dim"
|
|
11772
|
-
];
|
|
11773
|
-
var CALENDAR_BOARD_DAY_BG = {
|
|
11774
|
-
default: "var(--cmp-calendarBoard-dayCard-bg)",
|
|
11775
|
-
danger: "var(--color-red-30)",
|
|
11776
|
-
accent: "var(--color-brilliantblue-40)",
|
|
11777
|
-
complete: "var(--color-green-45)",
|
|
11778
|
-
dim: "var(--color-grey-25)"
|
|
11779
|
-
};
|
|
11780
|
-
function CalendarEventButton({
|
|
11781
|
-
event,
|
|
11782
|
-
onSelect,
|
|
11783
|
-
className
|
|
11784
|
-
}) {
|
|
11785
|
-
const preset = CALENDAR_BOARD_EVENT_PRESETS[event.color ?? "default"];
|
|
11786
|
-
const dot = event.dotColor ?? preset.dot;
|
|
11787
|
-
const disabled = event.disabled === true;
|
|
11788
|
-
const hasDescription = event.description != null && event.description !== "";
|
|
11789
|
-
const hasValue = event.value != null && event.value !== "";
|
|
11790
|
-
const title = [event.label.replace(/<[^>]*>/g, ""), event.description, event.value].filter((v) => v != null && v !== "").join(" ") || void 0;
|
|
11791
|
-
return /* @__PURE__ */ jsxs(
|
|
11792
|
-
"button",
|
|
11793
|
-
{
|
|
11794
|
-
type: "button",
|
|
11795
|
-
disabled,
|
|
11796
|
-
title,
|
|
11797
|
-
className: cn(
|
|
11798
|
-
// hover 는 배경 위에 8% 오버레이를 얹는다 — 프리셋 배경이 9종이라 색마다 hover 색을 두지 않는다.
|
|
11799
|
-
"group relative flex w-full min-w-0 items-center overflow-hidden text-left",
|
|
11800
|
-
"h-(--cmp-calendarBoard-item-height) shrink-0 rounded-(--cmp-calendarBoard-item-radius)",
|
|
11801
|
-
"gap-(--cmp-calendarBoard-eventButton-inline-gap) px-(--cmp-calendarBoard-item-paddingX)",
|
|
11802
|
-
"bg-(--ceb-bg) text-(--cmp-calendarBoard-eventButton-text-color-default)",
|
|
11803
|
-
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
11804
|
-
className
|
|
11805
|
-
),
|
|
11806
|
-
style: { "--ceb-bg": preset.bg },
|
|
11807
|
-
onClick: (e) => {
|
|
11808
|
-
if (disabled) return;
|
|
11809
|
-
onSelect?.(event, e);
|
|
11810
|
-
},
|
|
11811
|
-
children: [
|
|
11812
|
-
!disabled && /* @__PURE__ */ jsx(
|
|
11813
|
-
"span",
|
|
11814
|
-
{
|
|
11815
|
-
"aria-hidden": true,
|
|
11816
|
-
className: "pointer-events-none absolute inset-0 rounded-(--cmp-calendarBoard-item-radius) bg-(--cmp-calendarBoard-eventButton-hover-overlay-color) opacity-0 transition-opacity group-hover:opacity-(--cmp-calendarBoard-eventButton-hover-overlay-opacity)"
|
|
11817
|
-
}
|
|
11818
|
-
),
|
|
11819
|
-
/* @__PURE__ */ jsx(SBadge, { "aria-hidden": true, color: dot, className: "shrink-0" }),
|
|
11820
|
-
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-(--cmp-calendarBoard-eventButton-label-gap)", children: [
|
|
11821
|
-
/* @__PURE__ */ jsxs("span", { className: "typo-body-sm-default min-w-0 flex-1 truncate", children: [
|
|
11822
|
-
/* @__PURE__ */ jsx(
|
|
11823
|
-
"span",
|
|
11824
|
-
{
|
|
11825
|
-
className: cn(
|
|
11826
|
-
"typo-body-sm-semibold",
|
|
11827
|
-
hasDescription && "me-(--cmp-calendarBoard-eventButton-label-gap)"
|
|
11828
|
-
),
|
|
11829
|
-
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(event.label) }
|
|
11830
|
-
}
|
|
11831
|
-
),
|
|
11832
|
-
hasDescription && event.description
|
|
11833
|
-
] }),
|
|
11834
|
-
hasValue && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-(--cmp-calendarBoard-eventButton-label-gap)", children: [
|
|
11835
|
-
/* @__PURE__ */ jsx(
|
|
11836
|
-
"span",
|
|
11837
|
-
{
|
|
11838
|
-
"aria-hidden": true,
|
|
11839
|
-
className: "typo-body-sm-default text-(--cmp-calendarBoard-eventButton-text-color-separator)",
|
|
11840
|
-
children: "/"
|
|
11841
|
-
}
|
|
11842
|
-
),
|
|
11843
|
-
/* @__PURE__ */ jsx("span", { className: "typo-body-sm-default whitespace-nowrap", children: event.value })
|
|
11844
|
-
] })
|
|
11845
|
-
] })
|
|
11846
|
-
]
|
|
11847
|
-
}
|
|
11848
|
-
);
|
|
11849
|
-
}
|
|
11850
|
-
var CalendarMoreButton = /* @__PURE__ */ forwardRef(function CalendarMoreButton2({ count, label = "\uB354\uBCF4\uAE30", onClick, className }, ref) {
|
|
11851
|
-
return /* @__PURE__ */ jsxs(
|
|
11852
|
-
"button",
|
|
11853
|
-
{
|
|
11854
|
-
ref,
|
|
11855
|
-
type: "button",
|
|
11856
|
-
className: cn(
|
|
11857
|
-
"group relative flex w-full min-w-0 cursor-pointer items-center overflow-hidden text-left",
|
|
11858
|
-
"h-(--cmp-calendarBoard-item-height) shrink-0 rounded-(--cmp-calendarBoard-item-radius)",
|
|
11859
|
-
"gap-(--cmp-calendarBoard-moreButton-gap) px-(--cmp-calendarBoard-item-paddingX)",
|
|
11860
|
-
"bg-(--cmp-calendarBoard-moreButton-bg)",
|
|
11861
|
-
className
|
|
11862
|
-
),
|
|
11863
|
-
onClick,
|
|
11864
|
-
children: [
|
|
11865
|
-
/* @__PURE__ */ jsx(
|
|
11866
|
-
"span",
|
|
11867
|
-
{
|
|
11868
|
-
"aria-hidden": true,
|
|
11869
|
-
className: "pointer-events-none absolute inset-0 rounded-(--cmp-calendarBoard-item-radius) bg-(--cmp-calendarBoard-moreButton-hover-overlay-color) opacity-0 transition-opacity group-hover:opacity-(--cmp-calendarBoard-moreButton-hover-overlay-opacity)"
|
|
11870
|
-
}
|
|
11871
|
-
),
|
|
11872
|
-
/* @__PURE__ */ jsxs("span", { className: "typo-body-sm-semibold shrink-0 text-(--cmp-calendarBoard-moreButton-count-color)", children: [
|
|
11873
|
-
count,
|
|
11874
|
-
"\uAC1C"
|
|
11875
|
-
] }),
|
|
11876
|
-
/* @__PURE__ */ jsx("span", { className: "typo-body-sm-default min-w-0 truncate text-(--cmp-calendarBoard-moreButton-label-color)", children: label })
|
|
11877
|
-
]
|
|
11878
|
-
}
|
|
11879
|
-
);
|
|
11880
|
-
});
|
|
11881
|
-
var CalendarDayCard = /* @__PURE__ */ forwardRef(function CalendarDayCard2({
|
|
11882
|
-
date,
|
|
11883
|
-
day,
|
|
11884
|
-
inCurrentMonth,
|
|
11885
|
-
isToday,
|
|
11886
|
-
isSelected,
|
|
11887
|
-
selectable,
|
|
11888
|
-
color,
|
|
11889
|
-
events,
|
|
11890
|
-
body,
|
|
11891
|
-
hiddenCount,
|
|
11892
|
-
isOpen,
|
|
11893
|
-
moreLabel,
|
|
11894
|
-
onDaySelect,
|
|
11895
|
-
onEventClick,
|
|
11896
|
-
onOpenEvents,
|
|
11897
|
-
...rest
|
|
11898
|
-
}, ref) {
|
|
11899
|
-
const hasEvents = events.length + hiddenCount > 0;
|
|
11900
|
-
const interactive = selectable || hasEvents;
|
|
11901
|
-
const activate = () => {
|
|
11902
|
-
if (hasEvents) onOpenEvents?.();
|
|
11903
|
-
if (selectable) onDaySelect?.(date);
|
|
11904
|
-
};
|
|
11905
|
-
return /* @__PURE__ */ jsxs(
|
|
12350
|
+
return /* @__PURE__ */ jsx(
|
|
11906
12351
|
"div",
|
|
11907
12352
|
{
|
|
11908
|
-
|
|
11909
|
-
|
|
11910
|
-
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
activate();
|
|
11922
|
-
}
|
|
11923
|
-
} : void 0,
|
|
11924
|
-
className: cn(
|
|
11925
|
-
"relative flex min-h-(--cmp-calendarBoard-dayCard-minHeight) min-w-(--cmp-calendarBoard-dayCard-minWidth) flex-col bg-(--cdc-bg) px-(--cmp-calendarBoard-dayCard-paddingX) outline-none",
|
|
11926
|
-
interactive && "cursor-pointer"
|
|
11927
|
-
),
|
|
11928
|
-
style: { ...rest.style, "--cdc-bg": CALENDAR_BOARD_DAY_BG[color] },
|
|
11929
|
-
children: [
|
|
11930
|
-
isSelected && /* @__PURE__ */ jsx(
|
|
11931
|
-
"span",
|
|
11932
|
-
{
|
|
11933
|
-
"aria-hidden": true,
|
|
11934
|
-
className: "pointer-events-none absolute inset-[1px] rounded-(--cmp-calendarBoard-dayCard-focus-border-radius) border-(length:--cmp-calendarBoard-dayCard-focus-border-width) border-solid border-(--cmp-calendarBoard-dayCard-focus-border-color)"
|
|
11935
|
-
}
|
|
11936
|
-
),
|
|
11937
|
-
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 pt-(--cmp-calendarBoard-dayCard-header-paddingTop) pb-(--cmp-calendarBoard-dayCard-header-paddingBottom)", children: /* @__PURE__ */ jsx(
|
|
12353
|
+
role: "list",
|
|
12354
|
+
"aria-label": ariaLabel,
|
|
12355
|
+
className: cn("inline-flex items-center", className),
|
|
12356
|
+
style: {
|
|
12357
|
+
gap: STEPPER_LAYOUT.containerGap,
|
|
12358
|
+
fontSize: config.fontSize,
|
|
12359
|
+
lineHeight: config.lineHeight,
|
|
12360
|
+
...style
|
|
12361
|
+
},
|
|
12362
|
+
children: items.map((item4, index) => {
|
|
12363
|
+
const state2 = getState(item4, index);
|
|
12364
|
+
const content = isClickable ? /* @__PURE__ */ jsx("span", { role: "listitem", "aria-current": state2 === "active" ? "step" : void 0, children: renderClickableStepContent(item4, index) }) : renderStepContent(item4, index);
|
|
12365
|
+
return /* @__PURE__ */ jsxs(
|
|
11938
12366
|
"span",
|
|
11939
12367
|
{
|
|
11940
|
-
className:
|
|
11941
|
-
|
|
11942
|
-
isToday ? "typo-body-md-bold bg-(--cmp-calendarBoard-daySequence-bg-today) text-(--cmp-calendarBoard-daySequence-text-today)" : cn(
|
|
11943
|
-
"typo-body-md-medium",
|
|
11944
|
-
inCurrentMonth ? "text-(--cmp-calendarBoard-daySequence-text-default)" : "text-(--cmp-calendarBoard-daySequence-text-otherMonth)"
|
|
11945
|
-
),
|
|
11946
|
-
// 오늘이 아니면서 선택된 날은 테두리 원으로 표시한다 (오늘은 이미 채운 원이라 겹치지 않는다).
|
|
11947
|
-
// 굵기는 1px 로 고정한다 — 칸을 감싸는 focus 테두리(2px)와 달리 얇은 원이고, 대응 토큰이 없다.
|
|
11948
|
-
isSelected && !isToday && "border border-solid border-(--cmp-calendarBoard-daySequence-border-selected)"
|
|
11949
|
-
),
|
|
11950
|
-
children: day
|
|
11951
|
-
}
|
|
11952
|
-
) }),
|
|
11953
|
-
/* @__PURE__ */ jsxs(
|
|
11954
|
-
"div",
|
|
11955
|
-
{
|
|
11956
|
-
className: cn(
|
|
11957
|
-
"flex min-h-0 flex-col gap-(--cmp-calendarBoard-dayCard-grid-gap) pb-(--cmp-calendarBoard-dayCard-grid-paddingBottom)",
|
|
11958
|
-
// 슬롯은 남는 세로를 다 갖는다 — 안에서 h-full 로 칸을 채울 수 있어야 한다.
|
|
11959
|
-
body != null && "flex-1"
|
|
11960
|
-
),
|
|
12368
|
+
className: "inline-flex items-center",
|
|
12369
|
+
style: { gap: STEPPER_LAYOUT.containerGap },
|
|
11961
12370
|
children: [
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
{
|
|
11966
|
-
event,
|
|
11967
|
-
onSelect: (ev, e) => {
|
|
11968
|
-
e.stopPropagation();
|
|
11969
|
-
onEventClick?.(ev, e);
|
|
11970
|
-
}
|
|
11971
|
-
},
|
|
11972
|
-
event.id ?? `${event.date}-${i}`
|
|
11973
|
-
)),
|
|
11974
|
-
hiddenCount > 0 && /* @__PURE__ */ jsx(
|
|
11975
|
-
CalendarMoreButton,
|
|
12371
|
+
content,
|
|
12372
|
+
index < items.length - 1 && /* @__PURE__ */ jsx(
|
|
12373
|
+
"span",
|
|
11976
12374
|
{
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
12375
|
+
"aria-hidden": true,
|
|
12376
|
+
className: "inline-flex h-px shrink-0 items-center",
|
|
12377
|
+
style: { width: STEPPER_LAYOUT.dashWidth, color: STEPPER_COLORS.dash },
|
|
12378
|
+
children: /* @__PURE__ */ jsxs(
|
|
12379
|
+
"svg",
|
|
12380
|
+
{
|
|
12381
|
+
width: "20",
|
|
12382
|
+
height: "1",
|
|
12383
|
+
viewBox: "0 0 20 1",
|
|
12384
|
+
fill: "none",
|
|
12385
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
12386
|
+
children: [
|
|
12387
|
+
/* @__PURE__ */ jsx("rect", { width: "1.6", height: "1", fill: "currentColor" }),
|
|
12388
|
+
/* @__PURE__ */ jsx("rect", { x: "5", width: "3.3", height: "1", fill: "currentColor" }),
|
|
12389
|
+
/* @__PURE__ */ jsx("rect", { x: "11.7", width: "3.3", height: "1", fill: "currentColor" }),
|
|
12390
|
+
/* @__PURE__ */ jsx("rect", { x: "18.4", width: "1.6", height: "1", fill: "currentColor" })
|
|
12391
|
+
]
|
|
12392
|
+
}
|
|
12393
|
+
)
|
|
11983
12394
|
}
|
|
11984
12395
|
)
|
|
11985
12396
|
]
|
|
11986
|
-
}
|
|
11987
|
-
)
|
|
11988
|
-
]
|
|
11989
|
-
}
|
|
11990
|
-
);
|
|
11991
|
-
});
|
|
11992
|
-
var MAX_HEIGHT = 480;
|
|
11993
|
-
var MAX_WIDTH = "calc(100vw - 16px)";
|
|
11994
|
-
function CalendarDayEventListBox({
|
|
11995
|
-
date,
|
|
11996
|
-
events,
|
|
11997
|
-
onEventClick,
|
|
11998
|
-
minWidth,
|
|
11999
|
-
minHeight,
|
|
12000
|
-
onClose,
|
|
12001
|
-
closeLabel = "\uB2EB\uAE30"
|
|
12002
|
-
}) {
|
|
12003
|
-
const [y, m, d] = date.split("-").map(Number);
|
|
12004
|
-
const weekday = WEEK_LABELS[new Date(y, m - 1, d).getDay()];
|
|
12005
|
-
return /* @__PURE__ */ jsxs(
|
|
12006
|
-
"div",
|
|
12007
|
-
{
|
|
12008
|
-
className: "flex w-max flex-col overflow-hidden rounded-(--cmp-calendarBoard-radius) bg-(--cmp-calendarBoard-bg) shadow-(--shadow-overlay)",
|
|
12009
|
-
style: { minWidth, maxWidth: MAX_WIDTH, minHeight, maxHeight: MAX_HEIGHT },
|
|
12010
|
-
children: [
|
|
12011
|
-
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-(--cmp-calendarBoard-dayEvent-header-gap) px-(--cmp-calendarBoard-dayEvent-header-paddingX) py-(--cmp-calendarBoard-dayEvent-header-paddingY)", children: [
|
|
12012
|
-
/* @__PURE__ */ jsxs("span", { className: "typo-heading-md text-(--cmp-calendarBoard-header-content-color)", children: [
|
|
12013
|
-
d,
|
|
12014
|
-
"\uC77C"
|
|
12015
|
-
] }),
|
|
12016
|
-
/* @__PURE__ */ jsxs("span", { className: "typo-body-lg-default flex-1 text-(--cmp-calendarBoard-header-content-color)", children: [
|
|
12017
|
-
"(",
|
|
12018
|
-
weekday,
|
|
12019
|
-
")"
|
|
12020
|
-
] }),
|
|
12021
|
-
/* @__PURE__ */ jsx(
|
|
12022
|
-
SGhostButton,
|
|
12023
|
-
{
|
|
12024
|
-
icon: "close",
|
|
12025
|
-
size: "xs",
|
|
12026
|
-
ariaLabel: closeLabel,
|
|
12027
|
-
className: "shrink-0",
|
|
12028
|
-
onClick: onClose
|
|
12029
|
-
}
|
|
12030
|
-
)
|
|
12031
|
-
] }),
|
|
12032
|
-
/* @__PURE__ */ jsx(SScrollArea, { axis: "vertical", className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-(--cmp-calendarBoard-dayEvent-body-gap) px-(--cmp-calendarBoard-dayEvent-body-paddingX) pb-(--cmp-calendarBoard-dayEvent-body-paddingBottom)", children: events.map((event, i) => /* @__PURE__ */ jsx(
|
|
12033
|
-
CalendarEventButton,
|
|
12034
|
-
{
|
|
12035
|
-
event,
|
|
12036
|
-
onSelect: onEventClick
|
|
12037
12397
|
},
|
|
12038
|
-
|
|
12039
|
-
)
|
|
12040
|
-
|
|
12398
|
+
getItemValue(item4, index)
|
|
12399
|
+
);
|
|
12400
|
+
})
|
|
12041
12401
|
}
|
|
12042
12402
|
);
|
|
12403
|
+
});
|
|
12404
|
+
|
|
12405
|
+
// src/lib/date.ts
|
|
12406
|
+
function todayStr() {
|
|
12407
|
+
const d = /* @__PURE__ */ new Date();
|
|
12408
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
12043
12409
|
}
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
function shiftIntoView(desired, size, viewport) {
|
|
12047
|
-
const max = Math.max(viewport - size - VIEWPORT_PADDING2, VIEWPORT_PADDING2);
|
|
12048
|
-
return Math.min(Math.max(desired, VIEWPORT_PADDING2), max) - desired;
|
|
12410
|
+
function formatDate(year, month, day) {
|
|
12411
|
+
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
12049
12412
|
}
|
|
12050
|
-
function
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
const row = v("--cmp-calendarBoard-item-height") + gap;
|
|
12055
|
-
if (row <= 0) return null;
|
|
12056
|
-
const header = v("--cmp-calendarBoard-dayCard-header-paddingTop") + v("--cmp-calendarBoard-daySequence-size") + v("--cmp-calendarBoard-dayCard-header-paddingBottom");
|
|
12057
|
-
const free = cell.getBoundingClientRect().height - header - v("--cmp-calendarBoard-dayCard-grid-paddingBottom") + gap;
|
|
12058
|
-
if (free <= 0) return null;
|
|
12059
|
-
return Math.max(1, Math.floor(free / row));
|
|
12413
|
+
function calcYearMonth(year, month, dir) {
|
|
12414
|
+
if (dir === "prev")
|
|
12415
|
+
return month === 1 ? { year: year - 1, month: 12 } : { year, month: month - 1 };
|
|
12416
|
+
return month === 12 ? { year: year + 1, month: 1 } : { year, month: month + 1 };
|
|
12060
12417
|
}
|
|
12061
|
-
function
|
|
12062
|
-
year,
|
|
12063
|
-
month,
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
}
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
)
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
const
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
const adjust = () => {
|
|
12134
|
-
const cellRect = cell.getBoundingClientRect();
|
|
12135
|
-
const panelRect = panelEl.getBoundingClientRect();
|
|
12136
|
-
const next = {
|
|
12137
|
-
cellWidth: cellRect.width,
|
|
12138
|
-
cellHeight: cellRect.height,
|
|
12139
|
-
side: -(cellRect.height + DAY_EVENT_OUTDENT) + shiftIntoView(cellRect.top - DAY_EVENT_OUTDENT, panelRect.height, window.innerHeight),
|
|
12140
|
-
align: -DAY_EVENT_OUTDENT + shiftIntoView(cellRect.left - DAY_EVENT_OUTDENT, panelRect.width, window.innerWidth)
|
|
12141
|
-
};
|
|
12142
|
-
setPlacement(
|
|
12143
|
-
(prev) => prev.cellWidth === next.cellWidth && prev.cellHeight === next.cellHeight && prev.side === next.side && prev.align === next.align ? prev : next
|
|
12144
|
-
);
|
|
12145
|
-
};
|
|
12146
|
-
adjust();
|
|
12147
|
-
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(adjust);
|
|
12148
|
-
observer?.observe(panelEl);
|
|
12149
|
-
window.addEventListener("scroll", adjust, true);
|
|
12150
|
-
window.addEventListener("resize", adjust);
|
|
12151
|
-
return () => {
|
|
12152
|
-
observer?.disconnect();
|
|
12153
|
-
window.removeEventListener("scroll", adjust, true);
|
|
12154
|
-
window.removeEventListener("resize", adjust);
|
|
12155
|
-
};
|
|
12156
|
-
}, [openDate, panelEl]);
|
|
12157
|
-
const columns = "repeat(7, minmax(var(--cmp-calendarBoard-dayCard-minWidth), 1fr))";
|
|
12158
|
-
const openEventList = (date, list) => {
|
|
12159
|
-
if (onMoreClick) {
|
|
12160
|
-
onMoreClick({ date, events: list });
|
|
12161
|
-
return;
|
|
12162
|
-
}
|
|
12163
|
-
setOpenDate((prev) => prev === date ? null : date);
|
|
12164
|
-
};
|
|
12418
|
+
function monthCells(year, month) {
|
|
12419
|
+
const firstDayIndex = new Date(year, month - 1, 1).getDay();
|
|
12420
|
+
const daysInCurrent = new Date(year, month, 0).getDate();
|
|
12421
|
+
const prev = calcYearMonth(year, month, "prev");
|
|
12422
|
+
const daysInPrev = new Date(prev.year, prev.month, 0).getDate();
|
|
12423
|
+
const next = calcYearMonth(year, month, "next");
|
|
12424
|
+
const cells = [];
|
|
12425
|
+
for (let i = firstDayIndex - 1; i >= 0; i--) {
|
|
12426
|
+
const day = daysInPrev - i;
|
|
12427
|
+
cells.push({ date: formatDate(prev.year, prev.month, day), day, inCurrentMonth: false });
|
|
12428
|
+
}
|
|
12429
|
+
for (let day = 1; day <= daysInCurrent; day++) {
|
|
12430
|
+
cells.push({ date: formatDate(year, month, day), day, inCurrentMonth: true });
|
|
12431
|
+
}
|
|
12432
|
+
const remaining = (7 - cells.length % 7) % 7;
|
|
12433
|
+
for (let day = 1; day <= remaining; day++) {
|
|
12434
|
+
cells.push({ date: formatDate(next.year, next.month, day), day, inCurrentMonth: false });
|
|
12435
|
+
}
|
|
12436
|
+
return cells;
|
|
12437
|
+
}
|
|
12438
|
+
var WEEK_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
|
|
12439
|
+
|
|
12440
|
+
// src/components/SCalendarBoard/calendarBoard.config.ts
|
|
12441
|
+
var CALENDAR_BOARD_EVENT_COLORS = [
|
|
12442
|
+
"default",
|
|
12443
|
+
"blue",
|
|
12444
|
+
"oceanBlue",
|
|
12445
|
+
"lightBlue",
|
|
12446
|
+
"green",
|
|
12447
|
+
"yellow",
|
|
12448
|
+
"orange",
|
|
12449
|
+
"red",
|
|
12450
|
+
"white"
|
|
12451
|
+
];
|
|
12452
|
+
var BG = (name) => `var(--cmp-calendarBoard-eventButton-bg-${name})`;
|
|
12453
|
+
var CALENDAR_BOARD_EVENT_PRESETS = {
|
|
12454
|
+
default: { bg: BG("default"), dot: "indigo" },
|
|
12455
|
+
blue: { bg: BG("blue"), dot: "blue" },
|
|
12456
|
+
oceanBlue: { bg: BG("oceanBlue"), dot: "darkblue" },
|
|
12457
|
+
lightBlue: { bg: BG("lightBlue"), dot: "lightblue" },
|
|
12458
|
+
green: { bg: BG("green"), dot: "green" },
|
|
12459
|
+
yellow: { bg: BG("yellow"), dot: "yellow" },
|
|
12460
|
+
orange: { bg: BG("orange"), dot: "orange" },
|
|
12461
|
+
red: { bg: BG("red"), dot: "red" },
|
|
12462
|
+
white: { bg: BG("white"), dot: "grey" }
|
|
12463
|
+
};
|
|
12464
|
+
var CALENDAR_BOARD_MAX_VISIBLE_EVENTS = 4;
|
|
12465
|
+
var CALENDAR_BOARD_DAY_COLORS = [
|
|
12466
|
+
"default",
|
|
12467
|
+
"danger",
|
|
12468
|
+
"accent",
|
|
12469
|
+
"complete",
|
|
12470
|
+
"dim"
|
|
12471
|
+
];
|
|
12472
|
+
var CALENDAR_BOARD_DAY_BG = {
|
|
12473
|
+
default: "var(--cmp-calendarBoard-dayCard-bg)",
|
|
12474
|
+
danger: "var(--color-red-30)",
|
|
12475
|
+
accent: "var(--color-brilliantblue-40)",
|
|
12476
|
+
complete: "var(--color-green-45)",
|
|
12477
|
+
dim: "var(--color-grey-25)"
|
|
12478
|
+
};
|
|
12479
|
+
function CalendarEventButton({
|
|
12480
|
+
event,
|
|
12481
|
+
onSelect,
|
|
12482
|
+
className
|
|
12483
|
+
}) {
|
|
12484
|
+
const preset = CALENDAR_BOARD_EVENT_PRESETS[event.color ?? "default"];
|
|
12485
|
+
const dot = event.dotColor ?? preset.dot;
|
|
12486
|
+
const disabled = event.disabled === true;
|
|
12487
|
+
const hasDescription = event.description != null && event.description !== "";
|
|
12488
|
+
const hasValue = event.value != null && event.value !== "";
|
|
12489
|
+
const title = [event.label.replace(/<[^>]*>/g, ""), event.description, event.value].filter((v) => v != null && v !== "").join(" ") || void 0;
|
|
12165
12490
|
return /* @__PURE__ */ jsxs(
|
|
12166
|
-
"
|
|
12491
|
+
"button",
|
|
12167
12492
|
{
|
|
12493
|
+
type: "button",
|
|
12494
|
+
disabled,
|
|
12495
|
+
title,
|
|
12168
12496
|
className: cn(
|
|
12169
|
-
//
|
|
12170
|
-
"flex
|
|
12497
|
+
// hover 는 배경 위에 8% 오버레이를 얹는다 — 프리셋 배경이 9종이라 색마다 hover 색을 두지 않는다.
|
|
12498
|
+
"group relative flex w-full min-w-0 items-center overflow-hidden text-left",
|
|
12499
|
+
"h-(--cmp-calendarBoard-item-height) shrink-0 rounded-(--cmp-calendarBoard-item-radius)",
|
|
12500
|
+
"gap-(--cmp-calendarBoard-eventButton-inline-gap) px-(--cmp-calendarBoard-item-paddingX)",
|
|
12501
|
+
"bg-(--ceb-bg) text-(--cmp-calendarBoard-eventButton-text-color-default)",
|
|
12502
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
12171
12503
|
className
|
|
12172
12504
|
),
|
|
12173
|
-
style,
|
|
12505
|
+
style: { "--ceb-bg": preset.bg },
|
|
12506
|
+
onClick: (e) => {
|
|
12507
|
+
if (disabled) return;
|
|
12508
|
+
onSelect?.(event, e);
|
|
12509
|
+
},
|
|
12174
12510
|
children: [
|
|
12175
|
-
/* @__PURE__ */
|
|
12176
|
-
|
|
12511
|
+
!disabled && /* @__PURE__ */ jsx(
|
|
12512
|
+
"span",
|
|
12513
|
+
{
|
|
12514
|
+
"aria-hidden": true,
|
|
12515
|
+
className: "pointer-events-none absolute inset-0 rounded-(--cmp-calendarBoard-item-radius) bg-(--cmp-calendarBoard-eventButton-hover-overlay-color) opacity-0 transition-opacity group-hover:opacity-(--cmp-calendarBoard-eventButton-hover-overlay-opacity)"
|
|
12516
|
+
}
|
|
12517
|
+
),
|
|
12518
|
+
/* @__PURE__ */ jsx(SBadge, { "aria-hidden": true, color: dot, className: "shrink-0" }),
|
|
12519
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-(--cmp-calendarBoard-eventButton-label-gap)", children: [
|
|
12520
|
+
/* @__PURE__ */ jsxs("span", { className: "typo-body-sm-default min-w-0 flex-1 truncate", children: [
|
|
12177
12521
|
/* @__PURE__ */ jsx(
|
|
12178
|
-
|
|
12522
|
+
"span",
|
|
12179
12523
|
{
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12524
|
+
className: cn(
|
|
12525
|
+
"typo-body-sm-semibold",
|
|
12526
|
+
hasDescription && "me-(--cmp-calendarBoard-eventButton-label-gap)"
|
|
12527
|
+
),
|
|
12528
|
+
dangerouslySetInnerHTML: { __html: sanitizeInlineHtml(event.label) }
|
|
12184
12529
|
}
|
|
12185
12530
|
),
|
|
12186
|
-
|
|
12187
|
-
/* @__PURE__ */ jsx(
|
|
12188
|
-
SGhostButton,
|
|
12189
|
-
{
|
|
12190
|
-
icon: "chevronRight",
|
|
12191
|
-
size: "xxs",
|
|
12192
|
-
ariaLabel: "\uB2E4\uC74C \uD574",
|
|
12193
|
-
onClick: () => setView({ year: view.year + 1, month: view.month })
|
|
12194
|
-
}
|
|
12195
|
-
)
|
|
12531
|
+
hasDescription && event.description
|
|
12196
12532
|
] }),
|
|
12197
|
-
/* @__PURE__ */
|
|
12198
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-(--cmp-calendarBoard-header-content-gap)", children: [
|
|
12533
|
+
hasValue && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-(--cmp-calendarBoard-eventButton-label-gap)", children: [
|
|
12199
12534
|
/* @__PURE__ */ jsx(
|
|
12200
|
-
|
|
12535
|
+
"span",
|
|
12201
12536
|
{
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
onClick: () => setView(calcYearMonth(view.year, view.month, "prev"))
|
|
12537
|
+
"aria-hidden": true,
|
|
12538
|
+
className: "typo-body-sm-default text-(--cmp-calendarBoard-eventButton-text-color-separator)",
|
|
12539
|
+
children: "/"
|
|
12206
12540
|
}
|
|
12207
12541
|
),
|
|
12208
|
-
/* @__PURE__ */
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12230
|
-
}
|
|
12231
|
-
),
|
|
12232
|
-
headerRight != null && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: headerRight })
|
|
12233
|
-
] }),
|
|
12234
|
-
/* @__PURE__ */ jsx(SDivider, {}),
|
|
12542
|
+
/* @__PURE__ */ jsx("span", { className: "typo-body-sm-default whitespace-nowrap", children: event.value })
|
|
12543
|
+
] })
|
|
12544
|
+
] })
|
|
12545
|
+
]
|
|
12546
|
+
}
|
|
12547
|
+
);
|
|
12548
|
+
}
|
|
12549
|
+
var CalendarMoreButton = /* @__PURE__ */ forwardRef(function CalendarMoreButton2({ count, label = "\uB354\uBCF4\uAE30", onClick, className }, ref) {
|
|
12550
|
+
return /* @__PURE__ */ jsxs(
|
|
12551
|
+
"button",
|
|
12552
|
+
{
|
|
12553
|
+
ref,
|
|
12554
|
+
type: "button",
|
|
12555
|
+
className: cn(
|
|
12556
|
+
"group relative flex w-full min-w-0 cursor-pointer items-center overflow-hidden text-left",
|
|
12557
|
+
"h-(--cmp-calendarBoard-item-height) shrink-0 rounded-(--cmp-calendarBoard-item-radius)",
|
|
12558
|
+
"gap-(--cmp-calendarBoard-moreButton-gap) px-(--cmp-calendarBoard-item-paddingX)",
|
|
12559
|
+
"bg-(--cmp-calendarBoard-moreButton-bg)",
|
|
12560
|
+
className
|
|
12561
|
+
),
|
|
12562
|
+
onClick,
|
|
12563
|
+
children: [
|
|
12235
12564
|
/* @__PURE__ */ jsx(
|
|
12236
|
-
"
|
|
12565
|
+
"span",
|
|
12237
12566
|
{
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
children: WEEK_LABELS.map((label) => /* @__PURE__ */ jsx(
|
|
12241
|
-
"div",
|
|
12242
|
-
{
|
|
12243
|
-
className: "typo-body-md-default flex justify-center text-(--cmp-calendarBoard-grid-weekRow-color)",
|
|
12244
|
-
children: label
|
|
12245
|
-
},
|
|
12246
|
-
label
|
|
12247
|
-
))
|
|
12567
|
+
"aria-hidden": true,
|
|
12568
|
+
className: "pointer-events-none absolute inset-0 rounded-(--cmp-calendarBoard-item-radius) bg-(--cmp-calendarBoard-moreButton-hover-overlay-color) opacity-0 transition-opacity group-hover:opacity-(--cmp-calendarBoard-moreButton-hover-overlay-opacity)"
|
|
12248
12569
|
}
|
|
12249
12570
|
),
|
|
12250
|
-
/* @__PURE__ */ jsxs(
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
|
|
12293
|
-
|
|
12294
|
-
|
|
12295
|
-
|
|
12296
|
-
|
|
12297
|
-
|
|
12571
|
+
/* @__PURE__ */ jsxs("span", { className: "typo-body-sm-semibold shrink-0 text-(--cmp-calendarBoard-moreButton-count-color)", children: [
|
|
12572
|
+
count,
|
|
12573
|
+
"\uAC1C"
|
|
12574
|
+
] }),
|
|
12575
|
+
/* @__PURE__ */ jsx("span", { className: "typo-body-sm-default min-w-0 truncate text-(--cmp-calendarBoard-moreButton-label-color)", children: label })
|
|
12576
|
+
]
|
|
12577
|
+
}
|
|
12578
|
+
);
|
|
12579
|
+
});
|
|
12580
|
+
var CalendarDayCard = /* @__PURE__ */ forwardRef(function CalendarDayCard2({
|
|
12581
|
+
date,
|
|
12582
|
+
day,
|
|
12583
|
+
inCurrentMonth,
|
|
12584
|
+
isToday,
|
|
12585
|
+
isSelected,
|
|
12586
|
+
selectable,
|
|
12587
|
+
color,
|
|
12588
|
+
events,
|
|
12589
|
+
body,
|
|
12590
|
+
hiddenCount,
|
|
12591
|
+
isOpen,
|
|
12592
|
+
moreLabel,
|
|
12593
|
+
onDaySelect,
|
|
12594
|
+
onEventClick,
|
|
12595
|
+
onOpenEvents,
|
|
12596
|
+
...rest
|
|
12597
|
+
}, ref) {
|
|
12598
|
+
const hasEvents = events.length + hiddenCount > 0;
|
|
12599
|
+
const interactive = selectable || hasEvents;
|
|
12600
|
+
const activate = () => {
|
|
12601
|
+
if (hasEvents) onOpenEvents?.();
|
|
12602
|
+
if (selectable) onDaySelect?.(date);
|
|
12603
|
+
};
|
|
12604
|
+
return /* @__PURE__ */ jsxs(
|
|
12605
|
+
"div",
|
|
12606
|
+
{
|
|
12607
|
+
...rest,
|
|
12608
|
+
ref,
|
|
12609
|
+
role: "gridcell",
|
|
12610
|
+
"data-date": date,
|
|
12611
|
+
"aria-selected": selectable ? isSelected : void 0,
|
|
12612
|
+
"aria-current": isToday ? "date" : void 0,
|
|
12613
|
+
"aria-haspopup": hasEvents ? "dialog" : void 0,
|
|
12614
|
+
"aria-expanded": hasEvents ? isOpen : void 0,
|
|
12615
|
+
tabIndex: interactive ? 0 : void 0,
|
|
12616
|
+
onClick: interactive ? activate : void 0,
|
|
12617
|
+
onKeyDown: interactive ? (e) => {
|
|
12618
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
12619
|
+
e.preventDefault();
|
|
12620
|
+
activate();
|
|
12621
|
+
}
|
|
12622
|
+
} : void 0,
|
|
12623
|
+
className: cn(
|
|
12624
|
+
"relative flex min-h-(--cmp-calendarBoard-dayCard-minHeight) min-w-(--cmp-calendarBoard-dayCard-minWidth) flex-col bg-(--cdc-bg) px-(--cmp-calendarBoard-dayCard-paddingX) outline-none",
|
|
12625
|
+
interactive && "cursor-pointer"
|
|
12626
|
+
),
|
|
12627
|
+
style: { ...rest.style, "--cdc-bg": CALENDAR_BOARD_DAY_BG[color] },
|
|
12628
|
+
children: [
|
|
12629
|
+
isSelected && /* @__PURE__ */ jsx(
|
|
12630
|
+
"span",
|
|
12631
|
+
{
|
|
12632
|
+
"aria-hidden": true,
|
|
12633
|
+
className: "pointer-events-none absolute inset-[1px] rounded-(--cmp-calendarBoard-dayCard-focus-border-radius) border-(length:--cmp-calendarBoard-dayCard-focus-border-width) border-solid border-(--cmp-calendarBoard-dayCard-focus-border-color)"
|
|
12634
|
+
}
|
|
12635
|
+
),
|
|
12636
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 pt-(--cmp-calendarBoard-dayCard-header-paddingTop) pb-(--cmp-calendarBoard-dayCard-header-paddingBottom)", children: /* @__PURE__ */ jsx(
|
|
12637
|
+
"span",
|
|
12638
|
+
{
|
|
12639
|
+
className: cn(
|
|
12640
|
+
"inline-flex size-(--cmp-calendarBoard-daySequence-size) items-center justify-center rounded-(--cmp-calendarBoard-daySequence-radius)",
|
|
12641
|
+
isToday ? "typo-body-md-bold bg-(--cmp-calendarBoard-daySequence-bg-today) text-(--cmp-calendarBoard-daySequence-text-today)" : cn(
|
|
12642
|
+
"typo-body-md-medium",
|
|
12643
|
+
inCurrentMonth ? "text-(--cmp-calendarBoard-daySequence-text-default)" : "text-(--cmp-calendarBoard-daySequence-text-otherMonth)"
|
|
12298
12644
|
),
|
|
12299
|
-
|
|
12300
|
-
|
|
12645
|
+
// 오늘이 아니면서 선택된 날은 테두리 원으로 표시한다 (오늘은 이미 채운 원이라 겹치지 않는다).
|
|
12646
|
+
// 굵기는 1px 로 고정한다 — 칸을 감싸는 focus 테두리(2px)와 달리 얇은 원이고, 대응 토큰이 없다.
|
|
12647
|
+
isSelected && !isToday && "border border-solid border-(--cmp-calendarBoard-daySequence-border-selected)"
|
|
12648
|
+
),
|
|
12649
|
+
children: day
|
|
12650
|
+
}
|
|
12651
|
+
) }),
|
|
12652
|
+
/* @__PURE__ */ jsxs(
|
|
12653
|
+
"div",
|
|
12654
|
+
{
|
|
12655
|
+
className: cn(
|
|
12656
|
+
"flex min-h-0 flex-col gap-(--cmp-calendarBoard-dayCard-grid-gap) pb-(--cmp-calendarBoard-dayCard-grid-paddingBottom)",
|
|
12657
|
+
// 슬롯은 남는 세로를 다 갖는다 — 안에서 h-full 로 칸을 채울 수 있어야 한다.
|
|
12658
|
+
body != null && "flex-1"
|
|
12659
|
+
),
|
|
12660
|
+
children: [
|
|
12661
|
+
body,
|
|
12662
|
+
body == null && events.map((event, i) => /* @__PURE__ */ jsx(
|
|
12663
|
+
CalendarEventButton,
|
|
12301
12664
|
{
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
align: "start",
|
|
12308
|
-
ref: setPanelEl,
|
|
12309
|
-
sideOffset: placement.side,
|
|
12310
|
-
alignOffset: placement.align,
|
|
12311
|
-
avoidCollisions: false,
|
|
12312
|
-
className: cn("z-50 outline-none", FLOATING_SLIDE_ANIM),
|
|
12313
|
-
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
12314
|
-
children: openDate != null && /* @__PURE__ */ jsx(
|
|
12315
|
-
CalendarDayEventListBox,
|
|
12316
|
-
{
|
|
12317
|
-
date: openDate,
|
|
12318
|
-
minWidth: placement.cellWidth > 0 ? placement.cellWidth + DAY_EVENT_OUTDENT * 2 : void 0,
|
|
12319
|
-
minHeight: placement.cellHeight > 0 ? placement.cellHeight + DAY_EVENT_OUTDENT * 2 : void 0,
|
|
12320
|
-
events: openEvents,
|
|
12321
|
-
onEventClick,
|
|
12322
|
-
onClose: () => setOpenDate(null)
|
|
12323
|
-
}
|
|
12324
|
-
)
|
|
12665
|
+
event,
|
|
12666
|
+
onSelect: (ev, e) => {
|
|
12667
|
+
e.stopPropagation();
|
|
12668
|
+
onEventClick?.(ev, e);
|
|
12669
|
+
}
|
|
12325
12670
|
},
|
|
12326
|
-
|
|
12327
|
-
)
|
|
12671
|
+
event.id ?? `${event.date}-${i}`
|
|
12672
|
+
)),
|
|
12673
|
+
hiddenCount > 0 && /* @__PURE__ */ jsx(
|
|
12674
|
+
CalendarMoreButton,
|
|
12675
|
+
{
|
|
12676
|
+
count: hiddenCount,
|
|
12677
|
+
label: moreLabel,
|
|
12678
|
+
onClick: (e) => {
|
|
12679
|
+
e.stopPropagation();
|
|
12680
|
+
onOpenEvents?.();
|
|
12681
|
+
}
|
|
12682
|
+
}
|
|
12683
|
+
)
|
|
12328
12684
|
]
|
|
12329
12685
|
}
|
|
12330
12686
|
)
|
|
12331
12687
|
]
|
|
12332
12688
|
}
|
|
12333
12689
|
);
|
|
12334
|
-
}
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
return `min(${css}, ${availableHeight})`;
|
|
12342
|
-
}
|
|
12343
|
-
function runRules(value, rules) {
|
|
12344
|
-
if (!rules || rules.length === 0) return "";
|
|
12345
|
-
for (const rule of rules) {
|
|
12346
|
-
const result = rule(value ?? "");
|
|
12347
|
-
if (result !== true) return typeof result === "string" ? result : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uAC12\uC785\uB2C8\uB2E4.";
|
|
12348
|
-
}
|
|
12349
|
-
return "";
|
|
12350
|
-
}
|
|
12351
|
-
var FormContext = /* @__PURE__ */ createContext(null);
|
|
12352
|
-
function useFormContext() {
|
|
12353
|
-
return useContext(FormContext);
|
|
12354
|
-
}
|
|
12355
|
-
function useFormField(field) {
|
|
12356
|
-
const ctx = useFormContext();
|
|
12357
|
-
const cbRef = useRef(field);
|
|
12358
|
-
cbRef.current = field;
|
|
12359
|
-
const name = field.name ?? "";
|
|
12360
|
-
useEffect(() => {
|
|
12361
|
-
if (!ctx) return;
|
|
12362
|
-
return ctx.register({
|
|
12363
|
-
name,
|
|
12364
|
-
validate: () => cbRef.current.validate(),
|
|
12365
|
-
resetValidation: () => cbRef.current.resetValidation()
|
|
12366
|
-
});
|
|
12367
|
-
}, [ctx, name]);
|
|
12368
|
-
}
|
|
12369
|
-
var FIELD_SIZE = {
|
|
12370
|
-
sm: { height: 28, radius: 4, fieldGap: 12, labelGap: 6, fontSize: 12, lineHeight: 20, icon: 16 },
|
|
12371
|
-
md: { height: 36, radius: 6, fieldGap: 16, labelGap: 8, fontSize: 14, lineHeight: 24, icon: 16 }
|
|
12372
|
-
};
|
|
12373
|
-
var ALIGN = {
|
|
12374
|
-
start: "flex-start",
|
|
12375
|
-
center: "center",
|
|
12376
|
-
end: "flex-end"
|
|
12377
|
-
};
|
|
12378
|
-
var FOCUS_RING_SHADOW = "0px 0px 4px 0px #0071ff66";
|
|
12379
|
-
var cssLen = (v) => v === void 0 || v === "" || v === 0 ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
12380
|
-
var SField = /* @__PURE__ */ forwardRef(function SField2({
|
|
12381
|
-
name,
|
|
12382
|
-
label = "",
|
|
12383
|
-
icon,
|
|
12384
|
-
iconColor,
|
|
12385
|
-
labelTooltip = "",
|
|
12386
|
-
labelTooltipProps,
|
|
12387
|
-
labelWidth,
|
|
12388
|
-
labelHeight,
|
|
12389
|
-
size = "sm",
|
|
12390
|
-
addonLabel = "",
|
|
12391
|
-
addonAlign = "start",
|
|
12392
|
-
error = false,
|
|
12393
|
-
errorMessage = "",
|
|
12394
|
-
status,
|
|
12395
|
-
focused = false,
|
|
12396
|
-
hovered = false,
|
|
12397
|
-
rules: _rules,
|
|
12398
|
-
hint = "",
|
|
12399
|
-
disabled = false,
|
|
12400
|
-
readOnly = false,
|
|
12401
|
-
width,
|
|
12690
|
+
});
|
|
12691
|
+
var MAX_HEIGHT = 480;
|
|
12692
|
+
var MAX_WIDTH = "calc(100vw - 16px)";
|
|
12693
|
+
function CalendarDayEventListBox({
|
|
12694
|
+
date,
|
|
12695
|
+
events,
|
|
12696
|
+
onEventClick,
|
|
12402
12697
|
minWidth,
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
"
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12698
|
+
minHeight,
|
|
12699
|
+
onClose,
|
|
12700
|
+
closeLabel = "\uB2EB\uAE30"
|
|
12701
|
+
}) {
|
|
12702
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
12703
|
+
const weekday = WEEK_LABELS[new Date(y, m - 1, d).getDay()];
|
|
12704
|
+
return /* @__PURE__ */ jsxs(
|
|
12705
|
+
"div",
|
|
12706
|
+
{
|
|
12707
|
+
className: "flex w-max flex-col overflow-hidden rounded-(--cmp-calendarBoard-radius) bg-(--cmp-calendarBoard-bg) shadow-(--shadow-overlay)",
|
|
12708
|
+
style: { minWidth, maxWidth: MAX_WIDTH, minHeight, maxHeight: MAX_HEIGHT },
|
|
12709
|
+
children: [
|
|
12710
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-(--cmp-calendarBoard-dayEvent-header-gap) px-(--cmp-calendarBoard-dayEvent-header-paddingX) py-(--cmp-calendarBoard-dayEvent-header-paddingY)", children: [
|
|
12711
|
+
/* @__PURE__ */ jsxs("span", { className: "typo-heading-md text-(--cmp-calendarBoard-header-content-color)", children: [
|
|
12712
|
+
d,
|
|
12713
|
+
"\uC77C"
|
|
12714
|
+
] }),
|
|
12715
|
+
/* @__PURE__ */ jsxs("span", { className: "typo-body-lg-default flex-1 text-(--cmp-calendarBoard-header-content-color)", children: [
|
|
12716
|
+
"(",
|
|
12717
|
+
weekday,
|
|
12718
|
+
")"
|
|
12719
|
+
] }),
|
|
12720
|
+
/* @__PURE__ */ jsx(
|
|
12721
|
+
SGhostButton,
|
|
12722
|
+
{
|
|
12723
|
+
icon: "close",
|
|
12724
|
+
size: "xs",
|
|
12725
|
+
ariaLabel: closeLabel,
|
|
12726
|
+
className: "shrink-0",
|
|
12727
|
+
onClick: onClose
|
|
12728
|
+
}
|
|
12729
|
+
)
|
|
12730
|
+
] }),
|
|
12731
|
+
/* @__PURE__ */ jsx(SScrollArea, { axis: "vertical", className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-(--cmp-calendarBoard-dayEvent-body-gap) px-(--cmp-calendarBoard-dayEvent-body-paddingX) pb-(--cmp-calendarBoard-dayEvent-body-paddingBottom)", children: events.map((event, i) => /* @__PURE__ */ jsx(
|
|
12732
|
+
CalendarEventButton,
|
|
12733
|
+
{
|
|
12734
|
+
event,
|
|
12735
|
+
onSelect: onEventClick
|
|
12736
|
+
},
|
|
12737
|
+
event.id ?? `${event.date}-${i}`
|
|
12738
|
+
)) }) })
|
|
12739
|
+
]
|
|
12740
|
+
}
|
|
12427
12741
|
);
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
const
|
|
12437
|
-
const
|
|
12438
|
-
const
|
|
12439
|
-
const
|
|
12440
|
-
|
|
12441
|
-
const
|
|
12442
|
-
const
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12742
|
+
}
|
|
12743
|
+
var DAY_EVENT_OUTDENT = 16;
|
|
12744
|
+
var VIEWPORT_PADDING2 = 8;
|
|
12745
|
+
function shiftIntoView(desired, size, viewport) {
|
|
12746
|
+
const max = Math.max(viewport - size - VIEWPORT_PADDING2, VIEWPORT_PADDING2);
|
|
12747
|
+
return Math.min(Math.max(desired, VIEWPORT_PADDING2), max) - desired;
|
|
12748
|
+
}
|
|
12749
|
+
function measureRowCapacity(cell) {
|
|
12750
|
+
const cs = getComputedStyle(cell);
|
|
12751
|
+
const v = (name) => Number.parseFloat(cs.getPropertyValue(name)) || 0;
|
|
12752
|
+
const gap = v("--cmp-calendarBoard-dayCard-grid-gap");
|
|
12753
|
+
const row = v("--cmp-calendarBoard-item-height") + gap;
|
|
12754
|
+
if (row <= 0) return null;
|
|
12755
|
+
const header = v("--cmp-calendarBoard-dayCard-header-paddingTop") + v("--cmp-calendarBoard-daySequence-size") + v("--cmp-calendarBoard-dayCard-header-paddingBottom");
|
|
12756
|
+
const free = cell.getBoundingClientRect().height - header - v("--cmp-calendarBoard-dayCard-grid-paddingBottom") + gap;
|
|
12757
|
+
if (free <= 0) return null;
|
|
12758
|
+
return Math.max(1, Math.floor(free / row));
|
|
12759
|
+
}
|
|
12760
|
+
function SCalendarBoard({
|
|
12761
|
+
year,
|
|
12762
|
+
month,
|
|
12763
|
+
defaultYear,
|
|
12764
|
+
defaultMonth,
|
|
12765
|
+
onViewChange,
|
|
12766
|
+
selectable = false,
|
|
12767
|
+
value,
|
|
12768
|
+
onValueChange,
|
|
12769
|
+
events,
|
|
12770
|
+
dayColors,
|
|
12771
|
+
dayContent,
|
|
12772
|
+
onEventClick,
|
|
12773
|
+
onMoreClick,
|
|
12774
|
+
todayLabel = "\uC624\uB298",
|
|
12775
|
+
moreLabel,
|
|
12776
|
+
headerRight,
|
|
12777
|
+
className,
|
|
12778
|
+
style
|
|
12779
|
+
}) {
|
|
12780
|
+
const today = todayStr();
|
|
12781
|
+
const [ty, tm] = [Number(today.slice(0, 4)), Number(today.slice(5, 7))];
|
|
12782
|
+
const [innerView, setInnerView] = useState(() => ({
|
|
12783
|
+
year: defaultYear ?? ty,
|
|
12784
|
+
month: defaultMonth ?? tm
|
|
12785
|
+
}));
|
|
12786
|
+
const controlled = year != null && month != null;
|
|
12787
|
+
const view = controlled ? { year, month } : innerView;
|
|
12788
|
+
const [openDate, setOpenDate] = useState(null);
|
|
12789
|
+
const [placement, setPlacement] = useState({ cellWidth: 0, cellHeight: 0, side: 0, align: 0 });
|
|
12790
|
+
const [panelEl, setPanelEl] = useState(null);
|
|
12791
|
+
const portalContainer = usePortalContainer();
|
|
12792
|
+
const setView = useCallback(
|
|
12793
|
+
(next) => {
|
|
12794
|
+
setOpenDate(null);
|
|
12795
|
+
if (!controlled) setInnerView(next);
|
|
12796
|
+
onViewChange?.(next);
|
|
12797
|
+
},
|
|
12798
|
+
[controlled, onViewChange]
|
|
12449
12799
|
);
|
|
12450
|
-
const
|
|
12451
|
-
const
|
|
12452
|
-
|
|
12800
|
+
const cells = useMemo(() => monthCells(view.year, view.month), [view.year, view.month]);
|
|
12801
|
+
const rowCount = cells.length / 7;
|
|
12802
|
+
const gridRef = useRef(null);
|
|
12803
|
+
const [rowCapacity, setRowCapacity] = useState(CALENDAR_BOARD_MAX_VISIBLE_EVENTS);
|
|
12804
|
+
useEffect(() => {
|
|
12805
|
+
const grid = gridRef.current;
|
|
12806
|
+
if (grid == null || typeof ResizeObserver === "undefined") return;
|
|
12807
|
+
const cell = grid.querySelector('[role="gridcell"]');
|
|
12808
|
+
if (cell == null) return;
|
|
12809
|
+
const apply = () => {
|
|
12810
|
+
const next = measureRowCapacity(cell);
|
|
12811
|
+
if (next != null) setRowCapacity(next);
|
|
12812
|
+
};
|
|
12813
|
+
apply();
|
|
12814
|
+
const observer = new ResizeObserver(apply);
|
|
12815
|
+
observer.observe(cell);
|
|
12816
|
+
return () => observer.disconnect();
|
|
12817
|
+
}, [rowCount]);
|
|
12818
|
+
const eventMap = useMemo(() => {
|
|
12819
|
+
const map = /* @__PURE__ */ new Map();
|
|
12820
|
+
(events ?? []).forEach((event) => {
|
|
12821
|
+
const list = map.get(event.date);
|
|
12822
|
+
if (list) list.push(event);
|
|
12823
|
+
else map.set(event.date, [event]);
|
|
12824
|
+
});
|
|
12825
|
+
return map;
|
|
12826
|
+
}, [events]);
|
|
12827
|
+
const openEvents = openDate ? eventMap.get(openDate) ?? [] : [];
|
|
12828
|
+
useLayoutEffect(() => {
|
|
12829
|
+
if (openDate == null || panelEl == null) return;
|
|
12830
|
+
const cell = gridRef.current?.querySelector(`[data-date="${openDate}"]`);
|
|
12831
|
+
if (cell == null) return;
|
|
12832
|
+
const adjust = () => {
|
|
12833
|
+
const cellRect = cell.getBoundingClientRect();
|
|
12834
|
+
const panelRect = panelEl.getBoundingClientRect();
|
|
12835
|
+
const next = {
|
|
12836
|
+
cellWidth: cellRect.width,
|
|
12837
|
+
cellHeight: cellRect.height,
|
|
12838
|
+
side: -(cellRect.height + DAY_EVENT_OUTDENT) + shiftIntoView(cellRect.top - DAY_EVENT_OUTDENT, panelRect.height, window.innerHeight),
|
|
12839
|
+
align: -DAY_EVENT_OUTDENT + shiftIntoView(cellRect.left - DAY_EVENT_OUTDENT, panelRect.width, window.innerWidth)
|
|
12840
|
+
};
|
|
12841
|
+
setPlacement(
|
|
12842
|
+
(prev) => prev.cellWidth === next.cellWidth && prev.cellHeight === next.cellHeight && prev.side === next.side && prev.align === next.align ? prev : next
|
|
12843
|
+
);
|
|
12844
|
+
};
|
|
12845
|
+
adjust();
|
|
12846
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(adjust);
|
|
12847
|
+
observer?.observe(panelEl);
|
|
12848
|
+
window.addEventListener("scroll", adjust, true);
|
|
12849
|
+
window.addEventListener("resize", adjust);
|
|
12850
|
+
return () => {
|
|
12851
|
+
observer?.disconnect();
|
|
12852
|
+
window.removeEventListener("scroll", adjust, true);
|
|
12853
|
+
window.removeEventListener("resize", adjust);
|
|
12854
|
+
};
|
|
12855
|
+
}, [openDate, panelEl]);
|
|
12856
|
+
const columns = "repeat(7, minmax(var(--cmp-calendarBoard-dayCard-minWidth), 1fr))";
|
|
12857
|
+
const openEventList = (date, list) => {
|
|
12858
|
+
if (onMoreClick) {
|
|
12859
|
+
onMoreClick({ date, events: list });
|
|
12860
|
+
return;
|
|
12861
|
+
}
|
|
12862
|
+
setOpenDate((prev) => prev === date ? null : date);
|
|
12863
|
+
};
|
|
12864
|
+
return /* @__PURE__ */ jsxs(
|
|
12453
12865
|
"div",
|
|
12454
12866
|
{
|
|
12455
|
-
ref: rootRef,
|
|
12456
|
-
"data-name": name || void 0,
|
|
12457
12867
|
className: cn(
|
|
12458
|
-
"
|
|
12459
|
-
|
|
12460
|
-
// 블록 레벨(flex)로 두어 쌓임은 그대로 유지한다. 나란히 놓으려면 부모를 flex 로.
|
|
12461
|
-
hug ? "flex w-fit max-w-full" : "inline-flex w-full",
|
|
12868
|
+
// 판 높이는 부모가 정한다 — 행이 그 높이를 균등 분할하고, 칸 높이가 다시 "몇 줄 보일지" 를 정한다.
|
|
12869
|
+
"flex h-full w-full flex-col overflow-hidden rounded-(--cmp-calendarBoard-radius) border border-solid border-(--cmp-calendarBoard-border) bg-(--cmp-calendarBoard-bg)",
|
|
12462
12870
|
className
|
|
12463
12871
|
),
|
|
12464
12872
|
style,
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12873
|
+
children: [
|
|
12874
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-(--cmp-calendarBoard-header-gap) px-sd-16 py-sd-12", children: [
|
|
12875
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-(--cmp-calendarBoard-header-content-gap)", children: [
|
|
12876
|
+
/* @__PURE__ */ jsx(
|
|
12877
|
+
SGhostButton,
|
|
12878
|
+
{
|
|
12879
|
+
icon: "chevronLeft",
|
|
12880
|
+
size: "xxs",
|
|
12881
|
+
ariaLabel: "\uC774\uC804 \uD574",
|
|
12882
|
+
onClick: () => setView({ year: view.year - 1, month: view.month })
|
|
12883
|
+
}
|
|
12884
|
+
),
|
|
12885
|
+
/* @__PURE__ */ jsx("span", { className: "typo-heading-lg inline-flex min-w-[48px] justify-center text-(--cmp-calendarBoard-header-content-color)", children: view.year }),
|
|
12886
|
+
/* @__PURE__ */ jsx(
|
|
12887
|
+
SGhostButton,
|
|
12888
|
+
{
|
|
12889
|
+
icon: "chevronRight",
|
|
12890
|
+
size: "xxs",
|
|
12891
|
+
ariaLabel: "\uB2E4\uC74C \uD574",
|
|
12892
|
+
onClick: () => setView({ year: view.year + 1, month: view.month })
|
|
12893
|
+
}
|
|
12894
|
+
)
|
|
12895
|
+
] }),
|
|
12896
|
+
/* @__PURE__ */ jsx(SDivider, { vertical: true, height: "var(--cmp-calendarBoard-header-content-divider-height)" }),
|
|
12897
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-(--cmp-calendarBoard-header-content-gap)", children: [
|
|
12898
|
+
/* @__PURE__ */ jsx(
|
|
12899
|
+
SGhostButton,
|
|
12900
|
+
{
|
|
12901
|
+
icon: "chevronLeft",
|
|
12902
|
+
size: "xxs",
|
|
12903
|
+
ariaLabel: "\uC774\uC804 \uB2EC",
|
|
12904
|
+
onClick: () => setView(calcYearMonth(view.year, view.month, "prev"))
|
|
12905
|
+
}
|
|
12906
|
+
),
|
|
12907
|
+
/* @__PURE__ */ jsxs("span", { className: "typo-heading-lg inline-flex min-w-[48px] justify-center text-(--cmp-calendarBoard-header-content-color)", children: [
|
|
12908
|
+
view.month,
|
|
12909
|
+
"\uC6D4"
|
|
12910
|
+
] }),
|
|
12911
|
+
/* @__PURE__ */ jsx(
|
|
12912
|
+
SGhostButton,
|
|
12913
|
+
{
|
|
12914
|
+
icon: "chevronRight",
|
|
12915
|
+
size: "xxs",
|
|
12916
|
+
ariaLabel: "\uB2E4\uC74C \uB2EC",
|
|
12917
|
+
onClick: () => setView(calcYearMonth(view.year, view.month, "next"))
|
|
12918
|
+
}
|
|
12919
|
+
)
|
|
12920
|
+
] }),
|
|
12921
|
+
todayLabel !== "" && /* @__PURE__ */ jsx(
|
|
12922
|
+
SButton,
|
|
12923
|
+
{
|
|
12924
|
+
color: "neutral",
|
|
12925
|
+
outline: true,
|
|
12926
|
+
size: "xs",
|
|
12927
|
+
label: todayLabel,
|
|
12928
|
+
onClick: () => setView({ year: ty, month: tm })
|
|
12929
|
+
}
|
|
12930
|
+
),
|
|
12931
|
+
headerRight != null && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: headerRight })
|
|
12932
|
+
] }),
|
|
12933
|
+
/* @__PURE__ */ jsx(SDivider, {}),
|
|
12934
|
+
/* @__PURE__ */ jsx(
|
|
12469
12935
|
"div",
|
|
12470
12936
|
{
|
|
12471
|
-
className: "
|
|
12472
|
-
style: {
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
SIcon,
|
|
12482
|
-
{
|
|
12483
|
-
name: icon,
|
|
12484
|
-
size: s.icon,
|
|
12485
|
-
color: iconColor,
|
|
12486
|
-
style: { marginRight: s.labelGap }
|
|
12487
|
-
}
|
|
12488
|
-
),
|
|
12489
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: label }),
|
|
12490
|
-
(labelTooltip !== "" || labelTooltipProps) && /* @__PURE__ */ jsx("span", { className: "shrink-0 flex items-center", style: { marginLeft: s.labelGap }, children: /* @__PURE__ */ jsx(
|
|
12491
|
-
STooltip2,
|
|
12492
|
-
{
|
|
12493
|
-
message: labelTooltip !== "" ? [labelTooltip] : void 0,
|
|
12494
|
-
iconSize: s.icon,
|
|
12495
|
-
...labelTooltipProps
|
|
12496
|
-
}
|
|
12497
|
-
) })
|
|
12498
|
-
]
|
|
12937
|
+
className: "grid shrink-0 bg-(--cmp-calendarBoard-grid-bg) pt-(--cmp-calendarBoard-grid-paddingTop) pb-(--cmp-calendarBoard-grid-gap)",
|
|
12938
|
+
style: { gridTemplateColumns: columns },
|
|
12939
|
+
children: WEEK_LABELS.map((label) => /* @__PURE__ */ jsx(
|
|
12940
|
+
"div",
|
|
12941
|
+
{
|
|
12942
|
+
className: "typo-body-md-default flex justify-center text-(--cmp-calendarBoard-grid-weekRow-color)",
|
|
12943
|
+
children: label
|
|
12944
|
+
},
|
|
12945
|
+
label
|
|
12946
|
+
))
|
|
12499
12947
|
}
|
|
12500
12948
|
),
|
|
12501
12949
|
/* @__PURE__ */ jsxs(
|
|
12502
|
-
|
|
12950
|
+
RPopover12.Root,
|
|
12503
12951
|
{
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
minWidth: fieldWidthValue(minWidth),
|
|
12508
|
-
maxWidth: resolvedMaxWidth
|
|
12952
|
+
open: openDate !== null,
|
|
12953
|
+
onOpenChange: (open) => {
|
|
12954
|
+
if (!open) setOpenDate(null);
|
|
12509
12955
|
},
|
|
12510
12956
|
children: [
|
|
12511
|
-
/* @__PURE__ */
|
|
12957
|
+
/* @__PURE__ */ jsx(
|
|
12512
12958
|
"div",
|
|
12513
12959
|
{
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
// 이 상자가 스크롤포트가 되어 안쪽의 position:sticky 가 페이지 스크롤을 따라가지
|
|
12518
|
-
// 못한다 (SEditor 의 고정 툴바). 여러 줄 필드에서만 바꿔 파급을 좁힌다.
|
|
12519
|
-
multiline ? "overflow-clip" : "overflow-hidden",
|
|
12520
|
-
interactive && !borderless && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
|
|
12521
|
-
disabled && "cursor-not-allowed"
|
|
12522
|
-
),
|
|
12960
|
+
ref: gridRef,
|
|
12961
|
+
role: "grid",
|
|
12962
|
+
className: "grid min-h-0 flex-1 gap-px overflow-auto border-t border-solid border-(--cmp-calendarBoard-grid-month-border) bg-(--cmp-calendarBoard-grid-month-border)",
|
|
12523
12963
|
style: {
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
...interactive && !borderless && (focused || hovered) ? { boxShadow: FOCUS_RING_SHADOW } : {},
|
|
12528
|
-
...multiline ? { minHeight: s.height } : { height: s.height },
|
|
12529
|
-
"borderRadius": s.radius,
|
|
12530
|
-
"background": bgColor,
|
|
12531
|
-
"color": textColor
|
|
12964
|
+
gridTemplateColumns: columns,
|
|
12965
|
+
// 행은 판 높이를 균등하게 나눠 갖는다 — 일정이 많은 주만 길어지면 격자가 깨진다.
|
|
12966
|
+
gridTemplateRows: `repeat(${rowCount}, minmax(var(--cmp-calendarBoard-dayCard-minHeight), 1fr))`
|
|
12532
12967
|
},
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12968
|
+
children: cells.map((cell) => {
|
|
12969
|
+
const content = dayContent?.[cell.date];
|
|
12970
|
+
const list = content == null ? eventMap.get(cell.date) ?? [] : [];
|
|
12971
|
+
const folded = list.length > rowCapacity;
|
|
12972
|
+
const visible = folded ? list.slice(0, rowCapacity - 1) : list;
|
|
12973
|
+
const card = /* @__PURE__ */ jsx(
|
|
12974
|
+
CalendarDayCard,
|
|
12538
12975
|
{
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12976
|
+
date: cell.date,
|
|
12977
|
+
day: cell.day,
|
|
12978
|
+
inCurrentMonth: cell.inCurrentMonth,
|
|
12979
|
+
isToday: cell.date === today,
|
|
12980
|
+
isSelected: value != null && value === cell.date,
|
|
12981
|
+
selectable,
|
|
12982
|
+
color: dayColors?.[cell.date] ?? "default",
|
|
12983
|
+
events: visible,
|
|
12984
|
+
body: content,
|
|
12985
|
+
hiddenCount: folded ? list.length - (rowCapacity - 1) : 0,
|
|
12986
|
+
isOpen: openDate === cell.date,
|
|
12987
|
+
moreLabel,
|
|
12988
|
+
onDaySelect: (date) => onValueChange?.(date, list),
|
|
12989
|
+
onEventClick,
|
|
12990
|
+
onOpenEvents: () => openEventList(cell.date, list)
|
|
12991
|
+
},
|
|
12992
|
+
cell.date
|
|
12993
|
+
);
|
|
12994
|
+
return cell.date === openDate ? /* @__PURE__ */ jsx(RPopover12.Anchor, { asChild: true, children: card }, cell.date) : card;
|
|
12995
|
+
})
|
|
12557
12996
|
}
|
|
12558
12997
|
),
|
|
12559
|
-
|
|
12998
|
+
/* @__PURE__ */ jsx(RPopover12.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
|
|
12999
|
+
RPopover12.Content,
|
|
13000
|
+
{
|
|
13001
|
+
onInteractOutside: (e) => {
|
|
13002
|
+
const target = e.detail.originalEvent.target;
|
|
13003
|
+
if (target instanceof Node && gridRef.current?.contains(target)) e.preventDefault();
|
|
13004
|
+
},
|
|
13005
|
+
side: "bottom",
|
|
13006
|
+
align: "start",
|
|
13007
|
+
ref: setPanelEl,
|
|
13008
|
+
sideOffset: placement.side,
|
|
13009
|
+
alignOffset: placement.align,
|
|
13010
|
+
avoidCollisions: false,
|
|
13011
|
+
className: cn("z-50 outline-none", FLOATING_SLIDE_ANIM),
|
|
13012
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
13013
|
+
children: openDate != null && /* @__PURE__ */ jsx(
|
|
13014
|
+
CalendarDayEventListBox,
|
|
13015
|
+
{
|
|
13016
|
+
date: openDate,
|
|
13017
|
+
minWidth: placement.cellWidth > 0 ? placement.cellWidth + DAY_EVENT_OUTDENT * 2 : void 0,
|
|
13018
|
+
minHeight: placement.cellHeight > 0 ? placement.cellHeight + DAY_EVENT_OUTDENT * 2 : void 0,
|
|
13019
|
+
events: openEvents,
|
|
13020
|
+
onEventClick,
|
|
13021
|
+
onClose: () => setOpenDate(null)
|
|
13022
|
+
}
|
|
13023
|
+
)
|
|
13024
|
+
},
|
|
13025
|
+
openDate
|
|
13026
|
+
) })
|
|
12560
13027
|
]
|
|
12561
13028
|
}
|
|
12562
13029
|
)
|
|
12563
|
-
]
|
|
13030
|
+
]
|
|
12564
13031
|
}
|
|
12565
13032
|
);
|
|
12566
|
-
}
|
|
13033
|
+
}
|
|
12567
13034
|
|
|
12568
|
-
// src/lib/
|
|
12569
|
-
var
|
|
13035
|
+
// src/lib/floating-height.ts
|
|
13036
|
+
var POPOVER_AVAILABLE_HEIGHT = "var(--radix-popover-content-available-height)";
|
|
13037
|
+
function clampToAvailableHeight(value, availableHeight) {
|
|
13038
|
+
if (value == null || value === "") return availableHeight;
|
|
13039
|
+
const css = typeof value === "number" ? `${value}px` : value;
|
|
13040
|
+
return `min(${css}, ${availableHeight})`;
|
|
13041
|
+
}
|
|
12570
13042
|
var FONT = {
|
|
12571
13043
|
sm: {
|
|
12572
13044
|
fontSize: 12,
|
|
@@ -14851,158 +15323,6 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
14851
15323
|
}
|
|
14852
15324
|
);
|
|
14853
15325
|
});
|
|
14854
|
-
var TEXTAREA_SIZE = {
|
|
14855
|
-
sm: {
|
|
14856
|
-
fontSize: 12,
|
|
14857
|
-
lineHeight: 20,
|
|
14858
|
-
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
14859
|
-
paddingY: "var(--cmp-textinput-sm-paddingY)"
|
|
14860
|
-
},
|
|
14861
|
-
md: {
|
|
14862
|
-
fontSize: 14,
|
|
14863
|
-
lineHeight: 24,
|
|
14864
|
-
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
14865
|
-
paddingY: "var(--cmp-textinput-md-paddingY)"
|
|
14866
|
-
}
|
|
14867
|
-
};
|
|
14868
|
-
var MIN_ROWS = 2;
|
|
14869
|
-
var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
14870
|
-
value,
|
|
14871
|
-
onValueChange,
|
|
14872
|
-
onChange,
|
|
14873
|
-
size = "sm",
|
|
14874
|
-
rows = MIN_ROWS,
|
|
14875
|
-
autogrow = false,
|
|
14876
|
-
maxRows,
|
|
14877
|
-
rules,
|
|
14878
|
-
status,
|
|
14879
|
-
focused,
|
|
14880
|
-
hovered,
|
|
14881
|
-
textareaClassName,
|
|
14882
|
-
textareaStyle,
|
|
14883
|
-
label,
|
|
14884
|
-
labelWidth,
|
|
14885
|
-
icon,
|
|
14886
|
-
iconColor,
|
|
14887
|
-
labelTooltip,
|
|
14888
|
-
labelTooltipProps,
|
|
14889
|
-
addonLabel,
|
|
14890
|
-
addonAlign,
|
|
14891
|
-
hint,
|
|
14892
|
-
error,
|
|
14893
|
-
errorMessage,
|
|
14894
|
-
width,
|
|
14895
|
-
disabled = false,
|
|
14896
|
-
readOnly = false,
|
|
14897
|
-
placeholder = "\uC785\uB825\uD574 \uC8FC\uC138\uC694.",
|
|
14898
|
-
onBlur,
|
|
14899
|
-
className,
|
|
14900
|
-
style,
|
|
14901
|
-
...rest
|
|
14902
|
-
}, ref) {
|
|
14903
|
-
const p = TEXTAREA_SIZE[size];
|
|
14904
|
-
const heightForRows = (n) => `calc(${p.lineHeight * n}px + ${p.paddingY} * 2)`;
|
|
14905
|
-
const minHeight = heightForRows(MIN_ROWS);
|
|
14906
|
-
const maxHeight = autogrow && maxRows != null ? heightForRows(maxRows) : void 0;
|
|
14907
|
-
const [ruleError, setRuleError] = useState("");
|
|
14908
|
-
const innerRef = useRef(null);
|
|
14909
|
-
const setRefs2 = useCallback(
|
|
14910
|
-
(node) => {
|
|
14911
|
-
innerRef.current = node;
|
|
14912
|
-
if (typeof ref === "function") ref(node);
|
|
14913
|
-
else if (ref) ref.current = node;
|
|
14914
|
-
},
|
|
14915
|
-
[ref]
|
|
14916
|
-
);
|
|
14917
|
-
useLayoutEffect(() => {
|
|
14918
|
-
const el = innerRef.current;
|
|
14919
|
-
if (el == null) return;
|
|
14920
|
-
if (!autogrow) {
|
|
14921
|
-
el.style.height = "";
|
|
14922
|
-
return;
|
|
14923
|
-
}
|
|
14924
|
-
el.style.height = "auto";
|
|
14925
|
-
el.style.height = `${el.scrollHeight}px`;
|
|
14926
|
-
}, [autogrow, maxHeight, minHeight, rows, value]);
|
|
14927
|
-
useFormField({
|
|
14928
|
-
name: rest.name,
|
|
14929
|
-
validate: () => {
|
|
14930
|
-
const msg = runRules(value, rules);
|
|
14931
|
-
setRuleError(msg);
|
|
14932
|
-
return msg === "";
|
|
14933
|
-
},
|
|
14934
|
-
resetValidation: () => setRuleError("")
|
|
14935
|
-
});
|
|
14936
|
-
const resolvedError = error || ruleError !== "";
|
|
14937
|
-
const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
|
|
14938
|
-
const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
|
|
14939
|
-
return /* @__PURE__ */ jsx(
|
|
14940
|
-
SField,
|
|
14941
|
-
{
|
|
14942
|
-
label,
|
|
14943
|
-
labelWidth,
|
|
14944
|
-
icon,
|
|
14945
|
-
iconColor,
|
|
14946
|
-
labelTooltip,
|
|
14947
|
-
labelTooltipProps,
|
|
14948
|
-
addonLabel,
|
|
14949
|
-
addonAlign,
|
|
14950
|
-
hint,
|
|
14951
|
-
size,
|
|
14952
|
-
error: resolvedError,
|
|
14953
|
-
status: resolvedStatus,
|
|
14954
|
-
focused,
|
|
14955
|
-
hovered,
|
|
14956
|
-
errorMessage: resolvedErrorMessage,
|
|
14957
|
-
width,
|
|
14958
|
-
disabled,
|
|
14959
|
-
readOnly,
|
|
14960
|
-
multiline: true,
|
|
14961
|
-
className,
|
|
14962
|
-
style,
|
|
14963
|
-
children: /* @__PURE__ */ jsx(
|
|
14964
|
-
"textarea",
|
|
14965
|
-
{
|
|
14966
|
-
ref: setRefs2,
|
|
14967
|
-
value: value ?? "",
|
|
14968
|
-
rows,
|
|
14969
|
-
disabled,
|
|
14970
|
-
readOnly,
|
|
14971
|
-
placeholder,
|
|
14972
|
-
onChange: (e) => {
|
|
14973
|
-
onChange?.(e);
|
|
14974
|
-
onValueChange?.(e.target.value);
|
|
14975
|
-
if (ruleError !== "") setRuleError(runRules(e.target.value, rules));
|
|
14976
|
-
},
|
|
14977
|
-
onBlur: (e) => {
|
|
14978
|
-
onBlur?.(e);
|
|
14979
|
-
if (rules && rules.length > 0) setRuleError(runRules(e.target.value, rules));
|
|
14980
|
-
},
|
|
14981
|
-
className: cn(
|
|
14982
|
-
"w-full border-0 bg-transparent outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed",
|
|
14983
|
-
// autogrow 와 끌어서 늘리기는 같은 높이를 두고 다투므로 함께 두지 않는다
|
|
14984
|
-
autogrow ? "resize-none" : "resize-y",
|
|
14985
|
-
AUTOFILL_RESET_CLASS,
|
|
14986
|
-
textareaClassName
|
|
14987
|
-
),
|
|
14988
|
-
style: {
|
|
14989
|
-
minHeight,
|
|
14990
|
-
maxHeight,
|
|
14991
|
-
// 상한이 있으면 거기 닿았을 때 안에서 스크롤한다. 상한이 없으면 높이가 늘 내용과
|
|
14992
|
-
// 같으므로 스크롤바가 나올 일이 없고, 반올림으로 1px 이 넘쳐 깜빡이는 것만 막는다.
|
|
14993
|
-
overflowY: autogrow ? maxRows != null ? "auto" : "hidden" : void 0,
|
|
14994
|
-
padding: `${p.paddingY} ${p.paddingX}`,
|
|
14995
|
-
fontSize: p.fontSize,
|
|
14996
|
-
lineHeight: `${p.lineHeight}px`,
|
|
14997
|
-
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
14998
|
-
...textareaStyle
|
|
14999
|
-
},
|
|
15000
|
-
...rest
|
|
15001
|
-
}
|
|
15002
|
-
)
|
|
15003
|
-
}
|
|
15004
|
-
);
|
|
15005
|
-
});
|
|
15006
15326
|
var PAD2 = {
|
|
15007
15327
|
sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
|
|
15008
15328
|
md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
|
|
@@ -23059,6 +23379,6 @@ function STimeRangePicker({
|
|
|
23059
23379
|
);
|
|
23060
23380
|
}
|
|
23061
23381
|
|
|
23062
|
-
export { ACCOUNT_LIST_BOX_ICONS, ACCOUNT_LIST_BOX_ITEM_TONES, ACCOUNT_LIST_BOX_LABELS, ACCOUNT_LIST_BOX_LAYOUT, ACCOUNT_LIST_BOX_TONE_CONFIG, BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, CALENDAR_BOARD_DAY_BG, CALENDAR_BOARD_DAY_COLORS, CALENDAR_BOARD_EVENT_COLORS, CALENDAR_BOARD_EVENT_PRESETS, CALENDAR_BOARD_MAX_VISIBLE_EVENTS, COLOR_KEYS, FIELD_WIDTH_GRADES, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, GNB_SYSTEM_COLORS, GNB_SYSTEM_COLOR_CONFIG, GNB_SYSTEM_LAYOUT, GNB_SYSTEM_PLACEMENTS, GNB_SYSTEM_TOP_COLOR_CONFIG, ICONS, IMAGE_FITS, PAGE_BACKGROUNDS, PAGE_CONTENT_HEIGHTS, PAGE_CONTENT_WIDTHS, PAGE_HEADER_VARIANTS, RangeCalendar, SAccountListBox, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCalendarBoard, SCallout, SCard, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SEDITOR_DEFAULT_FONT_SIZE, SEDITOR_HEADING_LABELS, SEDITOR_HEADING_LEVELS, SEditor, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGnbSystem, SGnbSystemContext, SGuide, SIcon, SImage, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SModal, SModalOutlet, SNumberInput, SPage, SPageHeader, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioCard, SRadioCardGroup, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSearchInput, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, SSystemActionButton, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, SYSTEM_ACTION_BUTTON_COLORS, SYSTEM_ACTION_BUTTON_COLOR_CONFIG, SYSTEM_ACTION_BUTTON_LAYOUT, SYSTEM_ACTION_BUTTON_TYPES, SYSTEM_ACTION_BUTTON_TYPE_CONFIG, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, fieldWidthValue, findGnbAncestors, findGnbRailValue, isColorKey, isFieldWidthGrade, loading, resolveColor, useSLayout };
|
|
23382
|
+
export { ACCOUNT_LIST_BOX_ICONS, ACCOUNT_LIST_BOX_ITEM_TONES, ACCOUNT_LIST_BOX_LABELS, ACCOUNT_LIST_BOX_LAYOUT, ACCOUNT_LIST_BOX_TONE_CONFIG, BADGE_COLORS, BUTTON_COLORS, BUTTON_SIZES, CALENDAR_BOARD_DAY_BG, CALENDAR_BOARD_DAY_COLORS, CALENDAR_BOARD_EVENT_COLORS, CALENDAR_BOARD_EVENT_PRESETS, CALENDAR_BOARD_MAX_VISIBLE_EVENTS, CHAT_MESSAGE_DIRECTIONS, CHAT_MESSAGE_READ_STATUSES, CHAT_MESSAGE_VARIANTS, COLOR_KEYS, FIELD_WIDTH_GRADES, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, GNB_SYSTEM_COLORS, GNB_SYSTEM_COLOR_CONFIG, GNB_SYSTEM_LAYOUT, GNB_SYSTEM_PLACEMENTS, GNB_SYSTEM_TOP_COLOR_CONFIG, ICONS, IMAGE_FITS, PAGE_BACKGROUNDS, PAGE_CONTENT_HEIGHTS, PAGE_CONTENT_WIDTHS, PAGE_HEADER_VARIANTS, RangeCalendar, SAccountListBox, SActionModal, SBadge, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCalendarBoard, SCallout, SCard, SChatInput2 as SChatInput, SChatMessage2 as SChatMessage, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, SDateRangePicker, SDivider, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SEDITOR_DEFAULT_FONT_SIZE, SEDITOR_HEADING_LABELS, SEDITOR_HEADING_LEVELS, SEditor, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGnbSystem, SGnbSystemContext, SGuide, SIcon, SImage, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLayout, SLayoutContext, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoadingViewport, SLoginCard2 as SLoginCard, SModal, SModalOutlet, SNumberInput, SPage, SPageHeader, SPagination, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioCard, SRadioCardGroup, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSearchInput, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, SSystemActionButton, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, SYSTEM_ACTION_BUTTON_COLORS, SYSTEM_ACTION_BUTTON_COLOR_CONFIG, SYSTEM_ACTION_BUTTON_LAYOUT, SYSTEM_ACTION_BUTTON_TYPES, SYSTEM_ACTION_BUTTON_TYPE_CONFIG, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, fieldWidthValue, findGnbAncestors, findGnbRailValue, isColorKey, isFieldWidthGrade, loading, resolveColor, useSLayout };
|
|
23063
23383
|
//# sourceMappingURL=index.js.map
|
|
23064
23384
|
//# sourceMappingURL=index.js.map
|