@gravity-ui/blog-constructor 5.8.0-alpha.0 → 5.8.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 (43) hide show
  1. package/build/cjs/blocks/Author/schema.d.ts +3 -0
  2. package/build/cjs/blocks/Banner/schema.d.ts +6 -0
  3. package/build/cjs/blocks/CTA/schema.d.ts +6 -0
  4. package/build/cjs/blocks/ColoredText/schema.d.ts +6 -0
  5. package/build/cjs/blocks/Feed/schema.d.ts +6 -0
  6. package/build/cjs/blocks/Header/schema.d.ts +3 -0
  7. package/build/cjs/blocks/Layout/schema.d.ts +3 -0
  8. package/build/cjs/blocks/Media/schema.d.ts +3 -0
  9. package/build/cjs/blocks/Meta/schema.d.ts +3 -0
  10. package/build/cjs/blocks/Suggest/schema.d.ts +3 -0
  11. package/build/cjs/blocks/YFM/schema.d.ts +3 -0
  12. package/build/cjs/components/PostCard/PostCard.js +21 -5
  13. package/build/cjs/components/PostInfo/SuggestPostInfo.d.ts +5 -1
  14. package/build/cjs/components/PostInfo/SuggestPostInfo.js +5 -3
  15. package/build/cjs/components/PostInfo/components/Date.d.ts +2 -1
  16. package/build/cjs/components/PostInfo/components/Date.js +2 -2
  17. package/build/cjs/components/PostInfo/components/ReadingTime.d.ts +2 -1
  18. package/build/cjs/components/PostInfo/components/ReadingTime.js +1 -1
  19. package/build/cjs/hooks/useAriaAttributes.d.ts +17 -0
  20. package/build/cjs/hooks/useAriaAttributes.js +19 -0
  21. package/build/cjs/schema/index.d.ts +45 -0
  22. package/build/esm/blocks/Author/schema.d.ts +3 -0
  23. package/build/esm/blocks/Banner/schema.d.ts +6 -0
  24. package/build/esm/blocks/CTA/schema.d.ts +6 -0
  25. package/build/esm/blocks/ColoredText/schema.d.ts +6 -0
  26. package/build/esm/blocks/Feed/schema.d.ts +6 -0
  27. package/build/esm/blocks/Header/schema.d.ts +3 -0
  28. package/build/esm/blocks/Layout/schema.d.ts +3 -0
  29. package/build/esm/blocks/Media/schema.d.ts +3 -0
  30. package/build/esm/blocks/Meta/schema.d.ts +3 -0
  31. package/build/esm/blocks/Suggest/schema.d.ts +3 -0
  32. package/build/esm/blocks/YFM/schema.d.ts +3 -0
  33. package/build/esm/components/PostCard/PostCard.js +21 -5
  34. package/build/esm/components/PostInfo/SuggestPostInfo.d.ts +5 -1
  35. package/build/esm/components/PostInfo/SuggestPostInfo.js +5 -3
  36. package/build/esm/components/PostInfo/components/Date.d.ts +2 -1
  37. package/build/esm/components/PostInfo/components/Date.js +2 -2
  38. package/build/esm/components/PostInfo/components/ReadingTime.d.ts +2 -1
  39. package/build/esm/components/PostInfo/components/ReadingTime.js +1 -1
  40. package/build/esm/hooks/useAriaAttributes.d.ts +17 -0
  41. package/build/esm/hooks/useAriaAttributes.js +15 -0
  42. package/build/esm/schema/index.d.ts +45 -0
  43. package/package.json +3 -4
@@ -37,6 +37,9 @@ export declare const Author: {
37
37
  url: {
38
38
  type: string;
39
39
  };
40
+ urlTitle: {
41
+ type: string;
42
+ };
40
43
  };
41
44
  };
42
45
  visible: {
@@ -36,6 +36,9 @@ export declare const Banner: {
36
36
  url: {
37
37
  type: string;
38
38
  };
39
+ urlTitle: {
40
+ type: string;
41
+ };
39
42
  resetMargin: {
40
43
  type: string;
41
44
  };
@@ -123,6 +126,9 @@ export declare const Banner: {
123
126
  url: {
124
127
  type: string;
125
128
  };
129
+ urlTitle: {
130
+ type: string;
131
+ };
126
132
  };
127
133
  };
128
134
  visible: {
@@ -33,6 +33,9 @@ export declare const CTA: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  resetMargin: {
37
40
  type: string;
38
41
  };
@@ -123,6 +126,9 @@ export declare const CTA: {
123
126
  url: {
124
127
  type: string;
125
128
  };
129
+ urlTitle: {
130
+ type: string;
131
+ };
126
132
  };
127
133
  };
128
134
  visible: {
@@ -53,6 +53,9 @@ export declare const ColoredText: {
53
53
  url: {
54
54
  type: string;
55
55
  };
56
+ urlTitle: {
57
+ type: string;
58
+ };
56
59
  resetMargin: {
57
60
  type: string;
58
61
  };
@@ -140,6 +143,9 @@ export declare const ColoredText: {
140
143
  url: {
141
144
  type: string;
142
145
  };
146
+ urlTitle: {
147
+ type: string;
148
+ };
143
149
  };
144
150
  };
145
151
  visible: {
@@ -19,6 +19,9 @@ export declare const Feed: {
19
19
  url: {
20
20
  type: string;
21
21
  };
22
+ urlTitle: {
23
+ type: string;
24
+ };
22
25
  resetMargin: {
23
26
  type: string;
24
27
  };
@@ -47,6 +50,9 @@ export declare const Feed: {
47
50
  url: {
48
51
  type: string;
49
52
  };
53
+ urlTitle: {
54
+ type: string;
55
+ };
50
56
  };
51
57
  };
52
58
  visible: {
@@ -511,6 +511,9 @@ export declare const Header: {
511
511
  url: {
512
512
  type: string;
513
513
  };
514
+ urlTitle: {
515
+ type: string;
516
+ };
514
517
  };
515
518
  };
516
519
  visible: {
@@ -44,6 +44,9 @@ export declare const Layout: {
44
44
  url: {
45
45
  type: string;
46
46
  };
47
+ urlTitle: {
48
+ type: string;
49
+ };
47
50
  };
48
51
  };
49
52
  visible: {
@@ -279,6 +279,9 @@ export declare const Media: {
279
279
  url: {
280
280
  type: string;
281
281
  };
282
+ urlTitle: {
283
+ type: string;
284
+ };
282
285
  };
283
286
  };
284
287
  visible: {
@@ -33,6 +33,9 @@ export declare const Meta: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  };
37
40
  };
38
41
  visible: {
@@ -33,6 +33,9 @@ export declare const Suggest: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  };
37
40
  };
38
41
  visible: {
@@ -38,6 +38,9 @@ export declare const YFM: {
38
38
  url: {
39
39
  type: string;
40
40
  };
41
+ urlTitle: {
42
+ type: string;
43
+ };
41
44
  };
42
45
  };
43
46
  visible: {
@@ -4,10 +4,12 @@ exports.PostCard = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importStar(require("react"));
6
6
  const page_constructor_1 = require("@gravity-ui/page-constructor");
7
+ const uikit_1 = require("@gravity-ui/uikit");
7
8
  const LikesContext_1 = require("../../contexts/LikesContext");
8
9
  const common_1 = require("../../models/common");
9
10
  const cn_1 = require("../../utils/cn");
10
11
  const SuggestPostInfo_1 = require("../PostInfo/SuggestPostInfo");
12
+ const useAriaAttributes_1 = require("../../hooks/useAriaAttributes");
11
13
  const b = (0, cn_1.block)('post-card');
12
14
  const PostCard = ({ post, metrikaGoals, fullWidth = false, size = common_1.PostCardSize.SMALL, showTag = false, titleHeadingLevel = common_1.PostCardTitleHeadingLevel.H3, }) => {
13
15
  var _a;
@@ -21,19 +23,33 @@ const PostCard = ({ post, metrikaGoals, fullWidth = false, size = common_1.PostC
21
23
  toggleLike,
22
24
  }
23
25
  : undefined, [hasUserLike, likes, toggleLike, hasLikes]);
24
- return (react_1.default.createElement(page_constructor_1.CardBase, { url: url, metrikaGoals: metrikaGoals, className: b('card', { fullWidth }) },
26
+ const titleId = (0, uikit_1.useUniqId)();
27
+ const descriptionId = (0, uikit_1.useUniqId)();
28
+ const dateId = (0, uikit_1.useUniqId)();
29
+ const tagId = (0, uikit_1.useUniqId)();
30
+ const readingTimeId = (0, uikit_1.useUniqId)();
31
+ const isTagVisible = showTag && ((_a = tags === null || tags === void 0 ? void 0 : tags[0]) === null || _a === void 0 ? void 0 : _a.name);
32
+ const ariaAttributes = (0, useAriaAttributes_1.useAriaAttributes)({
33
+ labelIds: [isTagVisible && tagId, title && titleId],
34
+ descriptionIds: [
35
+ description && descriptionId,
36
+ date && dateId,
37
+ readingTime && readingTimeId,
38
+ ],
39
+ });
40
+ return (react_1.default.createElement(page_constructor_1.CardBase, { url: url, metrikaGoals: metrikaGoals, className: b('card', { fullWidth }), extraProps: ariaAttributes },
25
41
  react_1.default.createElement(page_constructor_1.CardBase.Header, { image: image, className: b('header', { fullWidth }) },
26
42
  react_1.default.createElement("div", { className: b('image-container'), "data-qa": "blog-suggest-header" })),
27
43
  react_1.default.createElement(page_constructor_1.CardBase.Content, null,
28
- showTag && ((_a = tags === null || tags === void 0 ? void 0 : tags[0]) === null || _a === void 0 ? void 0 : _a.name) && (react_1.default.createElement("div", { className: b('tag', { size }) }, tags[0].name)),
44
+ isTagVisible && (react_1.default.createElement("div", { id: tagId, className: b('tag', { size }) }, tags[0].name)),
29
45
  title &&
30
46
  react_1.default.createElement(titleHeadingLevel, { className: b('title', { size }) }, react_1.default.createElement("span", null,
31
- react_1.default.createElement(page_constructor_1.HTML, null, title))),
47
+ react_1.default.createElement(page_constructor_1.HTML, { id: titleId }, title))),
32
48
  description && (react_1.default.createElement(page_constructor_1.YFMWrapper, { className: b('description'), content: description, modifiers: {
33
49
  blog: size === 'm',
34
50
  blogCard: true,
35
- } }))),
51
+ }, id: descriptionId }))),
36
52
  react_1.default.createElement(page_constructor_1.CardBase.Footer, null,
37
- react_1.default.createElement(SuggestPostInfo_1.SuggestPostInfo, { postId: blogPostId || id, date: date, readingTime: readingTime, hasUserLike: hasUserLike, likes: likesProps, size: size, qa: "blog-suggest-block" }))));
53
+ react_1.default.createElement(SuggestPostInfo_1.SuggestPostInfo, { postId: blogPostId || id, date: date, readingTime: readingTime, hasUserLike: hasUserLike, likes: likesProps, size: size, qa: "blog-suggest-block", dateId: dateId, readingTimeId: readingTimeId }))));
38
54
  };
39
55
  exports.PostCard = PostCard;
@@ -8,6 +8,8 @@ export interface SuggestPostInfoProps extends Pick<PostData, 'date' | 'readingTi
8
8
  hasUserLike?: boolean;
9
9
  toggleLike?: ToggleLikeCallbackType;
10
10
  };
11
+ dateId?: string;
12
+ readingTimeId?: string;
11
13
  }
12
14
  /**
13
15
  * Suggest blog card info component
@@ -20,7 +22,9 @@ export interface SuggestPostInfoProps extends Pick<PostData, 'date' | 'readingTi
20
22
  * @param qa - test-attr
21
23
  * @param size - text size
22
24
  * @param isModernIcon - flag what we need render 'bookmark' icon
25
+ * @param dateId - id value for element with post date. Useful when providing accessible description
26
+ * @param readingTimeId - id value for element with reading time. Useful when providing accessible description
23
27
  *
24
28
  * @returns jsx
25
29
  */
26
- export declare const SuggestPostInfo: ({ postId, date, readingTime, likes, size, qa, }: SuggestPostInfoProps) => React.JSX.Element;
30
+ export declare const SuggestPostInfo: ({ postId, date, readingTime, likes, size, qa, dateId, readingTimeId, }: SuggestPostInfoProps) => React.JSX.Element;
@@ -21,10 +21,12 @@ const b = (0, cn_1.block)('post-info');
21
21
  * @param qa - test-attr
22
22
  * @param size - text size
23
23
  * @param isModernIcon - flag what we need render 'bookmark' icon
24
+ * @param dateId - id value for element with post date. Useful when providing accessible description
25
+ * @param readingTimeId - id value for element with reading time. Useful when providing accessible description
24
26
  *
25
27
  * @returns jsx
26
28
  */
27
- const SuggestPostInfo = ({ postId, date, readingTime, likes, size = common_1.PostCardSize.SMALL, qa, }) => {
29
+ const SuggestPostInfo = ({ postId, date, readingTime, likes, size = common_1.PostCardSize.SMALL, qa, dateId, readingTimeId, }) => {
28
30
  const { hasUserLike, likesCount, handleLike } = (0, useLikes_1.useLikes)({
29
31
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
30
32
  count: likes === null || likes === void 0 ? void 0 : likes.likesCount,
@@ -33,8 +35,8 @@ const SuggestPostInfo = ({ postId, date, readingTime, likes, size = common_1.Pos
33
35
  });
34
36
  return (react_1.default.createElement("div", { className: b('container') },
35
37
  react_1.default.createElement("div", { className: b('suggest-container') },
36
- date && react_1.default.createElement(Date_1.Date, { date: date, size: size }),
37
- readingTime && react_1.default.createElement(ReadingTime_1.ReadingTime, { readingTime: readingTime, size: size })),
38
+ date && react_1.default.createElement(Date_1.Date, { date: date, size: size, id: dateId }),
39
+ readingTime && (react_1.default.createElement(ReadingTime_1.ReadingTime, { readingTime: readingTime, size: size, id: readingTimeId }))),
38
40
  likes && postId && (react_1.default.createElement(Save_1.Save, { postId: postId, title: likesCount, hasUserLike: hasUserLike, handleUserLike: handleLike, size: size, qa: qa }))));
39
41
  };
40
42
  exports.SuggestPostInfo = SuggestPostInfo;
@@ -3,6 +3,7 @@ import { PostCardSize } from '../../../models/common';
3
3
  type DateProps = {
4
4
  date: string | number;
5
5
  size?: PostCardSize;
6
+ id?: string;
6
7
  };
7
- export declare const Date: ({ date, size }: DateProps) => React.JSX.Element;
8
+ export declare const Date: ({ date, size, id }: DateProps) => React.JSX.Element;
8
9
  export {};
@@ -8,8 +8,8 @@ const common_1 = require("../../../models/common");
8
8
  const cn_1 = require("../../../utils/cn");
9
9
  const date_1 = require("../../../utils/date");
10
10
  const b = (0, cn_1.block)('post-info');
11
- const Date = ({ date, size = common_1.PostCardSize.SMALL }) => {
11
+ const Date = ({ date, size = common_1.PostCardSize.SMALL, id }) => {
12
12
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
13
- return react_1.default.createElement("div", { className: b('item', { size }) }, (0, date_1.format)(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code));
13
+ return (react_1.default.createElement("div", { className: b('item', { size }), id: id }, (0, date_1.format)(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
14
14
  };
15
15
  exports.Date = Date;
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  type ReadingTimeProps = {
3
3
  readingTime: number;
4
4
  size?: 's' | 'm';
5
+ id?: string;
5
6
  };
6
- export declare const ReadingTime: ({ readingTime, size }: ReadingTimeProps) => React.JSX.Element;
7
+ export declare const ReadingTime: ({ readingTime, size, id }: ReadingTimeProps) => React.JSX.Element;
7
8
  export {};
@@ -9,7 +9,7 @@ const Time_1 = require("../../../icons/Time");
9
9
  const cn_1 = require("../../../utils/cn");
10
10
  const b = (0, cn_1.block)('post-info');
11
11
  const ICON_SIZE = 16;
12
- const ReadingTime = ({ readingTime, size = 's' }) => (react_1.default.createElement("div", { className: b('item', { size }) },
12
+ const ReadingTime = ({ readingTime, size = 's', id }) => (react_1.default.createElement("div", { className: b('item', { size }), id: id },
13
13
  react_1.default.createElement("span", { className: b('icon') },
14
14
  react_1.default.createElement(uikit_1.Icon, { data: Time_1.Time, size: ICON_SIZE, className: b('icon-color') })),
15
15
  (0, i18n_1.i18)(i18n_1.Keyset.ContextReadingTime, { count: readingTime })));
@@ -0,0 +1,17 @@
1
+ type Labels = string | number | boolean | undefined;
2
+ type Description = string | number | boolean | undefined;
3
+ interface UseAriaAttributesProps {
4
+ labelIds?: Labels[];
5
+ descriptionIds: Description[];
6
+ }
7
+ /**
8
+ * Returns aria-attributes
9
+ * @param labelIds - labels ids. Falsy values will be ignored
10
+ * @param descriptionIds - descriptions ids. Falsy values will be ignored
11
+ * @returns aria attributes for the element to be labelled
12
+ */
13
+ export declare const useAriaAttributes: ({ labelIds, descriptionIds }: UseAriaAttributesProps) => {
14
+ 'aria-labelledby': string;
15
+ 'aria-describedby': string;
16
+ };
17
+ export {};
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAriaAttributes = void 0;
4
+ const react_1 = require("react");
5
+ /**
6
+ * Returns aria-attributes
7
+ * @param labelIds - labels ids. Falsy values will be ignored
8
+ * @param descriptionIds - descriptions ids. Falsy values will be ignored
9
+ * @returns aria attributes for the element to be labelled
10
+ */
11
+ const useAriaAttributes = ({ labelIds = [], descriptionIds = [] }) => {
12
+ const labelledBy = (0, react_1.useMemo)(() => labelIds.filter(Boolean).join(' '), [labelIds]);
13
+ const describedBy = (0, react_1.useMemo)(() => descriptionIds.filter(Boolean).join(' '), [descriptionIds]);
14
+ return {
15
+ 'aria-labelledby': labelledBy,
16
+ 'aria-describedby': describedBy,
17
+ };
18
+ };
19
+ exports.useAriaAttributes = useAriaAttributes;
@@ -519,6 +519,9 @@ export declare const schemasForCustom: {
519
519
  url: {
520
520
  type: string;
521
521
  };
522
+ urlTitle: {
523
+ type: string;
524
+ };
522
525
  };
523
526
  };
524
527
  visible: {
@@ -579,6 +582,9 @@ export declare const schemasForCustom: {
579
582
  url: {
580
583
  type: string;
581
584
  };
585
+ urlTitle: {
586
+ type: string;
587
+ };
582
588
  };
583
589
  };
584
590
  visible: {
@@ -636,6 +642,9 @@ export declare const schemasForCustom: {
636
642
  url: {
637
643
  type: string;
638
644
  };
645
+ urlTitle: {
646
+ type: string;
647
+ };
639
648
  resetMargin: {
640
649
  type: string;
641
650
  };
@@ -723,6 +732,9 @@ export declare const schemasForCustom: {
723
732
  url: {
724
733
  type: string;
725
734
  };
735
+ urlTitle: {
736
+ type: string;
737
+ };
726
738
  };
727
739
  };
728
740
  visible: {
@@ -797,6 +809,9 @@ export declare const schemasForCustom: {
797
809
  url: {
798
810
  type: string;
799
811
  };
812
+ urlTitle: {
813
+ type: string;
814
+ };
800
815
  resetMargin: {
801
816
  type: string;
802
817
  };
@@ -884,6 +899,9 @@ export declare const schemasForCustom: {
884
899
  url: {
885
900
  type: string;
886
901
  };
902
+ urlTitle: {
903
+ type: string;
904
+ };
887
905
  };
888
906
  };
889
907
  visible: {
@@ -938,6 +956,9 @@ export declare const schemasForCustom: {
938
956
  url: {
939
957
  type: string;
940
958
  };
959
+ urlTitle: {
960
+ type: string;
961
+ };
941
962
  resetMargin: {
942
963
  type: string;
943
964
  };
@@ -1028,6 +1049,9 @@ export declare const schemasForCustom: {
1028
1049
  url: {
1029
1050
  type: string;
1030
1051
  };
1052
+ urlTitle: {
1053
+ type: string;
1054
+ };
1031
1055
  };
1032
1056
  };
1033
1057
  visible: {
@@ -1068,6 +1092,9 @@ export declare const schemasForCustom: {
1068
1092
  url: {
1069
1093
  type: string;
1070
1094
  };
1095
+ urlTitle: {
1096
+ type: string;
1097
+ };
1071
1098
  resetMargin: {
1072
1099
  type: string;
1073
1100
  };
@@ -1096,6 +1123,9 @@ export declare const schemasForCustom: {
1096
1123
  url: {
1097
1124
  type: string;
1098
1125
  };
1126
+ urlTitle: {
1127
+ type: string;
1128
+ };
1099
1129
  };
1100
1130
  };
1101
1131
  visible: {
@@ -1161,6 +1191,9 @@ export declare const schemasForCustom: {
1161
1191
  url: {
1162
1192
  type: string;
1163
1193
  };
1194
+ urlTitle: {
1195
+ type: string;
1196
+ };
1164
1197
  };
1165
1198
  };
1166
1199
  visible: {
@@ -1461,6 +1494,9 @@ export declare const schemasForCustom: {
1461
1494
  url: {
1462
1495
  type: string;
1463
1496
  };
1497
+ urlTitle: {
1498
+ type: string;
1499
+ };
1464
1500
  };
1465
1501
  };
1466
1502
  visible: {
@@ -1515,6 +1551,9 @@ export declare const schemasForCustom: {
1515
1551
  url: {
1516
1552
  type: string;
1517
1553
  };
1554
+ urlTitle: {
1555
+ type: string;
1556
+ };
1518
1557
  };
1519
1558
  };
1520
1559
  visible: {
@@ -1569,6 +1608,9 @@ export declare const schemasForCustom: {
1569
1608
  url: {
1570
1609
  type: string;
1571
1610
  };
1611
+ urlTitle: {
1612
+ type: string;
1613
+ };
1572
1614
  };
1573
1615
  };
1574
1616
  visible: {
@@ -1628,6 +1670,9 @@ export declare const schemasForCustom: {
1628
1670
  url: {
1629
1671
  type: string;
1630
1672
  };
1673
+ urlTitle: {
1674
+ type: string;
1675
+ };
1631
1676
  };
1632
1677
  };
1633
1678
  visible: {
@@ -37,6 +37,9 @@ export declare const Author: {
37
37
  url: {
38
38
  type: string;
39
39
  };
40
+ urlTitle: {
41
+ type: string;
42
+ };
40
43
  };
41
44
  };
42
45
  visible: {
@@ -36,6 +36,9 @@ export declare const Banner: {
36
36
  url: {
37
37
  type: string;
38
38
  };
39
+ urlTitle: {
40
+ type: string;
41
+ };
39
42
  resetMargin: {
40
43
  type: string;
41
44
  };
@@ -123,6 +126,9 @@ export declare const Banner: {
123
126
  url: {
124
127
  type: string;
125
128
  };
129
+ urlTitle: {
130
+ type: string;
131
+ };
126
132
  };
127
133
  };
128
134
  visible: {
@@ -33,6 +33,9 @@ export declare const CTA: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  resetMargin: {
37
40
  type: string;
38
41
  };
@@ -123,6 +126,9 @@ export declare const CTA: {
123
126
  url: {
124
127
  type: string;
125
128
  };
129
+ urlTitle: {
130
+ type: string;
131
+ };
126
132
  };
127
133
  };
128
134
  visible: {
@@ -53,6 +53,9 @@ export declare const ColoredText: {
53
53
  url: {
54
54
  type: string;
55
55
  };
56
+ urlTitle: {
57
+ type: string;
58
+ };
56
59
  resetMargin: {
57
60
  type: string;
58
61
  };
@@ -140,6 +143,9 @@ export declare const ColoredText: {
140
143
  url: {
141
144
  type: string;
142
145
  };
146
+ urlTitle: {
147
+ type: string;
148
+ };
143
149
  };
144
150
  };
145
151
  visible: {
@@ -19,6 +19,9 @@ export declare const Feed: {
19
19
  url: {
20
20
  type: string;
21
21
  };
22
+ urlTitle: {
23
+ type: string;
24
+ };
22
25
  resetMargin: {
23
26
  type: string;
24
27
  };
@@ -47,6 +50,9 @@ export declare const Feed: {
47
50
  url: {
48
51
  type: string;
49
52
  };
53
+ urlTitle: {
54
+ type: string;
55
+ };
50
56
  };
51
57
  };
52
58
  visible: {
@@ -511,6 +511,9 @@ export declare const Header: {
511
511
  url: {
512
512
  type: string;
513
513
  };
514
+ urlTitle: {
515
+ type: string;
516
+ };
514
517
  };
515
518
  };
516
519
  visible: {
@@ -44,6 +44,9 @@ export declare const Layout: {
44
44
  url: {
45
45
  type: string;
46
46
  };
47
+ urlTitle: {
48
+ type: string;
49
+ };
47
50
  };
48
51
  };
49
52
  visible: {
@@ -279,6 +279,9 @@ export declare const Media: {
279
279
  url: {
280
280
  type: string;
281
281
  };
282
+ urlTitle: {
283
+ type: string;
284
+ };
282
285
  };
283
286
  };
284
287
  visible: {
@@ -33,6 +33,9 @@ export declare const Meta: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  };
37
40
  };
38
41
  visible: {
@@ -33,6 +33,9 @@ export declare const Suggest: {
33
33
  url: {
34
34
  type: string;
35
35
  };
36
+ urlTitle: {
37
+ type: string;
38
+ };
36
39
  };
37
40
  };
38
41
  visible: {
@@ -38,6 +38,9 @@ export declare const YFM: {
38
38
  url: {
39
39
  type: string;
40
40
  };
41
+ urlTitle: {
42
+ type: string;
43
+ };
41
44
  };
42
45
  };
43
46
  visible: {
@@ -1,9 +1,11 @@
1
1
  import React, { useContext, useMemo } from 'react';
2
2
  import { CardBase, HTML, YFMWrapper } from '@gravity-ui/page-constructor';
3
+ import { useUniqId } from '@gravity-ui/uikit';
3
4
  import { LikesContext } from '../../contexts/LikesContext';
4
5
  import { PostCardSize, PostCardTitleHeadingLevel } from '../../models/common';
5
6
  import { block } from '../../utils/cn';
6
7
  import { SuggestPostInfo } from '../PostInfo/SuggestPostInfo';
8
+ import { useAriaAttributes } from '../../hooks/useAriaAttributes';
7
9
  import './PostCard.css';
8
10
  const b = block('post-card');
9
11
  export const PostCard = ({ post, metrikaGoals, fullWidth = false, size = PostCardSize.SMALL, showTag = false, titleHeadingLevel = PostCardTitleHeadingLevel.H3, }) => {
@@ -18,18 +20,32 @@ export const PostCard = ({ post, metrikaGoals, fullWidth = false, size = PostCar
18
20
  toggleLike,
19
21
  }
20
22
  : undefined, [hasUserLike, likes, toggleLike, hasLikes]);
21
- return (React.createElement(CardBase, { url: url, metrikaGoals: metrikaGoals, className: b('card', { fullWidth }) },
23
+ const titleId = useUniqId();
24
+ const descriptionId = useUniqId();
25
+ const dateId = useUniqId();
26
+ const tagId = useUniqId();
27
+ const readingTimeId = useUniqId();
28
+ const isTagVisible = showTag && ((_a = tags === null || tags === void 0 ? void 0 : tags[0]) === null || _a === void 0 ? void 0 : _a.name);
29
+ const ariaAttributes = useAriaAttributes({
30
+ labelIds: [isTagVisible && tagId, title && titleId],
31
+ descriptionIds: [
32
+ description && descriptionId,
33
+ date && dateId,
34
+ readingTime && readingTimeId,
35
+ ],
36
+ });
37
+ return (React.createElement(CardBase, { url: url, metrikaGoals: metrikaGoals, className: b('card', { fullWidth }), extraProps: ariaAttributes },
22
38
  React.createElement(CardBase.Header, { image: image, className: b('header', { fullWidth }) },
23
39
  React.createElement("div", { className: b('image-container'), "data-qa": "blog-suggest-header" })),
24
40
  React.createElement(CardBase.Content, null,
25
- showTag && ((_a = tags === null || tags === void 0 ? void 0 : tags[0]) === null || _a === void 0 ? void 0 : _a.name) && (React.createElement("div", { className: b('tag', { size }) }, tags[0].name)),
41
+ isTagVisible && (React.createElement("div", { id: tagId, className: b('tag', { size }) }, tags[0].name)),
26
42
  title &&
27
43
  React.createElement(titleHeadingLevel, { className: b('title', { size }) }, React.createElement("span", null,
28
- React.createElement(HTML, null, title))),
44
+ React.createElement(HTML, { id: titleId }, title))),
29
45
  description && (React.createElement(YFMWrapper, { className: b('description'), content: description, modifiers: {
30
46
  blog: size === 'm',
31
47
  blogCard: true,
32
- } }))),
48
+ }, id: descriptionId }))),
33
49
  React.createElement(CardBase.Footer, null,
34
- React.createElement(SuggestPostInfo, { postId: blogPostId || id, date: date, readingTime: readingTime, hasUserLike: hasUserLike, likes: likesProps, size: size, qa: "blog-suggest-block" }))));
50
+ React.createElement(SuggestPostInfo, { postId: blogPostId || id, date: date, readingTime: readingTime, hasUserLike: hasUserLike, likes: likesProps, size: size, qa: "blog-suggest-block", dateId: dateId, readingTimeId: readingTimeId }))));
35
51
  };
@@ -9,6 +9,8 @@ export interface SuggestPostInfoProps extends Pick<PostData, 'date' | 'readingTi
9
9
  hasUserLike?: boolean;
10
10
  toggleLike?: ToggleLikeCallbackType;
11
11
  };
12
+ dateId?: string;
13
+ readingTimeId?: string;
12
14
  }
13
15
  /**
14
16
  * Suggest blog card info component
@@ -21,7 +23,9 @@ export interface SuggestPostInfoProps extends Pick<PostData, 'date' | 'readingTi
21
23
  * @param qa - test-attr
22
24
  * @param size - text size
23
25
  * @param isModernIcon - flag what we need render 'bookmark' icon
26
+ * @param dateId - id value for element with post date. Useful when providing accessible description
27
+ * @param readingTimeId - id value for element with reading time. Useful when providing accessible description
24
28
  *
25
29
  * @returns jsx
26
30
  */
27
- export declare const SuggestPostInfo: ({ postId, date, readingTime, likes, size, qa, }: SuggestPostInfoProps) => React.JSX.Element;
31
+ export declare const SuggestPostInfo: ({ postId, date, readingTime, likes, size, qa, dateId, readingTimeId, }: SuggestPostInfoProps) => React.JSX.Element;
@@ -18,10 +18,12 @@ const b = block('post-info');
18
18
  * @param qa - test-attr
19
19
  * @param size - text size
20
20
  * @param isModernIcon - flag what we need render 'bookmark' icon
21
+ * @param dateId - id value for element with post date. Useful when providing accessible description
22
+ * @param readingTimeId - id value for element with reading time. Useful when providing accessible description
21
23
  *
22
24
  * @returns jsx
23
25
  */
24
- export const SuggestPostInfo = ({ postId, date, readingTime, likes, size = PostCardSize.SMALL, qa, }) => {
26
+ export const SuggestPostInfo = ({ postId, date, readingTime, likes, size = PostCardSize.SMALL, qa, dateId, readingTimeId, }) => {
25
27
  const { hasUserLike, likesCount, handleLike } = useLikes({
26
28
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
27
29
  count: likes === null || likes === void 0 ? void 0 : likes.likesCount,
@@ -30,7 +32,7 @@ export const SuggestPostInfo = ({ postId, date, readingTime, likes, size = PostC
30
32
  });
31
33
  return (React.createElement("div", { className: b('container') },
32
34
  React.createElement("div", { className: b('suggest-container') },
33
- date && React.createElement(Date, { date: date, size: size }),
34
- readingTime && React.createElement(ReadingTime, { readingTime: readingTime, size: size })),
35
+ date && React.createElement(Date, { date: date, size: size, id: dateId }),
36
+ readingTime && (React.createElement(ReadingTime, { readingTime: readingTime, size: size, id: readingTimeId }))),
35
37
  likes && postId && (React.createElement(Save, { postId: postId, title: likesCount, hasUserLike: hasUserLike, handleUserLike: handleLike, size: size, qa: qa }))));
36
38
  };
@@ -4,6 +4,7 @@ import '../PostInfo.css';
4
4
  type DateProps = {
5
5
  date: string | number;
6
6
  size?: PostCardSize;
7
+ id?: string;
7
8
  };
8
- export declare const Date: ({ date, size }: DateProps) => React.JSX.Element;
9
+ export declare const Date: ({ date, size, id }: DateProps) => React.JSX.Element;
9
10
  export {};
@@ -5,7 +5,7 @@ import { block } from '../../../utils/cn';
5
5
  import { format } from '../../../utils/date';
6
6
  import '../PostInfo.css';
7
7
  const b = block('post-info');
8
- export const Date = ({ date, size = PostCardSize.SMALL }) => {
8
+ export const Date = ({ date, size = PostCardSize.SMALL, id }) => {
9
9
  const { locale } = useContext(LocaleContext);
10
- return React.createElement("div", { className: b('item', { size }) }, format(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code));
10
+ return (React.createElement("div", { className: b('item', { size }), id: id }, format(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
11
11
  };
@@ -3,6 +3,7 @@ import '../PostInfo.css';
3
3
  type ReadingTimeProps = {
4
4
  readingTime: number;
5
5
  size?: 's' | 'm';
6
+ id?: string;
6
7
  };
7
- export declare const ReadingTime: ({ readingTime, size }: ReadingTimeProps) => React.JSX.Element;
8
+ export declare const ReadingTime: ({ readingTime, size, id }: ReadingTimeProps) => React.JSX.Element;
8
9
  export {};
@@ -6,7 +6,7 @@ import { block } from '../../../utils/cn';
6
6
  import '../PostInfo.css';
7
7
  const b = block('post-info');
8
8
  const ICON_SIZE = 16;
9
- export const ReadingTime = ({ readingTime, size = 's' }) => (React.createElement("div", { className: b('item', { size }) },
9
+ export const ReadingTime = ({ readingTime, size = 's', id }) => (React.createElement("div", { className: b('item', { size }), id: id },
10
10
  React.createElement("span", { className: b('icon') },
11
11
  React.createElement(Icon, { data: Time, size: ICON_SIZE, className: b('icon-color') })),
12
12
  i18(Keyset.ContextReadingTime, { count: readingTime })));
@@ -0,0 +1,17 @@
1
+ type Labels = string | number | boolean | undefined;
2
+ type Description = string | number | boolean | undefined;
3
+ interface UseAriaAttributesProps {
4
+ labelIds?: Labels[];
5
+ descriptionIds: Description[];
6
+ }
7
+ /**
8
+ * Returns aria-attributes
9
+ * @param labelIds - labels ids. Falsy values will be ignored
10
+ * @param descriptionIds - descriptions ids. Falsy values will be ignored
11
+ * @returns aria attributes for the element to be labelled
12
+ */
13
+ export declare const useAriaAttributes: ({ labelIds, descriptionIds }: UseAriaAttributesProps) => {
14
+ 'aria-labelledby': string;
15
+ 'aria-describedby': string;
16
+ };
17
+ export {};
@@ -0,0 +1,15 @@
1
+ import { useMemo } from 'react';
2
+ /**
3
+ * Returns aria-attributes
4
+ * @param labelIds - labels ids. Falsy values will be ignored
5
+ * @param descriptionIds - descriptions ids. Falsy values will be ignored
6
+ * @returns aria attributes for the element to be labelled
7
+ */
8
+ export const useAriaAttributes = ({ labelIds = [], descriptionIds = [] }) => {
9
+ const labelledBy = useMemo(() => labelIds.filter(Boolean).join(' '), [labelIds]);
10
+ const describedBy = useMemo(() => descriptionIds.filter(Boolean).join(' '), [descriptionIds]);
11
+ return {
12
+ 'aria-labelledby': labelledBy,
13
+ 'aria-describedby': describedBy,
14
+ };
15
+ };
@@ -519,6 +519,9 @@ export declare const schemasForCustom: {
519
519
  url: {
520
520
  type: string;
521
521
  };
522
+ urlTitle: {
523
+ type: string;
524
+ };
522
525
  };
523
526
  };
524
527
  visible: {
@@ -579,6 +582,9 @@ export declare const schemasForCustom: {
579
582
  url: {
580
583
  type: string;
581
584
  };
585
+ urlTitle: {
586
+ type: string;
587
+ };
582
588
  };
583
589
  };
584
590
  visible: {
@@ -636,6 +642,9 @@ export declare const schemasForCustom: {
636
642
  url: {
637
643
  type: string;
638
644
  };
645
+ urlTitle: {
646
+ type: string;
647
+ };
639
648
  resetMargin: {
640
649
  type: string;
641
650
  };
@@ -723,6 +732,9 @@ export declare const schemasForCustom: {
723
732
  url: {
724
733
  type: string;
725
734
  };
735
+ urlTitle: {
736
+ type: string;
737
+ };
726
738
  };
727
739
  };
728
740
  visible: {
@@ -797,6 +809,9 @@ export declare const schemasForCustom: {
797
809
  url: {
798
810
  type: string;
799
811
  };
812
+ urlTitle: {
813
+ type: string;
814
+ };
800
815
  resetMargin: {
801
816
  type: string;
802
817
  };
@@ -884,6 +899,9 @@ export declare const schemasForCustom: {
884
899
  url: {
885
900
  type: string;
886
901
  };
902
+ urlTitle: {
903
+ type: string;
904
+ };
887
905
  };
888
906
  };
889
907
  visible: {
@@ -938,6 +956,9 @@ export declare const schemasForCustom: {
938
956
  url: {
939
957
  type: string;
940
958
  };
959
+ urlTitle: {
960
+ type: string;
961
+ };
941
962
  resetMargin: {
942
963
  type: string;
943
964
  };
@@ -1028,6 +1049,9 @@ export declare const schemasForCustom: {
1028
1049
  url: {
1029
1050
  type: string;
1030
1051
  };
1052
+ urlTitle: {
1053
+ type: string;
1054
+ };
1031
1055
  };
1032
1056
  };
1033
1057
  visible: {
@@ -1068,6 +1092,9 @@ export declare const schemasForCustom: {
1068
1092
  url: {
1069
1093
  type: string;
1070
1094
  };
1095
+ urlTitle: {
1096
+ type: string;
1097
+ };
1071
1098
  resetMargin: {
1072
1099
  type: string;
1073
1100
  };
@@ -1096,6 +1123,9 @@ export declare const schemasForCustom: {
1096
1123
  url: {
1097
1124
  type: string;
1098
1125
  };
1126
+ urlTitle: {
1127
+ type: string;
1128
+ };
1099
1129
  };
1100
1130
  };
1101
1131
  visible: {
@@ -1161,6 +1191,9 @@ export declare const schemasForCustom: {
1161
1191
  url: {
1162
1192
  type: string;
1163
1193
  };
1194
+ urlTitle: {
1195
+ type: string;
1196
+ };
1164
1197
  };
1165
1198
  };
1166
1199
  visible: {
@@ -1461,6 +1494,9 @@ export declare const schemasForCustom: {
1461
1494
  url: {
1462
1495
  type: string;
1463
1496
  };
1497
+ urlTitle: {
1498
+ type: string;
1499
+ };
1464
1500
  };
1465
1501
  };
1466
1502
  visible: {
@@ -1515,6 +1551,9 @@ export declare const schemasForCustom: {
1515
1551
  url: {
1516
1552
  type: string;
1517
1553
  };
1554
+ urlTitle: {
1555
+ type: string;
1556
+ };
1518
1557
  };
1519
1558
  };
1520
1559
  visible: {
@@ -1569,6 +1608,9 @@ export declare const schemasForCustom: {
1569
1608
  url: {
1570
1609
  type: string;
1571
1610
  };
1611
+ urlTitle: {
1612
+ type: string;
1613
+ };
1572
1614
  };
1573
1615
  };
1574
1616
  visible: {
@@ -1628,6 +1670,9 @@ export declare const schemasForCustom: {
1628
1670
  url: {
1629
1671
  type: string;
1630
1672
  };
1673
+ urlTitle: {
1674
+ type: string;
1675
+ };
1631
1676
  };
1632
1677
  };
1633
1678
  visible: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/blog-constructor",
3
- "version": "5.8.0-alpha.0",
3
+ "version": "5.8.0",
4
4
  "description": "Gravity UI Blog Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -66,7 +66,6 @@
66
66
  "react-helmet": "^6.1.0",
67
67
  "react-player": "^2.9.0",
68
68
  "react-slick": "^0.29.0",
69
- "react-spring": "^9.7.2",
70
69
  "react-transition-group": "^4.4.2",
71
70
  "react-waypoint": "^10.1.0",
72
71
  "sanitize-html": "^2.6.1",
@@ -79,7 +78,7 @@
79
78
  },
80
79
  "peerDependencies": {
81
80
  "@doc-tools/transform": "^3.3.2",
82
- "@gravity-ui/page-constructor": "^4.26.0",
81
+ "@gravity-ui/page-constructor": "^4.31.0",
83
82
  "@gravity-ui/uikit": "^5.12.0",
84
83
  "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
85
84
  },
@@ -90,7 +89,7 @@
90
89
  "@commitlint/config-conventional": "^17.4.3",
91
90
  "@doc-tools/transform": "^3.11.0",
92
91
  "@gravity-ui/eslint-config": "^3.1.1",
93
- "@gravity-ui/page-constructor": "^4.28.0",
92
+ "@gravity-ui/page-constructor": "^4.31.0",
94
93
  "@gravity-ui/prettier-config": "^1.1.0",
95
94
  "@gravity-ui/stylelint-config": "^4.0.1",
96
95
  "@gravity-ui/tsconfig": "^1.0.0",