@snack-uikit/card 0.9.12-preview-993a9cfb.0 → 0.10.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.10.0 (2024-02-20)
7
+
8
+
9
+ ### Features
10
+
11
+ * **FF-4295:** add href prop ([8874f1c](https://github.com/cloud-ru-tech/snack-uikit/commit/8874f1c5fef99ce1ef3033977de9fd538e829f42))
12
+
13
+
14
+
15
+
16
+
6
17
  ## 0.9.11 (2024-02-13)
7
18
 
8
19
  ### Only dependencies have been changed
package/README.md CHANGED
@@ -32,7 +32,7 @@ import { Card, SearchPrivate } from "@snack-uikit/card";
32
32
  | checked | `boolean` | - | Управление состоянием выбран/не выбран |
33
33
  | outline | `boolean` | - | Управление состоянием наличия обводки |
34
34
  | multipleSelection | `boolean` | - | Отображение галочки для режима массового выделения карточек |
35
- | onClick | `() => void` | - | Колбек на клик по карточке |
35
+ | onClick | `(e: MouseEvent<HTMLDivElement \| HTMLAnchorElement, MouseEvent>) => void` | - | Колбек на клик по карточке |
36
36
  | size | enum Size: `"s"`, `"m"`, `"l"` | - | Размер |
37
37
  | promoBadge | `string` | - | Текст для PromoBadge |
38
38
  | children | `ReactNode` | - | Вложенный контент |
@@ -41,6 +41,7 @@ import { Card, SearchPrivate } from "@snack-uikit/card";
41
41
  | image | `ReactNode` | - | Вложенный Image |
42
42
  | functionBadge | `ReactNode` | - | Вложенный FunctionBadge |
43
43
  | className | `string` | - | CSS-класс для элемента с контентом |
44
+ | href | `string` | - | Ссылка карточки |
44
45
 
45
46
 
46
47
  [//]: DOCUMENTATION_SECTION_END
@@ -1,4 +1,4 @@
1
- import { ReactElement, ReactNode } from 'react';
1
+ import { MouseEvent, ReactElement, ReactNode } from 'react';
2
2
  import { WithSupportProps } from '@snack-uikit/utils';
3
3
  import { Size } from '../../types';
4
4
  import { HeaderProps } from '../Header';
@@ -12,7 +12,7 @@ export type CardProps = WithSupportProps<{
12
12
  /** Отображение галочки для режима массового выделения карточек */
13
13
  multipleSelection?: boolean;
14
14
  /** Колбек на клик по карточке */
15
- onClick?(): void;
15
+ onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
16
16
  /** Размер */
17
17
  size?: Size;
18
18
  /** Текст для PromoBadge */
@@ -29,5 +29,7 @@ export type CardProps = WithSupportProps<{
29
29
  functionBadge?: ReactNode;
30
30
  /** CSS-класс для элемента с контентом */
31
31
  className?: string;
32
+ /** Ссылка карточки */
33
+ href?: string;
32
34
  }>;
33
- export declare function Card({ onClick, disabled, checked, outline, multipleSelection, size, children, header, footer, functionBadge, promoBadge, image, className, ...rest }: CardProps): import("react/jsx-runtime").JSX.Element;
35
+ export declare function Card({ onClick, disabled, checked, outline, multipleSelection, size, children, header, footer, functionBadge, promoBadge, image, className, href, ...rest }: CardProps): import("react/jsx-runtime").JSX.Element;
@@ -14,22 +14,25 @@ import cn from 'classnames';
14
14
  import { useCallback, useRef } from 'react';
15
15
  import { Typography } from '@snack-uikit/typography';
16
16
  import { extractSupportProps } from '@snack-uikit/utils';
17
- import { SIZE } from '../../constants';
17
+ import { SIZE, TEST_IDS } from '../../constants';
18
18
  import { CardContext } from '../../context';
19
19
  import { Check, FunctionBadgeWrapper, PromoBadge } from '../../helperComponents';
20
20
  import { TRIGGER_CLICK_KEY_CODES } from './constants';
21
21
  import styles from './styles.module.css';
22
22
  export function Card(_a) {
23
- var { onClick, disabled = false, checked, outline, multipleSelection = false, size = SIZE.M, children, header, footer, functionBadge, promoBadge, image, className } = _a, rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className"]);
24
- const localRef = useRef(null);
23
+ var { onClick, disabled = false, checked, outline, multipleSelection = false, size = SIZE.M, children, header, footer, functionBadge, promoBadge, image, className, href } = _a, rest = __rest(_a, ["onClick", "disabled", "checked", "outline", "multipleSelection", "size", "children", "header", "footer", "functionBadge", "promoBadge", "image", "className", "href"]);
24
+ const localDivRef = useRef(null);
25
+ const localAnchorRef = useRef(null);
25
26
  const onKeyDown = useCallback((e) => {
26
- if (e.target === localRef.current) {
27
+ var _a, _b;
28
+ if (e.target === localDivRef.current) {
27
29
  if (TRIGGER_CLICK_KEY_CODES.includes(e.code)) {
28
- onClick === null || onClick === void 0 ? void 0 : onClick();
30
+ href ? (_a = localAnchorRef.current) === null || _a === void 0 ? void 0 : _a.click() : (_b = localDivRef.current) === null || _b === void 0 ? void 0 : _b.click();
29
31
  }
30
32
  }
31
- }, [onClick]);
32
- return (_jsx(CardContext.Provider, { value: { size, disabled }, children: _jsxs("div", Object.assign({ ref: localRef, className: cn(styles.card, className) }, extractSupportProps(rest), { onClick: onClick, "data-disabled": disabled || undefined, "data-checked": checked || undefined, "data-outline": outline || undefined, "data-pointer": onClick ? true : undefined,
33
+ }, [href]);
34
+ const supportProps = extractSupportProps(rest);
35
+ return (_jsx(CardContext.Provider, { value: { size, disabled }, children: _jsxs("div", Object.assign({ 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,
33
36
  // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
34
- tabIndex: 0, onKeyDown: onKeyDown, children: [image, promoBadge && _jsx(PromoBadge, { text: promoBadge }), _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 || 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 })] }) })] }), !disabled && checked && multipleSelection && _jsx(Check, { className: styles.check })] })) }));
37
+ tabIndex: 0, onKeyDown: onKeyDown, children: [image, promoBadge && _jsx(PromoBadge, { text: promoBadge }), _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 })] }) })] }), !disabled && checked && multipleSelection && _jsx(Check, { className: styles.check })] })) }));
35
38
  }
@@ -1,5 +1,6 @@
1
1
  .functionBadgeWrapper{
2
2
  position:absolute;
3
+ z-index:1;
3
4
  top:0;
4
5
  right:0;
5
6
  display:none;
@@ -125,6 +126,16 @@
125
126
  cursor:not-allowed;
126
127
  }
127
128
 
129
+ .anchor{
130
+ position:absolute;
131
+ z-index:1;
132
+ top:0;
133
+ right:0;
134
+ bottom:0;
135
+ left:0;
136
+ border-radius:var(--radius-card-container, 20px);
137
+ }
138
+
128
139
  .body{
129
140
  display:block;
130
141
  width:100%;
@@ -6,6 +6,10 @@
6
6
  box-sizing:border-box;
7
7
  }
8
8
 
9
+ .label{
10
+ color:var(--sys-primary-accent-default, #794ed3);
11
+ }
12
+
9
13
  .icon{
10
14
  display:flex;
11
15
  align-items:center;
@@ -15,8 +19,4 @@
15
19
  .icon svg{
16
20
  width:var(--size-icon-container-s, 24px) !important;
17
21
  height:var(--size-icon-container-s, 24px) !important;
18
- }
19
-
20
- .label{
21
- color:var(--sys-primary-accent-default, #794ed3);
22
22
  }
@@ -14,4 +14,5 @@ export declare const TEST_IDS: {
14
14
  title: string;
15
15
  description: string;
16
16
  metadata: string;
17
+ anchor: string;
17
18
  };
package/dist/constants.js CHANGED
@@ -14,4 +14,5 @@ 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',
17
18
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Card",
7
- "version": "0.9.12-preview-993a9cfb.0",
7
+ "version": "0.10.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -32,16 +32,16 @@
32
32
  "license": "Apache-2.0",
33
33
  "scripts": {},
34
34
  "dependencies": {
35
- "@snack-uikit/button": "0.16.1-preview-993a9cfb.0",
36
- "@snack-uikit/icon-predefined": "0.4.2-preview-993a9cfb.0",
35
+ "@snack-uikit/button": "0.16.0",
36
+ "@snack-uikit/icon-predefined": "0.4.1",
37
37
  "@snack-uikit/icons": "0.20.1",
38
- "@snack-uikit/list": "0.3.4-preview-993a9cfb.0",
38
+ "@snack-uikit/list": "0.3.3",
39
39
  "@snack-uikit/promo-tag": "0.4.1",
40
- "@snack-uikit/tag": "0.7.4-preview-993a9cfb.0",
41
- "@snack-uikit/truncate-string": "0.4.8-preview-993a9cfb.0",
40
+ "@snack-uikit/tag": "0.7.3",
41
+ "@snack-uikit/truncate-string": "0.4.7",
42
42
  "@snack-uikit/typography": "0.6.1",
43
43
  "@snack-uikit/utils": "3.2.0",
44
44
  "classnames": "2.3.2"
45
45
  },
46
- "gitHead": "a421965dc78af63a8c292e595b3f0a8ff1be86f9"
46
+ "gitHead": "c812034af313f7a0f6247e848e83e783e181032c"
47
47
  }
@@ -1,10 +1,10 @@
1
1
  import cn from 'classnames';
2
- import { KeyboardEvent, ReactElement, ReactNode, useCallback, useRef } from 'react';
2
+ import { KeyboardEvent, MouseEvent, ReactElement, ReactNode, useCallback, useRef } from 'react';
3
3
 
4
4
  import { Typography } from '@snack-uikit/typography';
5
5
  import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
6
6
 
7
- import { SIZE } from '../../constants';
7
+ import { SIZE, TEST_IDS } from '../../constants';
8
8
  import { CardContext } from '../../context';
9
9
  import { Check, FunctionBadgeWrapper, PromoBadge } from '../../helperComponents';
10
10
  import { Size } from '../../types';
@@ -22,7 +22,7 @@ export type CardProps = WithSupportProps<{
22
22
  /** Отображение галочки для режима массового выделения карточек */
23
23
  multipleSelection?: boolean;
24
24
  /** Колбек на клик по карточке */
25
- onClick?(): void;
25
+ onClick?(e: MouseEvent<HTMLDivElement | HTMLAnchorElement>): void;
26
26
  /** Размер */
27
27
  size?: Size;
28
28
  /** Текст для PromoBadge */
@@ -39,6 +39,8 @@ export type CardProps = WithSupportProps<{
39
39
  functionBadge?: ReactNode;
40
40
  /** CSS-класс для элемента с контентом */
41
41
  className?: string;
42
+ /** Ссылка карточки */
43
+ href?: string;
42
44
  }>;
43
45
 
44
46
  export function Card({
@@ -55,28 +57,32 @@ export function Card({
55
57
  promoBadge,
56
58
  image,
57
59
  className,
60
+ href,
58
61
  ...rest
59
62
  }: CardProps) {
60
- const localRef = useRef<HTMLDivElement>(null);
63
+ const localDivRef = useRef<HTMLDivElement>(null);
64
+ const localAnchorRef = useRef<HTMLAnchorElement>(null);
61
65
 
62
66
  const onKeyDown = useCallback(
63
67
  (e: KeyboardEvent<HTMLDivElement>) => {
64
- if (e.target === localRef.current) {
68
+ if (e.target === localDivRef.current) {
65
69
  if (TRIGGER_CLICK_KEY_CODES.includes(e.code)) {
66
- onClick?.();
70
+ href ? localAnchorRef.current?.click() : localDivRef.current?.click();
67
71
  }
68
72
  }
69
73
  },
70
- [onClick],
74
+ [href],
71
75
  );
72
76
 
77
+ const supportProps = extractSupportProps(rest);
78
+
73
79
  return (
74
80
  <CardContext.Provider value={{ size, disabled }}>
75
81
  {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
76
82
  <div
77
- ref={localRef}
83
+ ref={localDivRef}
78
84
  className={cn(styles.card, className)}
79
- {...extractSupportProps(rest)}
85
+ {...supportProps}
80
86
  onClick={onClick}
81
87
  data-disabled={disabled || undefined}
82
88
  data-checked={checked || undefined}
@@ -91,6 +97,17 @@ export function Card({
91
97
  {promoBadge && <PromoBadge text={promoBadge} />}
92
98
 
93
99
  <div className={styles.composition} tabIndex={-1}>
100
+ {href && (
101
+ <a
102
+ ref={localAnchorRef}
103
+ data-test-id={TEST_IDS.anchor}
104
+ tabIndex={-1}
105
+ href={href}
106
+ className={styles.anchor}
107
+ aria-label={supportProps['aria-label'] as string}
108
+ />
109
+ )}
110
+
94
111
  {!disabled && functionBadge && (
95
112
  <FunctionBadgeWrapper className={styles.functionBadgeWrapper}>{functionBadge}</FunctionBadgeWrapper>
96
113
  )}
@@ -5,8 +5,10 @@ $sizes: 's', 'm', 'l';
5
5
 
6
6
  .functionBadgeWrapper {
7
7
  position: absolute;
8
+ z-index: 1;
8
9
  top: 0;
9
10
  right: 0;
11
+
10
12
  display: none;
11
13
 
12
14
  &[data-visible] {
@@ -160,6 +162,17 @@ $sizes: 's', 'm', 'l';
160
162
  }
161
163
  }
162
164
 
165
+ .anchor {
166
+ position: absolute;
167
+ z-index: 1;
168
+ top: 0;
169
+ right: 0;
170
+ bottom: 0;
171
+ left: 0;
172
+
173
+ border-radius: $radius-card-container;
174
+ }
175
+
163
176
  .body {
164
177
  display: block;
165
178
  width: 100%;
@@ -10,6 +10,10 @@
10
10
  box-sizing: border-box;
11
11
  }
12
12
 
13
+ .label {
14
+ color: $sys-primary-accent-default;
15
+ }
16
+
13
17
  .icon {
14
18
  display: flex;
15
19
  align-items: center;
@@ -20,8 +24,4 @@
20
24
  width: $icon-s !important; /* stylelint-disable-line declaration-no-important */
21
25
  height: $icon-s !important; /* stylelint-disable-line declaration-no-important */
22
26
  }
23
- }
24
-
25
- .label {
26
- color: $sys-primary-accent-default;
27
27
  }
package/src/constants.ts CHANGED
@@ -15,4 +15,5 @@ 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',
18
19
  };