@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,162 @@
1
+ import cn from 'classnames';
2
+ import { ReactNode } from 'react';
3
+
4
+ import { FieldStepperProps } from '@snack-uikit/fields';
5
+ import { Scroll } from '@snack-uikit/scroll';
6
+ import { QuestionTooltip } from '@snack-uikit/tooltip';
7
+ import { Typography } from '@snack-uikit/typography';
8
+
9
+ import { useAdaptive } from '../../../hooks';
10
+ import { AnyType, FormValues, Price } from '../../../types';
11
+ import { formatNumber, getPrice, getValue, setValue } from '../../../utils';
12
+ import { CONTROL } from '../constants';
13
+ import { ObjectDecorator } from '../ObjectDecorator';
14
+ import { StepperControlUi } from '../StepperControl';
15
+ import { BaseDecoratorProps, TooltipPlacement } from '../types';
16
+ import { StepperWithAllowedValues } from './helperComponents';
17
+ import styles from './styles.module.scss';
18
+
19
+ type TableRow = {
20
+ label: string;
21
+ labelTooltip?: ReactNode;
22
+ labelTooltipPlacement?: TooltipPlacement;
23
+ accessorKey: string;
24
+ priceAccessorKey?: string;
25
+
26
+ allowedValues?: number[];
27
+
28
+ uiProps?: Pick<FieldStepperProps, 'step' | 'min' | 'max' | 'disabled' | 'postfix'>;
29
+ };
30
+
31
+ export type TableControl = {
32
+ type: typeof CONTROL.Table;
33
+ defaultValue?: FormValues;
34
+ accessorKey: string;
35
+
36
+ decoratorProps?: Pick<BaseDecoratorProps, 'label' | 'labelTooltip' | 'labelTooltipPlacement'>;
37
+ counter?: {
38
+ accessorKey: string;
39
+ label: string;
40
+ uiProps?: Pick<FieldStepperProps, 'step' | 'min' | 'max' | 'disabled' | 'postfix'>;
41
+ };
42
+
43
+ rows: TableRow[];
44
+
45
+ onChangeFn?: never;
46
+ relateFn?: never;
47
+ watchedControls?: never;
48
+ };
49
+
50
+ export type TableControlUiProps = {
51
+ value?: string;
52
+ onChange?(value?: string): void;
53
+ watchedValues?: FormValues;
54
+ priceList: Record<string, Price>;
55
+ } & TableControl;
56
+
57
+ export function TableControlUi({
58
+ rows,
59
+ counter,
60
+ decoratorProps,
61
+ value: valueProp,
62
+ onChange: onChangeProp,
63
+ priceList,
64
+ accessorKey,
65
+ }: TableControlUiProps) {
66
+ const { isMobile } = useAdaptive();
67
+
68
+ const onChange = (accessorKey: string) => (newValue: AnyType) => {
69
+ setValue(valueProp, accessorKey, newValue);
70
+ onChangeProp?.(valueProp);
71
+ };
72
+
73
+ return (
74
+ <div className={styles.wrapper}>
75
+ <div className={styles.headline} data-mobile={isMobile || undefined}>
76
+ <ObjectDecorator {...decoratorProps} />
77
+
78
+ {counter && (
79
+ <div className={styles.counter}>
80
+ <Typography.SansBodyS> {counter.label}</Typography.SansBodyS>
81
+ <StepperControlUi
82
+ value={getValue(valueProp, counter.accessorKey)}
83
+ onChange={onChange(counter.accessorKey)}
84
+ uiProps={{
85
+ min: 1,
86
+ size: 's',
87
+ showHint: false,
88
+ ...counter.uiProps,
89
+ }}
90
+ accessorKey={accessorKey}
91
+ type='stepper'
92
+ decoratorProps={{}}
93
+ />
94
+ </div>
95
+ )}
96
+ </div>
97
+
98
+ <div className={styles.table}>
99
+ <Scroll barHideStrategy='never'>
100
+ <div className={cn(styles.row, styles.header)}>
101
+ <div className={styles.cell}>Ресурс</div>
102
+ <div className={styles.cell}>Количество</div>
103
+ <div className={styles.cell}>Стоимость в месяц</div>
104
+ </div>
105
+
106
+ {rows.map(({ accessorKey, label, labelTooltip, labelTooltipPlacement, uiProps, allowedValues }) => (
107
+ <div className={styles.row} key={accessorKey}>
108
+ <div className={styles.cell}>
109
+ <span>
110
+ {label}&nbsp;
111
+ {labelTooltip && (
112
+ <span className={styles.tipWrapperInline}>
113
+ <QuestionTooltip
114
+ data-pointer
115
+ tip={labelTooltip}
116
+ placement={labelTooltipPlacement}
117
+ size='xs'
118
+ tabIndex={-1}
119
+ />
120
+ </span>
121
+ )}
122
+ </span>
123
+ </div>
124
+ <div className={styles.cell}>
125
+ {allowedValues ? (
126
+ <StepperWithAllowedValues
127
+ value={getValue(valueProp, accessorKey)}
128
+ onChange={onChange(accessorKey)}
129
+ allowedValues={allowedValues}
130
+ {...uiProps}
131
+ />
132
+ ) : (
133
+ <StepperControlUi
134
+ value={getValue(valueProp, accessorKey)}
135
+ onChange={onChange(accessorKey)}
136
+ uiProps={{
137
+ showHint: false,
138
+ min: 0,
139
+ size: 's',
140
+ ...uiProps,
141
+ }}
142
+ type='stepper'
143
+ decoratorProps={{}}
144
+ accessorKey={accessorKey}
145
+ />
146
+ )}
147
+ </div>
148
+ <div className={styles.cell}>
149
+ {formatNumber(
150
+ getPrice({
151
+ price: getValue(priceList, accessorKey),
152
+ pricePeriod: 'month',
153
+ }),
154
+ ) + ' ₽'}
155
+ </div>
156
+ </div>
157
+ ))}
158
+ </Scroll>
159
+ </div>
160
+ </div>
161
+ );
162
+ }
@@ -0,0 +1,50 @@
1
+ import { ReactNode, useState } from 'react';
2
+
3
+ import { MinusSVG, PlusSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { ButtonFunction } from '@snack-uikit/button';
5
+ import { InputPrivate } from '@snack-uikit/input-private';
6
+
7
+ import styles from './styles.module.scss';
8
+
9
+ type StepperWithAllowedValuesProps = {
10
+ value: number;
11
+ onChange(value: number): void;
12
+ allowedValues: number[];
13
+ postfix?: ReactNode;
14
+ };
15
+
16
+ export function StepperWithAllowedValues({ value, onChange, allowedValues, postfix }: StepperWithAllowedValuesProps) {
17
+ const [selectedIdx, setSelectedIdx] = useState<number>(allowedValues.findIndex(item => item === value));
18
+
19
+ return (
20
+ <div className={styles.input}>
21
+ <ButtonFunction
22
+ icon={<MinusSVG />}
23
+ onClick={() => {
24
+ const newIdx = Math.max(selectedIdx - 1, 0);
25
+ setSelectedIdx(newIdx);
26
+ onChange(allowedValues[newIdx]);
27
+ }}
28
+ />
29
+ <div className={styles.content}>
30
+ <div
31
+ style={{
32
+ width: `${allowedValues[selectedIdx].toString().length * 8}px`,
33
+ }}
34
+ >
35
+ <InputPrivate readonly value={String(allowedValues[selectedIdx])} />
36
+ </div>
37
+ {postfix && <div className={styles.postfix}>{postfix}</div>}
38
+ </div>
39
+
40
+ <ButtonFunction
41
+ icon={<PlusSVG />}
42
+ onClick={() => {
43
+ const newIdx = Math.min(selectedIdx + 1, allowedValues.length - 1);
44
+ setSelectedIdx(newIdx);
45
+ onChange(allowedValues[newIdx]);
46
+ }}
47
+ />
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1 @@
1
+ export * from './StepperWithAllowedValues';
@@ -0,0 +1,53 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as ft;
2
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-fields' as ft-fields;
3
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-element' as ft-element;
4
+
5
+ .input {
6
+ @include ft.composite-var(ft-fields.$fields-single-line-container-s);
7
+
8
+ display: grid;
9
+ grid-template-columns: auto 1fr auto;
10
+ align-items: center;
11
+ width: 100%;
12
+ box-sizing: border-box;
13
+
14
+ border-style: solid;
15
+ border-color: ft.$sys-neutral-decor-default;
16
+ padding: 0 2px;
17
+ gap: 0;
18
+
19
+ &:hover {
20
+ background-color: ft.$sys-neutral-background2-level;
21
+ }
22
+
23
+ &:focus-within {
24
+ @include ft.outline-var(ft-element.$container-focused-m);
25
+
26
+ background-color: ft.$sys-neutral-background2-level;
27
+ border-color: ft.$sys-primary-accent-default;
28
+ outline-color: ft.$sys-primary-decor-activated;
29
+ }
30
+
31
+ .content {
32
+ @include ft.composite-var(ft.$sans-body-s);
33
+
34
+ width: 100%;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ gap: ft.$dimension-050m;
39
+
40
+ input:read-only {
41
+ @include ft.composite-var(ft.$sans-body-s);
42
+
43
+ /* stylelint-disable-next-line declaration-no-important */
44
+ color: ft.$sys-neutral-text-main !important;
45
+
46
+ cursor: default;
47
+ }
48
+ }
49
+
50
+ .postfix {
51
+ color: ft.$sys-neutral-text-support;
52
+ }
53
+ }
@@ -0,0 +1 @@
1
+ export * from './TableControl';
@@ -0,0 +1,104 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-table' as ft-table;
2
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as ft;
3
+
4
+ .tipWrapper {
5
+ display: inline-flex;
6
+ height: 16px;
7
+ align-items: center;
8
+ }
9
+
10
+ .tipWrapperInline {
11
+ display: inline-flex;
12
+ height: 16px;
13
+ > span {
14
+ transform: translate(0, 3px);
15
+ }
16
+ }
17
+
18
+ $border: solid ft-table.$border-width-table ft.$sys-neutral-decor-default;
19
+
20
+ .table {
21
+ @include ft.composite-var(ft.$sans-body-m);
22
+
23
+ border-radius: ft-table.$radius-table-container;
24
+
25
+ border: $border;
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ .row {
30
+ @include ft-table.composite-var(ft-table.$table-line-container);
31
+
32
+ height: auto;
33
+ min-height: ft-table.$size-table-line-height;
34
+
35
+ display: grid;
36
+ grid-template-columns: 2fr minmax(186px, 1fr) minmax(160px, 1fr);
37
+ align-items: center;
38
+
39
+ box-sizing: border-box;
40
+
41
+ min-width: 500px;
42
+ }
43
+
44
+ .cell {
45
+ @include ft-table.composite-var(ft-table.$table-cells);
46
+
47
+ box-sizing: border-box;
48
+
49
+ display: flex;
50
+ height: 100%;
51
+ width: 100%;
52
+
53
+ align-items: center;
54
+
55
+ color: ft.$sys-neutral-text-main;
56
+
57
+ padding-top: 2px;
58
+ padding-bottom: 2px;
59
+
60
+ border-right: $border;
61
+ border-bottom: $border;
62
+ }
63
+
64
+ .cell:last-child {
65
+ border-right: none;
66
+ }
67
+
68
+ .row.header {
69
+ .cell {
70
+ color: ft.$sys-neutral-text-light;
71
+ }
72
+ }
73
+
74
+ .row:last-child {
75
+ .cell {
76
+ border-bottom: none;
77
+ }
78
+ }
79
+
80
+ .headline {
81
+ display: flex;
82
+ justify-content: space-between;
83
+ align-items: center;
84
+ gap: 8px;
85
+ flex-direction: row;
86
+
87
+ &[data-mobile] {
88
+ align-items: flex-start;
89
+ flex-direction: column;
90
+ }
91
+ }
92
+
93
+ .counter {
94
+ display: grid;
95
+ grid-template-columns: 1fr 120px;
96
+ gap: 24px;
97
+ align-items: center;
98
+ }
99
+
100
+ .wrapper {
101
+ display: flex;
102
+ flex-direction: column;
103
+ gap: 8px;
104
+ }
@@ -0,0 +1,46 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { Card } from '@snack-uikit/card';
4
+ import { useToggleGroup } from '@snack-uikit/toggles';
5
+ import { Tooltip } from '@snack-uikit/tooltip';
6
+
7
+ import styles from './styles.module.scss';
8
+
9
+ export type ToggleCardItem = {
10
+ value: string;
11
+
12
+ label?: string;
13
+ description?: ReactNode;
14
+
15
+ disabled?: boolean;
16
+ disabledReason?: ReactNode;
17
+
18
+ dataTestId?: string;
19
+ };
20
+
21
+ export function ToggleCard({ value, label, description, disabled, disabledReason, dataTestId }: ToggleCardItem) {
22
+ const { isChecked, handleClick } = useToggleGroup({ value });
23
+
24
+ return (
25
+ <Tooltip open={disabled && disabled ? undefined : false} tip={disabledReason}>
26
+ <Card
27
+ outline
28
+ checked={isChecked}
29
+ onClick={handleClick}
30
+ className={styles.card}
31
+ disabled={disabled}
32
+ data-test-id={dataTestId}
33
+ size='s'
34
+ >
35
+ <Card.Header
36
+ title={label ?? value}
37
+ description={description as string}
38
+ truncate={{
39
+ title: 10,
40
+ description: 20,
41
+ }}
42
+ />
43
+ </Card>
44
+ </Tooltip>
45
+ );
46
+ }
@@ -0,0 +1 @@
1
+ export * from './ToggleCard';
@@ -0,0 +1,11 @@
1
+ .card {
2
+ min-height: 100%;
3
+
4
+ div {
5
+ min-height: 100%;
6
+ display: flex;
7
+ flex-direction: column;
8
+ flex: 1;
9
+ width: 100%;
10
+ }
11
+ }
@@ -0,0 +1,93 @@
1
+ import { useEffect, useMemo } from 'react';
2
+
3
+ import { CarouselProps } from '@snack-uikit/carousel';
4
+ import { FieldDecorator } from '@snack-uikit/fields';
5
+ import { ToggleGroup } from '@snack-uikit/toggles';
6
+
7
+ import { useAdaptive } from '../../../hooks';
8
+ import { FormValues } from '../../../types';
9
+ import { parseKeyToDataTest } from '../../../utils';
10
+ import { CarouselControlUi } from '../CarouselControl';
11
+ import { CONTROL } from '../constants';
12
+ import { ToggleCard, ToggleCardItem } from '../ToggleCard';
13
+ import { BaseControlWithItems } from '../types';
14
+ import styles from './styles.module.scss';
15
+
16
+ type UiProps = Pick<
17
+ CarouselProps,
18
+ 'transition' | 'scrollBy' | 'className' | 'swipe' | 'infiniteScroll' | 'arrows' | 'showItems' | 'pagination' | 'gap'
19
+ >;
20
+
21
+ export type ToggleCardsControl = {
22
+ type: typeof CONTROL.ToggleCards;
23
+ accessorKey?: string;
24
+ defaultValue?: string;
25
+ } & BaseControlWithItems<ToggleCardItem, UiProps>;
26
+
27
+ export type ToggleCardsControlUiProps = {
28
+ value?: string;
29
+ onChange?(value: string): void;
30
+ watchedValues?: FormValues;
31
+ } & ToggleCardsControl;
32
+
33
+ function ToggleCardsControlUiDesktop({
34
+ items: itemsProp,
35
+ uiProps,
36
+ value,
37
+ onChange,
38
+ decoratorProps,
39
+ relateFn,
40
+ watchedValues,
41
+ accessorKey,
42
+ }: ToggleCardsControlUiProps) {
43
+ const {
44
+ items: relatedItems,
45
+ decoratorProps: relatedDecoratorProps,
46
+ uiProps: relatedUiProps,
47
+ } = useMemo(() => relateFn?.(watchedValues ?? {}) ?? {}, [relateFn, watchedValues]);
48
+
49
+ const items = useMemo(() => relatedItems ?? itemsProp, [itemsProp, relatedItems]);
50
+
51
+ const dataTestAttribute = parseKeyToDataTest('toggle-cards', accessorKey);
52
+
53
+ useEffect(() => {
54
+ if (!items.find(item => String(item.value) === String(value))) {
55
+ onChange?.(String(items?.[0]?.value));
56
+ }
57
+ }, [value, onChange, items, relatedItems]);
58
+
59
+ const visible = relatedUiProps?.visible ?? uiProps?.visible ?? true;
60
+
61
+ if (!visible) {
62
+ return null;
63
+ }
64
+
65
+ return (
66
+ <div className={styles.carousel}>
67
+ <FieldDecorator size='m' {...decoratorProps} {...relatedDecoratorProps} data-test-id={dataTestAttribute}>
68
+ <ToggleGroup
69
+ selectionMode='single'
70
+ value={value}
71
+ onChange={value => {
72
+ value && onChange?.(value);
73
+ }}
74
+ >
75
+ <div className={styles.group}>
76
+ {items.map(item => (
77
+ <ToggleCard {...item} key={item.value} />
78
+ ))}
79
+ </div>
80
+ </ToggleGroup>
81
+ </FieldDecorator>
82
+ </div>
83
+ );
84
+ }
85
+ export function ToggleCardsControlUi(props: ToggleCardsControlUiProps) {
86
+ const { isMobile } = useAdaptive();
87
+
88
+ if (isMobile) {
89
+ return <CarouselControlUi {...props} type={CONTROL.Carousel} />;
90
+ }
91
+
92
+ return <ToggleCardsControlUiDesktop {...props} />;
93
+ }
@@ -0,0 +1 @@
1
+ export * from './ToggleCardsControl';
@@ -0,0 +1,40 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
+
3
+ .carousel {
4
+ position: relative;
5
+ display: flex;
6
+ flex-direction: column;
7
+
8
+ gap: stv.$dimension-1m;
9
+
10
+ .headline {
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+
15
+ .label {
16
+ @include stv.composite-var(stv.$sans-label-l);
17
+ color: stv.$sys-neutral-text-support;
18
+ .tip {
19
+ transform: translateY(stv.$dimension-050m);
20
+ margin-left: stv.$dimension-050m;
21
+ }
22
+ }
23
+ }
24
+
25
+ ul {
26
+ margin: 0;
27
+ padding: 0 0 0 stv.$dimension-2m;
28
+ list-style-type: disc;
29
+ }
30
+
31
+ li {
32
+ list-style-type: disc;
33
+ }
34
+ }
35
+
36
+ .group {
37
+ display: grid;
38
+ grid-template-columns: 1fr 1fr;
39
+ gap: stv.$dimension-2m;
40
+ }
@@ -0,0 +1,59 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { AnyType, FormValues, PRICE_PERIOD } from '../../../types';
4
+ import { parseKeyToDataTest } from '../../../utils';
5
+ import { CONTROL } from '../constants';
6
+ import { BaseControl } from '../types';
7
+ import { SwitchRow, SwitchRowProps } from './components';
8
+
9
+ type UiProps = Pick<SwitchRowProps, 'className' | 'disabled' | 'description'>;
10
+
11
+ export type ToggleControl = {
12
+ type: typeof CONTROL.Toggle;
13
+ defaultValue?: boolean;
14
+ } & BaseControl<UiProps>;
15
+
16
+ export type ToggleControlUiProps = ToggleControl & {
17
+ value?: boolean;
18
+ onChange?(value: boolean): void;
19
+ onChangePeriod?: (value: PRICE_PERIOD, setValue: (arr: [string, AnyType][]) => void) => void;
20
+ canChangeWholePricePeriod?: boolean;
21
+ watchedValues?: FormValues;
22
+ };
23
+
24
+ const noop = () => {};
25
+
26
+ export function ToggleControlUi({
27
+ decoratorProps,
28
+ uiProps,
29
+ value,
30
+ onChange,
31
+ watchedValues,
32
+ relateFn,
33
+ accessorKey,
34
+ }: ToggleControlUiProps) {
35
+ const { decoratorProps: relatedDecoratorProps, uiProps: relatedUiProps } = useMemo(
36
+ () => relateFn?.(watchedValues ?? {}) ?? {},
37
+ [relateFn, watchedValues],
38
+ );
39
+
40
+ const dataTestAttribute = parseKeyToDataTest('toggle', accessorKey);
41
+
42
+ const visible = relatedUiProps?.visible ?? uiProps?.visible ?? true;
43
+
44
+ if (!visible) {
45
+ return null;
46
+ }
47
+
48
+ return (
49
+ <SwitchRow
50
+ checked={value || false}
51
+ onChange={onChange ?? noop}
52
+ dataTestId={dataTestAttribute}
53
+ {...decoratorProps}
54
+ {...relatedDecoratorProps}
55
+ {...uiProps}
56
+ {...relatedUiProps}
57
+ />
58
+ );
59
+ }