@versini/ui-button 6.0.8 → 7.0.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
@@ -1,3 +1,218 @@
1
1
  # @versini/ui-button
2
2
 
3
- This is a button component.
3
+ [![npm version](https://img.shields.io/npm/v/@versini/ui-button?style=flat-square)](https://www.npmjs.com/package/@versini/ui-button)
4
+
5
+ > A comprehensive collection of accessible React button components built with TypeScript and TailwindCSS.
6
+
7
+ The Button package provides a complete set of button components including standard buttons, icon buttons, link buttons, and copy-to-clipboard buttons. All components are fully accessible, keyboard navigable, and support multiple themes and variants.
8
+
9
+ ## Table of Contents
10
+
11
+ - [Features](#features)
12
+ - [Installation](#installation)
13
+ - [Usage](#usage)
14
+ - [API](#api)
15
+
16
+ ## Features
17
+
18
+ - **🎯 Multiple Button Types**: Button, ButtonIcon, ButtonLink, ButtonCopy
19
+ - **♿ Accessible**: WCAG compliant with proper ARIA support and keyboard navigation
20
+ - **🎨 Customizable**: Multiple variants, sizes, and styling options
21
+ - **🌲 Tree-shakeable**: Import only the components you need
22
+ - **🔧 TypeScript**: Fully typed with comprehensive prop definitions
23
+ - **🎭 Theme Support**: Built-in support for light, dark, and system themes
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ npm install @versini/ui-button
29
+ ```
30
+
31
+ > **Note**: This component requires TailwindCSS and the `@versini/ui-styles` plugin for proper styling. See the [root README](../../README.md#tailwindcss-setup) for complete setup instructions.
32
+
33
+ ## Usage
34
+
35
+ ### Basic Button
36
+
37
+ ```tsx
38
+ import { Button } from "@versini/ui-button";
39
+
40
+ function App() {
41
+ return (
42
+ <Button variant="primary" onClick={() => console.log("Button clicked!")}>
43
+ Click me
44
+ </Button>
45
+ );
46
+ }
47
+ ```
48
+
49
+ ### Button with Icon
50
+
51
+ ```tsx
52
+ import { ButtonIcon } from "@versini/ui-button";
53
+ import { IconSettings } from "@versini/ui-icons";
54
+
55
+ function App() {
56
+ return (
57
+ <ButtonIcon
58
+ label="Settings"
59
+ onClick={() => console.log("Settings clicked!")}
60
+ >
61
+ <IconSettings />
62
+ </ButtonIcon>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ### Link Button
68
+
69
+ ```tsx
70
+ import { ButtonLink } from "@versini/ui-button";
71
+
72
+ function App() {
73
+ return (
74
+ <ButtonLink href="https://example.com" target="_blank" variant="secondary">
75
+ Visit Website
76
+ </ButtonLink>
77
+ );
78
+ }
79
+ ```
80
+
81
+ ### Copy Button
82
+
83
+ ```tsx
84
+ import { ButtonCopy } from "@versini/ui-button";
85
+
86
+ function App() {
87
+ return <ButtonCopy copyToClipboard="Hello, World!" labelLeft="Copy" />;
88
+ }
89
+ ```
90
+
91
+ ### Different Variants
92
+
93
+ ```tsx
94
+ import { Button } from "@versini/ui-button";
95
+
96
+ function VariantExamples() {
97
+ return (
98
+ <div className="space-x-2">
99
+ <Button variant="primary">Primary</Button>
100
+ <Button variant="secondary">Secondary</Button>
101
+ <Button variant="danger">Danger</Button>
102
+ <Button variant="selected">Selected</Button>
103
+ </div>
104
+ );
105
+ }
106
+ ```
107
+
108
+ ### Different Sizes
109
+
110
+ ```tsx
111
+ import { Button } from "@versini/ui-button";
112
+
113
+ function SizeExamples() {
114
+ return (
115
+ <div className="space-x-2">
116
+ <Button size="small">Small</Button>
117
+ <Button size="medium">Medium</Button>
118
+ <Button size="large">Large</Button>
119
+ </div>
120
+ );
121
+ }
122
+ ```
123
+
124
+ ### Icon Button with Labels
125
+
126
+ ```tsx
127
+ import { ButtonIcon } from "@versini/ui-button";
128
+ import { IconUser, IconSettings, IconSave } from "@versini/ui-icons";
129
+
130
+ function IconButtonExamples() {
131
+ return (
132
+ <div className="space-x-2">
133
+ <ButtonIcon label="User profile">
134
+ <IconUser />
135
+ </ButtonIcon>
136
+
137
+ <ButtonIcon labelLeft="Save document">
138
+ <IconSave />
139
+ </ButtonIcon>
140
+
141
+ <ButtonIcon labelRight="Settings">
142
+ <IconSettings />
143
+ </ButtonIcon>
144
+ </div>
145
+ );
146
+ }
147
+ ```
148
+
149
+ ### Theme Modes
150
+
151
+ ```tsx
152
+ import { Button } from "@versini/ui-button";
153
+
154
+ function ThemeExamples() {
155
+ return (
156
+ <div className="space-x-2">
157
+ <Button mode="light">Light Mode</Button>
158
+ <Button mode="dark">Dark Mode</Button>
159
+ <Button mode="system">System Mode</Button>
160
+ </div>
161
+ );
162
+ }
163
+ ```
164
+
165
+ ## API
166
+
167
+ ### Button Props
168
+
169
+ | Prop | Type | Default | Description |
170
+ | --------- | ---------------------------------------------------- | ----------- | -------------------------------------------------- |
171
+ | children | `React.ReactNode` | - | The text to render in the button |
172
+ | variant | `"primary" \| "secondary" \| "danger" \| "selected"` | `"primary"` | The variant style of the Button |
173
+ | size | `"small" \| "medium" \| "large"` | `"medium"` | The size of the Button |
174
+ | disabled | `boolean` | `false` | Whether or not the Button is disabled |
175
+ | fullWidth | `boolean` | `false` | Whether or not the Button is full width |
176
+ | mode | `"dark" \| "light" \| "system" \| "alt-system"` | `"system"` | The mode of Button |
177
+ | focusMode | `"dark" \| "light" \| "system" \| "alt-system"` | `"system"` | The type of focus for the Button |
178
+ | noBorder | `boolean` | `false` | Whether or not to render the Button with a border |
179
+ | raw | `boolean` | `false` | Whether or not to render the Button with styles |
180
+ | radius | `"small" \| "medium" \| "large"` | `"large"` | The rounded style of the Button |
181
+ | truncate | `boolean` | `false` | Whether or not to truncate the text automatically |
182
+ | className | `string` | - | CSS class(es) to add to the main component wrapper |
183
+ | onClick | `React.MouseEventHandler<HTMLButtonElement>` | - | Handler to call when the Button is clicked |
184
+
185
+ ### ButtonIcon Props
186
+
187
+ | Prop | Type | Default | Description |
188
+ | ------------- | ---------------------------------------------------- | ----------- | --------------------------------------------------------------- |
189
+ | children | `React.ReactNode` | - | The icon to render in the button |
190
+ | label | `string` | - | The label to use as aria-label (required if no labelLeft/Right) |
191
+ | labelLeft | `string` | - | The label to show to the left of the icon |
192
+ | labelRight | `string` | - | The label to show to the right of the icon |
193
+ | variant | `"primary" \| "secondary" \| "danger" \| "selected"` | `"primary"` | The variant style of the Button |
194
+ | size | `"small" \| "medium" \| "large"` | `"medium"` | The size of the Button |
195
+ | align | `"left" \| "right" \| "center"` | `"center"` | Cell content alignment |
196
+ | noBackground | `boolean` | `false` | Option to make the Button transparent |
197
+ | animated | `boolean` | `false` | Whether or not to animate the label when displayed |
198
+ | iconClassName | `string` | - | The extra class name to pass to the icon itself |
199
+
200
+ _Inherits all common button props (mode, focusMode, disabled, etc.)_
201
+
202
+ ### ButtonLink Props
203
+
204
+ | Prop | Type | Default | Description |
205
+ | --------------- | -------------------------------------------- | --------- | ------------------------------------------- |
206
+ | href | `string` | - | A valid URL of a linked resource |
207
+ | target | `"_blank" \| "_self" \| "_parent" \| "_top"` | `"_self"` | Where to display the linked resource |
208
+ | noNewWindowIcon | `boolean` | `false` | Whether to add an icon for new window links |
209
+
210
+ _Inherits all Button props_
211
+
212
+ ### ButtonCopy Props
213
+
214
+ | Prop | Type | Default | Description |
215
+ | --------------- | -------------------------- | ------- | ---------------------------------- |
216
+ | copyToClipboard | `string \| (() => string)` | - | What text to copy to the clipboard |
217
+
218
+ _Inherits all ButtonIcon props except children, align, label, fullWidth, size_
@@ -0,0 +1,21 @@
1
+ import { jsx as a } from "react/jsx-runtime";
2
+ import i from "react";
3
+ const u = (t, n, e) => {
4
+ !n && (!document.activeElement || document.activeElement !== t.currentTarget) && typeof t?.currentTarget?.focus == "function" && t.currentTarget.focus(), typeof e == "function" && e(t);
5
+ }, f = i.forwardRef((t, n) => {
6
+ const { onClick: e, noInternalClick: o = !1, ...r } = t;
7
+ return /* @__PURE__ */ a(
8
+ "button",
9
+ {
10
+ ref: n,
11
+ onClick: (c) => {
12
+ u(c, o, e);
13
+ },
14
+ ...r
15
+ }
16
+ );
17
+ });
18
+ f.displayName = "BaseButton";
19
+ export {
20
+ f as BaseButton_private
21
+ };
@@ -1,38 +1,38 @@
1
- import c from "clsx";
2
- const v = "av-button", l = "icon", p = "button", h = "link", m = ({
1
+ import s from "clsx";
2
+ const b = "av-button", y = "icon", p = "button", l = "link", m = ({
3
3
  type: t,
4
4
  size: e,
5
5
  labelRight: r,
6
6
  labelLeft: a,
7
- align: o,
8
- animated: s
7
+ align: i,
8
+ animated: c
9
9
  }) => {
10
- const n = "max-h-8 py-0 px-2", g = "max-h-9 h-8 px-3", d = "max-h-12 py-2 px-4";
10
+ const g = "max-h-8 py-0 px-2", n = "max-h-9 h-8 px-3", h = "max-h-12 py-2 px-4";
11
11
  switch (t) {
12
12
  case p:
13
- case h:
14
- return c({
15
- [n]: e === "small",
16
- [g]: e === "medium",
17
- [d]: e === "large"
18
- });
19
13
  case l:
20
- return c("flex items-center", {
21
- "justify-center": o === "center",
22
- "justify-start": o === "left",
23
- "justify-end": o === "right",
24
- "h-6 w-6 p-0": e === "small" && !s && !(r || a),
25
- "h-6 px-2": e === "small" && !s && (r || a),
26
- "h-8 w-8 p-1": e === "medium" && !s && !(r || a),
27
- "h-8 px-3": e === "medium" && !s && (r || a),
28
- "h-12 w-12 p-2": e === "large" && !s && !(r || a),
29
- "h-12 px-4": e === "large" && !s && (r || a),
30
- "h-6 py-0": e === "small" && s && !(r || a),
31
- "h-6": e === "small" && s && (r || a),
32
- "h-8 py-1": e === "medium" && s && !(r || a),
33
- "h-8": e === "medium" && s && (r || a),
34
- "h-12 py-2": e === "large" && s && !(r || a),
35
- "h-12": e === "large" && s && (r || a)
14
+ return s({
15
+ [g]: e === "small",
16
+ [n]: e === "medium",
17
+ [h]: e === "large"
18
+ });
19
+ case y:
20
+ return s("flex items-center", {
21
+ "justify-center": i === "center",
22
+ "justify-start": i === "left",
23
+ "justify-end": i === "right",
24
+ "h-6 w-6 p-0": e === "small" && !c && !(r || a),
25
+ "h-6 px-2": e === "small" && !c && (r || a),
26
+ "h-8 w-8 p-1": e === "medium" && !c && !(r || a),
27
+ "h-8 px-3": e === "medium" && !c && (r || a),
28
+ "h-12 w-12 p-2": e === "large" && !c && !(r || a),
29
+ "h-12 px-4": e === "large" && !c && (r || a),
30
+ "h-6 py-0": e === "small" && c && !(r || a),
31
+ "h-6": e === "small" && c && (r || a),
32
+ "h-8 py-1": e === "medium" && c && !(r || a),
33
+ "h-8": e === "medium" && c && (r || a),
34
+ "h-12 py-2": e === "large" && c && !(r || a),
35
+ "h-12": e === "large" && c && (r || a)
36
36
  });
37
37
  }
38
38
  }, B = ({
@@ -41,21 +41,21 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
41
41
  labelRight: r,
42
42
  labelLeft: a
43
43
  }) => {
44
- const o = "text-sm font-medium", s = "text-base font-medium", n = "text-lg font-medium";
44
+ const i = "text-sm font-medium", c = "text-base font-medium", g = "text-lg font-medium";
45
45
  switch (t) {
46
46
  case p:
47
- case h:
48
- return c({
49
- "text-center": t === h,
50
- [o]: e === "small",
51
- [s]: e === "medium",
52
- [n]: e === "large"
53
- });
54
47
  case l:
55
- return c({
56
- [o]: e === "small" && (r || a),
57
- [s]: e === "medium" && (r || a),
58
- [n]: e === "large" && (r || a)
48
+ return s({
49
+ "text-center": t === l,
50
+ [i]: e === "small",
51
+ [c]: e === "medium",
52
+ [g]: e === "large"
53
+ });
54
+ case y:
55
+ return s({
56
+ [i]: e === "small" && (r || a),
57
+ [c]: e === "medium" && (r || a),
58
+ [g]: e === "large" && (r || a)
59
59
  });
60
60
  }
61
61
  }, w = ({
@@ -67,23 +67,23 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
67
67
  if (e)
68
68
  return "not-prose";
69
69
  if (a === "primary")
70
- return c("not-prose", {
70
+ return s("not-prose", {
71
71
  truncate: r,
72
- "text-copy-light": t === "dark" || t === "system",
73
- "text-copy-lighter": t === "light" || t === "alt-system",
74
- "dark:text-copy-lighter": t === "system",
75
- "dark:text-copy-light": t === "alt-system"
72
+ "text-copy-dark": t === "dark" || t === "system",
73
+ "text-copy-light": t === "light" || t === "alt-system",
74
+ "dark:text-copy-light": t === "system",
75
+ "dark:text-copy-dark": t === "alt-system"
76
76
  });
77
77
  if (a === "secondary")
78
- return c("not-prose", {
78
+ return s("not-prose", {
79
79
  truncate: r,
80
- "text-copy-light": t === "light" || t === "system",
81
- "text-copy-lighter": t === "dark" || t === "alt-system",
82
- "dark:text-copy-lighter": t === "alt-system",
83
- "dark:text-copy-light": t === "system"
80
+ "text-copy-light": t === "dark" || t === "system",
81
+ "text-copy-dark": t === "light" || t === "alt-system",
82
+ "dark:text-copy-dark": t === "system",
83
+ "dark:text-copy-light": t === "alt-system"
84
84
  });
85
85
  if (a === "danger")
86
- return c("not-prose", {
86
+ return s("not-prose", {
87
87
  truncate: r,
88
88
  "text-copy-light": t === "dark" || t === "system",
89
89
  "text-copy-lighter": t === "light" || t === "alt-system",
@@ -91,7 +91,7 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
91
91
  "dark:text-copy-light": t === "alt-system"
92
92
  });
93
93
  if (a === "selected")
94
- return c("not-prose text-copy-lighter", {
94
+ return s("not-prose text-copy-lighter", {
95
95
  truncate: r
96
96
  });
97
97
  }, T = ({
@@ -101,21 +101,21 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
101
101
  }) => {
102
102
  if (!e) {
103
103
  if (r === "primary")
104
- return c({
105
- "bg-action-dark": t === "dark",
106
- "bg-action-light": t === "light",
107
- "bg-action-dark dark:bg-action-light": t === "system",
108
- "bg-action-light dark:bg-action-dark": t === "alt-system"
104
+ return s({
105
+ "bg-action-light": t === "dark",
106
+ "bg-action-dark": t === "light",
107
+ "bg-action-light dark:bg-action-dark": t === "system",
108
+ "bg-action-dark dark:bg-action-light": t === "alt-system"
109
109
  });
110
110
  if (r === "secondary")
111
- return c({
112
- "bg-action-dark": t === "light",
113
- "bg-action-light": t === "dark",
114
- "bg-action-dark dark:bg-action-light": t === "alt-system",
115
- "bg-action-light dark:bg-action-dark": t === "system"
111
+ return s({
112
+ "bg-action-light": t === "light",
113
+ "bg-action-dark": t === "dark",
114
+ "bg-action-light dark:bg-action-dark": t === "alt-system",
115
+ "bg-action-dark dark:bg-action-light": t === "system"
116
116
  });
117
117
  if (r === "danger")
118
- return c({
118
+ return s({
119
119
  "bg-action-danger-dark": t === "dark",
120
120
  "bg-action-danger-light": t === "light",
121
121
  "bg-action-danger-dark dark:bg-action-danger-light": t === "system",
@@ -126,7 +126,7 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
126
126
  }
127
127
  }, E = ({
128
128
  radius: t
129
- }) => c({
129
+ }) => s({
130
130
  "rounded-full": t === "large",
131
131
  "rounded-md": t === "medium",
132
132
  "rounded-xs": t === "small"
@@ -138,21 +138,29 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
138
138
  if (e)
139
139
  return "";
140
140
  if (r === "primary")
141
- return c("hover:text-copy-light-hover", {
142
- "hover:bg-action-dark-hover": t === "dark",
143
- "hover:bg-action-light-hover": t === "light",
144
- "hover:bg-action-dark-hover dark:hover:bg-action-light-hover": t === "system",
145
- "hover:bg-action-light-hover dark:hover:bg-action-dark-hover": t === "alt-system"
141
+ return s({
142
+ "hover:text-copy-dark-hover": t === "dark" || t === "system",
143
+ "hover:text-copy-light-hover": t === "light" || t === "alt-system",
144
+ "dark:hover:text-copy-light-hover": t === "system",
145
+ "dark:hover:text-copy-dark-hover": t === "alt-system",
146
+ "hover:bg-action-light-hover": t === "dark",
147
+ "hover:bg-action-dark-hover": t === "light",
148
+ "hover:bg-action-light-hover dark:hover:bg-action-dark-hover": t === "system",
149
+ "hover:bg-action-dark-hover dark:hover:bg-action-light-hover": t === "alt-system"
146
150
  });
147
151
  if (r === "secondary")
148
- return c("hover:text-copy-light-hover", {
149
- "hover:bg-action-dark-hover": t === "light",
150
- "hover:bg-action-light-hover": t === "dark",
151
- "hover:bg-action-dark-hover dark:hover:bg-action-light-hover": t === "alt-system",
152
- "hover:bg-action-light-hover dark:hover:bg-action-dark-hover": t === "system"
152
+ return s({
153
+ "hover:text-copy-light-hover": t === "dark" || t === "system",
154
+ "hover:text-copy-dark-hover": t === "light" || t === "alt-system",
155
+ "dark:hover:text-copy-dark-hover": t === "system",
156
+ "dark:hover:text-copy-light-hover": t === "alt-system",
157
+ "hover:bg-action-light-hover": t === "light",
158
+ "hover:bg-action-dark-hover": t === "dark",
159
+ "hover:bg-action-light-hover dark:hover:bg-action-dark-hover": t === "alt-system",
160
+ "hover:bg-action-dark-hover dark:hover:bg-action-light-hover": t === "system"
153
161
  });
154
162
  if (r === "danger")
155
- return c("hover:text-copy-light-hover", {
163
+ return s("hover:text-copy-light-hover", {
156
164
  "hover:bg-action-danger-dark-hover": t === "dark",
157
165
  "hover:bg-action-danger-light-hover": t === "light",
158
166
  "hover:bg-action-danger-dark-hover dark:hover:bg-action-danger-light-hover": t === "system",
@@ -168,21 +176,29 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
168
176
  if (e)
169
177
  return "";
170
178
  if (r === "primary")
171
- return c("active:text-copy-light-active", {
172
- "active:bg-action-dark-active": t === "dark",
173
- "active:bg-action-light-active": t === "light",
174
- "active:bg-action-dark-active dark:active:bg-action-light-active": t === "system",
175
- "active:bg-action-light-active dark:active:bg-action-dark-active": t === "alt-system"
179
+ return s({
180
+ "active:text-copy-dark-active": t === "dark" || t === "system",
181
+ "active:text-copy-light-active": t === "light" || t === "alt-system",
182
+ "dark:active:text-copy-light-active": t === "system",
183
+ "dark:active:text-copy-dark-active": t === "alt-system",
184
+ "active:bg-action-light-active": t === "dark",
185
+ "active:bg-action-dark-active": t === "light",
186
+ "active:bg-action-light-active dark:active:bg-action-dark-active": t === "system",
187
+ "active:bg-action-dark-active dark:active:bg-action-light-active": t === "alt-system"
176
188
  });
177
189
  if (r === "secondary")
178
- return c("active:text-copy-light-active", {
179
- "active:bg-action-dark-active": t === "light",
180
- "active:bg-action-light-active": t === "dark",
181
- "active:bg-action-dark-active dark:active:bg-action-light-active": t === "alt-system",
182
- "active:bg-action-light-active dark:active:bg-action-dark-active": t === "system"
190
+ return s({
191
+ "active:text-copy-light-active": t === "dark" || t === "system",
192
+ "active:text-copy-dark-active": t === "light" || t === "alt-system",
193
+ "dark:active:text-copy-dark-active": t === "system",
194
+ "dark:active:text-copy-light-active": t === "alt-system",
195
+ "active:bg-action-light-active": t === "light",
196
+ "active:bg-action-dark-active": t === "dark",
197
+ "active:bg-action-light-active dark:active:bg-action-dark-active": t === "alt-system",
198
+ "active:bg-action-dark-active dark:active:bg-action-light-active": t === "system"
183
199
  });
184
200
  if (r === "danger")
185
- return c("active:text-copy-lighter-active", {
201
+ return s("active:text-copy-lighter-active", {
186
202
  "active:bg-action-danger-dark-active": t === "dark",
187
203
  "active:bg-action-danger-light-active": t === "light",
188
204
  "active:bg-action-danger-dark-active dark:active:bg-action-danger-light-active": t === "system",
@@ -198,21 +214,21 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
198
214
  if (e)
199
215
  return "border border-transparent";
200
216
  if (r === "primary")
201
- return c("border", {
202
- "border-border-dark": t === "dark",
217
+ return s("border", {
218
+ "border-border-medium": t === "dark",
203
219
  "border-border-accent": t === "light",
204
- "border-border-dark dark:border-border-accent": t === "system",
205
- "border-border-accent dark:border-border-dark": t === "alt-system"
220
+ "border-border-medium dark:border-border-accent": t === "system",
221
+ "border-border-accent dark:border-border-medium": t === "alt-system"
206
222
  });
207
223
  if (r === "secondary")
208
- return c("border", {
209
- "border-border-dark": t === "light",
224
+ return s("border", {
225
+ "border-border-medium": t === "light",
210
226
  "border-border-accent": t === "dark",
211
- "border-border-dark dark:border-border-accent": t === "alt-system",
212
- "border-border-accent dark:border-border-dark": t === "system"
227
+ "border-border-medium dark:border-border-accent": t === "alt-system",
228
+ "border-border-accent dark:border-border-medium": t === "system"
213
229
  });
214
230
  if (r === "danger")
215
- return c("border", {
231
+ return s("border", {
216
232
  "border-border-danger-dark": t === "dark",
217
233
  "border-border-danger-medium": t === "light",
218
234
  "border-border-danger-dark dark:border-border-danger-medium": t === "system",
@@ -222,7 +238,7 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
222
238
  return "border border-border-selected-dark";
223
239
  }, j = ({
224
240
  focusMode: t
225
- }) => c("focus:outline", "focus:outline-2", "focus:outline-offset-2", {
241
+ }) => s("focus:outline", "focus:outline-2", "focus:outline-offset-2", {
226
242
  "focus:outline-focus-dark": t === "dark",
227
243
  "focus:outline-focus-light": t === "light",
228
244
  "focus:outline-focus-light dark:focus:outline-focus-dark": t === "alt-system",
@@ -230,74 +246,89 @@ const v = "av-button", l = "icon", p = "button", h = "link", m = ({
230
246
  }), O = ({
231
247
  mode: t,
232
248
  raw: e,
233
- iconClassName: r
234
- }) => e ? "" : c(
235
- {
236
- "text-copy-accent-dark": t === "light" || t === "alt-system",
249
+ iconClassName: r,
250
+ variant: a = "primary"
251
+ }) => {
252
+ if (e)
253
+ return "";
254
+ let i = {};
255
+ return a === "primary" ? i = {
256
+ "text-copy-dark": t === "dark" || t === "system",
257
+ "text-copy-light": t === "light" || t === "alt-system",
258
+ "dark:text-copy-light": t === "system",
259
+ "dark:text-copy-dark": t === "alt-system"
260
+ } : a === "secondary" ? i = {
237
261
  "text-copy-light": t === "dark" || t === "system",
238
- "dark:text-copy-light": t === "alt-system",
239
- "dark:text-copy-accent-dark": t === "system"
240
- },
241
- r
242
- ), P = ({
262
+ "text-copy-dark": t === "light" || t === "alt-system",
263
+ "dark:text-copy-dark": t === "system",
264
+ "dark:text-copy-light": t === "alt-system"
265
+ } : a === "danger" ? i = {
266
+ "text-copy-light": t === "dark" || t === "system",
267
+ "text-copy-lighter": t === "light" || t === "alt-system",
268
+ "dark:text-copy-lighter": t === "system",
269
+ "dark:text-copy-light": t === "alt-system"
270
+ } : a === "selected" && (i = {
271
+ "text-copy-lighter": !0
272
+ }), s(i, r);
273
+ }, P = ({
243
274
  animated: t
244
- }) => c({
275
+ }) => s({
245
276
  "transition-opacity duration-300 ease-in-out": t
246
277
  }), S = ({
247
278
  type: t,
248
279
  className: e,
249
280
  raw: r,
250
281
  mode: a,
251
- focusMode: o,
252
- disabled: s,
253
- fullWidth: n,
254
- size: g,
255
- noBorder: d,
256
- labelRight: k,
257
- labelLeft: u,
258
- noBackground: y,
259
- variant: i,
282
+ focusMode: i,
283
+ disabled: c,
284
+ fullWidth: g,
285
+ size: n,
286
+ noBorder: h,
287
+ labelRight: d,
288
+ labelLeft: k,
289
+ noBackground: u,
290
+ variant: o,
260
291
  truncate: x,
261
292
  align: f,
262
293
  radius: C,
263
- animated: b
264
- }) => (i || (i = "primary"), r ? c(v, e) : c(
265
- v,
294
+ animated: v
295
+ }) => (o || (o = "primary"), r ? s(b, e) : s(
296
+ b,
266
297
  w({
267
298
  mode: a,
268
- variant: i,
269
- noBackground: y,
299
+ variant: o,
300
+ noBackground: u,
270
301
  truncate: x
271
302
  }),
272
- T({ mode: a, noBackground: y, variant: i }),
303
+ T({ mode: a, noBackground: u, variant: o }),
273
304
  E({ radius: C }),
274
305
  m({
275
306
  type: t,
276
- size: g,
277
- labelRight: k,
278
- labelLeft: u,
307
+ size: n,
308
+ labelRight: d,
309
+ labelLeft: k,
279
310
  align: f,
280
- animated: b
311
+ animated: v
281
312
  }),
282
- B({ type: t, size: g, labelRight: k, labelLeft: u }),
283
- _({ mode: a, variant: i, noBorder: d }),
284
- j({ focusMode: o }),
285
- I({ mode: a, variant: i, disabled: s }),
286
- N({ mode: a, variant: i, disabled: s }),
313
+ B({ type: t, size: n, labelRight: d, labelLeft: k }),
314
+ _({ mode: a, variant: o, noBorder: h }),
315
+ j({ focusMode: i }),
316
+ I({ mode: a, variant: o, disabled: c }),
317
+ N({ mode: a, variant: o, disabled: c }),
287
318
  {
288
- "w-full": n,
289
- "disabled:cursor-not-allowed disabled:opacity-50": s
319
+ "w-full": g,
320
+ "disabled:cursor-not-allowed disabled:opacity-50": c
290
321
  },
291
- c({
292
- "transition-[width] duration-300 ease-in": t === l && b
322
+ s({
323
+ "transition-[width] duration-300 ease-in": t === y && v
293
324
  }),
294
325
  e
295
326
  ));
296
327
  export {
297
- v as BUTTON_CLASSNAME,
328
+ b as BUTTON_CLASSNAME,
298
329
  p as TYPE_BUTTON,
299
- l as TYPE_ICON,
300
- h as TYPE_LINK,
330
+ y as TYPE_ICON,
331
+ l as TYPE_LINK,
301
332
  S as getButtonClasses,
302
333
  P as getButtonIconLabelClasses,
303
334
  O as getIconClasses
@@ -1,7 +1,7 @@
1
1
  import { jsx as c } from "react/jsx-runtime";
2
2
  import N from "react";
3
- import { BaseButton_private as T } from "../../chunks/BaseButton.BFKIL4GO.js";
4
- import { getButtonClasses as g, TYPE_BUTTON as x } from "../../chunks/utilities.B84qY3__.js";
3
+ import { BaseButton_private as T } from "../../chunks/BaseButton.BpaKdSwW.js";
4
+ import { getButtonClasses as g, TYPE_BUTTON as x } from "../../chunks/utilities.BDrrw2K7.js";
5
5
  const C = N.forwardRef(
6
6
  ({
7
7
  children: s,
@@ -1,15 +1,15 @@
1
- import { jsx as m, jsxs as U } from "react/jsx-runtime";
2
- import Y, { useRef as p, useCallback as J, useEffect as T, useMemo as E, useState as K, useLayoutEffect as O } from "react";
3
- import { BaseButton_private as Q } from "../../chunks/BaseButton.BFKIL4GO.js";
4
- import { getButtonClasses as V, TYPE_ICON as X, getIconClasses as Z, getButtonIconLabelClasses as z } from "../../chunks/utilities.B84qY3__.js";
1
+ import { jsx as y, jsxs as U } from "react/jsx-runtime";
2
+ import Y, { useRef as m, useCallback as J, useEffect as T, useMemo as j, useState as K, useLayoutEffect as D } from "react";
3
+ import { BaseButton_private as Q } from "../../chunks/BaseButton.BpaKdSwW.js";
4
+ import { getButtonClasses as V, TYPE_ICON as X, getIconClasses as Z, getButtonIconLabelClasses as z } from "../../chunks/utilities.BDrrw2K7.js";
5
5
  function ee() {
6
- const t = p(!1);
6
+ const t = m(!1);
7
7
  return T(() => (t.current = !0, () => {
8
8
  t.current = !1;
9
9
  }), []), J(() => t.current, []);
10
10
  }
11
11
  function te(t) {
12
- return E(() => t.every((r) => r == null) ? () => {
12
+ return j(() => t.every((r) => r == null) ? () => {
13
13
  } : (r) => {
14
14
  t.forEach((e) => {
15
15
  typeof e == "function" ? e(r) : e != null && (e.current = r);
@@ -27,15 +27,15 @@ const re = {
27
27
  right: 0
28
28
  };
29
29
  function A(t) {
30
- const r = ee(), e = p(0), s = p(null), [d, C] = K(re), i = E(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((w) => {
31
- const a = w[0];
32
- a && (cancelAnimationFrame(e.current), e.current = requestAnimationFrame(() => {
33
- s.current && r() && C(a.contentRect);
30
+ const r = ee(), e = m(0), s = m(null), [p, C] = K(re), d = j(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((w) => {
31
+ const i = w[0];
32
+ i && (cancelAnimationFrame(e.current), e.current = requestAnimationFrame(() => {
33
+ s.current && r() && C(i.contentRect);
34
34
  }));
35
35
  }), [r]);
36
- return T(() => (s.current && (i == null || i.observe(s.current, t)), () => {
37
- i == null || i.disconnect(), e.current && cancelAnimationFrame(e.current);
38
- }), [i, t]), [s, d];
36
+ return T(() => (s.current && d?.observe(s.current, t), () => {
37
+ d?.disconnect(), e.current && cancelAnimationFrame(e.current);
38
+ }), [d, t]), [s, p];
39
39
  }
40
40
  const b = {
41
41
  small: 24,
@@ -45,62 +45,62 @@ const b = {
45
45
  large: 48
46
46
  // w-12
47
47
  }, ne = {
48
- small: 8 * 2,
48
+ small: 16,
49
49
  // px-2 x 2
50
- medium: 12 * 2,
50
+ medium: 24,
51
51
  // px-3 x 2
52
- large: 16 * 2
52
+ large: 32
53
53
  // px-4 x 2
54
- }, ce = 2, se = 300, le = Y.forwardRef(
54
+ }, ce = 2, se = 300, ue = Y.forwardRef(
55
55
  ({
56
56
  children: t,
57
57
  disabled: r = !1,
58
58
  mode: e = "system",
59
59
  focusMode: s = "system",
60
- fullWidth: d = !1,
60
+ fullWidth: p = !1,
61
61
  className: C,
62
- type: i = "button",
62
+ type: d = "button",
63
63
  raw: w = !1,
64
- noBorder: a = !1,
65
- "aria-label": j,
66
- label: F,
67
- size: l = "medium",
64
+ noBorder: i = !1,
65
+ "aria-label": F,
66
+ label: H,
67
+ size: u = "medium",
68
68
  labelRight: h,
69
69
  labelLeft: R,
70
- noBackground: H = !1,
71
- align: S = "center",
72
- radius: W = "large",
73
- variant: _ = "primary",
74
- iconClassName: $,
75
- animated: u = !1,
76
- ...M
77
- }, P) => {
70
+ noBackground: S = !1,
71
+ align: W = "center",
72
+ radius: _ = "large",
73
+ variant: g = "secondary",
74
+ iconClassName: M,
75
+ animated: l = !1,
76
+ ...P
77
+ }, $) => {
78
78
  const k = V({
79
79
  type: X,
80
80
  mode: e,
81
81
  focusMode: s,
82
- fullWidth: d,
82
+ fullWidth: p,
83
83
  disabled: r,
84
84
  raw: w,
85
85
  className: C,
86
- noBorder: a,
87
- size: l,
86
+ noBorder: i,
87
+ size: u,
88
88
  labelRight: h,
89
89
  labelLeft: R,
90
- noBackground: H,
91
- align: S,
92
- radius: W,
93
- variant: _,
94
- animated: u
95
- }), q = Z({ mode: e, raw: w, iconClassName: $ }), g = z({ animated: u }), G = "flex items-center justify-center relative w-full h-full overflow-hidden", [n, N] = A(), [c, v] = A(), [I, B] = A(), x = p(0), o = p(null), f = p(null), L = te([P, o]);
96
- return O(() => {
97
- I && I.current && u && (x.current = B.width + ne[l] + (a ? 0 : ce), o.current && !o.current.style.width && (o.current.style.width = `${b[l]}px`));
98
- }, [B, I, l, a, u]), O(() => {
99
- if (o && o.current && u) {
100
- let y = b[l];
101
- h && n && N.width > 0 ? y = N.width + x.current : R && c && v.width > 0 && (y = v.width + x.current), f.current && clearTimeout(f.current), y !== parseInt(o.current.style.width || "0", 10) && (n.current && (n.current.style.opacity = "0"), c.current && (c.current.style.opacity = "0"), o.current.style.width = `${y}px`, y > b[l] && (f.current = setTimeout(() => {
102
- n.current && h && (n.current.style.opacity = "1"), c.current && R && (c.current.style.opacity = "1"), f.current = null;
103
- }, se * 0.8))), y === b[l] && (n.current && (n.current.style.opacity = "0"), c.current && (c.current.style.opacity = "0"));
90
+ noBackground: S,
91
+ align: W,
92
+ radius: _,
93
+ variant: g,
94
+ animated: l
95
+ }), q = Z({ mode: e, raw: w, iconClassName: M, variant: g }), B = z({ animated: l }), G = "flex items-center justify-center relative w-full h-full overflow-hidden", [n, N] = A(), [c, v] = A(), [I, O] = A(), x = m(0), o = m(null), a = m(null), L = te([$, o]);
96
+ return D(() => {
97
+ I && I.current && l && (x.current = O.width + ne[u] + (i ? 0 : ce), o.current && !o.current.style.width && (o.current.style.width = `${b[u]}px`));
98
+ }, [O, I, u, i, l]), D(() => {
99
+ if (o && o.current && l) {
100
+ let f = b[u];
101
+ h && n && N.width > 0 ? f = N.width + x.current : R && c && v.width > 0 && (f = v.width + x.current), a.current && clearTimeout(a.current), f !== parseInt(o.current.style.width || "0", 10) && (n.current && (n.current.style.opacity = "0"), c.current && (c.current.style.opacity = "0"), o.current.style.width = `${f}px`, f > b[u] && (a.current = setTimeout(() => {
102
+ n.current && h && (n.current.style.opacity = "1"), c.current && R && (c.current.style.opacity = "1"), a.current = null;
103
+ }, se * 0.8))), f === b[u] && (n.current && (n.current.style.opacity = "0"), c.current && (c.current.style.opacity = "0"));
104
104
  }
105
105
  }, [
106
106
  N,
@@ -109,61 +109,61 @@ const b = {
109
109
  v,
110
110
  R,
111
111
  c,
112
- l,
113
- u
112
+ u,
113
+ l
114
114
  ]), T(() => () => {
115
- f.current && clearTimeout(f.current);
116
- }, []), /* @__PURE__ */ m(
115
+ a.current && clearTimeout(a.current);
116
+ }, []), /* @__PURE__ */ y(
117
117
  Q,
118
118
  {
119
119
  ref: L,
120
120
  className: k,
121
121
  disabled: r,
122
- type: i,
123
- "aria-label": j || F,
124
- ...M,
122
+ type: d,
123
+ "aria-label": F || H,
124
+ ...P,
125
125
  children: /* @__PURE__ */ U("div", { className: G, children: [
126
- /* @__PURE__ */ m(
127
- D,
126
+ /* @__PURE__ */ y(
127
+ E,
128
128
  {
129
129
  label: R,
130
130
  labelRef: c,
131
- labelClass: g,
131
+ labelClass: B,
132
132
  labelInnerClass: "pr-2",
133
- initiallyHidden: u
133
+ initiallyHidden: l
134
134
  }
135
135
  ),
136
- /* @__PURE__ */ m("span", { ref: I, className: q, children: t }),
137
- /* @__PURE__ */ m(
138
- D,
136
+ /* @__PURE__ */ y("span", { ref: I, className: q, children: t }),
137
+ /* @__PURE__ */ y(
138
+ E,
139
139
  {
140
140
  label: h,
141
141
  labelRef: n,
142
- labelClass: g,
142
+ labelClass: B,
143
143
  labelInnerClass: "pl-2",
144
- initiallyHidden: u
144
+ initiallyHidden: l
145
145
  }
146
146
  )
147
147
  ] })
148
148
  }
149
149
  );
150
150
  }
151
- ), D = ({
151
+ ), E = ({
152
152
  labelRef: t,
153
153
  labelClass: r,
154
154
  label: e,
155
155
  labelInnerClass: s,
156
- initiallyHidden: d = !1
157
- }) => /* @__PURE__ */ m(
156
+ initiallyHidden: p = !1
157
+ }) => /* @__PURE__ */ y(
158
158
  "span",
159
159
  {
160
160
  ref: t,
161
161
  className: r,
162
- style: d ? { opacity: 0 } : void 0,
163
- children: e && /* @__PURE__ */ m("span", { className: s, children: e })
162
+ style: p ? { opacity: 0 } : void 0,
163
+ children: e && /* @__PURE__ */ y("span", { className: s, children: e })
164
164
  }
165
165
  );
166
- le.displayName = "ButtonIcon";
166
+ ue.displayName = "ButtonIcon";
167
167
  export {
168
- le as ButtonIcon
168
+ ue as ButtonIcon
169
169
  };
@@ -1,7 +1,7 @@
1
1
  import { jsx as s, jsxs as o } from "react/jsx-runtime";
2
2
  import r from "clsx";
3
3
  import v from "react";
4
- import { getButtonClasses as V, TYPE_LINK as C } from "../../chunks/utilities.B84qY3__.js";
4
+ import { getButtonClasses as V, TYPE_LINK as C } from "../../chunks/utilities.BDrrw2K7.js";
5
5
  const L = v.forwardRef(
6
6
  ({
7
7
  children: t,
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BUTTON_CLASSNAME as B } from "./chunks/utilities.B84qY3__.js";
1
+ import { BUTTON_CLASSNAME as B } from "./chunks/utilities.BDrrw2K7.js";
2
2
  import { Button as T } from "./components/Button/Button.js";
3
3
  import { ButtonCopy as I } from "./components/Button/ButtonCopy.js";
4
4
  import { ButtonIcon as l } from "./components/Button/ButtonIcon.js";
@@ -7,13 +7,13 @@ import { jsx as e } from "react/jsx-runtime";
7
7
  import a from "clsx";
8
8
  import m from "react";
9
9
  /*!
10
- @versini/ui-button v6.0.8
10
+ @versini/ui-button v7.0.0
11
11
  © 2025 gizmette.com
12
12
  */
13
13
  try {
14
14
  window.__VERSINI_UI_BUTTON__ || (window.__VERSINI_UI_BUTTON__ = {
15
- version: "6.0.8",
16
- buildTime: "06/28/2025 08:58 PM EDT",
15
+ version: "7.0.0",
16
+ buildTime: "08/07/2025 04:11 PM EDT",
17
17
  homepage: "https://github.com/aversini/ui-components",
18
18
  license: "MIT"
19
19
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versini/ui-button",
3
- "version": "6.0.8",
3
+ "version": "7.0.0",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "publishConfig": {
@@ -27,6 +27,7 @@
27
27
  "dev:types": "tsup --watch src",
28
28
  "dev": "npm-run-all clean --parallel dev:js dev:types",
29
29
  "lint": "biome lint src",
30
+ "lint:fix": "biome check src --write --no-errors-on-unmatched",
30
31
  "prettier": "biome check --write --no-errors-on-unmatched",
31
32
  "start": "static-server dist --port 5173",
32
33
  "test:coverage:ui": "vitest --coverage --ui",
@@ -39,11 +40,12 @@
39
40
  "react-dom": "^18.3.1 || ^19.0.0"
40
41
  },
41
42
  "devDependencies": {
42
- "@versini/ui-types": "5.0.5"
43
+ "@testing-library/jest-dom": "6.6.4",
44
+ "@versini/ui-types": "5.0.6"
43
45
  },
44
46
  "dependencies": {
45
47
  "@tailwindcss/typography": "0.5.16",
46
- "@versini/ui-hooks": "4.7.4",
48
+ "@versini/ui-hooks": "4.7.5",
47
49
  "@versini/ui-icons": "4.10.0",
48
50
  "clsx": "2.1.1",
49
51
  "tailwindcss": "4.1.11"
@@ -51,5 +53,5 @@
51
53
  "sideEffects": [
52
54
  "**/*.css"
53
55
  ],
54
- "gitHead": "1b9a792d10e1f67fc7af7cfdff718ef1e1c78633"
56
+ "gitHead": "42daab1fb88c366495abbc1db78a9987de05e59b"
55
57
  }
@@ -1,22 +0,0 @@
1
- import { jsx as a } from "react/jsx-runtime";
2
- import i from "react";
3
- const u = (t, r, n) => {
4
- var o;
5
- !r && (!document.activeElement || document.activeElement !== t.currentTarget) && typeof ((o = t == null ? void 0 : t.currentTarget) == null ? void 0 : o.focus) == "function" && t.currentTarget.focus(), typeof n == "function" && n(t);
6
- }, f = i.forwardRef((t, r) => {
7
- const { onClick: n, noInternalClick: o = !1, ...e } = t;
8
- return /* @__PURE__ */ a(
9
- "button",
10
- {
11
- ref: r,
12
- onClick: (c) => {
13
- u(c, o, n);
14
- },
15
- ...e
16
- }
17
- );
18
- });
19
- f.displayName = "BaseButton";
20
- export {
21
- f as BaseButton_private
22
- };