@dotss/ui 1.3.1 → 1.4.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/Button/Button.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const M=require("@emotion/react/jsx-runtime"),b=require("react"),z=require("../hooks/useCheckHoverPossible/useCheckHoverPossible.cjs"),W=require("../utils/getIconLabel/getIconLabel.cjs"),j=require("@emotion/styled"),a=require("../utils/getContrastingTextColor/getContrastingTextColor.cjs"),m=l=>l&&l.__esModule?l:{default:l},_=m(j),q=_.default.button`
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const a=require("@emotion/react/jsx-runtime"),M=require("react"),j=require("../Box/Box.cjs"),N=require("../CircularProgressIndicator/CircularProgressIndicator.cjs"),E=require("../hooks/useCheckHoverPossible/useCheckHoverPossible.cjs"),T=require("../utils/getIconLabel/getIconLabel.cjs"),F=require("@emotion/styled"),s=require("../utils/getContrastingTextColor/getContrastingTextColor.cjs"),V=l=>l&&l.__esModule?l:{default:l},G=V(F),J=G.default.button`
2
2
  display: inline-flex;
3
3
  align-items: center;
4
4
  justify-content: center;
@@ -7,18 +7,19 @@
7
7
  color: inherit;
8
8
  }
9
9
 
10
- ${({theme:{palette:{brand:l,grey:e}},variant:t,color:o})=>{let p={backgroundColor:l.primary.main,color:a.default(l.primary.main,[e.white,e[100]])};return t==="filled"&&o==="secondary"&&(p={backgroundColor:l.secondary,color:a.default(l.secondary,[e.white,e[100]])}),t==="filled"&&o==="tertiary"&&(p={backgroundColor:l.tertiary,color:a.default(l.tertiary,[e.white,e[100]])}),t==="outlined"&&(p={borderColor:e[50],backgroundColor:e.white,color:a.default(e.white,[e.white,e[100]])}),t==="text"&&o==="primary"&&(p={backgroundColor:"transparent",color:a.default("transparent",[e.white,e[100]])}),t==="text"&&o==="secondary"&&(p={backgroundColor:"transparent",color:e[70]}),p}};
10
+ ${({theme:{palette:{brand:l,grey:e}},variant:t,color:u})=>{let p={backgroundColor:l.primary.main,color:s.default(l.primary.main,[e.white,e[100]])};return t==="filled"&&u==="secondary"&&(p={backgroundColor:l.secondary,color:s.default(l.secondary,[e.white,e[100]])}),t==="filled"&&u==="tertiary"&&(p={backgroundColor:l.tertiary,color:s.default(l.tertiary,[e.white,e[100]])}),t==="outlined"&&(p={borderColor:e[50],backgroundColor:e.white,color:s.default(e.white,[e.white,e[100]])}),t==="text"&&u==="primary"&&(p={backgroundColor:"transparent",color:s.default("transparent",[e.white,e[100]])}),t==="text"&&u==="secondary"&&(p={backgroundColor:"transparent",color:e[70]}),p}};
11
11
 
12
- ${({theme:{spacing:l,typography:e},variant:t,size:o,startAdornment:p,endAdornment:r,iconOnly:f})=>{let u={gap:l.content(1),padding:10,borderRadius:8,fontSize:e.b4M.size,fontWeight:e.b4M.weight,lineHeight:e.b4M.lineHeight,letterSpacing:e.b4M.letterSpacing,"& svg":{width:20,height:20}};if(o==="2xLarge"){const{h0B:i}=e;let x="26px 24px";p&&(x=t==="text"?"26px 16px 26px 12px":"26px 36px 26px 24px"),r&&(x=t==="text"?"26px 12px 26px 16px":"26px 24px 26px 36px"),p&&r&&(x=t==="text"?"26px 12px":"26px 24px"),f&&(x="26px 25px"),u={gap:l.content(3),maxHeight:100,padding:x,borderRadius:20,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:48,height:48}}}if(o==="xLarge"){const{h4B:i}=e;let x="16px 12px";p&&(x=t==="text"?"16px 8px 16px 4px":"16px 16px 16px 12px"),r&&(x=t==="text"?"16px 4px 16px 8px":"16px 12px 16px 16px"),p&&r&&(x=t==="text"?"16px 4px":"16px 12px"),f&&(x="16px 15px"),u={gap:l.content(2),maxHeight:56,padding:x,borderRadius:12,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:24,height:24}}}if(o==="large"){const{b2M:i}=e;let x="12px 8px";p&&(x=t==="text"?"12px 8px 12px 4px":"12px 12px 12px 8px"),r&&(x=t==="text"?"12px 4px 12px 8px":"12px 8px 12px 12px"),p&&r&&(x=t==="text"?"12px 4px":"12px 8px"),f&&(x="12px 11px"),u={gap:6,maxHeight:48,padding:x,borderRadius:10,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:24,height:24}}}if(o==="medium"){const{b4M:i}=e;let x="10px 8px";p&&(x=t==="text"?"10px 8px 10px 4px":"10px 10px 10px 8px"),r&&(x=t==="text"?"10px 4px 10px 8px":"10px 8px 10px 10px"),p&&r&&(x=t==="text"?"10px 4px":"10px 8px"),f&&(x="10px 9px"),u={gap:l.content(1),maxHeight:40,padding:x,borderRadius:8,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:20,height:20}}}if(o==="small"){const{c3M:i}=e;let x="8px 6px";p&&(x=t==="text"?"8px 8px 8px 4px":"8px 8px 8px 6px"),r&&(x=t==="text"?"8px 4px 8px 8px":"8px 6px 8px 8px"),p&&r&&(x=t==="text"?"8px 6px":"8px 4px"),f&&(x="8px 7px"),u={gap:l.content(1),maxHeight:32,padding:x,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}}if(o==="xSmall"){const{c3M:i}=e;let x="4px 6px";p&&(x=t==="text"?"4px 8px 4px 4px":"4px 8px 4px 6px"),r&&(x=t==="text"?"4px 4px 4px 8px":"4px 6px 4px 8px"),p&&r&&(x=t==="text"?"4px":"4px 6px"),f&&(x="4px 3px"),f?u={gap:l.content(1),maxHeight:24,width:24,height:24,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}:u={gap:l.content(1),maxHeight:24,padding:x,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}}return t==="text"&&o==="xLarge"&&(u={...u,borderWidth:1.5}),u}};
12
+ ${({theme:{spacing:l,typography:e},variant:t,size:u,startAdornment:p,endAdornment:o,iconOnly:f})=>{let r={gap:l.content(1),padding:10,borderRadius:8,fontSize:e.b4M.size,fontWeight:e.b4M.weight,lineHeight:e.b4M.lineHeight,letterSpacing:e.b4M.letterSpacing,"& svg":{width:20,height:20}};if(u==="2xLarge"){const{h0B:i}=e;let x="26px 24px";p&&(x=t==="text"?"26px 16px 26px 12px":"26px 36px 26px 24px"),o&&(x=t==="text"?"26px 12px 26px 16px":"26px 24px 26px 36px"),p&&o&&(x=t==="text"?"26px 12px":"26px 24px"),f&&(x="26px 25px"),r={gap:l.content(3),maxHeight:100,padding:x,borderRadius:20,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:48,height:48}}}if(u==="xLarge"){const{h4B:i}=e;let x="16px 12px";p&&(x=t==="text"?"16px 8px 16px 4px":"16px 16px 16px 12px"),o&&(x=t==="text"?"16px 4px 16px 8px":"16px 12px 16px 16px"),p&&o&&(x=t==="text"?"16px 4px":"16px 12px"),f&&(x="16px 15px"),r={gap:l.content(2),maxHeight:56,padding:x,borderRadius:12,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:24,height:24}}}if(u==="large"){const{b2M:i}=e;let x="12px 8px";p&&(x=t==="text"?"12px 8px 12px 4px":"12px 12px 12px 8px"),o&&(x=t==="text"?"12px 4px 12px 8px":"12px 8px 12px 12px"),p&&o&&(x=t==="text"?"12px 4px":"12px 8px"),f&&(x="12px 11px"),r={gap:6,maxHeight:48,padding:x,borderRadius:10,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:24,height:24}}}if(u==="medium"){const{b4M:i}=e;let x="10px 8px";p&&(x=t==="text"?"10px 8px 10px 4px":"10px 10px 10px 8px"),o&&(x=t==="text"?"10px 4px 10px 8px":"10px 8px 10px 10px"),p&&o&&(x=t==="text"?"10px 4px":"10px 8px"),f&&(x="10px 9px"),r={gap:l.content(1),maxHeight:40,padding:x,borderRadius:8,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:20,height:20}}}if(u==="small"){const{c3M:i}=e;let x="8px 6px";p&&(x=t==="text"?"8px 8px 8px 4px":"8px 8px 8px 6px"),o&&(x=t==="text"?"8px 4px 8px 8px":"8px 6px 8px 8px"),p&&o&&(x=t==="text"?"8px 6px":"8px 4px"),f&&(x="8px 7px"),r={gap:l.content(1),maxHeight:32,padding:x,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}}if(u==="xSmall"){const{c3M:i}=e;let x="4px 6px";p&&(x=t==="text"?"4px 8px 4px 4px":"4px 8px 4px 6px"),o&&(x=t==="text"?"4px 4px 4px 8px":"4px 6px 4px 8px"),p&&o&&(x=t==="text"?"4px":"4px 6px"),f&&(x="4px 3px"),f?r={gap:l.content(1),maxHeight:24,width:24,height:24,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}:r={gap:l.content(1),maxHeight:24,padding:x,borderRadius:6,fontSize:i.size,fontWeight:i.weight,lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,"& svg":{width:16,height:16}}}return t==="text"&&u==="xLarge"&&(r={...r,borderWidth:1.5}),r}};
13
13
 
14
14
  ${({rounded:l})=>l?{}:{borderRadius:"unset"}}
15
15
 
16
- ${({theme:{palette:{brand:l,grey:e}},variant:t,color:o,isHoverPossible:p})=>{let r={'&:active:not([aria-disabled="true"])':{backgroundColor:l.primary.press},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:l.primary.press}}:{}};return t==="filled"&&o==="secondary"&&(r={'&:active:not([aria-disabled="true"])':{backgroundColor:e[100]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[100]}}:{}}),t==="filled"&&o==="tertiary"&&(r={'&:active:not([aria-disabled="true"])':{backgroundColor:e[70]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[70]}}:{}}),(t==="outlined"||t==="text")&&(r={'&:active:not([aria-disabled="true"])':{backgroundColor:e[10]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[10]}}:{}}),r}}
16
+ ${({theme:{palette:{brand:l,grey:e}},variant:t,color:u,isHoverPossible:p})=>{let o={'&:active:not([aria-disabled="true"])':{backgroundColor:l.primary.press},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:l.primary.press}}:{}};return t==="filled"&&u==="secondary"&&(o={'&:active:not([aria-disabled="true"])':{backgroundColor:e[100]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[100]}}:{}}),t==="filled"&&u==="tertiary"&&(o={'&:active:not([aria-disabled="true"])':{backgroundColor:e[70]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[70]}}:{}}),(t==="outlined"||t==="text")&&(o={'&:active:not([aria-disabled="true"])':{backgroundColor:e[10]},...p?{'&:hover:not([aria-disabled="true"])':{backgroundColor:e[10]}}:{}}),o}}
17
17
 
18
- &[aria-disabled="true"] {
18
+ &[aria-disabled="true"], &[aria-busy="true"] {
19
19
  cursor: not-allowed;
20
- ${({theme:{palette:{brand:l,grey:e}},variant:t,color:o})=>{let p={backgroundColor:l.primary.disable,color:a.default(l.primary.disable,[e[30],e.white])};return t==="filled"&&o==="secondary"&&(p={backgroundColor:e[10],color:a.default(e[10],[e[30],e.white])}),t==="outlined"&&(p={borderColor:e[30],backgroundColor:e[10],color:a.default(e[30],[e[30],e.white])}),t==="text"&&(p={color:a.default(e[30],[e[30],e.white])}),p}};
20
+
21
+ ${({theme:{palette:{brand:l,grey:e}},variant:t,color:u})=>{let p={backgroundColor:l.primary.disable,color:s.default(l.primary.disable,[e[30],e.white])};return t==="filled"&&u==="secondary"&&(p={backgroundColor:e[10],color:s.default(e[10],[e[30],e.white])}),t==="outlined"&&(p={borderColor:e[30],backgroundColor:e[10],color:s.default(e[30],[e[30],e.white])}),t==="text"&&(p={color:s.default(e[30],[e[30],e.white])}),p}};
21
22
  }
22
23
 
23
24
  ${({fullWidth:l})=>l?{width:"100%"}:null};
24
- `,$=b.forwardRef(function({tag:e="button",children:t,variant:o="filled",size:p="medium",color:r="primary",startAdornment:f,endAdornment:u,iconOnly:i,fullWidth:x,inlineCSS:n,rounded:w=!0,disabled:h,onClick:c,onKeyDown:s,...g},S){const{isHoverPossible:H}=z.default(),C=()=>{if(!i)return;if(g["aria-label"])return g["aria-label"];const d=f||u||t;if(b.isValidElement(d))return W.default(d.props.name)},k=d=>{h||c==null||c(d)},R=d=>{h||s==null||s(d)};return M.jsxs(q,{as:e,ref:S,variant:o,size:p,color:r,fullWidth:x,rounded:w,startAdornment:f,endAdornment:u,iconOnly:i,isHoverPossible:H,"aria-disabled":h,"aria-label":C(),onClick:k,onKeyDown:R,...g,css:n,children:[f,!i&&t,u]})});exports.default=$;
25
+ `,P=M.forwardRef(function({tag:e="button",children:t,variant:u="filled",size:p="medium",color:o="primary",startAdornment:f,endAdornment:r,iconOnly:i,fullWidth:x,inlineCSS:z,rounded:W=!0,disabled:w,onClick:S,onKeyDown:H,loading:c,loadingPosition:R,loadingIndicator:h,...C},q){const{isHoverPossible:m}=E.default(),_=()=>{if(!i)return;if(C["aria-label"])return C["aria-label"];const d=f||r||t;if(M.isValidElement(d))return T.default(d.props.name)},$=d=>{w||c||S==null||S(d)},B=d=>{w||c||H==null||H(d)},L=!!c,k=h?a.jsx(a.Fragment,{children:h}):a.jsx(N.default,{loop:!0});let g=f,b=i?null:t,n=r;return L&&(R?R==="start"?(g=a.jsx(j.default,{children:k}),n=h?null:r,b=i||h?null:t):(g=h?null:f,n=a.jsx(j.default,{children:k}),b=i||h?null:t):(g=null,n=null,b=i?null:k)),a.jsxs(J,{as:e,ref:q,type:e==="button"?"button":void 0,variant:u,size:p,color:o,fullWidth:x,rounded:W,startAdornment:f,endAdornment:r,iconOnly:i,isHoverPossible:m,"aria-disabled":w||c,"aria-busy":c,"aria-label":_(),onClick:$,onKeyDown:B,...C,css:z,children:[g,b,n,c&&a.jsx(j.default,{visuallyHidden:!0,role:"status","aria-live":"polite","aria-atomic":"true",children:typeof t=="string"?`${t} 중`:"로딩 중"})]})});exports.default=P;
@@ -11,6 +11,9 @@ export type ButtonProps<T extends ElementType = 'button'> = PolymorphicComponent
11
11
  iconOnly?: boolean;
12
12
  fullWidth?: boolean;
13
13
  rounded?: boolean;
14
+ loading?: boolean;
15
+ loadingPosition?: 'start' | 'end';
16
+ loadingIndicator?: ReactNode;
14
17
  };
15
18
  type ButtonComponent<DT extends ElementType> = <T extends ElementType = DT>(props: ButtonProps<T>) => ReactNode;
16
19
  declare const Button: ButtonComponent<'button'>;
@@ -1,10 +1,12 @@
1
- import { jsxs as k } from "@emotion/react/jsx-runtime";
2
- import { forwardRef as z, isValidElement as R } from "react";
3
- import W from "../hooks/useCheckHoverPossible/useCheckHoverPossible.es.js";
4
- import M from "../utils/getIconLabel/getIconLabel.es.js";
5
- import j from "@emotion/styled";
6
- import c from "../utils/getContrastingTextColor/getContrastingTextColor.es.js";
7
- const $ = j.button`
1
+ import { jsxs as E, jsx as g, Fragment as F } from "@emotion/react/jsx-runtime";
2
+ import { forwardRef as T, isValidElement as V } from "react";
3
+ import k from "../Box/Box.es.js";
4
+ import q from "../CircularProgressIndicator/CircularProgressIndicator.es.js";
5
+ import G from "../hooks/useCheckHoverPossible/useCheckHoverPossible.es.js";
6
+ import J from "../utils/getIconLabel/getIconLabel.es.js";
7
+ import Q from "@emotion/styled";
8
+ import h from "../utils/getContrastingTextColor/getContrastingTextColor.es.js";
9
+ const U = Q.button`
8
10
  display: inline-flex;
9
11
  align-items: center;
10
12
  justify-content: center;
@@ -22,21 +24,21 @@ const $ = j.button`
22
24
  }) => {
23
25
  let p = {
24
26
  backgroundColor: l.primary.main,
25
- color: c(l.primary.main, [e.white, e[100]])
27
+ color: h(l.primary.main, [e.white, e[100]])
26
28
  };
27
29
  return t === "filled" && o === "secondary" && (p = {
28
30
  backgroundColor: l.secondary,
29
- color: c(l.secondary, [e.white, e[100]])
31
+ color: h(l.secondary, [e.white, e[100]])
30
32
  }), t === "filled" && o === "tertiary" && (p = {
31
33
  backgroundColor: l.tertiary,
32
- color: c(l.tertiary, [e.white, e[100]])
34
+ color: h(l.tertiary, [e.white, e[100]])
33
35
  }), t === "outlined" && (p = {
34
36
  borderColor: e[50],
35
37
  backgroundColor: e.white,
36
- color: c(e.white, [e.white, e[100]])
38
+ color: h(e.white, [e.white, e[100]])
37
39
  }), t === "text" && o === "primary" && (p = {
38
40
  backgroundColor: "transparent",
39
- color: c("transparent", [e.white, e[100]])
41
+ color: h("transparent", [e.white, e[100]])
40
42
  }), t === "text" && o === "secondary" && (p = {
41
43
  backgroundColor: "transparent",
42
44
  color: e[70]
@@ -49,9 +51,9 @@ const $ = j.button`
49
51
  size: o,
50
52
  startAdornment: p,
51
53
  endAdornment: r,
52
- iconOnly: f
54
+ iconOnly: u
53
55
  }) => {
54
- let h = {
56
+ let f = {
55
57
  gap: l.content(1),
56
58
  padding: 10,
57
59
  borderRadius: 8,
@@ -67,7 +69,7 @@ const $ = j.button`
67
69
  if (o === "2xLarge") {
68
70
  const { h0B: i } = e;
69
71
  let x = "26px 24px";
70
- p && (x = t === "text" ? "26px 16px 26px 12px" : "26px 36px 26px 24px"), r && (x = t === "text" ? "26px 12px 26px 16px" : "26px 24px 26px 36px"), p && r && (x = t === "text" ? "26px 12px" : "26px 24px"), f && (x = "26px 25px"), h = {
72
+ p && (x = t === "text" ? "26px 16px 26px 12px" : "26px 36px 26px 24px"), r && (x = t === "text" ? "26px 12px 26px 16px" : "26px 24px 26px 36px"), p && r && (x = t === "text" ? "26px 12px" : "26px 24px"), u && (x = "26px 25px"), f = {
71
73
  gap: l.content(3),
72
74
  maxHeight: 100,
73
75
  padding: x,
@@ -85,7 +87,7 @@ const $ = j.button`
85
87
  if (o === "xLarge") {
86
88
  const { h4B: i } = e;
87
89
  let x = "16px 12px";
88
- p && (x = t === "text" ? "16px 8px 16px 4px" : "16px 16px 16px 12px"), r && (x = t === "text" ? "16px 4px 16px 8px" : "16px 12px 16px 16px"), p && r && (x = t === "text" ? "16px 4px" : "16px 12px"), f && (x = "16px 15px"), h = {
90
+ p && (x = t === "text" ? "16px 8px 16px 4px" : "16px 16px 16px 12px"), r && (x = t === "text" ? "16px 4px 16px 8px" : "16px 12px 16px 16px"), p && r && (x = t === "text" ? "16px 4px" : "16px 12px"), u && (x = "16px 15px"), f = {
89
91
  gap: l.content(2),
90
92
  maxHeight: 56,
91
93
  padding: x,
@@ -103,7 +105,7 @@ const $ = j.button`
103
105
  if (o === "large") {
104
106
  const { b2M: i } = e;
105
107
  let x = "12px 8px";
106
- p && (x = t === "text" ? "12px 8px 12px 4px" : "12px 12px 12px 8px"), r && (x = t === "text" ? "12px 4px 12px 8px" : "12px 8px 12px 12px"), p && r && (x = t === "text" ? "12px 4px" : "12px 8px"), f && (x = "12px 11px"), h = {
108
+ p && (x = t === "text" ? "12px 8px 12px 4px" : "12px 12px 12px 8px"), r && (x = t === "text" ? "12px 4px 12px 8px" : "12px 8px 12px 12px"), p && r && (x = t === "text" ? "12px 4px" : "12px 8px"), u && (x = "12px 11px"), f = {
107
109
  gap: 6,
108
110
  maxHeight: 48,
109
111
  padding: x,
@@ -121,7 +123,7 @@ const $ = j.button`
121
123
  if (o === "medium") {
122
124
  const { b4M: i } = e;
123
125
  let x = "10px 8px";
124
- p && (x = t === "text" ? "10px 8px 10px 4px" : "10px 10px 10px 8px"), r && (x = t === "text" ? "10px 4px 10px 8px" : "10px 8px 10px 10px"), p && r && (x = t === "text" ? "10px 4px" : "10px 8px"), f && (x = "10px 9px"), h = {
126
+ p && (x = t === "text" ? "10px 8px 10px 4px" : "10px 10px 10px 8px"), r && (x = t === "text" ? "10px 4px 10px 8px" : "10px 8px 10px 10px"), p && r && (x = t === "text" ? "10px 4px" : "10px 8px"), u && (x = "10px 9px"), f = {
125
127
  gap: l.content(1),
126
128
  maxHeight: 40,
127
129
  padding: x,
@@ -139,7 +141,7 @@ const $ = j.button`
139
141
  if (o === "small") {
140
142
  const { c3M: i } = e;
141
143
  let x = "8px 6px";
142
- p && (x = t === "text" ? "8px 8px 8px 4px" : "8px 8px 8px 6px"), r && (x = t === "text" ? "8px 4px 8px 8px" : "8px 6px 8px 8px"), p && r && (x = t === "text" ? "8px 6px" : "8px 4px"), f && (x = "8px 7px"), h = {
144
+ p && (x = t === "text" ? "8px 8px 8px 4px" : "8px 8px 8px 6px"), r && (x = t === "text" ? "8px 4px 8px 8px" : "8px 6px 8px 8px"), p && r && (x = t === "text" ? "8px 6px" : "8px 4px"), u && (x = "8px 7px"), f = {
143
145
  gap: l.content(1),
144
146
  maxHeight: 32,
145
147
  padding: x,
@@ -157,7 +159,7 @@ const $ = j.button`
157
159
  if (o === "xSmall") {
158
160
  const { c3M: i } = e;
159
161
  let x = "4px 6px";
160
- p && (x = t === "text" ? "4px 8px 4px 4px" : "4px 8px 4px 6px"), r && (x = t === "text" ? "4px 4px 4px 8px" : "4px 6px 4px 8px"), p && r && (x = t === "text" ? "4px" : "4px 6px"), f && (x = "4px 3px"), f ? h = {
162
+ p && (x = t === "text" ? "4px 8px 4px 4px" : "4px 8px 4px 6px"), r && (x = t === "text" ? "4px 4px 4px 8px" : "4px 6px 4px 8px"), p && r && (x = t === "text" ? "4px" : "4px 6px"), u && (x = "4px 3px"), u ? f = {
161
163
  gap: l.content(1),
162
164
  maxHeight: 24,
163
165
  width: 24,
@@ -171,7 +173,7 @@ const $ = j.button`
171
173
  width: 16,
172
174
  height: 16
173
175
  }
174
- } : h = {
176
+ } : f = {
175
177
  gap: l.content(1),
176
178
  maxHeight: 24,
177
179
  padding: x,
@@ -186,10 +188,10 @@ const $ = j.button`
186
188
  }
187
189
  };
188
190
  }
189
- return t === "text" && o === "xLarge" && (h = {
190
- ...h,
191
+ return t === "text" && o === "xLarge" && (f = {
192
+ ...f,
191
193
  borderWidth: 1.5
192
- }), h;
194
+ }), f;
193
195
  }};
194
196
 
195
197
  ${({ rounded: l }) => l ? {} : {
@@ -220,8 +222,9 @@ const $ = j.button`
220
222
  }), r;
221
223
  }}
222
224
 
223
- &[aria-disabled="true"] {
225
+ &[aria-disabled="true"], &[aria-busy="true"] {
224
226
  cursor: not-allowed;
227
+
225
228
  ${({
226
229
  theme: {
227
230
  palette: { brand: l, grey: e }
@@ -231,17 +234,17 @@ const $ = j.button`
231
234
  }) => {
232
235
  let p = {
233
236
  backgroundColor: l.primary.disable,
234
- color: c(l.primary.disable, [e[30], e.white])
237
+ color: h(l.primary.disable, [e[30], e.white])
235
238
  };
236
239
  return t === "filled" && o === "secondary" && (p = {
237
240
  backgroundColor: e[10],
238
- color: c(e[10], [e[30], e.white])
241
+ color: h(e[10], [e[30], e.white])
239
242
  }), t === "outlined" && (p = {
240
243
  borderColor: e[30],
241
244
  backgroundColor: e[10],
242
- color: c(e[30], [e[30], e.white])
245
+ color: h(e[30], [e[30], e.white])
243
246
  }), t === "text" && (p = {
244
- color: c(e[30], [e[30], e.white])
247
+ color: h(e[30], [e[30], e.white])
245
248
  }), p;
246
249
  }};
247
250
  }
@@ -249,62 +252,70 @@ const $ = j.button`
249
252
  ${({ fullWidth: l }) => l ? {
250
253
  width: "100%"
251
254
  } : null};
252
- `, q = z(function({
255
+ `, v = T(function({
253
256
  tag: e = "button",
254
257
  children: t,
255
258
  variant: o = "filled",
256
259
  size: p = "medium",
257
260
  color: r = "primary",
258
- startAdornment: f,
259
- endAdornment: h,
261
+ startAdornment: u,
262
+ endAdornment: f,
260
263
  iconOnly: i,
261
264
  fullWidth: x,
262
- inlineCSS: b,
263
- rounded: n = !0,
264
- disabled: g,
265
- onClick: d,
266
- onKeyDown: u,
267
- ...s
268
- }, w) {
269
- const { isHoverPossible: S } = W(), H = () => {
265
+ inlineCSS: R,
266
+ rounded: W = !0,
267
+ disabled: w,
268
+ onClick: S,
269
+ onKeyDown: H,
270
+ loading: s,
271
+ loadingPosition: z,
272
+ loadingIndicator: c,
273
+ ...m
274
+ }, M) {
275
+ const { isHoverPossible: j } = G(), $ = () => {
270
276
  if (!i) return;
271
- if (s["aria-label"]) return s["aria-label"];
272
- const a = f || h || t;
273
- if (R(a))
274
- return M(a.props.name);
275
- }, C = (a) => {
276
- g || d == null || d(a);
277
- }, m = (a) => {
278
- g || u == null || u(a);
279
- };
280
- return /* @__PURE__ */ k(
281
- $,
277
+ if (m["aria-label"]) return m["aria-label"];
278
+ const a = u || f || t;
279
+ if (V(a))
280
+ return J(a.props.name);
281
+ }, B = (a) => {
282
+ w || s || S == null || S(a);
283
+ }, L = (a) => {
284
+ w || s || H == null || H(a);
285
+ }, N = !!s, C = c ? /* @__PURE__ */ g(F, { children: c }) : /* @__PURE__ */ g(q, { loop: !0 });
286
+ let d = u, b = i ? null : t, n = f;
287
+ return N && (z ? z === "start" ? (d = /* @__PURE__ */ g(k, { children: C }), n = c ? null : f, b = i || c ? null : t) : (d = c ? null : u, n = /* @__PURE__ */ g(k, { children: C }), b = i || c ? null : t) : (d = null, n = null, b = i ? null : C)), /* @__PURE__ */ E(
288
+ U,
282
289
  {
283
290
  as: e,
284
- ref: w,
291
+ ref: M,
292
+ type: e === "button" ? "button" : void 0,
285
293
  variant: o,
286
294
  size: p,
287
295
  color: r,
288
296
  fullWidth: x,
289
- rounded: n,
290
- startAdornment: f,
291
- endAdornment: h,
297
+ rounded: W,
298
+ startAdornment: u,
299
+ endAdornment: f,
292
300
  iconOnly: i,
293
- isHoverPossible: S,
294
- "aria-disabled": g,
295
- "aria-label": H(),
296
- onClick: C,
297
- onKeyDown: m,
298
- ...s,
299
- css: b,
301
+ isHoverPossible: j,
302
+ "aria-disabled": w || s,
303
+ "aria-busy": s,
304
+ "aria-label": $(),
305
+ onClick: B,
306
+ onKeyDown: L,
307
+ ...m,
308
+ css: R,
300
309
  children: [
301
- f,
302
- !i && t,
303
- h
310
+ d,
311
+ b,
312
+ n,
313
+ s && // TODO: loadingIndicator가 문자열이 아닌 경우 처리
314
+ /* @__PURE__ */ g(k, { visuallyHidden: !0, role: "status", "aria-live": "polite", "aria-atomic": "true", children: typeof t == "string" ? `${t} 중` : "로딩 중" })
304
315
  ]
305
316
  }
306
317
  );
307
318
  });
308
319
  export {
309
- q as default
320
+ v as default
310
321
  };
@@ -35,4 +35,5 @@ export declare const StartAdornment: Story;
35
35
  export declare const EndAdornment: Story;
36
36
  export declare const BothAdornment: Story;
37
37
  export declare const IconOnly: Story;
38
+ export declare const Loading: Story;
38
39
  export declare const AnchorButton: Story;
@@ -34,3 +34,4 @@ export declare const PasswordVisibility: Story;
34
34
  export declare const Success: Story;
35
35
  export declare const Error: Story;
36
36
  export declare const WithScreenReaderSupport: Story;
37
+ export declare const withUseForm: Story;
package/hooks/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useCheckHoverPossible/useCheckHoverPossible.cjs"),u=require("./useCheckKeyboardMode/useCheckKeyboardMode.cjs"),s=require("./useCheckHasFocus/useCheckHasFocus.cjs"),o=require("./useFocusBoundary/useFocusBoundary.cjs"),r=require("./interactions/useCollapse/useCollapse.cjs"),t=require("./useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.cjs"),c=require("./usePrefersReducedMotion/usePrefersReducedMotion.cjs");exports.useCheckHoverPossible=e.default;exports.useCheckKeyboardMode=u.default;exports.useCheckHasFocus=s.default;exports.useFocusBoundary=o.default;exports.useCollapse=r.default;exports.useIsomorphicLayoutEffect=t.default;exports.usePrefersReducedMotion=c.default;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useCheckHoverPossible/useCheckHoverPossible.cjs"),u=require("./useCheckKeyboardMode/useCheckKeyboardMode.cjs"),s=require("./useCheckHasFocus/useCheckHasFocus.cjs"),o=require("./useFocusBoundary/useFocusBoundary.cjs"),r=require("./interactions/useCollapse/useCollapse.cjs"),t=require("./useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.cjs"),c=require("./usePrefersReducedMotion/usePrefersReducedMotion.cjs"),a=require("./useForm/useForm.cjs");exports.useCheckHoverPossible=e.default;exports.useCheckKeyboardMode=u.default;exports.useCheckHasFocus=s.default;exports.useFocusBoundary=o.default;exports.useCollapse=r.default;exports.useIsomorphicLayoutEffect=t.default;exports.usePrefersReducedMotion=c.default;exports.useForm=a.default;
package/hooks/index.d.ts CHANGED
@@ -5,5 +5,7 @@ export { default as useFocusBoundary } from './useFocusBoundary/useFocusBoundary
5
5
  export { default as useCollapse } from './interactions/useCollapse/useCollapse';
6
6
  export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect/useIsomorphicLayoutEffect';
7
7
  export { default as usePrefersReducedMotion } from './usePrefersReducedMotion/usePrefersReducedMotion';
8
+ export { default as useForm } from './useForm/useForm';
8
9
  export type { UseFocusBoundaryProps } from './useFocusBoundary/useFocusBoundary';
9
10
  export type { UseCollapseProps } from './interactions/useCollapse/useCollapse';
11
+ export type { FieldErrors, FormContext, FormFieldHelper, OnSubmitFn, SubmitFn, ValidateFn, UseFormProps, UseFormReturn } from './useForm/useForm';
package/hooks/index.es.js CHANGED
@@ -2,15 +2,17 @@ import { default as s } from "./useCheckHoverPossible/useCheckHoverPossible.es.j
2
2
  import { default as a } from "./useCheckKeyboardMode/useCheckKeyboardMode.es.js";
3
3
  import { default as f } from "./useCheckHasFocus/useCheckHasFocus.es.js";
4
4
  import { default as d } from "./useFocusBoundary/useFocusBoundary.es.js";
5
- import { default as p } from "./interactions/useCollapse/useCollapse.es.js";
6
- import { default as m } from "./useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.es.js";
5
+ import { default as m } from "./interactions/useCollapse/useCollapse.es.js";
6
+ import { default as c } from "./useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.es.js";
7
7
  import { default as h } from "./usePrefersReducedMotion/usePrefersReducedMotion.es.js";
8
+ import { default as i } from "./useForm/useForm.es.js";
8
9
  export {
9
10
  f as useCheckHasFocus,
10
11
  s as useCheckHoverPossible,
11
12
  a as useCheckKeyboardMode,
12
- p as useCollapse,
13
+ m as useCollapse,
13
14
  d as useFocusBoundary,
14
- m as useIsomorphicLayoutEffect,
15
+ i as useForm,
16
+ c as useIsomorphicLayoutEffect,
15
17
  h as usePrefersReducedMotion
16
18
  };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("react"),y=require("./useForm.utils.cjs");function O({fieldNames:S,values:u,validate:C,meta:n,scrollOptions:k,scrollOnError:d=!0,focusOnError:o=!1}){const a=t.useRef(new Map),E=t.useRef(new Map),[l,b]=t.useState({}),[V,F]=t.useState(!1),R=d||o,_=t.useCallback(e=>{const r=E.current.get(e);if(r)return r;const s=c=>{c?a.current.set(e,c):a.current.delete(e)};return E.current.set(e,s),s},[]),i=t.useCallback(e=>{requestAnimationFrame(()=>{for(const r of S){if(!(e==null?void 0:e[r]))continue;const c=a.current.get(r);if(d&&c&&c.scrollIntoView(k??y.DEFAULT_SCROLL_OPTIONS),o&&c){const g=c.querySelector('input:not([type="hidden"]):not([disabled]), textarea:not([disabled])');g==null||g.focus({preventScroll:!0})}break}})},[S,k,d,o]),w=t.useCallback(()=>{const e={};return C({values:u,meta:n,fieldRefs:a.current,error:e})},[C,u,n]),f=t.useCallback(({callEffectOnError:e=!0}={})=>{const r=w();b(r);const s=y.hasError(r);return s&&e&&R&&i(r),{isValid:!s,errors:r}},[w,R,i]),m=t.useCallback(({callEffectOnError:e=!0}={})=>{f({callEffectOnError:e})},[f]),q=t.useCallback(()=>{b({})},[]),M=t.useCallback((e,r)=>{b(s=>({...s,[e]:r}))},[]),h=t.useCallback(e=>{i(e)},[i]),I=t.useCallback(e=>{const r=l==null?void 0:l[e];if(r)return{severity:"error",message:r}},[l]),L=t.useCallback((e={})=>async()=>{F(!0);const{isValid:r,errors:s}=f({callEffectOnError:!0}),c={values:u,meta:n,fieldRefs:a.current,error:s};r?e!=null&&e.onSuccess&&await e.onSuccess(c):e!=null&&e.onError&&await e.onError(c),e!=null&&e.onSettled&&await e.onSettled(c)},[f,u,n,F]);return{isSubmitted:V,errors:l,registerField:_,clearErrors:q,triggerValidate:m,triggerSetFieldError:M,triggerEffectOnError:h,getFieldHelper:I,submit:L}}exports.default=O;
@@ -0,0 +1,48 @@
1
+ import { DEFAULT_SCROLL_OPTIONS } from './useForm.utils';
2
+
3
+ export type FieldErrors<K extends string> = Partial<Record<K, string>>;
4
+ export type FormFieldHelper = {
5
+ severity: 'error';
6
+ message?: string;
7
+ };
8
+ export type FormContext<V, N extends string, M> = {
9
+ values: V;
10
+ meta?: M;
11
+ fieldRefs: Map<N, HTMLElement | null>;
12
+ error: FieldErrors<N>;
13
+ };
14
+ export type ValidateFn<V, N extends string, M> = (ctx: FormContext<V, N, M>) => FieldErrors<N>;
15
+ export type OnSubmitFn<V, N extends string, M> = (ctx: FormContext<V, N, M>) => void | Promise<void>;
16
+ export type SubmitFn<V, N extends string, M> = (options?: Partial<Record<'onError' | 'onSuccess' | 'onSettled', OnSubmitFn<V, N, M>>>) => () => Promise<void>;
17
+ export interface UseFormProps<V, N extends string, M> {
18
+ fieldNames: readonly N[];
19
+ values: V;
20
+ validate: ValidateFn<V, N, M>;
21
+ meta?: M;
22
+ scrollOptions?: typeof DEFAULT_SCROLL_OPTIONS;
23
+ scrollOnError?: boolean;
24
+ focusOnError?: boolean;
25
+ }
26
+ export interface UseFormReturn<V, N extends string, M> {
27
+ /** 제출 여부 */
28
+ isSubmitted: boolean;
29
+ /** 에러 상태 */
30
+ errors: FieldErrors<N>;
31
+ /** 필드 등록 */
32
+ registerField: (name: N) => (element: HTMLElement | null) => void;
33
+ /** 에러 초기화 */
34
+ clearErrors: () => void;
35
+ /** 필드 에러 도움말 반환 */
36
+ getFieldHelper: (name: N) => FormFieldHelper | undefined;
37
+ /** 제출 함수 */
38
+ submit: SubmitFn<V, N, M>;
39
+ /** [imperative] 검증 후 errors 갱신 직접 호출 */
40
+ triggerValidate: (options?: {
41
+ callEffectOnError?: boolean;
42
+ }) => void;
43
+ /** [imperative] 필드 에러 설정 직접 호출 */
44
+ triggerSetFieldError: (name: N, message: string) => void;
45
+ /** [imperative] 에러 발생 시 스크롤·포커스 처리 직접 호출 */
46
+ triggerEffectOnError: (errors: FieldErrors<N>) => void;
47
+ }
48
+ export default function useForm<V, N extends string, M = unknown>({ fieldNames, values, validate, meta, scrollOptions, scrollOnError, focusOnError }: UseFormProps<V, N, M>): UseFormReturn<V, N, M>;
@@ -0,0 +1,98 @@
1
+ import { useRef as C, useState as R, useCallback as n } from "react";
2
+ import { DEFAULT_SCROLL_OPTIONS as T, hasError as _ } from "./useForm.utils.es.js";
3
+ function H({
4
+ fieldNames: b,
5
+ values: f,
6
+ validate: E,
7
+ meta: i,
8
+ scrollOptions: m,
9
+ scrollOnError: d = !0,
10
+ focusOnError: o = !1
11
+ }) {
12
+ const s = C(/* @__PURE__ */ new Map()), w = C(/* @__PURE__ */ new Map()), [a, g] = R({}), [k, F] = R(!1), V = d || o, h = n((e) => {
13
+ const r = w.current.get(e);
14
+ if (r)
15
+ return r;
16
+ const c = (t) => {
17
+ t ? s.current.set(e, t) : s.current.delete(e);
18
+ };
19
+ return w.current.set(e, c), c;
20
+ }, []), u = n(
21
+ (e) => {
22
+ requestAnimationFrame(() => {
23
+ for (const r of b) {
24
+ if (!(e == null ? void 0 : e[r])) continue;
25
+ const t = s.current.get(r);
26
+ if (d && t && t.scrollIntoView(m ?? T), o && t) {
27
+ const S = t.querySelector(
28
+ 'input:not([type="hidden"]):not([disabled]), textarea:not([disabled])'
29
+ );
30
+ S == null || S.focus({
31
+ preventScroll: !0
32
+ });
33
+ }
34
+ break;
35
+ }
36
+ });
37
+ },
38
+ [b, m, d, o]
39
+ ), y = n(() => {
40
+ const e = {};
41
+ return E({ values: f, meta: i, fieldRefs: s.current, error: e });
42
+ }, [E, f, i]), l = n(
43
+ ({ callEffectOnError: e = !0 } = {}) => {
44
+ const r = y();
45
+ g(r);
46
+ const c = _(r);
47
+ return c && e && V && u(r), { isValid: !c, errors: r };
48
+ },
49
+ [y, V, u]
50
+ ), I = n(
51
+ ({ callEffectOnError: e = !0 } = {}) => {
52
+ l({ callEffectOnError: e });
53
+ },
54
+ [l]
55
+ ), L = n(() => {
56
+ g({});
57
+ }, []), q = n((e, r) => {
58
+ g((c) => ({ ...c, [e]: r }));
59
+ }, []), A = n(
60
+ (e) => {
61
+ u(e);
62
+ },
63
+ [u]
64
+ ), M = n(
65
+ (e) => {
66
+ const r = a == null ? void 0 : a[e];
67
+ if (r)
68
+ return { severity: "error", message: r };
69
+ },
70
+ [a]
71
+ ), O = n(
72
+ (e = {}) => async () => {
73
+ F(!0);
74
+ const { isValid: r, errors: c } = l({ callEffectOnError: !0 }), t = {
75
+ values: f,
76
+ meta: i,
77
+ fieldRefs: s.current,
78
+ error: c
79
+ };
80
+ r ? e != null && e.onSuccess && await e.onSuccess(t) : e != null && e.onError && await e.onError(t), e != null && e.onSettled && await e.onSettled(t);
81
+ },
82
+ [l, f, i, F]
83
+ );
84
+ return {
85
+ isSubmitted: k,
86
+ errors: a,
87
+ registerField: h,
88
+ clearErrors: L,
89
+ triggerValidate: I,
90
+ triggerSetFieldError: q,
91
+ triggerEffectOnError: A,
92
+ getFieldHelper: M,
93
+ submit: O
94
+ };
95
+ }
96
+ export {
97
+ H as default
98
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function t(e){return e?Object.values(e).some(r=>r!=null&&r!==""):!1}const n=Object.freeze({block:"center",inline:"center",behavior:"smooth"});exports.DEFAULT_SCROLL_OPTIONS=n;exports.hasError=t;
@@ -0,0 +1,4 @@
1
+ import { FieldErrors } from './useForm';
2
+
3
+ export declare function hasError<K extends string>(errors: FieldErrors<K> | null): boolean;
4
+ export declare const DEFAULT_SCROLL_OPTIONS: ScrollIntoViewOptions;
@@ -0,0 +1,12 @@
1
+ function t(e) {
2
+ return e ? Object.values(e).some((n) => n != null && n !== "") : !1;
3
+ }
4
+ const r = Object.freeze({
5
+ block: "center",
6
+ inline: "center",
7
+ behavior: "smooth"
8
+ });
9
+ export {
10
+ r as DEFAULT_SCROLL_OPTIONS,
11
+ t as hasError
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotss/ui",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "React UI components for Dotss",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",