@versini/ui-button 11.2.1 → 11.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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -1,2 +1,2 @@
1
1
  import type { ButtonIconTypes } from "@versini/ui-types";
2
- export declare function ButtonIcon({ children, disabled, mode, focusMode, fullWidth, className, type, raw, noBorder, "aria-label": ariaLabel, label, size, labelRight, labelLeft, noBackground, align, radius, variant, iconClassName, animated, ref, ...otherProps }: ButtonIconTypes.Props): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ButtonIcon({ children, disabled, mode, focusMode, fullWidth, className, type, raw, noBorder, "aria-label": ariaLabel, label, size, labelRight, labelLeft, noBackground, align, radius, variant, iconClassName, animated, badge, ref, ...otherProps }: ButtonIconTypes.Props): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -8,7 +8,7 @@ import { useMergeRefs } from "@versini/ui-hooks/use-merge-refs";
8
8
  import { useResizeObserver } from "@versini/ui-hooks/use-resize-observer";
9
9
  import { useEffect, useLayoutEffect, useRef } from "react";
10
10
  import { BaseButton_private } from "../private/BaseButton.js";
11
- import { TYPE_ICON, getButtonClasses, getButtonIconLabelClasses, getIconClasses } from "./utilities.js";
11
+ import { TYPE_ICON, getBadgeClasses, getButtonClasses, getButtonIconLabelClasses, getIconClasses } from "./utilities.js";
12
12
 
13
13
  ;// CONCATENATED MODULE: external "react/jsx-runtime"
14
14
 
@@ -41,7 +41,7 @@ const PADDINGS = {
41
41
  };
42
42
  const BORDERS = 2; // border x 2
43
43
  const ANIMATION_DURATION = 300; // ms - should match the CSS transition duration
44
- function ButtonIcon({ children, disabled = false, mode = "system", focusMode = "system", fullWidth = false, className, type = "button", raw = false, noBorder = false, "aria-label": ariaLabel, label, size = "medium", labelRight, labelLeft, noBackground = false, align = "center", radius = "large", variant = "secondary", iconClassName, animated = false, ref, ...otherProps }) {
44
+ function ButtonIcon({ children, disabled = false, mode = "system", focusMode = "system", fullWidth = false, className, type = "button", raw = false, noBorder = false, "aria-label": ariaLabel, label, size = "medium", labelRight, labelLeft, noBackground = false, align = "center", radius = "large", variant = "secondary", iconClassName, animated = false, badge, ref, ...otherProps }) {
45
45
  const buttonClass = getButtonClasses({
46
46
  type: TYPE_ICON,
47
47
  mode,
@@ -58,7 +58,8 @@ function ButtonIcon({ children, disabled = false, mode = "system", focusMode = "
58
58
  align,
59
59
  radius,
60
60
  variant,
61
- animated
61
+ animated,
62
+ badge
62
63
  });
63
64
  const iconClass = getIconClasses({
64
65
  mode,
@@ -167,37 +168,48 @@ function ButtonIcon({ children, disabled = false, mode = "system", focusMode = "
167
168
  }
168
169
  };
169
170
  }, []);
170
- /* v8 ignore stop */ return /*#__PURE__*/ jsx(BaseButton_private, {
171
+ /* v8 ignore stop */ const badgeInfo = getBadgeClasses({
172
+ size,
173
+ badge
174
+ });
175
+ return /*#__PURE__*/ jsxs(BaseButton_private, {
171
176
  ref: mergedRef,
172
177
  className: buttonClass,
173
178
  disabled: disabled,
174
179
  type: type,
175
180
  "aria-label": ariaLabel || label,
176
181
  ...otherProps,
177
- children: /*#__PURE__*/ jsxs("div", {
178
- className: contentWrapperClass,
179
- children: [
180
- /*#__PURE__*/ jsx(ButtonLabel, {
181
- label: labelLeft,
182
- labelRef: labelLeftRef,
183
- labelClass: labelClass,
184
- labelInnerClass: "pr-2",
185
- initiallyHidden: animated
186
- }),
187
- /*#__PURE__*/ jsx("span", {
188
- ref: iconRef,
189
- className: iconClass,
190
- children: children
191
- }),
192
- /*#__PURE__*/ jsx(ButtonLabel, {
193
- label: labelRight,
194
- labelRef: labelRightRef,
195
- labelClass: labelClass,
196
- labelInnerClass: "pl-2",
197
- initiallyHidden: animated
198
- })
199
- ]
200
- })
182
+ children: [
183
+ /*#__PURE__*/ jsxs("div", {
184
+ className: contentWrapperClass,
185
+ children: [
186
+ /*#__PURE__*/ jsx(ButtonLabel, {
187
+ label: labelLeft,
188
+ labelRef: labelLeftRef,
189
+ labelClass: labelClass,
190
+ labelInnerClass: "pr-2",
191
+ initiallyHidden: animated
192
+ }),
193
+ /*#__PURE__*/ jsx("span", {
194
+ ref: iconRef,
195
+ className: iconClass,
196
+ children: children
197
+ }),
198
+ /*#__PURE__*/ jsx(ButtonLabel, {
199
+ label: labelRight,
200
+ labelRef: labelRightRef,
201
+ labelClass: labelClass,
202
+ labelInnerClass: "pl-2",
203
+ initiallyHidden: animated
204
+ })
205
+ ]
206
+ }),
207
+ badgeInfo && /*#__PURE__*/ jsx("span", {
208
+ className: badgeInfo.className,
209
+ "aria-hidden": "true",
210
+ children: badgeInfo.displayValue
211
+ })
212
+ ]
201
213
  });
202
214
  }
203
215
  const ButtonLabel = ({ labelRef, labelClass, label, labelInnerClass, initiallyHidden = false })=>{
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -9,5 +9,9 @@ export declare const getIconClasses: ({ mode, raw, iconClassName, variant, }: Pi
9
9
  variant?: ButtonTypes.Props["variant"];
10
10
  }) => string;
11
11
  export declare const getButtonIconLabelClasses: ({ animated, }: Pick<ButtonIconTypes.Props, "animated">) => string;
12
- export declare const getButtonClasses: ({ type, className, raw, mode, focusMode, disabled, fullWidth, size, noBorder, labelRight, labelLeft, noBackground, variant, truncate, align, radius, animated, }: GetButtonClassesProps) => string;
12
+ export declare const getBadgeClasses: ({ size, badge, }: Pick<ButtonIconTypes.Props, "size" | "badge">) => {
13
+ className: string;
14
+ displayValue: string | null;
15
+ } | null;
16
+ export declare const getButtonClasses: ({ type, className, raw, mode, focusMode, disabled, fullWidth, size, noBorder, labelRight, labelLeft, noBackground, variant, truncate, align, radius, animated, badge, }: GetButtonClassesProps) => string;
13
17
  export {};
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -305,10 +305,41 @@ const getButtonIconLabelClasses = ({ animated })=>{
305
305
  "transition-opacity duration-300 ease-in-out": animated
306
306
  });
307
307
  };
308
- const getButtonClasses = ({ type, className, raw, mode, focusMode, disabled, fullWidth, size, noBorder, labelRight, labelLeft, noBackground, variant, truncate, align, radius, animated })=>{
308
+ const getBadgeClasses = ({ size, badge })=>{
309
+ if (badge === undefined || badge === false || badge === 0) {
310
+ return null;
311
+ }
312
+ const isNumber = typeof badge === "number";
313
+ const displayValue = isNumber ? badge > 99 ? "99+" : String(badge) : null;
314
+ // Base classes for badge positioning and styling
315
+ const baseClasses = clsx("absolute inline-flex items-center justify-center", "border border-border-white", "rounded-full", "text-copy-lighter", "bg-copy-error-dark", "pointer-events-none");
316
+ // Size-specific classes for positioning and dimensions
317
+ const sizeClasses = clsx({
318
+ // Dot badge (boolean true) - small circle
319
+ "size-2 -top-0.5 right-0": !isNumber && size === "small",
320
+ "size-2.5 -top-0.5 right-0": !isNumber && size === "medium",
321
+ "size-3 -top-0.5 right-1": !isNumber && size === "large",
322
+ // Number badge - larger to fit text
323
+ "min-w-3 h-3 text-[8px] px-1 -top-1.5 -right-1.5": isNumber && size === "small" && badge < 10,
324
+ "min-w-3 h-3 text-[8px] px-1 -top-1.5 -right-2": isNumber && size === "small" && badge >= 10 && badge <= 99,
325
+ "min-w-3 h-3 text-[8px] px-1 -top-1.5 -right-3": isNumber && size === "small" && badge > 99,
326
+ "min-w-4 h-4 text-[10px] px-1 -top-1.5 -right-0.5": isNumber && size === "medium" && badge < 10,
327
+ "min-w-4 h-4 text-[10px] px-1 -top-1.5 -right-2": isNumber && size === "medium" && badge >= 10 && badge <= 99,
328
+ "min-w-4 h-4 text-[10px] px-1 -top-1.5 -right-3": isNumber && size === "medium" && badge > 99,
329
+ "min-w-5 h-5 text-xs px-1 -top-1 -right-1": isNumber && size === "large" && badge < 10,
330
+ "min-w-5 h-5 text-xs px-1 -top-1 -right-2": isNumber && size === "large" && badge >= 10 && badge <= 99,
331
+ "min-w-5 h-5 text-xs px-1 -top-1 -right-3": isNumber && size === "large" && badge > 99
332
+ });
333
+ return {
334
+ className: clsx(baseClasses, sizeClasses),
335
+ displayValue
336
+ };
337
+ };
338
+ const getButtonClasses = ({ type, className, raw, mode, focusMode, disabled, fullWidth, size, noBorder, labelRight, labelLeft, noBackground, variant, truncate, align, radius, animated, badge })=>{
309
339
  if (!variant) {
310
340
  variant = "primary";
311
341
  }
342
+ const hasBadge = badge !== undefined && badge !== false && badge !== 0;
312
343
  return raw ? clsx(BUTTON_CLASSNAME, className) : clsx(BUTTON_CLASSNAME, getButtonTextCopyClasses({
313
344
  mode,
314
345
  variant,
@@ -348,10 +379,11 @@ const getButtonClasses = ({ type, className, raw, mode, focusMode, disabled, ful
348
379
  disabled
349
380
  }), {
350
381
  "w-full": fullWidth,
351
- "disabled:cursor-not-allowed disabled:opacity-50": disabled
382
+ "disabled:cursor-not-allowed disabled:opacity-50": disabled,
383
+ relative: hasBadge
352
384
  }, clsx({
353
385
  "transition-[width] duration-300 ease-in": type === TYPE_ICON && animated
354
386
  }), className);
355
387
  };
356
388
 
357
- export { TYPE_BUTTON, TYPE_ICON, TYPE_LINK, getButtonClasses, getButtonIconLabelClasses, getIconClasses };
389
+ export { TYPE_BUTTON, TYPE_ICON, TYPE_LINK, getBadgeClasses, getButtonClasses, getButtonIconLabelClasses, getIconClasses };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- @versini/ui-button v11.2.1
2
+ @versini/ui-button v11.3.0
3
3
  © 2025 gizmette.com
4
4
  */
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versini/ui-button",
3
- "version": "11.2.1",
3
+ "version": "11.3.0",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "publishConfig": {
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "devDependencies": {
65
65
  "@testing-library/jest-dom": "6.9.1",
66
- "@versini/ui-types": "8.2.0"
66
+ "@versini/ui-types": "8.3.0"
67
67
  },
68
68
  "dependencies": {
69
69
  "@tailwindcss/typography": "0.5.19",
@@ -75,5 +75,5 @@
75
75
  "sideEffects": [
76
76
  "**/*.css"
77
77
  ],
78
- "gitHead": "2333d25be1b8cfa5044c898d4da08391ffc2f0f9"
78
+ "gitHead": "fae53f4bd56440f7a72ed63b1a2a02b0c3b5a7e6"
79
79
  }