@snack-uikit/card 0.16.14 → 0.16.15-preview-31ae96b0.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.
Files changed (30) hide show
  1. package/README.md +4 -3
  2. package/dist/cjs/components/Card/Card.d.ts +12 -8
  3. package/dist/cjs/components/Card/Card.js +31 -27
  4. package/dist/cjs/components/Card/styles.module.css +3 -10
  5. package/dist/cjs/components/Footer/components/Action/Action.js +14 -0
  6. package/dist/cjs/components/Footer/components/Promo/Promo.js +7 -0
  7. package/dist/cjs/components/FunctionBadge/FunctionBadge.js +1 -0
  8. package/dist/cjs/constants.d.ts +0 -1
  9. package/dist/cjs/constants.js +1 -2
  10. package/dist/esm/components/Card/Card.d.ts +12 -8
  11. package/dist/esm/components/Card/Card.js +11 -19
  12. package/dist/esm/components/Card/styles.module.css +3 -10
  13. package/dist/esm/components/Footer/components/Action/Action.js +13 -1
  14. package/dist/esm/components/Footer/components/Promo/Promo.js +7 -1
  15. package/dist/esm/components/FunctionBadge/FunctionBadge.js +1 -0
  16. package/dist/esm/constants.d.ts +0 -1
  17. package/dist/esm/constants.js +0 -1
  18. package/package.json +3 -4
  19. package/src/components/Card/Card.tsx +39 -44
  20. package/src/components/Card/styles.module.scss +2 -12
  21. package/src/components/Footer/components/Action/Action.tsx +25 -2
  22. package/src/components/Footer/components/Promo/Promo.tsx +11 -1
  23. package/src/components/FunctionBadge/FunctionBadge.tsx +2 -0
  24. package/src/components/FunctionBadge/styles.module.scss +1 -1
  25. package/src/constants.ts +0 -1
  26. package/dist/cjs/components/Card/constants.d.ts +0 -1
  27. package/dist/cjs/components/Card/constants.js +0 -7
  28. package/dist/esm/components/Card/constants.d.ts +0 -1
  29. package/dist/esm/components/Card/constants.js +0 -1
  30. package/src/components/Card/constants.ts +0 -1
package/README.md CHANGED
@@ -32,7 +32,6 @@ import { Card, SearchPrivate } from "@snack-uikit/card";
32
32
  | checked | `boolean` | - | Управление состоянием выбран/не выбран |
33
33
  | outline | `boolean` | - | Управление состоянием наличия обводки |
34
34
  | multipleSelection | `boolean` | - | Отображение галочки для режима массового выделения карточек |
35
- | onClick | `(e: MouseEvent<HTMLDivElement \| HTMLAnchorElement, MouseEvent>) => void` | - | Колбек на клик по карточке |
36
35
  | size | enum Size: `"s"`, `"m"`, `"l"` | - | Размер |
37
36
  | promoBadge | `string \| Pick<PromoTagProps, "text" \| "appearance">` | - | PromoBadge |
38
37
  | children | `ReactNode` | - | Вложенный контент |
@@ -42,8 +41,10 @@ import { Card, SearchPrivate } from "@snack-uikit/card";
42
41
  | functionBadge | `ReactNode` | - | Вложенный FunctionBadge |
43
42
  | className | `string` | - | CSS-класс для элемента с контентом |
44
43
  | href | `string` | - | Ссылка карточки |
45
- | onKeyDown | `KeyboardEventHandler<HTMLDivElement>` | - | Колбек нажатия клавиши клавиатуры |
46
- | ref | `LegacyRef<HTMLDivElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
44
+ | target | `HTMLAttributeAnchorTarget` | - | Атрибут target для ссылки |
45
+ | onClick | `(e: MouseEvent<HTMLAnchorElement \| HTMLDivElement, MouseEvent>) => void` | - | Колбек на клик по карточке |
46
+ | onKeyDown | `KeyboardEventHandler<HTMLAnchorElement \| HTMLDivElement>` | - | Колбек нажатия клавиши клавиатуры |
47
+ | ref | `LegacyRef<HTMLAnchorElement \| HTMLDivElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
47
48
  | key | `Key` | - | |
48
49
 
49
50
 
@@ -1,4 +1,4 @@
1
- import { KeyboardEventHandler, MouseEvent, ReactElement, ReactNode } from 'react';
1
+ import { HTMLAttributeAnchorTarget, KeyboardEventHandler, MouseEvent, ReactElement, ReactNode } from 'react';
2
2
  import { PromoTagProps } from '@snack-uikit/promo-tag';
3
3
  import { WithSupportProps } from '@snack-uikit/utils';
4
4
  import { Size } from '../../types';
@@ -12,8 +12,6 @@ export type CardProps = WithSupportProps<{
12
12
  outline?: boolean;
13
13
  /** Отображение галочки для режима массового выделения карточек */
14
14
  multipleSelection?: boolean;
15
- /** Колбек на клик по карточке */
16
- onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
17
15
  /** Размер */
18
16
  size?: Size;
19
17
  /** PromoBadge */
@@ -32,8 +30,12 @@ export type CardProps = WithSupportProps<{
32
30
  className?: string;
33
31
  /** Ссылка карточки */
34
32
  href?: string;
33
+ /** Атрибут target для ссылки */
34
+ target?: HTMLAttributeAnchorTarget;
35
+ /** Колбек на клик по карточке */
36
+ onClick?(e: MouseEvent<HTMLAnchorElement | HTMLDivElement>): void;
35
37
  /** Колбек нажатия клавиши клавиатуры */
36
- onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
38
+ onKeyDown?: KeyboardEventHandler<HTMLAnchorElement | HTMLDivElement>;
37
39
  }>;
38
40
  export declare const Card: import("react").ForwardRefExoticComponent<{
39
41
  'data-test-id'?: string;
@@ -46,8 +48,6 @@ export declare const Card: import("react").ForwardRefExoticComponent<{
46
48
  outline?: boolean;
47
49
  /** Отображение галочки для режима массового выделения карточек */
48
50
  multipleSelection?: boolean;
49
- /** Колбек на клик по карточке */
50
- onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
51
51
  /** Размер */
52
52
  size?: Size;
53
53
  /** PromoBadge */
@@ -66,6 +66,10 @@ export declare const Card: import("react").ForwardRefExoticComponent<{
66
66
  className?: string;
67
67
  /** Ссылка карточки */
68
68
  href?: string;
69
+ /** Атрибут target для ссылки */
70
+ target?: HTMLAttributeAnchorTarget;
71
+ /** Колбек на клик по карточке */
72
+ onClick?(e: MouseEvent<HTMLAnchorElement | HTMLDivElement>): void;
69
73
  /** Колбек нажатия клавиши клавиатуры */
70
- onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
71
- } & import("react").RefAttributes<HTMLDivElement>>;
74
+ onKeyDown?: KeyboardEventHandler<HTMLAnchorElement | HTMLDivElement>;
75
+ } & import("react").RefAttributes<HTMLDivElement | HTMLAnchorElement>>;
@@ -19,15 +19,34 @@ Object.defineProperty(exports, "__esModule", {
19
19
  exports.Card = void 0;
20
20
  const jsx_runtime_1 = require("react/jsx-runtime");
21
21
  const classnames_1 = __importDefault(require("classnames"));
22
- const merge_refs_1 = __importDefault(require("merge-refs"));
23
22
  const react_1 = require("react");
24
23
  const typography_1 = require("@snack-uikit/typography");
25
24
  const utils_1 = require("@snack-uikit/utils");
26
25
  const constants_1 = require("../../constants");
27
26
  const context_1 = require("../../context");
28
27
  const helperComponents_1 = require("../../helperComponents");
29
- const constants_2 = require("./constants");
30
28
  const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
29
+ const CardTag = (0, react_1.forwardRef)((_a, ref) => {
30
+ var {
31
+ children,
32
+ href,
33
+ target,
34
+ disabled
35
+ } = _a,
36
+ props = __rest(_a, ["children", "href", "target", "disabled"]);
37
+ if (href && !disabled) {
38
+ return (0, jsx_runtime_1.jsx)("a", Object.assign({}, props, {
39
+ href: href,
40
+ target: target,
41
+ ref: ref,
42
+ children: children
43
+ }));
44
+ }
45
+ return (0, jsx_runtime_1.jsx)("div", Object.assign({}, props, {
46
+ ref: ref,
47
+ children: children
48
+ }));
49
+ });
31
50
  exports.Card = (0, react_1.forwardRef)((_a, ref) => {
32
51
  var {
33
52
  onClick,
@@ -44,28 +63,18 @@ exports.Card = (0, react_1.forwardRef)((_a, ref) => {
44
63
  image,
45
64
  className,
46
65
  href,
47
- onKeyDown: onKeyDownProp
66
+ onKeyDown,
67
+ target
48
68
  } = _a,
49
- rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className", "href", "onKeyDown"]);
50
- const localDivRef = (0, react_1.useRef)(null);
51
- const localAnchorRef = (0, react_1.useRef)(null);
52
- const onKeyDown = (0, react_1.useCallback)(e => {
53
- var _a, _b;
54
- if (e.target === localDivRef.current) {
55
- if (constants_2.TRIGGER_CLICK_KEY_CODES.includes(e.code) || e.key === ' ') {
56
- href ? (_a = localAnchorRef.current) === null || _a === void 0 ? void 0 : _a.click() : (_b = localDivRef.current) === null || _b === void 0 ? void 0 : _b.click();
57
- }
58
- onKeyDownProp === null || onKeyDownProp === void 0 ? void 0 : onKeyDownProp(e);
59
- }
60
- }, [href, onKeyDownProp]);
69
+ rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className", "href", "onKeyDown", "target"]);
61
70
  const supportProps = (0, utils_1.extractSupportProps)(rest);
62
71
  return (0, jsx_runtime_1.jsx)(context_1.CardContext.Provider, {
63
72
  value: {
64
73
  size,
65
74
  disabled
66
75
  },
67
- children: (0, jsx_runtime_1.jsxs)("div", Object.assign({
68
- ref: (0, merge_refs_1.default)(ref, localDivRef),
76
+ children: (0, jsx_runtime_1.jsxs)(CardTag, Object.assign({
77
+ ref: ref,
69
78
  className: (0, classnames_1.default)(styles_module_scss_1.default.card, className)
70
79
  }, supportProps, {
71
80
  onClick: onClick,
@@ -73,20 +82,15 @@ exports.Card = (0, react_1.forwardRef)((_a, ref) => {
73
82
  "data-checked": checked || undefined,
74
83
  "data-outline": outline || undefined,
75
84
  "data-pointer": onClick ? true : undefined,
76
- // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
85
+ disabled: disabled,
86
+ href: href,
87
+ target: target,
77
88
  tabIndex: 0,
78
89
  onKeyDown: onKeyDown,
79
90
  children: [image, (0, jsx_runtime_1.jsxs)("div", {
80
91
  className: styles_module_scss_1.default.composition,
81
92
  tabIndex: -1,
82
- children: [href && (0, jsx_runtime_1.jsx)("a", {
83
- ref: localAnchorRef,
84
- "data-test-id": constants_1.TEST_IDS.anchor,
85
- tabIndex: -1,
86
- href: href,
87
- className: styles_module_scss_1.default.anchor,
88
- "aria-label": supportProps['aria-label']
89
- }), !disabled && functionBadge && (0, jsx_runtime_1.jsx)(helperComponents_1.FunctionBadgeWrapper, {
93
+ children: [!disabled && functionBadge && (0, jsx_runtime_1.jsx)(helperComponents_1.FunctionBadgeWrapper, {
90
94
  className: styles_module_scss_1.default.functionBadgeWrapper,
91
95
  children: functionBadge
92
96
  }), (0, jsx_runtime_1.jsx)("div", {
@@ -94,7 +98,7 @@ exports.Card = (0, react_1.forwardRef)((_a, ref) => {
94
98
  children: (0, jsx_runtime_1.jsxs)("div", {
95
99
  className: styles_module_scss_1.default.content,
96
100
  "data-size": size,
97
- children: [header || null, children && (0, jsx_runtime_1.jsx)(typography_1.Typography, {
101
+ children: [header, children && (0, jsx_runtime_1.jsx)(typography_1.Typography, {
98
102
  family: 'sans',
99
103
  size: size,
100
104
  purpose: 'body',
@@ -32,6 +32,9 @@
32
32
  margin:0;
33
33
  padding:0;
34
34
  text-align:left;
35
+ text-decoration:none;
36
+ -webkit-text-decoration-skip-ink:none;
37
+ text-decoration-skip-ink:none;
35
38
  background-color:var(--sys-neutral-background1-level, #fdfdfd);
36
39
  border:0;
37
40
  outline-color:transparent;
@@ -137,16 +140,6 @@
137
140
  cursor:not-allowed;
138
141
  }
139
142
 
140
- .anchor{
141
- position:absolute;
142
- z-index:1;
143
- top:0;
144
- right:0;
145
- bottom:0;
146
- left:0;
147
- border-radius:var(--radius-card-container, 20px);
148
- }
149
-
150
143
  .body{
151
144
  display:block;
152
145
  flex-grow:1;
@@ -33,14 +33,28 @@ function FooterAction(_a) {
33
33
  const {
34
34
  disabled
35
35
  } = (0, context_1.useCardContext)();
36
+ const handleButtonClick = e => {
37
+ var _a;
38
+ e.stopPropagation();
39
+ e.preventDefault();
40
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
41
+ };
42
+ const handleSecondaryButtonClick = e => {
43
+ var _a;
44
+ e.stopPropagation();
45
+ e.preventDefault();
46
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
47
+ };
36
48
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({
37
49
  className: (0, classnames_1.default)(styles_module_scss_1.default.action, className)
38
50
  }, (0, utils_1.excludeSupportProps)(rest), {
39
51
  children: [(0, jsx_runtime_1.jsx)(button_1.ButtonFilled, Object.assign({}, button, {
52
+ onClick: handleButtonClick,
40
53
  appearance: 'primary',
41
54
  size: 'm',
42
55
  disabled: disabled
43
56
  })), secondaryButton && (0, jsx_runtime_1.jsx)(button_1.ButtonTonal, Object.assign({}, secondaryButton, {
57
+ onClick: handleSecondaryButtonClick,
44
58
  appearance: 'neutral',
45
59
  size: 'm',
46
60
  disabled: disabled
@@ -35,10 +35,17 @@ function FooterPromo(_a) {
35
35
  const {
36
36
  disabled
37
37
  } = (0, context_1.useCardContext)();
38
+ const handleButtonClick = e => {
39
+ var _a;
40
+ e.stopPropagation();
41
+ e.preventDefault();
42
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
43
+ };
38
44
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({
39
45
  className: (0, classnames_1.default)(styles_module_scss_1.default.promo, className)
40
46
  }, (0, utils_1.excludeSupportProps)(rest), {
41
47
  children: [button && (0, jsx_runtime_1.jsx)(button_1.ButtonFilled, Object.assign({}, button, {
48
+ onClick: handleButtonClick,
42
49
  appearance: 'primary',
43
50
  size: 'm',
44
51
  disabled: disabled
@@ -41,6 +41,7 @@ function FunctionBadge(_ref) {
41
41
  }, [isOpen, setVisible]);
42
42
  const onClick = (0, react_1.useCallback)(e => {
43
43
  e.stopPropagation();
44
+ e.preventDefault();
44
45
  setIsOpen(isOpen => !isOpen);
45
46
  }, []);
46
47
  return (0, jsx_runtime_1.jsx)("span", {
@@ -14,5 +14,4 @@ export declare const TEST_IDS: {
14
14
  title: string;
15
15
  description: string;
16
16
  metadata: string;
17
- anchor: string;
18
17
  };
@@ -19,6 +19,5 @@ exports.TEST_IDS = {
19
19
  emblemIcon: 'card__header__emblem-icon',
20
20
  title: 'card__header__title',
21
21
  description: 'card__header__description',
22
- metadata: 'card__header__metadata',
23
- anchor: 'card__anchor'
22
+ metadata: 'card__header__metadata'
24
23
  };
@@ -1,4 +1,4 @@
1
- import { KeyboardEventHandler, MouseEvent, ReactElement, ReactNode } from 'react';
1
+ import { HTMLAttributeAnchorTarget, KeyboardEventHandler, MouseEvent, ReactElement, ReactNode } from 'react';
2
2
  import { PromoTagProps } from '@snack-uikit/promo-tag';
3
3
  import { WithSupportProps } from '@snack-uikit/utils';
4
4
  import { Size } from '../../types';
@@ -12,8 +12,6 @@ export type CardProps = WithSupportProps<{
12
12
  outline?: boolean;
13
13
  /** Отображение галочки для режима массового выделения карточек */
14
14
  multipleSelection?: boolean;
15
- /** Колбек на клик по карточке */
16
- onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
17
15
  /** Размер */
18
16
  size?: Size;
19
17
  /** PromoBadge */
@@ -32,8 +30,12 @@ export type CardProps = WithSupportProps<{
32
30
  className?: string;
33
31
  /** Ссылка карточки */
34
32
  href?: string;
33
+ /** Атрибут target для ссылки */
34
+ target?: HTMLAttributeAnchorTarget;
35
+ /** Колбек на клик по карточке */
36
+ onClick?(e: MouseEvent<HTMLAnchorElement | HTMLDivElement>): void;
35
37
  /** Колбек нажатия клавиши клавиатуры */
36
- onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
38
+ onKeyDown?: KeyboardEventHandler<HTMLAnchorElement | HTMLDivElement>;
37
39
  }>;
38
40
  export declare const Card: import("react").ForwardRefExoticComponent<{
39
41
  'data-test-id'?: string;
@@ -46,8 +48,6 @@ export declare const Card: import("react").ForwardRefExoticComponent<{
46
48
  outline?: boolean;
47
49
  /** Отображение галочки для режима массового выделения карточек */
48
50
  multipleSelection?: boolean;
49
- /** Колбек на клик по карточке */
50
- onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
51
51
  /** Размер */
52
52
  size?: Size;
53
53
  /** PromoBadge */
@@ -66,6 +66,10 @@ export declare const Card: import("react").ForwardRefExoticComponent<{
66
66
  className?: string;
67
67
  /** Ссылка карточки */
68
68
  href?: string;
69
+ /** Атрибут target для ссылки */
70
+ target?: HTMLAttributeAnchorTarget;
71
+ /** Колбек на клик по карточке */
72
+ onClick?(e: MouseEvent<HTMLAnchorElement | HTMLDivElement>): void;
69
73
  /** Колбек нажатия клавиши клавиатуры */
70
- onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
71
- } & import("react").RefAttributes<HTMLDivElement>>;
74
+ onKeyDown?: KeyboardEventHandler<HTMLAnchorElement | HTMLDivElement>;
75
+ } & import("react").RefAttributes<HTMLDivElement | HTMLAnchorElement>>;
@@ -11,30 +11,22 @@ 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 mergeRefs from 'merge-refs';
15
- import { forwardRef, useCallback, useRef, } from 'react';
14
+ import { forwardRef, } from 'react';
16
15
  import { Typography } from '@snack-uikit/typography';
17
16
  import { extractSupportProps } from '@snack-uikit/utils';
18
- import { SIZE, TEST_IDS } from '../../constants';
17
+ import { SIZE } from '../../constants';
19
18
  import { CardContext } from '../../context';
20
19
  import { Check, FunctionBadgeWrapper, PromoBadge } from '../../helperComponents';
21
- import { TRIGGER_CLICK_KEY_CODES } from './constants';
22
20
  import styles from './styles.module.css';
21
+ const CardTag = forwardRef((_a, ref) => {
22
+ var { children, href, target, disabled } = _a, props = __rest(_a, ["children", "href", "target", "disabled"]);
23
+ if (href && !disabled) {
24
+ return (_jsx("a", Object.assign({}, props, { href: href, target: target, ref: ref, children: children })));
25
+ }
26
+ return (_jsx("div", Object.assign({}, props, { ref: ref, children: children })));
27
+ });
23
28
  export const Card = forwardRef((_a, ref) => {
24
- var { onClick, disabled = false, checked, outline, multipleSelection = false, size = SIZE.M, children, header, footer, functionBadge, promoBadge, image, className, href, onKeyDown: onKeyDownProp } = _a, rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className", "href", "onKeyDown"]);
25
- const localDivRef = useRef(null);
26
- const localAnchorRef = useRef(null);
27
- const onKeyDown = useCallback((e) => {
28
- var _a, _b;
29
- if (e.target === localDivRef.current) {
30
- if (TRIGGER_CLICK_KEY_CODES.includes(e.code) || e.key === ' ') {
31
- href ? (_a = localAnchorRef.current) === null || _a === void 0 ? void 0 : _a.click() : (_b = localDivRef.current) === null || _b === void 0 ? void 0 : _b.click();
32
- }
33
- onKeyDownProp === null || onKeyDownProp === void 0 ? void 0 : onKeyDownProp(e);
34
- }
35
- }, [href, onKeyDownProp]);
29
+ var { onClick, disabled = false, checked, outline, multipleSelection = false, size = SIZE.M, children, header, footer, functionBadge, promoBadge, image, className, href, onKeyDown, target } = _a, rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className", "href", "onKeyDown", "target"]);
36
30
  const supportProps = extractSupportProps(rest);
37
- return (_jsx(CardContext.Provider, { value: { size, disabled }, children: _jsxs("div", Object.assign({ ref: mergeRefs(ref, localDivRef), className: cn(styles.card, className) }, supportProps, { onClick: onClick, "data-disabled": disabled || undefined, "data-checked": checked || undefined, "data-outline": outline || undefined, "data-pointer": onClick ? true : undefined,
38
- // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
39
- tabIndex: 0, onKeyDown: onKeyDown, children: [image, _jsxs("div", { className: styles.composition, tabIndex: -1, children: [href && (_jsx("a", { ref: localAnchorRef, "data-test-id": TEST_IDS.anchor, tabIndex: -1, href: href, className: styles.anchor, "aria-label": supportProps['aria-label'] })), !disabled && functionBadge && (_jsx(FunctionBadgeWrapper, { className: styles.functionBadgeWrapper, children: functionBadge })), _jsx("div", { className: styles.contentWrapper, children: _jsxs("div", { className: styles.content, "data-size": size, children: [header || null, children && (_jsx(Typography, { family: 'sans', size: size, purpose: 'body', className: styles.body, tag: 'div', children: children })), footer && _jsx("div", { className: styles.footer, children: footer })] }) }), promoBadge && _jsx(PromoBadge, Object.assign({}, (typeof promoBadge === 'string' ? { text: promoBadge } : promoBadge)))] }), checked && multipleSelection && _jsx(Check, { className: styles.check })] })) }));
31
+ return (_jsx(CardContext.Provider, { value: { size, disabled }, children: _jsxs(CardTag, Object.assign({ ref: ref, className: cn(styles.card, className) }, supportProps, { onClick: onClick, "data-disabled": disabled || undefined, "data-checked": checked || undefined, "data-outline": outline || undefined, "data-pointer": onClick ? true : undefined, disabled: disabled, href: href, target: target, tabIndex: 0, onKeyDown: onKeyDown, children: [image, _jsxs("div", { className: styles.composition, tabIndex: -1, children: [!disabled && functionBadge && (_jsx(FunctionBadgeWrapper, { className: styles.functionBadgeWrapper, children: functionBadge })), _jsx("div", { className: styles.contentWrapper, children: _jsxs("div", { className: styles.content, "data-size": size, children: [header, children && (_jsx(Typography, { family: 'sans', size: size, purpose: 'body', className: styles.body, tag: 'div', children: children })), footer && _jsx("div", { className: styles.footer, children: footer })] }) }), promoBadge && _jsx(PromoBadge, Object.assign({}, (typeof promoBadge === 'string' ? { text: promoBadge } : promoBadge)))] }), checked && multipleSelection && _jsx(Check, { className: styles.check })] })) }));
40
32
  });
@@ -32,6 +32,9 @@
32
32
  margin:0;
33
33
  padding:0;
34
34
  text-align:left;
35
+ text-decoration:none;
36
+ -webkit-text-decoration-skip-ink:none;
37
+ text-decoration-skip-ink:none;
35
38
  background-color:var(--sys-neutral-background1-level, #fdfdfd);
36
39
  border:0;
37
40
  outline-color:transparent;
@@ -137,16 +140,6 @@
137
140
  cursor:not-allowed;
138
141
  }
139
142
 
140
- .anchor{
141
- position:absolute;
142
- z-index:1;
143
- top:0;
144
- right:0;
145
- bottom:0;
146
- left:0;
147
- border-radius:var(--radius-card-container, 20px);
148
- }
149
-
150
143
  .body{
151
144
  display:block;
152
145
  flex-grow:1;
@@ -18,5 +18,17 @@ import styles from './styles.module.css';
18
18
  export function FooterAction(_a) {
19
19
  var { button, secondaryButton, className } = _a, rest = __rest(_a, ["button", "secondaryButton", "className"]);
20
20
  const { disabled } = useCardContext();
21
- return (_jsxs("div", Object.assign({ className: cn(styles.action, className) }, excludeSupportProps(rest), { children: [_jsx(ButtonFilled, Object.assign({}, button, { appearance: 'primary', size: 'm', disabled: disabled })), secondaryButton && _jsx(ButtonTonal, Object.assign({}, secondaryButton, { appearance: 'neutral', size: 'm', disabled: disabled }))] })));
21
+ const handleButtonClick = e => {
22
+ var _a;
23
+ e.stopPropagation();
24
+ e.preventDefault();
25
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
26
+ };
27
+ const handleSecondaryButtonClick = e => {
28
+ var _a;
29
+ e.stopPropagation();
30
+ e.preventDefault();
31
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
32
+ };
33
+ return (_jsxs("div", Object.assign({ className: cn(styles.action, className) }, excludeSupportProps(rest), { children: [_jsx(ButtonFilled, Object.assign({}, button, { onClick: handleButtonClick, appearance: 'primary', size: 'm', disabled: disabled })), secondaryButton && (_jsx(ButtonTonal, Object.assign({}, secondaryButton, { onClick: handleSecondaryButtonClick, appearance: 'neutral', size: 'm', disabled: disabled })))] })));
22
34
  }
@@ -19,5 +19,11 @@ import styles from './styles.module.css';
19
19
  export function FooterPromo(_a) {
20
20
  var { volume, button, className, size } = _a, rest = __rest(_a, ["volume", "button", "className", "size"]);
21
21
  const { disabled } = useCardContext();
22
- return (_jsxs("div", Object.assign({ className: cn(styles.promo, className) }, excludeSupportProps(rest), { children: [button && _jsx(ButtonFilled, Object.assign({}, button, { appearance: 'primary', size: 'm', disabled: disabled })), volume && _jsx(Dimension, Object.assign({}, volume, { size: size }))] })));
22
+ const handleButtonClick = e => {
23
+ var _a;
24
+ e.stopPropagation();
25
+ e.preventDefault();
26
+ (_a = button === null || button === void 0 ? void 0 : button.onClick) === null || _a === void 0 ? void 0 : _a.call(button, e);
27
+ };
28
+ return (_jsxs("div", Object.assign({ className: cn(styles.promo, className) }, excludeSupportProps(rest), { children: [button && (_jsx(ButtonFilled, Object.assign({}, button, { onClick: handleButtonClick, appearance: 'primary', size: 'm', disabled: disabled }))), volume && _jsx(Dimension, Object.assign({}, volume, { size: size }))] })));
23
29
  }
@@ -27,6 +27,7 @@ export function FunctionBadge({ icon, options }) {
27
27
  }, [isOpen, setVisible]);
28
28
  const onClick = useCallback((e) => {
29
29
  e.stopPropagation();
30
+ e.preventDefault();
30
31
  setIsOpen(isOpen => !isOpen);
31
32
  }, []);
32
33
  return (_jsx("span", { className: styles.wrapper, children: _jsx(Droplist, { trigger: 'clickAndFocusVisible', open: isOpen, onOpenChange: setIsOpen, widthStrategy: 'gte', scroll: true, "data-test-id": TEST_IDS.droplist, placement: 'bottom-end', triggerElemRef: buttonRef, items: options.map((_a) => {
@@ -14,5 +14,4 @@ export declare const TEST_IDS: {
14
14
  title: string;
15
15
  description: string;
16
16
  metadata: string;
17
- anchor: string;
18
17
  };
@@ -14,5 +14,4 @@ export const TEST_IDS = {
14
14
  title: 'card__header__title',
15
15
  description: 'card__header__description',
16
16
  metadata: 'card__header__metadata',
17
- anchor: 'card__anchor',
18
17
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Card",
7
- "version": "0.16.14",
7
+ "version": "0.16.15-preview-31ae96b0.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -45,8 +45,7 @@
45
45
  "@snack-uikit/truncate-string": "0.6.6",
46
46
  "@snack-uikit/typography": "0.8.4",
47
47
  "@snack-uikit/utils": "3.7.0",
48
- "classnames": "2.5.1",
49
- "merge-refs": "1.3.0"
48
+ "classnames": "2.5.1"
50
49
  },
51
- "gitHead": "3528e78aec23804dca44d311947c1dcd4ed3792b"
50
+ "gitHead": "88a3023d9740bca7c55a403e7590d9fb21083dad"
52
51
  }
@@ -1,26 +1,23 @@
1
1
  import cn from 'classnames';
2
- import mergeRefs from 'merge-refs';
3
2
  import {
3
+ ForwardedRef,
4
4
  forwardRef,
5
- KeyboardEvent,
5
+ HTMLAttributeAnchorTarget,
6
6
  KeyboardEventHandler,
7
7
  MouseEvent,
8
8
  ReactElement,
9
9
  ReactNode,
10
- useCallback,
11
- useRef,
12
10
  } from 'react';
13
11
 
14
12
  import { PromoTagProps } from '@snack-uikit/promo-tag';
15
13
  import { Typography } from '@snack-uikit/typography';
16
14
  import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
17
15
 
18
- import { SIZE, TEST_IDS } from '../../constants';
16
+ import { SIZE } from '../../constants';
19
17
  import { CardContext } from '../../context';
20
18
  import { Check, FunctionBadgeWrapper, PromoBadge } from '../../helperComponents';
21
19
  import { Size } from '../../types';
22
20
  import { HeaderProps } from '../Header';
23
- import { TRIGGER_CLICK_KEY_CODES } from './constants';
24
21
  import styles from './styles.module.scss';
25
22
 
26
23
  export type CardProps = WithSupportProps<{
@@ -32,8 +29,6 @@ export type CardProps = WithSupportProps<{
32
29
  outline?: boolean;
33
30
  /** Отображение галочки для режима массового выделения карточек */
34
31
  multipleSelection?: boolean;
35
- /** Колбек на клик по карточке */
36
- onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
37
32
  /** Размер */
38
33
  size?: Size;
39
34
  /** PromoBadge */
@@ -52,11 +47,36 @@ export type CardProps = WithSupportProps<{
52
47
  className?: string;
53
48
  /** Ссылка карточки */
54
49
  href?: string;
50
+ /** Атрибут target для ссылки */
51
+ target?: HTMLAttributeAnchorTarget;
52
+ /** Колбек на клик по карточке */
53
+ onClick?(e: MouseEvent<HTMLAnchorElement | HTMLDivElement>): void;
55
54
  /** Колбек нажатия клавиши клавиатуры */
56
- onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
55
+ onKeyDown?: KeyboardEventHandler<HTMLAnchorElement | HTMLDivElement>;
57
56
  }>;
58
57
 
59
- export const Card = forwardRef<HTMLDivElement, CardProps>(
58
+ const CardTag = forwardRef<
59
+ HTMLAnchorElement | HTMLDivElement,
60
+ CardProps & {
61
+ tabIndex?: number;
62
+ }
63
+ >(({ children, href, target, disabled, ...props }, ref) => {
64
+ if (href && !disabled) {
65
+ return (
66
+ <a {...props} href={href} target={target} ref={ref as ForwardedRef<HTMLAnchorElement>}>
67
+ {children}
68
+ </a>
69
+ );
70
+ }
71
+
72
+ return (
73
+ <div {...props} ref={ref as ForwardedRef<HTMLDivElement>}>
74
+ {children}
75
+ </div>
76
+ );
77
+ });
78
+
79
+ export const Card = forwardRef<HTMLAnchorElement | HTMLDivElement, CardProps>(
60
80
  (
61
81
  {
62
82
  onClick,
@@ -73,34 +93,18 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(
73
93
  image,
74
94
  className,
75
95
  href,
76
- onKeyDown: onKeyDownProp,
96
+ onKeyDown,
97
+ target,
77
98
  ...rest
78
99
  },
79
100
  ref,
80
101
  ) => {
81
- const localDivRef = useRef<HTMLDivElement>(null);
82
- const localAnchorRef = useRef<HTMLAnchorElement>(null);
83
-
84
- const onKeyDown = useCallback(
85
- (e: KeyboardEvent<HTMLDivElement>) => {
86
- if (e.target === localDivRef.current) {
87
- if (TRIGGER_CLICK_KEY_CODES.includes(e.code) || e.key === ' ') {
88
- href ? localAnchorRef.current?.click() : localDivRef.current?.click();
89
- }
90
-
91
- onKeyDownProp?.(e);
92
- }
93
- },
94
- [href, onKeyDownProp],
95
- );
96
-
97
102
  const supportProps = extractSupportProps(rest);
98
103
 
99
104
  return (
100
105
  <CardContext.Provider value={{ size, disabled }}>
101
- {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
102
- <div
103
- ref={mergeRefs(ref, localDivRef)}
106
+ <CardTag
107
+ ref={ref}
104
108
  className={cn(styles.card, className)}
105
109
  {...supportProps}
106
110
  onClick={onClick}
@@ -108,31 +112,22 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(
108
112
  data-checked={checked || undefined}
109
113
  data-outline={outline || undefined}
110
114
  data-pointer={onClick ? true : undefined}
111
- // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
115
+ disabled={disabled}
116
+ href={href}
117
+ target={target}
112
118
  tabIndex={0}
113
119
  onKeyDown={onKeyDown}
114
120
  >
115
121
  {image}
116
122
 
117
123
  <div className={styles.composition} tabIndex={-1}>
118
- {href && (
119
- <a
120
- ref={localAnchorRef}
121
- data-test-id={TEST_IDS.anchor}
122
- tabIndex={-1}
123
- href={href}
124
- className={styles.anchor}
125
- aria-label={supportProps['aria-label'] as string}
126
- />
127
- )}
128
-
129
124
  {!disabled && functionBadge && (
130
125
  <FunctionBadgeWrapper className={styles.functionBadgeWrapper}>{functionBadge}</FunctionBadgeWrapper>
131
126
  )}
132
127
 
133
128
  <div className={styles.contentWrapper}>
134
129
  <div className={styles.content} data-size={size}>
135
- {header || null}
130
+ {header}
136
131
 
137
132
  {children && (
138
133
  <Typography family='sans' size={size} purpose='body' className={styles.body} tag='div'>
@@ -148,7 +143,7 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(
148
143
  </div>
149
144
 
150
145
  {checked && multipleSelection && <Check className={styles.check} />}
151
- </div>
146
+ </CardTag>
152
147
  </CardContext.Provider>
153
148
  );
154
149
  },
@@ -45,6 +45,8 @@ $sizes: 's', 'm', 'l';
45
45
  padding: 0;
46
46
 
47
47
  text-align: left;
48
+ text-decoration: none;
49
+ text-decoration-skip-ink: none;
48
50
 
49
51
  background-color: styles-tokens-card.$sys-neutral-background1-level;
50
52
  border: 0;
@@ -187,18 +189,6 @@ $sizes: 's', 'm', 'l';
187
189
  }
188
190
  }
189
191
 
190
- .anchor {
191
- position: absolute;
192
- /* stylelint-disable-next-line declaration-property-value-allowed-list */
193
- z-index: 1;
194
- top: 0;
195
- right: 0;
196
- bottom: 0;
197
- left: 0;
198
-
199
- border-radius: styles-tokens-card.$radius-card-container;
200
- }
201
-
202
192
  .body {
203
193
  display: block;
204
194
  flex-grow: 1;
@@ -1,4 +1,5 @@
1
1
  import cn from 'classnames';
2
+ import { MouseEventHandler } from 'react';
2
3
 
3
4
  import { ButtonFilled, ButtonFilledProps, ButtonTonal, ButtonTonalProps } from '@snack-uikit/button';
4
5
  import { excludeSupportProps, WithSupportProps } from '@snack-uikit/utils';
@@ -18,10 +19,32 @@ export type FooterActionProps = WithSupportProps<{
18
19
  export function FooterAction({ button, secondaryButton, className, ...rest }: FooterActionProps) {
19
20
  const { disabled } = useCardContext();
20
21
 
22
+ const handleButtonClick: MouseEventHandler<HTMLButtonElement> = e => {
23
+ e.stopPropagation();
24
+ e.preventDefault();
25
+
26
+ button?.onClick?.(e);
27
+ };
28
+
29
+ const handleSecondaryButtonClick: MouseEventHandler<HTMLButtonElement> = e => {
30
+ e.stopPropagation();
31
+ e.preventDefault();
32
+
33
+ button?.onClick?.(e);
34
+ };
35
+
21
36
  return (
22
37
  <div className={cn(styles.action, className)} {...excludeSupportProps(rest)}>
23
- <ButtonFilled {...button} appearance='primary' size='m' disabled={disabled} />
24
- {secondaryButton && <ButtonTonal {...secondaryButton} appearance='neutral' size='m' disabled={disabled} />}
38
+ <ButtonFilled {...button} onClick={handleButtonClick} appearance='primary' size='m' disabled={disabled} />
39
+ {secondaryButton && (
40
+ <ButtonTonal
41
+ {...secondaryButton}
42
+ onClick={handleSecondaryButtonClick}
43
+ appearance='neutral'
44
+ size='m'
45
+ disabled={disabled}
46
+ />
47
+ )}
25
48
  </div>
26
49
  );
27
50
  }
@@ -1,4 +1,5 @@
1
1
  import cn from 'classnames';
2
+ import { MouseEventHandler } from 'react';
2
3
 
3
4
  import { ButtonFilled, ButtonFilledProps } from '@snack-uikit/button';
4
5
  import { excludeSupportProps, WithSupportProps } from '@snack-uikit/utils';
@@ -22,9 +23,18 @@ export type FooterPromoProps = WithSupportProps<{
22
23
  export function FooterPromo({ volume, button, className, size, ...rest }: FooterPromoProps) {
23
24
  const { disabled } = useCardContext();
24
25
 
26
+ const handleButtonClick: MouseEventHandler<HTMLButtonElement> = e => {
27
+ e.stopPropagation();
28
+ e.preventDefault();
29
+
30
+ button?.onClick?.(e);
31
+ };
32
+
25
33
  return (
26
34
  <div className={cn(styles.promo, className)} {...excludeSupportProps(rest)}>
27
- {button && <ButtonFilled {...button} appearance='primary' size='m' disabled={disabled} />}
35
+ {button && (
36
+ <ButtonFilled {...button} onClick={handleButtonClick} appearance='primary' size='m' disabled={disabled} />
37
+ )}
28
38
  {volume && <Dimension {...volume} size={size} />}
29
39
  </div>
30
40
  );
@@ -33,6 +33,8 @@ export function FunctionBadge({ icon, options }: FunctionBadgeProps) {
33
33
 
34
34
  const onClick = useCallback((e: MouseEvent<HTMLButtonElement>) => {
35
35
  e.stopPropagation();
36
+ e.preventDefault();
37
+
36
38
  setIsOpen(isOpen => !isOpen);
37
39
  }, []);
38
40
 
@@ -49,4 +49,4 @@
49
49
 
50
50
  li.item {
51
51
  width: max-content;
52
- }
52
+ }
package/src/constants.ts CHANGED
@@ -15,5 +15,4 @@ export const TEST_IDS = {
15
15
  title: 'card__header__title',
16
16
  description: 'card__header__description',
17
17
  metadata: 'card__header__metadata',
18
- anchor: 'card__anchor',
19
18
  };
@@ -1 +0,0 @@
1
- export declare const TRIGGER_CLICK_KEY_CODES: string[];
@@ -1,7 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.TRIGGER_CLICK_KEY_CODES = void 0;
7
- exports.TRIGGER_CLICK_KEY_CODES = ['Enter', 'Space'];
@@ -1 +0,0 @@
1
- export declare const TRIGGER_CLICK_KEY_CODES: string[];
@@ -1 +0,0 @@
1
- export const TRIGGER_CLICK_KEY_CODES = ['Enter', 'Space'];
@@ -1 +0,0 @@
1
- export const TRIGGER_CLICK_KEY_CODES = ['Enter', 'Space'];