@ringcentral/juno 2.1.1 → 2.1.2

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.
@@ -11,8 +11,17 @@ declare type RcBadgeProps = {
11
11
  borderColor?: RcPaletteKeys;
12
12
  /** The component used for the root node. Either a string to use a HTML element or a component. */
13
13
  component?: ElementType;
14
- /** Wrapped shape the badge should overlap */
15
- overlap?: UnionPick<NonNullable<ComponentProps<typeof MuiBadge>['overlap']>, 'circular' | 'rectangular'> | 'none';
14
+ /**
15
+ * Wrapped shape the badge should overlap
16
+ * - `circular`: for circular children
17
+ * - `rectangular`: for rectangular children
18
+ * - `round`: for round radius rectangular children, like
19
+ * ```jsx
20
+ * <RcButton radius="round">click</RcButton>
21
+ * ```
22
+ * - `none`: not do any overlap on that badge
23
+ */
24
+ overlap?: UnionPick<NonNullable<ComponentProps<typeof MuiBadge>['overlap']>, 'circular' | 'rectangular'> | 'none' | 'round';
16
25
  /**
17
26
  * Custom dot render Component in `dot` mode
18
27
  * if you don't want any dot, you can set `null`
@@ -13,9 +13,31 @@ var utils_2 = require("./utils");
13
13
  var _RcBadge = react_1.forwardRef(function (inProps, ref) {
14
14
  var props = foundation_1.useThemeProps({ props: inProps, name: 'RcBadge' });
15
15
  var classesProp = props.classes, children = props.children, overlap = props.overlap, color = props.color, variant = props.variant, textColor = props.textColor, anchorOrigin = props.anchorOrigin, borderColor = props.borderColor, component = props.component, dotComponent = props.dotComponent, dotProps = props.dotProps, rest = tslib_1.__rest(props, ["classes", "children", "overlap", "color", "variant", "textColor", "anchorOrigin", "borderColor", "component", "dotComponent", "dotProps"]);
16
+ // * should never change overlap
17
+ if (process.env.NODE_ENV !== 'production') {
18
+ // eslint-disable-next-line react-hooks/rules-of-hooks
19
+ foundation_1.useChange(function (prev) {
20
+ if (!prev)
21
+ return;
22
+ foundation_1.logInDev({
23
+ component: 'RcBadge',
24
+ message: 'Should not change `overlap` prop after component render',
25
+ level: 'error',
26
+ });
27
+ }, function () { return overlap; });
28
+ }
29
+ var innerRef = react_1.useRef(null);
30
+ var badgeRef = foundation_1.useForkRef(innerRef, ref);
31
+ var isRound = overlap === 'round';
32
+ var isDot = variant === 'dot';
33
+ var notPassOverlapToMui = overlap !== 'none' && !isRound;
34
+ // overlap will never change in production mode
35
+ if (isRound) {
36
+ // eslint-disable-next-line react-hooks/rules-of-hooks
37
+ utils_2.useRoundBadgeOffset(innerRef);
38
+ }
16
39
  var classes = react_1.useMemo(function () { return foundation_1.combineProps(utils_2.RcBadgeClasses, classesProp); }, [classesProp]);
17
40
  var CustomDotBadge = react_1.useMemo(function () {
18
- var isDot = variant === 'dot';
19
41
  return isDot
20
42
  ? react_1.forwardRef(function (_a, ref) {
21
43
  var OmitChildren = _a.children, rest = tslib_1.__rest(_a, ["children"]);
@@ -29,8 +51,10 @@ var _RcBadge = react_1.forwardRef(function (inProps, ref) {
29
51
  react_1.default.createElement(DotComponent, tslib_1.__assign({}, applyDotProps))))));
30
52
  })
31
53
  : undefined;
32
- }, [anchorOrigin, children, dotComponent, dotProps, overlap, variant]);
33
- return (react_1.default.createElement(Badge_1.default, tslib_1.__assign({}, rest, { variant: variant, anchorOrigin: anchorOrigin, component: (component || CustomDotBadge), overlap: overlap !== 'none' ? overlap : undefined, ref: ref, classes: classes }), children));
54
+ }, [isDot, dotProps, overlap, anchorOrigin, children, dotComponent]);
55
+ return (react_1.default.createElement(Badge_1.default, tslib_1.__assign({}, rest, { variant: variant, anchorOrigin: anchorOrigin, component: (component || CustomDotBadge),
56
+ // TODO: that as any for ts v3.8 still not support pick variable out of if check
57
+ overlap: notPassOverlapToMui ? overlap : undefined, ref: badgeRef, classes: classes }), children));
34
58
  });
35
59
  var RcBadge = foundation_1.styled(_RcBadge)(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), styles_1.BadgeStyle);
36
60
  exports.RcBadge = RcBadge;
@@ -5,6 +5,7 @@ var foundation_1 = require("../../../foundation");
5
5
  var utils_1 = require("../utils");
6
6
  exports.BadgeStyle = function (_a) {
7
7
  var badgeContent = _a.badgeContent, overlap = _a.overlap, variant = _a.variant, textColor = _a.textColor, borderColor = _a.borderColor, max = _a.max, color = _a.color;
8
+ var overlapRound = overlap === 'round';
8
9
  var overlapNone = overlap === 'none';
9
10
  var isStandard = variant !== 'dot';
10
11
  var borderCurrColor = foundation_1.getParsePaletteColor(borderColor, null, false);
@@ -12,10 +13,10 @@ exports.BadgeStyle = function (_a) {
12
13
  var manyChar = (['number', 'string'].includes(typeof badgeContent) &&
13
14
  ("" + badgeContent).length !== 1) ||
14
15
  (max && max > 0 && +badgeContent > max);
15
- return foundation_1.css(templateObject_5 || (templateObject_5 = tslib_1.__makeTemplateObject(["\n .", " {\n color: ", ";\n background-color: ", ";\n\n ", ";\n\n ", "\n\n ", "\n }\n "], ["\n .", " {\n color: ", ";\n background-color: ", ";\n\n ",
16
+ return foundation_1.css(templateObject_5 || (templateObject_5 = tslib_1.__makeTemplateObject(["\n .", " {\n margin: ", ";\n color: ", ";\n background-color: ", ";\n\n ", ";\n\n ", "\n\n ", "\n }\n "], ["\n .", " {\n margin: ", ";\n color: ", ";\n background-color: ", ";\n\n ",
16
17
  ";\n\n ",
17
18
  "\n\n ",
18
- "\n }\n "])), utils_1.RcBadgeClasses.badge, foundation_1.getParsePaletteColor(textColor, null, false), foundation_1.getParsePaletteColor(color, null, false), borderColor && foundation_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n ", "\n "], ["\n ",
19
+ "\n }\n "])), utils_1.RcBadgeClasses.badge, overlapRound && "var(" + utils_1.roundBadgeMarginKey + ")", foundation_1.getParsePaletteColor(textColor, null, false), foundation_1.getParsePaletteColor(color, null, false), borderColor && foundation_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n ", "\n "], ["\n ",
19
20
  "\n "])), isStandard
20
21
  ? foundation_1.fakeBorder({ color: borderCurrColor, radius: 'round' })
21
22
  : foundation_1.css(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n border-color: ", ";\n "], ["\n border-color: ", ";\n "])), borderCurrColor)), isStandard && foundation_1.css(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n height: 18px;\n min-width: 18px;\n padding: ", ";\n "], ["\n height: 18px;\n min-width: 18px;\n padding: ", ";\n "])), !manyChar && 0), overlapNone && foundation_1.css(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n position: unset;\n transform: unset;\n\n &.", " {\n transform: scale(0);\n }\n "], ["\n position: unset;\n transform: unset;\n\n &.", " {\n transform: scale(0);\n }\n "])), utils_1.RcBadgeClasses.invisible));
@@ -1 +1,8 @@
1
1
  export declare const RcBadgeClasses: Partial<import("../../../foundation").UnitMap<import("@material-ui/core").BadgeClassKey, any>>;
2
+ export declare const roundBadgeMarginKey = "--badge-round-margin";
3
+ /**
4
+ * a circle inside square, that diagonal of a square to circle distance to be the round offset.
5
+ * @param x that circle r
6
+ * @returns the distance of that offset
7
+ */
8
+ export declare const getRoundOffset: (x: number) => number;
@@ -2,3 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var foundation_1 = require("../../../foundation");
4
4
  exports.RcBadgeClasses = foundation_1.RcClasses(['badge', 'invisible'], 'RcBadge');
5
+ exports.roundBadgeMarginKey = '--badge-round-margin';
6
+ var sqrt2 = Math.sqrt(2);
7
+ var powBy = sqrt2 - 1; // 0.292893218813452
8
+ /**
9
+ * a circle inside square, that diagonal of a square to circle distance to be the round offset.
10
+ * @param x that circle r
11
+ * @returns the distance of that offset
12
+ */
13
+ exports.getRoundOffset = function (x) {
14
+ return (x * powBy) / sqrt2;
15
+ };
@@ -1 +1,2 @@
1
1
  export * from './BadgeUtils';
2
+ export * from './useRoundBadgeOffset';
@@ -2,3 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./BadgeUtils"), exports);
5
+ tslib_1.__exportStar(require("./useRoundBadgeOffset"), exports);
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ /**
3
+ * modify round badge offset to correct position,
4
+ * only trigger when host element height change
5
+ * @param badgeRef badge
6
+ */
7
+ export declare const useRoundBadgeOffset: (badgeRef: React.RefObject<HTMLElement>) => void;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var tslib_1 = require("tslib");
4
+ var react_1 = require("react");
5
+ var foundation_1 = require("../../../foundation");
6
+ var BadgeUtils_1 = require("./BadgeUtils");
7
+ /**
8
+ * modify round badge offset to correct position,
9
+ * only trigger when host element height change
10
+ * @param badgeRef badge
11
+ */
12
+ exports.useRoundBadgeOffset = function (badgeRef) {
13
+ var currHeightRef = react_1.useRef(0);
14
+ // eslint-disable-next-line react-hooks/rules-of-hooks
15
+ foundation_1.useResizeObserver(badgeRef, function (_a) {
16
+ var _b = tslib_1.__read(_a, 1), badgeObsEntry = _b[0];
17
+ var height = badgeObsEntry.contentRect.height;
18
+ var element = badgeObsEntry.target;
19
+ if (currHeightRef.current === height)
20
+ return;
21
+ currHeightRef.current = height;
22
+ var offset = BadgeUtils_1.getRoundOffset(height / 2);
23
+ element.style.setProperty(BadgeUtils_1.roundBadgeMarginKey, foundation_1.px(offset));
24
+ }, { mode: 'throttle' });
25
+ };
@@ -1,19 +1,41 @@
1
1
  import { __assign, __makeTemplateObject, __rest } from "tslib";
2
- import React, { forwardRef, useMemo, } from 'react';
2
+ import React, { forwardRef, useMemo, useRef, } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import MuiBadge from '@material-ui/core/Badge';
5
5
  import { capitalize } from '@material-ui/core/utils';
6
- import { combineProps, styled, useThemeProps, } from '../../foundation';
6
+ import { combineProps, logInDev, styled, useChange, useForkRef, useThemeProps, } from '../../foundation';
7
7
  import { RcBox } from '../Box';
8
8
  import { RcPresence } from '../Presence';
9
9
  import { BadgeStyle } from './styles';
10
- import { RcBadgeClasses } from './utils';
10
+ import { RcBadgeClasses, useRoundBadgeOffset } from './utils';
11
11
  var _RcBadge = forwardRef(function (inProps, ref) {
12
12
  var props = useThemeProps({ props: inProps, name: 'RcBadge' });
13
13
  var classesProp = props.classes, children = props.children, overlap = props.overlap, color = props.color, variant = props.variant, textColor = props.textColor, anchorOrigin = props.anchorOrigin, borderColor = props.borderColor, component = props.component, dotComponent = props.dotComponent, dotProps = props.dotProps, rest = __rest(props, ["classes", "children", "overlap", "color", "variant", "textColor", "anchorOrigin", "borderColor", "component", "dotComponent", "dotProps"]);
14
+ // * should never change overlap
15
+ if (process.env.NODE_ENV !== 'production') {
16
+ // eslint-disable-next-line react-hooks/rules-of-hooks
17
+ useChange(function (prev) {
18
+ if (!prev)
19
+ return;
20
+ logInDev({
21
+ component: 'RcBadge',
22
+ message: 'Should not change `overlap` prop after component render',
23
+ level: 'error',
24
+ });
25
+ }, function () { return overlap; });
26
+ }
27
+ var innerRef = useRef(null);
28
+ var badgeRef = useForkRef(innerRef, ref);
29
+ var isRound = overlap === 'round';
30
+ var isDot = variant === 'dot';
31
+ var notPassOverlapToMui = overlap !== 'none' && !isRound;
32
+ // overlap will never change in production mode
33
+ if (isRound) {
34
+ // eslint-disable-next-line react-hooks/rules-of-hooks
35
+ useRoundBadgeOffset(innerRef);
36
+ }
14
37
  var classes = useMemo(function () { return combineProps(RcBadgeClasses, classesProp); }, [classesProp]);
15
38
  var CustomDotBadge = useMemo(function () {
16
- var isDot = variant === 'dot';
17
39
  return isDot
18
40
  ? forwardRef(function (_a, ref) {
19
41
  var OmitChildren = _a.children, rest = __rest(_a, ["children"]);
@@ -27,8 +49,10 @@ var _RcBadge = forwardRef(function (inProps, ref) {
27
49
  React.createElement(DotComponent, __assign({}, applyDotProps))))));
28
50
  })
29
51
  : undefined;
30
- }, [anchorOrigin, children, dotComponent, dotProps, overlap, variant]);
31
- return (React.createElement(MuiBadge, __assign({}, rest, { variant: variant, anchorOrigin: anchorOrigin, component: (component || CustomDotBadge), overlap: overlap !== 'none' ? overlap : undefined, ref: ref, classes: classes }), children));
52
+ }, [isDot, dotProps, overlap, anchorOrigin, children, dotComponent]);
53
+ return (React.createElement(MuiBadge, __assign({}, rest, { variant: variant, anchorOrigin: anchorOrigin, component: (component || CustomDotBadge),
54
+ // TODO: that as any for ts v3.8 still not support pick variable out of if check
55
+ overlap: notPassOverlapToMui ? overlap : undefined, ref: badgeRef, classes: classes }), children));
32
56
  });
33
57
  var RcBadge = styled(_RcBadge)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), BadgeStyle);
34
58
  RcBadge.defaultProps = {
@@ -1,8 +1,9 @@
1
1
  import { __makeTemplateObject } from "tslib";
2
2
  import { css, fakeBorder, getParsePaletteColor, } from '../../../foundation';
3
- import { RcBadgeClasses } from '../utils';
3
+ import { RcBadgeClasses, roundBadgeMarginKey } from '../utils';
4
4
  export var BadgeStyle = function (_a) {
5
5
  var badgeContent = _a.badgeContent, overlap = _a.overlap, variant = _a.variant, textColor = _a.textColor, borderColor = _a.borderColor, max = _a.max, color = _a.color;
6
+ var overlapRound = overlap === 'round';
6
7
  var overlapNone = overlap === 'none';
7
8
  var isStandard = variant !== 'dot';
8
9
  var borderCurrColor = getParsePaletteColor(borderColor, null, false);
@@ -10,10 +11,10 @@ export var BadgeStyle = function (_a) {
10
11
  var manyChar = (['number', 'string'].includes(typeof badgeContent) &&
11
12
  ("" + badgeContent).length !== 1) ||
12
13
  (max && max > 0 && +badgeContent > max);
13
- return css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n .", " {\n color: ", ";\n background-color: ", ";\n\n ", ";\n\n ", "\n\n ", "\n }\n "], ["\n .", " {\n color: ", ";\n background-color: ", ";\n\n ",
14
+ return css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n .", " {\n margin: ", ";\n color: ", ";\n background-color: ", ";\n\n ", ";\n\n ", "\n\n ", "\n }\n "], ["\n .", " {\n margin: ", ";\n color: ", ";\n background-color: ", ";\n\n ",
14
15
  ";\n\n ",
15
16
  "\n\n ",
16
- "\n }\n "])), RcBadgeClasses.badge, getParsePaletteColor(textColor, null, false), getParsePaletteColor(color, null, false), borderColor && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n ", "\n "], ["\n ",
17
+ "\n }\n "])), RcBadgeClasses.badge, overlapRound && "var(" + roundBadgeMarginKey + ")", getParsePaletteColor(textColor, null, false), getParsePaletteColor(color, null, false), borderColor && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n ", "\n "], ["\n ",
17
18
  "\n "])), isStandard
18
19
  ? fakeBorder({ color: borderCurrColor, radius: 'round' })
19
20
  : css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n border-color: ", ";\n "], ["\n border-color: ", ";\n "])), borderCurrColor)), isStandard && css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n height: 18px;\n min-width: 18px;\n padding: ", ";\n "], ["\n height: 18px;\n min-width: 18px;\n padding: ", ";\n "])), !manyChar && 0), overlapNone && css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n position: unset;\n transform: unset;\n\n &.", " {\n transform: scale(0);\n }\n "], ["\n position: unset;\n transform: unset;\n\n &.", " {\n transform: scale(0);\n }\n "])), RcBadgeClasses.invisible));
@@ -1,2 +1,13 @@
1
1
  import { RcClasses } from '../../../foundation';
2
2
  export var RcBadgeClasses = RcClasses(['badge', 'invisible'], 'RcBadge');
3
+ export var roundBadgeMarginKey = '--badge-round-margin';
4
+ var sqrt2 = Math.sqrt(2);
5
+ var powBy = sqrt2 - 1; // 0.292893218813452
6
+ /**
7
+ * a circle inside square, that diagonal of a square to circle distance to be the round offset.
8
+ * @param x that circle r
9
+ * @returns the distance of that offset
10
+ */
11
+ export var getRoundOffset = function (x) {
12
+ return (x * powBy) / sqrt2;
13
+ };
@@ -1 +1,2 @@
1
1
  export * from './BadgeUtils';
2
+ export * from './useRoundBadgeOffset';
@@ -0,0 +1,23 @@
1
+ import { __read } from "tslib";
2
+ import { useRef } from 'react';
3
+ import { px, useResizeObserver } from '../../../foundation';
4
+ import { getRoundOffset, roundBadgeMarginKey } from './BadgeUtils';
5
+ /**
6
+ * modify round badge offset to correct position,
7
+ * only trigger when host element height change
8
+ * @param badgeRef badge
9
+ */
10
+ export var useRoundBadgeOffset = function (badgeRef) {
11
+ var currHeightRef = useRef(0);
12
+ // eslint-disable-next-line react-hooks/rules-of-hooks
13
+ useResizeObserver(badgeRef, function (_a) {
14
+ var _b = __read(_a, 1), badgeObsEntry = _b[0];
15
+ var height = badgeObsEntry.contentRect.height;
16
+ var element = badgeObsEntry.target;
17
+ if (currHeightRef.current === height)
18
+ return;
19
+ currHeightRef.current = height;
20
+ var offset = getRoundOffset(height / 2);
21
+ element.style.setProperty(roundBadgeMarginKey, px(offset));
22
+ }, { mode: 'throttle' });
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ringcentral/juno",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "author": "RingCentral",
5
5
  "license": "MIT",
6
6
  "bugs": {