@redneckz/wildless-cms-uni-blocks 0.8.31 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/bundle/blocks.schema.json +1 -1
  2. package/bundle/bundle.umd.js +93 -22
  3. package/bundle/bundle.umd.min.js +1 -1
  4. package/bundle/components/Filtration/Filtration.d.ts +6 -0
  5. package/bundle/components/Filtration/FiltrationContent.d.ts +78 -0
  6. package/bundle/components/Filtration/FiltrationInner.d.ts +7 -0
  7. package/bundle/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  8. package/bundle/components/Filtration/renderFormItem.d.ts +4 -0
  9. package/bundle/hooks/useForm.d.ts +12 -0
  10. package/bundle/model/JSXBlock.d.ts +2 -0
  11. package/bundle/ui-kit/ControlProps.d.ts +4 -0
  12. package/bundle/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  13. package/bundle/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  14. package/bundle/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  15. package/dist/components/ApplicationForm/renderSlideCheckboxes.js +1 -1
  16. package/dist/components/ApplicationForm/renderSlideCheckboxes.js.map +1 -1
  17. package/dist/components/Blocks.js +2 -0
  18. package/dist/components/Blocks.js.map +1 -1
  19. package/dist/components/Filtration/Filtration.d.ts +6 -0
  20. package/dist/components/Filtration/Filtration.js +17 -0
  21. package/dist/components/Filtration/Filtration.js.map +1 -0
  22. package/dist/components/Filtration/FiltrationContent.d.ts +78 -0
  23. package/dist/components/Filtration/FiltrationContent.js +2 -0
  24. package/dist/components/Filtration/FiltrationContent.js.map +1 -0
  25. package/dist/components/Filtration/FiltrationInner.d.ts +7 -0
  26. package/dist/components/Filtration/FiltrationInner.js +23 -0
  27. package/dist/components/Filtration/FiltrationInner.js.map +1 -0
  28. package/dist/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  29. package/dist/components/Filtration/checkShouldRenderBlock.js +11 -0
  30. package/dist/components/Filtration/checkShouldRenderBlock.js.map +1 -0
  31. package/dist/components/Filtration/renderFormItem.d.ts +4 -0
  32. package/dist/components/Filtration/renderFormItem.js +21 -0
  33. package/dist/components/Filtration/renderFormItem.js.map +1 -0
  34. package/dist/hooks/useForm.d.ts +12 -0
  35. package/dist/hooks/useForm.js +21 -0
  36. package/dist/hooks/useForm.js.map +1 -0
  37. package/dist/model/JSXBlock.d.ts +2 -0
  38. package/dist/ui-kit/ControlProps.d.ts +4 -0
  39. package/dist/ui-kit/ControlProps.js +2 -0
  40. package/dist/ui-kit/ControlProps.js.map +1 -0
  41. package/dist/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  42. package/dist/ui-kit/Foldable/DefaultFoldButton.js +5 -7
  43. package/dist/ui-kit/Foldable/DefaultFoldButton.js.map +1 -1
  44. package/dist/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  45. package/dist/ui-kit/SlideCheckbox/SlideCheckbox.js +2 -2
  46. package/dist/ui-kit/SlideCheckbox/SlideCheckbox.js.map +1 -1
  47. package/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  48. package/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js +19 -0
  49. package/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js.map +1 -0
  50. package/lib/common.css +1 -1
  51. package/lib/components/ApplicationForm/renderSlideCheckboxes.js +1 -1
  52. package/lib/components/ApplicationForm/renderSlideCheckboxes.js.map +1 -1
  53. package/lib/components/Blocks.js +2 -0
  54. package/lib/components/Blocks.js.map +1 -1
  55. package/lib/components/Filtration/Filtration.d.ts +6 -0
  56. package/lib/components/Filtration/Filtration.fixture.d.ts +5 -0
  57. package/lib/components/Filtration/Filtration.js +15 -0
  58. package/lib/components/Filtration/Filtration.js.map +1 -0
  59. package/lib/components/Filtration/FiltrationContent.d.ts +78 -0
  60. package/lib/components/Filtration/FiltrationContent.js +2 -0
  61. package/lib/components/Filtration/FiltrationContent.js.map +1 -0
  62. package/lib/components/Filtration/FiltrationInner.d.ts +7 -0
  63. package/lib/components/Filtration/FiltrationInner.js +21 -0
  64. package/lib/components/Filtration/FiltrationInner.js.map +1 -0
  65. package/lib/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  66. package/lib/components/Filtration/checkShouldRenderBlock.js +8 -0
  67. package/lib/components/Filtration/checkShouldRenderBlock.js.map +1 -0
  68. package/lib/components/Filtration/renderFormItem.d.ts +4 -0
  69. package/lib/components/Filtration/renderFormItem.js +18 -0
  70. package/lib/components/Filtration/renderFormItem.js.map +1 -0
  71. package/lib/hooks/useForm.d.ts +12 -0
  72. package/lib/hooks/useForm.js +18 -0
  73. package/lib/hooks/useForm.js.map +1 -0
  74. package/lib/model/JSXBlock.d.ts +2 -0
  75. package/lib/ui-kit/ControlProps.d.ts +4 -0
  76. package/lib/ui-kit/ControlProps.js +2 -0
  77. package/lib/ui-kit/ControlProps.js.map +1 -0
  78. package/lib/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  79. package/lib/ui-kit/Foldable/DefaultFoldButton.js +5 -7
  80. package/lib/ui-kit/Foldable/DefaultFoldButton.js.map +1 -1
  81. package/lib/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  82. package/lib/ui-kit/SlideCheckbox/SlideCheckbox.js +2 -2
  83. package/lib/ui-kit/SlideCheckbox/SlideCheckbox.js.map +1 -1
  84. package/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  85. package/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js +17 -0
  86. package/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js.map +1 -0
  87. package/mobile/bundle/bundle.umd.js +5 -8
  88. package/mobile/bundle/bundle.umd.min.js +1 -1
  89. package/mobile/bundle/components/Filtration/Filtration.d.ts +6 -0
  90. package/mobile/bundle/components/Filtration/FiltrationContent.d.ts +78 -0
  91. package/mobile/bundle/components/Filtration/FiltrationInner.d.ts +7 -0
  92. package/mobile/bundle/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  93. package/mobile/bundle/components/Filtration/renderFormItem.d.ts +4 -0
  94. package/mobile/bundle/hooks/useForm.d.ts +12 -0
  95. package/mobile/bundle/model/JSXBlock.d.ts +2 -0
  96. package/mobile/bundle/ui-kit/ControlProps.d.ts +4 -0
  97. package/mobile/bundle/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  98. package/mobile/bundle/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  99. package/mobile/bundle/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  100. package/mobile/dist/components/ApplicationForm/renderSlideCheckboxes.js +1 -1
  101. package/mobile/dist/components/ApplicationForm/renderSlideCheckboxes.js.map +1 -1
  102. package/mobile/dist/components/Filtration/Filtration.d.ts +6 -0
  103. package/mobile/dist/components/Filtration/Filtration.js +17 -0
  104. package/mobile/dist/components/Filtration/Filtration.js.map +1 -0
  105. package/mobile/dist/components/Filtration/FiltrationContent.d.ts +78 -0
  106. package/mobile/dist/components/Filtration/FiltrationContent.js +2 -0
  107. package/mobile/dist/components/Filtration/FiltrationContent.js.map +1 -0
  108. package/mobile/dist/components/Filtration/FiltrationInner.d.ts +7 -0
  109. package/mobile/dist/components/Filtration/FiltrationInner.js +23 -0
  110. package/mobile/dist/components/Filtration/FiltrationInner.js.map +1 -0
  111. package/mobile/dist/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  112. package/mobile/dist/components/Filtration/checkShouldRenderBlock.js +11 -0
  113. package/mobile/dist/components/Filtration/checkShouldRenderBlock.js.map +1 -0
  114. package/mobile/dist/components/Filtration/renderFormItem.d.ts +4 -0
  115. package/mobile/dist/components/Filtration/renderFormItem.js +21 -0
  116. package/mobile/dist/components/Filtration/renderFormItem.js.map +1 -0
  117. package/mobile/dist/hooks/useForm.d.ts +12 -0
  118. package/mobile/dist/hooks/useForm.js +21 -0
  119. package/mobile/dist/hooks/useForm.js.map +1 -0
  120. package/mobile/dist/model/JSXBlock.d.ts +2 -0
  121. package/mobile/dist/ui-kit/ControlProps.d.ts +4 -0
  122. package/mobile/dist/ui-kit/ControlProps.js +2 -0
  123. package/mobile/dist/ui-kit/ControlProps.js.map +1 -0
  124. package/mobile/dist/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  125. package/mobile/dist/ui-kit/Foldable/DefaultFoldButton.js +5 -7
  126. package/mobile/dist/ui-kit/Foldable/DefaultFoldButton.js.map +1 -1
  127. package/mobile/dist/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  128. package/mobile/dist/ui-kit/SlideCheckbox/SlideCheckbox.js +2 -2
  129. package/mobile/dist/ui-kit/SlideCheckbox/SlideCheckbox.js.map +1 -1
  130. package/mobile/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  131. package/mobile/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js +19 -0
  132. package/mobile/dist/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js.map +1 -0
  133. package/mobile/lib/components/ApplicationForm/renderSlideCheckboxes.js +1 -1
  134. package/mobile/lib/components/ApplicationForm/renderSlideCheckboxes.js.map +1 -1
  135. package/mobile/lib/components/Filtration/Filtration.d.ts +6 -0
  136. package/mobile/lib/components/Filtration/Filtration.js +15 -0
  137. package/mobile/lib/components/Filtration/Filtration.js.map +1 -0
  138. package/mobile/lib/components/Filtration/FiltrationContent.d.ts +78 -0
  139. package/mobile/lib/components/Filtration/FiltrationContent.js +2 -0
  140. package/mobile/lib/components/Filtration/FiltrationContent.js.map +1 -0
  141. package/mobile/lib/components/Filtration/FiltrationInner.d.ts +7 -0
  142. package/mobile/lib/components/Filtration/FiltrationInner.js +21 -0
  143. package/mobile/lib/components/Filtration/FiltrationInner.js.map +1 -0
  144. package/mobile/lib/components/Filtration/checkShouldRenderBlock.d.ts +1 -0
  145. package/mobile/lib/components/Filtration/checkShouldRenderBlock.js +8 -0
  146. package/mobile/lib/components/Filtration/checkShouldRenderBlock.js.map +1 -0
  147. package/mobile/lib/components/Filtration/renderFormItem.d.ts +4 -0
  148. package/mobile/lib/components/Filtration/renderFormItem.js +18 -0
  149. package/mobile/lib/components/Filtration/renderFormItem.js.map +1 -0
  150. package/mobile/lib/hooks/useForm.d.ts +12 -0
  151. package/mobile/lib/hooks/useForm.js +18 -0
  152. package/mobile/lib/hooks/useForm.js.map +1 -0
  153. package/mobile/lib/model/JSXBlock.d.ts +2 -0
  154. package/mobile/lib/ui-kit/ControlProps.d.ts +4 -0
  155. package/mobile/lib/ui-kit/ControlProps.js +2 -0
  156. package/mobile/lib/ui-kit/ControlProps.js.map +1 -0
  157. package/mobile/lib/ui-kit/Foldable/DefaultFoldButton.d.ts +1 -0
  158. package/mobile/lib/ui-kit/Foldable/DefaultFoldButton.js +5 -7
  159. package/mobile/lib/ui-kit/Foldable/DefaultFoldButton.js.map +1 -1
  160. package/mobile/lib/ui-kit/SlideCheckbox/SlideCheckbox.d.ts +3 -2
  161. package/mobile/lib/ui-kit/SlideCheckbox/SlideCheckbox.js +2 -2
  162. package/mobile/lib/ui-kit/SlideCheckbox/SlideCheckbox.js.map +1 -1
  163. package/mobile/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.d.ts +15 -0
  164. package/mobile/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js +17 -0
  165. package/mobile/lib/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.js.map +1 -0
  166. package/mobile/src/components/ApplicationForm/renderSlideCheckboxes.tsx +4 -4
  167. package/mobile/src/components/Filtration/Filtration.example.json +37 -0
  168. package/mobile/src/components/Filtration/Filtration.tsx +41 -0
  169. package/mobile/src/components/Filtration/Filtration.ui.json +1 -0
  170. package/mobile/src/components/Filtration/FiltrationContent.ts +87 -0
  171. package/mobile/src/components/Filtration/FiltrationInner.tsx +67 -0
  172. package/mobile/src/components/Filtration/checkShouldRenderBlock.ts +18 -0
  173. package/mobile/src/components/Filtration/renderFormItem.tsx +36 -0
  174. package/mobile/src/hooks/useForm.ts +29 -0
  175. package/mobile/src/model/JSXBlock.ts +2 -0
  176. package/mobile/src/ui-kit/ControlProps.ts +4 -0
  177. package/mobile/src/ui-kit/Foldable/DefaultFoldButton.tsx +10 -4
  178. package/mobile/src/ui-kit/SlideCheckbox/SlideCheckbox.tsx +26 -23
  179. package/mobile/src/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.tsx +44 -0
  180. package/package.json +2 -1
  181. package/src/components/ApplicationForm/renderSlideCheckboxes.tsx +4 -4
  182. package/src/components/Blocks.ts +2 -0
  183. package/src/components/Filtration/Filtration.example.json +37 -0
  184. package/src/components/Filtration/Filtration.fixture.tsx +147 -0
  185. package/src/components/Filtration/Filtration.tsx +41 -0
  186. package/src/components/Filtration/Filtration.ui.json +1 -0
  187. package/src/components/Filtration/FiltrationContent.ts +87 -0
  188. package/src/components/Filtration/FiltrationInner.tsx +67 -0
  189. package/src/components/Filtration/checkShouldRenderBlock.ts +18 -0
  190. package/src/components/Filtration/renderFormItem.tsx +36 -0
  191. package/src/hooks/useForm.ts +29 -0
  192. package/src/model/JSXBlock.ts +2 -0
  193. package/src/ui-kit/ControlProps.ts +4 -0
  194. package/src/ui-kit/Foldable/DefaultFoldButton.tsx +10 -4
  195. package/src/ui-kit/SlideCheckbox/SlideCheckbox.fixture.tsx +1 -1
  196. package/src/ui-kit/SlideCheckbox/SlideCheckbox.tsx +26 -23
  197. package/src/ui-kit/SlideCheckboxGroup/SlideCheckboxGroup.tsx +44 -0
@@ -1,33 +1,36 @@
1
1
  import { JSX } from '@redneckz/uni-jsx';
2
- import { Text } from '../../ui-kit/Text/Text';
2
+ import { Text } from '../Text/Text';
3
3
 
4
4
  interface SlideCheckboxProps {
5
- checked?: boolean;
5
+ value?: boolean;
6
6
  text?: string;
7
- onClick?: () => void;
7
+ type?: 'checkbox' | 'radio';
8
+ onChange?: (value: boolean) => void;
8
9
  }
9
- export const SlideCheckbox = JSX<SlideCheckboxProps>(({ checked, text, onClick }) => (
10
- <div
11
- role="checkbox"
12
- aria-checked={checked}
13
- className="flex justify-start items-center w-full cursor-pointer mb-4"
14
- onClick={() => onClick && onClick()}
15
- >
10
+ export const SlideCheckbox = JSX<SlideCheckboxProps>(
11
+ ({ value = false, text, type = 'checkbox', onChange }) => (
16
12
  <div
17
- className={`relative duration-300 w-9 h-5 mr-3 rounded rounded-2xl ${
18
- checked ? 'bg-primary-main' : 'bg-main-divider'
19
- }`}
13
+ role={type}
14
+ aria-checked={value}
15
+ className="flex justify-start items-center w-full cursor-pointer mb-4"
16
+ onClick={() => onChange && onChange(!value)}
20
17
  >
21
18
  <div
22
- className={`absolute opacity-80 duration-500 top-0.5 w-4 h-4 bg-white rounded rounded-full ${
23
- checked ? 'left-[50%]' : 'left-[5%]'
19
+ className={`relative flex-shrink-0 duration-300 w-9 h-5 mr-3 rounded-2xl ${
20
+ value ? 'bg-primary-main' : 'bg-main-divider'
24
21
  }`}
25
- />
22
+ >
23
+ <div
24
+ className={`absolute opacity-80 duration-500 top-0.5 w-4 h-4 bg-white rounded-full ${
25
+ value ? 'left-[50%]' : 'left-[5%]'
26
+ }`}
27
+ />
28
+ </div>
29
+ <div>
30
+ <Text size="text-m" font="font-light" color="text-primary-text">
31
+ {text}
32
+ </Text>
33
+ </div>
26
34
  </div>
27
- <div>
28
- <Text size="text-m" font="font-light" color="text-primary-text">
29
- {text}
30
- </Text>
31
- </div>
32
- </div>
33
- ));
35
+ ),
36
+ );
@@ -0,0 +1,44 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import type { ControlProps } from '../ControlProps';
3
+ import { SlideCheckbox } from '../SlideCheckbox/SlideCheckbox';
4
+
5
+ type SlideCheckboxGroupItem = {
6
+ value: string;
7
+ title: string;
8
+ };
9
+
10
+ interface SlideCheckboxGroupProps extends ControlProps<string> {
11
+ multiple: false;
12
+ items: SlideCheckboxGroupItem[];
13
+ }
14
+
15
+ interface MultipleSlideCheckboxGroupProps extends ControlProps<string[]> {
16
+ multiple: true;
17
+ items: SlideCheckboxGroupItem[];
18
+ }
19
+
20
+ export const SlideCheckboxGroup = JSX<SlideCheckboxGroupProps | MultipleSlideCheckboxGroupProps>(
21
+ ({ value, onChange, items = [], multiple }) => {
22
+ const handleChange = (newValue: string) => {
23
+ if (multiple) {
24
+ const hasAlready = value?.includes(newValue);
25
+ onChange &&
26
+ onChange(
27
+ hasAlready ? value?.filter((v) => v !== newValue) : [...(value || []), newValue],
28
+ );
29
+ } else {
30
+ onChange && onChange(value === newValue ? undefined : newValue);
31
+ }
32
+ };
33
+
34
+ return items.map((item) => (
35
+ <SlideCheckbox
36
+ key={item.value}
37
+ text={item.title}
38
+ value={[value].flatMap((_) => _).includes(item.value)}
39
+ onChange={() => handleChange(item.value)}
40
+ type={multiple ? 'checkbox' : 'radio'}
41
+ />
42
+ ));
43
+ },
44
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redneckz/wildless-cms-uni-blocks",
3
- "version": "0.8.31",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "ЦК",
@@ -120,6 +120,7 @@
120
120
  },
121
121
  "dependencies": {
122
122
  "@redneckz/uni-jsx": "^2.3.4",
123
+ "@types/json-schema": "^7.0.11",
123
124
  "glob": "^8.0.3",
124
125
  "rehype-parse": "^8.0.4",
125
126
  "rehype-sanitize": "^5.0.1",
@@ -15,14 +15,14 @@ export const renderSlideCheckboxes = ({
15
15
  }: SlideCheckboxesProps) => (
16
16
  <div className="mb-5">
17
17
  <SlideCheckbox
18
- checked={onlineСheckout}
18
+ value={onlineСheckout}
19
19
  text="Хочу купить онлайн-кассу"
20
- onClick={() => handleChange({ onlineСheckout: !onlineСheckout })}
20
+ onChange={() => handleChange({ onlineСheckout: !onlineСheckout })}
21
21
  />
22
22
  <SlideCheckbox
23
- checked={posTerminal}
23
+ value={posTerminal}
24
24
  text="Хочу купить POS-терминал"
25
- onClick={() => handleChange({ posTerminal: !posTerminal })}
25
+ onChange={() => handleChange({ posTerminal: !posTerminal })}
26
26
  />
27
27
  </div>
28
28
  );
@@ -23,6 +23,7 @@ import { ComparisonTable } from './ComparisonTable/ComparisonTable';
23
23
  import { ContactsBlock } from './ContactsBlock/ContactsBlock';
24
24
  import { ErrorBlock } from './ErrorBlock/ErrorBlock';
25
25
  import { ExchangeRateTile } from './ExchangeRateTile/ExchangeRateTile';
26
+ import { Filtration } from './Filtration/Filtration';
26
27
  import { Footer } from './Footer/Footer';
27
28
  import { GracePeriod } from './GracePeriod/GracePeriod';
28
29
  import { Header } from './Header/Header';
@@ -80,6 +81,7 @@ export const Blocks: BlocksRegistry = {
80
81
  ContactsBlock,
81
82
  ErrorBlock,
82
83
  ExchangeRateTile,
84
+ Filtration,
83
85
  Footer,
84
86
  GracePeriod,
85
87
  Header,
@@ -0,0 +1,37 @@
1
+ {
2
+ "content": {
3
+ "filtrationSchema": {
4
+ "propertyType": {
5
+ "title": "Тип недвижимости",
6
+ "type": "string",
7
+ "enum": ["flat", "apartment", "house", "storeRoom", "parkingSpace"],
8
+ "enumNames": ["Квартира", "Апартаменты", "Жилой дом", "Кладовая", "Машино-место"]
9
+ },
10
+ "stage": {
11
+ "title": "Этап строительства",
12
+ "type": "string",
13
+ "enum": ["built", "inProgress"],
14
+ "enumNames": ["Готовое жильё", "Строящиеся"]
15
+ },
16
+ "categories": {
17
+ "title": "Категории",
18
+ "type": "string",
19
+ "enum": ["salaryClient", "IT", "youngFamily", "military", "medicalWorker", "scientist"],
20
+ "enumNames": [
21
+ "Зарплатный клиент",
22
+ "IT-специалист",
23
+ "Молодая семья",
24
+ "Военнослужащий",
25
+ "Медицинский работник",
26
+ "Научный сотрудник"
27
+ ]
28
+ },
29
+ "extraOptions": {
30
+ "title": "Дополнительно",
31
+ "type": "string",
32
+ "enum": ["preferentialMortgage", "children"],
33
+ "enumNames": ["Льготная ипотека", "Дети"]
34
+ }
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,147 @@
1
+ import type { BlockRendererOptions } from '../../BlockRenderer/BlockRendererOptions';
2
+ import { Blocks } from '../Blocks';
3
+ import { PRODUCT_TILE } from '../ProductTile/ProductTile.fixture';
4
+ import { Filtration } from './Filtration';
5
+ import type { FiltrationContent } from './FiltrationContent';
6
+
7
+ const PROPERTY_APARTMENT = {
8
+ propertyType: 'apartment',
9
+ };
10
+
11
+ const PROPERTY_FLAT = {
12
+ propertyType: 'flat',
13
+ };
14
+
15
+ const PROPERTY_HOUSE = {
16
+ propertyType: 'house',
17
+ };
18
+
19
+ const STAGE_BUILT = {
20
+ stage: 'built',
21
+ };
22
+
23
+ const STAGE_IN_PROGRESS = {
24
+ stage: 'inProgress',
25
+ };
26
+
27
+ const EXTRA_MORTGAGE = {
28
+ extraOptions: 'preferentialMortgage',
29
+ };
30
+
31
+ const EXTRA_CHILDREN = {
32
+ extraOptions: 'children',
33
+ };
34
+
35
+ const CATEGORY_IT = {
36
+ categories: 'IT',
37
+ };
38
+
39
+ const CATEGORY_SALARY = {
40
+ categories: 'salaryClient',
41
+ };
42
+
43
+ const generateBlock = (...presets: any[]) => ({
44
+ type: 'ProductTile',
45
+ style: ['col-span-6'],
46
+ content: { ...presets.reduce((acc, p) => ({ ...acc, ...p })) },
47
+ });
48
+
49
+ const SCHEMA: FiltrationContent['filtrationSchema'] = {
50
+ propertyType: {
51
+ title: 'Тип недвижимости',
52
+ type: 'string',
53
+ enum: ['flat', 'apartment', 'house', 'storeRoom', 'parkingSpace'],
54
+ enumNames: ['Квартира', 'Апартаменты', 'Жилой дом', 'Кладовая', 'Машино-место'],
55
+ },
56
+ stage: {
57
+ title: 'Этап строительства',
58
+ type: 'string',
59
+ enum: ['built', 'inProgress'],
60
+ enumNames: ['Готовое жильё', 'Строящиеся'],
61
+ },
62
+ categories: {
63
+ title: 'Категории',
64
+ type: 'string',
65
+ enum: ['salaryClient', 'IT', 'youngFamily', 'military', 'medicalWorker', 'scientist'],
66
+ enumNames: [
67
+ 'Зарплатный клиент',
68
+ 'IT-специалист',
69
+ 'Молодая семья',
70
+ 'Военнослужащий',
71
+ 'Медицинский работник',
72
+ 'Научный сотрудник',
73
+ ],
74
+ },
75
+ extraOptions: {
76
+ title: 'Дополнительно',
77
+ type: 'string',
78
+ enum: ['preferentialMortgage', 'children'],
79
+ enumNames: ['Льготная ипотека', 'Дети'],
80
+ },
81
+ };
82
+
83
+ const options = {
84
+ blocksRegistry: Blocks,
85
+ } as BlockRendererOptions;
86
+
87
+ export default {
88
+ default: (
89
+ <div className="container grid grid-cols-12">
90
+ <Filtration
91
+ className="col-span-12"
92
+ label="Другие ипотечные программы"
93
+ filtrationSchema={SCHEMA}
94
+ topItemsCount={2}
95
+ resetButton={{ text: 'Очистить фильтры', buttonVersion: 'secondary' }}
96
+ block={{
97
+ type: 'Filtration',
98
+ blocks: [
99
+ generateBlock(
100
+ PRODUCT_TILE,
101
+ PROPERTY_APARTMENT,
102
+ STAGE_IN_PROGRESS,
103
+ EXTRA_MORTGAGE,
104
+ CATEGORY_IT,
105
+ ),
106
+ generateBlock(
107
+ PRODUCT_TILE,
108
+ PROPERTY_APARTMENT,
109
+ STAGE_BUILT,
110
+ EXTRA_CHILDREN,
111
+ CATEGORY_SALARY,
112
+ ),
113
+ generateBlock(
114
+ PRODUCT_TILE,
115
+ PROPERTY_FLAT,
116
+ STAGE_IN_PROGRESS,
117
+ EXTRA_MORTGAGE,
118
+ CATEGORY_SALARY,
119
+ ),
120
+ generateBlock(
121
+ PRODUCT_TILE,
122
+ PROPERTY_FLAT,
123
+ STAGE_BUILT,
124
+ EXTRA_MORTGAGE,
125
+ CATEGORY_SALARY,
126
+ ),
127
+ generateBlock(
128
+ PRODUCT_TILE,
129
+ PROPERTY_APARTMENT,
130
+ STAGE_BUILT,
131
+ EXTRA_CHILDREN,
132
+ CATEGORY_IT,
133
+ ),
134
+ generateBlock(
135
+ PRODUCT_TILE,
136
+ PROPERTY_HOUSE,
137
+ STAGE_BUILT,
138
+ EXTRA_MORTGAGE,
139
+ CATEGORY_SALARY,
140
+ ),
141
+ ],
142
+ }}
143
+ options={options}
144
+ />
145
+ </div>
146
+ ),
147
+ };
@@ -0,0 +1,41 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import { useForm } from '../../hooks/useForm';
3
+ import type { JSXBlock, UniBlockProps } from '../../model/JSXBlock';
4
+ import { BlockWrapper } from '../../ui-kit/BlockWrapper';
5
+ import { Button } from '../../ui-kit/Button/Button';
6
+ import { style } from '../../utils/style';
7
+ import type { FiltrationContent } from './FiltrationContent';
8
+ import { FiltrationInner } from './FiltrationInner';
9
+ import { renderFormItem } from './renderFormItem';
10
+
11
+ interface FiltrationProps extends FiltrationContent, UniBlockProps {}
12
+
13
+ export const Filtration: JSXBlock<FiltrationProps> = JSX<FiltrationProps>(
14
+ ({ className, filtrationSchema = {}, resetButton, ...rest }) => {
15
+ const { formState, register, resetForm } = useForm();
16
+
17
+ return (
18
+ <BlockWrapper className={style('p-9', className)} {...rest}>
19
+ <form className="flex justify-between">
20
+ <div className="flex gap-11">
21
+ {Object.keys(filtrationSchema).map(renderFormItem(filtrationSchema, register))}
22
+ </div>
23
+ {resetButton ? (
24
+ <div>
25
+ <Button
26
+ className="w-72"
27
+ text={resetButton.text}
28
+ version={resetButton.buttonVersion}
29
+ onClick={resetForm}
30
+ />
31
+ </div>
32
+ ) : null}
33
+ </form>
34
+ <FiltrationInner filtrationState={formState} {...rest} />
35
+ </BlockWrapper>
36
+ );
37
+ },
38
+ );
39
+
40
+ Filtration.childrenTypes = ['ProductTile'];
41
+ Filtration.childSchema = (content?: FiltrationContent) => content?.filtrationSchema || {};
@@ -0,0 +1,87 @@
1
+ import type { ButtonVersion } from '../../model/ButtonVersion';
2
+
3
+ /**
4
+ * @title Заголовок
5
+ */
6
+ type Title = string;
7
+
8
+ /**
9
+ * @title Ключи
10
+ */
11
+ type Enum = string[];
12
+
13
+ /**
14
+ * @title Имена
15
+ */
16
+ type EnumNames = string[];
17
+
18
+ export type StringEnum = {
19
+ title?: Title;
20
+ /**
21
+ * @default string
22
+ * @hidden
23
+ */
24
+ type?: 'string';
25
+ enum?: Enum;
26
+ enumNames?: EnumNames;
27
+ };
28
+
29
+ export type StringArray = {
30
+ title?: Title;
31
+ /**
32
+ * @default array
33
+ * @hidden
34
+ */
35
+ type?: 'array';
36
+ items?: {
37
+ /**
38
+ * @default string
39
+ * @hidden
40
+ */
41
+ type?: 'string';
42
+ enum?: Enum;
43
+ enumNames?: EnumNames;
44
+ };
45
+ };
46
+
47
+ // TODO: Make customizable to implement arbitrary filtration blocks
48
+ export type FiltrationSchema = {
49
+ /** @title Тип недвижимости */
50
+ propertyType?: StringEnum;
51
+ /** @title Этап строительства */
52
+ stage?: StringEnum;
53
+ /** @title Категории */
54
+ categories?: StringEnum;
55
+ /** @title Дополнительно */
56
+ extraOptions?: StringEnum;
57
+ };
58
+
59
+ /**
60
+ * @title Кнопка сброса
61
+ */
62
+ export type ResetButton = {
63
+ /**
64
+ * @title Текст кнопки
65
+ */
66
+ text: string;
67
+ /**
68
+ * @title Цвет кнопки
69
+ */
70
+ buttonVersion: ButtonVersion;
71
+ };
72
+
73
+ export interface FiltrationInnerContent {
74
+ /** @title Название кнопки */
75
+ label?: string;
76
+ /** @title Количество отображаемых предметов */
77
+ topItemsCount?: number;
78
+ }
79
+
80
+ /**
81
+ * @title Фильтрация
82
+ */
83
+ export interface FiltrationContent extends FiltrationInnerContent {
84
+ /** @title Параметры фильтрации */
85
+ filtrationSchema?: FiltrationSchema;
86
+ resetButton?: ResetButton;
87
+ }
@@ -0,0 +1,67 @@
1
+ import { JSX } from '@redneckz/uni-jsx';
2
+ import { renderBlocksList } from '../../BlockRenderer/renderBlockList';
3
+ import type { IconName } from '../../icons/IconName';
4
+ import type { UniBlockProps } from '../../model/JSXBlock';
5
+ import { DefaultFoldButton } from '../../ui-kit/Foldable/DefaultFoldButton';
6
+ import { Foldable } from '../../ui-kit/Foldable/Foldable';
7
+ import { FoldableSection } from '../../ui-kit/Foldable/FoldableSection';
8
+ import { style } from '../../utils/style';
9
+ import { ErrorBlock } from '../ErrorBlock/ErrorBlock';
10
+ import { checkShouldRenderBlock } from './checkShouldRenderBlock';
11
+ import type { FiltrationInnerContent } from './FiltrationContent';
12
+
13
+ const ICONS: IconName[] = ['ArrowDownIcon', 'ArrowUpIcon'];
14
+
15
+ const resultsGridStyle = 'grid grid-cols-12 gap-1 border-box';
16
+
17
+ interface FiltrationInnerProps extends FiltrationInnerContent, UniBlockProps {
18
+ filtrationState?: Record<string, any>;
19
+ }
20
+
21
+ export const FiltrationInner = JSX<FiltrationInnerProps>(
22
+ ({ label = '', filtrationState = {}, topItemsCount = 0, block, ...rest }) => {
23
+ const blocksToRender =
24
+ block?.blocks?.filter((b) => checkShouldRenderBlock(filtrationState, b.content || {})) || [];
25
+
26
+ const [visibleBlocks, hiddenBlocks] =
27
+ topItemsCount > 0
28
+ ? [blocksToRender.slice(0, topItemsCount), blocksToRender.slice(topItemsCount)]
29
+ : [blocksToRender, []];
30
+
31
+ return (
32
+ <div>
33
+ <div className={style(blocksToRender.length ? 'hidden' : '')}>
34
+ <ErrorBlock
35
+ error={{ errorContentType: 'Image' }}
36
+ title="Нет подходящей ипотечной программы"
37
+ subtitle="Попробуйте очистить фильтры"
38
+ />
39
+ </div>
40
+ <div className={style(blocksToRender.length ? '' : 'hidden')}>
41
+ <div className={resultsGridStyle}>
42
+ {renderBlocksList(visibleBlocks, { ...rest.options, parent: block })}
43
+ </div>
44
+ <Foldable
45
+ renderFoldableSection={({ isUnfolded }) => {
46
+ return (
47
+ <FoldableSection className={resultsGridStyle} isUnfolded={isUnfolded}>
48
+ {renderBlocksList(hiddenBlocks, { ...rest.options, parent: block })}
49
+ </FoldableSection>
50
+ );
51
+ }}
52
+ renderFoldButton={({ isUnfolded, onToggle }) => (
53
+ <DefaultFoldButton
54
+ className="mt-11"
55
+ disabled={topItemsCount > hiddenBlocks.length}
56
+ label={label}
57
+ icon={ICONS[Number(isUnfolded)]}
58
+ dataTheme={rest.options?.page?.colorPalette}
59
+ onClick={onToggle}
60
+ />
61
+ )}
62
+ />
63
+ </div>
64
+ </div>
65
+ );
66
+ },
67
+ );
@@ -0,0 +1,18 @@
1
+ const isSingularFieldMatch =
2
+ <P extends Partial<Record<string, any>>, T extends P>(key: string, pattern: P) =>
3
+ (target: T) =>
4
+ pattern[key] === undefined || pattern[key] === target[key];
5
+
6
+ const isMultipleFieldMatch =
7
+ <P extends Partial<Record<string, any[]>>, T extends P>(key: string, pattern: P) =>
8
+ (target: T) =>
9
+ pattern[key] === undefined || pattern[key]?.every((_) => target[key]?.includes(_));
10
+
11
+ export const checkShouldRenderBlock = (pattern: Record<string, any>, target: Record<string, any>) =>
12
+ Object.entries(pattern)
13
+ .map(([key, subPattern]) =>
14
+ Array.isArray(subPattern)
15
+ ? isMultipleFieldMatch(key, pattern)
16
+ : isSingularFieldMatch(key, pattern),
17
+ )
18
+ .every((predicate) => predicate(target));
@@ -0,0 +1,36 @@
1
+ import type { FormElementRegisterer } from '../../hooks/useForm';
2
+ import { SlideCheckboxGroup } from '../../ui-kit/SlideCheckboxGroup/SlideCheckboxGroup';
3
+ import { Text } from '../../ui-kit/Text/Text';
4
+ import type { FiltrationSchema, StringEnum } from './FiltrationContent';
5
+
6
+ export const renderFormItem =
7
+ (filtrationSchema: FiltrationSchema, register: FormElementRegisterer) => (key: string) => {
8
+ const item = filtrationSchema[key as keyof typeof filtrationSchema];
9
+ const type = item?.type;
10
+
11
+ switch (type) {
12
+ case 'string':
13
+ return renderRadioButtons(key, register)(item);
14
+ default:
15
+ return null;
16
+ }
17
+ };
18
+
19
+ const renderRadioButtons =
20
+ (key: string, register: FormElementRegisterer) => (item?: StringEnum) => {
21
+ const options =
22
+ item?.enum?.map((e, i) => ({ value: e, title: item?.enumNames?.[i] || '' })) || [];
23
+
24
+ return (
25
+ <div role="radiogroup" key={key}>
26
+ {item?.title ? (
27
+ <div className="mb-4">
28
+ <Text size="text-m" font="font-light" color="text-secondary-text">
29
+ {item.title}
30
+ </Text>
31
+ </div>
32
+ ) : null}
33
+ <SlideCheckboxGroup items={options} multiple={false} {...register(key)} />
34
+ </div>
35
+ );
36
+ };
@@ -0,0 +1,29 @@
1
+ import { useCallback, useRef, useState } from '@redneckz/uni-jsx/lib/hooks';
2
+
3
+ export type FormElementRegisterer = ReturnType<typeof useForm>['register'];
4
+
5
+ export const useForm = <FormState extends Record<string, any>>(
6
+ initialState: Partial<FormState> = {},
7
+ ) => {
8
+ const [formState, setFormState] = useState<Partial<FormState>>(initialState);
9
+
10
+ const handlersMap = useRef<Partial<Record<keyof FormState, () => void>>>({});
11
+
12
+ const register = <FieldName extends keyof FormState>(fieldName: FieldName) => {
13
+ if (!handlersMap.current) {
14
+ return {};
15
+ }
16
+
17
+ const handler = (value?: FormState[FieldName]) => {
18
+ setFormState((prev) => ({ ...prev, [fieldName]: value }));
19
+ };
20
+
21
+ handlersMap.current[fieldName] ||= handler;
22
+
23
+ return { value: formState?.[fieldName], onChange: handlersMap.current[fieldName] };
24
+ };
25
+
26
+ const resetForm = useCallback(() => setFormState({}), []);
27
+
28
+ return { formState, register, resetForm };
29
+ };
@@ -1,4 +1,5 @@
1
1
  import type { UNIComponent } from '@redneckz/uni-jsx';
2
+ import type { JSONSchema7Definition } from 'json-schema';
2
3
  import type { BlockRendererOptions } from '../BlockRenderer/BlockRendererOptions';
3
4
  import type { SlotName } from './BlockDecorator';
4
5
  import type { BlockVersion } from './BlockVersion';
@@ -26,5 +27,6 @@ export type JSXBlock<BlockProps extends UniBlockProps = UniBlockProps> = UNIComp
26
27
  VNode | VNode[]
27
28
  > & {
28
29
  childrenTypes?: string[] | { include?: string[]; exclude?: string[] };
30
+ childSchema?: (content: BlockDef['content']) => Record<string, JSONSchema7Definition>;
29
31
  slots?: (props: BlockProps) => SlotName[];
30
32
  };
@@ -0,0 +1,4 @@
1
+ export interface ControlProps<T> {
2
+ value?: T;
3
+ onChange?: (value: T | undefined) => void;
4
+ }