@redneckz/wildless-cms-uni-blocks 0.3.55 → 0.3.57

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 (201) hide show
  1. package/bundle/blocks.schema.json +1 -1
  2. package/bundle/bundle.umd.js +69 -21
  3. package/bundle/bundle.umd.min.js +1 -1
  4. package/dist/components/BlockContent.d.ts +2 -1
  5. package/dist/components/Blocks.d.ts +1 -0
  6. package/dist/components/Blocks.js +2 -0
  7. package/dist/components/Blocks.js.map +1 -1
  8. package/dist/components/ContentPage/ContentPage.js +3 -5
  9. package/dist/components/ContentPage/ContentPage.js.map +1 -1
  10. package/dist/components/ContentPage/CustomContentPage.d.ts +30 -0
  11. package/dist/components/ContentPage/CustomContentPage.js +33 -0
  12. package/dist/components/ContentPage/CustomContentPage.js.map +1 -0
  13. package/dist/components/GroupBlock/BlocksTypeProps.d.ts +36 -0
  14. package/dist/components/GroupBlock/BlocksTypeProps.js +2 -0
  15. package/dist/components/GroupBlock/BlocksTypeProps.js.map +1 -0
  16. package/dist/components/GroupBlock/EmbeddableGroupBlocks.d.ts +4 -0
  17. package/dist/components/GroupBlock/EmbeddableGroupBlocks.js +9 -0
  18. package/dist/components/GroupBlock/EmbeddableGroupBlocks.js.map +1 -0
  19. package/dist/components/GroupBlock/GroupBlock.d.ts +9 -0
  20. package/dist/components/GroupBlock/GroupBlock.js +19 -0
  21. package/dist/components/GroupBlock/GroupBlock.js.map +1 -0
  22. package/dist/components/GroupBlock/GroupBlockContent.d.ts +21 -0
  23. package/dist/components/GroupBlock/GroupBlockContent.js +2 -0
  24. package/dist/components/GroupBlock/GroupBlockContent.js.map +1 -0
  25. package/dist/components/GroupBlock/GroupBlockTabs.d.ts +10 -0
  26. package/dist/components/GroupBlock/GroupBlockTabs.js +18 -0
  27. package/dist/components/GroupBlock/GroupBlockTabs.js.map +1 -0
  28. package/dist/components/GroupBlock/GroupBlocksItem.d.ts +8 -0
  29. package/dist/components/GroupBlock/GroupBlocksItem.js +20 -0
  30. package/dist/components/GroupBlock/GroupBlocksItem.js.map +1 -0
  31. package/dist/components/GroupBlock/filterBlocksByTag.d.ts +2 -0
  32. package/dist/components/GroupBlock/filterBlocksByTag.js +7 -0
  33. package/dist/components/GroupBlock/filterBlocksByTag.js.map +1 -0
  34. package/dist/components/GroupBlock/renderBlocksTypes.d.ts +9 -0
  35. package/dist/components/GroupBlock/renderBlocksTypes.js +16 -0
  36. package/dist/components/GroupBlock/renderBlocksTypes.js.map +1 -0
  37. package/dist/components/OtherProducts/OtherProductsContent.d.ts +4 -2
  38. package/dist/components/ProductBlock/ProductBlockInner.js +1 -1
  39. package/dist/components/ProductBlock/ProductBlockInner.js.map +1 -1
  40. package/dist/components/ProductGalleryGreen/ProductGalleryGreen.js +9 -11
  41. package/dist/components/ProductGalleryGreen/ProductGalleryGreen.js.map +1 -1
  42. package/dist/types.d.ts +5 -0
  43. package/dist/utils/style2className.d.ts +1 -0
  44. package/dist/utils/style2className.js +7 -0
  45. package/dist/utils/style2className.js.map +1 -0
  46. package/lib/common.css +1 -1
  47. package/lib/components/BlockContent.d.ts +2 -1
  48. package/lib/components/Blocks.d.ts +1 -0
  49. package/lib/components/Blocks.js +2 -0
  50. package/lib/components/Blocks.js.map +1 -1
  51. package/lib/components/ContentPage/ContentPage.js +1 -3
  52. package/lib/components/ContentPage/ContentPage.js.map +1 -1
  53. package/lib/components/ContentPage/CustomContentPage.d.ts +30 -0
  54. package/lib/components/ContentPage/CustomContentPage.js +31 -0
  55. package/lib/components/ContentPage/CustomContentPage.js.map +1 -0
  56. package/lib/components/GroupBlock/BlocksTypeProps.d.ts +36 -0
  57. package/lib/components/GroupBlock/BlocksTypeProps.js +2 -0
  58. package/lib/components/GroupBlock/BlocksTypeProps.js.map +1 -0
  59. package/lib/components/GroupBlock/EmbeddableGroupBlocks.d.ts +4 -0
  60. package/lib/components/GroupBlock/EmbeddableGroupBlocks.js +7 -0
  61. package/lib/components/GroupBlock/EmbeddableGroupBlocks.js.map +1 -0
  62. package/lib/components/GroupBlock/GroupBlock.d.ts +9 -0
  63. package/lib/components/GroupBlock/GroupBlock.fixture.d.ts +4 -0
  64. package/lib/components/GroupBlock/GroupBlock.js +17 -0
  65. package/lib/components/GroupBlock/GroupBlock.js.map +1 -0
  66. package/lib/components/GroupBlock/GroupBlockContent.d.ts +21 -0
  67. package/lib/components/GroupBlock/GroupBlockContent.js +2 -0
  68. package/lib/components/GroupBlock/GroupBlockContent.js.map +1 -0
  69. package/lib/components/GroupBlock/GroupBlockTabs.d.ts +10 -0
  70. package/lib/components/GroupBlock/GroupBlockTabs.js +16 -0
  71. package/lib/components/GroupBlock/GroupBlockTabs.js.map +1 -0
  72. package/lib/components/GroupBlock/GroupBlocksItem.d.ts +8 -0
  73. package/lib/components/GroupBlock/GroupBlocksItem.js +17 -0
  74. package/lib/components/GroupBlock/GroupBlocksItem.js.map +1 -0
  75. package/lib/components/GroupBlock/filterBlocksByTag.d.ts +2 -0
  76. package/lib/components/GroupBlock/filterBlocksByTag.js +4 -0
  77. package/lib/components/GroupBlock/filterBlocksByTag.js.map +1 -0
  78. package/lib/components/GroupBlock/renderBlocksTypes.d.ts +9 -0
  79. package/lib/components/GroupBlock/renderBlocksTypes.js +13 -0
  80. package/lib/components/GroupBlock/renderBlocksTypes.js.map +1 -0
  81. package/lib/components/OtherProducts/OtherProductsContent.d.ts +4 -2
  82. package/lib/components/ProductBlock/ProductBlockInner.js +1 -1
  83. package/lib/components/ProductBlock/ProductBlockInner.js.map +1 -1
  84. package/lib/components/ProductGalleryGreen/ProductGalleryGreen.js +9 -11
  85. package/lib/components/ProductGalleryGreen/ProductGalleryGreen.js.map +1 -1
  86. package/lib/types.d.ts +5 -0
  87. package/lib/utils/style2className.d.ts +1 -0
  88. package/lib/utils/style2className.js +4 -0
  89. package/lib/utils/style2className.js.map +1 -0
  90. package/mobile/bundle/bundle.umd.js +4 -3
  91. package/mobile/bundle/bundle.umd.min.js +1 -1
  92. package/mobile/dist/components/BlockContent.d.ts +2 -1
  93. package/mobile/dist/components/ContentPage/ContentPage.js +3 -5
  94. package/mobile/dist/components/ContentPage/ContentPage.js.map +1 -1
  95. package/mobile/dist/components/ContentPage/CustomContentPage.d.ts +30 -0
  96. package/mobile/dist/components/ContentPage/CustomContentPage.js +33 -0
  97. package/mobile/dist/components/ContentPage/CustomContentPage.js.map +1 -0
  98. package/mobile/dist/components/GroupBlock/BlocksTypeProps.d.ts +36 -0
  99. package/mobile/dist/components/GroupBlock/BlocksTypeProps.js +2 -0
  100. package/mobile/dist/components/GroupBlock/BlocksTypeProps.js.map +1 -0
  101. package/mobile/dist/components/GroupBlock/EmbeddableGroupBlocks.d.ts +4 -0
  102. package/mobile/dist/components/GroupBlock/EmbeddableGroupBlocks.js +9 -0
  103. package/mobile/dist/components/GroupBlock/EmbeddableGroupBlocks.js.map +1 -0
  104. package/mobile/dist/components/GroupBlock/GroupBlock.d.ts +9 -0
  105. package/mobile/dist/components/GroupBlock/GroupBlock.js +19 -0
  106. package/mobile/dist/components/GroupBlock/GroupBlock.js.map +1 -0
  107. package/mobile/dist/components/GroupBlock/GroupBlockContent.d.ts +21 -0
  108. package/mobile/dist/components/GroupBlock/GroupBlockContent.js +2 -0
  109. package/mobile/dist/components/GroupBlock/GroupBlockContent.js.map +1 -0
  110. package/mobile/dist/components/GroupBlock/GroupBlockTabs.d.ts +10 -0
  111. package/mobile/dist/components/GroupBlock/GroupBlockTabs.js +18 -0
  112. package/mobile/dist/components/GroupBlock/GroupBlockTabs.js.map +1 -0
  113. package/mobile/dist/components/GroupBlock/GroupBlocksItem.d.ts +8 -0
  114. package/mobile/dist/components/GroupBlock/GroupBlocksItem.js +20 -0
  115. package/mobile/dist/components/GroupBlock/GroupBlocksItem.js.map +1 -0
  116. package/mobile/dist/components/GroupBlock/filterBlocksByTag.d.ts +2 -0
  117. package/mobile/dist/components/GroupBlock/filterBlocksByTag.js +7 -0
  118. package/mobile/dist/components/GroupBlock/filterBlocksByTag.js.map +1 -0
  119. package/mobile/dist/components/GroupBlock/renderBlocksTypes.d.ts +9 -0
  120. package/mobile/dist/components/GroupBlock/renderBlocksTypes.js +16 -0
  121. package/mobile/dist/components/GroupBlock/renderBlocksTypes.js.map +1 -0
  122. package/mobile/dist/components/OtherProducts/OtherProductsContent.d.ts +4 -2
  123. package/mobile/dist/components/ProductGalleryGreen/ProductGalleryGreen.js +9 -11
  124. package/mobile/dist/components/ProductGalleryGreen/ProductGalleryGreen.js.map +1 -1
  125. package/mobile/dist/types.d.ts +5 -0
  126. package/mobile/dist/utils/style2className.d.ts +1 -0
  127. package/mobile/dist/utils/style2className.js +7 -0
  128. package/mobile/dist/utils/style2className.js.map +1 -0
  129. package/mobile/lib/components/BlockContent.d.ts +2 -1
  130. package/mobile/lib/components/ContentPage/ContentPage.js +1 -3
  131. package/mobile/lib/components/ContentPage/ContentPage.js.map +1 -1
  132. package/mobile/lib/components/ContentPage/CustomContentPage.d.ts +30 -0
  133. package/mobile/lib/components/ContentPage/CustomContentPage.js +31 -0
  134. package/mobile/lib/components/ContentPage/CustomContentPage.js.map +1 -0
  135. package/mobile/lib/components/GroupBlock/BlocksTypeProps.d.ts +36 -0
  136. package/mobile/lib/components/GroupBlock/BlocksTypeProps.js +2 -0
  137. package/mobile/lib/components/GroupBlock/BlocksTypeProps.js.map +1 -0
  138. package/mobile/lib/components/GroupBlock/EmbeddableGroupBlocks.d.ts +4 -0
  139. package/mobile/lib/components/GroupBlock/EmbeddableGroupBlocks.js +7 -0
  140. package/mobile/lib/components/GroupBlock/EmbeddableGroupBlocks.js.map +1 -0
  141. package/mobile/lib/components/GroupBlock/GroupBlock.d.ts +9 -0
  142. package/mobile/lib/components/GroupBlock/GroupBlock.js +17 -0
  143. package/mobile/lib/components/GroupBlock/GroupBlock.js.map +1 -0
  144. package/mobile/lib/components/GroupBlock/GroupBlockContent.d.ts +21 -0
  145. package/mobile/lib/components/GroupBlock/GroupBlockContent.js +2 -0
  146. package/mobile/lib/components/GroupBlock/GroupBlockContent.js.map +1 -0
  147. package/mobile/lib/components/GroupBlock/GroupBlockTabs.d.ts +10 -0
  148. package/mobile/lib/components/GroupBlock/GroupBlockTabs.js +16 -0
  149. package/mobile/lib/components/GroupBlock/GroupBlockTabs.js.map +1 -0
  150. package/mobile/lib/components/GroupBlock/GroupBlocksItem.d.ts +8 -0
  151. package/mobile/lib/components/GroupBlock/GroupBlocksItem.js +17 -0
  152. package/mobile/lib/components/GroupBlock/GroupBlocksItem.js.map +1 -0
  153. package/mobile/lib/components/GroupBlock/filterBlocksByTag.d.ts +2 -0
  154. package/mobile/lib/components/GroupBlock/filterBlocksByTag.js +4 -0
  155. package/mobile/lib/components/GroupBlock/filterBlocksByTag.js.map +1 -0
  156. package/mobile/lib/components/GroupBlock/renderBlocksTypes.d.ts +9 -0
  157. package/mobile/lib/components/GroupBlock/renderBlocksTypes.js +13 -0
  158. package/mobile/lib/components/GroupBlock/renderBlocksTypes.js.map +1 -0
  159. package/mobile/lib/components/OtherProducts/OtherProductsContent.d.ts +4 -2
  160. package/mobile/lib/components/ProductGalleryGreen/ProductGalleryGreen.js +9 -11
  161. package/mobile/lib/components/ProductGalleryGreen/ProductGalleryGreen.js.map +1 -1
  162. package/mobile/lib/types.d.ts +5 -0
  163. package/mobile/lib/utils/style2className.d.ts +1 -0
  164. package/mobile/lib/utils/style2className.js +4 -0
  165. package/mobile/lib/utils/style2className.js.map +1 -0
  166. package/mobile/src/components/BlockContent.ts +3 -1
  167. package/mobile/src/components/ContentPage/ContentPage.tsx +1 -4
  168. package/mobile/src/components/ContentPage/CustomContentPage.tsx +82 -0
  169. package/mobile/src/components/GroupBlock/BlocksTypeProps.ts +40 -0
  170. package/mobile/src/components/GroupBlock/EmbeddableGroupBlocks.tsx +7 -0
  171. package/mobile/src/components/GroupBlock/GroupBlock.example.json +27 -0
  172. package/mobile/src/components/GroupBlock/GroupBlock.tsx +43 -0
  173. package/mobile/src/components/GroupBlock/GroupBlockContent.ts +23 -0
  174. package/mobile/src/components/GroupBlock/GroupBlockTabs.tsx +54 -0
  175. package/mobile/src/components/GroupBlock/GroupBlocksItem.tsx +30 -0
  176. package/mobile/src/components/GroupBlock/filterBlocksByTag.ts +5 -0
  177. package/mobile/src/components/GroupBlock/renderBlocksTypes.tsx +27 -0
  178. package/mobile/src/components/OtherProducts/OtherProductsContent.ts +4 -2
  179. package/mobile/src/components/ProductGalleryGreen/ProductGalleryGreen.tsx +8 -14
  180. package/mobile/src/types.ts +7 -1
  181. package/mobile/src/utils/style2className.ts +3 -0
  182. package/package.json +1 -1
  183. package/src/components/BlockContent.ts +3 -1
  184. package/src/components/Blocks.ts +2 -0
  185. package/src/components/ContentPage/ContentPage.tsx +1 -4
  186. package/src/components/ContentPage/CustomContentPage.tsx +82 -0
  187. package/src/components/GroupBlock/BlocksTypeProps.ts +40 -0
  188. package/src/components/GroupBlock/EmbeddableGroupBlocks.tsx +7 -0
  189. package/src/components/GroupBlock/GroupBlock.example.json +27 -0
  190. package/src/components/GroupBlock/GroupBlock.fixture.tsx +51 -0
  191. package/src/components/GroupBlock/GroupBlock.tsx +43 -0
  192. package/src/components/GroupBlock/GroupBlockContent.ts +23 -0
  193. package/src/components/GroupBlock/GroupBlockTabs.tsx +54 -0
  194. package/src/components/GroupBlock/GroupBlocksItem.tsx +30 -0
  195. package/src/components/GroupBlock/filterBlocksByTag.ts +5 -0
  196. package/src/components/GroupBlock/renderBlocksTypes.tsx +27 -0
  197. package/src/components/OtherProducts/OtherProductsContent.ts +4 -2
  198. package/src/components/ProductBlock/ProductBlockInner.tsx +1 -1
  199. package/src/components/ProductGalleryGreen/ProductGalleryGreen.tsx +8 -14
  200. package/src/types.ts +7 -1
  201. package/src/utils/style2className.ts +3 -0
@@ -0,0 +1,27 @@
1
+ import type { JSXBlock } from '../../components/ContentPage/ContentPage';
2
+ import type { ContentPageContext } from '../../components/ContentPage/ContentPageContext';
3
+ import type { GroupBlockDef } from './BlocksTypeProps';
4
+ import { EmbeddableGroupBlocks } from './EmbeddableGroupBlocks';
5
+ import { style2className } from '../../utils/style2className';
6
+
7
+ type EmbeddableBlocksProps = {
8
+ groupBlocks?: GroupBlockDef[];
9
+ context: ContentPageContext;
10
+ className?: string;
11
+ };
12
+
13
+ export const renderBlock =
14
+ ({ context, className }: EmbeddableBlocksProps) =>
15
+ (block: GroupBlockDef, i: number) => {
16
+ const type = block?.blockType;
17
+ if (!type || !(type in EmbeddableGroupBlocks)) {
18
+ return null;
19
+ }
20
+ const classNameBlock = style2className(block?.style);
21
+ const EmbeddedBlock: JSXBlock = EmbeddableGroupBlocks[type];
22
+ return (
23
+ <div className={className} key={`block_${i}`}>
24
+ <EmbeddedBlock context={context} {...block} className={classNameBlock} />
25
+ </div>
26
+ );
27
+ };
@@ -14,7 +14,10 @@ export interface BlockItemCommonProps {
14
14
  * @title Отображать в раскрытом виде
15
15
  */
16
16
  isExpanded?: boolean;
17
- /** @title Блоки */
17
+ /**
18
+ * @title Блоки
19
+ * @maxItems 10
20
+ */
18
21
  blocks?: BlockDef[];
19
22
  columns?: ColumnsCount;
20
23
  }
@@ -27,7 +30,6 @@ export interface OtherProductsContent {
27
30
  title?: string;
28
31
  /**
29
32
  * @title Список
30
- * @maxItems 10
31
33
  */
32
34
  blockItems?: BlockItemCommonProps[];
33
35
  colorPalette?: ColorPalette;
@@ -28,7 +28,7 @@ const productSlideStyleMap: Record<BlockVersion, string> = {
28
28
  };
29
29
 
30
30
  export const ProductGalleryGreen = JSX<ProductGalleryProps>(
31
- ({ className = '', context, slides = [], version = 'primary', duration = 0, anchor = null }) => {
31
+ ({ className = '', context, slides = [], version = 'primary', anchor = null }) => {
32
32
  const galleryNav = slides.map((s) => s.nav);
33
33
  const galleryBlocks = slides.map((s) => s.productBlock);
34
34
  const [activeSlideIndex, setActiveSlideIndex] = context.useState(0);
@@ -55,7 +55,6 @@ export const ProductGalleryGreen = JSX<ProductGalleryProps>(
55
55
  activeSlideIndex,
56
56
  onClick: () => setActiveSlideIndex(i),
57
57
  version,
58
- duration,
59
58
  }),
60
59
  )}
61
60
  </div>
@@ -76,7 +75,7 @@ function renderProductBlock(block: ProductBlockInnerContent, i: number, context)
76
75
  >
77
76
  <div className="flex grow">
78
77
  <ProductBlockInner
79
- className={`pl-[50px] pr-2 z-[1] ${additionalClass}`}
78
+ className={`pl-[50px] z-[1] ${additionalClass}`}
80
79
  context={context}
81
80
  textBlockClassName="mb-[154px]"
82
81
  {...block}
@@ -86,12 +85,12 @@ function renderProductBlock(block: ProductBlockInnerContent, i: number, context)
86
85
  );
87
86
  }
88
87
 
89
- function renderNavButton({ slide, i, activeSlideIndex, onClick, version, duration }) {
88
+ function renderNavButton({ slide, i, activeSlideIndex, onClick, version }) {
90
89
  const isActiveBtn = i === activeSlideIndex;
91
90
 
92
91
  const btnClassName = isActiveBtn
93
- ? 'bg-white shadow-dark-blue/42 h-[102px] w-[354px] min-w-[354px] max-w-[354px] p-0 border-none'
94
- : `min-w-[277px] px-0 pt-4 pb-[23px] hover:py-[26px] hover:py-[26px] ease-in duration-300
92
+ ? 'bg-white shadow-dark-blue/42 h-[102px] w-[354px] min-w-[354px] p-0 border-none'
93
+ : `min-w-[277px] px-0 pt-4 pb-[23px] hover:py-[26px] hover:py-[26px] ease-in duration-300 bg-white/10
95
94
  ${productSlideStyleMap[version]}`;
96
95
  const btnTitleClassName = isActiveBtn
97
96
  ? 'text-primary-text text-title-2xs'
@@ -100,8 +99,7 @@ function renderNavButton({ slide, i, activeSlideIndex, onClick, version, duratio
100
99
  ? 'text-secondary-text text-m-title-xs mt-2.5'
101
100
  : `text-m-md mt-1.5 ${productBlockStyleMap[version].text}`;
102
101
 
103
- const additionalBorder = version === 'secondary' ? 'border-white/50' : '';
104
- const progressBarClassName = isActiveBtn ? 'animate-slide' : '';
102
+ const additionalBorder = version === 'secondary' ? 'border-white/50' : 'border-black/50';
105
103
 
106
104
  return (
107
105
  <button
@@ -109,18 +107,14 @@ function renderNavButton({ slide, i, activeSlideIndex, onClick, version, duratio
109
107
  key={String(i)}
110
108
  onClick={onClick}
111
109
  aria-label={slide?.title}
112
- className={`box-border font-sans group relative overflow-hidden border-[1px] cursor-pointer text-left mx-1 grow basis-0 backdrop-blur-sm
113
- ${btnClassName} ${additionalBorder}
110
+ className={`box-border font-sans relative overflow-hidden border-[1px] border-white/50 cursor-pointer text-left mx-1 grow basis-0
111
+ ${btnClassName} ${additionalBorder}
114
112
  `}
115
113
  >
116
114
  <div className="border-0 px-6">
117
115
  <div className={`font-medium ${btnTitleClassName}`}>{slide?.title}</div>
118
116
  <div className={`text-secondary-text ${btnDescClassName}`}>{slide.description}</div>
119
117
  </div>
120
- <div
121
- className={`absolute bottom-0 left-0 w-full h-[3px] bg-primary-main -translate-x-full ${progressBarClassName}`}
122
- style={{ animationDuration: `${duration}s`, animationFillMode: 'forwards' }}
123
- ></div>
124
118
  </button>
125
119
  );
126
120
  }
@@ -44,10 +44,16 @@ export interface ContentPageMeta {
44
44
  jsonLd?: string;
45
45
  }
46
46
 
47
+ export interface CustomPageTemplate {
48
+ content?: Record<string, any>;
49
+ type?: string;
50
+ }
51
+
47
52
  export interface ContentPageDef extends ContentPageMeta {
48
53
  style?: string[];
49
- blocks?: BlockDef[]; //! for compatibility
54
+ blocks?: BlockDef[];
50
55
  slots?: SlotsMap;
56
+ customPageTmpl?: CustomPageTemplate;
51
57
  likeControl?: boolean;
52
58
  colorPalette?: ColorPalette;
53
59
  }
@@ -0,0 +1,3 @@
1
+ export function style2className(style: string[] | undefined | null): string {
2
+ return style ? style.filter(Boolean).join(' ') : '';
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redneckz/wildless-cms-uni-blocks",
3
- "version": "0.3.55",
3
+ "version": "0.3.57",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "ЦК",
@@ -5,6 +5,7 @@ import type { ExchangeRateTileContent } from './ExchangeRateTile/ExchangeRateTil
5
5
  import type { FooterContent } from './Footer/FooterContent';
6
6
  import type { GalleryContent } from './Gallery/GalleryContent';
7
7
  import type { GracePeriodContent } from './GracePeriod/GracePeriodContent';
8
+ import type { GroupBlockContent } from './GroupBlock/GroupBlockContent';
8
9
  import type { HeaderContent } from './Header/HeaderContent';
9
10
  import type { LinkDocsContent } from './LinkDocs/LinkDocsContent';
10
11
  import type { LinkListContent } from './LinkList/LinkListContent';
@@ -48,4 +49,5 @@ export type BlockContent =
48
49
  | TextBlockContent
49
50
  | TileContent
50
51
  | NavigationContent
51
- | LinkListContent;
52
+ | LinkListContent
53
+ | GroupBlockContent;
@@ -27,6 +27,7 @@ import { StepsBlock } from './StepsBlock/StepsBlock';
27
27
  import { TariffsTable } from './TariffsTable/TariffsTable';
28
28
  import { TextBlock } from './TextBlock/TextBlock';
29
29
  import { Tile } from './Tile/Tile';
30
+ import { GroupBlock } from './GroupBlock/GroupBlock';
30
31
 
31
32
  export const Blocks = {
32
33
  Accordion,
@@ -58,4 +59,5 @@ export const Blocks = {
58
59
  Tile,
59
60
  Navigation,
60
61
  Placeholder,
62
+ GroupBlock,
61
63
  };
@@ -2,6 +2,7 @@ import { JSX, PropsWithChildren } from '@redneckz/uni-jsx';
2
2
  import type { BlockDef, ContentPageDef, UniBlockProps } from '../../types';
3
3
  import { changeHashOnScroll } from '../../utils/changeHashOnScroll';
4
4
  import { isSSR } from '../../utils/isSSR';
5
+ import { style2className } from '../../utils/style2className';
5
6
  import type { BlockContent } from '../BlockContent';
6
7
  import { LikeControl } from '../LikeControl/LikeControl';
7
8
  import { Placeholder } from '../Placeholder/Placeholder';
@@ -128,7 +129,3 @@ function renderBlock(
128
129
  `block-${i}`,
129
130
  );
130
131
  }
131
-
132
- function style2className(style: string[] | undefined | null): string {
133
- return style ? style.join(' ') : '';
134
- }
@@ -0,0 +1,82 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { ContentPageDef, CustomPageTemplate, UniBlockProps } from '../../types';
3
+ import { style2className } from '../../utils/style2className';
4
+ import { ContentPageContext } from './ContentPageContext';
5
+
6
+ interface PageDecoratorProps<VNode> {
7
+ pageClassName: string;
8
+ pageTemplate: CustomPageTemplate;
9
+ render: (props: { pageClassName: string; pageTemplate: CustomPageTemplate }) => VNode;
10
+ }
11
+
12
+ export type PageDecorator<VNode = any> = (
13
+ props: PageDecoratorProps<VNode>,
14
+ index?: number | string,
15
+ ) => any;
16
+
17
+ export interface PageTemplate {
18
+ name: string;
19
+ template: any;
20
+ }
21
+
22
+ export type PageTemplatesRegistry = Record<string, PageTemplate>;
23
+
24
+ export interface CustomContentPageProps extends UniBlockProps {
25
+ pageTemplatesRegistry: PageTemplatesRegistry;
26
+ data: ContentPageDef;
27
+ pageDecorator?: PageDecorator;
28
+ }
29
+
30
+ export interface RenderPageFunc {
31
+ pageTemplate: CustomPageTemplate;
32
+ pageClassName: string;
33
+ pageDecorator: PageDecorator;
34
+ pageTemplatesRegistry: PageTemplatesRegistry;
35
+ context: ContentPageContext;
36
+ }
37
+
38
+ const defaultPageDecorator: PageDecorator = ({ pageClassName, pageTemplate, render }) =>
39
+ render({ pageClassName, pageTemplate });
40
+
41
+ export const CustomContentPage = JSX<CustomContentPageProps>(
42
+ ({
43
+ className = '',
44
+ context,
45
+ pageTemplatesRegistry,
46
+ data: { style: pageStyle, customPageTmpl: pageTemplate },
47
+ pageDecorator = defaultPageDecorator,
48
+ }) => {
49
+ return pageTemplate
50
+ ? renderPage({
51
+ pageTemplate,
52
+ pageClassName: `${style2className(pageStyle)} ${className}`,
53
+ pageDecorator,
54
+ pageTemplatesRegistry,
55
+ context,
56
+ })
57
+ : null;
58
+ },
59
+ );
60
+
61
+ function renderPage({
62
+ pageTemplate,
63
+ pageClassName,
64
+ pageDecorator,
65
+ pageTemplatesRegistry,
66
+ context,
67
+ }: RenderPageFunc) {
68
+ const { type } = pageTemplate;
69
+ if (!(type && type in pageTemplatesRegistry) || !pageTemplatesRegistry[type].template) {
70
+ throw new Error(`No page template with "${type}" is registered`);
71
+ }
72
+
73
+ const { template: PageComponent } = pageTemplatesRegistry[type];
74
+ return pageDecorator({
75
+ pageClassName,
76
+ pageTemplate,
77
+ render: (props) => {
78
+ const { content } = props.pageTemplate;
79
+ return <PageComponent className={props.pageClassName} context={context} {...content} />;
80
+ },
81
+ });
82
+ }
@@ -0,0 +1,40 @@
1
+ import type { ProductBlockContent } from '../../components/ProductBlock/ProductBlockContent';
2
+ import type { ProductTileContent } from '../../components/ProductTile/ProductTileContent';
3
+ import { ContentPageContext } from '../../components/ContentPage/ContentPageContext';
4
+
5
+ export interface ActiveHandler {
6
+ context: ContentPageContext;
7
+ blocks?: GroupBlockDef[];
8
+ initialState?: boolean;
9
+ }
10
+
11
+ export interface GroupBlockCommonProps {
12
+ /** @title Стиль */
13
+ style?: string[];
14
+ /** @title Теги */
15
+ tags?: string[];
16
+ }
17
+
18
+ /**
19
+ * @title Продуктовый блок
20
+ * @default {"blockType": "ProductBlock"}
21
+ */
22
+ export type ProductBlockDef = ProductBlockContent &
23
+ GroupBlockCommonProps & { blockType: 'ProductBlock' };
24
+
25
+ /**
26
+ * @title Продуктовая плитка
27
+ * @default {"blockType": "ProductTile"}
28
+ */
29
+ export type ProductTileDef = ProductTileContent &
30
+ GroupBlockCommonProps & { blockType: 'ProductTile' };
31
+
32
+ /**
33
+ * @title Выберите блок
34
+ */
35
+ export type EmptyOption = null;
36
+
37
+ /**
38
+ * @title Содержимое блока
39
+ */
40
+ export type GroupBlockDef = EmptyOption | ProductBlockDef | ProductTileDef;
@@ -0,0 +1,7 @@
1
+ import { ProductBlock } from '../ProductBlock/ProductBlock';
2
+ import { ProductTile } from '../ProductTile/ProductTile';
3
+
4
+ export const EmbeddableGroupBlocks = {
5
+ ProductBlock,
6
+ ProductTile,
7
+ };
@@ -0,0 +1,27 @@
1
+ {
2
+ "tabs": [
3
+ { "title": "Еще программы", "index": 0 },
4
+ { "title": "Страхование жизни", "index": 1, "tag": "tag1" },
5
+ { "title": "Страхование здоровья", "index": 2, "tag": "tag2" }
6
+ ],
7
+ "blocks": [
8
+ {
9
+ "blockType": "ProductBlock",
10
+ "title": "Продуктовый блок",
11
+ "description": "Описание текстового блока",
12
+ "tags":["tag2"]
13
+ },
14
+ {
15
+ "blockType": "ProductTile",
16
+ "title": "Продуктовая плитка",
17
+ "description": "Описание текстового блока",
18
+ "tags":["tag1"]
19
+ },
20
+ {
21
+ "blockType": "ProductBlock",
22
+ "title": "Продуктовый блок",
23
+ "description": "Описание текстового блока",
24
+ "tags":["tag2"]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,51 @@
1
+ import { context } from '../../setup-fixture';
2
+ import { PRODUCT_TILE } from '../ProductTile/ProductTile.fixture';
3
+ import { PRODUCT_BLOCK } from '../ProductBlock/ProductBlock.fixture';
4
+ import { GroupBlock } from './GroupBlock';
5
+ import groupBlockExample from './GroupBlock.example.json';
6
+ import type { ProductTileDef, ProductBlockDef } from './BlocksTypeProps';
7
+
8
+ const PRODUCT_TILE_GROUP_BLOCK: ProductTileDef = {
9
+ blockType: 'ProductTile',
10
+ tags: ['tag2'],
11
+ style: ['col-span-6'],
12
+ ...PRODUCT_TILE,
13
+ };
14
+
15
+ const PRODUCT_TILE_GROUP_BLOCK2: ProductTileDef = {
16
+ blockType: 'ProductTile',
17
+ tags: ['tag2'],
18
+ style: ['col-span-6'],
19
+ ...PRODUCT_TILE,
20
+ };
21
+
22
+ const PRODUCT_BLOCK_GROUP_BLOCK: ProductBlockDef = {
23
+ blockType: 'ProductBlock',
24
+ tags: ['tag1'],
25
+ style: ['col-span-12'],
26
+ ...PRODUCT_BLOCK,
27
+ };
28
+
29
+ const PRODUCT_BLOCK_GROUP_BLOCK2: ProductBlockDef = {
30
+ blockType: 'ProductBlock',
31
+ style: ['col-span-12'],
32
+ ...PRODUCT_BLOCK,
33
+ };
34
+
35
+ export default {
36
+ default: (
37
+ <div className="container grid grid-cols-12">
38
+ <GroupBlock
39
+ context={context}
40
+ className="col-span-12"
41
+ tabs={groupBlockExample.tabs}
42
+ groupBlocks={[
43
+ PRODUCT_TILE_GROUP_BLOCK,
44
+ PRODUCT_TILE_GROUP_BLOCK2,
45
+ PRODUCT_BLOCK_GROUP_BLOCK,
46
+ PRODUCT_BLOCK_GROUP_BLOCK2,
47
+ ]}
48
+ />
49
+ </div>
50
+ ),
51
+ };
@@ -0,0 +1,43 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { UniBlockProps } from '../../types';
3
+ import type { GroupBlockContent, GroupBlockTab } from './GroupBlockContent';
4
+ import { GroupBlockTabs } from './GroupBlockTabs';
5
+ import { GroupBlocksItem } from './GroupBlocksItem';
6
+ import { filterBlocksByTag } from './filterBlocksByTag';
7
+
8
+ export interface TabsItemProps extends GroupBlockTab {
9
+ count?: number;
10
+ }
11
+
12
+ export interface GroupBlockProps extends GroupBlockContent, UniBlockProps {
13
+ tabs?: TabsItemProps[];
14
+ }
15
+
16
+ export const GroupBlock = JSX<GroupBlockProps>(
17
+ ({ className = '', tabs, context, anchor = null, groupBlocks = [] }) => {
18
+ const [currentTag, setCurrentTag] = context.useState(tabs?.[0]?.tag);
19
+
20
+ const filteredBlocks = filterBlocksByTag(groupBlocks, currentTag);
21
+
22
+ const tabsNewMap = tabs?.map((tab) => {
23
+ const count = tab.tag
24
+ ? groupBlocks.filter((block) => block?.tags?.includes(`${tab.tag}`)).length
25
+ : groupBlocks.length;
26
+
27
+ return { ...tab, count };
28
+ });
29
+
30
+ return (
31
+ <section id={anchor} className={`box-border gap-1 h-12 ${className}`}>
32
+ {tabsNewMap?.length ? (
33
+ <GroupBlockTabs currentTag={currentTag} onTabClick={setCurrentTag} tabs={tabsNewMap} />
34
+ ) : null}
35
+ {groupBlocks.length ? (
36
+ <div className="list-none">
37
+ <GroupBlocksItem context={context} groupBlocks={filteredBlocks} />
38
+ </div>
39
+ ) : null}
40
+ </section>
41
+ );
42
+ },
43
+ );
@@ -0,0 +1,23 @@
1
+ import type { GroupBlockDef } from './BlocksTypeProps';
2
+
3
+ /**
4
+ * @title Таб
5
+ */
6
+ export interface GroupBlockTab {
7
+ /** @title Название */
8
+ title?: string;
9
+ /** @title Tег */
10
+ tag?: string;
11
+ }
12
+
13
+ /**
14
+ * @title Блок-группировки
15
+ */
16
+ export interface GroupBlockContent {
17
+ /** @title Блоки */
18
+ groupBlocks?: GroupBlockDef[];
19
+ /** @title Табы */
20
+ tabs?: GroupBlockTab[];
21
+ /** @title Показывать счетчик блоков во вкладках */
22
+ isShowCounter?: boolean;
23
+ }
@@ -0,0 +1,54 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { TabsItemProps } from './GroupBlock';
3
+
4
+ export type TabClickHandler = (tag) => void;
5
+
6
+ export interface GroupBlockTabsProps {
7
+ onTabClick: TabClickHandler;
8
+ currentTag?: string;
9
+ className?: string;
10
+ tabs?: TabsItemProps[];
11
+ isShowCounter?: boolean;
12
+ }
13
+
14
+ export const GroupBlockTabs = JSX<GroupBlockTabsProps>((props) => {
15
+ const { tabs, currentTag, onTabClick, className = '', isShowCounter = true } = props;
16
+
17
+ return (
18
+ <div className={`mb-2 box-border flex gap-x-1 h-12 ${className}`} role="tablist">
19
+ {tabs?.map(renderTab(onTabClick, isShowCounter, currentTag))}
20
+ </div>
21
+ );
22
+ });
23
+
24
+ const badgeStyle = 'w-[22px] h-[22px] rounded-full text-m-sm';
25
+
26
+ const renderTab =
27
+ (onTabClick: TabClickHandler, isShowCounter: boolean, currentTag?: string) =>
28
+ (tab: TabsItemProps, i: number) => {
29
+ const isActive = currentTag === tab.tag;
30
+ const tabBg = isActive ? 'bg-primary-main' : 'group bg-white';
31
+ const tabText = isActive ? 'text-white' : 'text-secondary-text group-hover:text-primary-main';
32
+ const counterBlockStyle = `${badgeStyle}
33
+ ${isActive ? 'bg-white/30 text-white' : 'bg-secondary-text/10 text-secondary-text'}`;
34
+
35
+ return (
36
+ <div
37
+ key={String(i)}
38
+ className={`flex h-full w-full flex-1 cursor-pointer mr-2 last:mr-0 box-content ${tabBg}`}
39
+ role="tab"
40
+ onClick={() => onTabClick(tab.tag)}
41
+ aria-selected={String(isActive)}
42
+ tag={tab?.tag}
43
+ >
44
+ <div className="flex flex-1 items-center justify-center">
45
+ {tab?.title ? <h3 className={`mr-8 ${tabText}`}>{tab?.title}</h3> : null}
46
+ {isShowCounter ? (
47
+ <div className={`flex items-center justify-center ${counterBlockStyle}`}>
48
+ <span>{tab.count}</span>
49
+ </div>
50
+ ) : null}
51
+ </div>
52
+ </div>
53
+ );
54
+ };
@@ -0,0 +1,30 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { JSXBlock } from '../../components/ContentPage/ContentPage';
3
+ import type { ContentPageContext } from '../../components/ContentPage/ContentPageContext';
4
+ import type { UniBlockProps } from '../../types';
5
+ import { style2className } from '../../utils/style2className';
6
+ import type { GroupBlockDef } from './BlocksTypeProps';
7
+ import { EmbeddableGroupBlocks } from './EmbeddableGroupBlocks';
8
+ import { GroupBlockContent } from './GroupBlockContent';
9
+
10
+ export interface GroupBlocksProps extends GroupBlockContent, UniBlockProps {}
11
+
12
+ export const GroupBlocksItem = JSX<GroupBlocksProps>(({ groupBlocks, context }) => {
13
+ return (
14
+ <div className={'grid grid-cols-12 gap-2 box-border'}>
15
+ {groupBlocks?.length ? groupBlocks.map(renderBlock(context)) : null}
16
+ </div>
17
+ );
18
+ });
19
+
20
+ export const renderBlock = (context: ContentPageContext) => (block: GroupBlockDef, i: number) => {
21
+ const type = block?.blockType;
22
+ if (!type || !(type in EmbeddableGroupBlocks)) {
23
+ return null;
24
+ }
25
+ const classNameBlock = style2className(block?.style);
26
+ const EmbeddedBlock: JSXBlock = EmbeddableGroupBlocks[type];
27
+ return (
28
+ <EmbeddedBlock key={`block_${i}`} context={context} {...block} className={classNameBlock} />
29
+ );
30
+ };
@@ -0,0 +1,5 @@
1
+ import { GroupBlockDef } from './BlocksTypeProps';
2
+
3
+ export const filterBlocksByTag = (blocks: GroupBlockDef[], tag?: string) => {
4
+ return tag ? blocks.filter((block) => block?.tags?.includes(tag)) : blocks;
5
+ };
@@ -0,0 +1,27 @@
1
+ import type { JSXBlock } from '../../components/ContentPage/ContentPage';
2
+ import type { ContentPageContext } from '../../components/ContentPage/ContentPageContext';
3
+ import type { GroupBlockDef } from './BlocksTypeProps';
4
+ import { EmbeddableGroupBlocks } from './EmbeddableGroupBlocks';
5
+ import { style2className } from '../../utils/style2className';
6
+
7
+ type EmbeddableBlocksProps = {
8
+ groupBlocks?: GroupBlockDef[];
9
+ context: ContentPageContext;
10
+ className?: string;
11
+ };
12
+
13
+ export const renderBlock =
14
+ ({ context, className }: EmbeddableBlocksProps) =>
15
+ (block: GroupBlockDef, i: number) => {
16
+ const type = block?.blockType;
17
+ if (!type || !(type in EmbeddableGroupBlocks)) {
18
+ return null;
19
+ }
20
+ const classNameBlock = style2className(block?.style);
21
+ const EmbeddedBlock: JSXBlock = EmbeddableGroupBlocks[type];
22
+ return (
23
+ <div className={className} key={`block_${i}`}>
24
+ <EmbeddedBlock context={context} {...block} className={classNameBlock} />
25
+ </div>
26
+ );
27
+ };
@@ -14,7 +14,10 @@ export interface BlockItemCommonProps {
14
14
  * @title Отображать в раскрытом виде
15
15
  */
16
16
  isExpanded?: boolean;
17
- /** @title Блоки */
17
+ /**
18
+ * @title Блоки
19
+ * @maxItems 10
20
+ */
18
21
  blocks?: BlockDef[];
19
22
  columns?: ColumnsCount;
20
23
  }
@@ -27,7 +30,6 @@ export interface OtherProductsContent {
27
30
  title?: string;
28
31
  /**
29
32
  * @title Список
30
- * @maxItems 10
31
33
  */
32
34
  blockItems?: BlockItemCommonProps[];
33
35
  colorPalette?: ColorPalette;
@@ -60,7 +60,7 @@ export const ProductBlockInner = JSX<ProductBlockInnerProps>(
60
60
  ) : null}
61
61
  </BaseTile>
62
62
  </div>
63
- {image?.src && <Img className="mt-auto" image={image} />}
63
+ {image?.src && <Img className="mt-[-50px]" image={image} />}
64
64
  </div>
65
65
  );
66
66
  },