@sito/ui 0.2.0 → 0.3.1

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,65 @@ 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`; their default icon sizes
53
+ are `16px`, `20px`, and `24px`. Override a specific token
54
+ (`--sito-ui-size-icon-button-icon-sm`, `-md`, or `-lg`) for theme-wide changes,
55
+ or use `iconSize` / `--sito-ui-icon-button-icon-size` for one button.
56
+
57
+ ## Development
58
+
59
+ Run the component test suite with:
60
+
61
+ ```sh
62
+ pnpm test:run
63
+ ```
64
+
65
+ Start Storybook with:
66
+
67
+ ```sh
68
+ pnpm storybook
69
+ ```
70
+
71
+ ## Dialog Exit Transitions
72
+
73
+ `Dialog` unmounts immediately by default. Pass `exitDurationMs` when a consumer
74
+ needs to keep the portal mounted long enough for a CSS exit animation:
75
+
76
+ ```tsx
77
+ <Dialog open={open} onClose={close} exitDurationMs={220}>
78
+ Dialog content
79
+ </Dialog>
80
+ ```
81
+
82
+ During that delay, the backdrop and dialog expose `data-state="closing"` plus
83
+ `sito-ui-dialog-backdrop--closing` and `sito-ui-dialog--closing` classes.
84
+ Use those hooks from consumer CSS to define the actual animation.
28
85
 
29
86
  ## Scope
30
87
 
@@ -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,23 @@
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-sm: 1rem;
56
+ --sito-ui-size-icon-button-icon-md: 1.25rem;
57
+ --sito-ui-size-icon-button-icon-lg: 1.5rem;
58
+ --sito-ui-size-icon-button-icon: var(--sito-ui-size-icon-button-icon-md);
47
59
  --sito-ui-size-button-spinner: 1em;
48
60
 
49
61
  --sito-ui-radius-pill: 1.5rem;
@@ -55,10 +67,8 @@
55
67
 
56
68
  --sito-ui-font-weight-semibold: 600;
57
69
  --sito-ui-font-size-button: 0.875rem;
58
- --sito-ui-font-size-icon-button: 1.25rem;
59
70
  --sito-ui-font-size-dialog-title: 1.25rem;
60
71
  --sito-ui-line-height-button: 1.25rem;
61
- --sito-ui-line-height-icon-button: 1.75rem;
62
72
  --sito-ui-line-height-dialog-title: 1.75rem;
63
73
 
64
74
  --sito-ui-motion-duration-normal: 300ms;
@@ -80,14 +90,20 @@
80
90
  --sito-ui-button-light: var(--sito-ui-color-default-light);
81
91
  --sito-ui-button-default: var(--sito-ui-color-default-default);
82
92
  --sito-ui-button-hover: var(--sito-ui-color-default-hover);
93
+ --sito-ui-button-height: var(--sito-ui-size-button-md, 40px);
94
+ --sito-ui-button-padding-block: var(--sito-ui-space-2);
95
+ --sito-ui-button-padding-inline: var(--sito-ui-space-4);
83
96
 
84
97
  display: flex;
98
+ box-sizing: border-box;
85
99
  gap: var(--sito-ui-space-2);
86
100
  font-weight: var(--sito-ui-font-weight-semibold);
87
101
  cursor: default;
88
102
  align-items: center;
89
103
  justify-content: center;
90
- padding: var(--sito-ui-space-2) var(--sito-ui-space-4);
104
+ height: var(--sito-ui-button-height);
105
+ padding: var(--sito-ui-button-padding-block)
106
+ var(--sito-ui-button-padding-inline);
91
107
  border-radius: var(--sito-ui-radius-pill);
92
108
  border: var(--sito-ui-border-width-thin) solid transparent;
93
109
  background-color: transparent;
@@ -101,6 +117,24 @@
101
117
  transition-timing-function: var(--sito-ui-motion-easing-standard);
102
118
  }
103
119
 
120
+ .sito-ui-button--sm {
121
+ --sito-ui-button-height: var(--sito-ui-size-button-sm, 32px);
122
+ --sito-ui-button-padding-block: var(--sito-ui-space-1);
123
+ --sito-ui-button-padding-inline: var(--sito-ui-space-3);
124
+ }
125
+
126
+ .sito-ui-button--md {
127
+ --sito-ui-button-height: var(--sito-ui-size-button-md, 40px);
128
+ --sito-ui-button-padding-block: var(--sito-ui-space-2);
129
+ --sito-ui-button-padding-inline: var(--sito-ui-space-4);
130
+ }
131
+
132
+ .sito-ui-button--lg {
133
+ --sito-ui-button-height: var(--sito-ui-size-button-lg, 48px);
134
+ --sito-ui-button-padding-block: var(--sito-ui-space-3);
135
+ --sito-ui-button-padding-inline: var(--sito-ui-space-5);
136
+ }
137
+
104
138
  .sito-ui-button:enabled:not([aria-disabled="true"]) {
105
139
  cursor: pointer;
106
140
  }
@@ -240,16 +274,55 @@
240
274
  }
241
275
 
242
276
  .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);
277
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-md);
278
+ --sito-ui-icon-button-icon-size: var(--sito-ui-size-icon-button-icon);
279
+ --sito-ui-size-button-spinner: var(--sito-ui-icon-button-icon-size);
280
+
281
+ box-sizing: border-box;
282
+ min-width: var(--sito-ui-icon-button-container-size);
283
+ min-height: var(--sito-ui-icon-button-container-size);
284
+ width: var(--sito-ui-icon-button-container-size);
285
+ height: var(--sito-ui-icon-button-container-size);
247
286
  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
287
  padding: var(--sito-ui-space-0);
251
288
  }
252
289
 
290
+ .sito-ui-icon-button--sm {
291
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-sm);
292
+ --sito-ui-icon-button-icon-size: var(--sito-ui-size-icon-button-icon-sm);
293
+ }
294
+
295
+ .sito-ui-icon-button--md {
296
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-md);
297
+ --sito-ui-icon-button-icon-size: var(--sito-ui-size-icon-button-icon-md);
298
+ }
299
+
300
+ .sito-ui-icon-button--lg {
301
+ --sito-ui-icon-button-container-size: var(--sito-ui-size-icon-button-lg);
302
+ --sito-ui-icon-button-icon-size: var(--sito-ui-size-icon-button-icon-lg);
303
+ }
304
+
305
+ .sito-ui-icon-button--with-content {
306
+ width: auto;
307
+ height: auto;
308
+ padding: var(--sito-ui-button-padding-block)
309
+ var(--sito-ui-button-padding-inline);
310
+ border-radius: var(--sito-ui-radius-pill);
311
+ font-size: var(--sito-ui-font-size-button);
312
+ line-height: var(--sito-ui-line-height-button);
313
+ }
314
+
315
+ .sito-ui-icon-button__icon {
316
+ display: inline-flex;
317
+ flex: 0 0 auto;
318
+ align-items: center;
319
+ justify-content: center;
320
+ width: var(--sito-ui-icon-button-icon-size);
321
+ height: var(--sito-ui-icon-button-icon-size);
322
+ font-size: var(--sito-ui-icon-button-icon-size);
323
+ line-height: 1;
324
+ }
325
+
253
326
  .sito-ui-dialog-backdrop {
254
327
  position: fixed;
255
328
  inset: 0;
@@ -264,6 +337,10 @@
264
337
  backdrop-filter: var(--sito-ui-dialog-backdrop-filter);
265
338
  }
266
339
 
340
+ .sito-ui-dialog-backdrop--closing {
341
+ pointer-events: none;
342
+ }
343
+
267
344
  .sito-ui-dialog {
268
345
  position: relative;
269
346
  display: flex;
package/dist/theme.css CHANGED
@@ -39,11 +39,23 @@
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-sm: 1rem;
56
+ --sito-ui-size-icon-button-icon-md: 1.25rem;
57
+ --sito-ui-size-icon-button-icon-lg: 1.5rem;
58
+ --sito-ui-size-icon-button-icon: var(--sito-ui-size-icon-button-icon-md);
47
59
  --sito-ui-size-button-spinner: 1em;
48
60
 
49
61
  --sito-ui-radius-pill: 1.5rem;
@@ -55,10 +67,8 @@
55
67
 
56
68
  --sito-ui-font-weight-semibold: 600;
57
69
  --sito-ui-font-size-button: 0.875rem;
58
- --sito-ui-font-size-icon-button: 1.25rem;
59
70
  --sito-ui-font-size-dialog-title: 1.25rem;
60
71
  --sito-ui-line-height-button: 1.25rem;
61
- --sito-ui-line-height-icon-button: 1.75rem;
62
72
  --sito-ui-line-height-dialog-title: 1.75rem;
63
73
 
64
74
  --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.1",
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
  }