@telepix-lab/telepix-ui 0.6.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/button/index.d.ts +12 -0
- package/dist/cjs/button/types.d.ts +1 -0
- package/dist/cjs/client.js +188 -36
- package/dist/cjs/date-picker/index.d.ts +17 -3
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +67 -19
- package/dist/cjs/notify-item/index.d.ts +12 -0
- package/dist/client.d.ts +17 -3
- package/dist/esm/button/index.d.ts +12 -0
- package/dist/esm/button/types.d.ts +1 -0
- package/dist/esm/client.js +189 -37
- package/dist/esm/date-picker/index.d.ts +17 -3
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +66 -20
- package/dist/esm/notify-item/index.d.ts +12 -0
- package/dist/index.d.ts +34 -9
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -24,3 +24,15 @@ export interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAtt
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export declare const Button: React.ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
27
|
+
/**
|
|
28
|
+
* Text Dim 스타일의 버튼 컴포넌트입니다.<br/>
|
|
29
|
+
* 텍스트 중심의 보조 액션(secondary / subtle action)에 적합한 low-emphasis 스타일을 제공합니다.<br/>
|
|
30
|
+
* 기본적으로 낮은 명도의 텍스트를 사용하며, hover 시 명도가 상승하고 selected 시 accent 색상으로 강조됩니다.<br/>
|
|
31
|
+
* <br/>
|
|
32
|
+
* ### 사용 예시
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <ButtonTextDim>자세히 보기</ButtonTextDim>
|
|
35
|
+
* <ButtonTextDim aria-selected="true">선택됨</ButtonTextDim>
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare const ButtonTextDim: React.ForwardRefExoticComponent<Omit<Omit<ButtonProps, "variant">, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -15,5 +15,6 @@ export declare const BUTTON_VARIANTS: {
|
|
|
15
15
|
readonly OUTLINE_ACCENT: "outline_accent";
|
|
16
16
|
readonly GHOST_ACCENT: "ghost_accent";
|
|
17
17
|
readonly GHOST_DIM: "ghost_dim";
|
|
18
|
+
readonly TEXT_DIM: "text_dim";
|
|
18
19
|
};
|
|
19
20
|
export type ButtonVariant = (typeof BUTTON_VARIANTS)[keyof typeof BUTTON_VARIANTS];
|
package/dist/cjs/client.js
CHANGED
|
@@ -12345,11 +12345,19 @@ const Checkbox = React.forwardRef(({ label, labelClassName, wrapperClassName, ..
|
|
|
12345
12345
|
setChecked(value);
|
|
12346
12346
|
onChange?.(value);
|
|
12347
12347
|
};
|
|
12348
|
-
|
|
12348
|
+
const handleWrapperClick = (e) => {
|
|
12349
|
+
// CheckboxRadix.Root와 label은 자체 클릭 핸들러를 가지고 있으므로
|
|
12350
|
+
// wrapper 영역(StateColorContainer 포함)을 직접 클릭한 경우에만 토글
|
|
12351
|
+
if (disabled || e.target !== e.currentTarget)
|
|
12352
|
+
return;
|
|
12353
|
+
const currentChecked = defaultChecked ? checked : isChecked;
|
|
12354
|
+
const newValue = !currentChecked;
|
|
12355
|
+
onCheckedChange(newValue);
|
|
12356
|
+
};
|
|
12357
|
+
return (jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2.5 pl-1.5 py-1 relative group/state", !label ? "pr-1.5 rounded-sm" : "pr-3 rounded-lg", !disabled && "cursor-pointer", wrapperClassName), onClick: handleWrapperClick, children: [jsxRuntime.jsx(Checkbox$1, { ref: ref, id: id ?? randomId, ...rest, checked: defaultChecked ? checked : isChecked, className: cn("size-4 p-0 cursor-pointer border-transparent bg-transparent", className), onCheckedChange: onCheckedChange, children: renderCheckboxIcon(defaultChecked ? checked : isChecked, disabled) }), label && (jsxRuntime.jsx("label", { className: cn("text-body leading-body-compact text-comp-mono-default font-medium cursor-pointer", disabled && "text-comp-disabled cursor-default", labelClassName), htmlFor: id ?? randomId, "aria-disabled": disabled, children: label })), jsxRuntime.jsx(StateColorContainer, { className: cn(disabled
|
|
12349
12358
|
? "bg-fill-default group-hover/state:bg-fill-default group-active/state:bg-fill-default"
|
|
12350
12359
|
: "") })] }));
|
|
12351
12360
|
});
|
|
12352
|
-
Checkbox.displayName = "Checkbox";
|
|
12353
12361
|
|
|
12354
12362
|
/**
|
|
12355
12363
|
* 카드 컴포넌트는 콘텐츠를 그룹화하고 시각적으로 구분하는 데 사용됩니다.<br/>
|
|
@@ -13128,6 +13136,7 @@ const Calendar = ({ className, classNames, showOutsideDays = true, ...props }) =
|
|
|
13128
13136
|
weekday: "text-comp-mono-subtle-default text-body font-normal leading-body size-9 p-1",
|
|
13129
13137
|
day: "p-1 bg-transparent",
|
|
13130
13138
|
day_button: "size-8 rounded-md hover:bg-fill-hovered focus:outline-none text-body leading-3.5 font-medium text-comp-mono-default cursor-pointer",
|
|
13139
|
+
disabled: "[&_button]:text-comp-disabled [&_button]:cursor-not-allowed [&_button]:hover:bg-transparent",
|
|
13131
13140
|
selected: cn("[&_button]:bg-page-accent-l0 bg-transparent", props.mode === "single" &&
|
|
13132
13141
|
"[&_button]:text-comp-accent-default [&_button]:hover:bg-page-accent-l0"),
|
|
13133
13142
|
outside: "[&_button]:text-comp-disabled",
|
|
@@ -13147,6 +13156,15 @@ const Calendar = ({ className, classNames, showOutsideDays = true, ...props }) =
|
|
|
13147
13156
|
}, ...props }));
|
|
13148
13157
|
};
|
|
13149
13158
|
|
|
13159
|
+
var dayjs_min = {exports: {}};
|
|
13160
|
+
|
|
13161
|
+
(function (module, exports) {
|
|
13162
|
+
!function(t,e){module.exports=e();}(commonjsGlobal,(function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return "["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return !r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return (e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return -t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return +(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return {M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},g="en",D={};D[g]=M;var p="$isDayjsObject",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else {var a=e.name;D[a]=e,i=a;}return !r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,true),this.parse(t),this.$x=this.$x||t.x||{},this[p]=true;}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init();},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds();},m.$utils=function(){return b},m.isValid=function(){return !(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v="set"+(this.$u?"UTC":"");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+"Hours",0);case u:return $(v+"Minutes",1);case s:return $(v+"Seconds",2);case i:return $(v+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,false)},m.$set=function(t,e){var n,o=b.p(t),f="set"+(this.$u?"UTC":""),l=(n={},n[a]=f+"Date",n[d]=f+"Date",n[c]=f+"Month",n[h]=f+"FullYear",n[u]=f+"Hours",n[s]=f+"Minutes",n[i]=f+"Seconds",n[r]=f+"Milliseconds",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d;}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,"0")},$=f||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case "YY":return String(e.$y).slice(-2);case "YYYY":return b.s(e.$y,4,"0");case "M":return a+1;case "MM":return b.s(a+1,2,"0");case "MMM":return h(n.monthsShort,a,c,3);case "MMMM":return h(c,a);case "D":return e.$D;case "DD":return b.s(e.$D,2,"0");case "d":return String(e.$W);case "dd":return h(n.weekdaysMin,e.$W,o,2);case "ddd":return h(n.weekdaysShort,e.$W,o,3);case "dddd":return o[e.$W];case "H":return String(s);case "HH":return b.s(s,2,"0");case "h":return d(1);case "hh":return d(2);case "a":return $(s,u,true);case "A":return $(s,u,false);case "m":return String(u);case "mm":return b.s(u,2,"0");case "s":return String(e.$s);case "ss":return b.s(e.$s,2,"0");case "SSS":return b.s(e.$ms,3,"0");case "Z":return i}return null}(t)||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g;}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,true);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",c],["$y",h],["$D",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])};})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=true),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));
|
|
13163
|
+
} (dayjs_min));
|
|
13164
|
+
|
|
13165
|
+
var dayjs_minExports = dayjs_min.exports;
|
|
13166
|
+
var dayjs = /*@__PURE__*/getDefaultExportFromCjs(dayjs_minExports);
|
|
13167
|
+
|
|
13150
13168
|
const BUTTON_SIZES = {
|
|
13151
13169
|
REGULAR: "regular",
|
|
13152
13170
|
SMALL: "small",
|
|
@@ -13154,7 +13172,9 @@ const BUTTON_SIZES = {
|
|
|
13154
13172
|
};
|
|
13155
13173
|
const BUTTON_VARIANTS = {
|
|
13156
13174
|
ACCENT: "accent",
|
|
13157
|
-
THUMBNAIL_GHOST: "thumbnail_ghost"
|
|
13175
|
+
THUMBNAIL_GHOST: "thumbnail_ghost",
|
|
13176
|
+
TEXT_DIM: "text_dim",
|
|
13177
|
+
};
|
|
13158
13178
|
|
|
13159
13179
|
/**
|
|
13160
13180
|
* 다양한 스타일과 속성을 지원하는 버튼 컴포넌트입니다.<br/>
|
|
@@ -13172,6 +13192,13 @@ const BUTTON_VARIANTS = {
|
|
|
13172
13192
|
*/
|
|
13173
13193
|
const Button = React.forwardRef(({ variant = "accent", size = "regular", fullWidth = false, isLoading = false, leftIcon, rightIcon, children, disabled, className, stateContainerClassName, ...rest }, ref) => {
|
|
13174
13194
|
const getClassName = (size, variant) => {
|
|
13195
|
+
// text_dim variant는 size에 관계없이 고정된 스타일 사용
|
|
13196
|
+
if (variant === BUTTON_VARIANTS.TEXT_DIM) {
|
|
13197
|
+
return [
|
|
13198
|
+
"h-auto py-0.5 px-0 text-body leading-body-compact gap-1.5",
|
|
13199
|
+
"bg-page-l-null text-comp-mono-subtle-default hover:text-comp-mono-default aria-selected:text-comp-mono-default disabled:bg-page-l-null disabled:text-comp-disabled disabled:hover:text-comp-disabled",
|
|
13200
|
+
];
|
|
13201
|
+
}
|
|
13175
13202
|
const sizeClassName = {
|
|
13176
13203
|
small: "h-7 py-0 px-1 text-label leading-label-compact gap-1",
|
|
13177
13204
|
regular: "h-9 py-0 px-2 text-body leading-body-compact gap-1.5",
|
|
@@ -13188,6 +13215,7 @@ const Button = React.forwardRef(({ variant = "accent", size = "regular", fullWid
|
|
|
13188
13215
|
outline_accent: "bg-page-l-null disabled:bg-page-l-null text-comp-accent-default disabled:text-comp-disabled border border-border-accent-bound disabled:border-pure-transparent aria-selected:border-border-accent-selected",
|
|
13189
13216
|
ghost_accent: "bg-page-l-null disabled:bg-page-l-null text-comp-accent-default disabled:text-comp-disabled",
|
|
13190
13217
|
ghost_dim: "bg-page-l-null disabled:bg-page-l-null text-comp-mono-subtle-default disabled:text-comp-disabled aria-selected:text-comp-mono-default",
|
|
13218
|
+
text_dim: "", // 위에서 처리되므로 여기서는 빈 문자열
|
|
13191
13219
|
}[variant];
|
|
13192
13220
|
return [sizeClassName, variantClassName];
|
|
13193
13221
|
};
|
|
@@ -13205,48 +13233,170 @@ const Button = React.forwardRef(({ variant = "accent", size = "regular", fullWid
|
|
|
13205
13233
|
return "size-5";
|
|
13206
13234
|
return "size-6"; // 기본값은 regular 크기
|
|
13207
13235
|
};
|
|
13208
|
-
return (jsxRuntime.jsxs("button", { ref: ref, disabled: disabled ?? isLoading, className: cn("flex group/state items-center justify-center relative box-border m-0 border-transparent outline-none cursor-pointer select-none align-middle appearance-none text-center transition-normal font-medium w-auto rounded-md overflow-hidden pointer-events-auto disabled:pointer-events-none disabled:cursor-not-allowed", ...getClassName(size, variant), fullWidth && "w-full", className), ...rest, children: [jsxRuntime.jsx(StateColorContainer, { isInverted: variant === BUTTON_VARIANTS.ACCENT, className: stateContainerClassName }), isLoading && (jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: cn("lucide lucide-loader-circle-icon lucide-loader-circle absolute animate-spin", size === BUTTON_SIZES.SMALL &&
|
|
13236
|
+
return (jsxRuntime.jsxs("button", { ref: ref, disabled: disabled ?? isLoading, className: cn("flex group/state items-center justify-center relative box-border m-0 border-transparent outline-none cursor-pointer select-none align-middle appearance-none text-center transition-normal font-medium w-auto rounded-md overflow-hidden pointer-events-auto disabled:pointer-events-none disabled:cursor-not-allowed", ...getClassName(size, variant), fullWidth && "w-full", className), ...rest, children: [variant !== BUTTON_VARIANTS.TEXT_DIM && (jsxRuntime.jsx(StateColorContainer, { isInverted: variant === BUTTON_VARIANTS.ACCENT, className: stateContainerClassName })), isLoading && (jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: cn("lucide lucide-loader-circle-icon lucide-loader-circle absolute animate-spin", size === BUTTON_SIZES.SMALL &&
|
|
13209
13237
|
"size-4 top-[calc(50%-8px)] left-[calc(50%-8px)]", size === BUTTON_SIZES.REGULAR &&
|
|
13210
13238
|
"size-5 top-[calc(50%-10px)] left-[calc(50%-10px)]", size === BUTTON_SIZES.LARGE &&
|
|
13211
13239
|
"size-6 top-[calc(50%-12px)] left-[calc(50%-12px)]"), children: jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) })), leftIcon && (jsxRuntime.jsx("div", { className: cn("flex items-center justify-center relative", variant === BUTTON_VARIANTS.THUMBNAIL_GHOST &&
|
|
13212
13240
|
"aspect-square [&_img]:rounded-sm", getThumbnailSize(variant, size)), children: leftIcon })), children && (jsxRuntime.jsx("div", { className: "flex-1", style: { visibility: isLoading ? "hidden" : "visible" }, children: children })), rightIcon && (jsxRuntime.jsx("div", { className: cn("flex items-center justify-center relative", getThumbnailSize(variant, size)), children: rightIcon }))] }));
|
|
13213
13241
|
});
|
|
13214
13242
|
Button.displayName = "Button";
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
|
|
13243
|
+
/**
|
|
13244
|
+
* Text Dim 스타일의 버튼 컴포넌트입니다.<br/>
|
|
13245
|
+
* 텍스트 중심의 보조 액션(secondary / subtle action)에 적합한 low-emphasis 스타일을 제공합니다.<br/>
|
|
13246
|
+
* 기본적으로 낮은 명도의 텍스트를 사용하며, hover 시 명도가 상승하고 selected 시 accent 색상으로 강조됩니다.<br/>
|
|
13247
|
+
* <br/>
|
|
13248
|
+
* ### 사용 예시
|
|
13249
|
+
* ```tsx
|
|
13250
|
+
* <ButtonTextDim>자세히 보기</ButtonTextDim>
|
|
13251
|
+
* <ButtonTextDim aria-selected="true">선택됨</ButtonTextDim>
|
|
13252
|
+
* ```
|
|
13253
|
+
*/
|
|
13254
|
+
const ButtonTextDim = React.forwardRef((props, ref) => {
|
|
13255
|
+
return jsxRuntime.jsx(Button, { ref: ref, variant: "text_dim", ...props });
|
|
13256
|
+
});
|
|
13257
|
+
ButtonTextDim.displayName = "ButtonTextDim";
|
|
13258
|
+
|
|
13259
|
+
// Constants
|
|
13260
|
+
const CALENDAR_MODES = {
|
|
13261
|
+
SINGLE: "single",
|
|
13262
|
+
MULTIPLE: "multiple",
|
|
13263
|
+
RANGE: "range",
|
|
13264
|
+
};
|
|
13265
|
+
const DEFAULT_FORMAT = "YYYY. MM. DD.";
|
|
13266
|
+
const DEFAULT_PLACEHOLDER = "Pick a date";
|
|
13267
|
+
const DatePicker = ({ size = "regular", placeholder = DEFAULT_PLACEHOLDER, format = DEFAULT_FORMAT, value, mode = CALENDAR_MODES.SINGLE, onChange, isInstantClose = false, open: openProp, onOpenChange: onOpenChangeProp, disabled, popoverContentClassName, minDate, maxDate, disabledDates, ...rest }) => {
|
|
13268
|
+
// Determine if component is in controlled mode
|
|
13269
|
+
// Using useRef to track initial controlled state (React's recommended approach)
|
|
13270
|
+
const isControlledRef = React.useRef(value !== undefined);
|
|
13271
|
+
const isControlled = isControlledRef.current;
|
|
13272
|
+
const [internalValue, setInternalValue] = React.useState(value);
|
|
13273
|
+
const [internalOpen, setInternalOpen] = React.useState(openProp ?? false);
|
|
13274
|
+
const [lastInteractedDate, setLastInteractedDate] = React.useState(undefined);
|
|
13275
|
+
// Use controlled value if provided, otherwise use internal state
|
|
13276
|
+
const displayValue = isControlled ? value : internalValue;
|
|
13277
|
+
const displayOpen = openProp !== undefined ? openProp : internalOpen;
|
|
13278
|
+
// Update last interacted date based on mode and selected date
|
|
13279
|
+
const updateLastInteractedDate = (date) => {
|
|
13280
|
+
try {
|
|
13281
|
+
if (mode === CALENDAR_MODES.RANGE &&
|
|
13282
|
+
date &&
|
|
13283
|
+
typeof date === "object" &&
|
|
13284
|
+
"from" in date) {
|
|
13285
|
+
const rangeValue = date;
|
|
13286
|
+
if (rangeValue.to) {
|
|
13287
|
+
setLastInteractedDate(rangeValue.to);
|
|
13288
|
+
}
|
|
13289
|
+
else if (rangeValue.from) {
|
|
13290
|
+
setLastInteractedDate(rangeValue.from);
|
|
13291
|
+
}
|
|
13292
|
+
}
|
|
13293
|
+
else if (mode === CALENDAR_MODES.SINGLE && date instanceof Date) {
|
|
13294
|
+
setLastInteractedDate(date);
|
|
13295
|
+
}
|
|
13296
|
+
else if (mode === CALENDAR_MODES.MULTIPLE &&
|
|
13297
|
+
Array.isArray(date) &&
|
|
13298
|
+
date.length > 0) {
|
|
13299
|
+
setLastInteractedDate(date[date.length - 1]);
|
|
13300
|
+
}
|
|
13232
13301
|
}
|
|
13233
|
-
|
|
13234
|
-
|
|
13235
|
-
onChange?.(value);
|
|
13302
|
+
catch (error) {
|
|
13303
|
+
console.warn("Error updating last interacted date:", error);
|
|
13236
13304
|
}
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13305
|
+
};
|
|
13306
|
+
const handleSelect = (date) => {
|
|
13307
|
+
updateLastInteractedDate(date);
|
|
13308
|
+
// Always call onChange to notify parent
|
|
13309
|
+
onChange?.(date);
|
|
13310
|
+
// Only update internal state in uncontrolled mode
|
|
13311
|
+
if (!isControlled) {
|
|
13312
|
+
setInternalValue(date);
|
|
13240
13313
|
}
|
|
13241
|
-
|
|
13242
|
-
if (isInstantClose && mode ===
|
|
13314
|
+
// Close popover if instant close is enabled (single mode only)
|
|
13315
|
+
if (isInstantClose && mode === CALENDAR_MODES.SINGLE) {
|
|
13243
13316
|
handleOpenChange(false);
|
|
13244
13317
|
}
|
|
13245
13318
|
};
|
|
13319
|
+
// Calculate disabled dates based on minDate, maxDate, range validation, and custom disabled dates
|
|
13320
|
+
// Using react-day-picker's native Matcher format for better performance
|
|
13321
|
+
const isCalendarDisabled = React.useMemo(() => {
|
|
13322
|
+
const matchers = [];
|
|
13323
|
+
// Add minDate constraint using native 'before' matcher
|
|
13324
|
+
if (minDate) {
|
|
13325
|
+
matchers.push({ before: minDate });
|
|
13326
|
+
}
|
|
13327
|
+
// Add maxDate constraint using native 'after' matcher
|
|
13328
|
+
if (maxDate) {
|
|
13329
|
+
matchers.push({ after: maxDate });
|
|
13330
|
+
}
|
|
13331
|
+
// Range mode: when only 'from' is selected, disable all dates before it
|
|
13332
|
+
if (mode === CALENDAR_MODES.RANGE &&
|
|
13333
|
+
displayValue &&
|
|
13334
|
+
typeof displayValue === "object" &&
|
|
13335
|
+
"from" in displayValue) {
|
|
13336
|
+
const rangeValue = displayValue;
|
|
13337
|
+
if (rangeValue.from && !rangeValue.to) {
|
|
13338
|
+
matchers.push({ before: rangeValue.from });
|
|
13339
|
+
}
|
|
13340
|
+
}
|
|
13341
|
+
// Add custom disabled dates
|
|
13342
|
+
if (disabledDates) {
|
|
13343
|
+
if (Array.isArray(disabledDates)) {
|
|
13344
|
+
matchers.push(...disabledDates);
|
|
13345
|
+
}
|
|
13346
|
+
else {
|
|
13347
|
+
matchers.push(disabledDates);
|
|
13348
|
+
}
|
|
13349
|
+
}
|
|
13350
|
+
// Return combined matchers (react-day-picker handles OR logic automatically)
|
|
13351
|
+
return matchers.length > 0 ? matchers : undefined;
|
|
13352
|
+
}, [minDate, maxDate, mode, displayValue, disabledDates]);
|
|
13246
13353
|
const handleOpenChange = (open) => {
|
|
13247
|
-
|
|
13354
|
+
// Update internal state only in uncontrolled mode
|
|
13355
|
+
if (openProp === undefined) {
|
|
13356
|
+
setInternalOpen(open);
|
|
13357
|
+
}
|
|
13358
|
+
// Always notify parent
|
|
13248
13359
|
onOpenChangeProp?.(open);
|
|
13249
13360
|
};
|
|
13361
|
+
// Calculate default month based on current value
|
|
13362
|
+
const getDefaultMonth = () => {
|
|
13363
|
+
try {
|
|
13364
|
+
// For range mode, prioritize lastInteractedDate if available
|
|
13365
|
+
if (mode === CALENDAR_MODES.RANGE && lastInteractedDate) {
|
|
13366
|
+
return lastInteractedDate;
|
|
13367
|
+
}
|
|
13368
|
+
if (!displayValue) {
|
|
13369
|
+
return undefined; // Use today's date as default when no value
|
|
13370
|
+
}
|
|
13371
|
+
if (mode === CALENDAR_MODES.SINGLE) {
|
|
13372
|
+
return displayValue;
|
|
13373
|
+
}
|
|
13374
|
+
else if (mode === CALENDAR_MODES.MULTIPLE) {
|
|
13375
|
+
const dates = displayValue;
|
|
13376
|
+
if (dates.length > 0) {
|
|
13377
|
+
// Use the most recent date in the array
|
|
13378
|
+
return dates[dates.length - 1];
|
|
13379
|
+
}
|
|
13380
|
+
}
|
|
13381
|
+
else if (mode === CALENDAR_MODES.RANGE) {
|
|
13382
|
+
const range = displayValue;
|
|
13383
|
+
// Use the most recent date (to) if available, otherwise use from
|
|
13384
|
+
if (range.to) {
|
|
13385
|
+
return range.to;
|
|
13386
|
+
}
|
|
13387
|
+
else if (range.from) {
|
|
13388
|
+
return range.from;
|
|
13389
|
+
}
|
|
13390
|
+
}
|
|
13391
|
+
return undefined;
|
|
13392
|
+
}
|
|
13393
|
+
catch (error) {
|
|
13394
|
+
console.warn("Error calculating default month:", error);
|
|
13395
|
+
return undefined;
|
|
13396
|
+
}
|
|
13397
|
+
};
|
|
13398
|
+
// Memoize default month calculation for performance
|
|
13399
|
+
const defaultMonth = React.useMemo(() => getDefaultMonth(), [mode, lastInteractedDate, displayValue]);
|
|
13250
13400
|
const getDateToFormatString = (date) => {
|
|
13251
13401
|
if (date instanceof Date) {
|
|
13252
13402
|
return dayjs(date).format(format);
|
|
@@ -13254,15 +13404,17 @@ const DatePicker = ({ size = "regular", placeholder = "Pick a date", format = "Y
|
|
|
13254
13404
|
else if (Array.isArray(date)) {
|
|
13255
13405
|
return date.map((d) => dayjs(d).format(format)).join(", ");
|
|
13256
13406
|
}
|
|
13257
|
-
else if (date &&
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
return
|
|
13407
|
+
else if (date && typeof date === "object" && "from" in date) {
|
|
13408
|
+
if (date.to) {
|
|
13409
|
+
return `${dayjs(date.from).format(format)} - ${dayjs(date.to).format(format)}`;
|
|
13410
|
+
}
|
|
13411
|
+
return dayjs(date.from).format(format);
|
|
13262
13412
|
}
|
|
13263
13413
|
return placeholder ?? "";
|
|
13264
13414
|
};
|
|
13265
|
-
return (jsxRuntime.jsxs(Root2$2, { open:
|
|
13415
|
+
return (jsxRuntime.jsxs(Root2$2, { open: displayOpen, onOpenChange: handleOpenChange, children: [jsxRuntime.jsx(Trigger$2, { asChild: true, children: jsxRuntime.jsx(Button, { size: size, fullWidth: true, variant: "outline", leftIcon: jsxRuntime.jsx(Calendar$1, { size: 20 }), className: "justify-start", "aria-selected": displayOpen, "aria-label": `Date picker, ${getDateToFormatString(displayValue) || placeholder}`, disabled: disabled, stateContainerClassName: displayOpen
|
|
13416
|
+
? "group-aria-selected/state:bg-fill-default"
|
|
13417
|
+
: undefined, children: getDateToFormatString(displayValue) }) }), jsxRuntime.jsx(Content2$2, { sideOffset: 10, align: "start", className: cn("z-10", popoverContentClassName), ...rest, children: mode === CALENDAR_MODES.SINGLE ? (jsxRuntime.jsx(Calendar, { mode: "single", ...rest, selected: displayValue, onSelect: handleSelect, disabled: isCalendarDisabled, defaultMonth: defaultMonth })) : mode === CALENDAR_MODES.MULTIPLE ? (jsxRuntime.jsx(Calendar, { mode: "multiple", ...rest, selected: Array.isArray(displayValue) ? displayValue : [], onSelect: handleSelect, disabled: isCalendarDisabled, defaultMonth: defaultMonth })) : (jsxRuntime.jsx(Calendar, { mode: "range", ...rest, selected: displayValue, onSelect: handleSelect, disabled: isCalendarDisabled, defaultMonth: defaultMonth })) })] }));
|
|
13266
13418
|
};
|
|
13267
13419
|
|
|
13268
13420
|
const ContextMenu = Root2$3;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Popover } from "radix-ui";
|
|
2
|
+
import { DateRange, Matcher } from "react-day-picker";
|
|
2
3
|
import { CalendarProps } from "../calendar";
|
|
3
|
-
import { DateRange } from "react-day-picker";
|
|
4
4
|
type AllDatePickerTypes = Date | undefined | DateRange | Date[];
|
|
5
5
|
interface DatePicker {
|
|
6
6
|
size: "regular" | "large";
|
|
@@ -11,7 +11,21 @@ interface DatePicker {
|
|
|
11
11
|
isInstantClose?: boolean;
|
|
12
12
|
disabled?: boolean;
|
|
13
13
|
popoverContentClassName?: string;
|
|
14
|
+
minDate?: Date;
|
|
15
|
+
maxDate?: Date;
|
|
16
|
+
/**
|
|
17
|
+
* Custom disabled dates matcher.
|
|
18
|
+
* Note: For optimal performance, memoize this prop in the parent component
|
|
19
|
+
* to avoid unnecessary recalculations.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const disabledDates = useMemo(() => [
|
|
23
|
+
* new Date(2025, 0, 15),
|
|
24
|
+
* { from: new Date(2025, 1, 10), to: new Date(2025, 1, 15) }
|
|
25
|
+
* ], []);
|
|
26
|
+
*/
|
|
27
|
+
disabledDates?: Matcher | Matcher[];
|
|
14
28
|
}
|
|
15
|
-
export type DatePickerProps = DatePicker & CalendarProps & Popover.PopoverProps & Omit<Popover.PopoverContentProps, "className">;
|
|
16
|
-
export declare const DatePicker: ({ size, placeholder, format, value, mode, onChange, isInstantClose, open: openProp, onOpenChange: onOpenChangeProp, disabled, popoverContentClassName, ...rest }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export type DatePickerProps = DatePicker & Omit<CalendarProps, "disabled" | "selected" | "onSelect"> & Popover.PopoverProps & Omit<Popover.PopoverContentProps, "className">;
|
|
30
|
+
export declare const DatePicker: ({ size, placeholder, format, value, mode, onChange, isInstantClose, open: openProp, onOpenChange: onOpenChangeProp, disabled, popoverContentClassName, minDate, maxDate, disabledDates, ...rest }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
31
|
export {};
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { Button } from "./button";
|
|
1
|
+
export { Button, ButtonTextDim } from "./button";
|
|
2
2
|
export { BUTTON_SIZES, BUTTON_VARIANTS } from "./button/types";
|
|
3
3
|
export type { ButtonSize, ButtonVariant } from "./button/types";
|
|
4
4
|
export { Card, CardBody, CardContent, CardFooter, CardHeader } from "./card";
|
|
5
5
|
export { Input } from "./input";
|
|
6
6
|
export { INPUT_SIZES, INPUT_VARIANTS } from "./input/types";
|
|
7
7
|
export type { InputSize, InputVariant } from "./input/types";
|
|
8
|
+
export { NotifyItem } from "./notify-item";
|
|
8
9
|
export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "./pagination";
|
|
9
10
|
export { StateColorContainer } from "./state-color-container";
|
|
10
11
|
export type { StateGroupName } from "./state-color-container/types";
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,24 +3,6 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
|
|
6
|
-
const BUTTON_SIZES = {
|
|
7
|
-
REGULAR: "regular",
|
|
8
|
-
SMALL: "small",
|
|
9
|
-
LARGE: "large",
|
|
10
|
-
};
|
|
11
|
-
const BUTTON_VARIANTS = {
|
|
12
|
-
ACCENT: "accent",
|
|
13
|
-
OUTLINE: "outline",
|
|
14
|
-
OUTLINE_TO_ACCENT: "outline_to_accent",
|
|
15
|
-
GHOST: "ghost",
|
|
16
|
-
THUMBNAIL_GHOST: "thumbnail_ghost",
|
|
17
|
-
GHOST_TO_ACCENT: "ghost_to_accent",
|
|
18
|
-
SUBTLE_FILLED: "subtle_filled",
|
|
19
|
-
OUTLINE_ACCENT: "outline_accent",
|
|
20
|
-
GHOST_ACCENT: "ghost_accent",
|
|
21
|
-
GHOST_DIM: "ghost_dim",
|
|
22
|
-
};
|
|
23
|
-
|
|
24
6
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
25
7
|
|
|
26
8
|
const CLASS_PART_SEPARATOR = '-';
|
|
@@ -3353,6 +3335,25 @@ const StateColorContainer = ({ groupName = "state", isInverted, className, }) =>
|
|
|
3353
3335
|
return (jsxRuntime.jsx("div", { className: cn("absolute left-0 top-0 right-0 bottom-0 inset-0 pointer-events-none z-0 rounded-[inherit]", actionClass, className) }));
|
|
3354
3336
|
};
|
|
3355
3337
|
|
|
3338
|
+
const BUTTON_SIZES = {
|
|
3339
|
+
REGULAR: "regular",
|
|
3340
|
+
SMALL: "small",
|
|
3341
|
+
LARGE: "large",
|
|
3342
|
+
};
|
|
3343
|
+
const BUTTON_VARIANTS = {
|
|
3344
|
+
ACCENT: "accent",
|
|
3345
|
+
OUTLINE: "outline",
|
|
3346
|
+
OUTLINE_TO_ACCENT: "outline_to_accent",
|
|
3347
|
+
GHOST: "ghost",
|
|
3348
|
+
THUMBNAIL_GHOST: "thumbnail_ghost",
|
|
3349
|
+
GHOST_TO_ACCENT: "ghost_to_accent",
|
|
3350
|
+
SUBTLE_FILLED: "subtle_filled",
|
|
3351
|
+
OUTLINE_ACCENT: "outline_accent",
|
|
3352
|
+
GHOST_ACCENT: "ghost_accent",
|
|
3353
|
+
GHOST_DIM: "ghost_dim",
|
|
3354
|
+
TEXT_DIM: "text_dim",
|
|
3355
|
+
};
|
|
3356
|
+
|
|
3356
3357
|
/**
|
|
3357
3358
|
* 다양한 스타일과 속성을 지원하는 버튼 컴포넌트입니다.<br/>
|
|
3358
3359
|
* 사용자는 버튼의 변형(variant), 크기(size), 전체 너비(fullWidth), 로딩 상태(isLoading), 아이콘(leftIcon, rightIcon) 등을 지정할 수 있습니다.<br/>
|
|
@@ -3369,6 +3370,13 @@ const StateColorContainer = ({ groupName = "state", isInverted, className, }) =>
|
|
|
3369
3370
|
*/
|
|
3370
3371
|
const Button = react.forwardRef(({ variant = "accent", size = "regular", fullWidth = false, isLoading = false, leftIcon, rightIcon, children, disabled, className, stateContainerClassName, ...rest }, ref) => {
|
|
3371
3372
|
const getClassName = (size, variant) => {
|
|
3373
|
+
// text_dim variant는 size에 관계없이 고정된 스타일 사용
|
|
3374
|
+
if (variant === BUTTON_VARIANTS.TEXT_DIM) {
|
|
3375
|
+
return [
|
|
3376
|
+
"h-auto py-0.5 px-0 text-body leading-body-compact gap-1.5",
|
|
3377
|
+
"bg-page-l-null text-comp-mono-subtle-default hover:text-comp-mono-default aria-selected:text-comp-mono-default disabled:bg-page-l-null disabled:text-comp-disabled disabled:hover:text-comp-disabled",
|
|
3378
|
+
];
|
|
3379
|
+
}
|
|
3372
3380
|
const sizeClassName = {
|
|
3373
3381
|
small: "h-7 py-0 px-1 text-label leading-label-compact gap-1",
|
|
3374
3382
|
regular: "h-9 py-0 px-2 text-body leading-body-compact gap-1.5",
|
|
@@ -3385,6 +3393,7 @@ const Button = react.forwardRef(({ variant = "accent", size = "regular", fullWid
|
|
|
3385
3393
|
outline_accent: "bg-page-l-null disabled:bg-page-l-null text-comp-accent-default disabled:text-comp-disabled border border-border-accent-bound disabled:border-pure-transparent aria-selected:border-border-accent-selected",
|
|
3386
3394
|
ghost_accent: "bg-page-l-null disabled:bg-page-l-null text-comp-accent-default disabled:text-comp-disabled",
|
|
3387
3395
|
ghost_dim: "bg-page-l-null disabled:bg-page-l-null text-comp-mono-subtle-default disabled:text-comp-disabled aria-selected:text-comp-mono-default",
|
|
3396
|
+
text_dim: "", // 위에서 처리되므로 여기서는 빈 문자열
|
|
3388
3397
|
}[variant];
|
|
3389
3398
|
return [sizeClassName, variantClassName];
|
|
3390
3399
|
};
|
|
@@ -3402,13 +3411,28 @@ const Button = react.forwardRef(({ variant = "accent", size = "regular", fullWid
|
|
|
3402
3411
|
return "size-5";
|
|
3403
3412
|
return "size-6"; // 기본값은 regular 크기
|
|
3404
3413
|
};
|
|
3405
|
-
return (jsxRuntime.jsxs("button", { ref: ref, disabled: disabled ?? isLoading, className: cn("flex group/state items-center justify-center relative box-border m-0 border-transparent outline-none cursor-pointer select-none align-middle appearance-none text-center transition-normal font-medium w-auto rounded-md overflow-hidden pointer-events-auto disabled:pointer-events-none disabled:cursor-not-allowed", ...getClassName(size, variant), fullWidth && "w-full", className), ...rest, children: [jsxRuntime.jsx(StateColorContainer, { isInverted: variant === BUTTON_VARIANTS.ACCENT, className: stateContainerClassName }), isLoading && (jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: cn("lucide lucide-loader-circle-icon lucide-loader-circle absolute animate-spin", size === BUTTON_SIZES.SMALL &&
|
|
3414
|
+
return (jsxRuntime.jsxs("button", { ref: ref, disabled: disabled ?? isLoading, className: cn("flex group/state items-center justify-center relative box-border m-0 border-transparent outline-none cursor-pointer select-none align-middle appearance-none text-center transition-normal font-medium w-auto rounded-md overflow-hidden pointer-events-auto disabled:pointer-events-none disabled:cursor-not-allowed", ...getClassName(size, variant), fullWidth && "w-full", className), ...rest, children: [variant !== BUTTON_VARIANTS.TEXT_DIM && (jsxRuntime.jsx(StateColorContainer, { isInverted: variant === BUTTON_VARIANTS.ACCENT, className: stateContainerClassName })), isLoading && (jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: cn("lucide lucide-loader-circle-icon lucide-loader-circle absolute animate-spin", size === BUTTON_SIZES.SMALL &&
|
|
3406
3415
|
"size-4 top-[calc(50%-8px)] left-[calc(50%-8px)]", size === BUTTON_SIZES.REGULAR &&
|
|
3407
3416
|
"size-5 top-[calc(50%-10px)] left-[calc(50%-10px)]", size === BUTTON_SIZES.LARGE &&
|
|
3408
3417
|
"size-6 top-[calc(50%-12px)] left-[calc(50%-12px)]"), children: jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) })), leftIcon && (jsxRuntime.jsx("div", { className: cn("flex items-center justify-center relative", variant === BUTTON_VARIANTS.THUMBNAIL_GHOST &&
|
|
3409
3418
|
"aspect-square [&_img]:rounded-sm", getThumbnailSize(variant, size)), children: leftIcon })), children && (jsxRuntime.jsx("div", { className: "flex-1", style: { visibility: isLoading ? "hidden" : "visible" }, children: children })), rightIcon && (jsxRuntime.jsx("div", { className: cn("flex items-center justify-center relative", getThumbnailSize(variant, size)), children: rightIcon }))] }));
|
|
3410
3419
|
});
|
|
3411
3420
|
Button.displayName = "Button";
|
|
3421
|
+
/**
|
|
3422
|
+
* Text Dim 스타일의 버튼 컴포넌트입니다.<br/>
|
|
3423
|
+
* 텍스트 중심의 보조 액션(secondary / subtle action)에 적합한 low-emphasis 스타일을 제공합니다.<br/>
|
|
3424
|
+
* 기본적으로 낮은 명도의 텍스트를 사용하며, hover 시 명도가 상승하고 selected 시 accent 색상으로 강조됩니다.<br/>
|
|
3425
|
+
* <br/>
|
|
3426
|
+
* ### 사용 예시
|
|
3427
|
+
* ```tsx
|
|
3428
|
+
* <ButtonTextDim>자세히 보기</ButtonTextDim>
|
|
3429
|
+
* <ButtonTextDim aria-selected="true">선택됨</ButtonTextDim>
|
|
3430
|
+
* ```
|
|
3431
|
+
*/
|
|
3432
|
+
const ButtonTextDim = react.forwardRef((props, ref) => {
|
|
3433
|
+
return jsxRuntime.jsx(Button, { ref: ref, variant: "text_dim", ...props });
|
|
3434
|
+
});
|
|
3435
|
+
ButtonTextDim.displayName = "ButtonTextDim";
|
|
3412
3436
|
|
|
3413
3437
|
/**
|
|
3414
3438
|
* 카드 컴포넌트는 콘텐츠를 그룹화하고 시각적으로 구분하는 데 사용됩니다.<br/>
|
|
@@ -3739,6 +3763,28 @@ const Input = react.forwardRef(({ size = "regular", variant = "outlined", leftIc
|
|
|
3739
3763
|
});
|
|
3740
3764
|
Input.displayName = "Input";
|
|
3741
3765
|
|
|
3766
|
+
const NOTIFY_ITEM_VARIANTS = {
|
|
3767
|
+
GHOST: "ghost",
|
|
3768
|
+
DYNAMIC_ACCENT: "dynamicAccent",
|
|
3769
|
+
};
|
|
3770
|
+
const NotifyItem = react.forwardRef(({ title, description, timestamp, icon, actionIcon, variant = NOTIFY_ITEM_VARIANTS.GHOST, unread = false, disabled, className, ...rest }, ref) => {
|
|
3771
|
+
return (jsxRuntime.jsxs("div", { ref: ref, "data-unread": unread, "data-disabled": disabled, className: cn("relative group/state inline-flex items-center min-h-9 w-full p-1.5 rounded cursor-pointer border border-transparent", variant === NOTIFY_ITEM_VARIANTS.GHOST && [
|
|
3772
|
+
!disabled && "bg-page-l-null *:text-comp-mono-subtle-default",
|
|
3773
|
+
"data-[unread=true]:border-border-bound data-[unread=true]:bg-page-l3 data-[unread=true]:*:text-comp-mono-default",
|
|
3774
|
+
], variant === NOTIFY_ITEM_VARIANTS.DYNAMIC_ACCENT && [
|
|
3775
|
+
"bg-page-l4 *:text-comp-mono-default",
|
|
3776
|
+
"data-[unread=true]:bg-page-accent-l0 data-[unread=true]:*:text-comp-accent-default",
|
|
3777
|
+
], disabled && [
|
|
3778
|
+
"cursor-not-allowed pointer-events-none bg-page-l-null *:text-comp-disabled",
|
|
3779
|
+
], className), ...rest, children: [icon && (jsxRuntime.jsx("div", { className: "size-9 flex justify-center items-center flex-shrink-0", children: icon })), jsxRuntime.jsxs("div", { className: "flex-1 self-stretch px-1.5 inline-flex flex-col justify-center items-start gap-1 min-w-0 text-inherit", children: [jsxRuntime.jsx(Text, { variant: "medBodyMedCompact", className: "text-inherit", children: title }), jsxRuntime.jsx(Text, { variant: "regularLabelCompact", className: cn("text-inherit", variant === NOTIFY_ITEM_VARIANTS.GHOST &&
|
|
3780
|
+
"group-data-[unread=true]/state:text-comp-mono-subtle-default", variant === NOTIFY_ITEM_VARIANTS.DYNAMIC_ACCENT &&
|
|
3781
|
+
!disabled &&
|
|
3782
|
+
"group-data-[unread=false]/state:text-comp-mono-subtle-default"), children: description })] }), timestamp && (jsxRuntime.jsx("div", { className: "h-9 flex justify-center items-center flex-shrink-0", children: jsxRuntime.jsx(Text, { variant: "medLabelMedCompact", className: cn("text-inherit", variant === NOTIFY_ITEM_VARIANTS.DYNAMIC_ACCENT &&
|
|
3783
|
+
!disabled &&
|
|
3784
|
+
"group-data-[unread=false]/state:text-comp-mono-subtle-default"), children: timestamp }) })), actionIcon && (jsxRuntime.jsx("div", { className: "size-9 flex justify-center items-center flex-shrink-0", children: actionIcon })), jsxRuntime.jsx(StateColorContainer, { groupName: "state", isInverted: variant === NOTIFY_ITEM_VARIANTS.DYNAMIC_ACCENT })] }));
|
|
3785
|
+
});
|
|
3786
|
+
NotifyItem.displayName = "NotifyItem";
|
|
3787
|
+
|
|
3742
3788
|
/**
|
|
3743
3789
|
* @license lucide-react v0.513.0 - ISC
|
|
3744
3790
|
*
|
|
@@ -3975,6 +4021,7 @@ TextArea.displayName = "TextArea";
|
|
|
3975
4021
|
exports.BUTTON_SIZES = BUTTON_SIZES;
|
|
3976
4022
|
exports.BUTTON_VARIANTS = BUTTON_VARIANTS;
|
|
3977
4023
|
exports.Button = Button;
|
|
4024
|
+
exports.ButtonTextDim = ButtonTextDim;
|
|
3978
4025
|
exports.Card = Card;
|
|
3979
4026
|
exports.CardBody = CardBody;
|
|
3980
4027
|
exports.CardContent = CardContent;
|
|
@@ -3984,6 +4031,7 @@ exports.FONT_WEIGHTS = FONT_WEIGHTS;
|
|
|
3984
4031
|
exports.INPUT_SIZES = INPUT_SIZES;
|
|
3985
4032
|
exports.INPUT_VARIANTS = INPUT_VARIANTS;
|
|
3986
4033
|
exports.Input = Input;
|
|
4034
|
+
exports.NotifyItem = NotifyItem;
|
|
3987
4035
|
exports.Pagination = Pagination;
|
|
3988
4036
|
exports.PaginationContent = PaginationContent;
|
|
3989
4037
|
exports.PaginationEllipsis = PaginationEllipsis;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface NotifyItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
2
|
+
title: string;
|
|
3
|
+
description: string;
|
|
4
|
+
timestamp?: string;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
actionIcon?: React.ReactNode;
|
|
7
|
+
variant?: "ghost" | "dynamicAccent";
|
|
8
|
+
unread?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const NotifyItem: import("react").ForwardRefExoticComponent<NotifyItemProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
12
|
+
export {};
|
package/dist/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as React$1 from 'react';
|
|
|
2
2
|
import React__default, { ReactNode, FC, Ref } from 'react';
|
|
3
3
|
import { RadioGroup as RadioGroup$1, Checkbox as Checkbox$1, Dialog as Dialog$1, Select as Select$1, Tooltip as Tooltip$1, Popover, ContextMenu as ContextMenu$1, Switch as Switch$1 } from 'radix-ui';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
-
import { DayPicker, DateRange } from 'react-day-picker';
|
|
5
|
+
import { DayPicker, DateRange, Matcher } from 'react-day-picker';
|
|
6
6
|
|
|
7
7
|
declare const RADIO_GROUP_ORIENTAIONS: {
|
|
8
8
|
readonly HORIZONTAL: "horizontal";
|
|
@@ -365,7 +365,7 @@ type CalendarProps = React$1.ComponentProps<typeof DayPicker>;
|
|
|
365
365
|
declare const Calendar: ({ className, classNames, showOutsideDays, ...props }: CalendarProps) => react_jsx_runtime.JSX.Element;
|
|
366
366
|
|
|
367
367
|
type AllDatePickerTypes = Date | undefined | DateRange | Date[];
|
|
368
|
-
type DatePickerProps = DatePicker & CalendarProps & Popover.PopoverProps & Omit<Popover.PopoverContentProps, "className">;
|
|
368
|
+
type DatePickerProps = DatePicker & Omit<CalendarProps, "disabled" | "selected" | "onSelect"> & Popover.PopoverProps & Omit<Popover.PopoverContentProps, "className">;
|
|
369
369
|
interface DatePicker {
|
|
370
370
|
size: "regular" | "large";
|
|
371
371
|
placeholder?: string;
|
|
@@ -375,8 +375,22 @@ interface DatePicker {
|
|
|
375
375
|
isInstantClose?: boolean;
|
|
376
376
|
disabled?: boolean;
|
|
377
377
|
popoverContentClassName?: string;
|
|
378
|
+
minDate?: Date;
|
|
379
|
+
maxDate?: Date;
|
|
380
|
+
/**
|
|
381
|
+
* Custom disabled dates matcher.
|
|
382
|
+
* Note: For optimal performance, memoize this prop in the parent component
|
|
383
|
+
* to avoid unnecessary recalculations.
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* const disabledDates = useMemo(() => [
|
|
387
|
+
* new Date(2025, 0, 15),
|
|
388
|
+
* { from: new Date(2025, 1, 10), to: new Date(2025, 1, 15) }
|
|
389
|
+
* ], []);
|
|
390
|
+
*/
|
|
391
|
+
disabledDates?: Matcher | Matcher[];
|
|
378
392
|
}
|
|
379
|
-
declare const DatePicker: ({ size, placeholder, format, value, mode, onChange, isInstantClose, open: openProp, onOpenChange: onOpenChangeProp, disabled, popoverContentClassName, ...rest }: DatePickerProps) => react_jsx_runtime.JSX.Element;
|
|
393
|
+
declare const DatePicker: ({ size, placeholder, format, value, mode, onChange, isInstantClose, open: openProp, onOpenChange: onOpenChangeProp, disabled, popoverContentClassName, minDate, maxDate, disabledDates, ...rest }: DatePickerProps) => react_jsx_runtime.JSX.Element;
|
|
380
394
|
|
|
381
395
|
declare const ContextMenu: FC<ContextMenu$1.ContextMenuProps>;
|
|
382
396
|
declare const ContextMenuTrigger: FC<ContextMenu$1.ContextMenuTriggerProps>;
|