@cloud-ru/uikit-product-calculator 0.33.3

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 (205) hide show
  1. package/CHANGELOG.md +1508 -0
  2. package/LICENSE +201 -0
  3. package/README.md +85 -0
  4. package/package.json +75 -0
  5. package/src/components/Calculator/Calculator.tsx +79 -0
  6. package/src/components/Calculator/index.ts +1 -0
  7. package/src/components/CalculatorContent/CalculatorContent.tsx +38 -0
  8. package/src/components/CalculatorContent/index.ts +1 -0
  9. package/src/components/CalculatorContent/styles.module.scss +79 -0
  10. package/src/components/Catalog/Catalog.tsx +225 -0
  11. package/src/components/Catalog/components/PrivateCardHeader.tsx +63 -0
  12. package/src/components/Catalog/components/index.ts +1 -0
  13. package/src/components/Catalog/components/styles.module.scss +35 -0
  14. package/src/components/Catalog/index.ts +1 -0
  15. package/src/components/Catalog/styles.module.scss +104 -0
  16. package/src/components/Controls/AlertControl/AlertControl.tsx +44 -0
  17. package/src/components/Controls/AlertControl/index.ts +1 -0
  18. package/src/components/Controls/ArrayControl/ArrayControl.tsx +105 -0
  19. package/src/components/Controls/ArrayControl/index.ts +1 -0
  20. package/src/components/Controls/ArrayControl/styles.module.scss +33 -0
  21. package/src/components/Controls/CarouselControl/CarouselControl.tsx +173 -0
  22. package/src/components/Controls/CarouselControl/index.ts +1 -0
  23. package/src/components/Controls/CarouselControl/styles.module.scss +32 -0
  24. package/src/components/Controls/Control/Control.tsx +205 -0
  25. package/src/components/Controls/Control/index.ts +1 -0
  26. package/src/components/Controls/ObjectControl/ObjectControl.tsx +150 -0
  27. package/src/components/Controls/ObjectControl/index.ts +1 -0
  28. package/src/components/Controls/ObjectControl/styles.module.scss +18 -0
  29. package/src/components/Controls/ObjectDecorator/ObjectDecorator.tsx +23 -0
  30. package/src/components/Controls/ObjectDecorator/index.ts +1 -0
  31. package/src/components/Controls/ObjectDecorator/styles.module.scss +15 -0
  32. package/src/components/Controls/SegmentedControl/SegmentedControl.tsx +79 -0
  33. package/src/components/Controls/SegmentedControl/SegmentedControlCard.tsx +38 -0
  34. package/src/components/Controls/SegmentedControl/index.ts +1 -0
  35. package/src/components/Controls/SegmentedControl/styles.module.scss +8 -0
  36. package/src/components/Controls/SelectControl/SelectControl.tsx +172 -0
  37. package/src/components/Controls/SelectControl/index.ts +1 -0
  38. package/src/components/Controls/SelectControl/styles.module.scss +5 -0
  39. package/src/components/Controls/SliderControl/SliderControl.tsx +92 -0
  40. package/src/components/Controls/SliderControl/index.ts +1 -0
  41. package/src/components/Controls/StepperControl/StepperControl.tsx +160 -0
  42. package/src/components/Controls/StepperControl/index.ts +1 -0
  43. package/src/components/Controls/StepperControl/styles.module.scss +16 -0
  44. package/src/components/Controls/TableControl/TableControl.tsx +162 -0
  45. package/src/components/Controls/TableControl/helperComponents/StepperWithAllowedValues.tsx +50 -0
  46. package/src/components/Controls/TableControl/helperComponents/index.ts +1 -0
  47. package/src/components/Controls/TableControl/helperComponents/styles.module.scss +53 -0
  48. package/src/components/Controls/TableControl/index.ts +1 -0
  49. package/src/components/Controls/TableControl/styles.module.scss +104 -0
  50. package/src/components/Controls/ToggleCard/ToggleCard.tsx +46 -0
  51. package/src/components/Controls/ToggleCard/index.ts +1 -0
  52. package/src/components/Controls/ToggleCard/styles.module.scss +11 -0
  53. package/src/components/Controls/ToggleCardsControl/ToggleCardsControl.tsx +93 -0
  54. package/src/components/Controls/ToggleCardsControl/index.ts +1 -0
  55. package/src/components/Controls/ToggleCardsControl/styles.module.scss +40 -0
  56. package/src/components/Controls/ToggleControl/ToggleControl.tsx +59 -0
  57. package/src/components/Controls/ToggleControl/components/SwitchRow.tsx +98 -0
  58. package/src/components/Controls/ToggleControl/components/index.ts +1 -0
  59. package/src/components/Controls/ToggleControl/components/styles.module.scss +110 -0
  60. package/src/components/Controls/ToggleControl/index.ts +1 -0
  61. package/src/components/Controls/ToggleObjectControl/ToggleObjectControl.tsx +111 -0
  62. package/src/components/Controls/ToggleObjectControl/index.ts +1 -0
  63. package/src/components/Controls/ToggleObjectControl/styles.module.scss +13 -0
  64. package/src/components/Controls/constants.ts +16 -0
  65. package/src/components/Controls/index.tsx +26 -0
  66. package/src/components/Controls/types.ts +181 -0
  67. package/src/components/Controls/utils.ts +49 -0
  68. package/src/components/Disclaimer/Disclaimer.tsx +33 -0
  69. package/src/components/Disclaimer/index.ts +1 -0
  70. package/src/components/Disclaimer/styles.module.scss +14 -0
  71. package/src/components/HeaderContainer/index.tsx +32 -0
  72. package/src/components/HeaderContainer/styles.module.scss +24 -0
  73. package/src/components/PriceSummary/PriceSummary.tsx +158 -0
  74. package/src/components/PriceSummary/components/PricePeriodSelect/PricePeriodSelect.tsx +81 -0
  75. package/src/components/PriceSummary/components/PricePeriodSelect/index.ts +1 -0
  76. package/src/components/PriceSummary/components/ProductCard/ProductCard.tsx +85 -0
  77. package/src/components/PriceSummary/components/ProductCard/index.ts +1 -0
  78. package/src/components/PriceSummary/components/ProductCard/styles.module.scss +7 -0
  79. package/src/components/PriceSummary/components/ProductListActions/ProductListActions.tsx +118 -0
  80. package/src/components/PriceSummary/components/ProductListActions/index.ts +1 -0
  81. package/src/components/PriceSummary/components/ProductListActions/styles.module.scss +38 -0
  82. package/src/components/PriceSummary/components/index.ts +3 -0
  83. package/src/components/PriceSummary/hooks.ts +36 -0
  84. package/src/components/PriceSummary/index.ts +1 -0
  85. package/src/components/PriceSummary/styles.module.scss +110 -0
  86. package/src/components/PriceSummary/utils/getTotalPrice.ts +19 -0
  87. package/src/components/PriceSummary/utils/index.ts +2 -0
  88. package/src/components/PriceSummary/utils/transformToProductCardData.ts +36 -0
  89. package/src/components/ProductHeadline/ProductPageHeadline.tsx +134 -0
  90. package/src/components/ProductHeadline/components/PriceCount.tsx +93 -0
  91. package/src/components/ProductHeadline/components/index.ts +1 -0
  92. package/src/components/ProductHeadline/components/styles.module.scss +52 -0
  93. package/src/components/ProductHeadline/index.ts +1 -0
  94. package/src/components/ProductHeadline/styles.module.scss +32 -0
  95. package/src/components/ProductPage/ProductPage.tsx +105 -0
  96. package/src/components/ProductPage/index.ts +1 -0
  97. package/src/components/ProductPage/styles.module.scss +13 -0
  98. package/src/components/Welcome/Welcome.tsx +138 -0
  99. package/src/components/Welcome/index.ts +1 -0
  100. package/src/components/Welcome/styles.module.scss +155 -0
  101. package/src/components/index.ts +3 -0
  102. package/src/config/config.tsx +27 -0
  103. package/src/config/index.ts +2 -0
  104. package/src/config/platforms/advanced/catalog.ts +82 -0
  105. package/src/config/platforms/advanced/constants.ts +23 -0
  106. package/src/config/platforms/advanced/index.ts +5 -0
  107. package/src/config/platforms/advanced/platform.tsx +13 -0
  108. package/src/config/platforms/advanced/product-config/AdvancedCloudBackup.ts +76 -0
  109. package/src/config/platforms/advanced/product-config/AdvancedCloudContainerEngine.tsx +260 -0
  110. package/src/config/platforms/advanced/product-config/AdvancedCloudServer.tsx +526 -0
  111. package/src/config/platforms/advanced/product-config/AdvancedDataAsYouUse.ts +159 -0
  112. package/src/config/platforms/advanced/product-config/AdvancedDataLakeInsight.ts +134 -0
  113. package/src/config/platforms/advanced/product-config/AdvancedDataWarehouseService.ts +94 -0
  114. package/src/config/platforms/advanced/product-config/AdvancedDcsMemcached.ts +69 -0
  115. package/src/config/platforms/advanced/product-config/AdvancedDcsRedis.ts +220 -0
  116. package/src/config/platforms/advanced/product-config/AdvancedDmsKafka.tsx +186 -0
  117. package/src/config/platforms/advanced/product-config/AdvancedDmsRabbitMq.ts +202 -0
  118. package/src/config/platforms/advanced/product-config/AdvancedDocumentDatabase.tsx +323 -0
  119. package/src/config/platforms/advanced/product-config/AdvancedElasticLoadBalance.tsx +252 -0
  120. package/src/config/platforms/advanced/product-config/AdvancedElasticSearch.ts +365 -0
  121. package/src/config/platforms/advanced/product-config/AdvancedFunctionGraph.tsx +65 -0
  122. package/src/config/platforms/advanced/product-config/AdvancedMapReduce.tsx +394 -0
  123. package/src/config/platforms/advanced/product-config/AdvancedMySqlDataBase.ts +417 -0
  124. package/src/config/platforms/advanced/product-config/AdvancedNetwork.ts +146 -0
  125. package/src/config/platforms/advanced/product-config/AdvancedObjectStorage.ts +232 -0
  126. package/src/config/platforms/advanced/product-config/AdvancedPostgreSqlDatabase.ts +402 -0
  127. package/src/config/platforms/advanced/product-config/AdvancedScalableFile.tsx +161 -0
  128. package/src/config/platforms/advanced/product-config/AdvancedSqlDatabase.ts +380 -0
  129. package/src/config/platforms/advanced/product-config/index.ts +21 -0
  130. package/src/config/platforms/advanced/products.ts +267 -0
  131. package/src/config/platforms/evolution/catalog.tsx +107 -0
  132. package/src/config/platforms/evolution/constants.ts +80 -0
  133. package/src/config/platforms/evolution/index.ts +5 -0
  134. package/src/config/platforms/evolution/platform.tsx +13 -0
  135. package/src/config/platforms/evolution/product-config/EvolutionArenadataDb.ts +151 -0
  136. package/src/config/platforms/evolution/product-config/EvolutionArtifactRegistry.ts +57 -0
  137. package/src/config/platforms/evolution/product-config/EvolutionBareMetal.tsx +172 -0
  138. package/src/config/platforms/evolution/product-config/EvolutionCloudServer.tsx +407 -0
  139. package/src/config/platforms/evolution/product-config/EvolutionCloudServerFreeTier.tsx +185 -0
  140. package/src/config/platforms/evolution/product-config/EvolutionCloudServerGpu.tsx +301 -0
  141. package/src/config/platforms/evolution/product-config/EvolutionContainerApps.ts +84 -0
  142. package/src/config/platforms/evolution/product-config/EvolutionContainerAppsFreeTier.ts +29 -0
  143. package/src/config/platforms/evolution/product-config/EvolutionKubernetes.ts +388 -0
  144. package/src/config/platforms/evolution/product-config/EvolutionManagedMetastore.ts +38 -0
  145. package/src/config/platforms/evolution/product-config/EvolutionManagedRedis.ts +161 -0
  146. package/src/config/platforms/evolution/product-config/EvolutionManagedSpark.ts +360 -0
  147. package/src/config/platforms/evolution/product-config/EvolutionManagedTrino.ts +53 -0
  148. package/src/config/platforms/evolution/product-config/EvolutionMlInference.tsx +703 -0
  149. package/src/config/platforms/evolution/product-config/EvolutionPostgreSql.ts +217 -0
  150. package/src/config/platforms/evolution/product-config/EvolutionPublicIp.ts +39 -0
  151. package/src/config/platforms/evolution/product-config/EvolutionSnatGateway.ts +22 -0
  152. package/src/config/platforms/evolution/product-config/EvolutionStorageS3.ts +223 -0
  153. package/src/config/platforms/evolution/product-config/EvolutionStorageS3FreeTier.ts +97 -0
  154. package/src/config/platforms/evolution/product-config/index.ts +17 -0
  155. package/src/config/platforms/evolution/products.ts +260 -0
  156. package/src/config/platforms/index.ts +3 -0
  157. package/src/config/platforms/vmware/catalog.ts +19 -0
  158. package/src/config/platforms/vmware/constants.ts +6 -0
  159. package/src/config/platforms/vmware/index.ts +5 -0
  160. package/src/config/platforms/vmware/platform.tsx +13 -0
  161. package/src/config/platforms/vmware/product-config/VmWareCloudBackup.ts +56 -0
  162. package/src/config/platforms/vmware/product-config/VmWareVirtualDataCenter.ts +309 -0
  163. package/src/config/platforms/vmware/product-config/VmWareVirtualMachinesBackup.ts +58 -0
  164. package/src/config/platforms/vmware/product-config/VmWareVirtualWorkspaces.tsx +210 -0
  165. package/src/config/platforms/vmware/product-config/index.ts +4 -0
  166. package/src/config/platforms/vmware/products.ts +63 -0
  167. package/src/config/styles.module.scss +9 -0
  168. package/src/config/utils/disk.ts +94 -0
  169. package/src/config/utils/diskPostgreSqlMySQL.ts +94 -0
  170. package/src/config/utils/eip.ts +104 -0
  171. package/src/config/utils/index.ts +52 -0
  172. package/src/config/utils/obs.ts +100 -0
  173. package/src/constants.ts +56 -0
  174. package/src/contexts/CalculatorContext.tsx +193 -0
  175. package/src/contexts/ProductContext.ts +25 -0
  176. package/src/contexts/index.ts +2 -0
  177. package/src/hooks/index.ts +6 -0
  178. package/src/hooks/useAdaptive.ts +20 -0
  179. package/src/hooks/useCatalogCardClick.ts +37 -0
  180. package/src/hooks/useProductClick.ts +14 -0
  181. package/src/hooks/useProductDelete.ts +46 -0
  182. package/src/index.ts +6 -0
  183. package/src/services/constants.ts +5 -0
  184. package/src/services/getFetcherFn.ts +57 -0
  185. package/src/services/getInitPrice.ts +64 -0
  186. package/src/services/getOnDownloadFileClick.ts +37 -0
  187. package/src/services/getOnShareClick.ts +56 -0
  188. package/src/services/index.ts +4 -0
  189. package/src/types/CalculatorType.ts +16 -0
  190. package/src/types/CatalogConfig.ts +13 -0
  191. package/src/types/Category.ts +14 -0
  192. package/src/types/FetcherFn.ts +26 -0
  193. package/src/types/FormValues.ts +4 -0
  194. package/src/types/Platform.ts +24 -0
  195. package/src/types/Price.ts +18 -0
  196. package/src/types/Product.ts +39 -0
  197. package/src/types/ProductState.ts +11 -0
  198. package/src/types/State.ts +7 -0
  199. package/src/types/index.ts +10 -0
  200. package/src/utils/filterNonEmptyArrays.ts +13 -0
  201. package/src/utils/formatNumber.ts +5 -0
  202. package/src/utils/getPrice.ts +38 -0
  203. package/src/utils/index.ts +5 -0
  204. package/src/utils/parseKeyToDataTest.ts +14 -0
  205. package/src/utils/value.ts +11 -0
@@ -0,0 +1,98 @@
1
+ import cn from 'classnames';
2
+ import { KeyboardEventHandler, ReactNode } from 'react';
3
+
4
+ import { extractSupportProps } from '@cloud-ru/uikit-product-utils';
5
+ import { Switch } from '@snack-uikit/toggles';
6
+ import { Tooltip } from '@snack-uikit/tooltip';
7
+
8
+ import { parseKeyToDataTest } from '../../../../utils';
9
+ import { ObjectDecorator } from '../../ObjectDecorator';
10
+ import { TooltipPlacement } from '../../types';
11
+ import styles from './styles.module.scss';
12
+
13
+ export type SwitchRowProps = {
14
+ label?: string;
15
+ description?: string;
16
+ checked: boolean;
17
+ disabled?: boolean;
18
+ loading?: boolean;
19
+ onChange(checked: boolean): void;
20
+ labelTooltip?: ReactNode;
21
+ labelTooltipPlacement?: TooltipPlacement;
22
+ disabledToggleTip?: ReactNode;
23
+ className?: string;
24
+ disableTitleTruncate?: boolean;
25
+ dataTestId: string;
26
+ };
27
+
28
+ export function SwitchRow({
29
+ label,
30
+ description,
31
+ checked,
32
+ disabled,
33
+ onChange,
34
+ labelTooltip,
35
+ labelTooltipPlacement,
36
+ className,
37
+ disabledToggleTip,
38
+ loading,
39
+ dataTestId,
40
+ ...rest
41
+ }: SwitchRowProps) {
42
+ const handleChange = () => !disabled && onChange(!checked);
43
+
44
+ const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = e => {
45
+ if (e.code === 'Enter' || e.code === 'Space') {
46
+ handleChange();
47
+ }
48
+ };
49
+
50
+ const toggle = (
51
+ <Switch
52
+ size='m'
53
+ checked={checked}
54
+ disabled={disabled}
55
+ data-pointer
56
+ showIcon={false}
57
+ tabIndex={-1}
58
+ loading={loading}
59
+ />
60
+ );
61
+
62
+ return (
63
+ <div
64
+ className={cn(styles.switchRow, className)}
65
+ role='switch'
66
+ aria-checked={checked}
67
+ tabIndex={disabled ? -1 : 0}
68
+ onClick={handleChange}
69
+ onKeyDown={handleKeyDown}
70
+ data-disabled={disabled || undefined}
71
+ data-loading={loading || undefined}
72
+ data-checked={checked || undefined}
73
+ data-mobile
74
+ data-test-id={dataTestId}
75
+ {...extractSupportProps(rest)}
76
+ >
77
+ <div className={styles.headline}>
78
+ <div className={styles.titleLayout}>
79
+ <div className={styles.titleWrapper} data-test-id={parseKeyToDataTest('toggle', 'title')}>
80
+ <ObjectDecorator label={label} labelTooltip={labelTooltip} labelTooltipPlacement={labelTooltipPlacement} />
81
+ </div>
82
+ </div>
83
+
84
+ <div className={styles.wrap}>
85
+ {disabled && disabledToggleTip ? (
86
+ <Tooltip tip={disabledToggleTip} triggerClassName={styles.switchRowWrapper}>
87
+ {toggle}
88
+ </Tooltip>
89
+ ) : (
90
+ toggle
91
+ )}
92
+ </div>
93
+ </div>
94
+
95
+ {description && <span className={styles.description}>{description}</span>}
96
+ </div>
97
+ );
98
+ }
@@ -0,0 +1 @@
1
+ export * from './SwitchRow';
@@ -0,0 +1,110 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-element' as element;
2
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-accordion' as accordion;
3
+
4
+ .description {
5
+ @include accordion.composite-var(accordion.$sans-body-m);
6
+
7
+ color: accordion.$sys-neutral-text-support;
8
+ }
9
+
10
+ .titleLayout {
11
+ @include accordion.composite-var(accordion.$sans-title-m);
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: flex-start;
15
+ gap: 4px;
16
+ flex-grow: 0;
17
+ overflow: hidden;
18
+
19
+ color: accordion.$sys-neutral-text-main;
20
+ }
21
+
22
+ .headline {
23
+ position: relative;
24
+ display: flex;
25
+ align-items: flex-start;
26
+ gap: 8px;
27
+
28
+ justify-content: space-between;
29
+ }
30
+
31
+ .switchRowWrapper {
32
+ display: inline-flex;
33
+ }
34
+
35
+ .switchRow {
36
+ @include accordion.composite-var(accordion.$collapse-block-container-primary);
37
+ @include accordion.composite-var(accordion.$collapse-block, 'container', 'shape-round');
38
+
39
+ box-sizing: border-box;
40
+
41
+ cursor: pointer;
42
+ position: relative;
43
+ overflow: hidden;
44
+ border: solid 1px accordion.$sys-neutral-decor-default;
45
+
46
+ background-color: accordion.$sys-neutral-background1-level;
47
+
48
+ &:focus-within,
49
+ &:hover {
50
+ background-color: accordion.$sys-neutral-background2-level;
51
+ }
52
+
53
+ &:focus-visible {
54
+ @include accordion.outline-var(element.$container-focused-s);
55
+
56
+ outline-color: accordion.$sys-available-complementary;
57
+ }
58
+
59
+ * {
60
+ &[data-pointer] {
61
+ cursor: pointer;
62
+ }
63
+ }
64
+
65
+ &[data-loading] {
66
+ cursor: wait;
67
+
68
+ * {
69
+ &[data-pointer] {
70
+ cursor: wait;
71
+ }
72
+ }
73
+ }
74
+
75
+ &[data-disabled] {
76
+ cursor: not-allowed;
77
+ background-color: transparent;
78
+
79
+ &::before {
80
+ background-color: accordion.$sys-neutral-accent-default;
81
+ opacity: 0.08;
82
+ }
83
+
84
+ .titleLayout,
85
+ .description {
86
+ color: accordion.$sys-neutral-text-disabled;
87
+ }
88
+
89
+ * {
90
+ &[data-pointer] {
91
+ cursor: not-allowed;
92
+ }
93
+ }
94
+ }
95
+
96
+ &[data-mobile] {
97
+ padding: 16px;
98
+ }
99
+ }
100
+
101
+ .titleWrapper {
102
+ display: flex;
103
+ align-items: flex-start;
104
+ overflow: hidden;
105
+ gap: 4px;
106
+ }
107
+
108
+ .wrap {
109
+ display: flex;
110
+ }
@@ -0,0 +1 @@
1
+ export * from './ToggleControl';
@@ -0,0 +1,111 @@
1
+ import { useMemo, useState } from 'react';
2
+
3
+ import { MobileAccordionPrimary } from '@cloud-ru/uikit-product-mobile-accordion';
4
+ import { Divider } from '@snack-uikit/divider';
5
+ import { Switch } from '@snack-uikit/toggles';
6
+
7
+ import { ProductContext, useCalculatorContext, useProductContext } from '../../../contexts';
8
+ import { FormValues } from '../../../types';
9
+ import { getValue, setValue } from '../../../utils';
10
+ import { CONTROL } from '../constants';
11
+ import { Control } from '../Control';
12
+ import { ObjectDecorator } from '../ObjectDecorator';
13
+ import { BaseControl, FormControl } from '../types';
14
+ import styles from './styles.module.scss';
15
+
16
+ type UiProps = {
17
+ disabled?: boolean;
18
+ };
19
+
20
+ export type ToggleObjectControl = {
21
+ type: typeof CONTROL.ToggleObject;
22
+ /**
23
+ * Поле, для значения вкл/выкл контрола
24
+ *
25
+ * @example 'eipIsNeeded'
26
+ */
27
+ switchKey: string;
28
+ /** Конфигурация тела аккордеона */
29
+ control: FormControl;
30
+
31
+ onChangeFn?: never;
32
+ } & Pick<
33
+ BaseControl<UiProps>,
34
+ 'decoratorProps' | 'uiProps' | 'watchedControls' | 'relateFn' | 'onChangePeriod' | 'canChangeWholePricePeriod'
35
+ >;
36
+
37
+ type ToggleObjectControlUiProps = ToggleObjectControl & {
38
+ value: FormValues;
39
+ onChange(value: FormValues): void;
40
+ watchedValues?: FormValues;
41
+ };
42
+
43
+ export function ToggleObjectControlUi({
44
+ decoratorProps,
45
+ control,
46
+ switchKey,
47
+ relateFn,
48
+ watchedValues,
49
+ uiProps,
50
+ }: ToggleObjectControlUiProps) {
51
+ const [expanded, setExpanded] = useState<string | undefined>(undefined);
52
+
53
+ const { value: valueProp, onChange: onChangeProp } = useProductContext();
54
+ const { onAnalyticsClick } = useCalculatorContext();
55
+
56
+ const { decoratorProps: relatedDecoratorProps, uiProps: relatedUiProps } = useMemo(
57
+ () => relateFn?.(watchedValues ?? {}) ?? {},
58
+ [relateFn, watchedValues],
59
+ );
60
+ const value: boolean = getValue(valueProp, switchKey);
61
+ const onChange = (newValue: boolean) => {
62
+ setValue(valueProp, switchKey, newValue);
63
+ onChangeProp({ ...valueProp });
64
+ };
65
+
66
+ const AdaptiveAccordionPrimary = MobileAccordionPrimary;
67
+
68
+ const visible = relatedUiProps?.visible ?? uiProps?.visible ?? true;
69
+
70
+ if (!visible) {
71
+ return null;
72
+ }
73
+
74
+ return (
75
+ <>
76
+ <AdaptiveAccordionPrimary selectionMode='single' expanded={expanded} onExpandedChange={setExpanded}>
77
+ <AdaptiveAccordionPrimary.CollapseBlock
78
+ outline
79
+ id='key'
80
+ header={<ObjectDecorator {...decoratorProps} {...relatedDecoratorProps} />}
81
+ actions={
82
+ <Switch
83
+ showIcon={false}
84
+ checked={value}
85
+ onChange={checked => {
86
+ onAnalyticsClick(String(checked), `toggle-object-control-ui`);
87
+ onChange(checked);
88
+ checked && setExpanded('key');
89
+ }}
90
+ />
91
+ }
92
+ >
93
+ <div className={styles.content}>
94
+ <Divider />
95
+ <ProductContext.Provider
96
+ value={{
97
+ value: valueProp,
98
+ onChange: newValue => {
99
+ setValue(newValue, switchKey, true);
100
+ onChangeProp({ ...newValue });
101
+ },
102
+ }}
103
+ >
104
+ <Control formControl={{ ...control, accessorKey: '' }} />
105
+ </ProductContext.Provider>
106
+ </div>
107
+ </AdaptiveAccordionPrimary.CollapseBlock>
108
+ </AdaptiveAccordionPrimary>
109
+ </>
110
+ );
111
+ }
@@ -0,0 +1 @@
1
+ export * from './ToggleObjectControl';
@@ -0,0 +1,13 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
+
3
+ .content {
4
+ display: flex;
5
+ flex-direction: column;
6
+ margin-top: stv.$dimension-1m;
7
+ gap: stv.$dimension-3m;
8
+ padding: stv.$dimension-050m;
9
+ }
10
+
11
+ .tip {
12
+ max-width: stv.$size-tooltip-container-max-width;
13
+ }
@@ -0,0 +1,16 @@
1
+ export const CONTROL = {
2
+ Object: 'object',
3
+ Array: 'array',
4
+ ToggleObject: 'toggle-object',
5
+ SelectSingle: 'select-single',
6
+ SelectMultiple: 'select-multiple',
7
+ Segmented: 'segmented',
8
+ Carousel: 'carousel',
9
+ Toggle: 'toggle',
10
+ ToggleCards: 'toggle-cards',
11
+ Stepper: 'stepper',
12
+ Alert: 'alert',
13
+ Table: 'table',
14
+ Slider: 'slider',
15
+ StepperWithValues: 'stepper-with-values',
16
+ } as const;
@@ -0,0 +1,26 @@
1
+ import { AlertControl } from './AlertControl';
2
+ import { ArrayControl } from './ArrayControl';
3
+ import { CarouselControl } from './CarouselControl';
4
+ import { ObjectControl } from './ObjectControl';
5
+ import { SegmentedControl } from './SegmentedControl';
6
+ import { SelectMultipleControl, SelectSingleControl } from './SelectControl';
7
+ import { StepperControl } from './StepperControl';
8
+ import { ToggleControl } from './ToggleControl';
9
+ import { ToggleObjectControl } from './ToggleObjectControl';
10
+
11
+ export type { FormControl, FormConfig } from './types';
12
+
13
+ export type {
14
+ CarouselControl,
15
+ SelectSingleControl,
16
+ SelectMultipleControl,
17
+ SegmentedControl,
18
+ ToggleControl,
19
+ StepperControl,
20
+ ObjectControl,
21
+ ArrayControl,
22
+ ToggleObjectControl,
23
+ AlertControl,
24
+ };
25
+
26
+ export * from './constants';
@@ -0,0 +1,181 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { AnyType, FormValues, PRICE_PERIOD } from '../../types';
4
+ import { AlertControl } from './AlertControl';
5
+ import { ArrayControl } from './ArrayControl';
6
+ import { CarouselControl } from './CarouselControl';
7
+ import { ObjectControl } from './ObjectControl';
8
+ import { SegmentedControl } from './SegmentedControl';
9
+ import { SelectMultipleControl, SelectSingleControl } from './SelectControl';
10
+ import { SliderControl } from './SliderControl';
11
+ import { StepperControl } from './StepperControl';
12
+ import { TableControl } from './TableControl';
13
+ import { ToggleCardsControl } from './ToggleCardsControl';
14
+ import { ToggleControl } from './ToggleControl';
15
+ import { ToggleObjectControl } from './ToggleObjectControl';
16
+
17
+ export type TooltipPlacement =
18
+ | 'left'
19
+ | 'left-start'
20
+ | 'left-end'
21
+ | 'right'
22
+ | 'right-start'
23
+ | 'right-end'
24
+ | 'top'
25
+ | 'top-start'
26
+ | 'top-end'
27
+ | 'bottom'
28
+ | 'bottom-start'
29
+ | 'bottom-end';
30
+
31
+ /** Базовые параметры декоратора для поля */
32
+ export type BaseDecoratorProps = {
33
+ /** Лейбл */
34
+ label?: string;
35
+ /** Дополнительный текст */
36
+ hint?: string;
37
+ /** Вспомогательный тултип */
38
+ labelTooltip?: ReactNode;
39
+ /** Расположение тултипа */
40
+ labelTooltipPlacement?: TooltipPlacement;
41
+ /** Дополтительный текст сверху */
42
+ caption?: string;
43
+ /** Флаг обязательное поле или нет */
44
+ required?: boolean;
45
+ };
46
+
47
+ export type WithVisible<T> = T & {
48
+ /** Флаг, отрисовывать элемент или нет */
49
+ visible?: boolean;
50
+ };
51
+
52
+ export type BaseControl<UiPropsT, DecoratorPropsT = BaseDecoratorProps> = {
53
+ /** Пропсы для декоратора
54
+ *
55
+ * @example
56
+ * {
57
+ * label: 'Колличество vCpu',
58
+ * labelToolTip: 'Виртуальные ядра'
59
+ * }
60
+ */
61
+ decoratorProps: DecoratorPropsT;
62
+ /**
63
+ * Специфичные пропсы для контролла
64
+ *
65
+ * @example
66
+ * {
67
+ * min: 0;
68
+ * max: 100;
69
+ * visible: true;
70
+ * }
71
+ */
72
+ uiProps?: WithVisible<UiPropsT>;
73
+ /**
74
+ * Поле (полный путь), куда будет сохраняться значение контролла
75
+ *
76
+ * @example 'esc.cpu'
77
+ */
78
+ accessorKey: string;
79
+ /**
80
+ * Функция для мутирования значения формы, eсли при изменении контролла, нужно изменить "явно" значения других
81
+ *
82
+ *
83
+ * @param {string} value - Новое значение, которое было установлено.
84
+ *
85
+ * @param {function(Array<[string, AnyType]>): void} setValue - Функция для установки нового значения.
86
+ *
87
+ * @returns {void}
88
+ *
89
+ * @example (value, setValue) => {
90
+ * // Изменение значения текущего контролла
91
+ * const arr = [['currentControlAccessorKey', value]];
92
+ * // Некоторое условие
93
+ * if(...someRule) {
94
+ * // Задаем значения для других контроллов
95
+ * arr.push(['someAnotherKey_1', someValue_1]);
96
+ * arr.push(['someAnotherKey_2', someValue_2]);
97
+ * }
98
+ * // Мутируем конфигурацию формы, чтобы применить изменения
99
+ * setValue(arr);
100
+ * }
101
+ */
102
+ onChangeFn?(value: string, setValue: (arr: [string, AnyType][]) => void): void;
103
+ /**
104
+ * Отслеживаемые "более главные" поля
105
+ *
106
+ * @example { storageClass: 'storages[0].obs.storageClass' },
107
+ */
108
+ watchedControls?: Record<string, string>;
109
+ /**
110
+ * Функция для изменения параметров контролла
111
+ *
112
+ * @param watchedValues - вычисленные 'watchedControls'
113
+ *
114
+ * @example ({ storageClass }) => {
115
+ * if (storageClass !== StorageClassItem.Cold) {
116
+ * return {
117
+ * uiProps: {
118
+ * visible: false,
119
+ * },
120
+ * };
121
+ * }
122
+ * }
123
+ */
124
+ relateFn?(watchedValues: FormValues):
125
+ | {
126
+ decoratorProps?: Partial<DecoratorPropsT>;
127
+ uiProps?: Partial<WithVisible<UiPropsT>>;
128
+ }
129
+ | undefined;
130
+ onChangePeriod?: (value: PRICE_PERIOD, setValue: (arr: [string, AnyType][]) => void) => void;
131
+ canChangeWholePricePeriod?: boolean;
132
+ };
133
+
134
+ export type BaseControlWithItems<ItemT, UiPropsT, DecoratorPropsT = BaseDecoratorProps> = Omit<
135
+ BaseControl<UiPropsT, DecoratorPropsT>,
136
+ 'relateFn'
137
+ > & {
138
+ /** Массив перечисляемых опций */
139
+ items: ItemT[];
140
+ /**
141
+ * Функция для изменения параметров контролла
142
+ *
143
+ * @param watchedValues - вычисленные 'watchedControls'
144
+ *
145
+ * @example ({ storageClass }) => {
146
+ * if (storageClass !== StorageClassItem.Cold) {
147
+ * return {
148
+ * uiProps: {
149
+ * visible: false,
150
+ * },
151
+ * };
152
+ * }
153
+ * }```
154
+ */
155
+ relateFn?(watchedValues: FormValues):
156
+ | {
157
+ decoratorProps?: Partial<DecoratorPropsT>;
158
+ uiProps?: Partial<WithVisible<UiPropsT>>;
159
+ items?: ItemT[];
160
+ }
161
+ | undefined;
162
+ onChangePeriod?: (value: PRICE_PERIOD, setValue: (arr: [string, AnyType][]) => void) => void;
163
+ canChangeWholePricePeriod?: boolean;
164
+ };
165
+
166
+ export type FormControl =
167
+ | CarouselControl
168
+ | SelectSingleControl
169
+ | SelectMultipleControl
170
+ | SegmentedControl
171
+ | ToggleControl
172
+ | StepperControl
173
+ | ObjectControl
174
+ | ArrayControl
175
+ | ToggleObjectControl
176
+ | AlertControl
177
+ | ToggleCardsControl
178
+ | SliderControl
179
+ | TableControl;
180
+
181
+ export type FormConfig = Omit<ObjectControl, 'type'>;
@@ -0,0 +1,49 @@
1
+ import { FormValues } from '../../types';
2
+ import { setValue } from '../../utils';
3
+ import { CONTROL } from './constants';
4
+ import { FormControl } from './types';
5
+
6
+ export function getDefaultValues(controls: Record<string, FormControl>): FormValues {
7
+ const defaultValue: FormValues = {};
8
+
9
+ function internalGetDefaultValues(controls: Record<string, FormControl>) {
10
+ Object.entries(controls).forEach(([key, control]) => {
11
+ if (control) {
12
+ switch (control.type) {
13
+ case CONTROL.Object: {
14
+ if (control.defaultValue !== undefined) {
15
+ setValue(defaultValue, key, JSON.parse(JSON.stringify(control.defaultValue)));
16
+ }
17
+
18
+ internalGetDefaultValues(control.controls);
19
+
20
+ break;
21
+ }
22
+
23
+ case CONTROL.ToggleObject: {
24
+ setValue(defaultValue, control.switchKey, false);
25
+ internalGetDefaultValues({ _: control.control });
26
+
27
+ break;
28
+ }
29
+
30
+ case CONTROL.Alert: {
31
+ break;
32
+ }
33
+
34
+ default: {
35
+ if (control.defaultValue !== undefined) {
36
+ const restedValue = JSON.parse(JSON.stringify(control.defaultValue));
37
+
38
+ setValue(defaultValue, control?.accessorKey ?? '', restedValue);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ });
44
+ }
45
+
46
+ internalGetDefaultValues(controls);
47
+
48
+ return defaultValue;
49
+ }
@@ -0,0 +1,33 @@
1
+ import cn from 'classnames';
2
+
3
+ import { Typography } from '@snack-uikit/typography';
4
+
5
+ import { useCalculatorContext } from '../../contexts';
6
+ import { CALCULATOR_TYPE } from '../../types';
7
+ import { parseKeyToDataTest } from '../../utils';
8
+ import styles from './styles.module.scss';
9
+
10
+ type DisclaimerProps = {
11
+ className?: string;
12
+ };
13
+
14
+ export function Disclaimer({ className }: DisclaimerProps) {
15
+ const { layoutType, calculatorType } = useCalculatorContext();
16
+ const dataTestAttribute = parseKeyToDataTest('disclaimer');
17
+
18
+ return (
19
+ <div
20
+ className={cn(styles.footer, className)}
21
+ data-mobile={layoutType === 'mobile' || undefined}
22
+ data-test-id={dataTestAttribute}
23
+ >
24
+ {calculatorType !== CALCULATOR_TYPE.Partners && (
25
+ <Typography family='sans' purpose='body' size={layoutType === 'mobile' ? 's' : 'm'} className={styles.text}>
26
+ Рассчитываемая Калькулятором стоимость является предварительной, основанной на внесенных пользователем данных,
27
+ и не может расцениваться как предложение заключить договор по определенной Калькулятором цене
28
+ (не&nbsp;является офертой).
29
+ </Typography>
30
+ )}
31
+ </div>
32
+ );
33
+ }
@@ -0,0 +1 @@
1
+ export * from './Disclaimer';
@@ -0,0 +1,14 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables';
2
+
3
+ .footer {
4
+ color: styles-theme-variables.$sys-neutral-text-light;
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: styles-theme-variables.$dimension-3m;
8
+ max-width: 800px;
9
+ text-align: justify;
10
+ }
11
+
12
+ .text {
13
+ text-align: left;
14
+ }