@cloud-ru/uikit-product-claudia 1.6.2

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 (94) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +201 -0
  3. package/README.md +586 -0
  4. package/package.json +60 -0
  5. package/src/components/ButtonClaudia/ButtonClaudia.tsx +33 -0
  6. package/src/components/ButtonClaudia/constants.ts +29 -0
  7. package/src/components/ButtonClaudia/helperComponents/ButtonPrivate/ButtonPrivate.tsx +99 -0
  8. package/src/components/ButtonClaudia/helperComponents/ButtonPrivate/constants.ts +13 -0
  9. package/src/components/ButtonClaudia/helperComponents/ButtonPrivate/index.ts +1 -0
  10. package/src/components/ButtonClaudia/helperComponents/ButtonPrivate/styles.module.scss +46 -0
  11. package/src/components/ButtonClaudia/helperComponents/ButtonPrivate/utils.tsx +92 -0
  12. package/src/components/ButtonClaudia/helperComponents/index.ts +1 -0
  13. package/src/components/ButtonClaudia/index.ts +1 -0
  14. package/src/components/ButtonClaudia/styles.module.scss +141 -0
  15. package/src/components/ButtonClaudia/types.ts +63 -0
  16. package/src/components/ButtonClaudia/utils.ts +15 -0
  17. package/src/components/ButtonGiga/ButtonGigaFunction/ButtonGigaFunction.tsx +43 -0
  18. package/src/components/ButtonGiga/ButtonGigaFunction/index.ts +1 -0
  19. package/src/components/ButtonGiga/ButtonGigaFunction/styles.module.scss +179 -0
  20. package/src/components/ButtonGiga/ButtonGigaFunction/types.ts +43 -0
  21. package/src/components/ButtonGiga/ButtonGigaFunction/utils.ts +16 -0
  22. package/src/components/ButtonGiga/ButtonGigaMama/ButtonGigaMama.tsx +29 -0
  23. package/src/components/ButtonGiga/ButtonGigaMama/index.ts +1 -0
  24. package/src/components/ButtonGiga/ButtonGigaMama/styles.module.scss +180 -0
  25. package/src/components/ButtonGiga/ButtonGigaMama/utils.ts +15 -0
  26. package/src/components/ButtonGiga/ButtonGigaOutline/ButtonGigaOutline.tsx +43 -0
  27. package/src/components/ButtonGiga/ButtonGigaOutline/index.ts +1 -0
  28. package/src/components/ButtonGiga/ButtonGigaOutline/styles.module.scss +223 -0
  29. package/src/components/ButtonGiga/ButtonGigaOutline/types.ts +63 -0
  30. package/src/components/ButtonGiga/ButtonGigaOutline/utils.ts +16 -0
  31. package/src/components/ButtonGiga/constants.ts +29 -0
  32. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/ButtonPrivate.tsx +99 -0
  33. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/constants.ts +15 -0
  34. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/index.ts +1 -0
  35. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/styles.module.scss +46 -0
  36. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/types.ts +63 -0
  37. package/src/components/ButtonGiga/helperComponents/ButtonPrivate/utils.tsx +92 -0
  38. package/src/components/ButtonGiga/helperComponents/index.ts +1 -0
  39. package/src/components/ButtonGiga/index.ts +3 -0
  40. package/src/components/ButtonGiga/types.ts +43 -0
  41. package/src/components/ChatStatusAnnouncement/ChatStatusAnnouncement.tsx +109 -0
  42. package/src/components/ChatStatusAnnouncement/constants.ts +1 -0
  43. package/src/components/ChatStatusAnnouncement/helperComponents/AlertButton/AlertButton.tsx +24 -0
  44. package/src/components/ChatStatusAnnouncement/helperComponents/AlertButton/index.ts +1 -0
  45. package/src/components/ChatStatusAnnouncement/helperComponents/AlertButton/styles.module.scss +27 -0
  46. package/src/components/ChatStatusAnnouncement/helperComponents/TextContent/TextContent.tsx +18 -0
  47. package/src/components/ChatStatusAnnouncement/helperComponents/TextContent/index.ts +1 -0
  48. package/src/components/ChatStatusAnnouncement/index.ts +1 -0
  49. package/src/components/ChatStatusAnnouncement/styled.module.scss +65 -0
  50. package/src/components/ChatStatusAnnouncement/types.ts +17 -0
  51. package/src/components/ChatStatusAnnouncement/utils/index.ts +52 -0
  52. package/src/components/IconGiga/IconGiga.tsx +64 -0
  53. package/src/components/IconGiga/constants.ts +23 -0
  54. package/src/components/IconGiga/index.ts +1 -0
  55. package/src/components/RecommendPannel/RecommendPanel.tsx +131 -0
  56. package/src/components/RecommendPannel/helperComponents/Chip/Chip.tsx +47 -0
  57. package/src/components/RecommendPannel/helperComponents/Chip/index.ts +1 -0
  58. package/src/components/RecommendPannel/helperComponents/Chip/styles.module.scss +45 -0
  59. package/src/components/RecommendPannel/helperComponents/ClaudiaChip/ClaudiaChip.tsx +40 -0
  60. package/src/components/RecommendPannel/helperComponents/ClaudiaChip/index.ts +1 -0
  61. package/src/components/RecommendPannel/helperComponents/CloseChip/CloseChip.tsx +106 -0
  62. package/src/components/RecommendPannel/helperComponents/CloseChip/index.ts +1 -0
  63. package/src/components/RecommendPannel/helperComponents/CloseChip/styles.module.scss +73 -0
  64. package/src/components/RecommendPannel/helperComponents/DropdownChip/DropdownChip.tsx +112 -0
  65. package/src/components/RecommendPannel/helperComponents/DropdownChip/index.ts +1 -0
  66. package/src/components/RecommendPannel/helperComponents/DropdownChip/styles.module.scss +56 -0
  67. package/src/components/RecommendPannel/hooks/index.ts +15 -0
  68. package/src/components/RecommendPannel/index.ts +1 -0
  69. package/src/components/RecommendPannel/styles.module.scss +4 -0
  70. package/src/components/RecommendPannel/types.ts +21 -0
  71. package/src/components/RecommendPannel/utils/gitVisibleChipsCount.ts +57 -0
  72. package/src/components/SshField/SshField.tsx +222 -0
  73. package/src/components/SshField/components/MobileFieldAi/MobileFieldAi.tsx +71 -0
  74. package/src/components/SshField/components/MobileFieldAi/index.ts +1 -0
  75. package/src/components/SshField/components/MobileFieldAi/styles.module.scss +80 -0
  76. package/src/components/SshField/components/TextArea/TextArea.tsx +113 -0
  77. package/src/components/SshField/components/TextArea/index.ts +1 -0
  78. package/src/components/SshField/components/TextArea/styles.module.scss +35 -0
  79. package/src/components/SshField/helperComponents/DropZoneContent/DropZoneContent.tsx +15 -0
  80. package/src/components/SshField/helperComponents/DropZoneContent/index.ts +1 -0
  81. package/src/components/SshField/helperComponents/DropZoneContent/styles.module.scss +17 -0
  82. package/src/components/SshField/helperComponents/FieldSubmitButton/FieldSubmitButton.tsx +45 -0
  83. package/src/components/SshField/helperComponents/FieldSubmitButton/index.ts +1 -0
  84. package/src/components/SshField/helperComponents/TextAreaActionsFooter/TextAreaActionsFooter.tsx +18 -0
  85. package/src/components/SshField/helperComponents/TextAreaActionsFooter/index.ts +1 -0
  86. package/src/components/SshField/helperComponents/TextAreaActionsFooter/styles.module.scss +23 -0
  87. package/src/components/SshField/index.ts +1 -0
  88. package/src/components/SshField/styles.module.scss +54 -0
  89. package/src/components/SshField/utils/handleFileError.ts +41 -0
  90. package/src/components/SshField/utils/isTouchDevice.ts +5 -0
  91. package/src/components/SshField/utils/readFileContent.ts +23 -0
  92. package/src/components/SshField/utils/validateSSHKey.ts +84 -0
  93. package/src/components/index.ts +6 -0
  94. package/src/index.ts +1 -0
@@ -0,0 +1,54 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-fields' as ste;
2
+
3
+ .wrapper {
4
+ display: flex;
5
+ flex-direction: column;
6
+ }
7
+
8
+ .chatStatus {
9
+ transform: translate(0px, 10px);
10
+ border-radius: 4px;
11
+ }
12
+
13
+ .uploadTooltip {
14
+ display: flex;
15
+ }
16
+
17
+ .secured {
18
+ textarea {
19
+ -webkit-text-security: disc;
20
+ /* stylelint-disable-next-line property-no-unknown */
21
+ text-security: disc;
22
+ }
23
+ }
24
+
25
+ .dropZone {
26
+ height: 90px;
27
+ transform: translateZ(0);
28
+ }
29
+
30
+ .defaultText {
31
+ color: ste.$sys-neutral-text-main;
32
+ }
33
+
34
+ .disclaimerText {
35
+ color: ste.$sys-green-text-support;
36
+ }
37
+
38
+ .mobileSubmitButton {
39
+ /* stylelint-disable-next-line declaration-no-important */
40
+ position: relative !important;
41
+ /* stylelint-disable-next-line declaration-no-important */
42
+ flex-shrink: 0 !important;
43
+
44
+ &:after {
45
+ content: '';
46
+ display: flex;
47
+ width: 48px;
48
+ height: 48px;
49
+ position: absolute;
50
+ top: 50%;
51
+ left: 50%;
52
+ transform: translate(-50%, -50%);
53
+ }
54
+ }
@@ -0,0 +1,41 @@
1
+ export type FileErrorType =
2
+ | 'INVALID_EXTENSION'
3
+ | 'INVALID_MIME_TYPE'
4
+ | 'FILE_TOO_LARGE'
5
+ | 'INVALID_FILE_TYPE'
6
+ | 'READ_ERROR'
7
+ | 'INVALID_SSH_KEY'
8
+ | 'EMPTY_FILE'
9
+ | 'BINARY_DATA'
10
+ | 'UNKNOWN_ERROR';
11
+
12
+ export const getFileErrorType = (error: unknown): FileErrorType => {
13
+ if (error instanceof Error) {
14
+ const [errorType] = error.message.split(': ');
15
+
16
+ switch (errorType as FileErrorType) {
17
+ case 'INVALID_EXTENSION':
18
+ case 'INVALID_MIME_TYPE':
19
+ return 'INVALID_EXTENSION';
20
+ case 'FILE_TOO_LARGE':
21
+ return 'FILE_TOO_LARGE';
22
+ case 'INVALID_FILE_TYPE':
23
+ return 'INVALID_EXTENSION';
24
+ case 'READ_ERROR':
25
+ return 'READ_ERROR';
26
+ case 'INVALID_SSH_KEY':
27
+ // Проверяем специфичные типы ошибок SSH ключа
28
+ if (error.message.includes('пустой') || error.message.includes('empty')) {
29
+ return 'EMPTY_FILE';
30
+ }
31
+ if (error.message.includes('бинарные') || error.message.includes('binary')) {
32
+ return 'BINARY_DATA';
33
+ }
34
+ return 'INVALID_SSH_KEY';
35
+ default:
36
+ return 'UNKNOWN_ERROR';
37
+ }
38
+ }
39
+
40
+ return 'UNKNOWN_ERROR';
41
+ };
@@ -0,0 +1,5 @@
1
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
2
+
3
+ export function isTouchDevice(layoutType: LayoutType) {
4
+ return ['mobile', 'tablet'].includes(layoutType);
5
+ }
@@ -0,0 +1,23 @@
1
+ export const readFileContent = (file: File): Promise<string> =>
2
+ new Promise((resolve, reject) => {
3
+ const reader = new FileReader();
4
+
5
+ reader.onload = (e: ProgressEvent<FileReader>) => {
6
+ if (e.target?.result && typeof e.target.result === 'string') {
7
+ resolve(e.target.result);
8
+ } else {
9
+ reject(new Error('READ_ERROR: Не удалось прочитать содержимое файла'));
10
+ }
11
+ };
12
+
13
+ reader.onerror = () => {
14
+ reject(new Error('READ_ERROR: Не удалось прочитать файл'));
15
+ };
16
+
17
+ reader.onabort = () => {
18
+ reject(new Error('READ_ERROR: Чтение файла было прервано'));
19
+ };
20
+
21
+ // Читаем как текст
22
+ reader.readAsText(file);
23
+ });
@@ -0,0 +1,84 @@
1
+ export const validateSSHKeyContent = (content: string): void => {
2
+ const trimmedContent = content.trim();
3
+
4
+ // Проверка на пустой файл
5
+ if (trimmedContent.length === 0) {
6
+ throw new Error('INVALID_SSH_KEY: Файл пустой');
7
+ }
8
+
9
+ // Проверка на бинарный файл (простейшая проверка)
10
+ const binaryChars = content
11
+ .split('')
12
+ .filter(char => char.charCodeAt(0) < 32 && char !== '\n' && char !== '\r' && char !== '\t').length;
13
+
14
+ if (binaryChars > content.length * 0.1) {
15
+ // Если больше 10% бинарных символов
16
+ throw new Error('INVALID_SSH_KEY: Файл содержит бинарные данные, а не текстовый SSH ключ');
17
+ }
18
+
19
+ // Базовая проверка на формат SSH ключа
20
+ const sshKeyPatterns = [
21
+ /^-----BEGIN (?:RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/,
22
+ /^ssh-(rsa|dsa|ecdsa|ed25519)/,
23
+ /^ecdsa-sha2-nistp/,
24
+ /^-----BEGIN.*PRIVATE KEY-----/,
25
+ /^-----BEGIN.*CERTIFICATE-----/,
26
+ ];
27
+
28
+ const isValidSSHKey = sshKeyPatterns.some(pattern => pattern.test(trimmedContent));
29
+
30
+ if (!isValidSSHKey) {
31
+ throw new Error(
32
+ 'INVALID_SSH_KEY: Файл не содержит валидный SSH ключ. Поддерживаются: RSA, DSA, ECDSA, Ed25519 ключи и сертификаты',
33
+ );
34
+ }
35
+ };
36
+
37
+ const DEFAULT_ALLOWED_MIME_TYPES = ['text/plain'];
38
+ const MAX_FILE_SIZE = 10 * 1024; // 10KB по умолчанию
39
+
40
+ const getFileExtension = (filename: string): string => {
41
+ const lastDotIndex = filename.lastIndexOf('.');
42
+
43
+ // Если точка не найдена или это первая точка в имени файла (скрытые файлы в Unix)
44
+ if (lastDotIndex <= 0) {
45
+ return '';
46
+ }
47
+
48
+ return filename.toLowerCase().slice(lastDotIndex);
49
+ };
50
+
51
+ const getFileMimeType = (file: File): string => file.type;
52
+
53
+ export const validateFileType = (file: File): void => {
54
+ const fileExtension = getFileExtension(file.name);
55
+ const mimeType = getFileMimeType(file);
56
+
57
+ // Проверка по MIME type (более надежный способ)
58
+ const isValidMimeType = DEFAULT_ALLOWED_MIME_TYPES.some(
59
+ allowedMime => mimeType.includes(allowedMime) || allowedMime.includes(mimeType),
60
+ );
61
+
62
+ // Файл должен пройти хотя бы одну проверку
63
+ if (!isValidMimeType) {
64
+ throw new Error(
65
+ `INVALID_MIME_TYPE: Неподходящий тип файла. MIME: ${mimeType}, расширение: ${fileExtension || 'нет'}. ` +
66
+ `Разрешенные MIME types: ${DEFAULT_ALLOWED_MIME_TYPES.join(', ')}, `,
67
+ );
68
+ }
69
+ };
70
+
71
+ export const validateFileSize = (file: File): void => {
72
+ if (file.size > MAX_FILE_SIZE) {
73
+ throw new Error(
74
+ `FILE_TOO_LARGE: Файл слишком большой. Размер: ${(file.size / 1024).toFixed(2)}KB, ` +
75
+ `максимальный: ${MAX_FILE_SIZE / 1024}KB`,
76
+ );
77
+ }
78
+
79
+ // Минимальный размер для SSH ключа (примерно 100 байт)
80
+ const minFileSize = 100;
81
+ if (file.size < minFileSize) {
82
+ throw new Error(`INVALID_FILE_TYPE: Файл слишком маленький для SSH ключа. Минимальный размер: ${minFileSize} байт`);
83
+ }
84
+ };
@@ -0,0 +1,6 @@
1
+ export * from './ButtonClaudia';
2
+ export * from './ButtonGiga';
3
+ export * from './ChatStatusAnnouncement';
4
+ export * from './IconGiga';
5
+ export * from './RecommendPannel';
6
+ export * from './SshField';
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './components';