@redneckz/wildless-cms-uni-blocks 0.2.76 → 0.2.79

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 (103) hide show
  1. package/bundle/blocks.schema.json +5 -82
  2. package/bundle/bundle.umd.js +35 -0
  3. package/bundle/bundle.umd.min.js +1 -1
  4. package/dist/components/Accordion/Accordion.d.ts +5 -0
  5. package/dist/components/Accordion/Accordion.js +10 -0
  6. package/dist/components/Accordion/Accordion.js.map +1 -0
  7. package/dist/components/Accordion/AccordionBlocks.d.ts +4 -0
  8. package/dist/components/Accordion/AccordionBlocks.js +7 -0
  9. package/dist/components/Accordion/AccordionBlocks.js.map +1 -0
  10. package/dist/components/Accordion/AccordionContent.d.ts +14 -0
  11. package/dist/components/Accordion/AccordionContent.js +2 -0
  12. package/dist/components/Accordion/AccordionContent.js.map +1 -0
  13. package/dist/components/Accordion/AccordionItem.d.ts +5 -0
  14. package/dist/components/Accordion/AccordionItem.js +35 -0
  15. package/dist/components/Accordion/AccordionItem.js.map +1 -0
  16. package/dist/components/Blocks.d.ts +1 -0
  17. package/dist/components/Blocks.js +2 -0
  18. package/dist/components/Blocks.js.map +1 -1
  19. package/dist/components/CreditCalculator/CreditCalculator.d.ts +4 -0
  20. package/dist/components/CreditCalculator/CreditCalculator.js +29 -0
  21. package/dist/components/CreditCalculator/CreditCalculator.js.map +1 -0
  22. package/dist/content-page-repository/ContentPageRepository.d.ts +3 -0
  23. package/dist/content-page-repository/ContentPageRepository.js +14 -0
  24. package/dist/content-page-repository/ContentPageRepository.js.map +1 -1
  25. package/dist/ui-kit/Checkbox/Checkbox.d.ts +2 -0
  26. package/dist/ui-kit/Checkbox/Checkbox.js +17 -0
  27. package/dist/ui-kit/Checkbox/Checkbox.js.map +1 -0
  28. package/dist/ui-kit/Checkbox/CheckboxProps.d.ts +6 -0
  29. package/dist/ui-kit/Checkbox/CheckboxProps.js +2 -0
  30. package/dist/ui-kit/Checkbox/CheckboxProps.js.map +1 -0
  31. package/dist/ui-kit/Icon/IconProps.d.ts +4 -1
  32. package/dist/ui-kit/Icon/IconProps.js +3 -0
  33. package/dist/ui-kit/Icon/IconProps.js.map +1 -1
  34. package/dist/ui-kit/InputRange/InputRange.d.ts +2 -0
  35. package/dist/ui-kit/InputRange/InputRange.js +25 -0
  36. package/dist/ui-kit/InputRange/InputRange.js.map +1 -0
  37. package/dist/ui-kit/InputRange/InputRangeProps.d.ts +10 -0
  38. package/dist/ui-kit/InputRange/InputRangeProps.js +2 -0
  39. package/dist/ui-kit/InputRange/InputRangeProps.js.map +1 -0
  40. package/dist/utils/clamp.d.ts +1 -0
  41. package/dist/utils/clamp.js +5 -0
  42. package/dist/utils/clamp.js.map +1 -0
  43. package/lib/common.css +1 -1
  44. package/lib/components/Accordion/Accordion.d.ts +5 -0
  45. package/lib/components/Accordion/Accordion.js +8 -0
  46. package/lib/components/Accordion/Accordion.js.map +1 -0
  47. package/lib/components/Accordion/AccordionBlocks.d.ts +4 -0
  48. package/lib/components/Accordion/AccordionBlocks.js +6 -0
  49. package/lib/components/Accordion/AccordionBlocks.js.map +1 -0
  50. package/lib/components/Accordion/AccordionContent.d.ts +14 -0
  51. package/lib/components/Accordion/AccordionContent.js +2 -0
  52. package/lib/components/Accordion/AccordionContent.js.map +1 -0
  53. package/lib/components/Accordion/AccordionItem.d.ts +5 -0
  54. package/lib/components/Accordion/AccordionItem.js +30 -0
  55. package/lib/components/Accordion/AccordionItem.js.map +1 -0
  56. package/lib/components/Blocks.d.ts +1 -0
  57. package/lib/components/Blocks.js +2 -0
  58. package/lib/components/Blocks.js.map +1 -1
  59. package/lib/components/CreditCalculator/CreditCalculator.d.ts +4 -0
  60. package/lib/components/CreditCalculator/CreditCalculator.js +27 -0
  61. package/lib/components/CreditCalculator/CreditCalculator.js.map +1 -0
  62. package/lib/content-page-repository/ContentPageRepository.d.ts +3 -0
  63. package/lib/content-page-repository/ContentPageRepository.js +14 -0
  64. package/lib/content-page-repository/ContentPageRepository.js.map +1 -1
  65. package/lib/ui-kit/Checkbox/Checkbox.d.ts +2 -0
  66. package/lib/ui-kit/Checkbox/Checkbox.js +15 -0
  67. package/lib/ui-kit/Checkbox/Checkbox.js.map +1 -0
  68. package/lib/ui-kit/Checkbox/CheckboxProps.d.ts +6 -0
  69. package/lib/ui-kit/Checkbox/CheckboxProps.js +2 -0
  70. package/lib/ui-kit/Checkbox/CheckboxProps.js.map +1 -0
  71. package/lib/ui-kit/Icon/IconProps.d.ts +4 -1
  72. package/lib/ui-kit/Icon/IconProps.js +3 -0
  73. package/lib/ui-kit/Icon/IconProps.js.map +1 -1
  74. package/lib/ui-kit/InputRange/InputRange.d.ts +2 -0
  75. package/lib/ui-kit/InputRange/InputRange.js +23 -0
  76. package/lib/ui-kit/InputRange/InputRange.js.map +1 -0
  77. package/lib/ui-kit/InputRange/InputRangeProps.d.ts +10 -0
  78. package/lib/ui-kit/InputRange/InputRangeProps.js +2 -0
  79. package/lib/ui-kit/InputRange/InputRangeProps.js.map +1 -0
  80. package/lib/utils/clamp.d.ts +1 -0
  81. package/lib/utils/clamp.js +2 -0
  82. package/lib/utils/clamp.js.map +1 -0
  83. package/package.json +3 -3
  84. package/src/common.css +40 -0
  85. package/src/components/Accordion/Accordion.fixture.tsx +62 -0
  86. package/src/components/Accordion/Accordion.tsx +22 -0
  87. package/src/components/Accordion/AccordionBlocks.tsx +7 -0
  88. package/src/components/Accordion/AccordionContent.ts +18 -0
  89. package/src/components/Accordion/AccordionItem.tsx +68 -0
  90. package/src/components/Blocks.ts +2 -0
  91. package/src/components/ContentPage/ContentPage.page.json +78 -0
  92. package/src/components/CreditCalculator/CreditCalculator.fixture.tsx +4 -0
  93. package/src/components/CreditCalculator/CreditCalculator.tsx +106 -0
  94. package/src/content-page-repository/ContentPageRepository.ts +17 -0
  95. package/src/icons/DocIcon.svg +5 -0
  96. package/src/icons/MinusIcon.svg +1 -0
  97. package/src/icons/PlusIcon.svg +1 -0
  98. package/src/ui-kit/Checkbox/Checkbox.tsx +36 -0
  99. package/src/ui-kit/Checkbox/CheckboxProps.ts +6 -0
  100. package/src/ui-kit/Icon/IconProps.ts +3 -0
  101. package/src/ui-kit/InputRange/InputRange.tsx +63 -0
  102. package/src/ui-kit/InputRange/InputRangeProps.ts +10 -0
  103. package/src/utils/clamp.ts +2 -0
@@ -20,5 +20,8 @@ export var IconMap;
20
20
  IconMap[IconMap["TelegramIcon"] = 17] = "TelegramIcon";
21
21
  IconMap[IconMap["VKIcon"] = 18] = "VKIcon";
22
22
  IconMap[IconMap["GlassIcon"] = 19] = "GlassIcon";
23
+ IconMap[IconMap["DocIcon"] = 20] = "DocIcon";
24
+ IconMap[IconMap["PlusIcon"] = 21] = "PlusIcon";
25
+ IconMap[IconMap["MinusIcon"] = 22] = "MinusIcon";
23
26
  })(IconMap || (IconMap = {}));
24
27
  //# sourceMappingURL=IconProps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IconProps.js","sourceRoot":"","sources":["../../../src/ui-kit/Icon/IconProps.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,OAqBX;AArBD,WAAY,OAAO;IACjB,+DAAmB,CAAA;IACnB,+CAAW,CAAA;IACX,qDAAc,CAAA;IACd,+CAAW,CAAA;IACX,mEAAqB,CAAA;IACrB,iDAAY,CAAA;IACZ,2DAAiB,CAAA;IACjB,6CAAU,CAAA;IACV,6CAAU,CAAA;IACV,+CAAW,CAAA;IACX,kDAAY,CAAA;IACZ,0CAAQ,CAAA;IACR,sDAAc,CAAA;IACd,sEAAsB,CAAA;IACtB,0DAAgB,CAAA;IAChB,oDAAa,CAAA;IACb,sDAAc,CAAA;IACd,sDAAc,CAAA;IACd,0CAAQ,CAAA;IACR,gDAAW,CAAA;AACb,CAAC,EArBW,OAAO,KAAP,OAAO,QAqBlB"}
1
+ {"version":3,"file":"IconProps.js","sourceRoot":"","sources":["../../../src/ui-kit/Icon/IconProps.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,OAwBX;AAxBD,WAAY,OAAO;IACjB,+DAAmB,CAAA;IACnB,+CAAW,CAAA;IACX,qDAAc,CAAA;IACd,+CAAW,CAAA;IACX,mEAAqB,CAAA;IACrB,iDAAY,CAAA;IACZ,2DAAiB,CAAA;IACjB,6CAAU,CAAA;IACV,6CAAU,CAAA;IACV,+CAAW,CAAA;IACX,kDAAY,CAAA;IACZ,0CAAQ,CAAA;IACR,sDAAc,CAAA;IACd,sEAAsB,CAAA;IACtB,0DAAgB,CAAA;IAChB,oDAAa,CAAA;IACb,sDAAc,CAAA;IACd,sDAAc,CAAA;IACd,0CAAQ,CAAA;IACR,gDAAW,CAAA;IACX,4CAAS,CAAA;IACT,8CAAU,CAAA;IACV,gDAAW,CAAA;AACb,CAAC,EAxBW,OAAO,KAAP,OAAO,QAwBlB"}
@@ -0,0 +1,2 @@
1
+ import type { InputRangeProps } from './InputRangeProps';
2
+ export declare const InputRange: (props: import("@redneckz/uni-jsx").PropsWithChildren<InputRangeProps, any>, context?: any) => any;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@redneckz/uni-jsx/jsx-runtime";
2
+ import { JSX } from '@redneckz/uni-jsx';
3
+ export const InputRange = JSX(({ className, title, items = [], min = 1, max = 100, step = 1, value = min, onChange }) => {
4
+ const handleChange = (value) => {
5
+ if (!onChange)
6
+ return;
7
+ const sanitizedValue = Number(value.replace(/\D/g, ''));
8
+ onChange(sanitizedValue);
9
+ };
10
+ const inputStyle = {
11
+ backgroundSize: `${(value * 100) / max - 1}% 100%`,
12
+ };
13
+ const handleBlur = () => {
14
+ if (!onChange)
15
+ return;
16
+ if (value < min)
17
+ onChange(min);
18
+ if (value > max)
19
+ onChange(max);
20
+ };
21
+ return (_jsxs("div", { className: className, children: [_jsxs("div", { className: "relative", children: [title ? (_jsx("span", { className: "absolute text-xs text-secondary-text top-1 mt-0.5 pl-4 ml-0.5", children: title })) : null, _jsx("input", { className: `m-0 font-sans text-sm w-full h-12 border-2 border-solid border-main-divider rounded-md outline-none p-0 pl-4 m-0 box-border text-primary-text ${title ? 'pt-4' : ''}`, value: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ' '), onChange: (e) => handleChange(e.target.value), onBlur: handleBlur }), _jsx("div", { className: "absolute inset-x-0 mt-0.5 top-8 px-4", children: _jsx("input", { className: "box-border w-full m-0 cursor-pointer slider", type: "range", min: min, max: max, step: step, value: value, onChange: (e) => handleChange(e.target.value), style: inputStyle }) })] }), _jsx("div", { className: "flex justify-between mt-3 mb-4", children: items.map((item, i) => (_jsx("span", { className: "text-xs text-secondary-text pl-4", children: item }, String(i)))) })] }));
22
+ });
23
+ //# sourceMappingURL=InputRange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputRange.js","sourceRoot":"","sources":["../../../src/ui-kit/InputRange/InputRange.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAGxC,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAC3B,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxF,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACxD,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG;QACjB,cAAc,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ;KACnD,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,KAAK,GAAG,GAAG;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,GAAG,GAAG;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAE,SAAS,aACvB,eAAK,SAAS,EAAC,UAAU,aACtB,KAAK,CAAC,CAAC,CAAC,CACP,eAAM,SAAS,EAAC,+DAA+D,YAC5E,KAAK,GACD,CACR,CAAC,CAAC,CAAC,IAAI,EACR,gBACE,SAAS,EAAE,iJACT,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EACnB,EAAE,EACF,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,CAAC,EAC1D,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC7C,MAAM,EAAE,UAAU,GAClB,EACF,cAAK,SAAS,EAAC,sCAAsC,YACnD,gBACE,SAAS,EAAC,6CAA6C,EACvD,IAAI,EAAC,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC7C,KAAK,EAAE,UAAU,GACjB,GACE,IACF,EACN,cAAK,SAAS,EAAC,gCAAgC,YAC5C,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,eAAsB,SAAS,EAAC,kCAAkC,YAC/D,IAAI,IADI,MAAM,CAAC,CAAC,CAAC,CAEb,CACR,CAAC,GACE,IACF,CACP,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface InputRangeProps {
2
+ className?: string;
3
+ items?: string[];
4
+ min?: number;
5
+ max?: number;
6
+ step?: number;
7
+ value?: number;
8
+ title?: string;
9
+ onChange?: (value: number) => void;
10
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=InputRangeProps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputRangeProps.js","sourceRoot":"","sources":["../../../src/ui-kit/InputRange/InputRangeProps.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare const clamp: (value: number, min: number, max: number) => number;
@@ -0,0 +1,2 @@
1
+ export const clamp = (value, min, max) => Math.max(min, Math.min(value, max));
2
+ //# sourceMappingURL=clamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clamp.js","sourceRoot":"","sources":["../../src/utils/clamp.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW,EAAE,EAAE,CAC/D,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redneckz/wildless-cms-uni-blocks",
3
- "version": "0.2.76",
3
+ "version": "0.2.79",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -84,8 +84,8 @@
84
84
  "postbuild:lib": "replace-in-file --configFile=replace-config.lib.cjs --verbose",
85
85
  "build:commonjs": "rimraf ./dist && tsc --module commonjs --noImplicitUseStrict --outDir dist",
86
86
  "bundle": "rimraf ./bundle && rollup -c && npm run build:schema",
87
- "build:schema": "ts-json-schema-generator --path './src/**/*Content.ts' --no-type-check --type '*' -o ./bundle/blocks.schema.json",
88
- "build:style": "postcss './src/**/*.css' --env production --dir ./lib",
87
+ "build:schema": "ts-json-schema-generator --path ./src/**/*Content.ts --no-type-check -o ./bundle/blocks.schema.json",
88
+ "build:style": "postcss ./src/**/*.css --env production --dir ./lib",
89
89
  "build:icons": "svgo -f ./src/icons -o ./cosmos-static/icons",
90
90
  "size": "size-limit",
91
91
  "test": "jest --coverage",
package/src/common.css CHANGED
@@ -98,4 +98,44 @@
98
98
  scroll-snap-stop: always;
99
99
  width: 100%;
100
100
  }
101
+
102
+ input[type='range'].slider {
103
+ -webkit-appearance: none;
104
+ height: 4px;
105
+ background: transparent;
106
+ border-radius: 5px;
107
+ background-image: linear-gradient(#42ab44, #42ab44);
108
+ background-repeat: no-repeat;
109
+ }
110
+
111
+ input[type='range'].slider::-webkit-slider-thumb {
112
+ -webkit-appearance: none;
113
+ height: 18px;
114
+ width: 18px;
115
+ border-radius: 50%;
116
+ background: #fff;
117
+ cursor: pointer;
118
+ box-shadow: none;
119
+ border: 3px solid #42ab44;
120
+ }
121
+
122
+ input[type='range'].slider::-moz-range-thumb {
123
+ height: 12px;
124
+ width: 12px;
125
+ border-radius: 50%;
126
+ background: #fff;
127
+ cursor: pointer;
128
+ box-shadow: none;
129
+ border: 3px solid #42ab44;
130
+ }
131
+
132
+ input[type='range'].slider::-ms-thumb {
133
+ height: 18px;
134
+ width: 18px;
135
+ border-radius: 50%;
136
+ background: #fff;
137
+ cursor: pointer;
138
+ box-shadow: none;
139
+ border: 3px solid #42ab44;
140
+ }
101
141
  }
@@ -0,0 +1,62 @@
1
+ import { context } from '../../setup-fixture';
2
+ import type { AccordionProps } from './Accordion';
3
+ import type { TextBlockContent } from '../TextBlock/TextBlockContent';
4
+ import { Accordion } from './Accordion';
5
+
6
+ const TEXT_BLOCK: TextBlockContent = {
7
+ title: 'Title',
8
+ description:
9
+ 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?',
10
+ blockVersion: 'secondary-light',
11
+ iconVersion: 'small',
12
+ };
13
+
14
+ const propsTextBlock: AccordionProps = {
15
+ title: 'Accordion title',
16
+ context,
17
+ accordionItems: [
18
+ {
19
+ label: 'Accordion label 1',
20
+ blocks: [
21
+ {
22
+ type: 'TextBlock',
23
+ data: TEXT_BLOCK,
24
+ },
25
+ {
26
+ type: 'TextBlock',
27
+ data: TEXT_BLOCK,
28
+ },
29
+ ],
30
+ },
31
+ {
32
+ label: 'Accordion label 2',
33
+ blocks: [
34
+ {
35
+ type: 'TextBlock',
36
+ data: TEXT_BLOCK,
37
+ },
38
+ {
39
+ type: 'TextBlock',
40
+ data: TEXT_BLOCK,
41
+ },
42
+ ],
43
+ },
44
+ {
45
+ label: 'Accordion label 3',
46
+ blocks: [
47
+ {
48
+ type: 'TextBlock',
49
+ data: TEXT_BLOCK,
50
+ },
51
+ {
52
+ type: 'TextBlock',
53
+ data: TEXT_BLOCK,
54
+ },
55
+ ],
56
+ },
57
+ ],
58
+ };
59
+
60
+ export default {
61
+ 'with text block': <Accordion {...propsTextBlock} />,
62
+ };
@@ -0,0 +1,22 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { UniBlockProps } from '../../types';
3
+ import type { AccordionContent } from './AccordionContent';
4
+ import { AccordionItem } from './AccordionItem';
5
+ import { Title } from '../../ui-kit/Title/Title';
6
+
7
+ export interface AccordionProps extends AccordionContent, UniBlockProps {}
8
+
9
+ export const Accordion = JSX<AccordionProps>(({ title, accordionItems, context, className }) => {
10
+ return (
11
+ <section className={`p-[50px] font-sans bg-white text-primary-text ${className || ''}`}>
12
+ {title ? <Title className="m-0 mb-2.5">{title}</Title> : null}
13
+ {accordionItems?.length ? (
14
+ <ul className="list-none m-0 p-0">
15
+ {accordionItems.map((item, i) => (
16
+ <AccordionItem key={`AccordionItem${i}`} {...item} context={context} />
17
+ ))}
18
+ </ul>
19
+ ) : null}
20
+ </section>
21
+ );
22
+ });
@@ -0,0 +1,7 @@
1
+ import { TextBlock } from '../TextBlock/TextBlock';
2
+
3
+ const AccordionBlocks = {
4
+ TextBlock,
5
+ };
6
+
7
+ export default AccordionBlocks;
@@ -0,0 +1,18 @@
1
+ import type { TextBlockContent } from '../TextBlock/TextBlockContent';
2
+
3
+ export interface AccordionContent {
4
+ title?: string;
5
+ accordionItems?: AccordionItemContent[];
6
+ }
7
+
8
+ export interface AccordionItemContent {
9
+ label?: string;
10
+ blocks?: AccordionBlockContent[];
11
+ }
12
+
13
+ export type AccordionBlockContent = {
14
+ type?: string;
15
+ data?: AccordionDataContent;
16
+ };
17
+
18
+ export type AccordionDataContent = TextBlockContent;
@@ -0,0 +1,68 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { UniBlockProps } from '../../types';
3
+ import type { AccordionItemContent, AccordionBlockContent } from './AccordionContent';
4
+ import { Icon } from '../../ui-kit/Icon/Icon';
5
+ import AccordionBlocks from './AccordionBlocks';
6
+
7
+ export interface AccordionItemProps extends AccordionItemContent, UniBlockProps {}
8
+
9
+ export const AccordionItem = JSX<AccordionItemProps>(({ label, blocks, context }) => {
10
+ const [isActive, setIsActive] = context.useState(false);
11
+ const hasContent = blocks?.length;
12
+ const icon = isActive ? 'MinusIcon' : 'PlusIcon';
13
+
14
+ const handleToggle = (e) => {
15
+ if (!hasContent) return null;
16
+ setIsActive(!isActive);
17
+ const contentBlock = getContentBlock(e);
18
+ contentBlock.style.maxHeight = contentBlock.style.maxHeight
19
+ ? null
20
+ : `${contentBlock.scrollHeight}px`;
21
+ };
22
+
23
+ return (
24
+ <li className="border-0 border-b border-solid border-main-divider last:border-b-0">
25
+ <button
26
+ className={`border-none bg-transparent px-0 py-5 flex justify-between text-left w-full font-sans text-primary-text
27
+ ${hasContent ? 'group cursor-pointer' : ''}`}
28
+ onClick={handleToggle}
29
+ >
30
+ <span
31
+ className={`m-0 text-xl pr-2.5 font-medium ${
32
+ hasContent ? 'group-hover:text-primary-main' : ''
33
+ }`}
34
+ >
35
+ {label}
36
+ </span>
37
+ {hasContent ? <Icon name={icon} width="24" height="24" /> : null}
38
+ </button>
39
+ {hasContent ? (
40
+ <div
41
+ className={`${
42
+ isActive ? 'pb-5' : ''
43
+ } text-sm transition-all duration-300 max-h-0 overflow-hidden group-last:last:pb-0 `}
44
+ >
45
+ {blocks?.length ? blocks.map(renderComponent) : null}
46
+ </div>
47
+ ) : null}
48
+ </li>
49
+ );
50
+ });
51
+
52
+ // TODO: draft, for dynamic rendering of components
53
+
54
+ const renderComponent = (block: AccordionBlockContent, i: number) => {
55
+ if (block.type && block.data && !AccordionBlocks.hasOwnProperty(block.type)) {
56
+ return null;
57
+ }
58
+
59
+ const AccordionBlock = block.type && AccordionBlocks[block.type];
60
+ return (
61
+ <div className="mb-5 last:mb-0" key={`component${i}`}>
62
+ <AccordionBlock {...block.data} />
63
+ </div>
64
+ );
65
+ };
66
+
67
+ const getContentBlock = (e) =>
68
+ e.target.tagName === 'BUTTON' ? e.target.nextSibling : e.target.parentNode.nextSibling;
@@ -14,6 +14,7 @@ import { StepsBlock } from './StepsBlock/StepsBlock';
14
14
  import { TextBlock } from './TextBlock/TextBlock';
15
15
  import { Tile } from './Tile/Tile';
16
16
  import { ComparisonTable } from './ComparisonTable/ComparisonTable';
17
+ import { Accordion } from './Accordion/Accordion';
17
18
 
18
19
  export const Blocks = {
19
20
  Header,
@@ -32,4 +33,5 @@ export const Blocks = {
32
33
  Gallery,
33
34
  MiniGallery,
34
35
  ComparisonTable,
36
+ Accordion,
35
37
  };
@@ -1282,6 +1282,84 @@
1282
1282
  ]
1283
1283
  }
1284
1284
  },
1285
+ {
1286
+ "type": "Accordion",
1287
+ "style": ["col-span-12"],
1288
+ "content": {
1289
+ "title": "Accordion title",
1290
+ "accordionItems": [
1291
+ {
1292
+ "label": "Accordion label 1",
1293
+ "blocks": [
1294
+ {
1295
+ "type": "TextBlock",
1296
+ "data": {
1297
+ "title": "Title",
1298
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1299
+ "blockVersion": "secondary-light",
1300
+ "iconVersion": "small"
1301
+ }
1302
+ },
1303
+ {
1304
+ "type": "TextBlock",
1305
+ "data": {
1306
+ "title": "Title",
1307
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1308
+ "blockVersion": "secondary-light",
1309
+ "iconVersion": "small"
1310
+ }
1311
+ }
1312
+ ]
1313
+ },
1314
+ {
1315
+ "label": "Accordion label 2",
1316
+ "blocks": [
1317
+ {
1318
+ "type": "TextBlock",
1319
+ "data": {
1320
+ "title": "Title",
1321
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1322
+ "blockVersion": "secondary-light",
1323
+ "iconVersion": "small"
1324
+ }
1325
+ },
1326
+ {
1327
+ "type": "TextBlock",
1328
+ "data": {
1329
+ "title": "Title",
1330
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1331
+ "blockVersion": "secondary-light",
1332
+ "iconVersion": "small"
1333
+ }
1334
+ }
1335
+ ]
1336
+ },
1337
+ {
1338
+ "label": "Accordion label 3",
1339
+ "blocks": [
1340
+ {
1341
+ "type": "TextBlock",
1342
+ "data": {
1343
+ "title": "Title",
1344
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1345
+ "blockVersion": "secondary-light",
1346
+ "iconVersion": "small"
1347
+ }
1348
+ },
1349
+ {
1350
+ "type": "TextBlock",
1351
+ "data": {
1352
+ "title": "Title",
1353
+ "description": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque minima odio soluta cupiditate pariatur, labore molestias quas necessitatibus nesciunt in praesentium accusamus provident sequi maiores autem. Voluptas quam neque iste?",
1354
+ "blockVersion": "secondary-light",
1355
+ "iconVersion": "small"
1356
+ }
1357
+ }
1358
+ ]
1359
+ }
1360
+ ]
1361
+ }
1362
+ },
1285
1363
  {
1286
1364
  "type": "Footer",
1287
1365
  "style": ["col-span-12"],
@@ -0,0 +1,4 @@
1
+ import { CreditCalculator } from './CreditCalculator';
2
+ import { context } from '../../setup-fixture';
3
+
4
+ export default <CreditCalculator context={context} />;
@@ -0,0 +1,106 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import { UniBlockProps } from '../../types';
3
+ import { Button } from '../../ui-kit/Button/Button';
4
+ import { Checkbox } from '../../ui-kit/Checkbox/Checkbox';
5
+ import { InputRange } from '../../ui-kit/InputRange/InputRange';
6
+ import { clamp } from '../../utils/clamp';
7
+
8
+ export interface CreditCalculatorProps extends UniBlockProps {}
9
+
10
+ const borderStyle = 'border-solid border-3 border-primary-main rounded-md';
11
+
12
+ const MIN_MONEY = 50000;
13
+ const MAX_MONEY = 3000000;
14
+ const STEP_MONEY = 1000;
15
+
16
+ const CREDIT_TERM_YEARS = [2, 3, 4, 5, 6, 7];
17
+
18
+ const MIN_MONTHS = 1;
19
+ const MAX_MONTHS = 84;
20
+ const STEP_MONTHS = 1;
21
+
22
+ const MONTHS_IN_YEAR = 12;
23
+
24
+ export const CreditCalculator = JSX<CreditCalculatorProps>(({ context, className }) => {
25
+ const [moneyValue, setMoneyValue] = context.useState(350000);
26
+ const [monthsValue, setMonthsValue] = context.useState(12);
27
+ const [isAnnuityChecked, setIsAnnuityChecked] = context.useState(true);
28
+ const [isInsuranceChecked, setIsInsuranceChecked] = context.useState(true);
29
+
30
+ const handleButtonClick = (value: number) => {
31
+ setMonthsValue(clamp(value * MONTHS_IN_YEAR, MIN_MONTHS, MAX_MONTHS));
32
+ };
33
+
34
+ return (
35
+ <section className={`font-sans text-primary-text bg-white p-4 ${className}`}>
36
+ <div className={`box-border p-12 flex flex-col justify-between ${borderStyle}`}>
37
+ <div className="flex justify-between">
38
+ <div className="grow mr-11">
39
+ <InputRange
40
+ title="Желаемая сумма кредита, ₽"
41
+ items={['От 50 000 рублей', 'До 3 000 000 рублей']}
42
+ min={MIN_MONEY}
43
+ max={MAX_MONEY}
44
+ step={STEP_MONEY}
45
+ value={moneyValue}
46
+ onChange={setMoneyValue}
47
+ />
48
+ <InputRange
49
+ title="Срок кредита, месяцев"
50
+ items={['Или выберите из предложенных вариантов ниже']}
51
+ min={MIN_MONTHS}
52
+ max={MAX_MONTHS}
53
+ step={STEP_MONTHS}
54
+ value={monthsValue}
55
+ onChange={setMonthsValue}
56
+ />
57
+ <div className="flex mb-7">
58
+ {CREDIT_TERM_YEARS.map((number, i) => renderButton(number, i, handleButtonClick))}
59
+ </div>
60
+ <Checkbox
61
+ text="Получаю пенсию на карту Россельхозбанка"
62
+ checked={isAnnuityChecked}
63
+ onChange={setIsAnnuityChecked}
64
+ />
65
+ <Checkbox
66
+ className="mb-4"
67
+ text="Комплексная страховая защита"
68
+ checked={isInsuranceChecked}
69
+ onChange={setIsInsuranceChecked}
70
+ />
71
+ </div>
72
+ <div className="p-9 bg-primary-main rounded-md text-white">
73
+ <div className="text-base mb-5">Наше предложение</div>
74
+ <div className="text-sm opacity-60">Ежемесячный платёж</div>
75
+ <div className="text-lg mb-3">26 827 ₽</div>
76
+ <div className="text-sm opacity-60">Ставка</div>
77
+ <div className="text-lg">16,9 %</div>
78
+ </div>
79
+ </div>
80
+ <div className="flex items-center">
81
+ <Button className="mr-3" text="Отправить заявку" version="primary" href="#" />
82
+ <div
83
+ className="w-80 text-xxs leading-4 text-secondary-text"
84
+ aria-label="Соглашение на обработку персональных данных"
85
+ >
86
+ Отправляя заявку, вы соглашаетесь на обработку персональных данных соответственно
87
+ требованиям ФЗ «О персональных данных»
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </section>
92
+ );
93
+ });
94
+
95
+ const renderButton = (number: number, i: number, handleClick: (number: number) => void) => (
96
+ <div
97
+ key={String(i)}
98
+ className="bg-secondary-light rounded-3xl h-10 w-[75px] box-border mr-2 flex items-center justify-center cursor-pointer"
99
+ role="button"
100
+ onClick={() => handleClick(number)}
101
+ >
102
+ <span className="font-medium text-sm">
103
+ {number} {number > 4 ? 'лет' : 'года'}
104
+ </span>
105
+ </div>
106
+ );
@@ -5,6 +5,7 @@ import type { ContentPageDef } from '../types';
5
5
  import type { TransformationOptions } from './TransformationOptions';
6
6
  import { transformContentPage } from './transformContentPage';
7
7
 
8
+ const INDEX_PAGE_SLUG = 'index';
8
9
  const find = util.promisify(glob);
9
10
 
10
11
  export function ContentPageRepository({
@@ -16,6 +17,11 @@ export function ContentPageRepository({
16
17
  return await Promise.all(pagePaths.map(readPage));
17
18
  }
18
19
 
20
+ async function getSecondaryContentPages() {
21
+ const pages = await getAllContentPages();
22
+ return pages.filter((content) => content.slug !== INDEX_PAGE_SLUG);
23
+ }
24
+
19
25
  async function getContentPageBySlug(slug: string): Promise<ContentPageDef | undefined> {
20
26
  const pages = await getAllContentPages();
21
27
  return pages.find((content) => content.slug === slug);
@@ -26,6 +32,14 @@ export function ContentPageRepository({
26
32
  return page && toMobilePage(page);
27
33
  }
28
34
 
35
+ async function getIndexPage() {
36
+ return await getContentPageBySlug(INDEX_PAGE_SLUG);
37
+ }
38
+
39
+ async function getIndexMobilePage() {
40
+ return await getMobilePageBySlug(INDEX_PAGE_SLUG);
41
+ }
42
+
29
43
  const cache: Record<string, ContentPageDef> = {};
30
44
  async function readPage(filePath: string): Promise<ContentPageDef> {
31
45
  if (!(filePath in cache)) {
@@ -41,5 +55,8 @@ export function ContentPageRepository({
41
55
  getAllContentPages,
42
56
  getContentPageBySlug,
43
57
  getMobilePageBySlug,
58
+ getSecondaryContentPages,
59
+ getIndexPage,
60
+ getIndexMobilePage,
44
61
  };
45
62
  }
@@ -0,0 +1,5 @@
1
+ <svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M9.809 2.759A2.813 2.813 0 0 1 11.742 2h5.524C18.776 2 20 3.16 20 4.59v13.82c0 1.43-1.224 2.59-2.734 2.59H6.734C5.224 21 4 19.84 4 18.41v-5.95c0-.477.408-.864.911-.864.504 0 .912.387.912.864v5.95c0 .476.408.863.911.863h10.532c.503 0 .911-.387.911-.864V4.591c0-.477-.408-.864-.911-.864h-5.367v4.03c0 .955-.816 1.728-1.823 1.728H4.911c-.368 0-.7-.21-.842-.533a.83.83 0 0 1 .198-.941l5.542-5.252Zm.267 2.19L7.112 7.758h2.964v-2.81Z" fill="#1C1C1C" />
3
+ <rect x="8" y="12" width="8" height="2" rx="1" fill="#42AB44" />
4
+ <rect x="8" y="15" width="5" height="2" rx="1" fill="#42AB44" />
5
+ </svg>
@@ -0,0 +1 @@
1
+ <svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 12h5M4 12h7" stroke="#42AB44" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
@@ -0,0 +1 @@
1
+ <svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 18V6M15 12h5M4 12h7M12 20V4" stroke="#42AB44" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
@@ -0,0 +1,36 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { CheckboxProps } from './CheckboxProps';
3
+ import { SVG } from '../SVG';
4
+
5
+ const CHECK_PATHS = [
6
+ {
7
+ d: 'M10.207.793a1 1 0 0 1 0 1.414l-6 6a1 1 0 0 1-1.414 0l-2.5-2.5a1 1 0 0 1 1.414-1.414L3.5 6.086 8.793.793a1 1 0 0 1 1.414 0Z',
8
+ fillRule: 'evenodd',
9
+ clipRule: 'evenodd',
10
+ fill: 'white',
11
+ },
12
+ ];
13
+
14
+ export const Checkbox = JSX<CheckboxProps>(({ text, checked, onChange, className }) => (
15
+ <div className={className}>
16
+ <label className="flex items-center cursor-pointer relative">
17
+ <input
18
+ className={`peer appearance-none w-5 h-5 border-solid border rounded border-black checked:bg-primary-main checked:border-primary-main`}
19
+ type="checkbox"
20
+ onChange={(e) => {
21
+ onChange(e.target.checked);
22
+ }}
23
+ checked={checked}
24
+ />
25
+ <SVG
26
+ paths={CHECK_PATHS}
27
+ className="hidden absolute left-2 ml-px peer-checked:block"
28
+ width="11"
29
+ height="9"
30
+ fill="white"
31
+ viewBox="0 0 11 9"
32
+ />
33
+ {text ? <span className="font-sans ml-2 text-sm cursor-pointer">{text}</span> : null}
34
+ </label>
35
+ </div>
36
+ ));
@@ -0,0 +1,6 @@
1
+ export interface CheckboxProps {
2
+ text?: string;
3
+ checked: boolean;
4
+ onChange: (value: boolean) => void;
5
+ className?: string;
6
+ }
@@ -19,6 +19,9 @@ export enum IconMap {
19
19
  'TelegramIcon',
20
20
  'VKIcon',
21
21
  'GlassIcon',
22
+ 'DocIcon',
23
+ 'PlusIcon',
24
+ 'MinusIcon',
22
25
  }
23
26
 
24
27
  export type IconName = keyof typeof IconMap;