@sito/ui 0.2.0 → 0.3.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/README.md CHANGED
@@ -23,8 +23,63 @@ import "@sito/ui/theme.css";
23
23
  import { Button, Dialog, DialogActions, IconButton, useDialog } from "@sito/ui";
24
24
  ```
25
25
 
26
- Exported types include `ButtonProps`, `IconButtonProps`, `DialogProps`,
27
- `DialogActionsProps`, and `UseDialogReturn`.
26
+ Exported types include `ButtonProps`, `ButtonSize`, `IconButtonProps`,
27
+ `DialogProps`, `DialogActionsProps`, `DialogState`, `IconButtonSize`, and
28
+ `UseDialogReturn`.
29
+
30
+ ## Button Sizes
31
+
32
+ `Button` supports `size="sm" | "md" | "lg"` for padding and height. `md` is
33
+ the default size.
34
+
35
+ ```tsx
36
+ <Button size="sm">Small</Button>
37
+ <Button size="md">Medium</Button>
38
+ <Button size="lg">Large</Button>
39
+ ```
40
+
41
+ ## Icon Button Sizes
42
+
43
+ `IconButton` supports `size="sm" | "md" | "lg"` for the button container.
44
+ `md` is the default size.
45
+
46
+ ```tsx
47
+ <IconButton aria-label="Add" icon="+" size="sm" />
48
+ <IconButton aria-label="Add" icon="+" size="md" />
49
+ <IconButton aria-label="Add" icon="+" size="lg" />
50
+ ```
51
+
52
+ The container sizes are `28px`, `40px`, and `48px`. Icon size is separate:
53
+ override `iconSize` or `--sito-ui-icon-button-icon-size`.
54
+
55
+ ## Development
56
+
57
+ Run the component test suite with:
58
+
59
+ ```sh
60
+ pnpm test:run
61
+ ```
62
+
63
+ Start Storybook with:
64
+
65
+ ```sh
66
+ pnpm storybook
67
+ ```
68
+
69
+ ## Dialog Exit Transitions
70
+
71
+ `Dialog` unmounts immediately by default. Pass `exitDurationMs` when a consumer
72
+ needs to keep the portal mounted long enough for a CSS exit animation:
73
+
74
+ ```tsx
75
+ <Dialog open={open} onClose={close} exitDurationMs={220}>
76
+ Dialog content
77
+ </Dialog>
78
+ ```
79
+
80
+ During that delay, the backdrop and dialog expose `data-state="closing"` plus
81
+ `sito-ui-dialog-backdrop--closing` and `sito-ui-dialog--closing` classes.
82
+ Use those hooks from consumer CSS to define the actual animation.
28
83
 
29
84
  ## Scope
30
85
 
@@ -1,3 +1,3 @@
1
1
  import { default as Button } from './Button';
2
- export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonVariant, } from './types';
2
+ export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonSize, ButtonVariant, } from './types';
3
3
  export { Button };
@@ -13,10 +13,17 @@ export declare const BUTTON_VARIANTS: {
13
13
  readonly SUBMIT: "submit";
14
14
  readonly OUTLINED: "outlined";
15
15
  };
16
+ export declare const BUTTON_SIZES: {
17
+ readonly SM: "sm";
18
+ readonly MD: "md";
19
+ readonly LG: "lg";
20
+ };
16
21
  export type ButtonColor = (typeof BUTTON_COLOR_VARIANTS)[keyof typeof BUTTON_COLOR_VARIANTS];
22
+ export type ButtonSize = (typeof BUTTON_SIZES)[keyof typeof BUTTON_SIZES];
17
23
  export type ButtonVariant = (typeof BUTTON_VARIANTS)[keyof typeof BUTTON_VARIANTS];
18
24
  export type ButtonBaseProps = {
19
25
  color?: ButtonColor | undefined;
26
+ size?: ButtonSize | undefined;
20
27
  variant?: ButtonVariant | undefined;
21
28
  loading?: boolean | undefined;
22
29
  loadingIndicator?: ReactNode;
@@ -1,3 +1,3 @@
1
1
  export { Dialog } from './Dialog';
2
2
  export { DialogActions } from './DialogActions';
3
- export type { DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogSubmitHandler, } from './types';
3
+ export type { DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogState, DialogSubmitHandler, } from './types';
@@ -6,6 +6,7 @@ export declare const DIALOG_INITIAL_FOCUS: {
6
6
  readonly SUBMIT: "submit";
7
7
  };
8
8
  export type DialogInitialFocus = (typeof DIALOG_INITIAL_FOCUS)[keyof typeof DIALOG_INITIAL_FOCUS];
9
+ export type DialogState = "open" | "closing";
9
10
  export type DialogSubmitHandler = (event: FormEvent<HTMLFormElement>) => void | Promise<void>;
10
11
  type DialogAccessibleNameProps = {
11
12
  title: ReactNode;
@@ -31,6 +32,8 @@ type DialogBaseProps = {
31
32
  closeIcon?: ReactNode;
32
33
  showCloseButton?: boolean;
33
34
  portalContainer?: Element | DocumentFragment | null;
35
+ exitDurationMs?: number;
36
+ onExitComplete?: () => void;
34
37
  };
35
38
  export type DialogProps = DialogBaseProps & DialogAccessibleNameProps;
36
39
  export type DialogActionButtonProps = ButtonProps & {
@@ -1,3 +1,3 @@
1
1
  import { default as IconButton } from './IconButton';
2
- export type { IconButtonProps } from './types';
2
+ export type { IconButtonProps, IconButtonSize } from './types';
3
3
  export { IconButton };
@@ -1,5 +1,11 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ButtonProps } from '../Button';
3
+ export declare const ICON_BUTTON_SIZES: {
4
+ readonly SM: "sm";
5
+ readonly MD: "md";
6
+ readonly LG: "lg";
7
+ };
8
+ export type IconButtonSize = (typeof ICON_BUTTON_SIZES)[keyof typeof ICON_BUTTON_SIZES];
3
9
  type IconButtonAccessibleLabelProps = {
4
10
  "aria-label": string;
5
11
  children?: ReactNode;
@@ -7,8 +13,10 @@ type IconButtonAccessibleLabelProps = {
7
13
  "aria-label"?: string;
8
14
  children: ReactNode;
9
15
  };
10
- export type IconButtonProps = Omit<ButtonProps, "aria-label" | "children"> & IconButtonAccessibleLabelProps & {
16
+ export type IconButtonProps = Omit<ButtonProps, "aria-label" | "children" | "size"> & IconButtonAccessibleLabelProps & {
11
17
  icon: ReactNode;
12
18
  iconClassName?: string;
19
+ iconSize?: number | string;
20
+ size?: IconButtonSize;
13
21
  };
14
22
  export {};
@@ -1,6 +1,6 @@
1
- export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonVariant, } from './Button';
1
+ export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonSize, ButtonVariant, } from './Button';
2
2
  export { Button } from './Button';
3
- export type { DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogSubmitHandler, } from './Dialog';
3
+ export type { DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogState, DialogSubmitHandler, } from './Dialog';
4
4
  export { Dialog, DialogActions } from './Dialog';
5
- export type { IconButtonProps } from './IconButton';
5
+ export type { IconButtonProps, IconButtonSize } from './IconButton';
6
6
  export { IconButton } from './IconButton';
package/dist/main.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonVariant, DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogSubmitHandler, IconButtonProps, } from './components';
1
+ export type { ButtonBaseProps, ButtonColor, ButtonProps, ButtonSize, ButtonVariant, DialogActionButtonProps, DialogActionsProps, DialogInitialFocus, DialogProps, DialogState, DialogSubmitHandler, IconButtonProps, IconButtonSize, } from './components';
2
2
  export { Button, Dialog, DialogActions, IconButton } from './components';
3
3
  export type { UseDialogReturn } from './hooks';
4
4
  export { useDialog } from './hooks';
package/dist/styles.css CHANGED
@@ -39,11 +39,20 @@
39
39
  --sito-ui-color-info-hover: #3397b9;
40
40
 
41
41
  --sito-ui-space-0: 0;
42
+ --sito-ui-space-1: 0.25rem;
42
43
  --sito-ui-space-2: 0.5rem;
44
+ --sito-ui-space-3: 0.75rem;
43
45
  --sito-ui-space-4: 1rem;
44
46
  --sito-ui-space-5: 1.25rem;
45
47
 
46
- --sito-ui-size-icon-button: 1.75rem;
48
+ --sito-ui-size-button-sm: 32px;
49
+ --sito-ui-size-button-md: 40px;
50
+ --sito-ui-size-button-lg: 48px;
51
+ --sito-ui-size-icon-button-sm: 28px;
52
+ --sito-ui-size-icon-button-md: 40px;
53
+ --sito-ui-size-icon-button-lg: 48px;
54
+ --sito-ui-size-icon-button: var(--sito-ui-size-icon-button-md);
55
+ --sito-ui-size-icon-button-icon: 1.25rem;
47
56
  --sito-ui-size-button-spinner: 1em;
48
57
 
49
58
  --sito-ui-radius-pill: 1.5rem;
@@ -55,10 +64,8 @@
55
64
 
56
65
  --sito-ui-font-weight-semibold: 600;
57
66
  --sito-ui-font-size-button: 0.875rem;
58
- --sito-ui-font-size-icon-button: 1.25rem;
59
67
  --sito-ui-font-size-dialog-title: 1.25rem;
60
68
  --sito-ui-line-height-button: 1.25rem;
61
- --sito-ui-line-height-icon-button: 1.75rem;
62
69
  --sito-ui-line-height-dialog-title: 1.75rem;
63
70
 
64
71
  --sito-ui-motion-duration-normal: 300ms;
@@ -80,14 +87,20 @@
80
87
  --sito-ui-button-light: var(--sito-ui-color-default-light);
81
88
  --sito-ui-button-default: var(--sito-ui-color-default-default);
82
89
  --sito-ui-button-hover: var(--sito-ui-color-default-hover);
90
+ --sito-ui-button-height: var(--sito-ui-size-button-md, 40px);
91
+ --sito-ui-button-padding-block: var(--sito-ui-space-2);
92
+ --sito-ui-button-padding-inline: var(--sito-ui-space-4);
83
93
 
84
94
  display: flex;
95
+ box-sizing: border-box;
85
96
  gap: var(--sito-ui-space-2);
86
97
  font-weight: var(--sito-ui-font-weight-semibold);
87
98
  cursor: default;
88
99
  align-items: center;
89
100
  justify-content: center;
90
- padding: var(--sito-ui-space-2) var(--sito-ui-space-4);
101
+ height: var(--sito-ui-button-height);
102
+ padding: var(--sito-ui-button-padding-block)
103
+ var(--sito-ui-button-padding-inline);
91
104
  border-radius: var(--sito-ui-radius-pill);
92
105
  border: var(--sito-ui-border-width-thin) solid transparent;
93
106
  background-color: transparent;
@@ -101,6 +114,24 @@
101
114
  transition-timing-function: var(--sito-ui-motion-easing-standard);
102
115
  }
103
116
 
117
+ .sito-ui-button--sm {
118
+ --sito-ui-button-height: var(--sito-ui-size-button-sm, 32px);
119
+ --sito-ui-button-padding-block: var(--sito-ui-space-1);
120
+ --sito-ui-button-padding-inline: var(--sito-ui-space-3);
121
+ }
122
+
123
+ .sito-ui-button--md {
124
+ --sito-ui-button-height: var(--sito-ui-size-button-md, 40px);
125
+ --sito-ui-button-padding-block: var(--sito-ui-space-2);
126
+ --sito-ui-button-padding-inline: var(--sito-ui-space-4);
127
+ }
128
+
129
+ .sito-ui-button--lg {
130
+ --sito-ui-button-height: var(--sito-ui-size-button-lg, 48px);
131
+ --sito-ui-button-padding-block: var(--sito-ui-space-3);
132
+ --sito-ui-button-padding-inline: var(--sito-ui-space-5);
133
+ }
134
+
104
135
  .sito-ui-button:enabled:not([aria-disabled="true"]) {
105
136
  cursor: pointer;
106
137
  }
@@ -240,16 +271,52 @@
240
271
  }
241
272
 
242
273
  .sito-ui-icon-button {
243
- min-width: var(--sito-ui-size-icon-button);
244
- min-height: var(--sito-ui-size-icon-button);
245
- width: var(--sito-ui-size-icon-button);
246
- height: var(--sito-ui-size-icon-button);
274
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-md);
275
+ --sito-ui-icon-button-icon-size: var(--sito-ui-size-icon-button-icon);
276
+ --sito-ui-size-button-spinner: var(--sito-ui-icon-button-icon-size);
277
+
278
+ box-sizing: border-box;
279
+ min-width: var(--sito-ui-icon-button-container-size);
280
+ min-height: var(--sito-ui-icon-button-container-size);
281
+ width: var(--sito-ui-icon-button-container-size);
282
+ height: var(--sito-ui-icon-button-container-size);
247
283
  border-radius: var(--sito-ui-radius-round);
248
- font-size: var(--sito-ui-font-size-icon-button);
249
- line-height: var(--sito-ui-line-height-icon-button);
250
284
  padding: var(--sito-ui-space-0);
251
285
  }
252
286
 
287
+ .sito-ui-icon-button--sm {
288
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-sm);
289
+ }
290
+
291
+ .sito-ui-icon-button--md {
292
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-md);
293
+ }
294
+
295
+ .sito-ui-icon-button--lg {
296
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-lg);
297
+ }
298
+
299
+ .sito-ui-icon-button--with-content {
300
+ width: auto;
301
+ height: auto;
302
+ padding: var(--sito-ui-button-padding-block)
303
+ var(--sito-ui-button-padding-inline);
304
+ border-radius: var(--sito-ui-radius-pill);
305
+ font-size: var(--sito-ui-font-size-button);
306
+ line-height: var(--sito-ui-line-height-button);
307
+ }
308
+
309
+ .sito-ui-icon-button__icon {
310
+ display: inline-flex;
311
+ flex: 0 0 auto;
312
+ align-items: center;
313
+ justify-content: center;
314
+ width: var(--sito-ui-icon-button-icon-size);
315
+ height: var(--sito-ui-icon-button-icon-size);
316
+ font-size: var(--sito-ui-icon-button-icon-size);
317
+ line-height: 1;
318
+ }
319
+
253
320
  .sito-ui-dialog-backdrop {
254
321
  position: fixed;
255
322
  inset: 0;
@@ -264,6 +331,10 @@
264
331
  backdrop-filter: var(--sito-ui-dialog-backdrop-filter);
265
332
  }
266
333
 
334
+ .sito-ui-dialog-backdrop--closing {
335
+ pointer-events: none;
336
+ }
337
+
267
338
  .sito-ui-dialog {
268
339
  position: relative;
269
340
  display: flex;
package/dist/theme.css CHANGED
@@ -39,11 +39,20 @@
39
39
  --sito-ui-color-info-hover: #3397b9;
40
40
 
41
41
  --sito-ui-space-0: 0;
42
+ --sito-ui-space-1: 0.25rem;
42
43
  --sito-ui-space-2: 0.5rem;
44
+ --sito-ui-space-3: 0.75rem;
43
45
  --sito-ui-space-4: 1rem;
44
46
  --sito-ui-space-5: 1.25rem;
45
47
 
46
- --sito-ui-size-icon-button: 1.75rem;
48
+ --sito-ui-size-button-sm: 32px;
49
+ --sito-ui-size-button-md: 40px;
50
+ --sito-ui-size-button-lg: 48px;
51
+ --sito-ui-size-icon-button-sm: 28px;
52
+ --sito-ui-size-icon-button-md: 40px;
53
+ --sito-ui-size-icon-button-lg: 48px;
54
+ --sito-ui-size-icon-button: var(--sito-ui-size-icon-button-md);
55
+ --sito-ui-size-icon-button-icon: 1.25rem;
47
56
  --sito-ui-size-button-spinner: 1em;
48
57
 
49
58
  --sito-ui-radius-pill: 1.5rem;
@@ -55,10 +64,8 @@
55
64
 
56
65
  --sito-ui-font-weight-semibold: 600;
57
66
  --sito-ui-font-size-button: 0.875rem;
58
- --sito-ui-font-size-icon-button: 1.25rem;
59
67
  --sito-ui-font-size-dialog-title: 1.25rem;
60
68
  --sito-ui-line-height-button: 1.25rem;
61
- --sito-ui-line-height-icon-button: 1.75rem;
62
69
  --sito-ui-line-height-dialog-title: 1.75rem;
63
70
 
64
71
  --sito-ui-motion-duration-normal: 300ms;
package/dist/ui.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("react"),t=require("react/jsx-runtime"),n=require("react-dom");var r=(...e)=>e.filter(Boolean).join(` `),i={DEFAULT:`default`,PRIMARY:`primary`,SECONDARY:`secondary`,ERROR:`error`,WARNING:`warning`,SUCCESS:`success`,INFO:`info`},a={TEXT:`text`,SUBMIT:`submit`,OUTLINED:`outlined`},o=(0,e.forwardRef)(function(e,n){let{color:o=i.DEFAULT,type:s=`button`,variant:c=a.TEXT,loading:l=!1,loadingIndicator:u,loadingLabel:d=`Loading`,disabled:f,className:p,children:m,...h}=e,g=r(`sito-ui-button`,`sito-ui-button--${c}`,`sito-ui-button--${o}`,l&&`sito-ui-button--loading`,p),_=u===void 0?(0,t.jsx)(`span`,{className:`sito-ui-button__spinner`,"aria-hidden":`true`,"data-sito-ui":`button-spinner`}):u;return(0,t.jsxs)(`button`,{"data-sito-ui":`button`,...h,type:s,ref:n,disabled:f||l,"aria-busy":l||h[`aria-busy`],className:g,children:[l?(0,t.jsxs)(t.Fragment,{children:[_,(0,t.jsx)(`span`,{className:`sito-ui-button__loading-label`,children:d})]}):null,m]})}),s=(0,e.forwardRef)(function(e,n){let{children:i,icon:a,iconClassName:s,type:c=`button`,variant:l=`text`,color:u=`default`,loading:d=!1,className:f,...p}=e,m=r(`sito-ui-icon-button`,f);return(0,t.jsxs)(o,{...p,ref:n,type:c,variant:l,color:u,loading:d,"data-sito-ui":`icon-button`,className:m,children:[d?null:(0,t.jsx)(`span`,{className:s,"aria-hidden":`true`,children:a}),i]})}),c=`input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled])`,l=`button[type="submit"]:not([disabled]), input[type="submit"]:not([disabled])`,u=[`a[href]`,`button:not([disabled])`,`textarea:not([disabled])`,`input:not([disabled])`,`select:not([disabled])`,`[tabindex]:not([tabindex="-1"])`].join(`,`),d=0,f=null,p=()=>typeof document<`u`&&!!document.body,m=()=>{p()&&(d===0&&(f=document.body.style.overflow,document.body.style.overflow=`hidden`),d+=1)},h=()=>{!p()||d===0||(--d,d===0&&(document.body.style.overflow=f??``,f=null))},g=e=>Array.from(e.querySelectorAll(u)).filter(e=>e.getAttribute(`aria-disabled`)!==`true`),_=()=>typeof document>`u`?null:document.activeElement instanceof HTMLElement?document.activeElement:null,v=i=>{let a=(0,e.useId)(),o=(0,e.useRef)(null),u=(0,e.useRef)(null),{dialogId:d,title:f,ariaLabel:p,children:v,onClose:y,initialFocus:b=`none`,closeOnBackdropClick:x=!1,closeOnEscape:S=!0,lockBodyScroll:C=!0,onSubmit:w,open:T=!1,mobileFullScreen:E=!1,containerClassName:D,className:O,closeLabel:k=`Close dialog`,closeIcon:A=`x`,showCloseButton:j=!0,portalContainer:M}=i,N=f?`${d??a}-title`:void 0,P=(0,e.useCallback)(e=>{if(e.key===`Escape`&&T&&S){y();return}if(e.key!==`Tab`||!T)return;let t=o.current;if(!t)return;let n=g(t);if(n.length===0){e.preventDefault(),t.focus();return}let r=n[0],i=n[n.length-1],a=_(),s=!a||!t.contains(a);if(e.shiftKey&&(s||a===r)){e.preventDefault(),i.focus();return}!e.shiftKey&&(s||a===i)&&(e.preventDefault(),r.focus())},[S,y,T]);(0,e.useEffect)(()=>{if(!(!T||typeof window>`u`))return window.addEventListener(`keydown`,P),()=>{window.removeEventListener(`keydown`,P)}},[P,T]),(0,e.useEffect)(()=>{if(T)return u.current=_(),()=>{u.current?.isConnected&&u.current.focus(),u.current=null}},[T]),(0,e.useEffect)(()=>{if(!T)return;let e=o.current;if(e){if(b===`first-input`){let t=e.querySelector(c);if(t){t.focus();return}}if(b===`submit`){let t=e.querySelector(l);if(t){t.focus();return}}e.focus()}},[b,T]),(0,e.useEffect)(()=>{if(!(!T||!C))return m(),()=>{h()}},[T,C]);let F=(0,e.useCallback)(e=>{x&&e.target===e.currentTarget&&y()},[x,y]),I=(0,e.useCallback)(e=>{e.preventDefault(),w?.(e)},[w]);if(!T||typeof document>`u`)return null;let L=w?(0,t.jsx)(`form`,{onSubmit:I,children:v}):v,R=typeof A==`string`?(0,t.jsx)(`span`,{"aria-hidden":`true`,children:A}):A;return(0,n.createPortal)((0,t.jsx)(`div`,{id:d?`backdrop-${d}`:void 0,"data-sito-ui":`dialog-backdrop`,onClick:F,className:r(`sito-ui-dialog-backdrop`,D),children:(0,t.jsxs)(`div`,{id:d,ref:o,role:`dialog`,"aria-modal":`true`,"aria-label":f?void 0:p,"aria-labelledby":N,tabIndex:-1,"data-sito-ui":`dialog`,className:r(`sito-ui-dialog`,E&&`sito-ui-dialog--mobile-full-screen`,O),children:[(0,t.jsxs)(`div`,{className:`sito-ui-dialog__header`,children:[f?(0,t.jsx)(`h3`,{id:N,className:`sito-ui-dialog__title`,children:f}):null,j?(0,t.jsx)(s,{icon:R,disabled:!T,"aria-disabled":!T,onClick:y,variant:`text`,color:`error`,className:`sito-ui-dialog__close`,"aria-label":k}):null]}),L]})}),M??document.body)},y=e=>{let{primaryText:n,cancelText:i,onPrimaryClick:a,onCancel:s,isLoading:c=!1,loadingIndicator:l,disabled:u=!1,primaryType:d=`submit`,containerClassName:f,primaryClassName:p,cancelClassName:m,alignEnd:h=!1,primaryName:g,primaryAriaLabel:_,cancelName:v,cancelAriaLabel:y,extraActions:b=[]}=e;return(0,t.jsxs)(`div`,{"data-sito-ui":`dialog-actions`,className:r(`sito-ui-dialog-actions`,h&&`sito-ui-dialog-actions--end`,f),children:[(0,t.jsx)(o,{type:d,color:`primary`,variant:`submit`,className:p,disabled:u,loading:c,loadingIndicator:l,onClick:a,name:g,"aria-label":_,children:n}),b.map(({id:e,...n})=>(0,t.jsx)(o,{...n},e)),(0,t.jsx)(o,{type:`button`,variant:`outlined`,className:m,disabled:u||c,onClick:s,name:v,"aria-label":y,children:i})]})},b=(t=!1)=>{let[n,r]=(0,e.useState)(t);return{open:n,setOpen:r,handleClose:()=>r(!1),handleOpen:()=>r(!0)}};exports.Button=o,exports.Dialog=v,exports.DialogActions=y,exports.IconButton=s,exports.useDialog=b;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("react"),t=require("react/jsx-runtime"),n=require("react-dom");var r=(...e)=>e.filter(Boolean).join(` `),i={DEFAULT:`default`,PRIMARY:`primary`,SECONDARY:`secondary`,ERROR:`error`,WARNING:`warning`,SUCCESS:`success`,INFO:`info`},a={TEXT:`text`,SUBMIT:`submit`,OUTLINED:`outlined`},o={SM:`sm`,MD:`md`,LG:`lg`},s=(0,e.forwardRef)(function(e,n){let{color:s=i.DEFAULT,size:c=o.MD,type:l=`button`,variant:u=a.TEXT,loading:d=!1,loadingIndicator:f,loadingLabel:p=`Loading`,disabled:m,className:h,children:g,..._}=e,v=r(`sito-ui-button`,`sito-ui-button--${u}`,`sito-ui-button--${s}`,`sito-ui-button--${c}`,d&&`sito-ui-button--loading`,h),y=f===void 0?(0,t.jsx)(`span`,{className:`sito-ui-button__spinner`,"aria-hidden":`true`,"data-sito-ui":`button-spinner`}):f;return(0,t.jsxs)(`button`,{"data-sito-ui":`button`,..._,type:l,ref:n,disabled:m||d,"aria-busy":d||_[`aria-busy`],className:v,children:[d?(0,t.jsxs)(t.Fragment,{children:[y,(0,t.jsx)(`span`,{className:`sito-ui-button__loading-label`,children:p})]}):null,g]})}),c={SM:`sm`,MD:`md`,LG:`lg`},l=e=>{if(e!==void 0)return typeof e==`number`?`${e}px`:e},u=(0,e.forwardRef)(function(e,n){let{children:i,icon:a,iconClassName:o,type:u=`button`,variant:d=`text`,color:f=`default`,loading:p=!1,size:m=c.MD,iconSize:h,className:g,style:_,...v}=e,y=i!=null&&typeof i!=`boolean`,b=l(h),x=b===void 0?_:{..._,"--sito-ui-icon-button-icon-size":b},S=r(`sito-ui-icon-button`,`sito-ui-icon-button--${m}`,y&&`sito-ui-icon-button--with-content`,g);return(0,t.jsxs)(s,{...v,ref:n,type:u,variant:d,color:f,size:m,loading:p,"data-sito-ui":`icon-button`,className:S,style:x,children:[p?null:(0,t.jsx)(`span`,{className:r(`sito-ui-icon-button__icon`,o),"aria-hidden":`true`,children:a}),i]})}),d=`input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled])`,f=`button[type="submit"]:not([disabled]), input[type="submit"]:not([disabled])`,p=[`a[href]`,`button:not([disabled])`,`textarea:not([disabled])`,`input:not([disabled])`,`select:not([disabled])`,`[tabindex]:not([tabindex="-1"])`].join(`,`),m=0,h=null,g=()=>typeof document<`u`&&!!document.body,_=()=>{g()&&(m===0&&(h=document.body.style.overflow,document.body.style.overflow=`hidden`),m+=1)},v=()=>{!g()||m===0||(--m,m===0&&(document.body.style.overflow=h??``,h=null))},y=e=>Array.from(e.querySelectorAll(p)).filter(e=>e.getAttribute(`aria-disabled`)!==`true`),b=()=>typeof document>`u`?null:document.activeElement instanceof HTMLElement?document.activeElement:null,x=typeof window>`u`?e.useEffect:e.useLayoutEffect,S=i=>{let a=(0,e.useId)(),o=(0,e.useRef)(null),s=(0,e.useRef)(null),c=(0,e.useRef)(null),l=(0,e.useRef)(void 0),{dialogId:p,title:m,ariaLabel:h,children:g,onClose:S,initialFocus:C=`none`,closeOnBackdropClick:w=!1,closeOnEscape:T=!0,lockBodyScroll:E=!0,onSubmit:D,open:O=!1,mobileFullScreen:k=!1,containerClassName:A,className:j,closeLabel:M=`Close dialog`,closeIcon:N=`x`,showCloseButton:P=!0,portalContainer:F,exitDurationMs:I=0,onExitComplete:L}=i,[R,z]=(0,e.useState)(O),[B,V]=(0,e.useState)(!1),H=m?`${p??a}-title`:void 0,U=B?`closing`:`open`,W=O&&!B;(0,e.useEffect)(()=>{l.current=L},[L]);let G=(0,e.useCallback)(()=>{c.current!==null&&(window.clearTimeout(c.current),c.current=null)},[]),K=(0,e.useCallback)(()=>{z(!1),V(!1),l.current?.(),c.current=null},[]);x(()=>{if(O){G(),z(!0),V(!1);return}if(!R)return;let e=Math.max(0,I);if(e===0){G(),K();return}V(!0),G(),c.current=window.setTimeout(K,e)},[G,I,K,O,R]),(0,e.useEffect)(()=>()=>{G()},[G]);let q=(0,e.useCallback)(e=>{if(e.key===`Escape`&&W&&T){S();return}if(e.key!==`Tab`||!W)return;let t=o.current;if(!t)return;let n=y(t);if(n.length===0){e.preventDefault(),t.focus();return}let r=n[0],i=n[n.length-1],a=b(),s=!a||!t.contains(a);if(e.shiftKey&&(s||a===r)){e.preventDefault(),i.focus();return}!e.shiftKey&&(s||a===i)&&(e.preventDefault(),r.focus())},[T,W,S]);(0,e.useEffect)(()=>{if(!(!W||typeof window>`u`))return window.addEventListener(`keydown`,q),()=>{window.removeEventListener(`keydown`,q)}},[q,W]),x(()=>{if(O)return s.current=b(),()=>{s.current?.isConnected&&s.current.focus(),s.current=null}},[O]),x(()=>{if(!O)return;let e=o.current;if(e){if(C===`first-input`){let t=e.querySelector(d);if(t){t.focus();return}}if(C===`submit`){let t=e.querySelector(f);if(t){t.focus();return}}e.focus()}},[C,O]),(0,e.useEffect)(()=>{if(!(!R||!E))return _(),()=>{v()}},[E,R]);let J=(0,e.useCallback)(e=>{W&&w&&e.target===e.currentTarget&&S()},[w,W,S]),Y=(0,e.useCallback)(e=>{e.preventDefault(),D?.(e)},[D]);if(!R||typeof document>`u`)return null;let X=D?(0,t.jsx)(`form`,{onSubmit:Y,children:g}):g,Z=typeof N==`string`?(0,t.jsx)(`span`,{"aria-hidden":`true`,children:N}):N;return(0,n.createPortal)((0,t.jsx)(`div`,{id:p?`backdrop-${p}`:void 0,"data-sito-ui":`dialog-backdrop`,"data-state":U,onClick:J,className:r(`sito-ui-dialog-backdrop`,`sito-ui-dialog-backdrop--${U}`,A),children:(0,t.jsxs)(`div`,{id:p,ref:o,role:`dialog`,"aria-modal":`true`,"aria-label":m?void 0:h,"aria-labelledby":H,tabIndex:-1,"data-sito-ui":`dialog`,"data-state":U,className:r(`sito-ui-dialog`,`sito-ui-dialog--${U}`,k&&`sito-ui-dialog--mobile-full-screen`,j),children:[(0,t.jsxs)(`div`,{className:`sito-ui-dialog__header`,children:[m?(0,t.jsx)(`h3`,{id:H,className:`sito-ui-dialog__title`,children:m}):null,P?(0,t.jsx)(u,{icon:Z,disabled:!W,"aria-disabled":!W,onClick:S,variant:`text`,color:`error`,className:`sito-ui-dialog__close`,"aria-label":M}):null]}),X]})}),F??document.body)},C=e=>{let{primaryText:n,cancelText:i,onPrimaryClick:a,onCancel:o,isLoading:c=!1,loadingIndicator:l,disabled:u=!1,primaryType:d=`submit`,containerClassName:f,primaryClassName:p,cancelClassName:m,alignEnd:h=!1,primaryName:g,primaryAriaLabel:_,cancelName:v,cancelAriaLabel:y,extraActions:b=[]}=e;return(0,t.jsxs)(`div`,{"data-sito-ui":`dialog-actions`,className:r(`sito-ui-dialog-actions`,h&&`sito-ui-dialog-actions--end`,f),children:[(0,t.jsx)(s,{type:d,color:`primary`,variant:`submit`,className:p,disabled:u,loading:c,loadingIndicator:l,onClick:a,name:g,"aria-label":_,children:n}),b.map(({id:e,...n})=>(0,t.jsx)(s,{...n},e)),(0,t.jsx)(s,{type:`button`,variant:`outlined`,className:m,disabled:u||c,onClick:o,name:v,"aria-label":y,children:i})]})},w=(t=!1)=>{let[n,r]=(0,e.useState)(t);return{open:n,setOpen:r,handleClose:()=>r(!1),handleOpen:()=>r(!0)}};exports.Button=s,exports.Dialog=S,exports.DialogActions=C,exports.IconButton=u,exports.useDialog=w;
package/dist/ui.js CHANGED
@@ -1,8 +1,8 @@
1
- import { forwardRef as e, useCallback as t, useEffect as n, useId as r, useRef as i, useState as a } from "react";
2
- import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
3
- import { createPortal as l } from "react-dom";
1
+ import { forwardRef as e, useCallback as t, useEffect as n, useId as r, useLayoutEffect as i, useRef as a, useState as o } from "react";
2
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
3
+ import { createPortal as u } from "react-dom";
4
4
  //#region src/utils/classNames.ts
5
- var u = (...e) => e.filter(Boolean).join(" "), d = {
5
+ var d = (...e) => e.filter(Boolean).join(" "), f = {
6
6
  DEFAULT: "default",
7
7
  PRIMARY: "primary",
8
8
  SECONDARY: "secondary",
@@ -10,103 +10,148 @@ var u = (...e) => e.filter(Boolean).join(" "), d = {
10
10
  WARNING: "warning",
11
11
  SUCCESS: "success",
12
12
  INFO: "info"
13
- }, f = {
13
+ }, p = {
14
14
  TEXT: "text",
15
15
  SUBMIT: "submit",
16
16
  OUTLINED: "outlined"
17
- }, p = e(function(e, t) {
18
- let { color: n = d.DEFAULT, type: r = "button", variant: i = f.TEXT, loading: a = !1, loadingIndicator: l, loadingLabel: p = "Loading", disabled: m, className: h, children: g, ..._ } = e, v = u("sito-ui-button", `sito-ui-button--${i}`, `sito-ui-button--${n}`, a && "sito-ui-button--loading", h), y = l === void 0 ? /* @__PURE__ */ s("span", {
17
+ }, m = {
18
+ SM: "sm",
19
+ MD: "md",
20
+ LG: "lg"
21
+ }, h = e(function(e, t) {
22
+ let { color: n = f.DEFAULT, size: r = m.MD, type: i = "button", variant: a = p.TEXT, loading: o = !1, loadingIndicator: u, loadingLabel: h = "Loading", disabled: g, className: _, children: v, ...y } = e, b = d("sito-ui-button", `sito-ui-button--${a}`, `sito-ui-button--${n}`, `sito-ui-button--${r}`, o && "sito-ui-button--loading", _), x = u === void 0 ? /* @__PURE__ */ c("span", {
19
23
  className: "sito-ui-button__spinner",
20
24
  "aria-hidden": "true",
21
25
  "data-sito-ui": "button-spinner"
22
- }) : l;
23
- return /* @__PURE__ */ c("button", {
26
+ }) : u;
27
+ return /* @__PURE__ */ l("button", {
24
28
  "data-sito-ui": "button",
25
- ..._,
26
- type: r,
29
+ ...y,
30
+ type: i,
27
31
  ref: t,
28
- disabled: m || a,
29
- "aria-busy": a || _["aria-busy"],
30
- className: v,
31
- children: [a ? /* @__PURE__ */ c(o, { children: [y, /* @__PURE__ */ s("span", {
32
+ disabled: g || o,
33
+ "aria-busy": o || y["aria-busy"],
34
+ className: b,
35
+ children: [o ? /* @__PURE__ */ l(s, { children: [x, /* @__PURE__ */ c("span", {
32
36
  className: "sito-ui-button__loading-label",
33
- children: p
34
- })] }) : null, g]
37
+ children: h
38
+ })] }) : null, v]
35
39
  });
36
- }), m = e(function(e, t) {
37
- let { children: n, icon: r, iconClassName: i, type: a = "button", variant: o = "text", color: l = "default", loading: d = !1, className: f, ...m } = e, h = u("sito-ui-icon-button", f);
38
- return /* @__PURE__ */ c(p, {
39
- ...m,
40
+ }), g = {
41
+ SM: "sm",
42
+ MD: "md",
43
+ LG: "lg"
44
+ }, _ = (e) => {
45
+ if (e !== void 0) return typeof e == "number" ? `${e}px` : e;
46
+ }, v = e(function(e, t) {
47
+ let { children: n, icon: r, iconClassName: i, type: a = "button", variant: o = "text", color: s = "default", loading: u = !1, size: f = g.MD, iconSize: p, className: m, style: v, ...y } = e, b = n != null && typeof n != "boolean", x = _(p), S = x === void 0 ? v : {
48
+ ...v,
49
+ "--sito-ui-icon-button-icon-size": x
50
+ }, C = d("sito-ui-icon-button", `sito-ui-icon-button--${f}`, b && "sito-ui-icon-button--with-content", m);
51
+ return /* @__PURE__ */ l(h, {
52
+ ...y,
40
53
  ref: t,
41
54
  type: a,
42
55
  variant: o,
43
- color: l,
44
- loading: d,
56
+ color: s,
57
+ size: f,
58
+ loading: u,
45
59
  "data-sito-ui": "icon-button",
46
- className: h,
47
- children: [d ? null : /* @__PURE__ */ s("span", {
48
- className: i,
60
+ className: C,
61
+ style: S,
62
+ children: [u ? null : /* @__PURE__ */ c("span", {
63
+ className: d("sito-ui-icon-button__icon", i),
49
64
  "aria-hidden": "true",
50
65
  children: r
51
66
  }), n]
52
67
  });
53
- }), h = "input:not([type=\"hidden\"]):not([disabled]), textarea:not([disabled]), select:not([disabled])", g = "button[type=\"submit\"]:not([disabled]), input[type=\"submit\"]:not([disabled])", _ = [
68
+ }), y = "input:not([type=\"hidden\"]):not([disabled]), textarea:not([disabled]), select:not([disabled])", b = "button[type=\"submit\"]:not([disabled]), input[type=\"submit\"]:not([disabled])", x = [
54
69
  "a[href]",
55
70
  "button:not([disabled])",
56
71
  "textarea:not([disabled])",
57
72
  "input:not([disabled])",
58
73
  "select:not([disabled])",
59
74
  "[tabindex]:not([tabindex=\"-1\"])"
60
- ].join(","), v = 0, y = null, b = () => typeof document < "u" && !!document.body, x = () => {
61
- b() && (v === 0 && (y = document.body.style.overflow, document.body.style.overflow = "hidden"), v += 1);
62
- }, S = () => {
63
- !b() || v === 0 || (--v, v === 0 && (document.body.style.overflow = y ?? "", y = null));
64
- }, C = (e) => Array.from(e.querySelectorAll(_)).filter((e) => e.getAttribute("aria-disabled") !== "true"), w = () => typeof document > "u" ? null : document.activeElement instanceof HTMLElement ? document.activeElement : null, T = (e) => {
65
- let a = r(), o = i(null), d = i(null), { dialogId: f, title: p, ariaLabel: _, children: v, onClose: y, initialFocus: b = "none", closeOnBackdropClick: T = !1, closeOnEscape: E = !0, lockBodyScroll: D = !0, onSubmit: O, open: k = !1, mobileFullScreen: A = !1, containerClassName: j, className: M, closeLabel: N = "Close dialog", closeIcon: P = "x", showCloseButton: F = !0, portalContainer: I } = e, L = p ? `${f ?? a}-title` : void 0, R = t((e) => {
66
- if (e.key === "Escape" && k && E) {
67
- y();
75
+ ].join(","), S = 0, C = null, w = () => typeof document < "u" && !!document.body, T = () => {
76
+ w() && (S === 0 && (C = document.body.style.overflow, document.body.style.overflow = "hidden"), S += 1);
77
+ }, E = () => {
78
+ !w() || S === 0 || (--S, S === 0 && (document.body.style.overflow = C ?? "", C = null));
79
+ }, D = (e) => Array.from(e.querySelectorAll(x)).filter((e) => e.getAttribute("aria-disabled") !== "true"), O = () => typeof document > "u" ? null : document.activeElement instanceof HTMLElement ? document.activeElement : null, k = typeof window > "u" ? n : i, A = (e) => {
80
+ let i = r(), s = a(null), f = a(null), p = a(null), m = a(void 0), { dialogId: h, title: g, ariaLabel: _, children: x, onClose: S, initialFocus: C = "none", closeOnBackdropClick: w = !1, closeOnEscape: A = !0, lockBodyScroll: j = !0, onSubmit: M, open: N = !1, mobileFullScreen: P = !1, containerClassName: F, className: I, closeLabel: L = "Close dialog", closeIcon: R = "x", showCloseButton: z = !0, portalContainer: B, exitDurationMs: V = 0, onExitComplete: H } = e, [U, W] = o(N), [G, K] = o(!1), q = g ? `${h ?? i}-title` : void 0, J = G ? "closing" : "open", Y = N && !G;
81
+ n(() => {
82
+ m.current = H;
83
+ }, [H]);
84
+ let X = t(() => {
85
+ p.current !== null && (window.clearTimeout(p.current), p.current = null);
86
+ }, []), Z = t(() => {
87
+ W(!1), K(!1), m.current?.(), p.current = null;
88
+ }, []);
89
+ k(() => {
90
+ if (N) {
91
+ X(), W(!0), K(!1);
92
+ return;
93
+ }
94
+ if (!U) return;
95
+ let e = Math.max(0, V);
96
+ if (e === 0) {
97
+ X(), Z();
68
98
  return;
69
99
  }
70
- if (e.key !== "Tab" || !k) return;
71
- let t = o.current;
100
+ K(!0), X(), p.current = window.setTimeout(Z, e);
101
+ }, [
102
+ X,
103
+ V,
104
+ Z,
105
+ N,
106
+ U
107
+ ]), n(() => () => {
108
+ X();
109
+ }, [X]);
110
+ let Q = t((e) => {
111
+ if (e.key === "Escape" && Y && A) {
112
+ S();
113
+ return;
114
+ }
115
+ if (e.key !== "Tab" || !Y) return;
116
+ let t = s.current;
72
117
  if (!t) return;
73
- let n = C(t);
118
+ let n = D(t);
74
119
  if (n.length === 0) {
75
120
  e.preventDefault(), t.focus();
76
121
  return;
77
122
  }
78
- let r = n[0], i = n[n.length - 1], a = w(), s = !a || !t.contains(a);
79
- if (e.shiftKey && (s || a === r)) {
123
+ let r = n[0], i = n[n.length - 1], a = O(), o = !a || !t.contains(a);
124
+ if (e.shiftKey && (o || a === r)) {
80
125
  e.preventDefault(), i.focus();
81
126
  return;
82
127
  }
83
- !e.shiftKey && (s || a === i) && (e.preventDefault(), r.focus());
128
+ !e.shiftKey && (o || a === i) && (e.preventDefault(), r.focus());
84
129
  }, [
85
- E,
86
- y,
87
- k
130
+ A,
131
+ Y,
132
+ S
88
133
  ]);
89
134
  n(() => {
90
- if (!(!k || typeof window > "u")) return window.addEventListener("keydown", R), () => {
91
- window.removeEventListener("keydown", R);
135
+ if (!(!Y || typeof window > "u")) return window.addEventListener("keydown", Q), () => {
136
+ window.removeEventListener("keydown", Q);
92
137
  };
93
- }, [R, k]), n(() => {
94
- if (k) return d.current = w(), () => {
95
- d.current?.isConnected && d.current.focus(), d.current = null;
138
+ }, [Q, Y]), k(() => {
139
+ if (N) return f.current = O(), () => {
140
+ f.current?.isConnected && f.current.focus(), f.current = null;
96
141
  };
97
- }, [k]), n(() => {
98
- if (!k) return;
99
- let e = o.current;
142
+ }, [N]), k(() => {
143
+ if (!N) return;
144
+ let e = s.current;
100
145
  if (e) {
101
- if (b === "first-input") {
102
- let t = e.querySelector(h);
146
+ if (C === "first-input") {
147
+ let t = e.querySelector(y);
103
148
  if (t) {
104
149
  t.focus();
105
150
  return;
106
151
  }
107
152
  }
108
- if (b === "submit") {
109
- let t = e.querySelector(g);
153
+ if (C === "submit") {
154
+ let t = e.querySelector(b);
110
155
  if (t) {
111
156
  t.focus();
112
157
  return;
@@ -114,70 +159,76 @@ var u = (...e) => e.filter(Boolean).join(" "), d = {
114
159
  }
115
160
  e.focus();
116
161
  }
117
- }, [b, k]), n(() => {
118
- if (!(!k || !D)) return x(), () => {
119
- S();
162
+ }, [C, N]), n(() => {
163
+ if (!(!U || !j)) return T(), () => {
164
+ E();
120
165
  };
121
- }, [k, D]);
122
- let z = t((e) => {
123
- T && e.target === e.currentTarget && y();
124
- }, [T, y]), B = t((e) => {
125
- e.preventDefault(), O?.(e);
126
- }, [O]);
127
- if (!k || typeof document > "u") return null;
128
- let V = O ? /* @__PURE__ */ s("form", {
129
- onSubmit: B,
130
- children: v
131
- }) : v, H = typeof P == "string" ? /* @__PURE__ */ s("span", {
166
+ }, [j, U]);
167
+ let $ = t((e) => {
168
+ Y && w && e.target === e.currentTarget && S();
169
+ }, [
170
+ w,
171
+ Y,
172
+ S
173
+ ]), ee = t((e) => {
174
+ e.preventDefault(), M?.(e);
175
+ }, [M]);
176
+ if (!U || typeof document > "u") return null;
177
+ let te = M ? /* @__PURE__ */ c("form", {
178
+ onSubmit: ee,
179
+ children: x
180
+ }) : x, ne = typeof R == "string" ? /* @__PURE__ */ c("span", {
132
181
  "aria-hidden": "true",
133
- children: P
134
- }) : P;
135
- return l(/* @__PURE__ */ s("div", {
136
- id: f ? `backdrop-${f}` : void 0,
182
+ children: R
183
+ }) : R;
184
+ return u(/* @__PURE__ */ c("div", {
185
+ id: h ? `backdrop-${h}` : void 0,
137
186
  "data-sito-ui": "dialog-backdrop",
138
- onClick: z,
139
- className: u("sito-ui-dialog-backdrop", j),
140
- children: /* @__PURE__ */ c("div", {
141
- id: f,
142
- ref: o,
187
+ "data-state": J,
188
+ onClick: $,
189
+ className: d("sito-ui-dialog-backdrop", `sito-ui-dialog-backdrop--${J}`, F),
190
+ children: /* @__PURE__ */ l("div", {
191
+ id: h,
192
+ ref: s,
143
193
  role: "dialog",
144
194
  "aria-modal": "true",
145
- "aria-label": p ? void 0 : _,
146
- "aria-labelledby": L,
195
+ "aria-label": g ? void 0 : _,
196
+ "aria-labelledby": q,
147
197
  tabIndex: -1,
148
198
  "data-sito-ui": "dialog",
149
- className: u("sito-ui-dialog", A && "sito-ui-dialog--mobile-full-screen", M),
150
- children: [/* @__PURE__ */ c("div", {
199
+ "data-state": J,
200
+ className: d("sito-ui-dialog", `sito-ui-dialog--${J}`, P && "sito-ui-dialog--mobile-full-screen", I),
201
+ children: [/* @__PURE__ */ l("div", {
151
202
  className: "sito-ui-dialog__header",
152
- children: [p ? /* @__PURE__ */ s("h3", {
153
- id: L,
203
+ children: [g ? /* @__PURE__ */ c("h3", {
204
+ id: q,
154
205
  className: "sito-ui-dialog__title",
155
- children: p
156
- }) : null, F ? /* @__PURE__ */ s(m, {
157
- icon: H,
158
- disabled: !k,
159
- "aria-disabled": !k,
160
- onClick: y,
206
+ children: g
207
+ }) : null, z ? /* @__PURE__ */ c(v, {
208
+ icon: ne,
209
+ disabled: !Y,
210
+ "aria-disabled": !Y,
211
+ onClick: S,
161
212
  variant: "text",
162
213
  color: "error",
163
214
  className: "sito-ui-dialog__close",
164
- "aria-label": N
215
+ "aria-label": L
165
216
  }) : null]
166
- }), V]
217
+ }), te]
167
218
  })
168
- }), I ?? document.body);
169
- }, E = (e) => {
170
- let { primaryText: t, cancelText: n, onPrimaryClick: r, onCancel: i, isLoading: a = !1, loadingIndicator: o, disabled: l = !1, primaryType: d = "submit", containerClassName: f, primaryClassName: m, cancelClassName: h, alignEnd: g = !1, primaryName: _, primaryAriaLabel: v, cancelName: y, cancelAriaLabel: b, extraActions: x = [] } = e;
171
- return /* @__PURE__ */ c("div", {
219
+ }), B ?? document.body);
220
+ }, j = (e) => {
221
+ let { primaryText: t, cancelText: n, onPrimaryClick: r, onCancel: i, isLoading: a = !1, loadingIndicator: o, disabled: s = !1, primaryType: u = "submit", containerClassName: f, primaryClassName: p, cancelClassName: m, alignEnd: g = !1, primaryName: _, primaryAriaLabel: v, cancelName: y, cancelAriaLabel: b, extraActions: x = [] } = e;
222
+ return /* @__PURE__ */ l("div", {
172
223
  "data-sito-ui": "dialog-actions",
173
- className: u("sito-ui-dialog-actions", g && "sito-ui-dialog-actions--end", f),
224
+ className: d("sito-ui-dialog-actions", g && "sito-ui-dialog-actions--end", f),
174
225
  children: [
175
- /* @__PURE__ */ s(p, {
176
- type: d,
226
+ /* @__PURE__ */ c(h, {
227
+ type: u,
177
228
  color: "primary",
178
229
  variant: "submit",
179
- className: m,
180
- disabled: l,
230
+ className: p,
231
+ disabled: s,
181
232
  loading: a,
182
233
  loadingIndicator: o,
183
234
  onClick: r,
@@ -185,12 +236,12 @@ var u = (...e) => e.filter(Boolean).join(" "), d = {
185
236
  "aria-label": v,
186
237
  children: t
187
238
  }),
188
- x.map(({ id: e, ...t }) => /* @__PURE__ */ s(p, { ...t }, e)),
189
- /* @__PURE__ */ s(p, {
239
+ x.map(({ id: e, ...t }) => /* @__PURE__ */ c(h, { ...t }, e)),
240
+ /* @__PURE__ */ c(h, {
190
241
  type: "button",
191
242
  variant: "outlined",
192
- className: h,
193
- disabled: l || a,
243
+ className: m,
244
+ disabled: s || a,
194
245
  onClick: i,
195
246
  name: y,
196
247
  "aria-label": b,
@@ -198,8 +249,8 @@ var u = (...e) => e.filter(Boolean).join(" "), d = {
198
249
  })
199
250
  ]
200
251
  });
201
- }, D = (e = !1) => {
202
- let [t, n] = a(e);
252
+ }, M = (e = !1) => {
253
+ let [t, n] = o(e);
203
254
  return {
204
255
  open: t,
205
256
  setOpen: n,
@@ -208,4 +259,4 @@ var u = (...e) => e.filter(Boolean).join(" "), d = {
208
259
  };
209
260
  };
210
261
  //#endregion
211
- export { p as Button, T as Dialog, E as DialogActions, m as IconButton, D as useDialog };
262
+ export { h as Button, A as Dialog, j as DialogActions, v as IconButton, M as useDialog };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sito/ui",
3
3
  "private": false,
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.34.4",
7
7
  "files": [
@@ -32,7 +32,11 @@
32
32
  "lint": "oxlint --type-aware --max-warnings 0",
33
33
  "lint:fix": "oxlint --type-aware --fix --max-warnings 0",
34
34
  "format": "prettier . --write",
35
- "preview": "vite preview"
35
+ "preview": "vite preview",
36
+ "storybook": "storybook dev -p 6006",
37
+ "build-storybook": "storybook build",
38
+ "test": "vitest",
39
+ "test:run": "vitest run"
36
40
  },
37
41
  "engines": {
38
42
  "node": "^20.19.0 || ^22.13.0 || >=24"
@@ -64,19 +68,27 @@
64
68
  }
65
69
  },
66
70
  "devDependencies": {
71
+ "@storybook/addon-docs": "10.4.6",
72
+ "@storybook/react-vite": "10.4.6",
73
+ "@testing-library/jest-dom": "6.9.1",
74
+ "@testing-library/react": "16.3.2",
75
+ "@testing-library/user-event": "14.6.1",
67
76
  "@types/node": "26.1.1",
68
77
  "@types/react": "19.2.17",
69
78
  "@types/react-dom": "19.2.3",
70
79
  "@typescript/typescript6": "^6.0.2",
71
80
  "@vitejs/plugin-react": "6.0.3",
72
81
  "autoprefixer": "10.5.2",
82
+ "jsdom": "29.1.1",
73
83
  "oxlint": "1.73.0",
74
84
  "oxlint-tsgolint": "0.24.0",
75
- "prettier": "3.9.4",
85
+ "prettier": "3.9.5",
76
86
  "react": "19.2.7",
77
87
  "react-dom": "19.2.7",
88
+ "storybook": "10.4.6",
78
89
  "typescript": "7.0.2",
79
90
  "vite": "8.1.4",
80
- "vite-plugin-dts": "5.0.3"
91
+ "vite-plugin-dts": "5.0.3",
92
+ "vitest": "4.1.10"
81
93
  }
82
94
  }