@redneckz/wildless-cms-uni-blocks 0.3.9 → 0.3.10

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 (101) hide show
  1. package/bundle/blocks.schema.json +1 -1
  2. package/dist/components/ComparisonTable/ComparisonTable.mobile.d.ts +5 -0
  3. package/dist/components/ComparisonTable/ComparisonTable.mobile.js +46 -0
  4. package/dist/components/ComparisonTable/ComparisonTable.mobile.js.map +1 -0
  5. package/dist/components/ComparisonTable/ComparisonTableContent.d.ts +4 -0
  6. package/dist/components/ComparisonTable/HeaderCell.mobile.d.ts +12 -0
  7. package/dist/components/ComparisonTable/HeaderCell.mobile.js +9 -0
  8. package/dist/components/ComparisonTable/HeaderCell.mobile.js.map +1 -0
  9. package/dist/components/ComparisonTable/TableCell.d.ts +3 -2
  10. package/dist/components/ComparisonTable/TableCell.js.map +1 -1
  11. package/dist/components/ComparisonTable/TableCell.mobile.d.ts +9 -0
  12. package/dist/components/ComparisonTable/TableCell.mobile.js +12 -0
  13. package/dist/components/ComparisonTable/TableCell.mobile.js.map +1 -0
  14. package/dist/components/ComparisonTable/TableColumn.d.ts +10 -0
  15. package/dist/components/ComparisonTable/TableColumn.js +19 -0
  16. package/dist/components/ComparisonTable/TableColumn.js.map +1 -0
  17. package/dist/components/Gallery/Gallery.mobile.js +2 -2
  18. package/dist/components/Gallery/Gallery.mobile.js.map +1 -1
  19. package/dist/ui-kit/SwipeListControl/SwipeListControl.js +11 -6
  20. package/dist/ui-kit/SwipeListControl/SwipeListControl.js.map +1 -1
  21. package/dist/ui-kit/SwipeListControl/SwipeListControlProps.d.ts +1 -0
  22. package/lib/common.css +1 -1
  23. package/lib/components/ComparisonTable/ComparisonTable.fixture.mobile.d.ts +5 -0
  24. package/lib/components/ComparisonTable/ComparisonTable.mobile.d.ts +5 -0
  25. package/lib/components/ComparisonTable/ComparisonTable.mobile.js +44 -0
  26. package/lib/components/ComparisonTable/ComparisonTable.mobile.js.map +1 -0
  27. package/lib/components/ComparisonTable/ComparisonTableContent.d.ts +4 -0
  28. package/lib/components/ComparisonTable/HeaderCell.mobile.d.ts +12 -0
  29. package/lib/components/ComparisonTable/HeaderCell.mobile.js +7 -0
  30. package/lib/components/ComparisonTable/HeaderCell.mobile.js.map +1 -0
  31. package/lib/components/ComparisonTable/TableCell.d.ts +3 -2
  32. package/lib/components/ComparisonTable/TableCell.js.map +1 -1
  33. package/lib/components/ComparisonTable/TableCell.mobile.d.ts +9 -0
  34. package/lib/components/ComparisonTable/TableCell.mobile.js +10 -0
  35. package/lib/components/ComparisonTable/TableCell.mobile.js.map +1 -0
  36. package/lib/components/ComparisonTable/TableColumn.d.ts +10 -0
  37. package/lib/components/ComparisonTable/TableColumn.js +17 -0
  38. package/lib/components/ComparisonTable/TableColumn.js.map +1 -0
  39. package/lib/components/Gallery/Gallery.mobile.js +2 -2
  40. package/lib/components/Gallery/Gallery.mobile.js.map +1 -1
  41. package/lib/ui-kit/SwipeListControl/SwipeListControl.js +12 -7
  42. package/lib/ui-kit/SwipeListControl/SwipeListControl.js.map +1 -1
  43. package/lib/ui-kit/SwipeListControl/SwipeListControlProps.d.ts +1 -0
  44. package/mobile/bundle/bundle.umd.js +65 -60
  45. package/mobile/bundle/bundle.umd.min.js +1 -1
  46. package/mobile/dist/components/ComparisonTable/ComparisonTable.js +38 -28
  47. package/mobile/dist/components/ComparisonTable/ComparisonTable.js.map +1 -1
  48. package/mobile/dist/components/ComparisonTable/ComparisonTableContent.d.ts +4 -0
  49. package/mobile/dist/components/ComparisonTable/HeaderCell.d.ts +2 -0
  50. package/mobile/dist/components/ComparisonTable/HeaderCell.js +1 -3
  51. package/mobile/dist/components/ComparisonTable/HeaderCell.js.map +1 -1
  52. package/mobile/dist/components/ComparisonTable/TableCell.d.ts +4 -3
  53. package/mobile/dist/components/ComparisonTable/TableCell.js +5 -5
  54. package/mobile/dist/components/ComparisonTable/TableCell.js.map +1 -1
  55. package/mobile/dist/components/ComparisonTable/TableColumn.d.ts +10 -0
  56. package/mobile/dist/components/ComparisonTable/TableColumn.js +19 -0
  57. package/mobile/dist/components/ComparisonTable/TableColumn.js.map +1 -0
  58. package/mobile/dist/components/Gallery/Gallery.js +2 -2
  59. package/mobile/dist/components/Gallery/Gallery.js.map +1 -1
  60. package/mobile/dist/ui-kit/SwipeListControl/SwipeListControl.js +11 -6
  61. package/mobile/dist/ui-kit/SwipeListControl/SwipeListControl.js.map +1 -1
  62. package/mobile/dist/ui-kit/SwipeListControl/SwipeListControlProps.d.ts +1 -0
  63. package/mobile/lib/components/ComparisonTable/ComparisonTable.js +38 -28
  64. package/mobile/lib/components/ComparisonTable/ComparisonTable.js.map +1 -1
  65. package/mobile/lib/components/ComparisonTable/ComparisonTableContent.d.ts +4 -0
  66. package/mobile/lib/components/ComparisonTable/HeaderCell.d.ts +2 -0
  67. package/mobile/lib/components/ComparisonTable/HeaderCell.js +1 -3
  68. package/mobile/lib/components/ComparisonTable/HeaderCell.js.map +1 -1
  69. package/mobile/lib/components/ComparisonTable/TableCell.d.ts +4 -3
  70. package/mobile/lib/components/ComparisonTable/TableCell.js +6 -6
  71. package/mobile/lib/components/ComparisonTable/TableCell.js.map +1 -1
  72. package/mobile/lib/components/ComparisonTable/TableColumn.d.ts +10 -0
  73. package/mobile/lib/components/ComparisonTable/TableColumn.js +17 -0
  74. package/mobile/lib/components/ComparisonTable/TableColumn.js.map +1 -0
  75. package/mobile/lib/components/Gallery/Gallery.js +2 -2
  76. package/mobile/lib/components/Gallery/Gallery.js.map +1 -1
  77. package/mobile/lib/ui-kit/SwipeListControl/SwipeListControl.js +12 -7
  78. package/mobile/lib/ui-kit/SwipeListControl/SwipeListControl.js.map +1 -1
  79. package/mobile/lib/ui-kit/SwipeListControl/SwipeListControlProps.d.ts +1 -0
  80. package/mobile/src/common.css +0 -2
  81. package/mobile/src/components/ComparisonTable/ComparisonTable.tsx +90 -102
  82. package/mobile/src/components/ComparisonTable/ComparisonTableContent.ts +4 -0
  83. package/mobile/src/components/ComparisonTable/HeaderCell.tsx +34 -30
  84. package/mobile/src/components/ComparisonTable/TableCell.tsx +30 -27
  85. package/mobile/src/components/ComparisonTable/TableColumn.tsx +66 -0
  86. package/mobile/src/components/Gallery/Gallery.tsx +2 -2
  87. package/mobile/src/ui-kit/SwipeListControl/SwipeListControl.tsx +27 -19
  88. package/mobile/src/ui-kit/SwipeListControl/SwipeListControlProps.ts +1 -0
  89. package/package.json +1 -1
  90. package/src/common.css +0 -2
  91. package/src/components/ComparisonTable/ComparisonTable.fixture.mobile.tsx +152 -0
  92. package/src/components/ComparisonTable/ComparisonTable.mobile.tsx +121 -0
  93. package/src/components/ComparisonTable/ComparisonTableContent.ts +4 -0
  94. package/src/components/ComparisonTable/HeaderCell.mobile.tsx +50 -0
  95. package/src/components/ComparisonTable/TableCell.mobile.tsx +46 -0
  96. package/src/components/ComparisonTable/TableCell.tsx +3 -2
  97. package/src/components/ComparisonTable/TableColumn.tsx +66 -0
  98. package/src/components/Gallery/Gallery.mobile.tsx +2 -2
  99. package/src/ui-kit/Button/Button.fixture.tsx +2 -6
  100. package/src/ui-kit/SwipeListControl/SwipeListControl.tsx +27 -19
  101. package/src/ui-kit/SwipeListControl/SwipeListControlProps.ts +1 -0
@@ -1,46 +1,50 @@
1
1
  import { JSX } from '@redneckz/uni-jsx';
2
2
  import type { LinkProps } from '../../model/LinkProps';
3
3
  import type { Picture } from '../../model/Picture';
4
- import { Button } from '../../ui-kit/Button/Button';
5
4
  import { Heading } from '../../ui-kit/Heading/Heading';
6
5
  import { Icon } from '../../ui-kit/Icon/Icon';
7
6
  import type { IconName } from '../../ui-kit/Icon/IconProps';
8
7
  import { Img } from '../../ui-kit/Img/Img';
9
- import { BORDER_CLASSES, GRADIENT } from './constants';
10
8
 
11
9
  export interface HeaderCellProps {
12
10
  icon?: IconName;
13
11
  image?: Picture;
14
12
  title?: string;
13
+ subtitle?: string;
14
+ isFillGradient?: boolean;
15
15
  link?: LinkProps;
16
16
  }
17
17
 
18
- export const HeaderCell = JSX<HeaderCellProps>(({ icon, image, title, link }) => (
19
- <div
20
- className={`w-80 box-border flex flex-col items-center rounded-t-md border-b-0 px-7 pt-7 pb-[46px] ${BORDER_CLASSES} ${GRADIENT}`}
21
- role="columnheader"
22
- scope="col"
23
- >
24
- {icon && !image?.src && (
25
- <Icon
26
- className="h-[63px] w-[63px] min-w-[63px] min-h-[63px] mb-4"
27
- name={icon}
28
- width="63"
29
- height="63"
30
- />
31
- )}
32
- {image?.src && <Img className="mb-[18px]" image={image} />}
33
- {title && <Heading headingType="h4" className="text-center text-white" title={title} />}
34
- {link?.text && (
35
- <div className="mt-auto w-full">
36
- <Button
37
- href={link.href}
38
- target={link.target}
39
- className="mt-4 w-full text-primary-main bg-white hover:bg-secondary-hover active:bg-secondary-active"
18
+ export const HeaderCell = JSX<HeaderCellProps>(
19
+ ({ icon, image, title, subtitle, isFillGradient }) => (
20
+ <div role="columnheader" scope="col">
21
+ {icon && (
22
+ <Icon
23
+ className="h-[63px] w-[63px] min-w-[63px] min-h-[63px] mb-4"
24
+ name={icon}
25
+ width="63"
26
+ height="63"
27
+ />
28
+ )}
29
+ {image?.src && (
30
+ <div className="mb-3.5">
31
+ <Img image={image} />
32
+ </div>
33
+ )}
34
+ {title && (
35
+ <Heading
36
+ headingType="h4"
37
+ className={`${isFillGradient ? 'text-white' : ''}`}
38
+ title={title}
39
+ />
40
+ )}
41
+ {subtitle && (
42
+ <div
43
+ className={`text-m-sm mb-3.5 ${isFillGradient ? 'text-white' : 'text-secondary-text/80'}`}
40
44
  >
41
- <div className="font-medium text-xs py-[11px]">{link.text}</div>
42
- </Button>
43
- </div>
44
- )}
45
- </div>
46
- ));
45
+ {subtitle}
46
+ </div>
47
+ )}
48
+ </div>
49
+ ),
50
+ );
@@ -1,43 +1,46 @@
1
1
  import { JSX } from '@redneckz/uni-jsx';
2
2
  import type { CellData } from './ComparisonTableContent';
3
- import { BORDER_CLASSES, DIVIDER_CLASSES, GRADIENT } from './constants';
3
+ import { DIVIDER_CLASSES } from './constants';
4
4
 
5
5
  export interface TableCellProps {
6
6
  cell: CellData[];
7
- isLastRow: boolean;
8
- isFirstRow: boolean;
9
- isFillGradient: boolean;
7
+ rowHeader?: string;
8
+ isLastRow?: boolean;
9
+ isFirstRow?: boolean;
10
+ isFillGradient?: boolean;
10
11
  }
11
12
 
12
- export const TableCell = JSX<TableCellProps>(({ cell, isFirstRow, isLastRow, isFillGradient }) => {
13
- const cellWrapperClasses = `w-80 box-border flex flex-col ${BORDER_CLASSES} ${
14
- !isLastRow ? 'border-y-0' : 'border-t-0 rounded-b-md'
15
- } ${isFillGradient ? GRADIENT : ''}`;
13
+ export const TableCell = JSX<TableCellProps>(({ cell, rowHeader, isFillGradient = false }) => {
14
+ const cellWrapperClasses = `box-border flex flex-col`;
16
15
 
17
- const cellClasses = `mx-7 h-full ${DIVIDER_CLASSES} ${
18
- isFillGradient && isFirstRow ? 'border-t' : ''
19
- } ${!isLastRow ? 'border-solid' : 'border-b-0'}`;
16
+ const cellClasses = `h-full ${DIVIDER_CLASSES}`;
20
17
 
21
18
  return (
22
19
  <div className={cellWrapperClasses} role="cell">
23
- <div className={cellClasses}>
24
- {cell.map((item, i) => renderCellInner(item, i, isFillGradient))}
25
- </div>
20
+ <div className={cellClasses}>{cell.map(renderCellInner(isFillGradient, rowHeader))}</div>
26
21
  </div>
27
22
  );
28
23
  });
29
24
 
30
- const renderCellInner = ({ label, description }: CellData, i: number, isFillGradient: boolean) => (
31
- <div key={String(i)} className="first:pt-7 pt-6 last:pb-7">
32
- {label && (
33
- <h5 className={`text-xl font-medium m-0 ${isFillGradient ? 'text-white' : ''}`}>{label}</h5>
34
- )}
35
- {description && (
36
- <div
37
- className={`text-sm opacity-80 ${isFillGradient ? 'text-white' : 'text-secondary-text'}`}
38
- >
39
- {description}
25
+ const renderCellInner =
26
+ (isFillGradient: boolean, rowHeader?: string) =>
27
+ ({ label, description }: CellData, i: number) =>
28
+ (
29
+ <div key={String(i)} className="flex justify-between text-m-sm py-3.5">
30
+ <div className={`${isFillGradient ? 'text-white/80' : 'text-secondary-text'}`}>
31
+ {rowHeader}
32
+ </div>
33
+ <div className="basis-1/2">
34
+ {label && (
35
+ <div className={`text-right ${isFillGradient ? 'text-white' : ''}`}>{label}</div>
36
+ )}
37
+ {description && (
38
+ <div
39
+ className={`text-right ${isFillGradient ? 'text-white/80' : 'text-secondary-text'}`}
40
+ >
41
+ {description}
42
+ </div>
43
+ )}
44
+ </div>
40
45
  </div>
41
- )}
42
- </div>
43
- );
46
+ );
@@ -0,0 +1,66 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { ButtonVersion } from '../../model/ButtonVersion';
3
+ import type { UniBlockProps } from '../../types';
4
+ import { Button } from '../../ui-kit/Button/Button';
5
+ import { GRADIENT } from './constants';
6
+ import { HeaderCell } from './HeaderCell';
7
+ import { TableCell } from './TableCell';
8
+
9
+ export interface TableColumnProps extends UniBlockProps {
10
+ header: any;
11
+ columnData: any;
12
+ visibleRowLength: number;
13
+ isFillGradient: boolean;
14
+ showRow: boolean;
15
+ onToggleColumn: () => void;
16
+ }
17
+
18
+ export const TableColumn = JSX<TableColumnProps>(
19
+ ({ header, columnData, visibleRowLength = 0, isFillGradient, showRow, onToggleColumn }) => {
20
+ const columnDataView = columnData.slice(0, showRow ? columnData.length : visibleRowLength);
21
+ const gradientClassName = isFillGradient ? GRADIENT : '';
22
+ const buttonVersion: ButtonVersion = isFillGradient ? 'secondary' : 'primary';
23
+ return (
24
+ <div className={`border border-main-stroke rounded-md p-4 mb-3.5 ${gradientClassName}`}>
25
+ <HeaderCell {...header} isFillGradient={isFillGradient} />
26
+ {columnDataView?.length
27
+ ? columnDataView.map(({ rowHeader, cell }, i) => (
28
+ <TableCell
29
+ key={String(i)}
30
+ cell={cell}
31
+ rowHeader={rowHeader}
32
+ isFillGradient={isFillGradient}
33
+ />
34
+ ))
35
+ : null}
36
+
37
+ {showRow && renderButton({ header, buttonVersion })}
38
+ {renderToggleButton({ onToggleColumn, isFillGradient, showRow })}
39
+ </div>
40
+ );
41
+ },
42
+ );
43
+
44
+ const renderButton = ({ header, buttonVersion }) => (
45
+ <Button
46
+ href={header.link.href}
47
+ target={header.link.target}
48
+ version={buttonVersion}
49
+ className="font-medium text-m-sm mt-4 py-[11px]"
50
+ >
51
+ {header.link.text}
52
+ </Button>
53
+ );
54
+
55
+ const renderToggleButton = ({ onToggleColumn, isFillGradient, showRow }) => (
56
+ <div className="mt-5">
57
+ <a
58
+ onClick={onToggleColumn}
59
+ className={`font-medium text-m-sm cursor-pointer ${
60
+ isFillGradient ? 'text-white/80' : 'text-primary-main'
61
+ }`}
62
+ >
63
+ {!showRow ? 'Показать описание' : 'Скрыть'}
64
+ </a>
65
+ </div>
66
+ );
@@ -2,12 +2,12 @@ import { JSX } from '@redneckz/uni-jsx';
2
2
  import { BlockVersion } from '../../model/BlockVersion';
3
3
  import { Button } from '../../ui-kit/Button/Button';
4
4
  import { Heading } from '../../ui-kit/Heading/Heading';
5
+ import { Icon } from '../../ui-kit/Icon/Icon';
5
6
  import { Img } from '../../ui-kit/Img/Img';
6
7
  import { SwipeListControl } from '../../ui-kit/SwipeListControl/SwipeListControl';
7
8
  import type { GalleryCard } from './GalleryContent';
8
9
  import { GalleryItem } from './GalleryContent';
9
10
  import type { GalleryProps } from './GalleryProps';
10
- import { Icon } from '../../ui-kit/Icon/Icon';
11
11
 
12
12
  const blockStyle: Record<BlockVersion, string> = {
13
13
  primary: 'bg-white',
@@ -57,7 +57,7 @@ function renderCard(card: GalleryCard, key: number) {
57
57
  {card.description ? renderDescription(card) : null}
58
58
  {card.items?.length ? renderItems(card.items) : null}
59
59
  </div>
60
- {card?.button?.href ? renderButton(card.button) : null}
60
+ {card?.button?.text ? renderButton(card.button) : null}
61
61
  </div>
62
62
  );
63
63
  }
@@ -1,10 +1,10 @@
1
1
  import { JSX } from '@redneckz/uni-jsx';
2
+ import { DEFAULT_GAP, DEFAULT_PADDING } from './constants';
3
+ import { SwipeListControlDots } from './SwipeListControlDots';
4
+ import { SwipeListControlList } from './SwipeListControlList';
2
5
  import type { SwipeListControlProps } from './SwipeListControlProps';
3
- import { getScrollPoints } from './utils/getScrollPoints';
4
6
  import { getIndexParts } from './utils/getIndexParts';
5
- import { SwipeListControlList } from './SwipeListControlList';
6
- import { SwipeListControlDots } from './SwipeListControlDots';
7
- import { DEFAULT_GAP, DEFAULT_PADDING } from './constants';
7
+ import { getScrollPoints } from './utils/getScrollPoints';
8
8
 
9
9
  export const SwipeListControl = JSX<SwipeListControlProps>(
10
10
  ({
@@ -14,6 +14,7 @@ export const SwipeListControl = JSX<SwipeListControlProps>(
14
14
  gap = DEFAULT_GAP,
15
15
  padding = DEFAULT_PADDING,
16
16
  showDots = true,
17
+ onSlideChange,
17
18
  }) => {
18
19
  const [activeIndex, setActiveIndex] = context.useState<number>(0);
19
20
  const [indexFraction, setIndexFraction] = context.useState<number>(0);
@@ -35,28 +36,35 @@ export const SwipeListControl = JSX<SwipeListControlProps>(
35
36
  });
36
37
 
37
38
  const { index, fraction } = getIndexParts(scrollLeft, scrollPoints);
39
+ if (index !== activeIndex && onSlideChange) {
40
+ onSlideChange();
41
+ }
38
42
  setActiveIndex(index);
39
43
  setIndexFraction(fraction);
40
44
  };
41
45
 
42
46
  return (
43
47
  <div className={className}>
44
- <SwipeListControlList
45
- gap={gap}
46
- padding={padding}
47
- activeIndex={activeIndex}
48
- onScroll={handleScroll}
49
- >
50
- {children}
51
- </SwipeListControlList>
52
- <SwipeListControlDots
53
- activeIndex={activeIndex}
54
- indexFraction={indexFraction}
55
- showDots={showDots}
56
- >
57
- {children}
58
- </SwipeListControlDots>
48
+ {renderSwipeList({ gap, padding, activeIndex, handleScroll, children })}
49
+ {renderSwipelistDots({ activeIndex, indexFraction, showDots, children })}
59
50
  </div>
60
51
  );
61
52
  },
62
53
  );
54
+
55
+ const renderSwipeList = ({ gap, padding, activeIndex, handleScroll, children }) => (
56
+ <SwipeListControlList
57
+ gap={gap}
58
+ padding={padding}
59
+ activeIndex={activeIndex}
60
+ onScroll={handleScroll}
61
+ >
62
+ {children}
63
+ </SwipeListControlList>
64
+ );
65
+
66
+ const renderSwipelistDots = ({ activeIndex, indexFraction, showDots, children }) => (
67
+ <SwipeListControlDots activeIndex={activeIndex} indexFraction={indexFraction} showDots={showDots}>
68
+ {children}
69
+ </SwipeListControlDots>
70
+ );
@@ -16,4 +16,5 @@ export interface SwipeContainer {
16
16
  export interface SwipeListControlProps extends SwipeContainer, UniBlockProps {
17
17
  /** @title Точки-индикаторы */
18
18
  showDots?: boolean;
19
+ onSlideChange?: () => void;
19
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redneckz/wildless-cms-uni-blocks",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "ЦК",
package/src/common.css CHANGED
@@ -86,9 +86,7 @@
86
86
  .horizontal-list {
87
87
  display: flex;
88
88
  overflow-x: scroll;
89
- overscroll-behavior: contain;
90
89
  -webkit-overflow-scrolling: touch;
91
- touch-action: pan-x;
92
90
  scroll-snap-type: x mandatory;
93
91
  }
94
92
 
@@ -0,0 +1,152 @@
1
+ import type { Picture } from '../../model/Picture';
2
+ import { context } from '../../setup-fixture';
3
+ import { ComparisonTable } from './ComparisonTable';
4
+ import type { Column } from './ComparisonTableContent';
5
+
6
+ const image1: Picture = {
7
+ src: 'card-1.png',
8
+ format: 'webp',
9
+ size: {
10
+ width: 100,
11
+ height: 63,
12
+ },
13
+ };
14
+
15
+ const image2: Picture = {
16
+ src: 'card-2.png',
17
+ format: 'webp',
18
+ size: {
19
+ width: 100,
20
+ height: 63,
21
+ },
22
+ };
23
+
24
+ const image3: Picture = {
25
+ src: 'card-3.png',
26
+ format: 'webp',
27
+ size: {
28
+ width: 100,
29
+ height: 63,
30
+ },
31
+ };
32
+
33
+ const rowHeaders = [
34
+ { title: 'Начисление процентов на остаток по счету' },
35
+ { title: 'Начисление процентов на остаток по счету' },
36
+ { title: 'Начисление процентов на остаток по счету' },
37
+ ];
38
+ const columns: Column[] = [
39
+ {
40
+ header: {
41
+ title: 'Россельхоз-Росснефть',
42
+ subtitle: 'Менеджер свяжется с вами и согласует встречу',
43
+ image: image1,
44
+ link: {
45
+ text: 'Подробнее',
46
+ href: '#',
47
+ },
48
+ },
49
+ data: [
50
+ [
51
+ {
52
+ label: 'Бесплатно',
53
+ description: 'Мир',
54
+ },
55
+ ],
56
+ [
57
+ {
58
+ label: 'Бесплатно',
59
+ description: 'Мир',
60
+ },
61
+ ],
62
+ [
63
+ {
64
+ label: 'Бесплатно',
65
+ description: 'Мир',
66
+ },
67
+ ],
68
+ ],
69
+ },
70
+ {
71
+ header: {
72
+ title: 'Россельхоз-Росснефть',
73
+ image: image2,
74
+ link: {
75
+ text: 'Подробнее',
76
+ href: '#',
77
+ },
78
+ },
79
+ data: [
80
+ [
81
+ {
82
+ label: 'Бесплатно',
83
+ description: 'Начисление процентов на остаток по счету',
84
+ },
85
+ ],
86
+ [
87
+ {
88
+ label: 'Бесплатно',
89
+ description: 'Начисление',
90
+ },
91
+ ],
92
+ [
93
+ {
94
+ description: 'Начисление процентов на остаток по счету',
95
+ },
96
+ ],
97
+ ],
98
+ },
99
+ {
100
+ header: {
101
+ title: 'Профсоюзная',
102
+ image: image3,
103
+ link: {
104
+ text: 'Подробнее',
105
+ href: '/credits',
106
+ },
107
+ },
108
+ data: [
109
+ [{ label: 'Нет' }],
110
+ [{ label: 'Бесплатно' }],
111
+ [{ label: 'Есть' }],
112
+ [{ label: 'До 20%' }],
113
+ [
114
+ {
115
+ label: 'Бесплатно',
116
+ description: 'При обороте по карте от 10000 ₽ в месяц',
117
+ },
118
+ ],
119
+ [{ label: '69 рублей в месяц' }],
120
+ [{ description: 'Для членов профсоюзных организаций' }],
121
+ ],
122
+ },
123
+ ];
124
+ export default {
125
+ default: (
126
+ <div className="container grid grid-cols-12">
127
+ <ComparisonTable
128
+ className="col-span-12"
129
+ title="Другие дебетовые карты Россельхозбанка"
130
+ isColoredFirstColumn={true}
131
+ context={context}
132
+ rowHeaders={rowHeaders}
133
+ columns={Array(2).fill(columns).flat()}
134
+ visibleRowLength={2}
135
+ />
136
+ </div>
137
+ ),
138
+ 'with swiper': (
139
+ <div className="container grid grid-cols-12">
140
+ <ComparisonTable
141
+ className="col-span-12"
142
+ title="Другие дебетовые карты Россельхозбанка"
143
+ isColoredFirstColumn={true}
144
+ context={context}
145
+ rowHeaders={rowHeaders}
146
+ useSwiper={true}
147
+ columns={Array(2).fill(columns).flat()}
148
+ visibleRowLength={2}
149
+ />
150
+ </div>
151
+ ),
152
+ };
@@ -0,0 +1,121 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { UniBlockProps } from '../../types';
3
+ import { Heading } from '../../ui-kit/Heading/Heading';
4
+ import { SwipeListControl } from '../../ui-kit/SwipeListControl/SwipeListControl';
5
+ import type { ComparisonTableContent } from './ComparisonTableContent';
6
+ import { TableColumn } from './TableColumn';
7
+
8
+ export interface ComparisonTableProps extends ComparisonTableContent, UniBlockProps {}
9
+
10
+ export const ComparisonTable = JSX<ComparisonTableProps>(
11
+ ({
12
+ className,
13
+ context,
14
+ title,
15
+ rowHeaders,
16
+ columns,
17
+ visibleRowLength = 0,
18
+ isColoredFirstColumn = false,
19
+ useSwiper = false,
20
+ }) => {
21
+ const tableData =
22
+ columns?.map(({ data, header }) => ({
23
+ header,
24
+ column: data?.map((cell, i) => ({ cell, rowHeader: rowHeaders?.[i]?.title })),
25
+ })) || [];
26
+
27
+ const [columnsViewState, setColumnsViewState] = context.useState<boolean[]>(
28
+ new Array(columns?.length).fill(!visibleRowLength),
29
+ );
30
+
31
+ const handleToggleColumn = (i: number) => {
32
+ columnsViewState[i] = !columnsViewState[i];
33
+ setColumnsViewState([...columnsViewState]);
34
+ };
35
+
36
+ return (
37
+ <section
38
+ className={`bg-white font-sans px-4 py-6 overflow-hidden text-primary-text relative ${
39
+ className || ''
40
+ }`}
41
+ >
42
+ {title && (
43
+ <Heading headingType="h3" className="font-medium text-center m-0 mb-5" title={title} />
44
+ )}
45
+
46
+ {renderColumns({
47
+ tableData,
48
+ context,
49
+ visibleRowLength,
50
+ isColoredFirstColumn,
51
+ columnsViewState,
52
+ handleToggleColumn,
53
+ useSwiper,
54
+ setColumnsViewState,
55
+ })}
56
+ </section>
57
+ );
58
+ },
59
+ );
60
+
61
+ const renderColumns = ({
62
+ context,
63
+ tableData,
64
+ visibleRowLength,
65
+ isColoredFirstColumn,
66
+ columnsViewState,
67
+ handleToggleColumn,
68
+ useSwiper,
69
+ setColumnsViewState,
70
+ }) => (
71
+ <div role="table">
72
+ {tableData?.length ? (
73
+ useSwiper ? (
74
+ <SwipeListControl
75
+ context={context}
76
+ onSlideChange={onSlideChange(columnsViewState, setColumnsViewState)}
77
+ >
78
+ {tableData.map(
79
+ renderColumn({
80
+ context,
81
+ visibleRowLength,
82
+ isColoredFirstColumn,
83
+ columnsViewState,
84
+ handleToggleColumn,
85
+ }),
86
+ )}
87
+ </SwipeListControl>
88
+ ) : (
89
+ tableData.map(
90
+ renderColumn({
91
+ context,
92
+ visibleRowLength,
93
+ isColoredFirstColumn,
94
+ columnsViewState,
95
+ handleToggleColumn,
96
+ }),
97
+ )
98
+ )
99
+ ) : null}
100
+ </div>
101
+ );
102
+
103
+ const renderColumn =
104
+ ({ context, visibleRowLength, isColoredFirstColumn, columnsViewState, handleToggleColumn }) =>
105
+ (columnData, i) =>
106
+ (
107
+ <TableColumn
108
+ key={String(i)}
109
+ context={context}
110
+ visibleRowLength={visibleRowLength}
111
+ showRow={columnsViewState[i]}
112
+ header={columnData.header}
113
+ columnData={columnData.column}
114
+ isFillGradient={i === 0 && isColoredFirstColumn}
115
+ onToggleColumn={() => handleToggleColumn(i)}
116
+ />
117
+ );
118
+
119
+ const onSlideChange = (columnsViewState, setColumnsViewState) => () => {
120
+ setColumnsViewState(new Array(columnsViewState.length).fill(false));
121
+ };
@@ -26,6 +26,8 @@ export interface CellData {
26
26
  export interface ColumnHeader {
27
27
  /** @title Заголовок */
28
28
  title?: string;
29
+ /** @title Подзаголовок */
30
+ subtitle?: string;
29
31
  icon?: IconName;
30
32
  image?: Picture;
31
33
  link?: LinkProps;
@@ -61,4 +63,6 @@ export interface ComparisonTableContent {
61
63
  isColoredFirstColumn?: boolean;
62
64
  /** @title Отображать заданное количество строк */
63
65
  visibleRowLength?: number;
66
+ /** @title Использовать свайпер- */
67
+ useSwiper?: boolean;
64
68
  }
@@ -0,0 +1,50 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { LinkProps } from '../../model/LinkProps';
3
+ import type { Picture } from '../../model/Picture';
4
+ import { Heading } from '../../ui-kit/Heading/Heading';
5
+ import { Icon } from '../../ui-kit/Icon/Icon';
6
+ import type { IconName } from '../../ui-kit/Icon/IconProps';
7
+ import { Img } from '../../ui-kit/Img/Img';
8
+
9
+ export interface HeaderCellProps {
10
+ icon?: IconName;
11
+ image?: Picture;
12
+ title?: string;
13
+ subtitle?: string;
14
+ isFillGradient?: boolean;
15
+ link?: LinkProps;
16
+ }
17
+
18
+ export const HeaderCell = JSX<HeaderCellProps>(
19
+ ({ icon, image, title, subtitle, isFillGradient }) => (
20
+ <div role="columnheader" scope="col">
21
+ {icon && (
22
+ <Icon
23
+ className="h-[63px] w-[63px] min-w-[63px] min-h-[63px] mb-4"
24
+ name={icon}
25
+ width="63"
26
+ height="63"
27
+ />
28
+ )}
29
+ {image?.src && (
30
+ <div className="mb-3.5">
31
+ <Img image={image} />
32
+ </div>
33
+ )}
34
+ {title && (
35
+ <Heading
36
+ headingType="h4"
37
+ className={`${isFillGradient ? 'text-white' : ''}`}
38
+ title={title}
39
+ />
40
+ )}
41
+ {subtitle && (
42
+ <div
43
+ className={`text-m-sm mb-3.5 ${isFillGradient ? 'text-white' : 'text-secondary-text/80'}`}
44
+ >
45
+ {subtitle}
46
+ </div>
47
+ )}
48
+ </div>
49
+ ),
50
+ );