@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,33 @@
1
+ import cn from 'classnames';
2
+ import { forwardRef } from 'react';
3
+
4
+ import { extractSupportProps, WithSupportProps } from '@cloud-ru/uikit-product-utils';
5
+
6
+ import { HTML_TYPE, SIZE, TARGET } from './constants';
7
+ import { ButtonPrivate } from './helperComponents';
8
+ import styles from './styles.module.scss';
9
+ import { CommonButtonProps } from './types';
10
+ import { extractCommonButtonProps } from './utils';
11
+
12
+ export type ButtonClaudiaProps = WithSupportProps<Omit<CommonButtonProps, 'appearance' | 'iconPosition'>>;
13
+
14
+ export const ButtonClaudia = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonClaudiaProps>(
15
+ (
16
+ { className, size = SIZE.S, target = TARGET.Blank, type = HTML_TYPE.Button, tabIndex, fullWidth = false, ...rest },
17
+ ref,
18
+ ) => (
19
+ <ButtonPrivate
20
+ {...extractSupportProps(rest)}
21
+ {...extractCommonButtonProps(rest)}
22
+ className={cn(styles.button, styles.specificityX2, className)}
23
+ iconClassName={styles.icon}
24
+ labelClassName={styles.label}
25
+ size={size}
26
+ fullWidth={fullWidth}
27
+ target={target}
28
+ type={type}
29
+ tabIndex={tabIndex}
30
+ ref={ref}
31
+ />
32
+ ),
33
+ );
@@ -0,0 +1,29 @@
1
+ export const APPEARANCE = {
2
+ Tertiary: 'tertiary',
3
+ Secondary: 'secondary',
4
+ } as const;
5
+
6
+ export const HTML_TYPE = {
7
+ Button: 'button',
8
+ Submit: 'submit',
9
+ Reset: 'reset',
10
+ } as const;
11
+
12
+ export const TARGET = {
13
+ Blank: '_blank',
14
+ Self: '_self',
15
+ Parent: '_parent',
16
+ Top: '_top',
17
+ } as const;
18
+
19
+ export const SIZE = {
20
+ Xs: 'xs',
21
+ S: 's',
22
+ M: 'm',
23
+ L: 'l',
24
+ } as const;
25
+
26
+ export const ICON_POSITION = {
27
+ Before: 'before',
28
+ After: 'after',
29
+ } as const;
@@ -0,0 +1,99 @@
1
+ import cn from 'classnames';
2
+ import { ForwardedRef, forwardRef, MouseEvent } from 'react';
3
+
4
+ import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
5
+
6
+ import { APPEARANCE, HTML_TYPE, ICON_POSITION, TARGET } from '../../constants';
7
+ import { CommonButtonProps } from '../../types';
8
+ import { APPEARANCE_TO_COLOR_MAP } from './constants';
9
+ import styles from './styles.module.scss';
10
+ import { getChildren, getVariant } from './utils';
11
+
12
+ export type ButtonPrivateProps = WithSupportProps<
13
+ CommonButtonProps & {
14
+ iconClassName: string;
15
+ labelClassName: string;
16
+ fullWidth?: boolean;
17
+ }
18
+ >;
19
+
20
+ export const ButtonPrivate = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonPrivateProps>(
21
+ (
22
+ {
23
+ className,
24
+ disabled,
25
+ href,
26
+ icon,
27
+ iconClassName,
28
+ iconPosition = ICON_POSITION.After,
29
+ label,
30
+ labelClassName,
31
+ loading,
32
+ onClick,
33
+ onKeyDown,
34
+ onFocus,
35
+ onBlur,
36
+ size,
37
+ target = TARGET.Blank,
38
+ type = HTML_TYPE.Button,
39
+ appearance = APPEARANCE.Tertiary,
40
+ tabIndex: tabIndexProp = 0,
41
+ fullWidth,
42
+ ...rest
43
+ },
44
+ ref,
45
+ ) => {
46
+ const variant = getVariant({ label, iconPosition, icon });
47
+ const children = getChildren({
48
+ icon,
49
+ iconClassName,
50
+ iconPosition,
51
+ label,
52
+ labelClassName,
53
+ loading,
54
+ });
55
+ const tabIndex = loading || disabled ? -1 : tabIndexProp;
56
+
57
+ const handleClick = (event: MouseEvent<HTMLElement>) => {
58
+ if (disabled || loading) {
59
+ event.preventDefault();
60
+ return;
61
+ }
62
+
63
+ if (onClick) {
64
+ onClick(event);
65
+ }
66
+ };
67
+
68
+ const buttonProps = {
69
+ ...extractSupportProps(rest),
70
+ className: cn(styles.button, className),
71
+ 'data-disabled': disabled || undefined,
72
+ 'aria-disabled': disabled || undefined,
73
+ 'data-loading': loading || undefined,
74
+ 'data-size': size,
75
+ 'data-full-width': fullWidth || undefined,
76
+ 'data-appearance': APPEARANCE_TO_COLOR_MAP[appearance],
77
+ 'data-variant': variant,
78
+ onClick: handleClick,
79
+ onKeyDown,
80
+ onFocus,
81
+ onBlur,
82
+ tabIndex,
83
+ };
84
+
85
+ if (href) {
86
+ return (
87
+ <a role='button' href={href} target={target} {...buttonProps} ref={ref as ForwardedRef<HTMLAnchorElement>}>
88
+ {children}
89
+ </a>
90
+ );
91
+ }
92
+
93
+ return (
94
+ <button {...buttonProps} type={type} ref={ref as ForwardedRef<HTMLButtonElement>}>
95
+ {children}
96
+ </button>
97
+ );
98
+ },
99
+ );
@@ -0,0 +1,13 @@
1
+ import { APPEARANCE } from '../../constants';
2
+
3
+ export enum Variant {
4
+ LabelOnly = 'label-only',
5
+ IconOnly = 'icon-only',
6
+ IconBefore = 'icon-before',
7
+ IconAfter = 'icon-after',
8
+ }
9
+
10
+ export const APPEARANCE_TO_COLOR_MAP = {
11
+ [APPEARANCE.Tertiary]: 'fluorescent-yellow',
12
+ [APPEARANCE.Secondary]: 'graphite',
13
+ };
@@ -0,0 +1 @@
1
+ export * from './ButtonPrivate';
@@ -0,0 +1,46 @@
1
+ @use '@sbercloud/figma-tokens-web/build/scss/components/styles-tokens-element';
2
+
3
+ .button {
4
+ cursor: pointer;
5
+
6
+ position: relative;
7
+
8
+ display: inline-flex;
9
+ flex-shrink: 0;
10
+ align-items: center;
11
+ justify-content: center;
12
+
13
+ box-sizing: border-box;
14
+ width: max-content;
15
+ min-width: max-content;
16
+ margin: 0;
17
+ padding: 0;
18
+
19
+ color: transparent;
20
+ text-decoration: none;
21
+ text-transform: none;
22
+
23
+ background-color: transparent;
24
+ border: 0 solid transparent;
25
+ outline: 0;
26
+ outline-offset: 0;
27
+
28
+ &[data-full-width] {
29
+ flex-grow: 1;
30
+ flex-shrink: 1;
31
+ width: 100%;
32
+ }
33
+
34
+ > * {
35
+ cursor: pointer;
36
+ }
37
+
38
+ &:disabled,
39
+ &[data-disabled],
40
+ &[data-loading] {
41
+ cursor: not-allowed;
42
+ > * {
43
+ cursor: not-allowed;
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,92 @@
1
+ import { Sun } from '@snack-uikit/loaders';
2
+
3
+ import { ICON_POSITION } from '../../constants';
4
+ import { ButtonPrivateProps } from './ButtonPrivate';
5
+ import { Variant } from './constants';
6
+
7
+ type GetVariantProps = Pick<ButtonPrivateProps, 'label' | 'icon' | 'iconPosition'>;
8
+
9
+ export function getVariant({ label, icon, iconPosition }: GetVariantProps) {
10
+ if (label && icon && iconPosition === ICON_POSITION.After) {
11
+ return Variant.IconAfter;
12
+ }
13
+
14
+ if (label && icon && iconPosition === ICON_POSITION.Before) {
15
+ return Variant.IconBefore;
16
+ }
17
+
18
+ if (label) {
19
+ return Variant.LabelOnly;
20
+ }
21
+
22
+ return Variant.IconOnly;
23
+ }
24
+
25
+ type GetWrappedIconProps = Pick<ButtonPrivateProps, 'icon' | 'iconClassName' | 'loading'>;
26
+
27
+ export function getWrappedIcon({ icon, iconClassName, loading }: GetWrappedIconProps) {
28
+ if (loading) {
29
+ return (
30
+ <span data-test-id={'loading-icon'} className={iconClassName}>
31
+ <Sun size='s' />
32
+ </span>
33
+ );
34
+ }
35
+
36
+ if (icon) {
37
+ return (
38
+ <span data-test-id={'icon'} className={iconClassName}>
39
+ {icon}
40
+ </span>
41
+ );
42
+ }
43
+
44
+ return undefined;
45
+ }
46
+
47
+ type GetWrappedLabelProps = Pick<ButtonPrivateProps, 'label' | 'labelClassName'>;
48
+
49
+ export function getWrappedLabel({ label, labelClassName }: GetWrappedLabelProps) {
50
+ return label ? (
51
+ <span data-test-id={'label'} className={labelClassName}>
52
+ {label}
53
+ </span>
54
+ ) : undefined;
55
+ }
56
+
57
+ type GetChildrenProps = Pick<
58
+ ButtonPrivateProps,
59
+ 'icon' | 'label' | 'iconPosition' | 'iconClassName' | 'labelClassName' | 'loading'
60
+ >;
61
+
62
+ export function getChildren({ icon, label, iconPosition, iconClassName, labelClassName, loading }: GetChildrenProps) {
63
+ const wrappedIcon = getWrappedIcon({
64
+ icon,
65
+ iconClassName,
66
+ loading,
67
+ });
68
+ const wrappedLabel = getWrappedLabel({
69
+ label,
70
+ labelClassName,
71
+ });
72
+
73
+ switch (iconPosition) {
74
+ case ICON_POSITION.Before: {
75
+ return (
76
+ <>
77
+ {wrappedIcon}
78
+ {wrappedLabel}
79
+ </>
80
+ );
81
+ }
82
+ case ICON_POSITION.After:
83
+ default: {
84
+ return (
85
+ <>
86
+ {wrappedLabel}
87
+ {wrappedIcon}
88
+ </>
89
+ );
90
+ }
91
+ }
92
+ }
@@ -0,0 +1 @@
1
+ export * from './ButtonPrivate';
@@ -0,0 +1 @@
1
+ export * from './ButtonClaudia';
@@ -0,0 +1,141 @@
1
+ @use '@sbercloud/figma-tokens-web/build/scss/components/styles-tokens-button-buttonFilled' as buttonFilled;
2
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as stv;
3
+ @use '@sbercloud/figma-tokens-web/build/scss/components/styles-tokens-element';
4
+
5
+ $sizes: 'xs', 's', 'm', 'l';
6
+ $variants: 'label-only', 'icon-only', 'icon-after';
7
+ $typography: (
8
+ 'xs': stv.$sans-label-s,
9
+ 's': stv.$sans-label-m,
10
+ 'm': stv.$sans-label-l,
11
+ 'l': stv.$sans-label-l,
12
+ );
13
+
14
+ @mixin icon-fill($color) {
15
+ .icon {
16
+ color: $color;
17
+ }
18
+ }
19
+
20
+ @mixin label-color($color) {
21
+ .label {
22
+ color: $color;
23
+ }
24
+ }
25
+
26
+ @mixin button-anatomy-styles($button-theme, $sizes, $variants, $typography, $hasLabel: true) {
27
+ @each $size in $sizes {
28
+ &[data-size='#{$size}'] {
29
+ @if $hasLabel == true {
30
+ .label {
31
+ @include styles-tokens-element.composite-var($typography, $size);
32
+ }
33
+ }
34
+
35
+ .icon {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+
40
+ width: styles-tokens-element.$icon-s;
41
+ height: styles-tokens-element.$icon-s;
42
+
43
+ svg {
44
+ max-width: styles-tokens-element.$icon-s;
45
+ max-height: styles-tokens-element.$icon-s;
46
+ }
47
+ }
48
+
49
+ @each $variant in $variants {
50
+ &[data-variant='#{$variant}'] {
51
+ @include styles-tokens-element.composite-var($button-theme, 'container', $size, $variant);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ @mixin loading-label-only($button-theme) {
59
+ &[data-loading][data-variant='label-only'] {
60
+ .icon {
61
+ position: absolute;
62
+ top: 50%;
63
+ left: 50%;
64
+ transform: translate(-50%, -50%);
65
+ }
66
+
67
+ .label {
68
+ @include styles-tokens-element.composite-var($button-theme, 'label', 'load-label-only');
69
+ }
70
+ }
71
+ }
72
+
73
+ @mixin button-common-state {
74
+ &:focus-visible {
75
+ @include styles-tokens-element.outline-var(styles-tokens-element.$container-focused-s);
76
+
77
+ outline-offset: styles-tokens-element.$spacing-state-focus-offset;
78
+ }
79
+ }
80
+
81
+ @mixin claudia-button-colors-styles {
82
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
83
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
84
+
85
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'accent-default');
86
+
87
+ @media (hover: hover) {
88
+ &:hover {
89
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
90
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
91
+
92
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'accent-hovered');
93
+ }
94
+ }
95
+
96
+ @media (hover: none) or (hover: hover) {
97
+ &:focus-visible {
98
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
99
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
100
+
101
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'accent-hovered');
102
+ }
103
+
104
+ &:active {
105
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
106
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
107
+
108
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'accent-pressed');
109
+ }
110
+
111
+ &[data-loading] {
112
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
113
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'on-accent'));
114
+
115
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'accent-pressed');
116
+ }
117
+
118
+ &:disabled,
119
+ &[data-disabled] {
120
+ @include label-color(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'text-light'));
121
+ @include icon-fill(stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'text-light'));
122
+
123
+ background-color: stv.simple-var(stv.$theme-variables, 'sys', 'claudia', 'decor-disabled');
124
+ }
125
+ }
126
+ }
127
+
128
+ @mixin claudia-button-common-state {
129
+ &:focus-visible {
130
+ @include button-common-state;
131
+
132
+ outline-color: stv.$sys-available-complementary !important; /* stylelint-disable-line declaration-no-important */
133
+ }
134
+ }
135
+
136
+ .button.specificityX2 {
137
+ @include button-anatomy-styles(buttonFilled.$button-filled, $sizes, $variants, $typography);
138
+ @include loading-label-only(buttonFilled.$button-filled);
139
+ @include claudia-button-colors-styles;
140
+ @include claudia-button-common-state;
141
+ }
@@ -0,0 +1,63 @@
1
+ import {
2
+ AnchorHTMLAttributes,
3
+ ButtonHTMLAttributes,
4
+ FocusEventHandler,
5
+ KeyboardEventHandler,
6
+ MouseEventHandler,
7
+ ReactElement,
8
+ } from 'react';
9
+
10
+ import { ValueOf } from '@snack-uikit/utils';
11
+
12
+ import { APPEARANCE, ICON_POSITION, SIZE } from './constants';
13
+
14
+ export type Appearance = ValueOf<typeof APPEARANCE>;
15
+
16
+ export type IconPosition = ValueOf<typeof ICON_POSITION>;
17
+
18
+ export type Size = ValueOf<typeof SIZE>;
19
+
20
+ export type BaseButtonProps = {
21
+ /** CSS-класс */
22
+ className?: string;
23
+ /** Флаг неактивности компонента */
24
+ disabled?: boolean;
25
+ /**
26
+ * Иконка
27
+ * @type ReactElement
28
+ */
29
+ icon?: ReactElement;
30
+ /** Позиция иконки */
31
+ iconPosition?: IconPosition;
32
+ /** Текст кнопки */
33
+ label?: string;
34
+ /** Флаг состояния загрузки */
35
+ loading?: boolean;
36
+ /** Колбек обработки клика */
37
+ onClick?: MouseEventHandler<HTMLElement>;
38
+ /** Колбек обработки нажатия клавиши */
39
+ onKeyDown?: KeyboardEventHandler<HTMLElement>;
40
+ /** Колбек обработки фокуса */
41
+ onFocus?: FocusEventHandler<HTMLAnchorElement | HTMLButtonElement>;
42
+ /** Колбек обработки блюра */
43
+ onBlur?: FocusEventHandler<HTMLAnchorElement | HTMLButtonElement>;
44
+ /** Размер */
45
+ size?: Size;
46
+ /** Внешний вид кнопки */
47
+ appearance?: Appearance;
48
+ /** HTML-аттрибут type */
49
+ type?: ButtonHTMLAttributes<HTMLButtonElement>['type'];
50
+ /** HTML-аттрибут tab-index */
51
+ tabIndex?: number;
52
+ /** Сделать кнопку во всю ширину */
53
+ fullWidth?: boolean;
54
+ };
55
+
56
+ export type AnchorButtonProps = {
57
+ /** Ссылка */
58
+ href?: string;
59
+ /** HTML-аттрибут target */
60
+ target?: AnchorHTMLAttributes<HTMLAnchorElement>['target'];
61
+ };
62
+
63
+ export type CommonButtonProps = AnchorButtonProps & BaseButtonProps;
@@ -0,0 +1,15 @@
1
+ import { CommonButtonProps } from './types';
2
+
3
+ export function extractCommonButtonProps({
4
+ disabled,
5
+ href,
6
+ icon,
7
+ label,
8
+ loading,
9
+ onClick,
10
+ onFocus,
11
+ onBlur,
12
+ onKeyDown,
13
+ }: CommonButtonProps) {
14
+ return { disabled, href, icon, label, loading, onClick, onKeyDown, onFocus, onBlur };
15
+ }
@@ -0,0 +1,43 @@
1
+ import cn from 'classnames';
2
+ import { forwardRef } from 'react';
3
+
4
+ import { extractSupportProps, WithSupportProps } from '@cloud-ru/uikit-product-utils';
5
+
6
+ import { HTML_TYPE, ICON_POSITION, SIZE, TARGET } from '../constants';
7
+ import { ButtonPrivate } from '../helperComponents';
8
+ import styles from './styles.module.scss';
9
+ import { CommonButtonProps } from './types';
10
+ import { extractCommonButtonProps } from './utils';
11
+
12
+ export type ButtonGigaFunctionProps = WithSupportProps<Omit<CommonButtonProps, 'appearance'>>;
13
+
14
+ export const ButtonGigaFunction = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonGigaFunctionProps>(
15
+ (
16
+ {
17
+ className,
18
+ size = SIZE.S,
19
+ target = TARGET.Blank,
20
+ type = HTML_TYPE.Button,
21
+ iconPosition = ICON_POSITION.Before,
22
+ tabIndex,
23
+ fullWidth = false,
24
+ ...rest
25
+ },
26
+ ref,
27
+ ) => (
28
+ <ButtonPrivate
29
+ {...extractSupportProps(rest)}
30
+ {...extractCommonButtonProps({ ...rest, iconPosition })}
31
+ className={cn(styles.button, styles.specificityX2, className)}
32
+ iconClassName={styles.icon}
33
+ labelClassName={styles.label}
34
+ iconPosition={iconPosition}
35
+ size={size}
36
+ fullWidth={fullWidth}
37
+ target={target}
38
+ type={type}
39
+ tabIndex={tabIndex}
40
+ ref={ref}
41
+ />
42
+ ),
43
+ );
@@ -0,0 +1 @@
1
+ export * from './ButtonGigaFunction';