@redneckz/wildless-cms-uni-blocks 0.14.57 → 0.14.59

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 (142) hide show
  1. package/bundle/blocks.schema.json +1 -1
  2. package/bundle/bundle.umd.js +494 -479
  3. package/bundle/bundle.umd.min.js +1 -1
  4. package/bundle/components/AdTile/AdTile.d.ts +6 -0
  5. package/bundle/components/AdTile/AdTileContent.d.ts +5 -0
  6. package/bundle/components/AdTile/useAdTile.d.ts +2 -0
  7. package/bundle/components/ComparisonTable/TableCell.d.ts +1 -1
  8. package/bundle/components/ComparisonTable/TableCell.mobile.d.ts +1 -1
  9. package/bundle/components/ComparisonTable/TableColumn.d.ts +1 -1
  10. package/bundle/model/ContentPageDef.d.ts +1 -0
  11. package/bundle/utils/isOdd.d.ts +1 -0
  12. package/dist/components/AdTile/AdTile.d.ts +6 -0
  13. package/dist/components/AdTile/AdTile.js +12 -0
  14. package/dist/components/AdTile/AdTile.js.map +1 -0
  15. package/dist/components/AdTile/AdTileContent.d.ts +5 -0
  16. package/dist/components/AdTile/AdTileContent.js +2 -0
  17. package/dist/components/AdTile/AdTileContent.js.map +1 -0
  18. package/dist/components/AdTile/useAdTile.d.ts +2 -0
  19. package/dist/components/AdTile/useAdTile.js +12 -0
  20. package/dist/components/AdTile/useAdTile.js.map +1 -0
  21. package/dist/components/Blocks.js +4 -2
  22. package/dist/components/Blocks.js.map +1 -1
  23. package/dist/components/Blocks.mobile.js +2 -0
  24. package/dist/components/Blocks.mobile.js.map +1 -1
  25. package/dist/components/ComparisonTable/TableCell.d.ts +1 -1
  26. package/dist/components/ComparisonTable/TableCell.js +1 -1
  27. package/dist/components/ComparisonTable/TableCell.js.map +1 -1
  28. package/dist/components/ComparisonTable/TableCell.mobile.d.ts +1 -1
  29. package/dist/components/ComparisonTable/TableCell.mobile.js +1 -1
  30. package/dist/components/ComparisonTable/TableCell.mobile.js.map +1 -1
  31. package/dist/components/ComparisonTable/TableColumn.d.ts +1 -1
  32. package/dist/model/ContentPageDef.d.ts +1 -0
  33. package/dist/ui-kit/BaseFiltration/BaseFiltrationInner.js +4 -2
  34. package/dist/ui-kit/BaseFiltration/BaseFiltrationInner.js.map +1 -1
  35. package/dist/utils/isOdd.d.ts +1 -0
  36. package/dist/utils/isOdd.js +5 -0
  37. package/dist/utils/isOdd.js.map +1 -0
  38. package/lib/components/AdTile/AdTile.d.ts +6 -0
  39. package/lib/components/AdTile/AdTile.fixture.d.ts +6 -0
  40. package/lib/components/AdTile/AdTile.js +10 -0
  41. package/lib/components/AdTile/AdTile.js.map +1 -0
  42. package/lib/components/AdTile/AdTileContent.d.ts +5 -0
  43. package/lib/components/AdTile/AdTileContent.js +2 -0
  44. package/lib/components/AdTile/AdTileContent.js.map +1 -0
  45. package/lib/components/AdTile/useAdTile.d.ts +2 -0
  46. package/lib/components/AdTile/useAdTile.js +9 -0
  47. package/lib/components/AdTile/useAdTile.js.map +1 -0
  48. package/lib/components/Blocks.js +4 -2
  49. package/lib/components/Blocks.js.map +1 -1
  50. package/lib/components/Blocks.mobile.js +2 -0
  51. package/lib/components/Blocks.mobile.js.map +1 -1
  52. package/lib/components/ComparisonTable/TableCell.d.ts +1 -1
  53. package/lib/components/ComparisonTable/TableCell.js +1 -1
  54. package/lib/components/ComparisonTable/TableCell.js.map +1 -1
  55. package/lib/components/ComparisonTable/TableCell.mobile.d.ts +1 -1
  56. package/lib/components/ComparisonTable/TableCell.mobile.js +1 -1
  57. package/lib/components/ComparisonTable/TableCell.mobile.js.map +1 -1
  58. package/lib/components/ComparisonTable/TableColumn.d.ts +1 -1
  59. package/lib/model/ContentPageDef.d.ts +1 -0
  60. package/lib/ui-kit/BaseFiltration/BaseFiltrationInner.js +4 -2
  61. package/lib/ui-kit/BaseFiltration/BaseFiltrationInner.js.map +1 -1
  62. package/lib/utils/isOdd.d.ts +1 -0
  63. package/lib/utils/isOdd.js +2 -0
  64. package/lib/utils/isOdd.js.map +1 -0
  65. package/mobile/bundle/bundle.umd.js +451 -436
  66. package/mobile/bundle/bundle.umd.min.js +1 -1
  67. package/mobile/bundle/components/AdTile/AdTile.d.ts +6 -0
  68. package/mobile/bundle/components/AdTile/AdTileContent.d.ts +5 -0
  69. package/mobile/bundle/components/AdTile/useAdTile.d.ts +2 -0
  70. package/mobile/bundle/components/ComparisonTable/TableCell.d.ts +1 -1
  71. package/mobile/bundle/components/ComparisonTable/TableColumn.d.ts +1 -1
  72. package/mobile/bundle/model/ContentPageDef.d.ts +1 -0
  73. package/mobile/bundle/utils/isOdd.d.ts +1 -0
  74. package/mobile/dist/components/AdTile/AdTile.d.ts +6 -0
  75. package/mobile/dist/components/AdTile/AdTile.js +12 -0
  76. package/mobile/dist/components/AdTile/AdTile.js.map +1 -0
  77. package/mobile/dist/components/AdTile/AdTileContent.d.ts +5 -0
  78. package/mobile/dist/components/AdTile/AdTileContent.js +2 -0
  79. package/mobile/dist/components/AdTile/AdTileContent.js.map +1 -0
  80. package/mobile/dist/components/AdTile/useAdTile.d.ts +2 -0
  81. package/mobile/dist/components/AdTile/useAdTile.js +12 -0
  82. package/mobile/dist/components/AdTile/useAdTile.js.map +1 -0
  83. package/mobile/dist/components/Blocks.js +2 -0
  84. package/mobile/dist/components/Blocks.js.map +1 -1
  85. package/mobile/dist/components/ComparisonTable/TableCell.d.ts +1 -1
  86. package/mobile/dist/components/ComparisonTable/TableCell.js +1 -1
  87. package/mobile/dist/components/ComparisonTable/TableCell.js.map +1 -1
  88. package/mobile/dist/components/ComparisonTable/TableColumn.d.ts +1 -1
  89. package/mobile/dist/model/ContentPageDef.d.ts +1 -0
  90. package/mobile/dist/ui-kit/BaseFiltration/BaseFiltrationInner.js +4 -2
  91. package/mobile/dist/ui-kit/BaseFiltration/BaseFiltrationInner.js.map +1 -1
  92. package/mobile/dist/utils/isOdd.d.ts +1 -0
  93. package/mobile/dist/utils/isOdd.js +5 -0
  94. package/mobile/dist/utils/isOdd.js.map +1 -0
  95. package/mobile/lib/common.css +1 -1
  96. package/mobile/lib/components/AdTile/AdTile.d.ts +6 -0
  97. package/mobile/lib/components/AdTile/AdTile.js +10 -0
  98. package/mobile/lib/components/AdTile/AdTile.js.map +1 -0
  99. package/mobile/lib/components/AdTile/AdTileContent.d.ts +5 -0
  100. package/mobile/lib/components/AdTile/AdTileContent.js +2 -0
  101. package/mobile/lib/components/AdTile/AdTileContent.js.map +1 -0
  102. package/mobile/lib/components/AdTile/useAdTile.d.ts +2 -0
  103. package/mobile/lib/components/AdTile/useAdTile.js +9 -0
  104. package/mobile/lib/components/AdTile/useAdTile.js.map +1 -0
  105. package/mobile/lib/components/Blocks.js +2 -0
  106. package/mobile/lib/components/Blocks.js.map +1 -1
  107. package/mobile/lib/components/ComparisonTable/TableCell.d.ts +1 -1
  108. package/mobile/lib/components/ComparisonTable/TableCell.js +1 -1
  109. package/mobile/lib/components/ComparisonTable/TableCell.js.map +1 -1
  110. package/mobile/lib/components/ComparisonTable/TableColumn.d.ts +1 -1
  111. package/mobile/lib/model/ContentPageDef.d.ts +1 -0
  112. package/mobile/lib/ui-kit/BaseFiltration/BaseFiltrationInner.js +4 -2
  113. package/mobile/lib/ui-kit/BaseFiltration/BaseFiltrationInner.js.map +1 -1
  114. package/mobile/lib/utils/isOdd.d.ts +1 -0
  115. package/mobile/lib/utils/isOdd.js +2 -0
  116. package/mobile/lib/utils/isOdd.js.map +1 -0
  117. package/mobile/src/components/AdTile/AdTile.example.json +1 -0
  118. package/mobile/src/components/AdTile/AdTile.tsx +18 -0
  119. package/mobile/src/components/AdTile/AdTile.ui.json +1 -0
  120. package/mobile/src/components/AdTile/AdTileContent.ts +6 -0
  121. package/mobile/src/components/AdTile/useAdTile.ts +17 -0
  122. package/mobile/src/components/Blocks.ts +3 -0
  123. package/mobile/src/components/ComparisonTable/TableCell.tsx +2 -2
  124. package/mobile/src/components/ComparisonTable/TableColumn.tsx +1 -1
  125. package/mobile/src/model/ContentPageDef.ts +1 -0
  126. package/mobile/src/ui-kit/BaseFiltration/BaseFiltrationInner.tsx +4 -0
  127. package/mobile/src/utils/isOdd.ts +1 -0
  128. package/package.json +1 -1
  129. package/src/components/AdTile/AdTile.example.json +1 -0
  130. package/src/components/AdTile/AdTile.fixture.tsx +11 -0
  131. package/src/components/AdTile/AdTile.tsx +18 -0
  132. package/src/components/AdTile/AdTile.ui.json +1 -0
  133. package/src/components/AdTile/AdTileContent.ts +6 -0
  134. package/src/components/AdTile/useAdTile.ts +17 -0
  135. package/src/components/Blocks.mobile.ts +3 -0
  136. package/src/components/Blocks.ts +5 -2
  137. package/src/components/ComparisonTable/TableCell.mobile.tsx +2 -2
  138. package/src/components/ComparisonTable/TableCell.tsx +2 -2
  139. package/src/components/ComparisonTable/TableColumn.tsx +1 -1
  140. package/src/model/ContentPageDef.ts +1 -0
  141. package/src/ui-kit/BaseFiltration/BaseFiltrationInner.tsx +4 -0
  142. package/src/utils/isOdd.ts +1 -0
@@ -243,30 +243,10 @@
243
243
  return JSXTmpl;
244
244
  };
245
245
 
246
- function LeadServiceAPI() {
247
- async function send(body, isIndividualType) {
248
- const url = isIndividualType ? '/api/v1/lead' : '/api/v1/sendcorporatelead';
249
- try {
250
- const response = await fetch(url, {
251
- method: 'POST',
252
- headers: { 'Content-Type': 'application/json' },
253
- mode: 'cors',
254
- body: JSON.stringify(body),
255
- });
256
- if (!response?.ok) {
257
- return null;
258
- }
259
- const data = await response.json();
260
- return data;
261
- }
262
- catch (e) {
263
- return null;
264
- }
265
- }
266
- return {
267
- send,
268
- };
269
- }
246
+ const isSSR = () => Boolean(typeof globalThis.process === 'object' && globalThis.process && globalThis.process.version);
247
+
248
+ const isClient = !isSSR();
249
+ const ClientOnly = JSX(({ children }) => (isClient ? children : null));
270
250
 
271
251
  class EventBus {
272
252
  subscribers = {};
@@ -374,154 +354,52 @@
374
354
  return (jsx(Tag, { className: style('font-sans m-0', styles$3[headingType], className), children: title || children }));
375
355
  });
376
356
 
377
- const identity = (_) => _;
378
-
379
- const useForm = (initialState, onSubmit) => {
380
- const [formState, setFormState] = useState(initialState);
381
- const [isDirtyForm, setDirtyForm] = useState(false);
382
- const [dirtyFieldsMap, setDirtyFieldsMap] = useState({});
383
- const handlersMap = useRef({});
384
- const field = useCallback((fieldName, options) => {
385
- const { parse = identity, format = identity } = options || {};
386
- if (!handlersMap.current) {
387
- handlersMap.current = {};
388
- }
389
- handlersMap.current[fieldName] ||= (value) => {
390
- setFormState((prev) => ({ ...prev, [fieldName]: parse(value) }));
391
- setDirtyFieldsMap((prev) => ({ ...prev, [fieldName]: true }));
392
- };
393
- return {
394
- value: format(formState[fieldName]),
395
- isDirty: isDirtyForm || dirtyFieldsMap[fieldName],
396
- onChange: handlersMap.current[fieldName],
397
- };
398
- }, [formState, isDirtyForm, dirtyFieldsMap]);
399
- const update = useCallback((_) => {
400
- setFormState(_);
401
- setDirtyFieldsMap(_);
402
- }, []);
403
- const reset = useCallback(() => {
404
- setFormState(initialState);
405
- setDirtyForm(false);
406
- setDirtyFieldsMap({});
407
- }, [initialState]);
408
- const handleSubmit = useCallback((e) => {
409
- e.preventDefault();
410
- setDirtyForm(true);
411
- onSubmit && onSubmit(formState);
412
- }, [onSubmit, formState]);
413
- return [
414
- formState,
415
- {
416
- isDirty: isDirtyForm || Object.values(dirtyFieldsMap).some(Boolean),
417
- field,
418
- update,
419
- reset,
420
- onSubmit: handleSubmit,
421
- },
422
- ];
423
- };
424
-
425
- const objectValidator = (validatorsMap) => (o) => (o &&
426
- Object.entries(validatorsMap).flatMap(([key, validator]) => validator(o[key]))) ||
427
- [];
428
-
429
- const isValidationSuccess = (info) => !info?.length;
430
- const validator = (predicate) => (message) => (_) => predicate(_) ? [] : [message];
431
-
432
- const isFilled = (_) => _ !== null && _ !== undefined;
357
+ const Paragraph = JSX(({ children, ...styleProps }) => (jsx("p", { className: style('font-sans', Object.values(styleProps)), children: children })));
433
358
 
434
- const defaultCache = new Map();
435
- const applyCache = (fetcher, cache = defaultCache) => (key) => {
436
- const cachedData = cache.get(key);
437
- if (isFilled(cachedData)) {
438
- return cachedData;
439
- }
440
- const data = fetcher(key);
441
- if (isFilled(data)) {
442
- cache.set(key, Promise.resolve(data));
443
- }
444
- else {
445
- cache.delete(key);
446
- }
447
- return data;
359
+ const headlineVersionStyles = {
360
+ XXL: {
361
+ title: { headingType: 'h0', as: 'h1' },
362
+ descriptionSize: 'text-h5',
363
+ descriptionWeight: 'font-normal',
364
+ descriptionStyle: 'mt-xl',
365
+ },
366
+ XL: {
367
+ title: { headingType: 'h1', as: 'h1' },
368
+ descriptionSize: 'text-xl',
369
+ descriptionWeight: 'font-light',
370
+ descriptionStyle: 'mt-m',
371
+ },
372
+ L: {
373
+ title: { headingType: 'h2', as: 'h2' },
374
+ descriptionSize: 'text-xl',
375
+ descriptionWeight: 'font-light',
376
+ descriptionStyle: 'mt-m',
377
+ },
378
+ M: {
379
+ title: { headingType: 'h3', as: 'h2' },
380
+ descriptionSize: 'text-xl',
381
+ descriptionWeight: 'font-light',
382
+ descriptionStyle: 'mt-s',
383
+ },
384
+ S: {
385
+ title: { headingType: 'h4', as: 'h2' },
386
+ descriptionSize: 'text-xl',
387
+ descriptionWeight: 'font-light',
388
+ descriptionStyle: 'mt-xs',
389
+ },
390
+ XS: {
391
+ title: { headingType: 'h5', as: 'h2' },
392
+ descriptionSize: 'text-m',
393
+ descriptionWeight: 'font-light',
394
+ descriptionStyle: 'mt-xs',
395
+ },
448
396
  };
449
397
 
450
- const isSimpleKey = (args) => Boolean(args && Array.isArray(args) && args.length === 1 && typeof args[0] === 'string');
451
- function useAsyncData(key, fetcher, { fallback, cache } = {}) {
452
- const args = useMemo(() => keyToArgs(key), [key]);
453
- const [simpleKey] = isSimpleKey(args) ? args : [];
454
- const [data, setData] = useState(undefined);
455
- const [error, setError] = useState(undefined);
456
- useEffect(() => {
457
- const isEmptyKey = !args.some(isFilled);
458
- if (isEmptyKey) {
459
- return;
460
- }
461
- let canceled = false;
462
- const setResult = (newData, err) => {
463
- if (!canceled) {
464
- setData(newData);
465
- setError(err);
466
- }
467
- };
468
- (async () => {
469
- try {
470
- setResult(await (simpleKey ? applyCache(fetcher, cache)(simpleKey) : fetcher(...args)));
471
- }
472
- catch (err) {
473
- setResult(undefined, err);
474
- }
475
- })();
476
- return () => {
477
- canceled = true;
478
- };
479
- }, [fetcher, cache, args]);
480
- const fallbackData = fallback && simpleKey && fallback[simpleKey];
481
- return {
482
- data: !data && fallbackData ? fallbackData : data,
483
- error,
484
- mutate: () => Promise.resolve(undefined) // TODO Clean up cache
485
- };
486
- }
487
- function keyToArgs(key) {
488
- if (Array.isArray(key)) {
489
- return key;
490
- }
491
- else if (key instanceof Function) {
492
- return keyToArgs(key());
493
- }
494
- else {
495
- return [key];
496
- }
497
- }
498
-
499
- async function fetchJSON(url, options) {
500
- try {
501
- return url ? await fetchJSONUnsafe(url, options) : null;
502
- }
503
- catch (err) {
504
- console.error(err);
505
- }
506
- return null;
507
- }
508
- async function fetchJSONUnsafe(url, options) {
509
- const response = await fetch(url, {
510
- ...options,
511
- headers: {
512
- ...options?.headers,
513
- 'Content-Type': 'application/json',
514
- },
515
- });
516
- return response.json();
517
- }
518
-
519
- const REGIONS_URL$1 = '/api/v1/regions';
520
- const EMPTY_VALUE$5 = [];
521
- function useGetRegions() {
522
- const { data } = useAsyncData(REGIONS_URL$1, fetchJSONUnsafe);
523
- return data || EMPTY_VALUE$5;
524
- }
398
+ const Headline = JSX(({ className, version = '', headlineVersion = 'XL', title, description, align = 'text-center', as, isEmbedded = false, isTheme = false, ...rest }) => {
399
+ const versionStyle = headlineVersionStyles[headlineVersion];
400
+ const descriptionStyle = { marginTop: versionStyle.descriptionStyle };
401
+ return (jsxs(BlockWrapper, { className: style(isEmbedded ? '@container-normal' : '', className), defaultPadding: isEmbedded ? '' : 'p-6xl', version: version, isTheme: isTheme, ...rest, children: [title ? (jsx(Heading, { className: style('whitespace-pre-wrap', align), ...versionStyle?.title, as: as || versionStyle?.title.as, title: title })) : null, description ? (jsx(Paragraph, { size: versionStyle.descriptionSize, font: versionStyle.descriptionWeight, align: align, ...descriptionStyle, children: description })) : null] }));
402
+ });
525
403
 
526
404
  const useDialogManager = () => ({
527
405
  open: (dialog, options = {}) => defaultEventBus.fire('dialog', { type: 'open', dialog, ...options }),
@@ -702,28 +580,416 @@
702
580
  const RegularButton = JSX(({ className = '', href, rel, target, ariaLabel, version, rounded, onClick, children }) => (jsx("a", { className: getRegularButtonClasses({ className, version, rounded }), href: href, rel: rel, target: target, "aria-label": ariaLabel, role: href ? 'link' : 'button', onClick: onClick, children: children })));
703
581
  const DisabledButton = JSX(({ className, ariaLabel, version, rounded, children }) => (jsx("div", { role: "button", "aria-disabled": "true", "aria-label": ariaLabel, tabIndex: -1, className: getDisabledButtonClasses({ className, rounded, version }), children: children })));
704
582
 
705
- const Paragraph = JSX(({ children, ...styleProps }) => (jsx("p", { className: style('font-sans', Object.values(styleProps)), children: children })));
706
-
707
- const Text = JSX(({ children, ...styleProps }) => (jsx("span", { className: style('font-sans', Object.values(styleProps)), children: children })));
708
-
709
- const Footnote = JSX(({ text, link }) => (jsxs(Paragraph, { size: "text-s", font: "font-light", color: "text-secondary-text", children: [jsx(Text, { children: text || 'Нажимая кнопку, вы подтверждаете согласие с ' }), link ? (jsx(Button, { href: link.href, ariaLabel: "\u0443\u0441\u043B\u043E\u0432\u0438\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043D\u043D\u044B\u0445", target: link.target, className: "text-primary-main", children: jsx(Text, { children: link.text }) })) : null] })));
583
+ const isOnlyDigits = (str) => str && !/\D/.test(str);
710
584
 
711
- const withValidator = (props, validator) => {
712
- const { value, isDirty } = props;
713
- const errors = isDirty ? validator(value) : [];
714
- return {
715
- ...props,
716
- errors,
717
- error: errors[0],
718
- };
585
+ const svgUseStyleMap = {
586
+ normal: '',
587
+ color: 'text-primary-main',
588
+ black: 'text-black',
589
+ white: 'text-black',
590
+ };
591
+ const Icon = JSX(({ className = '', imageClassName = '', name = '', alt = `Иконка ${name}`, title = alt, iconVersion = 'color', width, height, }) => {
592
+ const router = useRouter();
593
+ const href = adjustHref(router)(joinPath(projectSettings.CDN, '/icons', `${name}.svg`));
594
+ if (iconVersion !== 'normal') {
595
+ return (jsx(Background, { className: className, children: jsxs("svg", { className: style(getSvgSize(width), svgUseStyleMap[iconVersion], iconVersion === 'white' ? 'invert' : '', imageClassName), width: width, height: height, "aria-hidden": "true", children: [title ? jsx("title", { children: title }) : null, alt ? jsx("desc", { children: alt }) : null, jsx("use", { href: `${href}#icon`, xlinkHref: `${href}#icon` })] }) }));
596
+ }
597
+ return (jsx("img", { className: className, src: href, alt: alt, title: title, "aria-hidden": "true", width: width, height: height, style: getInlineStyle(className, height) }));
598
+ });
599
+ const getInlineStyle = (className, height) => {
600
+ if (className?.includes('h-')) {
601
+ return {};
602
+ }
603
+ return { height: isOnlyDigits(height) ? `${height}px` : height, width: 'auto' };
719
604
  };
605
+ const getSvgSize = (width) => (width ? '' : 'w-full h-full');
606
+ const Background = JSX(({ className, children }) => className ? jsx("div", { className: className, children: children }) : children);
720
607
 
721
- const Input = JSX(({ key, className = '', inputClassName = '', id, name, type = 'text', label, placeholder, value = '', valid = true, children, onChange, onFocus, onBlur, pattern, autoFocus = false, }) => {
722
- const inputRef = useRef(null);
723
- const handleChange = useCallback((e) => {
724
- onChange && onChange(e.target?.value || '');
725
- }, [onChange]);
726
- useEffect(() => {
608
+ const sourcesComparator = (a, b) => a?.media && b?.media ? a.media - b.media : 0;
609
+ const ImgAsPicture = JSX(({ className = '', image, imageClassName = '', pathPrefix }) => {
610
+ const router = useRouter();
611
+ return (jsxs("picture", { className: className, children: [image?.sources?.length
612
+ ? image.sources
613
+ .filter((_) => _?.src)
614
+ .sort(sourcesComparator)
615
+ .map(({ src, format, media }, index) => (jsx("source", { srcSet: adjustSrc(router, pathPrefix)(src), type: formatToMimeType(format), media: media ? `(max-width: ${media}px)` : '', width: image.size?.width, height: image.size?.height }, `${index}_${src}`)))
616
+ : null, image?.src
617
+ ? renderImg({ ...image, src: adjustSrc(router, pathPrefix)(image.src) }, imageClassName)
618
+ : null] }));
619
+ });
620
+ const renderImg = (image, imageClassName = '') => (jsx("img", { src: image.src, className: style('object-contain', imageClassName), alt: image.alt || image.title, title: image.title || '', style: {
621
+ width: image.size?.width ? `${image.size?.width}px` : '100%',
622
+ height: image.size?.height ? `${image.size?.height}px` : 'auto',
623
+ }, width: image.size?.width, height: image.size?.height }));
624
+ const adjustSrc = (router, pathPrefix) => (src) => src && !isURL(src) ? adjustHref(router)(joinPath(pathPrefix, src)) : src;
625
+ const formatToMimeType = (format) => format ? `image/${String(format)}` : undefined;
626
+
627
+ const Img = JSX(({ className = '', image, imageClassName = '', pathPrefix, ...iconProps }) => {
628
+ if (!image?.src && !image?.icon) {
629
+ return null;
630
+ }
631
+ return image.icon ? (jsx(Icon, { className: className, imageClassName: imageClassName, iconVersion: image?.iconVersion, name: image.icon, ...iconProps })) : (jsx(ImgAsPicture, { className: className, imageClassName: imageClassName, image: image, pathPrefix: pathPrefix }));
632
+ });
633
+
634
+ function renderBackwardButton(version, handleClick) {
635
+ const iconVersion = version === 'primary' ? 'white' : 'black';
636
+ const className = 'w-12 h-12 min-h-12 min-w-12 flex items-center justify-center';
637
+ const text = 'Вернуться назад';
638
+ return (jsxs("div", { className: "hidden sm:flex items-center gap-s", children: [jsx("div", { className: getRegularButtonClasses({ className, version, rounded: true }), onClick: handleClick, children: jsx(Img, { className: "w-4 h-4", image: {
639
+ icon: 'ArrowLeftIcon',
640
+ iconVersion: iconVersion,
641
+ } }) }), jsx(Button, { version: "link", className: "group-data-secondary:text-white/80", text: text, ariaLabel: text, onClick: handleClick })] }));
642
+ }
643
+
644
+ const imageAlignmentMap = {
645
+ start: '@xl:self-start',
646
+ center: '@xl:self-center',
647
+ end: '@xl:self-end',
648
+ };
649
+ const BaseTile = JSX(({ className, version = 'primary', defaultPadding, padding, title = '', insetTitle = '', buttons, leftImage, rightImage, imageAlign, isImageAlwaysOnRight = false, isImageSecondary = false, backwardButton, children, }) => {
650
+ const router = useRouter();
651
+ const handleClick = useCallback((ev) => {
652
+ ev?.preventDefault();
653
+ router.back();
654
+ }, []);
655
+ return (jsxs("div", { className: getStyle(padding, defaultPadding, className), children: [backwardButton ? renderBackwardButton(version, handleClick) : null, title ? jsx("div", { className: "relative", children: title }) : null, jsxs("div", { className: style('grow relative flex flex-col @xl:flex-row gap-3xl w-full', leftImage ? 'self-start @xl:w-auto' : ''), children: [renderImageContainer(leftImage, { imageAlign, className: 'mx-auto' }), jsxs("div", { className: style('grid gap-3xl h-full', rightImage ? '@xl:grid-cols-2' : '', leftImage ? '' : 'grow'), children: [jsxs("div", { className: "grow space-y-lg min-w-fit", children: [insetTitle, children] }), renderImageContainer(rightImage, {
656
+ className: style('@xl:justify-self-end @xl:col-start-2', buttons ? rowSpanStyle(isImageAlwaysOnRight) : '', positionStyle(isImageAlwaysOnRight), imageSecondaryStyle(isImageSecondary)),
657
+ imageAlign,
658
+ }), renderButtons(buttons)] })] })] }));
659
+ });
660
+ const getStyle = (padding = '', defaultPadding = '', className = '') => style('relative flex flex-col gap-3xl overflow-hidden', padding || defaultPadding, className);
661
+ const rowSpanStyle = (isImageAlwaysOnRight) => isImageAlwaysOnRight ? 'row-span-2' : '@xl:row-span-2';
662
+ const positionStyle = (isImageAlwaysOnRight) => isImageAlwaysOnRight ? 'col-start-2 self-center' : '';
663
+ const renderButtons = (buttons) => buttons ? jsx("div", { className: "self-end", children: buttons }) : null;
664
+ const renderImageContainer = (image, { className, imageAlign }) => image ? (jsx("div", { className: style('shrink-1/2 justify-self-center', imageAlign && imageAlignmentMap[imageAlign], className), children: image })) : null;
665
+ const imageSecondaryStyle = (isImageSecondary) => isImageSecondary ? 'hidden @xl:block' : '';
666
+
667
+ const sum = (list = []) => list.reduce((a, b) => a + b, 0);
668
+
669
+ const avg = (items = []) => (items?.length ? sum(items) / items.length : 0);
670
+
671
+ const deviation = (items) => items?.length ? Math.sqrt(Math.abs(avg(items.map((_) => _ ** 2)) - avg(items) ** 2)) : 0;
672
+
673
+ const renderBenefitIcon = (icon, benefitsVersion = 'normal') => icon ? (jsx("div", { className: style('sm:w-12 sm:h-12 sm:min-w-12 w-11 h-11 min-w-11 box-border flex items-center justify-center rounded-icon', benefitsVersion === 'normal'
674
+ ? 'bg-secondary-light text-primary-main'
675
+ : 'bg-primary-main text-black group-data-secondary:bg-white/30 group-data-secondary:text-black'), children: jsx(Img, { className: "w-6 h-6", image: { ...icon, iconVersion: icon.iconVersion || benefitsVersion } }) })) : null;
676
+
677
+ const getHtmlText = (html) => html.replace(/<\/?[^>]+\/?>/g, '').trim();
678
+
679
+ const RichText = JSX((props) => {
680
+ const { __html = '', richVersion = '' } = props;
681
+ return getHtmlText(__html) ? (jsx("div", { className: style(richVersion, 'md-container'), dangerouslySetInnerHTML: { __html } })) : null;
682
+ });
683
+
684
+ const renderBenefitDescription = (description, i) => description ? (jsx(Paragraph, { font: "font-light", size: "text-m", color: "text-secondary-text group-data-secondary:text-white", children: description }, `description-${i}`)) : null;
685
+
686
+ const Text = JSX(({ children, ...styleProps }) => (jsx("span", { className: style('font-sans', Object.values(styleProps)), children: children })));
687
+
688
+ const renderBenefitLabel = (label, i) => label ? (jsx(Text, { color: "text-primary-text group-data-secondary:text-white", size: "text-h6", children: label }, `label-${i}`)) : null;
689
+
690
+ const renderBenefitText = (_, i) => _.type === 'rte' && '__html' in _ && _.__html ? (jsx(RichText, { ..._ }, `rte-${i}`)) : ([
691
+ 'label' in _ ? renderBenefitLabel(_.label, i) : null,
692
+ 'description' in _ ? (jsx("span", { className: _.descriptionClassName, children: renderBenefitDescription(_.description, i) }, String(i))) : null,
693
+ ]);
694
+
695
+ const BenefitItem = JSX(({ className, benefitsVersion, ..._ }) => (jsxs("div", { className: style('flex gap-m min-w-56 items-center', className), children: ['icon' in _ ? renderBenefitIcon(_.icon, benefitsVersion) : null, jsx("div", { children: renderBenefitText(_) })] })));
696
+
697
+ const MAX_BENEFITS_LEN_DEVIATION = 16;
698
+ const benefitLength = (_) => _.type === 'rte'
699
+ ? _?.__html?.length || 0
700
+ : Math.max(_?.label?.length || 0, _?.description?.length || 0);
701
+ const isDistortedBenefits = (benefits) => deviation(benefits.map(benefitLength)) > MAX_BENEFITS_LEN_DEVIATION;
702
+ const hasIcon = (_) => _ && 'icon' in _ && _.icon && (_.icon.icon || _.icon.src);
703
+ const isTextualBenefits = (benefits) => !benefits.some(hasIcon);
704
+ const DefaultBenefitsList = JSX(({ className, benefitsVersion = 'normal', benefits }) => benefits?.length ? (jsx("div", { className: style('flex gap-x-m gap-y-s', isDistortedBenefits(benefits) || isTextualBenefits(benefits) ? 'flex-col' : 'flex-wrap', className), children: benefits.map((_, i) => (jsx(BenefitItem, { benefitsVersion: benefitsVersion, ..._ }, String(i)))) })) : null);
705
+
706
+ const TabularBenefitsList = JSX(({ className, benefits }) => benefits?.length ? (jsx("div", { className: style('grid grid-cols-[max-content_1fr] auto-rows-auto items-baseline gap-x-m gap-y-xs', className), children: benefits.flatMap(renderBenefitText) })) : null);
707
+
708
+ const BenefitsList = JSX(({ isTabularBenefits, ...rest }) => isTabularBenefits ? jsx(TabularBenefitsList, { ...rest }) : jsx(DefaultBenefitsList, { ...rest }));
709
+
710
+ const isIcon = (icon) => Boolean(icon?.src || icon?.icon);
711
+
712
+ const renderButtonsSection = (buttons, { className, buttonClassName, isVertical } = {}) => buttons?.length && buttons.some((_) => _?.text || _?.icon?.icon) ? (jsx("div", { className: style('flex', isVertical
713
+ ? 'flex-col gap-xs justify-items-stretch'
714
+ : 'flex-wrap @xl:flex-nowrap gap-lg sm:gap-m', className), children: buttons.map(renderButton(buttonClassName)) })) : null;
715
+ const renderButton = (buttonClassName = '') => (button, index) => {
716
+ const { text, icon, iconRight, version, ...rest } = button || {};
717
+ const iconVersion = getIconVersion(icon, version);
718
+ const iconRightVersion = getIconVersion(iconRight, version);
719
+ return text || icon?.icon ? (jsx(Button, { className: style('basis-full @lg:basis-auto', buttonClassName), appendLeft: renderButtonIcon({ ...icon, iconVersion }), appendRight: renderButtonIcon({ ...iconRight, iconVersion: iconRightVersion }), version: version, text: text, ...rest }, index ? String(index) : '')) : null;
720
+ };
721
+ const DEFAULT_ICON_W = 24;
722
+ const getIconVersion = (icon, version = 'secondary') => {
723
+ const iconVersionDefault = version === 'secondary' ? 'color' : 'white';
724
+ return icon?.iconVersion ? icon?.iconVersion : iconVersionDefault;
725
+ };
726
+ const renderButtonIcon = (icon) => isIcon(icon) ? (jsx(Img, { image: icon, width: String(icon?.size?.width || DEFAULT_ICON_W), height: String(DEFAULT_ICON_W) })) : null;
727
+
728
+ const DOT_SIZE_MAP = {
729
+ L: 'w-1.5 h-1.5 mr-m',
730
+ M: 'w-1.5 h-1.5 mr-s',
731
+ S: 'w-1 h-1 mr-xs',
732
+ XS: 'w-1 h-1 mr-xs',
733
+ };
734
+ const ListItem = JSX(({ className, isDotted, children, size = 'M' }) => (jsxs("div", { className: style('font-sans flex', className), role: "listitem", children: [isDotted ? (jsx("div", { className: "shrink-0", children: jsx("div", { className: style('align-middle inline-block rounded-full bg-primary-text group-data-secondary:bg-white', DOT_SIZE_MAP[size]) }) })) : null, jsx("span", { children: children })] })));
735
+
736
+ const TEXT_SIZE_MAP = {
737
+ XS: 'text-m font-light',
738
+ S: 'text-l font-light',
739
+ M: 'text-h6',
740
+ L: 'text-h5',
741
+ };
742
+ const ITEM_INDENT_MAP = {
743
+ XS: 'ml-2xs',
744
+ S: 'ml-xs',
745
+ M: 'ml-s',
746
+ L: 'ml-m',
747
+ };
748
+ const List = JSX(({ className, hasIndent, isDotted = true, items = [], listItemSize = 'M' }) => items?.length ? (jsx("section", { className: style('flex flex-col gap-xs text-left text-primary-text group-data-secondary:text-white group-data-gray:text-secondary-text', TEXT_SIZE_MAP[listItemSize], hasIndent ? ITEM_INDENT_MAP[listItemSize] : '', className), role: "list", children: items.map((item, i) => (jsx(ListItem, { isDotted: isDotted, size: listItemSize, children: item }, String(i)))) })) : null);
749
+
750
+ const toLocalNumberFormat = (fractionDigits = 0) => (_ = 0) => new Intl.NumberFormat('ru-RU', {
751
+ minimumFractionDigits: 0,
752
+ maximumFractionDigits: fractionDigits,
753
+ }).format(Number(_) || 0);
754
+
755
+ const PriceList = JSX(({ priceList }) => priceList?.length ? (jsx("div", { className: "flex flex-wrap xl:flex-nowrap xl:bg-main-divider xl:rounded-md p-xs gap-xl", children: priceList.map(renderPriceListItem) })) : null);
756
+ const renderPriceListItem = ({ label, amount }) => (jsxs("div", { className: "basis-full flex flex-col-reverse sm:flex-row sm:justify-between sm:bg-main-divider sm:py-m sm:px-lg sm:rounded-md items-baseline whitespace-pre", children: [jsx(Text, { font: "font-light", size: "text-l", color: "text-secondary-text", children: label }), amount ? (jsxs("span", { className: "font-sans text-h6 sm:text-primary-main text-primary-text", children: [toLocalNumberFormat(2)(amount), " \u20BD"] })) : null] }));
757
+
758
+ const Tags = JSX(({ className, tags }) => tags?.length ? (jsx("div", { className: style('flex flex-wrap gap-xs', className), role: "list", children: tags.map(renderTag) })) : null);
759
+ const renderTag = (tag, key) => (jsx("div", { className: "p-xs border-solid border rounded-md border-gray", role: "listitem", children: jsx(Text, { size: "text-m", font: "font-light", children: tag }) }, String(key)));
760
+
761
+ const BaseProductTile = JSX(
762
+ // eslint-disable-next-line max-lines-per-function
763
+ ({ className, padding, defaultPadding, title, description, headlineVersion = 'L', align = 'text-left', benefitsVersion, isTabularBenefits, benefits, __html, isFullWidthTitle, items, isDotted = true, priceList = [], listItemSize, tags = [], buttons, image, imageOptions: { imageAlign = 'center', directionRight = true, isImageAlwaysOnRight, isImageSecondary = false, } = {}, backwardButton, children, ...rest }) => {
764
+ const img = image?.src ? jsx(Img, { image: image }) : null;
765
+ const headline = (jsx(Headline, { title: title, description: description, headlineVersion: headlineVersion, align: align, isEmbedded: true }));
766
+ const filteredBenefits = benefits?.filter((_) => _?.type === 'rte' || 'label' in _ || 'description' in _);
767
+ return (jsx(BaseTile, { className: className, padding: padding, defaultPadding: defaultPadding, ...(isFullWidthTitle ? { title: headline } : { insetTitle: headline }), ...leftOrRightImage(img, directionRight), isImageSecondary: isImageSecondary, imageAlign: imageAlign, isImageAlwaysOnRight: isImageAlwaysOnRight, buttons: renderButtonsSection(buttons), backwardButton: backwardButton, ...rest, children: jsxs("div", { className: "flex flex-col sm:gap-xl gap-4xl", children: [filteredBenefits?.length ? (jsx(BenefitsList, { benefitsVersion: benefitsVersion, isTabularBenefits: isTabularBenefits, benefits: filteredBenefits })) : null, __html ? jsx(RichText, { __html: __html }) : null, items?.length ? (jsx(List, { items: items, isDotted: isDotted, listItemSize: listItemSize })) : null, children, priceList?.length ? jsx(PriceList, { priceList: priceList }) : null, renderTags(tags)] }) }));
768
+ });
769
+ const leftOrRightImage = (img, directionRight) => directionRight ? { rightImage: img } : { leftImage: img };
770
+ const renderTags = (tags) => (tags?.length ? jsx(Tags, { tags: tags }) : null);
771
+
772
+ const getBorderStyle$1 = (showBorder) => showBorder
773
+ ? 'border border-solid border-gray group-data-secondary:border-white/50 group-data-gray:border-main-divider'
774
+ : '';
775
+
776
+ const ProductBlock = JSX(({ className, padding, showBorder, ...rest }) => (jsx(BlockWrapper, { className: style('overflow-hidden flex flex-col gap-3xl box-border', getBorderStyle$1(showBorder), className), padding: "p-0", ...rest, children: jsx(BaseProductTile, { defaultPadding: "p-6xl", padding: padding, className: "grow h-full", ...rest }) })));
777
+
778
+ const isFilled = (_) => _ !== null && _ !== undefined;
779
+
780
+ const defaultCache = new Map();
781
+ const applyCache = (fetcher, cache = defaultCache) => (key) => {
782
+ const cachedData = cache.get(key);
783
+ if (isFilled(cachedData)) {
784
+ return cachedData;
785
+ }
786
+ const data = fetcher(key);
787
+ if (isFilled(data)) {
788
+ cache.set(key, Promise.resolve(data));
789
+ }
790
+ else {
791
+ cache.delete(key);
792
+ }
793
+ return data;
794
+ };
795
+
796
+ const isSimpleKey = (args) => Boolean(args && Array.isArray(args) && args.length === 1 && typeof args[0] === 'string');
797
+ function useAsyncData(key, fetcher, { fallback, cache } = {}) {
798
+ const args = useMemo(() => keyToArgs(key), [key]);
799
+ const [simpleKey] = isSimpleKey(args) ? args : [];
800
+ const [data, setData] = useState(undefined);
801
+ const [error, setError] = useState(undefined);
802
+ useEffect(() => {
803
+ const isEmptyKey = !args.some(isFilled);
804
+ if (isEmptyKey) {
805
+ return;
806
+ }
807
+ let canceled = false;
808
+ const setResult = (newData, err) => {
809
+ if (!canceled) {
810
+ setData(newData);
811
+ setError(err);
812
+ }
813
+ };
814
+ (async () => {
815
+ try {
816
+ setResult(await (simpleKey ? applyCache(fetcher, cache)(simpleKey) : fetcher(...args)));
817
+ }
818
+ catch (err) {
819
+ setResult(undefined, err);
820
+ }
821
+ })();
822
+ return () => {
823
+ canceled = true;
824
+ };
825
+ }, [fetcher, cache, args]);
826
+ const fallbackData = fallback && simpleKey && fallback[simpleKey];
827
+ return {
828
+ data: !data && fallbackData ? fallbackData : data,
829
+ error,
830
+ mutate: () => Promise.resolve(undefined) // TODO Clean up cache
831
+ };
832
+ }
833
+ function keyToArgs(key) {
834
+ if (Array.isArray(key)) {
835
+ return key;
836
+ }
837
+ else if (key instanceof Function) {
838
+ return keyToArgs(key());
839
+ }
840
+ else {
841
+ return [key];
842
+ }
843
+ }
844
+
845
+ async function fetchJSON(url, options) {
846
+ try {
847
+ return url ? await fetchJSONUnsafe(url, options) : null;
848
+ }
849
+ catch (err) {
850
+ console.error(err);
851
+ }
852
+ return null;
853
+ }
854
+ async function fetchJSONUnsafe(url, options) {
855
+ const response = await fetch(url, {
856
+ ...options,
857
+ headers: {
858
+ ...options?.headers,
859
+ 'Content-Type': 'application/json',
860
+ },
861
+ });
862
+ return response.json();
863
+ }
864
+
865
+ const EMPTY_VALUE$5 = {};
866
+ const DEFAULT_FOLDER_NAME = 'wcms-resources';
867
+ function useSWRResource(filename, options = {}) {
868
+ const { fallback = EMPTY_VALUE$5, folderName = DEFAULT_FOLDER_NAME, setBasePath = false } = options;
869
+ const path = joinPath('/', setBasePath ? projectSettings.BASE_PATH : '', folderName, `${filename}.json`);
870
+ const { data } = useAsyncData(filename ? path : null, fetchJSONUnsafe, {
871
+ fallback,
872
+ });
873
+ return data || EMPTY_VALUE$5;
874
+ }
875
+
876
+ const useAdTile = (sourceBook = 'reklamnaya-plitka') => {
877
+ const data = useSWRResource(sourceBook);
878
+ const tileIndex = useMemo(() => randomNumInRange(0, data?.items?.length), [data]);
879
+ return data?.items?.[tileIndex];
880
+ };
881
+ const randomNumInRange = (min = 0, max = 0) => Math.floor(Math.random() * (max - min) + min);
882
+
883
+ const AdTile = JSX((props) => {
884
+ const content = useAdTile(props.options?.page?.adSourceBook);
885
+ return content ? (jsx(ClientOnly, { children: jsx(ProductBlock, { ...content, ...props }) })) : null;
886
+ });
887
+
888
+ function LeadServiceAPI() {
889
+ async function send(body, isIndividualType) {
890
+ const url = isIndividualType ? '/api/v1/lead' : '/api/v1/sendcorporatelead';
891
+ try {
892
+ const response = await fetch(url, {
893
+ method: 'POST',
894
+ headers: { 'Content-Type': 'application/json' },
895
+ mode: 'cors',
896
+ body: JSON.stringify(body),
897
+ });
898
+ if (!response?.ok) {
899
+ return null;
900
+ }
901
+ const data = await response.json();
902
+ return data;
903
+ }
904
+ catch (e) {
905
+ return null;
906
+ }
907
+ }
908
+ return {
909
+ send,
910
+ };
911
+ }
912
+
913
+ const identity = (_) => _;
914
+
915
+ const useForm = (initialState, onSubmit) => {
916
+ const [formState, setFormState] = useState(initialState);
917
+ const [isDirtyForm, setDirtyForm] = useState(false);
918
+ const [dirtyFieldsMap, setDirtyFieldsMap] = useState({});
919
+ const handlersMap = useRef({});
920
+ const field = useCallback((fieldName, options) => {
921
+ const { parse = identity, format = identity } = options || {};
922
+ if (!handlersMap.current) {
923
+ handlersMap.current = {};
924
+ }
925
+ handlersMap.current[fieldName] ||= (value) => {
926
+ setFormState((prev) => ({ ...prev, [fieldName]: parse(value) }));
927
+ setDirtyFieldsMap((prev) => ({ ...prev, [fieldName]: true }));
928
+ };
929
+ return {
930
+ value: format(formState[fieldName]),
931
+ isDirty: isDirtyForm || dirtyFieldsMap[fieldName],
932
+ onChange: handlersMap.current[fieldName],
933
+ };
934
+ }, [formState, isDirtyForm, dirtyFieldsMap]);
935
+ const update = useCallback((_) => {
936
+ setFormState(_);
937
+ setDirtyFieldsMap(_);
938
+ }, []);
939
+ const reset = useCallback(() => {
940
+ setFormState(initialState);
941
+ setDirtyForm(false);
942
+ setDirtyFieldsMap({});
943
+ }, [initialState]);
944
+ const handleSubmit = useCallback((e) => {
945
+ e.preventDefault();
946
+ setDirtyForm(true);
947
+ onSubmit && onSubmit(formState);
948
+ }, [onSubmit, formState]);
949
+ return [
950
+ formState,
951
+ {
952
+ isDirty: isDirtyForm || Object.values(dirtyFieldsMap).some(Boolean),
953
+ field,
954
+ update,
955
+ reset,
956
+ onSubmit: handleSubmit,
957
+ },
958
+ ];
959
+ };
960
+
961
+ const objectValidator = (validatorsMap) => (o) => (o &&
962
+ Object.entries(validatorsMap).flatMap(([key, validator]) => validator(o[key]))) ||
963
+ [];
964
+
965
+ const isValidationSuccess = (info) => !info?.length;
966
+ const validator = (predicate) => (message) => (_) => predicate(_) ? [] : [message];
967
+
968
+ const REGIONS_URL$1 = '/api/v1/regions';
969
+ const EMPTY_VALUE$4 = [];
970
+ function useGetRegions() {
971
+ const { data } = useAsyncData(REGIONS_URL$1, fetchJSONUnsafe);
972
+ return data || EMPTY_VALUE$4;
973
+ }
974
+
975
+ const Footnote = JSX(({ text, link }) => (jsxs(Paragraph, { size: "text-s", font: "font-light", color: "text-secondary-text", children: [jsx(Text, { children: text || 'Нажимая кнопку, вы подтверждаете согласие с ' }), link ? (jsx(Button, { href: link.href, ariaLabel: "\u0443\u0441\u043B\u043E\u0432\u0438\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043D\u043D\u044B\u0445", target: link.target, className: "text-primary-main", children: jsx(Text, { children: link.text }) })) : null] })));
976
+
977
+ const withValidator = (props, validator) => {
978
+ const { value, isDirty } = props;
979
+ const errors = isDirty ? validator(value) : [];
980
+ return {
981
+ ...props,
982
+ errors,
983
+ error: errors[0],
984
+ };
985
+ };
986
+
987
+ const Input = JSX(({ key, className = '', inputClassName = '', id, name, type = 'text', label, placeholder, value = '', valid = true, children, onChange, onFocus, onBlur, pattern, autoFocus = false, }) => {
988
+ const inputRef = useRef(null);
989
+ const handleChange = useCallback((e) => {
990
+ onChange && onChange(e.target?.value || '');
991
+ }, [onChange]);
992
+ useEffect(() => {
727
993
  if (autoFocus) {
728
994
  inputRef.current?.focus();
729
995
  }
@@ -772,54 +1038,29 @@
772
1038
 
773
1039
  const ACQUIRING_TYPES = [
774
1040
  {
775
- name: 'Торговый эквайринг',
776
- },
777
- {
778
- name: 'Мобильный эквайринг',
779
- },
780
- {
781
- name: 'Интернет-эквайринг',
782
- },
783
- {
784
- name: 'QR-эквайринг (СБП)',
785
- },
786
- {
787
- name: 'Все виды эквайринга',
788
- },
789
- ];
790
-
791
- function useBool(defaultValue = false) {
792
- const [value, setValue] = useState(defaultValue);
793
- const setTrue = useCallback(() => setValue(true), []);
794
- const setFalse = useCallback(() => setValue(false), []);
795
- const toggle = useCallback(() => setValue(_ => !_), []);
796
- return [value, { setValue, setTrue, setFalse, toggle }];
797
- }
798
-
799
- const isOnlyDigits = (str) => str && !/\D/.test(str);
800
-
801
- const svgUseStyleMap = {
802
- normal: '',
803
- color: 'text-primary-main',
804
- black: 'text-black',
805
- white: 'text-black',
806
- };
807
- const Icon = JSX(({ className = '', imageClassName = '', name = '', alt = `Иконка ${name}`, title = alt, iconVersion = 'color', width, height, }) => {
808
- const router = useRouter();
809
- const href = adjustHref(router)(joinPath(projectSettings.CDN, '/icons', `${name}.svg`));
810
- if (iconVersion !== 'normal') {
811
- return (jsx(Background, { className: className, children: jsxs("svg", { className: style(getSvgSize(width), svgUseStyleMap[iconVersion], iconVersion === 'white' ? 'invert' : '', imageClassName), width: width, height: height, "aria-hidden": "true", children: [title ? jsx("title", { children: title }) : null, alt ? jsx("desc", { children: alt }) : null, jsx("use", { href: `${href}#icon`, xlinkHref: `${href}#icon` })] }) }));
812
- }
813
- return (jsx("img", { className: className, src: href, alt: alt, title: title, "aria-hidden": "true", width: width, height: height, style: getInlineStyle(className, height) }));
814
- });
815
- const getInlineStyle = (className, height) => {
816
- if (className?.includes('h-')) {
817
- return {};
818
- }
819
- return { height: isOnlyDigits(height) ? `${height}px` : height, width: 'auto' };
820
- };
821
- const getSvgSize = (width) => (width ? '' : 'w-full h-full');
822
- const Background = JSX(({ className, children }) => className ? jsx("div", { className: className, children: children }) : children);
1041
+ name: 'Торговый эквайринг',
1042
+ },
1043
+ {
1044
+ name: 'Мобильный эквайринг',
1045
+ },
1046
+ {
1047
+ name: 'Интернет-эквайринг',
1048
+ },
1049
+ {
1050
+ name: 'QR-эквайринг (СБП)',
1051
+ },
1052
+ {
1053
+ name: 'Все виды эквайринга',
1054
+ },
1055
+ ];
1056
+
1057
+ function useBool(defaultValue = false) {
1058
+ const [value, setValue] = useState(defaultValue);
1059
+ const setTrue = useCallback(() => setValue(true), []);
1060
+ const setFalse = useCallback(() => setValue(false), []);
1061
+ const toggle = useCallback(() => setValue(_ => !_), []);
1062
+ return [value, { setValue, setTrue, setFalse, toggle }];
1063
+ }
823
1064
 
824
1065
  const formatOption = (_) => _?.text || _?.key || '';
825
1066
 
@@ -909,11 +1150,11 @@
909
1150
  onClose: handleClose,
910
1151
  iconVersion,
911
1152
  });
912
- return (jsxs("div", { className: className, children: [renderLabel(label), jsxs("div", { className: style('relative', isOpen ? 'z-20' : 'z-10'), ref: inputRef, children: [jsxs("div", { className: style('h-14 text-l flex justify-between items-center text-primary-text cursor-pointer relative z-10', getBorderStyle$1(isBorder, valid)), onClick: isOpen ? handleClose : open, children: [jsx("p", { className: "p-m pr-3xl flex items-center overflow-hidden text-ellipsis whitespace-nowrap", children: formatOption(value) || placeholder }), renderIcon$1(isOpen, iconVersion)] }), isSearch && isOpen ? (jsx("div", { className: style('absolute top-0 w-full z-20'), children: jsx(Input, { type: "text", autoFocus: true, value: query, onChange: setQuery }) })) : null] })] }));
1153
+ return (jsxs("div", { className: className, children: [renderLabel(label), jsxs("div", { className: style('relative', isOpen ? 'z-20' : 'z-10'), ref: inputRef, children: [jsxs("div", { className: style('h-14 text-l flex justify-between items-center text-primary-text cursor-pointer relative z-10', getBorderStyle(isBorder, valid)), onClick: isOpen ? handleClose : open, children: [jsx("p", { className: "p-m pr-3xl flex items-center overflow-hidden text-ellipsis whitespace-nowrap", children: formatOption(value) || placeholder }), renderIcon$1(isOpen, iconVersion)] }), isSearch && isOpen ? (jsx("div", { className: style('absolute top-0 w-full z-20'), children: jsx(Input, { type: "text", autoFocus: true, value: query, onChange: setQuery }) })) : null] })] }));
913
1154
  });
914
1155
  const renderLabel = (label) => label ? (jsx("div", { className: "mb-xs", children: jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label }) })) : null;
915
1156
  const renderIcon$1 = (isOpen, iconVersion) => (jsx(Icon, { className: style('absolute right-3', isOpen ? '' : 'rotate-180'), iconVersion: iconVersion, name: "ArrowUpIcon", width: "16", height: "16" }));
916
- const getBorderStyle$1 = (isBorder, valid) => style(isBorder ? 'border rounded-md hover:border-primary-hover' : '', valid ? ' border-gray' : 'border-error');
1157
+ const getBorderStyle = (isBorder, valid) => style(isBorder ? 'border rounded-md hover:border-primary-hover' : '', valid ? ' border-gray' : 'border-error');
917
1158
 
918
1159
  const SelectControl = JSX(({ className = '', error, ...rest }) => (jsxs("div", { className: className, children: [jsx(Select, { ...rest, valid: !error }), jsx("div", { className: "h-2", children: error ? (jsx(Text, { size: "text-xs", font: "font-light", color: "text-error", children: error })) : null })] })));
919
1160
 
@@ -1005,14 +1246,14 @@
1005
1246
  });
1006
1247
 
1007
1248
  const BRANCHES_URL = '/api/v1/branches';
1008
- const EMPTY_VALUE$4 = [];
1249
+ const EMPTY_VALUE$3 = [];
1009
1250
  function useBranches(regionCode) {
1010
1251
  const { data } = useAsyncData(regionCode ? `${BRANCHES_URL}?regionCode=${regionCode}` : null, fetchSafeBoxes$1);
1011
- return data || EMPTY_VALUE$4;
1252
+ return data || EMPTY_VALUE$3;
1012
1253
  }
1013
1254
  const fetchSafeBoxes$1 = async (url) => {
1014
1255
  const result = await fetchJSON(url, { method: 'GET' });
1015
- return result || EMPTY_VALUE$4;
1256
+ return result || EMPTY_VALUE$3;
1016
1257
  };
1017
1258
 
1018
1259
  const MIN_CREDIT_AMOUNT = 1000;
@@ -1045,11 +1286,6 @@
1045
1286
 
1046
1287
  const clamp = (value, min, max) => Math.max(min, Math.min(value, max));
1047
1288
 
1048
- const toLocalNumberFormat = (fractionDigits = 0) => (_ = 0) => new Intl.NumberFormat('ru-RU', {
1049
- minimumFractionDigits: 0,
1050
- maximumFractionDigits: fractionDigits,
1051
- }).format(Number(_) || 0);
1052
-
1053
1289
  function parseDecimal(value) {
1054
1290
  const rawValue = (value || '').replace(/\D/g, '');
1055
1291
  const unsafeDecimal = parseInt(rawValue, 10);
@@ -1157,17 +1393,6 @@
1157
1393
  return (jsxs("form", { className: "container", onSubmit: formProps.onSubmit, children: [jsx(Heading, { headingType: "h6", title: "\u041E\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0437\u0430\u044F\u0432\u043A\u0443 \u0438 \u043C\u044B \u043E\u0442\u0432\u0435\u0442\u0438\u043C \u043D\u0430 \u043B\u044E\u0431\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u043F\u043E \u0434\u0435\u043F\u043E\u0437\u0438\u0442\u0430\u043C", className: "@xl:text-center mb-m" }), jsxs("div", { className: "max-w-[560px] m-auto space-y-s", children: [jsx(InputControl, { className: "shrink-0 w-full", label: "\u0418\u043C\u044F", ...withValidator(field('name'), nameValidator) }), jsx(PhoneInputControl, { className: "shrink-0 w-full", label: "\u0422\u0435\u043B\u0435\u0444\u043E\u043D", ...withValidator(field('phone'), phoneValidator) })] }), jsxs("div", { className: "flex justify-between flex-col-reverse @xl:items-center @xl:flex-row max-w-[560px] m-auto", children: [jsx("div", { className: "flex-1", children: jsx(Footnote, { link: link }) }), renderSubmitButton(button)] })] }));
1158
1394
  });
1159
1395
 
1160
- const EMPTY_VALUE$3 = {};
1161
- const DEFAULT_FOLDER_NAME = 'wcms-resources';
1162
- function useSWRResource(filename, options = {}) {
1163
- const { fallback = EMPTY_VALUE$3, folderName = DEFAULT_FOLDER_NAME, setBasePath = false } = options;
1164
- const path = joinPath('/', setBasePath ? projectSettings.BASE_PATH : '', folderName, `${filename}.json`);
1165
- const { data } = useAsyncData(filename ? path : null, fetchJSONUnsafe, {
1166
- fallback,
1167
- });
1168
- return data || EMPTY_VALUE$3;
1169
- }
1170
-
1171
1396
  const ApplicationFormGrantSupport = JSX((props) => {
1172
1397
  const { button, sourceBookDir } = props;
1173
1398
  const { regions } = useSWRResource(sourceBookDir || 'regions-grant-support');
@@ -1403,32 +1628,6 @@
1403
1628
  return (jsxs("form", { className: "container space-y-s", onSubmit: formProps.onSubmit, children: [renderIndividualsFields(field), jsxs("div", { className: "@xl:flex justify-between items-center", children: [jsxs("div", { className: "@xl:mb-0 mb-2 flex items-center gap-3", children: [jsx(Checkbox, { ...withValidator(field('consentDataProcessing'), defaultValidator) }), jsx(Footnote, { text: "\u0421\u043E\u0433\u043B\u0430\u0441\u0435\u043D \u0441 ", link: link })] }), renderSubmitButton(button)] })] }));
1404
1629
  });
1405
1630
 
1406
- const sourcesComparator = (a, b) => a?.media && b?.media ? a.media - b.media : 0;
1407
- const ImgAsPicture = JSX(({ className = '', image, imageClassName = '', pathPrefix }) => {
1408
- const router = useRouter();
1409
- return (jsxs("picture", { className: className, children: [image?.sources?.length
1410
- ? image.sources
1411
- .filter((_) => _?.src)
1412
- .sort(sourcesComparator)
1413
- .map(({ src, format, media }, index) => (jsx("source", { srcSet: adjustSrc(router, pathPrefix)(src), type: formatToMimeType(format), media: media ? `(max-width: ${media}px)` : '', width: image.size?.width, height: image.size?.height }, `${index}_${src}`)))
1414
- : null, image?.src
1415
- ? renderImg({ ...image, src: adjustSrc(router, pathPrefix)(image.src) }, imageClassName)
1416
- : null] }));
1417
- });
1418
- const renderImg = (image, imageClassName = '') => (jsx("img", { src: image.src, className: style('object-contain', imageClassName), alt: image.alt || image.title, title: image.title || '', style: {
1419
- width: image.size?.width ? `${image.size?.width}px` : '100%',
1420
- height: image.size?.height ? `${image.size?.height}px` : 'auto',
1421
- }, width: image.size?.width, height: image.size?.height }));
1422
- const adjustSrc = (router, pathPrefix) => (src) => src && !isURL(src) ? adjustHref(router)(joinPath(pathPrefix, src)) : src;
1423
- const formatToMimeType = (format) => format ? `image/${String(format)}` : undefined;
1424
-
1425
- const Img = JSX(({ className = '', image, imageClassName = '', pathPrefix, ...iconProps }) => {
1426
- if (!image?.src && !image?.icon) {
1427
- return null;
1428
- }
1429
- return image.icon ? (jsx(Icon, { className: className, imageClassName: imageClassName, iconVersion: image?.iconVersion, name: image.icon, ...iconProps })) : (jsx(ImgAsPicture, { className: className, imageClassName: imageClassName, image: image, pathPrefix: pathPrefix }));
1430
- });
1431
-
1432
1631
  const renderContacts = () => (jsxs("div", { className: "flex gap-xl", children: [jsxs("a", { className: "flex gap-s items-center text-primary-text no-underline", href: `tel:8 (800) 200-78-70`, "aria-label": "8 (800) 200-78-70", children: [jsx(Img, { image: { icon: 'PhoneIcon' }, width: "24", height: "24" }), jsx("span", { children: "8 (800) 200-78-70" })] }), jsxs("a", { className: "flex gap-s items-center text-primary-text no-underline", "aria-label": "ved@rshb.ru", href: `mailto:ved@rshb.ru`, children: [jsx(Img, { image: { icon: 'MailIcon' }, width: "24", height: "24" }), jsx("span", { children: "ved@rshb.ru" })] })] }));
1433
1632
 
1434
1633
  const Radio = JSX(({ name, text, value, checked, onChange, className }) => (jsx("div", { className: className, children: jsxs("label", { className: "font-sans flex gap-s items-center relative cursor-pointer", children: [jsx("input", { className: "appearance-none flex justify-center items-center shrink-0 w-5 h-5 border border-gray hover:border-primary-hover\n checked:border-2 checked:!border-primary-main focus:checked:border-primary-main focus:border-primary-text active:border-primary-text\n after:block after:w-2.5 after:h-2.5 after:rounded-full checked:after:bg-primary-main outline-none rounded-full cursor-pointer", type: "radio", value: value, name: name, checked: checked, onChange: (_) => onChange(_.target.value) }), text ? jsx(Text, { color: "text-primary-text", children: text }) : null] }) })));
@@ -1552,28 +1751,6 @@
1552
1751
  }, className: style('rounded-icon object-fit flex justify-center items-center', iconBgStyles[iconBgVersion], className), children: jsx(Icon, { ...rest, width: "54%", height: "54%", name: icon }) })) : null;
1553
1752
  });
1554
1753
 
1555
- const DOT_SIZE_MAP = {
1556
- L: 'w-1.5 h-1.5 mr-m',
1557
- M: 'w-1.5 h-1.5 mr-s',
1558
- S: 'w-1 h-1 mr-xs',
1559
- XS: 'w-1 h-1 mr-xs',
1560
- };
1561
- const ListItem = JSX(({ className, isDotted, children, size = 'M' }) => (jsxs("div", { className: style('font-sans flex', className), role: "listitem", children: [isDotted ? (jsx("div", { className: "shrink-0", children: jsx("div", { className: style('align-middle inline-block rounded-full bg-primary-text group-data-secondary:bg-white', DOT_SIZE_MAP[size]) }) })) : null, jsx("span", { children: children })] })));
1562
-
1563
- const TEXT_SIZE_MAP = {
1564
- XS: 'text-m font-light',
1565
- S: 'text-l font-light',
1566
- M: 'text-h6',
1567
- L: 'text-h5',
1568
- };
1569
- const ITEM_INDENT_MAP = {
1570
- XS: 'ml-2xs',
1571
- S: 'ml-xs',
1572
- M: 'ml-s',
1573
- L: 'ml-m',
1574
- };
1575
- const List = JSX(({ className, hasIndent, isDotted = true, items = [], listItemSize = 'M' }) => items?.length ? (jsx("section", { className: style('flex flex-col gap-xs text-left text-primary-text group-data-secondary:text-white group-data-gray:text-secondary-text', TEXT_SIZE_MAP[listItemSize], hasIndent ? ITEM_INDENT_MAP[listItemSize] : '', className), role: "list", children: items.map((item, i) => (jsx(ListItem, { isDotted: isDotted, size: listItemSize, children: item }, String(i)))) })) : null);
1576
-
1577
1754
  const defaultIconSize = 44;
1578
1755
 
1579
1756
  const BenefitsBlock = JSX(({ className = '', title, benefitList, ...rest }) => (jsxs(BlockWrapper, { className: className, defaultPadding: "p-6xl", ...rest, children: [title ? jsx(Heading, { headingType: "h3", as: "h2", className: AlignStyles, title: title }) : null, benefitList?.length ? (jsx("div", { className: "flex flex-col @md:flex-row flex-wrap w-full @md:justify-center mt-xl gap-5xl", role: "list", children: benefitList.map(renderBenefit) })) : null] })));
@@ -1590,69 +1767,6 @@
1590
1767
  return description?.items && description.items.length > 0 ? (jsx("ul", { className: style(listStyleType, description.listItemSize ? TEXT_SIZE_MAP[description.listItemSize] : ''), children: description.items.map((_, i) => (jsx("li", { children: jsx(Text, { color: "text-secondary-text group-data-secondary:text-white/80", font: "font-light", children: _ }) }, `benefitListItem-${i}`))) })) : null;
1591
1768
  };
1592
1769
 
1593
- const isIcon = (icon) => Boolean(icon?.src || icon?.icon);
1594
-
1595
- const renderButtonsSection = (buttons, { className, buttonClassName, isVertical } = {}) => buttons?.length && buttons.some((_) => _?.text || _?.icon?.icon) ? (jsx("div", { className: style('flex', isVertical
1596
- ? 'flex-col gap-xs justify-items-stretch'
1597
- : 'flex-wrap @xl:flex-nowrap gap-lg sm:gap-m', className), children: buttons.map(renderButton(buttonClassName)) })) : null;
1598
- const renderButton = (buttonClassName = '') => (button, index) => {
1599
- const { text, icon, iconRight, version, ...rest } = button || {};
1600
- const iconVersion = getIconVersion(icon, version);
1601
- const iconRightVersion = getIconVersion(iconRight, version);
1602
- return text || icon?.icon ? (jsx(Button, { className: style('basis-full @lg:basis-auto', buttonClassName), appendLeft: renderButtonIcon({ ...icon, iconVersion }), appendRight: renderButtonIcon({ ...iconRight, iconVersion: iconRightVersion }), version: version, text: text, ...rest }, index ? String(index) : '')) : null;
1603
- };
1604
- const DEFAULT_ICON_W = 24;
1605
- const getIconVersion = (icon, version = 'secondary') => {
1606
- const iconVersionDefault = version === 'secondary' ? 'color' : 'white';
1607
- return icon?.iconVersion ? icon?.iconVersion : iconVersionDefault;
1608
- };
1609
- const renderButtonIcon = (icon) => isIcon(icon) ? (jsx(Img, { image: icon, width: String(icon?.size?.width || DEFAULT_ICON_W), height: String(DEFAULT_ICON_W) })) : null;
1610
-
1611
- const headlineVersionStyles = {
1612
- XXL: {
1613
- title: { headingType: 'h0', as: 'h1' },
1614
- descriptionSize: 'text-h5',
1615
- descriptionWeight: 'font-normal',
1616
- descriptionStyle: 'mt-xl',
1617
- },
1618
- XL: {
1619
- title: { headingType: 'h1', as: 'h1' },
1620
- descriptionSize: 'text-xl',
1621
- descriptionWeight: 'font-light',
1622
- descriptionStyle: 'mt-m',
1623
- },
1624
- L: {
1625
- title: { headingType: 'h2', as: 'h2' },
1626
- descriptionSize: 'text-xl',
1627
- descriptionWeight: 'font-light',
1628
- descriptionStyle: 'mt-m',
1629
- },
1630
- M: {
1631
- title: { headingType: 'h3', as: 'h2' },
1632
- descriptionSize: 'text-xl',
1633
- descriptionWeight: 'font-light',
1634
- descriptionStyle: 'mt-s',
1635
- },
1636
- S: {
1637
- title: { headingType: 'h4', as: 'h2' },
1638
- descriptionSize: 'text-xl',
1639
- descriptionWeight: 'font-light',
1640
- descriptionStyle: 'mt-xs',
1641
- },
1642
- XS: {
1643
- title: { headingType: 'h5', as: 'h2' },
1644
- descriptionSize: 'text-m',
1645
- descriptionWeight: 'font-light',
1646
- descriptionStyle: 'mt-xs',
1647
- },
1648
- };
1649
-
1650
- const Headline = JSX(({ className, version = '', headlineVersion = 'XL', title, description, align = 'text-center', as, isEmbedded = false, isTheme = false, ...rest }) => {
1651
- const versionStyle = headlineVersionStyles[headlineVersion];
1652
- const descriptionStyle = { marginTop: versionStyle.descriptionStyle };
1653
- return (jsxs(BlockWrapper, { className: style(isEmbedded ? '@container-normal' : '', className), defaultPadding: isEmbedded ? '' : 'p-6xl', version: version, isTheme: isTheme, ...rest, children: [title ? (jsx(Heading, { className: style('whitespace-pre-wrap', align), ...versionStyle?.title, as: as || versionStyle?.title.as, title: title })) : null, description ? (jsx(Paragraph, { size: versionStyle.descriptionSize, font: versionStyle.descriptionWeight, align: align, ...descriptionStyle, children: description })) : null] }));
1654
- });
1655
-
1656
1770
  const Bonus = JSX(({ className = '', title, description, bonusItems = [], align = AlignStyles, ...rest }) => (jsx(BlockWrapper, { className: className, defaultPadding: "p-6xl", ...rest, children: jsxs("div", { className: "container", children: [jsx(Headline, { className: "mb-xl", isEmbedded: true, title: title, description: description, headlineVersion: "M", align: align }), jsx("div", { className: "flex flex-wrap gap-3xl gap-x-m w-full", children: bonusItems.length > 0
1657
1771
  ? bonusItems.map((_, i) => (jsxs("div", { className: "w-full @xl:w-[48%] sm:space-y-xs flex flex-col grow p-xl sm:p-m border border-gray", children: [jsx("div", { className: "grow", children: jsx(Headline, { title: _?.title, description: _?.description, headlineVersion: "S", isEmbedded: true, align: "text-left" }) }), jsxs("div", { className: "flex justify-center sm:justify-between sm:items-end", children: [jsx("div", { className: "hidden sm:block", children: renderButtonsSection(_?.buttons) }), _.bonusItemContent?.bonusType
1658
1772
  ? renderBonusItemContent(_.bonusItemContent)
@@ -2783,10 +2897,6 @@
2783
2897
  : null;
2784
2898
  }
2785
2899
 
2786
- const getBorderStyle = (showBorder) => showBorder
2787
- ? 'border border-solid border-gray group-data-secondary:border-white/50 group-data-gray:border-main-divider'
2788
- : '';
2789
-
2790
2900
  const renderCardHighlight = ({ className, text = 'ХИТ' } = {}) => (jsxs("div", { className: style('w-14 h-14 bg-white flex flex-col items-center justify-center rounded-md shadow-main-black', className), children: [jsx(Icon, { iconVersion: "black", name: "HeartIcon", width: "24", height: "24" }), jsx(Paragraph, { size: "text-s", font: "font-normal", align: "text-center", color: "text-primary-text", children: text })] }));
2791
2901
 
2792
2902
  const cardBaseStyle = 'relative h-full';
@@ -2815,7 +2925,7 @@
2815
2925
  };
2816
2926
  const cardWrapperStyle = (_, { someCardsHighlighted }) => style(cardBaseStyle, someCardsHighlighted && (isCardHighlighted(_) ? 'pt-3xl' : 'pt-3xl sm:pt-16'));
2817
2927
  const cardStyle = (_, { someCardsHighlighted, showBorder, cardSize = 'normal', }) => style(cardBaseStyle, 'min-w-80', CARD_SIZE_MAP[cardSize], // TODO fix для RecommendationCard
2818
- someCardsHighlighted && (isCardHighlighted(_) ? 'pt-3xl sm:pt-16' : 'pt-3xl'), getBorderStyle(showBorder), showBorder && 'h-full');
2928
+ someCardsHighlighted && (isCardHighlighted(_) ? 'pt-3xl sm:pt-16' : 'pt-3xl'), getBorderStyle$1(showBorder), showBorder && 'h-full');
2819
2929
  const isCardHighlighted = (_) => _?.content && 'isHighlighting' in _.content && _.content.isHighlighting;
2820
2930
 
2821
2931
  const VISIBLE_ITEM_COUNT = 1;
@@ -2870,39 +2980,6 @@
2870
2980
  isVertical: true,
2871
2981
  })] })] }) })));
2872
2982
 
2873
- function renderBackwardButton(version, handleClick) {
2874
- const iconVersion = version === 'primary' ? 'white' : 'black';
2875
- const className = 'w-12 h-12 min-h-12 min-w-12 flex items-center justify-center';
2876
- const text = 'Вернуться назад';
2877
- return (jsxs("div", { className: "hidden sm:flex items-center gap-s", children: [jsx("div", { className: getRegularButtonClasses({ className, version, rounded: true }), onClick: handleClick, children: jsx(Img, { className: "w-4 h-4", image: {
2878
- icon: 'ArrowLeftIcon',
2879
- iconVersion: iconVersion,
2880
- } }) }), jsx(Button, { version: "link", className: "group-data-secondary:text-white/80", text: text, ariaLabel: text, onClick: handleClick })] }));
2881
- }
2882
-
2883
- const imageAlignmentMap = {
2884
- start: '@xl:self-start',
2885
- center: '@xl:self-center',
2886
- end: '@xl:self-end',
2887
- };
2888
- const BaseTile = JSX(({ className, version = 'primary', defaultPadding, padding, title = '', insetTitle = '', buttons, leftImage, rightImage, imageAlign, isImageAlwaysOnRight = false, isImageSecondary = false, backwardButton, children, }) => {
2889
- const router = useRouter();
2890
- const handleClick = useCallback((ev) => {
2891
- ev?.preventDefault();
2892
- router.back();
2893
- }, []);
2894
- return (jsxs("div", { className: getStyle(padding, defaultPadding, className), children: [backwardButton ? renderBackwardButton(version, handleClick) : null, title ? jsx("div", { className: "relative", children: title }) : null, jsxs("div", { className: style('grow relative flex flex-col @xl:flex-row gap-3xl w-full', leftImage ? 'self-start @xl:w-auto' : ''), children: [renderImageContainer(leftImage, { imageAlign, className: 'mx-auto' }), jsxs("div", { className: style('grid gap-3xl h-full', rightImage ? '@xl:grid-cols-2' : '', leftImage ? '' : 'grow'), children: [jsxs("div", { className: "grow space-y-lg min-w-fit", children: [insetTitle, children] }), renderImageContainer(rightImage, {
2895
- className: style('@xl:justify-self-end @xl:col-start-2', buttons ? rowSpanStyle(isImageAlwaysOnRight) : '', positionStyle(isImageAlwaysOnRight), imageSecondaryStyle(isImageSecondary)),
2896
- imageAlign,
2897
- }), renderButtons(buttons)] })] })] }));
2898
- });
2899
- const getStyle = (padding = '', defaultPadding = '', className = '') => style('relative flex flex-col gap-3xl overflow-hidden', padding || defaultPadding, className);
2900
- const rowSpanStyle = (isImageAlwaysOnRight) => isImageAlwaysOnRight ? 'row-span-2' : '@xl:row-span-2';
2901
- const positionStyle = (isImageAlwaysOnRight) => isImageAlwaysOnRight ? 'col-start-2 self-center' : '';
2902
- const renderButtons = (buttons) => buttons ? jsx("div", { className: "self-end", children: buttons }) : null;
2903
- const renderImageContainer = (image, { className, imageAlign }) => image ? (jsx("div", { className: style('shrink-1/2 justify-self-center', imageAlign && imageAlignmentMap[imageAlign], className), children: image })) : null;
2904
- const imageSecondaryStyle = (isImageSecondary) => isImageSecondary ? 'hidden @xl:block' : '';
2905
-
2906
2983
  const cardStyleMap = {
2907
2984
  black: 'bg-black',
2908
2985
  white: 'bg-white',
@@ -2936,64 +3013,6 @@
2936
3013
  .map((link, index) => (jsx(CarouselLinkButton, { ...link }, String(index)))) }, String(groupIndex)))) }));
2937
3014
  };
2938
3015
 
2939
- const sum = (list = []) => list.reduce((a, b) => a + b, 0);
2940
-
2941
- const avg = (items = []) => (items?.length ? sum(items) / items.length : 0);
2942
-
2943
- const deviation = (items) => items?.length ? Math.sqrt(Math.abs(avg(items.map((_) => _ ** 2)) - avg(items) ** 2)) : 0;
2944
-
2945
- const renderBenefitIcon = (icon, benefitsVersion = 'normal') => icon ? (jsx("div", { className: style('sm:w-12 sm:h-12 sm:min-w-12 w-11 h-11 min-w-11 box-border flex items-center justify-center rounded-icon', benefitsVersion === 'normal'
2946
- ? 'bg-secondary-light text-primary-main'
2947
- : 'bg-primary-main text-black group-data-secondary:bg-white/30 group-data-secondary:text-black'), children: jsx(Img, { className: "w-6 h-6", image: { ...icon, iconVersion: icon.iconVersion || benefitsVersion } }) })) : null;
2948
-
2949
- const getHtmlText = (html) => html.replace(/<\/?[^>]+\/?>/g, '').trim();
2950
-
2951
- const RichText = JSX((props) => {
2952
- const { __html = '', richVersion = '' } = props;
2953
- return getHtmlText(__html) ? (jsx("div", { className: style(richVersion, 'md-container'), dangerouslySetInnerHTML: { __html } })) : null;
2954
- });
2955
-
2956
- const renderBenefitDescription = (description, i) => description ? (jsx(Paragraph, { font: "font-light", size: "text-m", color: "text-secondary-text group-data-secondary:text-white", children: description }, `description-${i}`)) : null;
2957
-
2958
- const renderBenefitLabel = (label, i) => label ? (jsx(Text, { color: "text-primary-text group-data-secondary:text-white", size: "text-h6", children: label }, `label-${i}`)) : null;
2959
-
2960
- const renderBenefitText = (_, i) => _.type === 'rte' && '__html' in _ && _.__html ? (jsx(RichText, { ..._ }, `rte-${i}`)) : ([
2961
- 'label' in _ ? renderBenefitLabel(_.label, i) : null,
2962
- 'description' in _ ? (jsx("span", { className: _.descriptionClassName, children: renderBenefitDescription(_.description, i) }, String(i))) : null,
2963
- ]);
2964
-
2965
- const BenefitItem = JSX(({ className, benefitsVersion, ..._ }) => (jsxs("div", { className: style('flex gap-m min-w-56 items-center', className), children: ['icon' in _ ? renderBenefitIcon(_.icon, benefitsVersion) : null, jsx("div", { children: renderBenefitText(_) })] })));
2966
-
2967
- const MAX_BENEFITS_LEN_DEVIATION = 16;
2968
- const benefitLength = (_) => _.type === 'rte'
2969
- ? _?.__html?.length || 0
2970
- : Math.max(_?.label?.length || 0, _?.description?.length || 0);
2971
- const isDistortedBenefits = (benefits) => deviation(benefits.map(benefitLength)) > MAX_BENEFITS_LEN_DEVIATION;
2972
- const hasIcon = (_) => _ && 'icon' in _ && _.icon && (_.icon.icon || _.icon.src);
2973
- const isTextualBenefits = (benefits) => !benefits.some(hasIcon);
2974
- const DefaultBenefitsList = JSX(({ className, benefitsVersion = 'normal', benefits }) => benefits?.length ? (jsx("div", { className: style('flex gap-x-m gap-y-s', isDistortedBenefits(benefits) || isTextualBenefits(benefits) ? 'flex-col' : 'flex-wrap', className), children: benefits.map((_, i) => (jsx(BenefitItem, { benefitsVersion: benefitsVersion, ..._ }, String(i)))) })) : null);
2975
-
2976
- const TabularBenefitsList = JSX(({ className, benefits }) => benefits?.length ? (jsx("div", { className: style('grid grid-cols-[max-content_1fr] auto-rows-auto items-baseline gap-x-m gap-y-xs', className), children: benefits.flatMap(renderBenefitText) })) : null);
2977
-
2978
- const BenefitsList = JSX(({ isTabularBenefits, ...rest }) => isTabularBenefits ? jsx(TabularBenefitsList, { ...rest }) : jsx(DefaultBenefitsList, { ...rest }));
2979
-
2980
- const PriceList = JSX(({ priceList }) => priceList?.length ? (jsx("div", { className: "flex flex-wrap xl:flex-nowrap xl:bg-main-divider xl:rounded-md p-xs gap-xl", children: priceList.map(renderPriceListItem) })) : null);
2981
- const renderPriceListItem = ({ label, amount }) => (jsxs("div", { className: "basis-full flex flex-col-reverse sm:flex-row sm:justify-between sm:bg-main-divider sm:py-m sm:px-lg sm:rounded-md items-baseline whitespace-pre", children: [jsx(Text, { font: "font-light", size: "text-l", color: "text-secondary-text", children: label }), amount ? (jsxs("span", { className: "font-sans text-h6 sm:text-primary-main text-primary-text", children: [toLocalNumberFormat(2)(amount), " \u20BD"] })) : null] }));
2982
-
2983
- const Tags = JSX(({ className, tags }) => tags?.length ? (jsx("div", { className: style('flex flex-wrap gap-xs', className), role: "list", children: tags.map(renderTag) })) : null);
2984
- const renderTag = (tag, key) => (jsx("div", { className: "p-xs border-solid border rounded-md border-gray", role: "listitem", children: jsx(Text, { size: "text-m", font: "font-light", children: tag }) }, String(key)));
2985
-
2986
- const BaseProductTile = JSX(
2987
- // eslint-disable-next-line max-lines-per-function
2988
- ({ className, padding, defaultPadding, title, description, headlineVersion = 'L', align = 'text-left', benefitsVersion, isTabularBenefits, benefits, __html, isFullWidthTitle, items, isDotted = true, priceList = [], listItemSize, tags = [], buttons, image, imageOptions: { imageAlign = 'center', directionRight = true, isImageAlwaysOnRight, isImageSecondary = false, } = {}, backwardButton, children, ...rest }) => {
2989
- const img = image?.src ? jsx(Img, { image: image }) : null;
2990
- const headline = (jsx(Headline, { title: title, description: description, headlineVersion: headlineVersion, align: align, isEmbedded: true }));
2991
- const filteredBenefits = benefits?.filter((_) => _?.type === 'rte' || 'label' in _ || 'description' in _);
2992
- return (jsx(BaseTile, { className: className, padding: padding, defaultPadding: defaultPadding, ...(isFullWidthTitle ? { title: headline } : { insetTitle: headline }), ...leftOrRightImage(img, directionRight), isImageSecondary: isImageSecondary, imageAlign: imageAlign, isImageAlwaysOnRight: isImageAlwaysOnRight, buttons: renderButtonsSection(buttons), backwardButton: backwardButton, ...rest, children: jsxs("div", { className: "flex flex-col sm:gap-xl gap-4xl", children: [filteredBenefits?.length ? (jsx(BenefitsList, { benefitsVersion: benefitsVersion, isTabularBenefits: isTabularBenefits, benefits: filteredBenefits })) : null, __html ? jsx(RichText, { __html: __html }) : null, items?.length ? (jsx(List, { items: items, isDotted: isDotted, listItemSize: listItemSize })) : null, children, priceList?.length ? jsx(PriceList, { priceList: priceList }) : null, renderTags(tags)] }) }));
2993
- });
2994
- const leftOrRightImage = (img, directionRight) => directionRight ? { rightImage: img } : { leftImage: img };
2995
- const renderTags = (tags) => (tags?.length ? jsx(Tags, { tags: tags }) : null);
2996
-
2997
3016
  const LinkWrapper = JSX(({ className = '', href, target, isRemote = false, children }) => {
2998
3017
  const link = useLink({ isRemote });
2999
3018
  const linkProps = link({ href, target });
@@ -3146,7 +3165,7 @@
3146
3165
  const TableCell = JSX(({ cell, isFirstRow, isLastRow, isFillGradient }) => {
3147
3166
  const cellWrapperStyle = style('w-80 box-border flex flex-col', borderStyle, !isLastRow ? 'border-y-0' : 'border-t-0 rounded-b-md', isFillGradient ? gradientStyle : '');
3148
3167
  const cellStyle = style('mx-2xl h-full', dividerStyle$1, isFillGradient && isFirstRow ? 'border-t' : '', !isLastRow ? 'border-solid' : 'border-b-0');
3149
- return (jsx("div", { className: cellWrapperStyle, role: "cell", children: jsx("div", { className: cellStyle, children: cell.map((item, i) => renderCellInner(item, i, isFillGradient)) }) }));
3168
+ return (jsx("div", { className: cellWrapperStyle, role: "cell", children: jsx("div", { className: cellStyle, children: cell ? cell.map((item, i) => renderCellInner(item, i, isFillGradient)) : null }) }));
3150
3169
  });
3151
3170
  const labelStyle = (isFillGradient = false) => `text-xl m-0 ${isFillGradient ? 'text-white' : ''}`;
3152
3171
  const descriptionStyle = (isFillGradient = false) => `text-s opacity-80 ${isFillGradient ? 'text-white' : 'text-secondary-text'}`;
@@ -3197,6 +3216,8 @@
3197
3216
  const renderBlocks = (info) => (jsx("div", { className: "flex gap-5xl grow basis-0", children: info.map((column, index) => renderBlocksColumn({ column, index })) }));
3198
3217
  const renderBlocksColumn = ({ column, index }) => column ? (jsx("div", { className: "flex flex-col gap-xl grow basis-0", children: column.map(({ title = '', description, additionalDescription, button }, key) => (jsxs("div", { children: [jsx(Headline, { title: title, description: description, headlineVersion: "XS", align: "text-left", isEmbedded: true }), additionalDescription ? (jsx("div", { className: "mt-xs opacity-80", children: jsx(Paragraph, { size: "text-m", font: "font-light", children: additionalDescription }) })) : null, button?.href ? jsx(Button, { className: "mt-xl", ...button }) : null] }, String(key)))) }, `col-${String(index)}`)) : null;
3199
3218
 
3219
+ const isOdd = (n) => n % 2 !== 0;
3220
+
3200
3221
  const TextWithIcon = JSX(({ textNode, iconNode, tag, onClick, justifyContent = 'between', className, ...rest }) => {
3201
3222
  const Tag = tag;
3202
3223
  return (jsxs(Tag, { tag: tag, className: style('flex items-center w-full gap-1', justifyContent === 'between' ? 'justify-between' : 'justify-center', className), onClick: onClick, ...rest, children: [textNode ? jsx("div", { children: textNode }) : null, iconNode ? jsx("div", { children: iconNode }) : null] }));
@@ -3222,8 +3243,8 @@
3222
3243
  const [visibleBlocks, hiddenBlocks] = topItemsCount > 0
3223
3244
  ? [blocksToRender.slice(0, topItemsCount), blocksToRender.slice(topItemsCount)]
3224
3245
  : [blocksToRender, []];
3225
- return (jsxs("div", { children: [jsx("div", { className: style(blocksToRender.length ? 'hidden' : 'block'), children: notFound ? jsx(NotFound, { ...notFound }) : null }), jsxs("div", { className: style('space-y-2xs', blocksToRender.length ? '' : 'hidden'), children: [jsx("div", { className: style(resultsGridStyle), children: renderBlocksList(visibleBlocks, { ...rest.options, parent: block }) }), jsx(Foldable, { renderFoldableSection: ({ isUnfolded }) => {
3226
- return (jsx(FoldableSection, { className: style(resultsGridStyle), isUnfolded: isUnfolded, children: renderBlocksList(hiddenBlocks, { ...rest.options, parent: block }) }));
3246
+ return (jsxs("div", { children: [jsx("div", { className: style(blocksToRender.length ? 'hidden' : 'block'), children: notFound ? jsx(NotFound, { ...notFound }) : null }), jsxs("div", { className: style('space-y-2xs', blocksToRender.length ? '' : 'hidden'), children: [jsxs("div", { className: style(resultsGridStyle), children: [renderBlocksList(visibleBlocks, { ...rest.options, parent: block }), isOdd(visibleBlocks.length) ? jsx(AdTile, { className: "col-span-6" }) : null] }), jsx(Foldable, { renderFoldableSection: ({ isUnfolded }) => {
3247
+ return (jsxs(FoldableSection, { className: style(resultsGridStyle), isUnfolded: isUnfolded, children: [renderBlocksList(hiddenBlocks, { ...rest.options, parent: block }), isOdd(hiddenBlocks.length) ? jsx(AdTile, { className: "col-span-6" }) : null] }));
3227
3248
  }, renderFoldButton: ({ isUnfolded, onToggle }) => (jsx(DefaultFoldButton, { className: style(topItemsCount < 1 ? 'hidden' : ''), disabled: !hiddenBlocks?.length, label: label, icon: ICONS[Number(isUnfolded)], dataTheme: rest.options?.page?.colorPalette, onClick: onToggle })) })] })] }));
3228
3249
  });
3229
3250
 
@@ -4267,7 +4288,7 @@
4267
4288
  const HorizontalLayout = JSX(({ className = '', gap = 'XS', isPadding = false, version = 'transparent', isTheme = false, isCardBorder, ...rest }) => (jsx(BlockWrapper, { className: style('relative', 'grid grid-cols-12', gapStyles[gap], className), defaultPadding: isPadding ? 'p-6xl' : '', version: version, isTheme: isTheme, ...rest, children: renderChildren({
4268
4289
  ...rest,
4269
4290
  extraProps: {
4270
- className: getBorderStyle(isCardBorder),
4291
+ className: getBorderStyle$1(isCardBorder),
4271
4292
  },
4272
4293
  }) })));
4273
4294
  HorizontalLayout.childrenTypes = {
@@ -4557,11 +4578,6 @@
4557
4578
  MortgageFiltration.childrenTypes = ['ProductTile'];
4558
4579
  MortgageFiltration.childSchema = (content) => content?.filtrationSchema || {};
4559
4580
 
4560
- const isSSR = () => Boolean(typeof globalThis.process === 'object' && globalThis.process && globalThis.process.version);
4561
-
4562
- const isClient = !isSSR();
4563
- const ClientOnly = JSX(({ children }) => (isClient ? children : null));
4564
-
4565
4581
  function renderClusterer(yandexMaps, map, points) {
4566
4582
  map.geoObjects.removeAll();
4567
4583
  const clusterIconContentLayout = yandexMaps.templateLayoutFactory.createClass('<div style="margin-top: -3px;">{{properties.geoObjects.length}}</div>');
@@ -4982,8 +4998,6 @@
4982
4998
  const renderShimmerItem = (width, index) => (jsx("div", { style: { width: `${width || 100}%` }, className: "h-4 mt-xs bg-secondary-light" }, String(index)));
4983
4999
  const goldenSequence = (first, size) => [first].concat(size > 0 ? goldenSequence(first / GOLDEN_RATIO, size - 1) : []);
4984
5000
 
4985
- const ProductBlock = JSX(({ className, padding, showBorder, ...rest }) => (jsx(BlockWrapper, { className: style('overflow-hidden flex flex-col gap-3xl box-border', getBorderStyle(showBorder), className), padding: "p-0", ...rest, children: jsx(BaseProductTile, { defaultPadding: "p-6xl", padding: padding, className: "grow h-full", ...rest }) })));
4986
-
4987
5001
  const ProductGallery = JSX(({ className = '', padding, slides = [], ...rest }) => {
4988
5002
  const [activeSlideIndex, setActiveSlideIndex] = useState(0);
4989
5003
  return (jsxs(BlockWrapper, { className: style('box-border overflow-hidden', className), defaultPadding: "py-6xl", padding: padding, ...rest, children: [jsx("div", { className: "flex duration-1000", style: { transform: `translateX(-${activeSlideIndex * 100}%)` }, role: "list", children: slides.map(({ productBlock }, i) => (jsx("div", { className: "box-border grow-0 shrink-0 basis-full", role: "listitem", children: jsx(BaseProductTile, { className: "pl-6xl h-full", headlineVersion: "M", isFullWidthTitle: false, ...productBlock, ...rest }) }, String(i)))) }), jsx("div", { className: "h-28 px-xs mt-m -mb-m flex gap-xs box-border", children: slides.map(renderNavButton({ activeSlideIndex, onClick: setActiveSlideIndex })) })] }));
@@ -5507,7 +5521,7 @@
5507
5521
  const VerticalLayout = JSX(({ className = '', gap = '', isPadding = false, isInnerPadding = true, version = 'transparent', isTheme = false, isInnerBorder = false, ...rest }) => (jsx(BlockWrapper, { className: style('relative flex flex-col', gapStyles[gap], className), defaultPadding: isPadding ? 'p-6xl' : '', version: version, isTheme: isTheme, ...rest, children: renderChildren({
5508
5522
  ...rest,
5509
5523
  extraProps: {
5510
- className: style('w-full', getBorderStyle(isInnerBorder)),
5524
+ className: style('w-full', getBorderStyle$1(isInnerBorder)),
5511
5525
  padding: isInnerPadding ? '' : 'p-0',
5512
5526
  },
5513
5527
  }) })));
@@ -5528,6 +5542,7 @@
5528
5542
  });
5529
5543
 
5530
5544
  const Blocks = {
5545
+ AdTile,
5531
5546
  ApplicationForm,
5532
5547
  BenefitsBlock,
5533
5548
  Bonus,
@@ -5545,8 +5560,8 @@
5545
5560
  CarouselTariffsCard,
5546
5561
  ComparisonTable,
5547
5562
  ContactsBlock,
5548
- Depository,
5549
5563
  DepositFiltration,
5564
+ Depository,
5550
5565
  ErrorBlock,
5551
5566
  ExchangeRateTile,
5552
5567
  Footer,
@@ -5570,8 +5585,8 @@
5570
5585
  RollupItem,
5571
5586
  SafeDepositRental,
5572
5587
  StepsBlock,
5573
- SwipeListControlBlock,
5574
5588
  StickyBottomMenu,
5589
+ SwipeListControlBlock,
5575
5590
  Tabs,
5576
5591
  TariffsTable,
5577
5592
  TextBlock,
@@ -5810,7 +5825,7 @@
5810
5825
  return (jsx("div", { className: "flex items-end absolute bottom-0 right-0 h-full pointer-events-none", children: jsx(LikeControl, { className: "rounded-tl-3xl sticky bottom-0 pointer-events-auto" }) }));
5811
5826
  }
5812
5827
 
5813
- const packageVersion = "0.14.56";
5828
+ const packageVersion = "0.14.58";
5814
5829
 
5815
5830
  exports.Blocks = Blocks;
5816
5831
  exports.ContentPage = ContentPage;