@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,45 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
+
3
+ .text {
4
+ color: stv.$sys-neutral-text-support;
5
+ }
6
+
7
+ .chip {
8
+ height: 32px;
9
+ border-radius: 4px;
10
+ padding: 8px;
11
+ box-sizing: border-box;
12
+ cursor: pointer;
13
+ max-width: 250px;
14
+ width: fit-content;
15
+
16
+ &[data-mobile] {
17
+ height: 40px;
18
+ }
19
+
20
+ &:hover {
21
+ border: 1px solid stv.$sys-neutral-decor-hovered;
22
+ }
23
+
24
+ &:hover .text {
25
+ color: stv.$sys-neutral-text-main;
26
+ }
27
+
28
+ &:focus {
29
+ border: 1px solid stv.$sys-neutral-decor-hovered;
30
+ }
31
+
32
+ &:active {
33
+ border: 1px solid stv.$sys-neutral-decor-activated;
34
+ }
35
+ }
36
+
37
+ .chipDefault {
38
+ border: 1px solid stv.$sys-neutral-background;
39
+ background-color: stv.$sys-neutral-background;
40
+ }
41
+
42
+ .chipOutline {
43
+ border: 1px solid stv.$sys-neutral-decor-default;
44
+ background-color: transparent;
45
+ }
@@ -0,0 +1,40 @@
1
+ import { forwardRef, MouseEventHandler, ReactNode, RefObject } from 'react';
2
+
3
+ import { AgentClaudiaSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { LAYOUT_TYPE, LayoutType } from '@cloud-ru/uikit-product-utils';
5
+ import { Tooltip } from '@snack-uikit/tooltip';
6
+
7
+ import { ButtonClaudia } from '../../../ButtonClaudia';
8
+ import { SIZE, Size } from '../../types';
9
+
10
+ type ClaudiaChipProps = {
11
+ onClick?: MouseEventHandler<HTMLElement>;
12
+ size: Size;
13
+ tooltip?: ReactNode;
14
+ layoutType?: LayoutType;
15
+ };
16
+
17
+ export const ClaudiaChip = forwardRef<HTMLElement | HTMLButtonElement, ClaudiaChipProps>(
18
+ ({ onClick, size, tooltip, layoutType }, ref) => {
19
+ const isMobile = layoutType === LAYOUT_TYPE.Mobile || size === SIZE.M;
20
+ const totalSize = isMobile ? SIZE.M : size;
21
+
22
+ if (!tooltip) {
23
+ return (
24
+ <ButtonClaudia
25
+ size={totalSize}
26
+ data-mobile={isMobile}
27
+ ref={ref as RefObject<HTMLButtonElement>}
28
+ onClick={onClick}
29
+ icon={<AgentClaudiaSVG size={24} />}
30
+ />
31
+ );
32
+ }
33
+
34
+ return (
35
+ <Tooltip triggerRef={ref as RefObject<HTMLElement>} tip={tooltip}>
36
+ <ButtonClaudia size={totalSize} data-mobile={isMobile} onClick={onClick} icon={<AgentClaudiaSVG size={24} />} />
37
+ </Tooltip>
38
+ );
39
+ },
40
+ );
@@ -0,0 +1 @@
1
+ export * from './ClaudiaChip';
@@ -0,0 +1,106 @@
1
+ import { ReactNode, useRef, useState } from 'react';
2
+
3
+ import { MoreInterfaceSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { MobileDropdown } from '@cloud-ru/uikit-product-mobile-dropdown';
5
+ import { LAYOUT_TYPE, LayoutType } from '@cloud-ru/uikit-product-utils';
6
+ import { Dropdown } from '@snack-uikit/dropdown';
7
+ import { Typography } from '@snack-uikit/typography';
8
+
9
+ import { useOutsideClick } from '../../hooks';
10
+ import { SIZE, Size } from '../../types';
11
+ import styles from './styles.module.scss';
12
+
13
+ type DropdownContentProps = {
14
+ content: ReactNode;
15
+ onClick: () => void;
16
+ closeDropdown: () => void;
17
+ isMobileChipSize: boolean;
18
+ };
19
+
20
+ function DropdownContent({ content, onClick, closeDropdown, isMobileChipSize }: DropdownContentProps) {
21
+ const onDropdownItemClick = () => {
22
+ closeDropdown();
23
+ onClick();
24
+ };
25
+
26
+ const TypographyComponent = isMobileChipSize ? Typography.SansBodyM : Typography.SansBodyS;
27
+
28
+ return (
29
+ <div className={styles.dropdown}>
30
+ <button className={styles.dropdownItem} data-mobile={isMobileChipSize || undefined} onClick={onDropdownItemClick}>
31
+ <TypographyComponent>{content}</TypographyComponent>
32
+ </button>
33
+ </div>
34
+ );
35
+ }
36
+
37
+ type CloseChipProps = {
38
+ content: ReactNode;
39
+ size: Size;
40
+ layoutType?: LayoutType;
41
+ onClick: () => void;
42
+ isVisible?: boolean;
43
+ };
44
+
45
+ export function CloseChip({ size, content, onClick, isVisible, layoutType }: CloseChipProps) {
46
+ const [isDropdownOpen, setDropdownOpen] = useState(false);
47
+ const ref = useRef<HTMLButtonElement>(null);
48
+ const isMobile = layoutType === LAYOUT_TYPE.Mobile;
49
+ const isMobileChipSize = isMobile || size === SIZE.M;
50
+
51
+ const openDropdown = () => setDropdownOpen(true);
52
+ const closeDropdown = () => setDropdownOpen(false);
53
+
54
+ useOutsideClick([ref], closeDropdown);
55
+
56
+ if (isMobile) {
57
+ return (
58
+ <MobileDropdown
59
+ open={isDropdownOpen}
60
+ content={
61
+ <DropdownContent
62
+ isMobileChipSize={isMobileChipSize}
63
+ closeDropdown={closeDropdown}
64
+ content={content}
65
+ onClick={onClick}
66
+ />
67
+ }
68
+ >
69
+ <button
70
+ data-hidden={!isVisible || undefined}
71
+ data-mobile={true}
72
+ className={styles.closeChip}
73
+ ref={ref}
74
+ onClick={openDropdown}
75
+ >
76
+ <MoreInterfaceSVG size={24} />
77
+ </button>
78
+ </MobileDropdown>
79
+ );
80
+ }
81
+
82
+ return (
83
+ <Dropdown
84
+ open={isDropdownOpen}
85
+ triggerRef={ref}
86
+ placement='bottom-end'
87
+ content={
88
+ <DropdownContent
89
+ isMobileChipSize={isMobileChipSize}
90
+ closeDropdown={closeDropdown}
91
+ content={content}
92
+ onClick={onClick}
93
+ />
94
+ }
95
+ >
96
+ <button
97
+ data-hidden={!isVisible || undefined}
98
+ data-mobile={isMobileChipSize || undefined}
99
+ className={styles.closeChip}
100
+ onClick={openDropdown}
101
+ >
102
+ <MoreInterfaceSVG size={24} />
103
+ </button>
104
+ </Dropdown>
105
+ );
106
+ }
@@ -0,0 +1 @@
1
+ export * from './CloseChip';
@@ -0,0 +1,73 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
+
3
+ .closeChip {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ width: 32px;
8
+ height: 32px;
9
+ transform: rotate(90deg);
10
+ cursor: pointer;
11
+ border: unset;
12
+ background-color: unset;
13
+
14
+ &[data-hidden] {
15
+ pointer-events: none;
16
+ opacity: 0;
17
+ }
18
+
19
+ &[data-mobile] {
20
+ width: 40px;
21
+ height: 40px;
22
+ }
23
+
24
+ & svg {
25
+ fill: stv.$sys-neutral-text-support;
26
+ }
27
+
28
+ &:hover svg {
29
+ fill: stv.$sys-neutral-text-main;
30
+ }
31
+ }
32
+
33
+ .dropdown {
34
+ display: flex;
35
+ flex-direction: column;
36
+ border-radius: 4px;
37
+ padding: 4px 0px;
38
+ box-sizing: border-box;
39
+ }
40
+
41
+ .dropdownItem {
42
+ width: 100%;
43
+ height: 32px;
44
+ display: flex;
45
+ justify-content: flex-start;
46
+ align-items: center;
47
+ cursor: pointer;
48
+ border: unset;
49
+ background-color: unset;
50
+ position: relative;
51
+ padding: 0px 8px;
52
+
53
+ &[data-mobile] {
54
+ padding: 0px 10px;
55
+ height: 40px;
56
+ }
57
+
58
+ &:before {
59
+ pointer-events: none;
60
+ content: '';
61
+ position: absolute;
62
+ top: 0;
63
+ left: 0;
64
+ width: 100%;
65
+ height: 100%;
66
+ background-color: transparent;
67
+ }
68
+
69
+ &:hover::before {
70
+ background-color: stv.$sys-neutral-accent-default;
71
+ opacity: 0.08;
72
+ }
73
+ }
@@ -0,0 +1,112 @@
1
+ import { useRef, useState } from 'react';
2
+
3
+ import { MobileDropdown } from '@cloud-ru/uikit-product-mobile-dropdown';
4
+ import { LAYOUT_TYPE, LayoutType } from '@cloud-ru/uikit-product-utils';
5
+ import { Dropdown } from '@snack-uikit/dropdown';
6
+ import { TruncateString } from '@snack-uikit/truncate-string';
7
+ import { Typography } from '@snack-uikit/typography';
8
+
9
+ import { useOutsideClick } from '../../hooks';
10
+ import { ChipProps, ChipType, SIZE, Size } from '../../types';
11
+ import { Chip } from '../Chip';
12
+ import styles from './styles.module.scss';
13
+
14
+ type DropdownContentProps = {
15
+ dropdownItems: ChipProps[];
16
+ closeDropdown: () => void;
17
+ isMobile: boolean;
18
+ size: Size;
19
+ };
20
+
21
+ function DropdownContent({ size, dropdownItems, closeDropdown, isMobile }: DropdownContentProps) {
22
+ const isMobileChipSize = isMobile || size === SIZE.M;
23
+
24
+ const TypographyComponent = isMobileChipSize ? Typography.SansBodyM : Typography.SansBodyS;
25
+
26
+ return (
27
+ <div className={styles.dropdown} data-mobile={isMobile || undefined}>
28
+ {dropdownItems.map(item => (
29
+ <button
30
+ key={item.id}
31
+ data-mobile={isMobileChipSize || undefined}
32
+ className={styles.dropdownItem}
33
+ onClick={() => {
34
+ closeDropdown();
35
+ item?.onClick?.();
36
+ }}
37
+ >
38
+ <TypographyComponent>
39
+ <TruncateString variant='end' placement='top' text={item.label} maxLines={1} />
40
+ </TypographyComponent>
41
+ </button>
42
+ ))}
43
+ </div>
44
+ );
45
+ }
46
+
47
+ type DropdownChip = {
48
+ label: string;
49
+ type: ChipType;
50
+ size: Size;
51
+ layoutType?: LayoutType;
52
+ dropdownItems: ChipProps[];
53
+ };
54
+
55
+ export function DropdownChip({ size, layoutType, type, label, dropdownItems }: DropdownChip) {
56
+ const [isDropdownOpen, setDropdownOpen] = useState(false);
57
+ const ref = useRef<HTMLButtonElement>(null);
58
+ const isMobile = layoutType === LAYOUT_TYPE.Mobile;
59
+
60
+ const openDropdown = () => setDropdownOpen(true);
61
+ const closeDropdown = () => setDropdownOpen(false);
62
+
63
+ useOutsideClick([ref], closeDropdown);
64
+
65
+ if (isMobile) {
66
+ return (
67
+ <MobileDropdown
68
+ open={isDropdownOpen}
69
+ content={
70
+ <DropdownContent
71
+ size={size}
72
+ isMobile={isMobile}
73
+ closeDropdown={closeDropdown}
74
+ dropdownItems={dropdownItems}
75
+ />
76
+ }
77
+ >
78
+ <Chip
79
+ ref={ref}
80
+ isVisible={true}
81
+ className={styles.dropdownChip}
82
+ type={type}
83
+ label={label}
84
+ size={size}
85
+ layoutType={layoutType}
86
+ onClick={openDropdown}
87
+ />
88
+ </MobileDropdown>
89
+ );
90
+ }
91
+
92
+ return (
93
+ <Dropdown
94
+ triggerRef={ref}
95
+ open={isDropdownOpen}
96
+ placement='bottom-end'
97
+ content={
98
+ <DropdownContent size={size} isMobile={isMobile} closeDropdown={closeDropdown} dropdownItems={dropdownItems} />
99
+ }
100
+ >
101
+ <Chip
102
+ isVisible={true}
103
+ className={styles.dropdownChip}
104
+ type={type}
105
+ label={label}
106
+ size={size}
107
+ layoutType={layoutType}
108
+ onClick={openDropdown}
109
+ />
110
+ </Dropdown>
111
+ );
112
+ }
@@ -0,0 +1 @@
1
+ export * from './DropdownChip';
@@ -0,0 +1,56 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
2
+
3
+ .dropdown {
4
+ width: 256px;
5
+ display: flex;
6
+ flex-direction: column;
7
+ border-radius: 4px;
8
+ padding: 4px 0px;
9
+ box-sizing: border-box;
10
+
11
+ &[data-mobile] {
12
+ width: 100%;
13
+ }
14
+ }
15
+
16
+ .dropdownChip {
17
+ min-width: 33px;
18
+
19
+ &[data-mobile] {
20
+ min-width: 40px;
21
+ }
22
+ }
23
+
24
+ .dropdownItem {
25
+ width: 100%;
26
+ height: 32px;
27
+ display: flex;
28
+ justify-content: flex-start;
29
+ align-items: center;
30
+ cursor: pointer;
31
+ border: unset;
32
+ background-color: unset;
33
+ padding: 4px 8px;
34
+ position: relative;
35
+
36
+ &[data-mobile] {
37
+ padding: 8px 10px;
38
+ height: 40px;
39
+ }
40
+
41
+ &:before {
42
+ pointer-events: none;
43
+ content: '';
44
+ position: absolute;
45
+ top: 0;
46
+ left: 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ background-color: transparent;
50
+ }
51
+
52
+ &:hover::before {
53
+ background-color: stv.$sys-neutral-accent-default;
54
+ opacity: 0.08;
55
+ }
56
+ }
@@ -0,0 +1,15 @@
1
+ import { RefObject, useEffect } from 'react';
2
+
3
+ export const useOutsideClick = (ref: RefObject<HTMLElement>[], handler: () => void) => {
4
+ useEffect(() => {
5
+ const handleClick = (event: MouseEvent) => {
6
+ ref.forEach(ref => {
7
+ if (ref.current && event.target instanceof Element && !ref.current.contains(event.target)) {
8
+ handler();
9
+ }
10
+ });
11
+ };
12
+ document.body.addEventListener('click', handleClick);
13
+ return () => document.body.removeEventListener('click', handleClick);
14
+ }, [ref, handler]);
15
+ };
@@ -0,0 +1 @@
1
+ export * from './RecommendPanel';
@@ -0,0 +1,4 @@
1
+ .container {
2
+ display: flex;
3
+ gap: 8px;
4
+ }
@@ -0,0 +1,21 @@
1
+ import { ValueOf } from '@snack-uikit/utils';
2
+
3
+ export const CHIP_TYPE = {
4
+ Default: 'default',
5
+ Outline: 'outline',
6
+ } as const;
7
+
8
+ export type ChipType = ValueOf<typeof CHIP_TYPE>;
9
+
10
+ export type ChipProps = {
11
+ id: string;
12
+ label: string;
13
+ onClick?: () => void;
14
+ };
15
+
16
+ export const SIZE = {
17
+ S: 's',
18
+ M: 'm',
19
+ } as const;
20
+
21
+ export type Size = ValueOf<typeof SIZE>;
@@ -0,0 +1,57 @@
1
+ import { ChipProps } from '../types';
2
+
3
+ const GAP = 8;
4
+
5
+ type GetVisibleChipsCountArgs = {
6
+ containerWidth: number;
7
+ chipWidths: number[];
8
+ chips: ChipProps[];
9
+ isSmall: boolean;
10
+ isCloseChipExist: boolean;
11
+ };
12
+
13
+ export const getVisibleChipsCount = ({
14
+ containerWidth,
15
+ chipWidths,
16
+ chips,
17
+ isSmall,
18
+ isCloseChipExist,
19
+ }: GetVisibleChipsCountArgs) => {
20
+ if (containerWidth === 0 || chipWidths.length === 0) {
21
+ return chips.length;
22
+ }
23
+
24
+ const baseIcon = (isSmall ? 40 : 32) + GAP;
25
+ const closeIconWidth = isCloseChipExist ? baseIcon - GAP : 0;
26
+
27
+ let availableWidth = Math.round(containerWidth) - baseIcon - closeIconWidth;
28
+ let visibleCount = 0;
29
+ let isCounterChipExist = false;
30
+ let isCounterChipWidthSubstracted = false;
31
+ const chipsWidthWithGap = chipWidths.map(chip => Math.round(chip + GAP));
32
+
33
+ for (let i = 0; i < chipsWidthWithGap.length; i++) {
34
+ const chipWidth = chipsWidthWithGap[i];
35
+
36
+ if (availableWidth >= chipWidth) {
37
+ if (isCounterChipExist && !isCounterChipWidthSubstracted) {
38
+ availableWidth -= baseIcon;
39
+ isCounterChipWidthSubstracted = true;
40
+ }
41
+
42
+ availableWidth -= chipWidth;
43
+ visibleCount++;
44
+
45
+ if (visibleCount === chipsWidthWithGap.length) {
46
+ isCounterChipExist = false;
47
+ isCounterChipWidthSubstracted = false;
48
+ } else {
49
+ isCounterChipExist = true;
50
+ }
51
+ } else {
52
+ break;
53
+ }
54
+ }
55
+
56
+ return Math.max(1, visibleCount);
57
+ };