@snack-uikit/tag 0.12.11 → 0.13.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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 0.13.0 (2025-04-07)
7
+
8
+
9
+ ### Features
10
+
11
+ * **PDS-1785:** tag with tooltip ([aafae6a](https://github.com/cloud-ru-tech/snack-uikit/commit/aafae6ae8f3840f4d574e661fb8d11532a1823f3))
12
+
13
+
14
+
15
+
16
+
6
17
  ## 0.12.11 (2025-03-19)
7
18
 
8
19
  ### Only dependencies have been changed
package/README.md CHANGED
@@ -20,6 +20,7 @@
20
20
  | tabIndex | `number` | - | tabIndex кнопки удаления |
21
21
  | onClick | `(e: MouseEvent<HTMLAnchorElement, MouseEvent>) => void` | - | |
22
22
  | target | `string` | - | |
23
+ | tooltip | `TooltipProps` | - | Тултип над тегом |
23
24
  ## Tag
24
25
  ### Props
25
26
  | name | type | default value | description |
@@ -33,6 +34,7 @@
33
34
  | tabIndex | `number` | - | tabIndex кнопки удаления |
34
35
  | onClick | `(e: MouseEvent<HTMLAnchorElement, MouseEvent>) => void` | - | |
35
36
  | target | `string` | - | |
37
+ | tooltip | `TooltipProps` | - | Тултип над тегом |
36
38
  ## TagRow
37
39
  ### Props
38
40
  | name | type | default value | description |
@@ -1,5 +1,3 @@
1
- import { TagBaseProps } from '../TagBase';
2
- import { TagLinkProps } from '../TagLink';
3
- export type TagProps = TagBaseProps | TagLinkProps;
1
+ import { TagLinkProps, TagProps } from '../../types';
4
2
  export declare function isTagLinkProps(props: TagProps): props is TagLinkProps;
5
3
  export declare function Tag(props: TagProps): import("react/jsx-runtime").JSX.Element;
@@ -6,14 +6,33 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isTagLinkProps = isTagLinkProps;
7
7
  exports.Tag = Tag;
8
8
  const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = require("react");
10
+ const tooltip_1 = require("@snack-uikit/tooltip");
9
11
  const TagBase_1 = require("../TagBase");
10
12
  const TagLink_1 = require("../TagLink");
11
13
  function isTagLinkProps(props) {
12
14
  return 'href' in props && props.href !== undefined;
13
15
  }
16
+ function isTagWithTooltip(props) {
17
+ return 'tooltip' in props && props.tooltip !== undefined;
18
+ }
14
19
  function Tag(props) {
15
- if (isTagLinkProps(props)) {
16
- return (0, jsx_runtime_1.jsx)(TagLink_1.TagLink, Object.assign({}, props));
20
+ const [restrictOpenTooltip, setRestrictOpenTooltip] = (0, react_1.useState)(false);
21
+ const isLinkTag = isTagLinkProps(props);
22
+ if (!isTagWithTooltip(props)) {
23
+ return isLinkTag ? (0, jsx_runtime_1.jsx)(TagLink_1.TagLink, Object.assign({}, props)) : (0, jsx_runtime_1.jsx)(TagBase_1.TagBase, Object.assign({}, props));
17
24
  }
18
- return (0, jsx_runtime_1.jsx)(TagBase_1.TagBase, Object.assign({}, props));
25
+ const {
26
+ tooltip
27
+ } = props;
28
+ const tooltipProps = tooltip && Object.assign(Object.assign({}, tooltip), {
29
+ open: restrictOpenTooltip ? false : tooltip.open
30
+ });
31
+ const tagBaseWithTooltipProps = Object.assign(Object.assign({}, props), {
32
+ changeRestrictTooltipState: setRestrictOpenTooltip
33
+ });
34
+ return (0, jsx_runtime_1.jsx)(tooltip_1.WithTooltip, {
35
+ tooltip: tooltipProps,
36
+ children: isLinkTag ? (0, jsx_runtime_1.jsx)(TagLink_1.TagLink, Object.assign({}, props)) : (0, jsx_runtime_1.jsx)(TagBase_1.TagBase, Object.assign({}, tagBaseWithTooltipProps))
37
+ });
19
38
  }
@@ -1,8 +1,5 @@
1
- import { MouseEventHandler } from 'react';
2
- import { WithSupportProps } from '@snack-uikit/utils';
3
- import { CommonTagProps } from '../../types';
4
- export type TagBaseProps = WithSupportProps<{
5
- /** Коллбэк на удаление */
6
- onDelete?: MouseEventHandler<HTMLButtonElement>;
7
- }> & CommonTagProps;
8
- export declare function TagBase({ label, size, appearance, onDelete, className, tabIndex, ...rest }: TagBaseProps): import("react/jsx-runtime").JSX.Element;
1
+ import { ManageRestrictTooltipProps, TagBaseProps } from '../../types';
2
+ type TagBaseWithTooltip = TagBaseProps & ManageRestrictTooltipProps;
3
+ type TagBaseComponentProps = TagBaseProps | TagBaseWithTooltip;
4
+ export declare function TagBase(props: TagBaseComponentProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -19,36 +19,63 @@ Object.defineProperty(exports, "__esModule", {
19
19
  exports.TagBase = TagBase;
20
20
  const jsx_runtime_1 = require("react/jsx-runtime");
21
21
  const classnames_1 = __importDefault(require("classnames"));
22
+ const react_1 = require("react");
22
23
  const icons_1 = require("@snack-uikit/icons");
23
24
  const utils_1 = require("@snack-uikit/utils");
24
25
  const constants_1 = require("../../constants");
25
26
  const constants_2 = require("./constants");
26
27
  const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
27
- function TagBase(_a) {
28
- var {
28
+ function isTagWithTooltip(props) {
29
+ return 'changeRestrictTooltipState' in props && props.changeRestrictTooltipState !== undefined;
30
+ }
31
+ function TagBase(props) {
32
+ const {
29
33
  label,
30
34
  size = constants_1.SIZE.Xs,
31
35
  appearance = constants_1.APPEARANCE.Neutral,
32
36
  onDelete,
33
37
  className,
34
38
  tabIndex
35
- } = _a,
36
- rest = __rest(_a, ["label", "size", "appearance", "onDelete", "className", "tabIndex"]);
39
+ } = props,
40
+ rest = __rest(props, ["label", "size", "appearance", "onDelete", "className", "tabIndex"]);
41
+ const deleteButtonRef = (0, react_1.useRef)(null);
42
+ const isRemovable = Boolean(onDelete);
43
+ const handleMouseEvents = isEntering => {
44
+ if (isRemovable && isTagWithTooltip(props)) {
45
+ const {
46
+ changeRestrictTooltipState
47
+ } = props;
48
+ changeRestrictTooltipState(isEntering);
49
+ }
50
+ };
51
+ const handleMouseEnter = event => {
52
+ var _a;
53
+ if ((_a = deleteButtonRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
54
+ handleMouseEvents(true);
55
+ }
56
+ };
57
+ const handleMouseLeave = () => {
58
+ handleMouseEvents(false);
59
+ };
37
60
  return (0, jsx_runtime_1.jsxs)("span", Object.assign({}, (0, utils_1.extractSupportProps)(rest), {
38
61
  className: (0, classnames_1.default)(styles_module_scss_1.default.tag, className),
39
62
  "data-size": size,
40
63
  "data-appearance": appearance,
41
- "data-removable": Boolean(onDelete),
64
+ "data-removable": isRemovable,
65
+ onMouseEnter: handleMouseEnter,
66
+ onMouseLeave: handleMouseLeave,
42
67
  children: [(0, jsx_runtime_1.jsx)("span", {
43
- title: label,
44
68
  className: styles_module_scss_1.default.label,
45
69
  children: label
46
- }), onDelete && (0, jsx_runtime_1.jsx)("button", {
70
+ }), isRemovable && (0, jsx_runtime_1.jsx)("button", {
47
71
  type: 'button',
48
72
  className: styles_module_scss_1.default.tagButton,
49
73
  onClick: onDelete,
50
74
  "data-test-id": 'tag-remove-button',
51
75
  tabIndex: tabIndex,
76
+ onMouseEnter: handleMouseEnter,
77
+ onMouseLeave: handleMouseLeave,
78
+ ref: deleteButtonRef,
52
79
  children: size === constants_1.SIZE.Xs ? (0, jsx_runtime_1.jsx)(icons_1.CrossSVG, {
53
80
  size: constants_2.ICON_SIZE[size],
54
81
  className: styles_module_scss_1.default.icon
@@ -1,9 +1,2 @@
1
- import { MouseEvent } from 'react';
2
- import { WithSupportProps } from '@snack-uikit/utils';
3
- import { CommonTagProps } from '../../types';
4
- export type TagLinkProps = WithSupportProps<CommonTagProps> & {
5
- href: string;
6
- onClick?(e: MouseEvent<HTMLAnchorElement>): void;
7
- target?: HTMLAnchorElement['target'];
8
- };
1
+ import { TagLinkProps } from '../../types';
9
2
  export declare function TagLink({ label, size, appearance, className, tabIndex, href, onClick, target, ...rest }: TagLinkProps): import("react/jsx-runtime").JSX.Element;
@@ -43,7 +43,6 @@ function TagLink(_a) {
43
43
  target: target,
44
44
  onClick: onClick,
45
45
  children: (0, jsx_runtime_1.jsx)("span", {
46
- title: label,
47
46
  className: styles_module_scss_1.default.label,
48
47
  children: label
49
48
  })
@@ -1,2 +1,2 @@
1
1
  import { TagRowItem, TagRowItemInner } from '../../types';
2
- export declare const mapTagRowItem: ({ label, appearance }: TagRowItem) => TagRowItemInner;
2
+ export declare const mapTagRowItem: ({ appearance, ...props }: TagRowItem) => TagRowItemInner;
@@ -1,24 +1,25 @@
1
1
  "use strict";
2
2
 
3
+ var __rest = void 0 && (void 0).__rest || function (s, e) {
4
+ var t = {};
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
8
+ }
9
+ return t;
10
+ };
3
11
  Object.defineProperty(exports, "__esModule", {
4
12
  value: true
5
13
  });
6
14
  exports.mapTagRowItem = void 0;
7
15
  const constants_1 = require("../../constants");
8
- const mapTagRowItem = _ref => {
9
- let {
10
- label,
16
+ const mapTagRowItem = _a => {
17
+ var {
18
+ appearance = constants_1.APPEARANCE.Neutral
19
+ } = _a,
20
+ props = __rest(_a, ["appearance"]);
21
+ return Object.assign(Object.assign({}, props), {
11
22
  appearance
12
- } = _ref;
13
- if (appearance) {
14
- return {
15
- label,
16
- appearance
17
- };
18
- }
19
- return {
20
- label,
21
- appearance: constants_1.APPEARANCE.Neutral
22
- };
23
+ });
23
24
  };
24
25
  exports.mapTagRowItem = mapTagRowItem;
@@ -18,12 +18,10 @@ function renderTag(size, handleRemoveItem, setRef) {
18
18
  return (0, jsx_runtime_1.jsx)("div", {
19
19
  ref: setRef === null || setRef === void 0 ? void 0 : setRef(item, index),
20
20
  className: styles_module_scss_1.default.tagWrapper,
21
- children: (0, jsx_runtime_1.jsx)(components_1.Tag, {
22
- label: item.label,
23
- appearance: item.appearance,
21
+ children: (0, jsx_runtime_1.jsx)(components_1.Tag, Object.assign({
24
22
  size: size,
25
23
  onDelete: handleRemoveItem === null || handleRemoveItem === void 0 ? void 0 : handleRemoveItem(item)
26
- })
24
+ }, item))
27
25
  }, item.label);
28
26
  };
29
27
  }
@@ -1,3 +1,3 @@
1
1
  export * from './components';
2
2
  export * from './constants';
3
- export type { Appearance, Size, TagRowItem } from './types';
3
+ export type { Appearance, Size, TagRowItem, TagProps } from './types';
@@ -1,5 +1,6 @@
1
- import { MouseEvent } from 'react';
2
- import { ValueOf } from '@snack-uikit/utils';
1
+ import { MouseEvent, MouseEventHandler } from 'react';
2
+ import { TooltipProps } from '@snack-uikit/tooltip';
3
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
3
4
  import { APPEARANCE, SIZE } from './constants';
4
5
  export type Appearance = ValueOf<typeof APPEARANCE>;
5
6
  export type Size = ValueOf<typeof SIZE>;
@@ -8,14 +9,17 @@ export type LinkProps = {
8
9
  onClick?(e: MouseEvent<HTMLAnchorElement>): void;
9
10
  target?: HTMLAnchorElement['target'];
10
11
  };
12
+ export type TagTooltipProps = {
13
+ /** Тултип над тегом */
14
+ tooltip?: TooltipProps;
15
+ };
11
16
  export type TagRowItem = {
12
17
  label: string;
13
18
  appearance?: Appearance;
14
- } & Partial<LinkProps>;
15
- export type TagRowItemInner = {
16
- label: string;
19
+ } & Partial<LinkProps> & TagTooltipProps;
20
+ export type TagRowItemInner = Omit<TagRowItem, 'appearance'> & {
17
21
  appearance: Appearance;
18
- } & Partial<LinkProps>;
22
+ };
19
23
  export type CommonTagProps = {
20
24
  /** Текст */
21
25
  label: string;
@@ -28,3 +32,19 @@ export type CommonTagProps = {
28
32
  /** tabIndex кнопки удаления */
29
33
  tabIndex?: number;
30
34
  };
35
+ export type TagBaseProps = WithSupportProps<{
36
+ /** Коллбэк на удаление */
37
+ onDelete?: MouseEventHandler<HTMLButtonElement>;
38
+ }> & CommonTagProps;
39
+ export type TagLinkProps = WithSupportProps<CommonTagProps> & {
40
+ href: string;
41
+ onClick?(e: MouseEvent<HTMLAnchorElement>): void;
42
+ target?: HTMLAnchorElement['target'];
43
+ };
44
+ export type ManageRestrictTooltipProps = {
45
+ changeRestrictTooltipState(state: boolean): void;
46
+ };
47
+ type TagWithoutTooltipProps = TagBaseProps | TagLinkProps;
48
+ export type TagWithTooltipProps = TagWithoutTooltipProps & TagTooltipProps;
49
+ export type TagProps = TagWithoutTooltipProps | TagWithTooltipProps;
50
+ export {};
@@ -1,5 +1,3 @@
1
- import { TagBaseProps } from '../TagBase';
2
- import { TagLinkProps } from '../TagLink';
3
- export type TagProps = TagBaseProps | TagLinkProps;
1
+ import { TagLinkProps, TagProps } from '../../types';
4
2
  export declare function isTagLinkProps(props: TagProps): props is TagLinkProps;
5
3
  export declare function Tag(props: TagProps): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,22 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { WithTooltip } from '@snack-uikit/tooltip';
2
4
  import { TagBase } from '../TagBase';
3
5
  import { TagLink } from '../TagLink';
4
6
  export function isTagLinkProps(props) {
5
7
  return 'href' in props && props.href !== undefined;
6
8
  }
9
+ function isTagWithTooltip(props) {
10
+ return 'tooltip' in props && props.tooltip !== undefined;
11
+ }
7
12
  export function Tag(props) {
8
- if (isTagLinkProps(props)) {
9
- return _jsx(TagLink, Object.assign({}, props));
13
+ const [restrictOpenTooltip, setRestrictOpenTooltip] = useState(false);
14
+ const isLinkTag = isTagLinkProps(props);
15
+ if (!isTagWithTooltip(props)) {
16
+ return isLinkTag ? _jsx(TagLink, Object.assign({}, props)) : _jsx(TagBase, Object.assign({}, props));
10
17
  }
11
- return _jsx(TagBase, Object.assign({}, props));
18
+ const { tooltip } = props;
19
+ const tooltipProps = tooltip && Object.assign(Object.assign({}, tooltip), { open: restrictOpenTooltip ? false : tooltip.open });
20
+ const tagBaseWithTooltipProps = Object.assign(Object.assign({}, props), { changeRestrictTooltipState: setRestrictOpenTooltip });
21
+ return (_jsx(WithTooltip, { tooltip: tooltipProps, children: isLinkTag ? _jsx(TagLink, Object.assign({}, props)) : _jsx(TagBase, Object.assign({}, tagBaseWithTooltipProps)) }));
12
22
  }
@@ -1,8 +1,5 @@
1
- import { MouseEventHandler } from 'react';
2
- import { WithSupportProps } from '@snack-uikit/utils';
3
- import { CommonTagProps } from '../../types';
4
- export type TagBaseProps = WithSupportProps<{
5
- /** Коллбэк на удаление */
6
- onDelete?: MouseEventHandler<HTMLButtonElement>;
7
- }> & CommonTagProps;
8
- export declare function TagBase({ label, size, appearance, onDelete, className, tabIndex, ...rest }: TagBaseProps): import("react/jsx-runtime").JSX.Element;
1
+ import { ManageRestrictTooltipProps, TagBaseProps } from '../../types';
2
+ type TagBaseWithTooltip = TagBaseProps & ManageRestrictTooltipProps;
3
+ type TagBaseComponentProps = TagBaseProps | TagBaseWithTooltip;
4
+ export declare function TagBase(props: TagBaseComponentProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -11,12 +11,33 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
+ import { useRef } from 'react';
14
15
  import { CrossSVG } from '@snack-uikit/icons';
15
16
  import { extractSupportProps } from '@snack-uikit/utils';
16
17
  import { APPEARANCE, SIZE } from '../../constants';
17
18
  import { ICON_SIZE } from './constants';
18
19
  import styles from './styles.module.css';
19
- export function TagBase(_a) {
20
- var { label, size = SIZE.Xs, appearance = APPEARANCE.Neutral, onDelete, className, tabIndex } = _a, rest = __rest(_a, ["label", "size", "appearance", "onDelete", "className", "tabIndex"]);
21
- return (_jsxs("span", Object.assign({}, extractSupportProps(rest), { className: cn(styles.tag, className), "data-size": size, "data-appearance": appearance, "data-removable": Boolean(onDelete), children: [_jsx("span", { title: label, className: styles.label, children: label }), onDelete && (_jsx("button", { type: 'button', className: styles.tagButton, onClick: onDelete, "data-test-id": 'tag-remove-button', tabIndex: tabIndex, children: size === SIZE.Xs ? (_jsx(CrossSVG, { size: ICON_SIZE[size], className: styles.icon })) : (_jsx(CrossSVG, { size: ICON_SIZE[size], className: styles.icon })) }))] })));
20
+ function isTagWithTooltip(props) {
21
+ return 'changeRestrictTooltipState' in props && props.changeRestrictTooltipState !== undefined;
22
+ }
23
+ export function TagBase(props) {
24
+ const { label, size = SIZE.Xs, appearance = APPEARANCE.Neutral, onDelete, className, tabIndex } = props, rest = __rest(props, ["label", "size", "appearance", "onDelete", "className", "tabIndex"]);
25
+ const deleteButtonRef = useRef(null);
26
+ const isRemovable = Boolean(onDelete);
27
+ const handleMouseEvents = (isEntering) => {
28
+ if (isRemovable && isTagWithTooltip(props)) {
29
+ const { changeRestrictTooltipState } = props;
30
+ changeRestrictTooltipState(isEntering);
31
+ }
32
+ };
33
+ const handleMouseEnter = (event) => {
34
+ var _a;
35
+ if ((_a = deleteButtonRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
36
+ handleMouseEvents(true);
37
+ }
38
+ };
39
+ const handleMouseLeave = () => {
40
+ handleMouseEvents(false);
41
+ };
42
+ return (_jsxs("span", Object.assign({}, extractSupportProps(rest), { className: cn(styles.tag, className), "data-size": size, "data-appearance": appearance, "data-removable": isRemovable, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [_jsx("span", { className: styles.label, children: label }), isRemovable && (_jsx("button", { type: 'button', className: styles.tagButton, onClick: onDelete, "data-test-id": 'tag-remove-button', tabIndex: tabIndex, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, ref: deleteButtonRef, children: size === SIZE.Xs ? (_jsx(CrossSVG, { size: ICON_SIZE[size], className: styles.icon })) : (_jsx(CrossSVG, { size: ICON_SIZE[size], className: styles.icon })) }))] })));
22
43
  }
@@ -1,9 +1,2 @@
1
- import { MouseEvent } from 'react';
2
- import { WithSupportProps } from '@snack-uikit/utils';
3
- import { CommonTagProps } from '../../types';
4
- export type TagLinkProps = WithSupportProps<CommonTagProps> & {
5
- href: string;
6
- onClick?(e: MouseEvent<HTMLAnchorElement>): void;
7
- target?: HTMLAnchorElement['target'];
8
- };
1
+ import { TagLinkProps } from '../../types';
9
2
  export declare function TagLink({ label, size, appearance, className, tabIndex, href, onClick, target, ...rest }: TagLinkProps): import("react/jsx-runtime").JSX.Element;
@@ -16,5 +16,5 @@ import { APPEARANCE, SIZE } from '../../constants';
16
16
  import styles from './styles.module.css';
17
17
  export function TagLink(_a) {
18
18
  var { label, size = SIZE.Xs, appearance = APPEARANCE.Neutral, className, tabIndex, href, onClick, target } = _a, rest = __rest(_a, ["label", "size", "appearance", "className", "tabIndex", "href", "onClick", "target"]);
19
- return (_jsx("a", Object.assign({}, extractSupportProps(rest), { className: cn(styles.tag, className), "data-size": size, "data-appearance": appearance, tabIndex: tabIndex, href: href, target: target, onClick: onClick, children: _jsx("span", { title: label, className: styles.label, children: label }) })));
19
+ return (_jsx("a", Object.assign({}, extractSupportProps(rest), { className: cn(styles.tag, className), "data-size": size, "data-appearance": appearance, tabIndex: tabIndex, href: href, target: target, onClick: onClick, children: _jsx("span", { className: styles.label, children: label }) })));
20
20
  }
@@ -1,2 +1,2 @@
1
1
  import { TagRowItem, TagRowItemInner } from '../../types';
2
- export declare const mapTagRowItem: ({ label, appearance }: TagRowItem) => TagRowItemInner;
2
+ export declare const mapTagRowItem: ({ appearance, ...props }: TagRowItem) => TagRowItemInner;
@@ -1,10 +1,16 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { APPEARANCE } from '../../constants';
2
- export const mapTagRowItem = ({ label, appearance }) => {
3
- if (appearance) {
4
- return { label, appearance };
5
- }
6
- return {
7
- label,
8
- appearance: APPEARANCE.Neutral,
9
- };
13
+ export const mapTagRowItem = (_a) => {
14
+ var { appearance = APPEARANCE.Neutral } = _a, props = __rest(_a, ["appearance"]);
15
+ return (Object.assign(Object.assign({}, props), { appearance }));
10
16
  };
@@ -4,7 +4,7 @@ import { SIZE } from '../../constants';
4
4
  import styles from './styles.module.css';
5
5
  function renderTag(size, handleRemoveItem, setRef) {
6
6
  return function TagRowItem(item, index) {
7
- return (_jsx("div", { ref: setRef === null || setRef === void 0 ? void 0 : setRef(item, index), className: styles.tagWrapper, children: _jsx(Tag, { label: item.label, appearance: item.appearance, size: size, onDelete: handleRemoveItem === null || handleRemoveItem === void 0 ? void 0 : handleRemoveItem(item) }) }, item.label));
7
+ return (_jsx("div", { ref: setRef === null || setRef === void 0 ? void 0 : setRef(item, index), className: styles.tagWrapper, children: _jsx(Tag, Object.assign({ size: size, onDelete: handleRemoveItem === null || handleRemoveItem === void 0 ? void 0 : handleRemoveItem(item) }, item)) }, item.label));
8
8
  };
9
9
  }
10
10
  export function TagList({ items, size = SIZE.Xs, onItemRemove, setTagRef }) {
@@ -1,3 +1,3 @@
1
1
  export * from './components';
2
2
  export * from './constants';
3
- export type { Appearance, Size, TagRowItem } from './types';
3
+ export type { Appearance, Size, TagRowItem, TagProps } from './types';
@@ -1,5 +1,6 @@
1
- import { MouseEvent } from 'react';
2
- import { ValueOf } from '@snack-uikit/utils';
1
+ import { MouseEvent, MouseEventHandler } from 'react';
2
+ import { TooltipProps } from '@snack-uikit/tooltip';
3
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
3
4
  import { APPEARANCE, SIZE } from './constants';
4
5
  export type Appearance = ValueOf<typeof APPEARANCE>;
5
6
  export type Size = ValueOf<typeof SIZE>;
@@ -8,14 +9,17 @@ export type LinkProps = {
8
9
  onClick?(e: MouseEvent<HTMLAnchorElement>): void;
9
10
  target?: HTMLAnchorElement['target'];
10
11
  };
12
+ export type TagTooltipProps = {
13
+ /** Тултип над тегом */
14
+ tooltip?: TooltipProps;
15
+ };
11
16
  export type TagRowItem = {
12
17
  label: string;
13
18
  appearance?: Appearance;
14
- } & Partial<LinkProps>;
15
- export type TagRowItemInner = {
16
- label: string;
19
+ } & Partial<LinkProps> & TagTooltipProps;
20
+ export type TagRowItemInner = Omit<TagRowItem, 'appearance'> & {
17
21
  appearance: Appearance;
18
- } & Partial<LinkProps>;
22
+ };
19
23
  export type CommonTagProps = {
20
24
  /** Текст */
21
25
  label: string;
@@ -28,3 +32,19 @@ export type CommonTagProps = {
28
32
  /** tabIndex кнопки удаления */
29
33
  tabIndex?: number;
30
34
  };
35
+ export type TagBaseProps = WithSupportProps<{
36
+ /** Коллбэк на удаление */
37
+ onDelete?: MouseEventHandler<HTMLButtonElement>;
38
+ }> & CommonTagProps;
39
+ export type TagLinkProps = WithSupportProps<CommonTagProps> & {
40
+ href: string;
41
+ onClick?(e: MouseEvent<HTMLAnchorElement>): void;
42
+ target?: HTMLAnchorElement['target'];
43
+ };
44
+ export type ManageRestrictTooltipProps = {
45
+ changeRestrictTooltipState(state: boolean): void;
46
+ };
47
+ type TagWithoutTooltipProps = TagBaseProps | TagLinkProps;
48
+ export type TagWithTooltipProps = TagWithoutTooltipProps & TagTooltipProps;
49
+ export type TagProps = TagWithoutTooltipProps | TagWithTooltipProps;
50
+ export {};
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Tag",
7
- "version": "0.12.11",
7
+ "version": "0.13.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -39,8 +39,9 @@
39
39
  "@snack-uikit/dropdown": "0.4.7",
40
40
  "@snack-uikit/icons": "0.26.2",
41
41
  "@snack-uikit/scroll": "0.9.5",
42
+ "@snack-uikit/tooltip": "0.17.1",
42
43
  "@snack-uikit/utils": "3.8.1",
43
44
  "classnames": "2.5.1"
44
45
  },
45
- "gitHead": "e14c6ec6fbc59b086b7ed348403eb1bac740b9c3"
46
+ "gitHead": "f429c3e85872bce0e7a9b06054840b6f761a546c"
46
47
  }
@@ -1,16 +1,38 @@
1
- import { TagBase, TagBaseProps } from '../TagBase';
2
- import { TagLink, TagLinkProps } from '../TagLink';
1
+ import { useState } from 'react';
3
2
 
4
- export type TagProps = TagBaseProps | TagLinkProps;
3
+ import { WithTooltip } from '@snack-uikit/tooltip';
4
+
5
+ import { TagLinkProps, TagProps, TagWithTooltipProps } from '../../types';
6
+ import { TagBase } from '../TagBase';
7
+ import { TagLink } from '../TagLink';
5
8
 
6
9
  export function isTagLinkProps(props: TagProps): props is TagLinkProps {
7
10
  return 'href' in props && props.href !== undefined;
8
11
  }
9
12
 
13
+ function isTagWithTooltip(props: TagProps): props is TagWithTooltipProps {
14
+ return 'tooltip' in props && props.tooltip !== undefined;
15
+ }
16
+
10
17
  export function Tag(props: TagProps) {
11
- if (isTagLinkProps(props)) {
12
- return <TagLink {...props} />;
18
+ const [restrictOpenTooltip, setRestrictOpenTooltip] = useState(false);
19
+ const isLinkTag = isTagLinkProps(props);
20
+
21
+ if (!isTagWithTooltip(props)) {
22
+ return isLinkTag ? <TagLink {...props} /> : <TagBase {...props} />;
13
23
  }
14
24
 
15
- return <TagBase {...props} />;
25
+ const { tooltip } = props;
26
+ const tooltipProps = tooltip && {
27
+ ...tooltip,
28
+ open: restrictOpenTooltip ? false : tooltip.open,
29
+ };
30
+
31
+ const tagBaseWithTooltipProps = { ...props, changeRestrictTooltipState: setRestrictOpenTooltip };
32
+
33
+ return (
34
+ <WithTooltip tooltip={tooltipProps}>
35
+ {isLinkTag ? <TagLink {...props} /> : <TagBase {...tagBaseWithTooltipProps} />}
36
+ </WithTooltip>
37
+ );
16
38
  }
@@ -1,47 +1,66 @@
1
1
  import cn from 'classnames';
2
- import { MouseEventHandler } from 'react';
2
+ import { MouseEvent, useRef } from 'react';
3
3
 
4
4
  import { CrossSVG } from '@snack-uikit/icons';
5
- import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
5
+ import { extractSupportProps } from '@snack-uikit/utils';
6
6
 
7
7
  import { APPEARANCE, SIZE } from '../../constants';
8
- import { CommonTagProps } from '../../types';
8
+ import { ManageRestrictTooltipProps, TagBaseProps } from '../../types';
9
9
  import { ICON_SIZE } from './constants';
10
10
  import styles from './styles.module.scss';
11
11
 
12
- export type TagBaseProps = WithSupportProps<{
13
- /** Коллбэк на удаление */
14
- onDelete?: MouseEventHandler<HTMLButtonElement>;
15
- }> &
16
- CommonTagProps;
17
-
18
- export function TagBase({
19
- label,
20
- size = SIZE.Xs,
21
- appearance = APPEARANCE.Neutral,
22
- onDelete,
23
- className,
24
- tabIndex,
25
- ...rest
26
- }: TagBaseProps) {
12
+ type TagBaseWithTooltip = TagBaseProps & ManageRestrictTooltipProps;
13
+ type TagBaseComponentProps = TagBaseProps | TagBaseWithTooltip;
14
+
15
+ function isTagWithTooltip(props: TagBaseProps): props is TagBaseWithTooltip {
16
+ return 'changeRestrictTooltipState' in props && props.changeRestrictTooltipState !== undefined;
17
+ }
18
+
19
+ export function TagBase(props: TagBaseComponentProps) {
20
+ const { label, size = SIZE.Xs, appearance = APPEARANCE.Neutral, onDelete, className, tabIndex, ...rest } = props;
21
+
22
+ const deleteButtonRef = useRef<HTMLButtonElement>(null);
23
+
24
+ const isRemovable = Boolean(onDelete);
25
+
26
+ const handleMouseEvents = (isEntering: boolean) => {
27
+ if (isRemovable && isTagWithTooltip(props)) {
28
+ const { changeRestrictTooltipState } = props;
29
+ changeRestrictTooltipState(isEntering);
30
+ }
31
+ };
32
+
33
+ const handleMouseEnter = (event: MouseEvent<HTMLButtonElement>) => {
34
+ if (deleteButtonRef.current?.contains(event.target as Node)) {
35
+ handleMouseEvents(true);
36
+ }
37
+ };
38
+
39
+ const handleMouseLeave = () => {
40
+ handleMouseEvents(false);
41
+ };
42
+
27
43
  return (
28
44
  <span
29
45
  {...extractSupportProps(rest)}
30
46
  className={cn(styles.tag, className)}
31
47
  data-size={size}
32
48
  data-appearance={appearance}
33
- data-removable={Boolean(onDelete)}
49
+ data-removable={isRemovable}
50
+ onMouseEnter={handleMouseEnter}
51
+ onMouseLeave={handleMouseLeave}
34
52
  >
35
- <span title={label} className={styles.label}>
36
- {label}
37
- </span>
38
- {onDelete && (
53
+ <span className={styles.label}>{label}</span>
54
+ {isRemovable && (
39
55
  <button
40
56
  type='button'
41
57
  className={styles.tagButton}
42
58
  onClick={onDelete}
43
59
  data-test-id='tag-remove-button'
44
60
  tabIndex={tabIndex}
61
+ onMouseEnter={handleMouseEnter}
62
+ onMouseLeave={handleMouseLeave}
63
+ ref={deleteButtonRef}
45
64
  >
46
65
  {size === SIZE.Xs ? (
47
66
  <CrossSVG size={ICON_SIZE[size]} className={styles.icon} />
@@ -1,18 +1,11 @@
1
1
  import cn from 'classnames';
2
- import { MouseEvent } from 'react';
3
2
 
4
- import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
3
+ import { extractSupportProps } from '@snack-uikit/utils';
5
4
 
6
5
  import { APPEARANCE, SIZE } from '../../constants';
7
- import { CommonTagProps } from '../../types';
6
+ import { TagLinkProps } from '../../types';
8
7
  import styles from './styles.module.scss';
9
8
 
10
- export type TagLinkProps = WithSupportProps<CommonTagProps> & {
11
- href: string;
12
- onClick?(e: MouseEvent<HTMLAnchorElement>): void;
13
- target?: HTMLAnchorElement['target'];
14
- };
15
-
16
9
  export function TagLink({
17
10
  label,
18
11
  size = SIZE.Xs,
@@ -35,9 +28,7 @@ export function TagLink({
35
28
  target={target}
36
29
  onClick={onClick}
37
30
  >
38
- <span title={label} className={styles.label}>
39
- {label}
40
- </span>
31
+ <span className={styles.label}>{label}</span>
41
32
  </a>
42
33
  );
43
34
  }
@@ -1,13 +1,7 @@
1
1
  import { APPEARANCE } from '../../constants';
2
2
  import { TagRowItem, TagRowItemInner } from '../../types';
3
3
 
4
- export const mapTagRowItem = ({ label, appearance }: TagRowItem): TagRowItemInner => {
5
- if (appearance) {
6
- return { label, appearance };
7
- }
8
-
9
- return {
10
- label,
11
- appearance: APPEARANCE.Neutral,
12
- };
13
- };
4
+ export const mapTagRowItem = ({ appearance = APPEARANCE.Neutral, ...props }: TagRowItem): TagRowItemInner => ({
5
+ ...props,
6
+ appearance,
7
+ });
@@ -20,7 +20,7 @@ function renderTag(size: Size, handleRemoveItem?: (item: TagRowItemInner) => OnD
20
20
  return function TagRowItem(item: TagRowItemInner, index: number) {
21
21
  return (
22
22
  <div key={item.label} ref={setRef?.(item, index)} className={styles.tagWrapper}>
23
- <Tag label={item.label} appearance={item.appearance} size={size} onDelete={handleRemoveItem?.(item)} />
23
+ <Tag size={size} onDelete={handleRemoveItem?.(item)} {...item} />
24
24
  </div>
25
25
  );
26
26
  };
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './components';
2
2
  export * from './constants';
3
- export type { Appearance, Size, TagRowItem } from './types';
3
+ export type { Appearance, Size, TagRowItem, TagProps } from './types';
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { MouseEvent } from 'react';
1
+ import { MouseEvent, MouseEventHandler } from 'react';
2
2
 
3
- import { ValueOf } from '@snack-uikit/utils';
3
+ import { TooltipProps } from '@snack-uikit/tooltip';
4
+ import { ValueOf, WithSupportProps } from '@snack-uikit/utils';
4
5
 
5
6
  import { APPEARANCE, SIZE } from './constants';
6
7
 
@@ -14,15 +15,20 @@ export type LinkProps = {
14
15
  target?: HTMLAnchorElement['target'];
15
16
  };
16
17
 
18
+ export type TagTooltipProps = {
19
+ /** Тултип над тегом */
20
+ tooltip?: TooltipProps;
21
+ };
22
+
17
23
  export type TagRowItem = {
18
24
  label: string;
19
25
  appearance?: Appearance;
20
- } & Partial<LinkProps>;
26
+ } & Partial<LinkProps> &
27
+ TagTooltipProps;
21
28
 
22
- export type TagRowItemInner = {
23
- label: string;
29
+ export type TagRowItemInner = Omit<TagRowItem, 'appearance'> & {
24
30
  appearance: Appearance;
25
- } & Partial<LinkProps>;
31
+ };
26
32
 
27
33
  export type CommonTagProps = {
28
34
  /** Текст */
@@ -36,3 +42,24 @@ export type CommonTagProps = {
36
42
  /** tabIndex кнопки удаления */
37
43
  tabIndex?: number;
38
44
  };
45
+
46
+ export type TagBaseProps = WithSupportProps<{
47
+ /** Коллбэк на удаление */
48
+ onDelete?: MouseEventHandler<HTMLButtonElement>;
49
+ }> &
50
+ CommonTagProps;
51
+
52
+ export type TagLinkProps = WithSupportProps<CommonTagProps> & {
53
+ href: string;
54
+ onClick?(e: MouseEvent<HTMLAnchorElement>): void;
55
+ target?: HTMLAnchorElement['target'];
56
+ };
57
+
58
+ export type ManageRestrictTooltipProps = {
59
+ changeRestrictTooltipState(state: boolean): void;
60
+ };
61
+
62
+ type TagWithoutTooltipProps = TagBaseProps | TagLinkProps;
63
+ export type TagWithTooltipProps = TagWithoutTooltipProps & TagTooltipProps;
64
+
65
+ export type TagProps = TagWithoutTooltipProps | TagWithTooltipProps;