@metamask/design-system-react 0.38.0 → 0.38.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/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.38.1]
11
+
12
+ ### Changed
13
+
14
+ - Added content guidelines to component documentation, including sentence case, punctuation, and prop-specific examples ([#1466](https://github.com/MetaMask/metamask-design-system/pull/1466))
15
+ - Updated the `AvatarGroup` migration guide with extension-specific prop mappings and migration examples ([#1460](https://github.com/MetaMask/metamask-design-system/pull/1460))
16
+
17
+ ### Fixed
18
+
19
+ - Fixed a `BadgeWrapper` layout feedback loop that could cause continuous layout updates and high CPU usage ([#1474](https://github.com/MetaMask/metamask-design-system/pull/1474))
20
+
10
21
  ## [0.38.0]
11
22
 
12
23
  ### Changed
@@ -509,7 +520,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
509
520
  - Full TypeScript support with type definitions and enums
510
521
  - Tailwind CSS integration with design token support
511
522
 
512
- [Unreleased]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.38.0...HEAD
523
+ [Unreleased]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.38.1...HEAD
524
+ [0.38.1]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.38.0...@metamask/design-system-react@0.38.1
513
525
  [0.38.0]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.37.0...@metamask/design-system-react@0.38.0
514
526
  [0.37.0]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.36.0...@metamask/design-system-react@0.37.0
515
527
  [0.36.0]: https://github.com/MetaMask/metamask-design-system/compare/@metamask/design-system-react@0.35.2...@metamask/design-system-react@0.36.0
@@ -30,7 +30,7 @@ const AvatarBase_1 = require("../AvatarBase/index.cjs");
30
30
  exports.AvatarFavicon = (0, react_1.forwardRef)(({ src, name = '', fallbackText, fallbackTextProps, className, size = design_system_shared_1.AvatarFaviconSize.Md, imageProps, ...props }, ref) => {
31
31
  const [finalFallbackText, setFinalFallbackText] = (0, react_1.useState)('');
32
32
  const backupFallbackText = fallbackText || name?.[0] || '?';
33
- const altText = name || 'Dapp logo'; // TBC: Add localization for default text
33
+ const altText = name || 'Site logo'; // TBC: Add localization for default text
34
34
  const onErrorHandler = (e) => {
35
35
  setFinalFallbackText(backupFallbackText);
36
36
  imageProps?.onError?.(e);
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarFavicon.cjs","sourceRoot":"","sources":["../../../src/components/AvatarFavicon/AvatarFavicon.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yEAGwC;AACxC,+CAAoD;AAEpD,wDAA2C;AAI9B,QAAA,aAAa,GAAG,IAAA,kBAAU,EACrC,CACE,EACE,GAAG,EACH,IAAI,GAAG,EAAE,EACT,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,IAAI,GAAG,wCAAiB,CAAC,EAAE,EAC3B,UAAU,EACV,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,IAAA,gBAAQ,EAAS,EAAE,CAAC,CAAC;IACvE,MAAM,kBAAkB,GAAG,YAAY,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,yCAAyC;IAE9E,MAAM,cAAc,GAAG,CAAC,CAAyC,EAAE,EAAE;QACnE,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;QACzC,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,CACL,8BAAC,uBAAU,IACT,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,sCAAe,CAAC,MAAM,EAC7B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,EAC1D,iBAAiB,EAAE,iBAAiB,KAChC,KAAK,IAER,GAAG,IAAI,CACN,uCACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,SAAS,EAAC,0BAA0B,KAChC,UAAU,EACd,OAAO,EAAE,cAAc,GACvB,CACH,CACU,CACd,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,qBAAa,CAAC,WAAW,GAAG,eAAe,CAAC","sourcesContent":["import {\n AvatarBaseShape,\n AvatarFaviconSize,\n} from '@metamask/design-system-shared';\nimport React, { forwardRef, useState } from 'react';\n\nimport { AvatarBase } from '../AvatarBase';\n\nimport type { AvatarFaviconProps } from './AvatarFavicon.types';\n\nexport const AvatarFavicon = forwardRef<HTMLDivElement, AvatarFaviconProps>(\n (\n {\n src,\n name = '',\n fallbackText,\n fallbackTextProps,\n className,\n size = AvatarFaviconSize.Md,\n imageProps,\n ...props\n },\n ref,\n ) => {\n const [finalFallbackText, setFinalFallbackText] = useState<string>('');\n const backupFallbackText = fallbackText || name?.[0] || '?';\n const altText = name || 'Dapp logo'; // TBC: Add localization for default text\n\n const onErrorHandler = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setFinalFallbackText(backupFallbackText);\n imageProps?.onError?.(e);\n };\n\n return (\n <AvatarBase\n ref={ref}\n shape={AvatarBaseShape.Circle}\n size={size}\n className={className}\n fallbackText={src ? finalFallbackText : backupFallbackText}\n fallbackTextProps={fallbackTextProps}\n {...props}\n >\n {src && (\n <img\n src={src}\n alt={altText}\n className=\"size-full object-contain\"\n {...imageProps}\n onError={onErrorHandler}\n />\n )}\n </AvatarBase>\n );\n },\n);\n\nAvatarFavicon.displayName = 'AvatarFavicon';\n"]}
1
+ {"version":3,"file":"AvatarFavicon.cjs","sourceRoot":"","sources":["../../../src/components/AvatarFavicon/AvatarFavicon.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yEAGwC;AACxC,+CAAoD;AAEpD,wDAA2C;AAI9B,QAAA,aAAa,GAAG,IAAA,kBAAU,EACrC,CACE,EACE,GAAG,EACH,IAAI,GAAG,EAAE,EACT,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,IAAI,GAAG,wCAAiB,CAAC,EAAE,EAC3B,UAAU,EACV,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,IAAA,gBAAQ,EAAS,EAAE,CAAC,CAAC;IACvE,MAAM,kBAAkB,GAAG,YAAY,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,yCAAyC;IAE9E,MAAM,cAAc,GAAG,CAAC,CAAyC,EAAE,EAAE;QACnE,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;QACzC,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,CACL,8BAAC,uBAAU,IACT,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,sCAAe,CAAC,MAAM,EAC7B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,EAC1D,iBAAiB,EAAE,iBAAiB,KAChC,KAAK,IAER,GAAG,IAAI,CACN,uCACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,SAAS,EAAC,0BAA0B,KAChC,UAAU,EACd,OAAO,EAAE,cAAc,GACvB,CACH,CACU,CACd,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,qBAAa,CAAC,WAAW,GAAG,eAAe,CAAC","sourcesContent":["import {\n AvatarBaseShape,\n AvatarFaviconSize,\n} from '@metamask/design-system-shared';\nimport React, { forwardRef, useState } from 'react';\n\nimport { AvatarBase } from '../AvatarBase';\n\nimport type { AvatarFaviconProps } from './AvatarFavicon.types';\n\nexport const AvatarFavicon = forwardRef<HTMLDivElement, AvatarFaviconProps>(\n (\n {\n src,\n name = '',\n fallbackText,\n fallbackTextProps,\n className,\n size = AvatarFaviconSize.Md,\n imageProps,\n ...props\n },\n ref,\n ) => {\n const [finalFallbackText, setFinalFallbackText] = useState<string>('');\n const backupFallbackText = fallbackText || name?.[0] || '?';\n const altText = name || 'Site logo'; // TBC: Add localization for default text\n\n const onErrorHandler = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setFinalFallbackText(backupFallbackText);\n imageProps?.onError?.(e);\n };\n\n return (\n <AvatarBase\n ref={ref}\n shape={AvatarBaseShape.Circle}\n size={size}\n className={className}\n fallbackText={src ? finalFallbackText : backupFallbackText}\n fallbackTextProps={fallbackTextProps}\n {...props}\n >\n {src && (\n <img\n src={src}\n alt={altText}\n className=\"size-full object-contain\"\n {...imageProps}\n onError={onErrorHandler}\n />\n )}\n </AvatarBase>\n );\n },\n);\n\nAvatarFavicon.displayName = 'AvatarFavicon';\n"]}
@@ -11,7 +11,7 @@ import { AvatarBase } from "../AvatarBase/index.mjs";
11
11
  export const AvatarFavicon = forwardRef(({ src, name = '', fallbackText, fallbackTextProps, className, size = AvatarFaviconSize.Md, imageProps, ...props }, ref) => {
12
12
  const [finalFallbackText, setFinalFallbackText] = useState('');
13
13
  const backupFallbackText = fallbackText || name?.[0] || '?';
14
- const altText = name || 'Dapp logo'; // TBC: Add localization for default text
14
+ const altText = name || 'Site logo'; // TBC: Add localization for default text
15
15
  const onErrorHandler = (e) => {
16
16
  setFinalFallbackText(backupFallbackText);
17
17
  imageProps?.onError?.(e);
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarFavicon.mjs","sourceRoot":"","sources":["../../../src/components/AvatarFavicon/AvatarFavicon.tsx"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACL,eAAe,EACf,iBAAiB,EAClB,uCAAuC;AACxC,OAAO,QAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc;;AAEpD,OAAO,EAAE,UAAU,EAAE,gCAAsB;AAI3C,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CACrC,CACE,EACE,GAAG,EACH,IAAI,GAAG,EAAE,EACT,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,IAAI,GAAG,iBAAiB,CAAC,EAAE,EAC3B,UAAU,EACV,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IACvE,MAAM,kBAAkB,GAAG,YAAY,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,yCAAyC;IAE9E,MAAM,cAAc,GAAG,CAAC,CAAyC,EAAE,EAAE;QACnE,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;QACzC,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,CACL,oBAAC,UAAU,IACT,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,eAAe,CAAC,MAAM,EAC7B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,EAC1D,iBAAiB,EAAE,iBAAiB,KAChC,KAAK,IAER,GAAG,IAAI,CACN,6BACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,SAAS,EAAC,0BAA0B,KAChC,UAAU,EACd,OAAO,EAAE,cAAc,GACvB,CACH,CACU,CACd,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC","sourcesContent":["import {\n AvatarBaseShape,\n AvatarFaviconSize,\n} from '@metamask/design-system-shared';\nimport React, { forwardRef, useState } from 'react';\n\nimport { AvatarBase } from '../AvatarBase';\n\nimport type { AvatarFaviconProps } from './AvatarFavicon.types';\n\nexport const AvatarFavicon = forwardRef<HTMLDivElement, AvatarFaviconProps>(\n (\n {\n src,\n name = '',\n fallbackText,\n fallbackTextProps,\n className,\n size = AvatarFaviconSize.Md,\n imageProps,\n ...props\n },\n ref,\n ) => {\n const [finalFallbackText, setFinalFallbackText] = useState<string>('');\n const backupFallbackText = fallbackText || name?.[0] || '?';\n const altText = name || 'Dapp logo'; // TBC: Add localization for default text\n\n const onErrorHandler = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setFinalFallbackText(backupFallbackText);\n imageProps?.onError?.(e);\n };\n\n return (\n <AvatarBase\n ref={ref}\n shape={AvatarBaseShape.Circle}\n size={size}\n className={className}\n fallbackText={src ? finalFallbackText : backupFallbackText}\n fallbackTextProps={fallbackTextProps}\n {...props}\n >\n {src && (\n <img\n src={src}\n alt={altText}\n className=\"size-full object-contain\"\n {...imageProps}\n onError={onErrorHandler}\n />\n )}\n </AvatarBase>\n );\n },\n);\n\nAvatarFavicon.displayName = 'AvatarFavicon';\n"]}
1
+ {"version":3,"file":"AvatarFavicon.mjs","sourceRoot":"","sources":["../../../src/components/AvatarFavicon/AvatarFavicon.tsx"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACL,eAAe,EACf,iBAAiB,EAClB,uCAAuC;AACxC,OAAO,QAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc;;AAEpD,OAAO,EAAE,UAAU,EAAE,gCAAsB;AAI3C,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CACrC,CACE,EACE,GAAG,EACH,IAAI,GAAG,EAAE,EACT,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,IAAI,GAAG,iBAAiB,CAAC,EAAE,EAC3B,UAAU,EACV,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IACvE,MAAM,kBAAkB,GAAG,YAAY,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,yCAAyC;IAE9E,MAAM,cAAc,GAAG,CAAC,CAAyC,EAAE,EAAE;QACnE,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;QACzC,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,OAAO,CACL,oBAAC,UAAU,IACT,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,eAAe,CAAC,MAAM,EAC7B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,EAC1D,iBAAiB,EAAE,iBAAiB,KAChC,KAAK,IAER,GAAG,IAAI,CACN,6BACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,EACZ,SAAS,EAAC,0BAA0B,KAChC,UAAU,EACd,OAAO,EAAE,cAAc,GACvB,CACH,CACU,CACd,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC","sourcesContent":["import {\n AvatarBaseShape,\n AvatarFaviconSize,\n} from '@metamask/design-system-shared';\nimport React, { forwardRef, useState } from 'react';\n\nimport { AvatarBase } from '../AvatarBase';\n\nimport type { AvatarFaviconProps } from './AvatarFavicon.types';\n\nexport const AvatarFavicon = forwardRef<HTMLDivElement, AvatarFaviconProps>(\n (\n {\n src,\n name = '',\n fallbackText,\n fallbackTextProps,\n className,\n size = AvatarFaviconSize.Md,\n imageProps,\n ...props\n },\n ref,\n ) => {\n const [finalFallbackText, setFinalFallbackText] = useState<string>('');\n const backupFallbackText = fallbackText || name?.[0] || '?';\n const altText = name || 'Site logo'; // TBC: Add localization for default text\n\n const onErrorHandler = (e: React.SyntheticEvent<HTMLImageElement>) => {\n setFinalFallbackText(backupFallbackText);\n imageProps?.onError?.(e);\n };\n\n return (\n <AvatarBase\n ref={ref}\n shape={AvatarBaseShape.Circle}\n size={size}\n className={className}\n fallbackText={src ? finalFallbackText : backupFallbackText}\n fallbackTextProps={fallbackTextProps}\n {...props}\n >\n {src && (\n <img\n src={src}\n alt={altText}\n className=\"size-full object-contain\"\n {...imageProps}\n onError={onErrorHandler}\n />\n )}\n </AvatarBase>\n );\n },\n);\n\nAvatarFavicon.displayName = 'AvatarFavicon';\n"]}
@@ -27,66 +27,31 @@ exports.BadgeWrapper = void 0;
27
27
  const design_system_shared_1 = require("@metamask/design-system-shared");
28
28
  const react_1 = __importStar(require("react"));
29
29
  const tw_merge_1 = require("../../utils/tw-merge.cjs");
30
+ const CIRCULAR_ANCHOR_EDGE_INSET = '7%';
31
+ const RECTANGULAR_ANCHOR_EDGE_INSET = '11%';
32
+ const getTransformValue = (percentage, offset) => offset === 0 ? percentage : `calc(${percentage} + ${offset}px)`;
30
33
  exports.BadgeWrapper = (0, react_1.forwardRef)(({ children, childrenContainerProps, badge, badgeContainerProps, position = design_system_shared_1.BadgeWrapperPosition.BottomRight, positionAnchorShape = design_system_shared_1.BadgeWrapperPositionAnchorShape.Circular, positionXOffset = 0, positionYOffset = 0, customPosition, className = '', style, ...props }, ref) => {
31
- const [anchorWidth, setAnchorWidth] = (0, react_1.useState)(0);
32
- const [anchorHeight, setAnchorHeight] = (0, react_1.useState)(0);
33
- const [badgeWidth, setBadgeWidth] = (0, react_1.useState)(0);
34
- const [badgeHeight, setBadgeHeight] = (0, react_1.useState)(0);
35
- const anchorRef = (0, react_1.useRef)(null);
36
- const badgeRef = (0, react_1.useRef)(null);
37
- // Measure both elements once on mount
38
- (0, react_1.useLayoutEffect)(() => {
39
- if (anchorRef.current) {
40
- const { width, height } = anchorRef.current.getBoundingClientRect();
41
- setAnchorWidth(width);
42
- setAnchorHeight(height);
43
- }
44
- if (badgeRef.current) {
45
- const { width, height } = badgeRef.current.getBoundingClientRect();
46
- setBadgeWidth(width);
47
- setBadgeHeight(height);
48
- }
49
- }, []); // empty deps → run only after first render
50
- const finalPositions = (0, react_1.useMemo)(() => {
51
- if (customPosition) {
52
- return customPosition;
53
- }
54
- const anchorShapeXOffset = positionAnchorShape === design_system_shared_1.BadgeWrapperPositionAnchorShape.Rectangular
55
- ? 0
56
- : anchorWidth * 0.1464;
57
- const anchorShapeYOffset = positionAnchorShape === design_system_shared_1.BadgeWrapperPositionAnchorShape.Rectangular
58
- ? 0
59
- : anchorHeight * 0.1464;
60
- const badgeCenteringXOffset = badgeWidth / 2;
61
- const badgeCenteringYOffset = badgeHeight / 2;
62
- const finalXOffset = anchorShapeXOffset - badgeCenteringXOffset + positionXOffset;
63
- const finalYOffset = anchorShapeYOffset - badgeCenteringYOffset + positionYOffset;
64
- switch (position) {
65
- case design_system_shared_1.BadgeWrapperPosition.TopRight:
66
- return { top: finalYOffset, right: finalXOffset };
67
- case design_system_shared_1.BadgeWrapperPosition.TopLeft:
68
- return { top: finalYOffset, left: finalXOffset };
69
- case design_system_shared_1.BadgeWrapperPosition.BottomLeft:
70
- return { bottom: finalYOffset, left: finalXOffset };
71
- case design_system_shared_1.BadgeWrapperPosition.BottomRight:
72
- default:
73
- return { bottom: finalYOffset, right: finalXOffset };
74
- }
75
- }, [
76
- position,
77
- positionAnchorShape,
78
- anchorWidth,
79
- anchorHeight,
80
- badgeWidth,
81
- badgeHeight,
82
- positionXOffset,
83
- positionYOffset,
84
- customPosition,
85
- ]);
34
+ const isTop = position === design_system_shared_1.BadgeWrapperPosition.TopRight ||
35
+ position === design_system_shared_1.BadgeWrapperPosition.TopLeft;
36
+ const isLeft = position === design_system_shared_1.BadgeWrapperPosition.TopLeft ||
37
+ position === design_system_shared_1.BadgeWrapperPosition.BottomLeft;
38
+ const edgeInset = positionAnchorShape === design_system_shared_1.BadgeWrapperPositionAnchorShape.Circular
39
+ ? CIRCULAR_ANCHOR_EDGE_INSET
40
+ : RECTANGULAR_ANCHOR_EDGE_INSET;
41
+ const finalPositions = customPosition
42
+ ? customPosition
43
+ : {
44
+ ...(isTop ? { top: edgeInset } : { bottom: edgeInset }),
45
+ ...(isLeft ? { left: edgeInset } : { right: edgeInset }),
46
+ transform: `translate(${getTransformValue(isLeft ? '-50%' : '50%', positionXOffset)}, ${getTransformValue(isTop ? '-50%' : '50%', positionYOffset)})`,
47
+ };
86
48
  const containerClassName = (0, tw_merge_1.twMerge)('relative inline-flex self-start', className);
87
49
  return (react_1.default.createElement("div", { ref: ref, className: containerClassName, style: style, ...props },
88
- react_1.default.createElement("div", { className: "inline-flex", ref: anchorRef, ...childrenContainerProps }, children),
89
- react_1.default.createElement("div", { ref: badgeRef, className: "absolute", style: finalPositions, ...badgeContainerProps }, badge)));
50
+ react_1.default.createElement("div", { className: "inline-flex", ...childrenContainerProps }, children),
51
+ react_1.default.createElement("div", { ...badgeContainerProps, className: (0, tw_merge_1.twMerge)('absolute inline-flex items-center justify-center', badgeContainerProps?.className), style: {
52
+ ...finalPositions,
53
+ ...badgeContainerProps?.style,
54
+ } }, badge)));
90
55
  });
91
56
  exports.BadgeWrapper.displayName = 'BadgeWrapper';
92
57
  //# sourceMappingURL=BadgeWrapper.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BadgeWrapper.cjs","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n BadgeWrapperPosition,\n BadgeWrapperPositionAnchorShape,\n} from '@metamask/design-system-shared';\nimport type { CSSProperties } from 'react';\nimport React, {\n forwardRef,\n useState,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { twMerge } from '../../utils/tw-merge';\n\nimport type { BadgeWrapperProps } from './BadgeWrapper.types';\n\nexport const BadgeWrapper = forwardRef<HTMLDivElement, BadgeWrapperProps>(\n (\n {\n children,\n childrenContainerProps,\n badge,\n badgeContainerProps,\n position = BadgeWrapperPosition.BottomRight,\n positionAnchorShape = BadgeWrapperPositionAnchorShape.Circular,\n positionXOffset = 0,\n positionYOffset = 0,\n customPosition,\n className = '',\n style,\n ...props\n },\n ref,\n ) => {\n const [anchorWidth, setAnchorWidth] = useState(0);\n const [anchorHeight, setAnchorHeight] = useState(0);\n const [badgeWidth, setBadgeWidth] = useState(0);\n const [badgeHeight, setBadgeHeight] = useState(0);\n\n const anchorRef = useRef<HTMLDivElement | null>(null);\n const badgeRef = useRef<HTMLDivElement | null>(null);\n\n // Measure both elements once on mount\n useLayoutEffect(() => {\n if (anchorRef.current) {\n const { width, height } = anchorRef.current.getBoundingClientRect();\n setAnchorWidth(width);\n setAnchorHeight(height);\n }\n if (badgeRef.current) {\n const { width, height } = badgeRef.current.getBoundingClientRect();\n setBadgeWidth(width);\n setBadgeHeight(height);\n }\n }, []); // empty deps → run only after first render\n\n const finalPositions = useMemo<React.CSSProperties>(() => {\n if (customPosition) {\n return customPosition as CSSProperties;\n }\n\n const anchorShapeXOffset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular\n ? 0\n : anchorWidth * 0.1464;\n const anchorShapeYOffset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular\n ? 0\n : anchorHeight * 0.1464;\n\n const badgeCenteringXOffset = badgeWidth / 2;\n const badgeCenteringYOffset = badgeHeight / 2;\n\n const finalXOffset =\n anchorShapeXOffset - badgeCenteringXOffset + positionXOffset;\n const finalYOffset =\n anchorShapeYOffset - badgeCenteringYOffset + positionYOffset;\n\n switch (position) {\n case BadgeWrapperPosition.TopRight:\n return { top: finalYOffset, right: finalXOffset };\n case BadgeWrapperPosition.TopLeft:\n return { top: finalYOffset, left: finalXOffset };\n case BadgeWrapperPosition.BottomLeft:\n return { bottom: finalYOffset, left: finalXOffset };\n case BadgeWrapperPosition.BottomRight:\n default:\n return { bottom: finalYOffset, right: finalXOffset };\n }\n }, [\n position,\n positionAnchorShape,\n anchorWidth,\n anchorHeight,\n badgeWidth,\n badgeHeight,\n positionXOffset,\n positionYOffset,\n customPosition,\n ]);\n\n const containerClassName = twMerge(\n 'relative inline-flex self-start',\n className,\n );\n\n return (\n <div ref={ref} className={containerClassName} style={style} {...props}>\n <div\n className=\"inline-flex\"\n ref={anchorRef}\n {...childrenContainerProps}\n >\n {children}\n </div>\n\n <div\n ref={badgeRef}\n className=\"absolute\"\n style={finalPositions}\n {...badgeContainerProps}\n >\n {badge}\n </div>\n </div>\n );\n },\n);\n\nBadgeWrapper.displayName = 'BadgeWrapper';\n"]}
1
+ {"version":3,"file":"BadgeWrapper.cjs","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yEAGwC;AAExC,+CAA0C;AAE1C,uDAA+C;AAI/C,MAAM,0BAA0B,GAAG,IAAI,CAAC;AACxC,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAE5C,MAAM,iBAAiB,GAAG,CAAC,UAAkB,EAAE,MAAc,EAAE,EAAE,CAC/D,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,UAAU,MAAM,MAAM,KAAK,CAAC;AAErD,QAAA,YAAY,GAAG,IAAA,kBAAU,EACpC,CACE,EACE,QAAQ,EACR,sBAAsB,EACtB,KAAK,EACL,mBAAmB,EACnB,QAAQ,GAAG,2CAAoB,CAAC,WAAW,EAC3C,mBAAmB,GAAG,sDAA+B,CAAC,QAAQ,EAC9D,eAAe,GAAG,CAAC,EACnB,eAAe,GAAG,CAAC,EACnB,cAAc,EACd,SAAS,GAAG,EAAE,EACd,KAAK,EACL,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,KAAK,GACT,QAAQ,KAAK,2CAAoB,CAAC,QAAQ;QAC1C,QAAQ,KAAK,2CAAoB,CAAC,OAAO,CAAC;IAC5C,MAAM,MAAM,GACV,QAAQ,KAAK,2CAAoB,CAAC,OAAO;QACzC,QAAQ,KAAK,2CAAoB,CAAC,UAAU,CAAC;IAC/C,MAAM,SAAS,GACb,mBAAmB,KAAK,sDAA+B,CAAC,QAAQ;QAC9D,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,6BAA6B,CAAC;IACpC,MAAM,cAAc,GAAwB,cAAc;QACxD,CAAC,CAAE,cAAgC;QACnC,CAAC,CAAC;YACE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACvD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YACxD,SAAS,EAAE,aAAa,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG;SACtJ,CAAC;IAEN,MAAM,kBAAkB,GAAG,IAAA,kBAAO,EAChC,iCAAiC,EACjC,SAAS,CACV,CAAC;IAEF,OAAO,CACL,uCAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAE,KAAK,KAAM,KAAK;QACnE,uCAAK,SAAS,EAAC,aAAa,KAAK,sBAAsB,IACpD,QAAQ,CACL;QAEN,0CACM,mBAAmB,EACvB,SAAS,EAAE,IAAA,kBAAO,EAChB,kDAAkD,EAClD,mBAAmB,EAAE,SAAS,CAC/B,EACD,KAAK,EAAE;gBACL,GAAG,cAAc;gBACjB,GAAI,mBAAmB,EAAE,KAAuB;aACjD,IAEA,KAAK,CACF,CACF,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,oBAAY,CAAC,WAAW,GAAG,cAAc,CAAC","sourcesContent":["import {\n BadgeWrapperPosition,\n BadgeWrapperPositionAnchorShape,\n} from '@metamask/design-system-shared';\nimport type { CSSProperties } from 'react';\nimport React, { forwardRef } from 'react';\n\nimport { twMerge } from '../../utils/tw-merge';\n\nimport type { BadgeWrapperProps } from './BadgeWrapper.types';\n\nconst CIRCULAR_ANCHOR_EDGE_INSET = '7%';\nconst RECTANGULAR_ANCHOR_EDGE_INSET = '11%';\n\nconst getTransformValue = (percentage: string, offset: number) =>\n offset === 0 ? percentage : `calc(${percentage} + ${offset}px)`;\n\nexport const BadgeWrapper = forwardRef<HTMLDivElement, BadgeWrapperProps>(\n (\n {\n children,\n childrenContainerProps,\n badge,\n badgeContainerProps,\n position = BadgeWrapperPosition.BottomRight,\n positionAnchorShape = BadgeWrapperPositionAnchorShape.Circular,\n positionXOffset = 0,\n positionYOffset = 0,\n customPosition,\n className = '',\n style,\n ...props\n },\n ref,\n ) => {\n const isTop =\n position === BadgeWrapperPosition.TopRight ||\n position === BadgeWrapperPosition.TopLeft;\n const isLeft =\n position === BadgeWrapperPosition.TopLeft ||\n position === BadgeWrapperPosition.BottomLeft;\n const edgeInset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Circular\n ? CIRCULAR_ANCHOR_EDGE_INSET\n : RECTANGULAR_ANCHOR_EDGE_INSET;\n const finalPositions: React.CSSProperties = customPosition\n ? (customPosition as CSSProperties)\n : {\n ...(isTop ? { top: edgeInset } : { bottom: edgeInset }),\n ...(isLeft ? { left: edgeInset } : { right: edgeInset }),\n transform: `translate(${getTransformValue(isLeft ? '-50%' : '50%', positionXOffset)}, ${getTransformValue(isTop ? '-50%' : '50%', positionYOffset)})`,\n };\n\n const containerClassName = twMerge(\n 'relative inline-flex self-start',\n className,\n );\n\n return (\n <div ref={ref} className={containerClassName} style={style} {...props}>\n <div className=\"inline-flex\" {...childrenContainerProps}>\n {children}\n </div>\n\n <div\n {...badgeContainerProps}\n className={twMerge(\n 'absolute inline-flex items-center justify-center',\n badgeContainerProps?.className,\n )}\n style={{\n ...finalPositions,\n ...(badgeContainerProps?.style as CSSProperties),\n }}\n >\n {badge}\n </div>\n </div>\n );\n },\n);\n\nBadgeWrapper.displayName = 'BadgeWrapper';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"BadgeWrapper.d.cts","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAMN,cAAc;AAIf,OAAO,KAAK,EAAE,iBAAiB,EAAE,iCAA6B;AAE9D,eAAO,MAAM,YAAY,uGA+GxB,CAAC"}
1
+ {"version":3,"file":"BadgeWrapper.d.cts","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAqB,cAAc;AAI1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,iCAA6B;AAQ9D,eAAO,MAAM,YAAY,uGA+DxB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"BadgeWrapper.d.mts","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAMN,cAAc;AAIf,OAAO,KAAK,EAAE,iBAAiB,EAAE,iCAA6B;AAE9D,eAAO,MAAM,YAAY,uGA+GxB,CAAC"}
1
+ {"version":3,"file":"BadgeWrapper.d.mts","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAqB,cAAc;AAI1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,iCAA6B;AAQ9D,eAAO,MAAM,YAAY,uGA+DxB,CAAC"}
@@ -5,69 +5,34 @@ function $importDefault(module) {
5
5
  return module;
6
6
  }
7
7
  import { BadgeWrapperPosition, BadgeWrapperPositionAnchorShape } from "@metamask/design-system-shared";
8
- import $React, { forwardRef, useState, useLayoutEffect, useMemo, useRef } from "react";
8
+ import $React, { forwardRef } from "react";
9
9
  const React = $importDefault($React);
10
10
  import { twMerge } from "../../utils/tw-merge.mjs";
11
+ const CIRCULAR_ANCHOR_EDGE_INSET = '7%';
12
+ const RECTANGULAR_ANCHOR_EDGE_INSET = '11%';
13
+ const getTransformValue = (percentage, offset) => offset === 0 ? percentage : `calc(${percentage} + ${offset}px)`;
11
14
  export const BadgeWrapper = forwardRef(({ children, childrenContainerProps, badge, badgeContainerProps, position = BadgeWrapperPosition.BottomRight, positionAnchorShape = BadgeWrapperPositionAnchorShape.Circular, positionXOffset = 0, positionYOffset = 0, customPosition, className = '', style, ...props }, ref) => {
12
- const [anchorWidth, setAnchorWidth] = useState(0);
13
- const [anchorHeight, setAnchorHeight] = useState(0);
14
- const [badgeWidth, setBadgeWidth] = useState(0);
15
- const [badgeHeight, setBadgeHeight] = useState(0);
16
- const anchorRef = useRef(null);
17
- const badgeRef = useRef(null);
18
- // Measure both elements once on mount
19
- useLayoutEffect(() => {
20
- if (anchorRef.current) {
21
- const { width, height } = anchorRef.current.getBoundingClientRect();
22
- setAnchorWidth(width);
23
- setAnchorHeight(height);
24
- }
25
- if (badgeRef.current) {
26
- const { width, height } = badgeRef.current.getBoundingClientRect();
27
- setBadgeWidth(width);
28
- setBadgeHeight(height);
29
- }
30
- }, []); // empty deps → run only after first render
31
- const finalPositions = useMemo(() => {
32
- if (customPosition) {
33
- return customPosition;
34
- }
35
- const anchorShapeXOffset = positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular
36
- ? 0
37
- : anchorWidth * 0.1464;
38
- const anchorShapeYOffset = positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular
39
- ? 0
40
- : anchorHeight * 0.1464;
41
- const badgeCenteringXOffset = badgeWidth / 2;
42
- const badgeCenteringYOffset = badgeHeight / 2;
43
- const finalXOffset = anchorShapeXOffset - badgeCenteringXOffset + positionXOffset;
44
- const finalYOffset = anchorShapeYOffset - badgeCenteringYOffset + positionYOffset;
45
- switch (position) {
46
- case BadgeWrapperPosition.TopRight:
47
- return { top: finalYOffset, right: finalXOffset };
48
- case BadgeWrapperPosition.TopLeft:
49
- return { top: finalYOffset, left: finalXOffset };
50
- case BadgeWrapperPosition.BottomLeft:
51
- return { bottom: finalYOffset, left: finalXOffset };
52
- case BadgeWrapperPosition.BottomRight:
53
- default:
54
- return { bottom: finalYOffset, right: finalXOffset };
55
- }
56
- }, [
57
- position,
58
- positionAnchorShape,
59
- anchorWidth,
60
- anchorHeight,
61
- badgeWidth,
62
- badgeHeight,
63
- positionXOffset,
64
- positionYOffset,
65
- customPosition,
66
- ]);
15
+ const isTop = position === BadgeWrapperPosition.TopRight ||
16
+ position === BadgeWrapperPosition.TopLeft;
17
+ const isLeft = position === BadgeWrapperPosition.TopLeft ||
18
+ position === BadgeWrapperPosition.BottomLeft;
19
+ const edgeInset = positionAnchorShape === BadgeWrapperPositionAnchorShape.Circular
20
+ ? CIRCULAR_ANCHOR_EDGE_INSET
21
+ : RECTANGULAR_ANCHOR_EDGE_INSET;
22
+ const finalPositions = customPosition
23
+ ? customPosition
24
+ : {
25
+ ...(isTop ? { top: edgeInset } : { bottom: edgeInset }),
26
+ ...(isLeft ? { left: edgeInset } : { right: edgeInset }),
27
+ transform: `translate(${getTransformValue(isLeft ? '-50%' : '50%', positionXOffset)}, ${getTransformValue(isTop ? '-50%' : '50%', positionYOffset)})`,
28
+ };
67
29
  const containerClassName = twMerge('relative inline-flex self-start', className);
68
30
  return (React.createElement("div", { ref: ref, className: containerClassName, style: style, ...props },
69
- React.createElement("div", { className: "inline-flex", ref: anchorRef, ...childrenContainerProps }, children),
70
- React.createElement("div", { ref: badgeRef, className: "absolute", style: finalPositions, ...badgeContainerProps }, badge)));
31
+ React.createElement("div", { className: "inline-flex", ...childrenContainerProps }, children),
32
+ React.createElement("div", { ...badgeContainerProps, className: twMerge('absolute inline-flex items-center justify-center', badgeContainerProps?.className), style: {
33
+ ...finalPositions,
34
+ ...badgeContainerProps?.style,
35
+ } }, badge)));
71
36
  });
72
37
  BadgeWrapper.displayName = 'BadgeWrapper';
73
38
  //# sourceMappingURL=BadgeWrapper.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BadgeWrapper.mjs","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n BadgeWrapperPosition,\n BadgeWrapperPositionAnchorShape,\n} from '@metamask/design-system-shared';\nimport type { CSSProperties } from 'react';\nimport React, {\n forwardRef,\n useState,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { twMerge } from '../../utils/tw-merge';\n\nimport type { BadgeWrapperProps } from './BadgeWrapper.types';\n\nexport const BadgeWrapper = forwardRef<HTMLDivElement, BadgeWrapperProps>(\n (\n {\n children,\n childrenContainerProps,\n badge,\n badgeContainerProps,\n position = BadgeWrapperPosition.BottomRight,\n positionAnchorShape = BadgeWrapperPositionAnchorShape.Circular,\n positionXOffset = 0,\n positionYOffset = 0,\n customPosition,\n className = '',\n style,\n ...props\n },\n ref,\n ) => {\n const [anchorWidth, setAnchorWidth] = useState(0);\n const [anchorHeight, setAnchorHeight] = useState(0);\n const [badgeWidth, setBadgeWidth] = useState(0);\n const [badgeHeight, setBadgeHeight] = useState(0);\n\n const anchorRef = useRef<HTMLDivElement | null>(null);\n const badgeRef = useRef<HTMLDivElement | null>(null);\n\n // Measure both elements once on mount\n useLayoutEffect(() => {\n if (anchorRef.current) {\n const { width, height } = anchorRef.current.getBoundingClientRect();\n setAnchorWidth(width);\n setAnchorHeight(height);\n }\n if (badgeRef.current) {\n const { width, height } = badgeRef.current.getBoundingClientRect();\n setBadgeWidth(width);\n setBadgeHeight(height);\n }\n }, []); // empty deps → run only after first render\n\n const finalPositions = useMemo<React.CSSProperties>(() => {\n if (customPosition) {\n return customPosition as CSSProperties;\n }\n\n const anchorShapeXOffset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular\n ? 0\n : anchorWidth * 0.1464;\n const anchorShapeYOffset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Rectangular\n ? 0\n : anchorHeight * 0.1464;\n\n const badgeCenteringXOffset = badgeWidth / 2;\n const badgeCenteringYOffset = badgeHeight / 2;\n\n const finalXOffset =\n anchorShapeXOffset - badgeCenteringXOffset + positionXOffset;\n const finalYOffset =\n anchorShapeYOffset - badgeCenteringYOffset + positionYOffset;\n\n switch (position) {\n case BadgeWrapperPosition.TopRight:\n return { top: finalYOffset, right: finalXOffset };\n case BadgeWrapperPosition.TopLeft:\n return { top: finalYOffset, left: finalXOffset };\n case BadgeWrapperPosition.BottomLeft:\n return { bottom: finalYOffset, left: finalXOffset };\n case BadgeWrapperPosition.BottomRight:\n default:\n return { bottom: finalYOffset, right: finalXOffset };\n }\n }, [\n position,\n positionAnchorShape,\n anchorWidth,\n anchorHeight,\n badgeWidth,\n badgeHeight,\n positionXOffset,\n positionYOffset,\n customPosition,\n ]);\n\n const containerClassName = twMerge(\n 'relative inline-flex self-start',\n className,\n );\n\n return (\n <div ref={ref} className={containerClassName} style={style} {...props}>\n <div\n className=\"inline-flex\"\n ref={anchorRef}\n {...childrenContainerProps}\n >\n {children}\n </div>\n\n <div\n ref={badgeRef}\n className=\"absolute\"\n style={finalPositions}\n {...badgeContainerProps}\n >\n {badge}\n </div>\n </div>\n );\n },\n);\n\nBadgeWrapper.displayName = 'BadgeWrapper';\n"]}
1
+ {"version":3,"file":"BadgeWrapper.mjs","sourceRoot":"","sources":["../../../src/components/BadgeWrapper/BadgeWrapper.tsx"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAChC,uCAAuC;AAExC,OAAO,QAAO,EAAE,UAAU,EAAE,cAAc;;AAE1C,OAAO,EAAE,OAAO,EAAE,iCAA6B;AAI/C,MAAM,0BAA0B,GAAG,IAAI,CAAC;AACxC,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAE5C,MAAM,iBAAiB,GAAG,CAAC,UAAkB,EAAE,MAAc,EAAE,EAAE,CAC/D,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,UAAU,MAAM,MAAM,KAAK,CAAC;AAElE,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CACpC,CACE,EACE,QAAQ,EACR,sBAAsB,EACtB,KAAK,EACL,mBAAmB,EACnB,QAAQ,GAAG,oBAAoB,CAAC,WAAW,EAC3C,mBAAmB,GAAG,+BAA+B,CAAC,QAAQ,EAC9D,eAAe,GAAG,CAAC,EACnB,eAAe,GAAG,CAAC,EACnB,cAAc,EACd,SAAS,GAAG,EAAE,EACd,KAAK,EACL,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,KAAK,GACT,QAAQ,KAAK,oBAAoB,CAAC,QAAQ;QAC1C,QAAQ,KAAK,oBAAoB,CAAC,OAAO,CAAC;IAC5C,MAAM,MAAM,GACV,QAAQ,KAAK,oBAAoB,CAAC,OAAO;QACzC,QAAQ,KAAK,oBAAoB,CAAC,UAAU,CAAC;IAC/C,MAAM,SAAS,GACb,mBAAmB,KAAK,+BAA+B,CAAC,QAAQ;QAC9D,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,6BAA6B,CAAC;IACpC,MAAM,cAAc,GAAwB,cAAc;QACxD,CAAC,CAAE,cAAgC;QACnC,CAAC,CAAC;YACE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACvD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YACxD,SAAS,EAAE,aAAa,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG;SACtJ,CAAC;IAEN,MAAM,kBAAkB,GAAG,OAAO,CAChC,iCAAiC,EACjC,SAAS,CACV,CAAC;IAEF,OAAO,CACL,6BAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAE,KAAK,KAAM,KAAK;QACnE,6BAAK,SAAS,EAAC,aAAa,KAAK,sBAAsB,IACpD,QAAQ,CACL;QAEN,gCACM,mBAAmB,EACvB,SAAS,EAAE,OAAO,CAChB,kDAAkD,EAClD,mBAAmB,EAAE,SAAS,CAC/B,EACD,KAAK,EAAE;gBACL,GAAG,cAAc;gBACjB,GAAI,mBAAmB,EAAE,KAAuB;aACjD,IAEA,KAAK,CACF,CACF,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,YAAY,CAAC,WAAW,GAAG,cAAc,CAAC","sourcesContent":["import {\n BadgeWrapperPosition,\n BadgeWrapperPositionAnchorShape,\n} from '@metamask/design-system-shared';\nimport type { CSSProperties } from 'react';\nimport React, { forwardRef } from 'react';\n\nimport { twMerge } from '../../utils/tw-merge';\n\nimport type { BadgeWrapperProps } from './BadgeWrapper.types';\n\nconst CIRCULAR_ANCHOR_EDGE_INSET = '7%';\nconst RECTANGULAR_ANCHOR_EDGE_INSET = '11%';\n\nconst getTransformValue = (percentage: string, offset: number) =>\n offset === 0 ? percentage : `calc(${percentage} + ${offset}px)`;\n\nexport const BadgeWrapper = forwardRef<HTMLDivElement, BadgeWrapperProps>(\n (\n {\n children,\n childrenContainerProps,\n badge,\n badgeContainerProps,\n position = BadgeWrapperPosition.BottomRight,\n positionAnchorShape = BadgeWrapperPositionAnchorShape.Circular,\n positionXOffset = 0,\n positionYOffset = 0,\n customPosition,\n className = '',\n style,\n ...props\n },\n ref,\n ) => {\n const isTop =\n position === BadgeWrapperPosition.TopRight ||\n position === BadgeWrapperPosition.TopLeft;\n const isLeft =\n position === BadgeWrapperPosition.TopLeft ||\n position === BadgeWrapperPosition.BottomLeft;\n const edgeInset =\n positionAnchorShape === BadgeWrapperPositionAnchorShape.Circular\n ? CIRCULAR_ANCHOR_EDGE_INSET\n : RECTANGULAR_ANCHOR_EDGE_INSET;\n const finalPositions: React.CSSProperties = customPosition\n ? (customPosition as CSSProperties)\n : {\n ...(isTop ? { top: edgeInset } : { bottom: edgeInset }),\n ...(isLeft ? { left: edgeInset } : { right: edgeInset }),\n transform: `translate(${getTransformValue(isLeft ? '-50%' : '50%', positionXOffset)}, ${getTransformValue(isTop ? '-50%' : '50%', positionYOffset)})`,\n };\n\n const containerClassName = twMerge(\n 'relative inline-flex self-start',\n className,\n );\n\n return (\n <div ref={ref} className={containerClassName} style={style} {...props}>\n <div className=\"inline-flex\" {...childrenContainerProps}>\n {children}\n </div>\n\n <div\n {...badgeContainerProps}\n className={twMerge(\n 'absolute inline-flex items-center justify-center',\n badgeContainerProps?.className,\n )}\n style={{\n ...finalPositions,\n ...(badgeContainerProps?.style as CSSProperties),\n }}\n >\n {badge}\n </div>\n </div>\n );\n },\n);\n\nBadgeWrapper.displayName = 'BadgeWrapper';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/design-system-react",
3
- "version": "0.38.0",
3
+ "version": "0.38.1",
4
4
  "description": "Design system react ui components",
5
5
  "keywords": [
6
6
  "MetaMask",