@cloud-ru/uikit-product-utils 7.0.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 (52) hide show
  1. package/CHANGELOG.md +671 -0
  2. package/LICENSE +201 -0
  3. package/README.md +264 -0
  4. package/package.json +54 -0
  5. package/src/components/ConfigProvider/ConfigProvider.tsx +20 -0
  6. package/src/components/ConfigProvider/index.ts +1 -0
  7. package/src/components/ForThemeMode/ForThemeMode.tsx +14 -0
  8. package/src/components/ForThemeMode/hooks.ts +18 -0
  9. package/src/components/ForThemeMode/index.ts +2 -0
  10. package/src/components/index.ts +2 -0
  11. package/src/constants/adaptive.ts +45 -0
  12. package/src/constants/displayMode.ts +25 -0
  13. package/src/constants/environment.ts +16 -0
  14. package/src/helpers/tryParseJson.ts +12 -0
  15. package/src/hooks/index.ts +13 -0
  16. package/src/hooks/private/getCustomStore.ts +19 -0
  17. package/src/hooks/useAdaptive.tsx +8 -0
  18. package/src/hooks/useBrand.ts +31 -0
  19. package/src/hooks/useComponentSize.tsx +42 -0
  20. package/src/hooks/useConfig.ts +170 -0
  21. package/src/hooks/useDisplayMode.ts +10 -0
  22. package/src/hooks/useEventHandler.ts +21 -0
  23. package/src/hooks/useForceUpdate.ts +6 -0
  24. package/src/hooks/useForceUpdateOnPageLoadedCompletely.ts +13 -0
  25. package/src/hooks/useLanguage.ts +62 -0
  26. package/src/hooks/useMatchMedia.ts +52 -0
  27. package/src/hooks/useTextProvider.ts +14 -0
  28. package/src/hooks/useTheme.ts +31 -0
  29. package/src/hooks/useUniqueId.ts +7 -0
  30. package/src/index.ts +7 -0
  31. package/src/styles/default.ts +67 -0
  32. package/src/styles/index.ts +1 -0
  33. package/src/types/adaptive.ts +9 -0
  34. package/src/types/general.ts +10 -0
  35. package/src/types/index.ts +5 -0
  36. package/src/types/language.ts +227 -0
  37. package/src/types/theme.ts +19 -0
  38. package/src/types/withSupportProps.ts +6 -0
  39. package/src/utils/alert.ts +5 -0
  40. package/src/utils/createTextProvider.ts +18 -0
  41. package/src/utils/excludeSupportProps.ts +6 -0
  42. package/src/utils/extractSupportProps.ts +6 -0
  43. package/src/utils/getAdaptive.ts +23 -0
  44. package/src/utils/getDisplayMode.ts +34 -0
  45. package/src/utils/getMatchMedia.ts +38 -0
  46. package/src/utils/getUserAgentInfo.ts +36 -0
  47. package/src/utils/index.ts +10 -0
  48. package/src/utils/keyboardSelectHandler.ts +8 -0
  49. package/src/utils/private/constants.ts +1 -0
  50. package/src/utils/private/excludeProps.ts +11 -0
  51. package/src/utils/private/extractProps.ts +7 -0
  52. package/src/utils/uniqueId.ts +18 -0
@@ -0,0 +1,227 @@
1
+ export enum LanguageCodeType {
2
+ arSA = 'ar-SA',
3
+ bgBG = 'bg-BG',
4
+ caES = 'ca-ES',
5
+ zhTW = 'zh-TW',
6
+ csCZ = 'cs-CZ',
7
+ daDK = 'da-DK',
8
+ deDE = 'de-DE',
9
+ elGR = 'el-GR',
10
+ enUS = 'en-US',
11
+ es = 'es',
12
+ fiFI = 'fi-FI',
13
+ frFR = 'fr-FR',
14
+ heIL = 'he-IL',
15
+ huHU = 'hu-HU',
16
+ isIS = 'is-IS',
17
+ itIT = 'it-IT',
18
+ jaJP = 'ja-JP',
19
+ koKR = 'ko-KR',
20
+ nlNL = 'nl-NL',
21
+ nbNO = 'nb-NO',
22
+ plPL = 'pl-PL',
23
+ ptBR = 'pt-BR',
24
+ rmCH = 'rm-CH',
25
+ roRO = 'ro-RO',
26
+ ruRU = 'ru-RU',
27
+ hrHR = 'hr-HR',
28
+ skSK = 'sk-SK',
29
+ sqAL = 'sq-AL',
30
+ svSE = 'sv-SE',
31
+ thTH = 'th-TH',
32
+ trTR = 'tr-TR',
33
+ urPK = 'ur-PK',
34
+ idID = 'id-ID',
35
+ ukUA = 'uk-UA',
36
+ beBY = 'be-BY',
37
+ slSI = 'sl-SI',
38
+ etEE = 'et-EE',
39
+ lvLV = 'lv-LV',
40
+ ltLT = 'lt-LT',
41
+ tgCyrlTJ = 'tg-Cyrl-TJ',
42
+ faIR = 'fa-IR',
43
+ viVN = 'vi-VN',
44
+ hyAM = 'hy-AM',
45
+ azLatnAZ = 'az-Latn-AZ',
46
+ euES = 'eu-ES',
47
+ hsbDE = 'hsb-DE',
48
+ mkMK = 'mk-MK',
49
+ tnZA = 'tn-ZA',
50
+ xhZA = 'xh-ZA',
51
+ zuZA = 'zu-ZA',
52
+ afZA = 'af-ZA',
53
+ kaGE = 'ka-GE',
54
+ foFO = 'fo-FO',
55
+ hiIN = 'hi-IN',
56
+ mtMT = 'mt-MT',
57
+ seNO = 'se-NO',
58
+ msMY = 'ms-MY',
59
+ kkKZ = 'kk-KZ',
60
+ kyKG = 'ky-KG',
61
+ swKE = 'sw-KE',
62
+ tkTM = 'tk-TM',
63
+ uzLatnUZ = 'uz-Latn-UZ',
64
+ ttRU = 'tt-RU',
65
+ bnIN = 'bn-IN',
66
+ paIN = 'pa-IN',
67
+ guIN = 'gu-IN',
68
+ orIN = 'or-IN',
69
+ taIN = 'ta-IN',
70
+ teIN = 'te-IN',
71
+ knIN = 'kn-IN',
72
+ mlIN = 'ml-IN',
73
+ asIN = 'as-IN',
74
+ mrIN = 'mr-IN',
75
+ saIN = 'sa-IN',
76
+ mnMN = 'mn-MN',
77
+ boCN = 'bo-CN',
78
+ cyGB = 'cy-GB',
79
+ kmKH = 'km-KH',
80
+ loLA = 'lo-LA',
81
+ chrCherUS = 'chr-Cher-US',
82
+ iuCansCA = 'iu-Cans-CA',
83
+ glES = 'gl-ES',
84
+ kokIN = 'kok-IN',
85
+ syrSY = 'syr-SY',
86
+ siLK = 'si-LK',
87
+ amET = 'am-ET',
88
+ neNP = 'ne-NP',
89
+ fyNL = 'fy-NL',
90
+ psAF = 'ps-AF',
91
+ filPH = 'fil-PH',
92
+ dvMV = 'dv-MV',
93
+ haLatnNG = 'ha-Latn-NG',
94
+ yoNG = 'yo-NG',
95
+ quzBO = 'quz-BO',
96
+ nsoZA = 'nso-ZA',
97
+ baRU = 'ba-RU',
98
+ lbLU = 'lb-LU',
99
+ klGL = 'kl-GL',
100
+ igNG = 'ig-NG',
101
+ tiET = 'ti-ET',
102
+ hawUS = 'haw-US',
103
+ iiCN = 'ii-CN',
104
+ arnCL = 'arn-CL',
105
+ mohCA = 'moh-CA',
106
+ brFR = 'br-FR',
107
+ ugCN = 'ug-CN',
108
+ miNZ = 'mi-NZ',
109
+ ocFR = 'oc-FR',
110
+ coFR = 'co-FR',
111
+ gswFR = 'gsw-FR',
112
+ sahRU = 'sah-RU',
113
+ qutGT = 'qut-GT',
114
+ rwRW = 'rw-RW',
115
+ woSN = 'wo-SN',
116
+ prsAF = 'prs-AF',
117
+ gdGB = 'gd-GB',
118
+ kuArabIQ = 'ku-Arab-IQ',
119
+ arIQ = 'ar-IQ',
120
+ caESvalencia = 'ca-ES-valencia',
121
+ zhCN = 'zh-CN',
122
+ deCH = 'de-CH',
123
+ enGB = 'en-GB',
124
+ esMX = 'es-MX',
125
+ frBE = 'fr-BE',
126
+ itCH = 'it-CH',
127
+ nlBE = 'nl-BE',
128
+ nnNO = 'nn-NO',
129
+ ptPT = 'pt-PT',
130
+ ruMO = 'ru-MO',
131
+ srLatnCS = 'sr-Latn-CS',
132
+ svFI = 'sv-FI',
133
+ azCyrlAZ = 'az-Cyrl-AZ',
134
+ dsbDE = 'dsb-DE',
135
+ tnBW = 'tn-BW',
136
+ seSE = 'se-SE',
137
+ gaIE = 'ga-IE',
138
+ msBN = 'ms-BN',
139
+ uzCyrlUZ = 'uz-Cyrl-UZ',
140
+ bnBD = 'bn-BD',
141
+ paArabPK = 'pa-Arab-PK',
142
+ taLK = 'ta-LK',
143
+ mnMongCN = 'mn-Mong-CN',
144
+ sdArabPK = 'sd-Arab-PK',
145
+ iuLatnCA = 'iu-Latn-CA',
146
+ tzmLatnDZ = 'tzm-Latn-DZ',
147
+ ffLatnSN = 'ff-Latn-SN',
148
+ quzEC = 'quz-EC',
149
+ tiER = 'ti-ER',
150
+ arEG = 'ar-EG',
151
+ zhHK = 'zh-HK',
152
+ deAT = 'de-AT',
153
+ enAU = 'en-AU',
154
+ esES = 'es-ES',
155
+ frCA = 'fr-CA',
156
+ srCyrlCS = 'sr-Cyrl-CS',
157
+ seFI = 'se-FI',
158
+ quzPE = 'quz-PE',
159
+ arLY = 'ar-LY',
160
+ zhSG = 'zh-SG',
161
+ deLU = 'de-LU',
162
+ enCA = 'en-CA',
163
+ esGT = 'es-GT',
164
+ frCH = 'fr-CH',
165
+ hrBA = 'hr-BA',
166
+ smjNO = 'smj-NO',
167
+ tzmTfngMA = 'tzm-Tfng-MA',
168
+ arDZ = 'ar-DZ',
169
+ zhMO = 'zh-MO',
170
+ deLI = 'de-LI',
171
+ enNZ = 'en-NZ',
172
+ esCR = 'es-CR',
173
+ frLU = 'fr-LU',
174
+ bsLatnBA = 'bs-Latn-BA',
175
+ smjSE = 'smj-SE',
176
+ arMA = 'ar-MA',
177
+ enIE = 'en-IE',
178
+ esPA = 'es-PA',
179
+ frMC = 'fr-MC',
180
+ srSPCyrl = 'sr-SP-Cyrl',
181
+ smaNO = 'sma-NO',
182
+ arTN = 'ar-TN',
183
+ enZA = 'en-ZA',
184
+ esDO = 'es-DO',
185
+ srCyrlBA = 'sr-Cyrl-BA',
186
+ smaSE = 'sma-SE',
187
+ arOM = 'ar-OM',
188
+ enJM = 'en-JM',
189
+ esVE = 'es-VE',
190
+ bsCyrlBA = 'bs-Cyrl-BA',
191
+ smsFI = 'sms-FI',
192
+ arYE = 'ar-YE',
193
+ en029 = 'en-029',
194
+ esCO = 'es-CO',
195
+ srLatnRS = 'sr-Latn-RS',
196
+ smnFI = 'smn-FI',
197
+ arSY = 'ar-SY',
198
+ enBZ = 'en-BZ',
199
+ esPE = 'es-PE',
200
+ srCyrlRS = 'sr-Cyrl-RS',
201
+ arJO = 'ar-JO',
202
+ enTT = 'en-TT',
203
+ esAR = 'es-AR',
204
+ srLatnME = 'sr-Latn-ME',
205
+ arLB = 'ar-LB',
206
+ enZW = 'en-ZW',
207
+ esEC = 'es-EC',
208
+ srCyrlME = 'sr-Cyrl-ME',
209
+ arKW = 'ar-KW',
210
+ enPH = 'en-PH',
211
+ esCL = 'es-CL',
212
+ arAE = 'ar-AE',
213
+ esUY = 'es-UY',
214
+ arBH = 'ar-BH',
215
+ esPY = 'es-PY',
216
+ arQA = 'ar-QA',
217
+ enIN = 'en-IN',
218
+ esBO = 'es-BO',
219
+ enMY = 'en-MY',
220
+ esSV = 'es-SV',
221
+ enSG = 'en-SG',
222
+ esHN = 'es-HN',
223
+ esNI = 'es-NI',
224
+ esPR = 'es-PR',
225
+ esUS = 'es-US',
226
+ cimode = 'cimode',
227
+ }
@@ -0,0 +1,19 @@
1
+ export enum Themes {
2
+ Purple = 'purple',
3
+ PurpleDark = 'purpleDark',
4
+ Green = 'green',
5
+ GreenDark = 'greenDark',
6
+ }
7
+
8
+ export enum Brand {
9
+ Cloud = 'Cloud',
10
+ CloudDark = 'CloudDark',
11
+ MLSpace = 'MLSpace',
12
+ MLSpaceDark = 'MLSpaceDark',
13
+ Site = 'Site',
14
+ SiteDark = 'SiteDark',
15
+ Admin = 'Admin',
16
+ AdminDark = 'AdminDark',
17
+ GigaId = 'GigaId',
18
+ GigaIdDark = 'GigaIdDark',
19
+ }
@@ -0,0 +1,6 @@
1
+ import { AriaAttributes } from 'react';
2
+
3
+ export type WithSupportProps<T> = {
4
+ 'data-test-id'?: string;
5
+ } & AriaAttributes &
6
+ T;
@@ -0,0 +1,5 @@
1
+ import { configureDevAlerts } from '@cloud-ru/ft-debug-mode';
2
+
3
+ const { error, warning } = configureDevAlerts({ scope: 'uikit-product', enabled: true });
4
+
5
+ export { error, warning };
@@ -0,0 +1,18 @@
1
+ import { LanguageCodeType } from '../types/language';
2
+
3
+ export function createTextProvider<T extends string = string, V = string>(
4
+ dictionary: Partial<Record<LanguageCodeType, Record<T, V>>>,
5
+ packageName: string,
6
+ ) {
7
+ return <R extends V>(language: LanguageCodeType, entity: T) => {
8
+ const langKey = language === LanguageCodeType.cimode ? LanguageCodeType.ruRU : language;
9
+ const value = dictionary?.[langKey]?.[entity] || '';
10
+
11
+ if (language === LanguageCodeType.cimode) {
12
+ const key = `uikit-${packageName}.${entity}`;
13
+ return (value instanceof Function ? () => key : key) as unknown as R;
14
+ }
15
+
16
+ return value as R;
17
+ };
18
+ }
@@ -0,0 +1,6 @@
1
+ import { DATA_AND_ARIA_REGEXP } from './private/constants';
2
+ import { excludeProps } from './private/excludeProps';
3
+
4
+ export function excludeSupportProps(props: Record<string, unknown>) {
5
+ return excludeProps(props, DATA_AND_ARIA_REGEXP);
6
+ }
@@ -0,0 +1,6 @@
1
+ import { DATA_AND_ARIA_REGEXP } from './private/constants';
2
+ import { extractProps } from './private/extractProps';
3
+
4
+ export function extractSupportProps(props: Record<string, unknown>) {
5
+ return extractProps(props, DATA_AND_ARIA_REGEXP);
6
+ }
@@ -0,0 +1,23 @@
1
+ import { AdaptiveQueriesTitle } from '../constants/adaptive';
2
+ import { LayoutType, MatchMediaGeneric } from '../types/adaptive';
3
+ import { getUserAgentInfo } from './getUserAgentInfo';
4
+
5
+ export function getAdaptive({ isMobile }: MatchMediaGeneric<AdaptiveQueriesTitle>) {
6
+ const { device } = getUserAgentInfo();
7
+
8
+ let layoutType: LayoutType;
9
+
10
+ switch (device.type) {
11
+ case 'mobile':
12
+ layoutType = 'mobile';
13
+ break;
14
+ case 'tablet':
15
+ layoutType = 'tablet';
16
+ break;
17
+ default:
18
+ layoutType = isMobile ? 'desktopSmall' : 'desktop';
19
+ break;
20
+ }
21
+
22
+ return { layoutType };
23
+ }
@@ -0,0 +1,34 @@
1
+ import { isBrowser } from '@snack-uikit/utils';
2
+
3
+ import { DISPLAY_MODE_QUERIES, DISPLAY_MODES } from '../constants/displayMode';
4
+ import { MatchMediaGeneric } from '../types';
5
+
6
+ export function getDisplayMode(matchMedia: MatchMediaGeneric<keyof typeof DISPLAY_MODE_QUERIES>) {
7
+ if (isBrowser()) {
8
+ if (document.referrer.startsWith('android-app://')) {
9
+ return 'twa';
10
+ }
11
+
12
+ if (matchMedia.isBrowser) {
13
+ return DISPLAY_MODES.Browser;
14
+ }
15
+
16
+ if (matchMedia.isPwa) {
17
+ return DISPLAY_MODES.Pwa;
18
+ }
19
+
20
+ if (matchMedia.isFullscreen) {
21
+ return DISPLAY_MODES.Fullscreen;
22
+ }
23
+
24
+ if (matchMedia.isMinimalUI) {
25
+ return DISPLAY_MODES.MinimalUI;
26
+ }
27
+
28
+ if (matchMedia.isWindowControlsOverlay) {
29
+ return DISPLAY_MODES.WindowControlsOverlay;
30
+ }
31
+ }
32
+
33
+ return 'unknown';
34
+ }
@@ -0,0 +1,38 @@
1
+ import { isBrowser } from '@snack-uikit/utils';
2
+
3
+ import { ADAPTIVE_QUERIES, INITIAL_ADAPTIVE_QUERIES_VALUE } from '../constants/adaptive';
4
+ import { DISPLAY_MODE_QUERIES, INITIAL_DISPLAY_MODE_QUERIES_VALUE } from '../constants/displayMode';
5
+ import { MatchMediaGeneric } from '../types';
6
+
7
+ function getMediaQueries<T extends string>({ queryValues }: { queryValues: Record<T, string> }) {
8
+ return Object.keys(queryValues).reduce(
9
+ (acc, key) => ({
10
+ ...acc,
11
+ [key]: isBrowser() ? globalThis.matchMedia(queryValues[key as T]) : undefined,
12
+ }),
13
+ {} as Record<T, MediaQueryList>,
14
+ );
15
+ }
16
+
17
+ export function getMediaQueryListGeneric<T extends string>({ queryValues }: { queryValues: Record<T, string> }) {
18
+ return Object.entries(getMediaQueries({ queryValues })) as Array<[T, MediaQueryList]>;
19
+ }
20
+
21
+ export function getMatchMediaGeneric<T extends string>({
22
+ queryValues,
23
+ initialValues,
24
+ }: {
25
+ queryValues: Record<T, string>;
26
+ initialValues: MatchMediaGeneric<T>;
27
+ }) {
28
+ return getMediaQueryListGeneric<T>({ queryValues }).reduce(
29
+ (acc, [key, q]) => ({ ...acc, [key]: q?.matches || false }),
30
+ initialValues,
31
+ );
32
+ }
33
+
34
+ export const getAdaptiveMatchMedia = () =>
35
+ getMatchMediaGeneric({ queryValues: ADAPTIVE_QUERIES, initialValues: INITIAL_ADAPTIVE_QUERIES_VALUE });
36
+
37
+ export const getDisplayModeMatchMedia = () =>
38
+ getMatchMediaGeneric({ queryValues: DISPLAY_MODE_QUERIES, initialValues: INITIAL_DISPLAY_MODE_QUERIES_VALUE });
@@ -0,0 +1,36 @@
1
+ import { UAParser } from 'ua-parser-js';
2
+
3
+ import { ValueOf } from '@snack-uikit/utils';
4
+
5
+ const DEVICE_TYPE = {
6
+ Console: 'console',
7
+ Mobile: 'mobile',
8
+ Tablet: 'tablet',
9
+ Smarttv: 'smarttv',
10
+ Wearable: 'wearable',
11
+ Embedded: 'embedded',
12
+ Desktop: 'desktop',
13
+ } as const;
14
+
15
+ const DEVICE_TYPES = Object.values(DEVICE_TYPE);
16
+
17
+ type DeviceType = ValueOf<typeof DEVICE_TYPE>;
18
+
19
+ const getDeviceType = (type: string | undefined): DeviceType =>
20
+ DEVICE_TYPES.find(value => value === type) || DEVICE_TYPE.Desktop;
21
+
22
+ export function getUserAgentInfo() {
23
+ const parser = new UAParser(globalThis.navigator.userAgent);
24
+ const device = parser.getDevice();
25
+ const browser = parser.getBrowser();
26
+ const os = parser.getOS();
27
+
28
+ return {
29
+ device: {
30
+ model: device.model,
31
+ type: getDeviceType(device.type),
32
+ },
33
+ os,
34
+ browser,
35
+ };
36
+ }
@@ -0,0 +1,10 @@
1
+ export * from './alert';
2
+ export * from './createTextProvider';
3
+ export * from './excludeSupportProps';
4
+ export * from './extractSupportProps';
5
+ export * from './getAdaptive';
6
+ export * from './getDisplayMode';
7
+ export * from './getMatchMedia';
8
+ export * from './getUserAgentInfo';
9
+ export * from './keyboardSelectHandler';
10
+ export * from './uniqueId';
@@ -0,0 +1,8 @@
1
+ import { KeyboardEvent } from 'react';
2
+
3
+ export function keyboardSelectHandler<T>(callback: (event?: KeyboardEvent<T>) => void) {
4
+ return (event: KeyboardEvent<T>) => {
5
+ if (!['Enter', 'Space'].includes(event.code)) return;
6
+ callback(event);
7
+ };
8
+ }
@@ -0,0 +1 @@
1
+ export const DATA_AND_ARIA_REGEXP = /^(data|aria)-/;
@@ -0,0 +1,11 @@
1
+ export function excludeProps(props: Record<string, unknown>, regexp: RegExp) {
2
+ return Object.keys(props)
3
+ .filter(prop => !prop.match(regexp))
4
+ .reduce(
5
+ (nextProps: Record<string, unknown>, prop) => ({
6
+ ...nextProps,
7
+ [prop]: props[prop],
8
+ }),
9
+ {},
10
+ );
11
+ }
@@ -0,0 +1,7 @@
1
+ export function extractProps(props: Record<string, unknown>, regex: RegExp) {
2
+ return Object.keys(props).reduce((nextProps: Record<string, unknown>, prop) => {
3
+ if (prop.match(regex)) nextProps[prop] = props[prop];
4
+
5
+ return nextProps;
6
+ }, {});
7
+ }
@@ -0,0 +1,18 @@
1
+ const KEY = Symbol.for('SBERCLOUD_UIKIT_PRODUCT_UTILS_UNIQUE_ID_KEY');
2
+ const DEFAULT_NAMESPACE = '__DEFAULT_NAMESPACE__';
3
+
4
+ declare global {
5
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
6
+ interface Window {
7
+ [KEY]: Record<string, number>;
8
+ }
9
+ }
10
+
11
+ export function uniqueId(namespace = DEFAULT_NAMESPACE) {
12
+ window[KEY] ??= {};
13
+ window[KEY][namespace] ??= 0;
14
+
15
+ const id = ++window[KEY][namespace];
16
+
17
+ return namespace === DEFAULT_NAMESPACE ? id.toString() : `${namespace}__${id}`;
18
+ }