@alfalab/core-components-switch 6.0.3 → 6.1.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.
package/modern/index.css CHANGED
@@ -12,10 +12,13 @@
12
12
  --gap-3xs: 2px;
13
13
  --gap-2xs: 4px;
14
14
  --gap-s: 12px;
15
+ --gap-2s: 14px;
15
16
  --gap-m: 16px;
16
17
  --gap-0: 0px;
17
18
  --gap-2: var(--gap-3xs);
18
19
  --gap-4: var(--gap-2xs);
20
+ --gap-6: 6px;
21
+ --gap-10: 10px;
19
22
  --gap-12: var(--gap-s);
20
23
  --gap-16: var(--gap-m);
21
24
  }
@@ -32,7 +35,7 @@
32
35
  --switch-error-color: var(--color-light-text-negative);
33
36
  --switch-icon-color: var(--color-static-neutral-0);
34
37
  }
35
- .switch__component_1ktzs {
38
+ .switch__component_afshm {
36
39
  display: inline-flex;
37
40
  align-items: flex-start;
38
41
  margin: var(--gap-0);
@@ -41,26 +44,27 @@
41
44
  cursor: pointer;
42
45
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
43
46
  }
44
- .switch__component_1ktzs input {
47
+ .switch__component_afshm input {
45
48
  opacity: 0;
46
49
  position: absolute;
47
50
  }
48
- .switch__start_1ktzs {
51
+ .switch__start_afshm {
49
52
  align-items: flex-start;
50
53
  }
51
- .switch__center_1ktzs {
54
+ .switch__center_afshm {
52
55
  align-items: center;
53
56
  }
54
- .switch__addons_1ktzs {
57
+ .switch__addons_afshm {
55
58
  margin-left: auto;
56
59
  padding-left: var(--gap-16);
57
60
  line-height: 24px;
58
61
  }
59
- .switch__block_1ktzs {
62
+ .switch__block_afshm {
60
63
  width: 100%;
61
64
  }
62
- .switch__switch_1ktzs {
65
+ .switch__switch_afshm {
63
66
  position: relative;
67
+ display: block;
64
68
  border-radius: var(--border-radius-16);
65
69
  width: 36px;
66
70
  height: 20px;
@@ -72,7 +76,12 @@
72
76
  border-color 0.2s ease;
73
77
  box-sizing: border-box;
74
78
  }
75
- .switch__switch_1ktzs:before {
79
+ .switch__switchSkeleton_afshm {
80
+ width: 36px;
81
+ height: 20px;
82
+ margin: var(--gap-2);
83
+ }
84
+ .switch__switch_afshm:before {
76
85
  content: '';
77
86
  position: absolute;
78
87
  top: var(--gap-0);
@@ -85,54 +94,65 @@
85
94
  box-sizing: border-box;
86
95
  transition: transform 0.2s ease;
87
96
  }
88
- .switch__content_1ktzs {
97
+ .switch__content_afshm {
89
98
  margin-left: var(--gap-12);
90
99
  flex-grow: 1;
91
100
  }
92
- .switch__label_1ktzs {
101
+ .switch__label_afshm {
93
102
  font-size: 16px;
94
103
  line-height: 24px;
95
104
  font-weight: 400;
96
105
  font-family: var(--font-family-system);
97
106
  display: block;
98
107
  }
99
- .switch__label_1ktzs:not(:only-child) {
100
- margin-bottom: var(--gap-4);
101
- }
102
- .switch__errorMessage_1ktzs {
108
+ .switch__labelWrap_afshm:not(:only-child) {
109
+ margin-bottom: var(--gap-4);
110
+ }
111
+ .switch__labelWrap_afshm.switch__loading_afshm {
112
+ height: var(--gap-12);
113
+ margin: var(--gap-6) 0;
114
+ }
115
+ .switch__labelWrap_afshm.switch__loading_afshm:not(:only-child) {
116
+ margin-bottom: var(--gap-2s);
117
+ }
118
+ .switch__errorMessage_afshm {
103
119
  font-size: 14px;
104
120
  line-height: 18px;
105
121
  font-weight: 400;
106
122
  font-family: var(--font-family-system);
107
123
  color: var(--switch-error-color);
108
124
  }
109
- .switch__hint_1ktzs {
125
+ .switch__hint_afshm {
110
126
  font-size: 14px;
111
127
  line-height: 18px;
112
128
  font-weight: 400;
113
129
  font-family: var(--font-family-system);
114
130
  display: block;
115
131
  }
116
- .switch__component_1ktzs.switch__reversed_1ktzs {
132
+ .switch__hintWrap_afshm.switch__loading_afshm {
133
+ height: var(--gap-10);
134
+ margin-bottom: var(--gap-4);
135
+ }
136
+ .switch__component_afshm.switch__reversed_afshm {
117
137
  flex-direction: row-reverse;
118
138
  }
119
- .switch__reversed_1ktzs .switch__content_1ktzs {
139
+ .switch__reversed_afshm .switch__content_afshm {
120
140
  margin-right: var(--gap-16);
121
141
  margin-left: var(--gap-0);
122
142
  }
123
- .switch__reversed_1ktzs .switch__addons_1ktzs {
143
+ .switch__reversed_afshm .switch__addons_afshm {
124
144
  margin-left: var(--gap-0);
125
145
  padding-left: var(--gap-0);
126
146
  margin-right: auto;
127
147
  padding-right: var(--gap-16);
128
148
  }
129
- .switch__checked_1ktzs .switch__switch_1ktzs:before {
149
+ .switch__checked_afshm .switch__switch_afshm:before {
130
150
  transform: translateX(16px);
131
151
  }
132
- .switch__disabled_1ktzs {
152
+ .switch__disabled_afshm {
133
153
  cursor: var(--disabled-cursor);
134
154
  }
135
- .switch__focused_1ktzs .switch__switch_1ktzs {
155
+ .switch__focused_afshm .switch__switch_afshm {
136
156
  outline: 2px solid var(--focus-color);
137
157
  outline-offset: 2px;
138
158
  }
@@ -1,6 +1,6 @@
1
1
  import './index.css';
2
2
 
3
- const styles = {"component":"switch__component_1ktzs","start":"switch__start_1ktzs","center":"switch__center_1ktzs","addons":"switch__addons_1ktzs","block":"switch__block_1ktzs","switch":"switch__switch_1ktzs","content":"switch__content_1ktzs","label":"switch__label_1ktzs","errorMessage":"switch__errorMessage_1ktzs","hint":"switch__hint_1ktzs","reversed":"switch__reversed_1ktzs","checked":"switch__checked_1ktzs","disabled":"switch__disabled_1ktzs","focused":"switch__focused_1ktzs"};
3
+ const styles = {"component":"switch__component_afshm","start":"switch__start_afshm","center":"switch__center_afshm","addons":"switch__addons_afshm","block":"switch__block_afshm","switch":"switch__switch_afshm","switchSkeleton":"switch__switchSkeleton_afshm","content":"switch__content_afshm","label":"switch__label_afshm","labelWrap":"switch__labelWrap_afshm","loading":"switch__loading_afshm","errorMessage":"switch__errorMessage_afshm","hint":"switch__hint_afshm","hintWrap":"switch__hintWrap_afshm","reversed":"switch__reversed_afshm","checked":"switch__checked_afshm","disabled":"switch__disabled_afshm","focused":"switch__focused_afshm"};
4
4
 
5
5
  export { styles as default };
6
6
  //# sourceMappingURL=index.module.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.module.css.js","sources":["src/index.module.css"],"sourcesContent":["@import '@alfalab/core-components-vars/src/index.css';\n@import './vars.css';\n\n.component {\n display: inline-flex;\n align-items: flex-start;\n margin: var(--gap-0);\n padding: var(--gap-0);\n border: 0;\n cursor: pointer;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n.component input {\n opacity: 0;\n position: absolute;\n}\n\n.start {\n align-items: flex-start;\n}\n\n.center {\n align-items: center;\n}\n\n.addons {\n margin-left: auto;\n padding-left: var(--gap-16);\n line-height: 24px;\n}\n\n.block {\n width: 100%;\n}\n\n.switch {\n position: relative;\n border-radius: var(--border-radius-16);\n width: 36px;\n height: 20px;\n margin: var(--gap-2);\n flex-shrink: 0;\n border: 2px solid var(--switch-border-color);\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease;\n box-sizing: border-box;\n}\n\n.switch:before {\n content: '';\n position: absolute;\n top: var(--gap-0);\n left: var(--gap-0);\n bottom: var(--gap-0);\n right: var(--gap-16);\n display: block;\n border-radius: var(--border-radius-circle);\n background-color: var(--switch-icon-color);\n box-sizing: border-box;\n transition: transform 0.2s ease;\n}\n\n.content {\n margin-left: var(--gap-12);\n flex-grow: 1;\n}\n\n.label {\n @mixin paragraph_primary_medium;\n display: block;\n}\n\n.label:not(:only-child) {\n margin-bottom: var(--gap-4);\n}\n\n.errorMessage {\n @mixin paragraph_component_secondary;\n color: var(--switch-error-color);\n}\n\n.hint {\n @mixin paragraph_component_secondary;\n display: block;\n}\n\n/* Reversed state */\n\n.component.reversed {\n flex-direction: row-reverse;\n}\n\n.reversed .content {\n margin-right: var(--gap-16);\n margin-left: var(--gap-0);\n}\n\n.reversed .addons {\n margin-left: var(--gap-0);\n padding-left: var(--gap-0);\n margin-right: auto;\n padding-right: var(--gap-16);\n}\n\n/* Checked state */\n\n.checked .switch:before {\n /* ширина компонента(36px + 2*2px) - отступы(2 * 2px) - размер кружка(20px) */\n transform: translateX(16px);\n}\n\n/* Disabled state */\n\n.disabled {\n cursor: var(--disabled-cursor);\n}\n\n/* Focused state */\n\n.focused .switch {\n @mixin focus-outline;\n}\n"],"names":[],"mappings":";;AAEgB,eAAe,CAAC,WAAW,CAAC,yBAAyB,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,SAAS,CAAC,uBAAuB,CAAC,OAAO,CAAC,qBAAqB,CAAC,cAAc,CAAC,4BAA4B,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,wBAAwB,CAAC,SAAS,CAAC,uBAAuB,CAAC,UAAU,CAAC,wBAAwB,CAAC,SAAS,CAAC,uBAAuB,CAAC;;;;"}
1
+ {"version":3,"file":"index.module.css.js","sources":["src/index.module.css"],"sourcesContent":["@import '@alfalab/core-components-vars/src/index.css';\n@import './vars.css';\n\n.component {\n display: inline-flex;\n align-items: flex-start;\n margin: var(--gap-0);\n padding: var(--gap-0);\n border: 0;\n cursor: pointer;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n.component input {\n opacity: 0;\n position: absolute;\n}\n\n.start {\n align-items: flex-start;\n}\n\n.center {\n align-items: center;\n}\n\n.addons {\n margin-left: auto;\n padding-left: var(--gap-16);\n line-height: 24px;\n}\n\n.block {\n width: 100%;\n}\n\n.switch {\n position: relative;\n display: block;\n border-radius: var(--border-radius-16);\n width: 36px;\n height: 20px;\n margin: var(--gap-2);\n flex-shrink: 0;\n border: 2px solid var(--switch-border-color);\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease;\n box-sizing: border-box;\n}\n\n.switchSkeleton {\n width: 36px;\n height: 20px;\n margin: var(--gap-2);\n}\n\n.switch:before {\n content: '';\n position: absolute;\n top: var(--gap-0);\n left: var(--gap-0);\n bottom: var(--gap-0);\n right: var(--gap-16);\n display: block;\n border-radius: var(--border-radius-circle);\n background-color: var(--switch-icon-color);\n box-sizing: border-box;\n transition: transform 0.2s ease;\n}\n\n.content {\n margin-left: var(--gap-12);\n flex-grow: 1;\n}\n\n.label {\n @mixin paragraph_primary_medium;\n display: block;\n}\n\n.labelWrap {\n &:not(:only-child) {\n margin-bottom: var(--gap-4);\n }\n\n &.loading {\n height: var(--gap-12);\n margin: var(--gap-6) 0;\n\n &:not(:only-child) {\n margin-bottom: var(--gap-2s);\n }\n }\n}\n\n.errorMessage {\n @mixin paragraph_component_secondary;\n color: var(--switch-error-color);\n}\n\n.hint {\n @mixin paragraph_component_secondary;\n display: block;\n}\n\n.hintWrap {\n &.loading {\n height: var(--gap-10);\n margin-bottom: var(--gap-4);\n }\n}\n\n/* Reversed state */\n\n.component.reversed {\n flex-direction: row-reverse;\n}\n\n.reversed .content {\n margin-right: var(--gap-16);\n margin-left: var(--gap-0);\n}\n\n.reversed .addons {\n margin-left: var(--gap-0);\n padding-left: var(--gap-0);\n margin-right: auto;\n padding-right: var(--gap-16);\n}\n\n/* Checked state */\n\n.checked .switch:before {\n /* ширина компонента(36px + 2*2px) - отступы(2 * 2px) - размер кружка(20px) */\n transform: translateX(16px);\n}\n\n/* Disabled state */\n\n.disabled {\n cursor: var(--disabled-cursor);\n}\n\n/* Focused state */\n\n.focused .switch {\n @mixin focus-outline;\n}\n"],"names":[],"mappings":";;AAEgB,eAAe,CAAC,WAAW,CAAC,yBAAyB,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,8BAA8B,CAAC,SAAS,CAAC,uBAAuB,CAAC,OAAO,CAAC,qBAAqB,CAAC,WAAW,CAAC,yBAAyB,CAAC,SAAS,CAAC,uBAAuB,CAAC,cAAc,CAAC,4BAA4B,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,wBAAwB,CAAC,UAAU,CAAC,wBAAwB,CAAC,SAAS,CAAC,uBAAuB,CAAC,UAAU,CAAC,wBAAwB,CAAC,SAAS,CAAC,uBAAuB,CAAC;;;;"}
@@ -20,36 +20,36 @@
20
20
  --switch-disabled-checked-bg-inverted-color: var(--switch-disabled-bg-inverted-color);
21
21
  --switch-icon-disabled-inverted-color: var(--color-light-neutral-translucent-500-inverted);
22
22
  }
23
- .switch__switch_17cag {
23
+ .switch__switch_11ccj {
24
24
  background-color: var(--switch-bg-inverted-color);
25
25
  }
26
- .switch__switch_17cag:hover {
26
+ .switch__switch_11ccj:hover {
27
27
  background-color: var(--switch-hover-bg-inverted-color);
28
28
  }
29
- .switch__label_17cag {
29
+ .switch__label_11ccj {
30
30
  color: var(--switch-label-inverted-color);
31
31
  }
32
- .switch__hint_17cag {
32
+ .switch__hint_11ccj {
33
33
  color: var(--switch-hint-inverted-color);
34
34
  }
35
- .switch__checked_17cag .switch__switch_17cag {
35
+ .switch__checked_11ccj .switch__switch_11ccj {
36
36
  background-color: var(--switch-checked-bg-inverted-color);
37
37
  }
38
- .switch__checked_17cag .switch__switch_17cag:hover {
38
+ .switch__checked_11ccj .switch__switch_11ccj:hover {
39
39
  background-color: var(--switch-checked-hover-bg-inverted-color);
40
40
  }
41
- .switch__disabled_17cag .switch__label_17cag {
41
+ .switch__disabled_11ccj .switch__label_11ccj {
42
42
  color: var(--switch-disabled-inverted-color);
43
43
  }
44
- .switch__disabled_17cag .switch__hint_17cag {
44
+ .switch__disabled_11ccj .switch__hint_11ccj {
45
45
  color: var(--switch-disabled-inverted-color);
46
46
  }
47
- .switch__disabled_17cag .switch__switch_17cag {
47
+ .switch__disabled_11ccj .switch__switch_11ccj {
48
48
  background-color: var(--switch-disabled-bg-inverted-color);
49
49
  }
50
- .switch__disabled_17cag .switch__switch_17cag:before {
50
+ .switch__disabled_11ccj .switch__switch_11ccj:before {
51
51
  background-color: var(--switch-icon-disabled-inverted-color);
52
52
  }
53
- .switch__disabled_17cag.switch__checked_17cag .switch__switch_17cag {
53
+ .switch__disabled_11ccj.switch__checked_11ccj .switch__switch_11ccj {
54
54
  background-color: var(--switch-disabled-checked-bg-inverted-color);
55
55
  }
@@ -1,6 +1,6 @@
1
1
  import './inverted.css';
2
2
 
3
- const invertedStyles = {"switch":"switch__switch_17cag","label":"switch__label_17cag","hint":"switch__hint_17cag","checked":"switch__checked_17cag","disabled":"switch__disabled_17cag"};
3
+ const invertedStyles = {"switch":"switch__switch_11ccj","label":"switch__label_11ccj","hint":"switch__hint_11ccj","checked":"switch__checked_11ccj","disabled":"switch__disabled_11ccj"};
4
4
 
5
5
  export { invertedStyles as default };
6
6
  //# sourceMappingURL=inverted.module.css.js.map
@@ -54,6 +54,11 @@ export type SwitchProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | '
54
54
  * @default default
55
55
  */
56
56
  colors?: Colors;
57
+ /**
58
+ * Показать скелетон
59
+ * @default false
60
+ */
61
+ showSkeleton?: boolean;
57
62
  };
58
63
  export declare const Switch: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "hint" | "onChange" | "disabled" | "enterKeyHint"> & {
59
64
  /**
@@ -108,5 +113,10 @@ export declare const Switch: React.ForwardRefExoticComponent<Omit<React.InputHTM
108
113
  * @default default
109
114
  */
110
115
  colors?: Colors;
116
+ /**
117
+ * Показать скелетон
118
+ * @default false
119
+ */
120
+ showSkeleton?: boolean;
111
121
  } & React.RefAttributes<HTMLLabelElement>>;
112
122
  export {};
@@ -2,6 +2,7 @@ import React, { forwardRef, useRef } from 'react';
2
2
  import mergeRefs from 'react-merge-refs';
3
3
  import cn from 'classnames';
4
4
  import { dom } from '@alfalab/core-components-shared/moderncssm';
5
+ import { Skeleton } from '@alfalab/core-components-skeleton/moderncssm';
5
6
  import { useFocus } from '@alfalab/hooks';
6
7
  import defaultStyles from './default.module.css';
7
8
  import styles from './index.module.css';
@@ -11,7 +12,7 @@ const colorStyles = {
11
12
  default: defaultStyles,
12
13
  inverted: invertedStyles,
13
14
  };
14
- const Switch = forwardRef(({ reversed = false, checked = false, align = 'start', addons, block, disabled, error, label, hint, name, value, className, onChange, dataTestId, colors = 'default', ...restProps }, ref) => {
15
+ const Switch = forwardRef(({ reversed = false, checked = false, align = 'start', addons, block, disabled, error, label, hint, name, value, className, onChange, dataTestId, colors = 'default', showSkeleton = false, ...restProps }, ref) => {
15
16
  const labelRef = useRef(null);
16
17
  const [focused] = useFocus(labelRef, 'keyboard');
17
18
  const handleChange = (e) => {
@@ -30,10 +31,19 @@ const Switch = forwardRef(({ reversed = false, checked = false, align = 'start',
30
31
  [styles.block]: block,
31
32
  }), ref: mergeRefs([labelRef, ref]) },
32
33
  React.createElement("input", { type: 'checkbox', onChange: handleChange, disabled: disabled, checked: checked, name: name, value: value, "data-test-id": dataTestId, ...restProps }),
33
- React.createElement("span", { className: cn(styles.switch, colorStyles[colors].switch) }),
34
+ React.createElement(Skeleton, { visible: showSkeleton, borderRadius: 'pill', colors: colors, className: cn({
35
+ [styles.switchSkeleton]: showSkeleton,
36
+ }) },
37
+ React.createElement("span", { className: cn(styles.switch, colorStyles[colors].switch) })),
34
38
  (label || hint || errorMessage) && (React.createElement("span", { className: styles.content },
35
- label && (React.createElement("span", { className: cn(styles.label, colorStyles[colors].label) }, label)),
36
- hint && !errorMessage && (React.createElement("span", { className: cn(styles.hint, colorStyles[colors].hint) }, hint)),
39
+ label && (React.createElement(Skeleton, { visible: showSkeleton, borderRadius: 'pill', colors: colors, className: cn(styles.labelWrap, {
40
+ [styles.loading]: showSkeleton,
41
+ }) },
42
+ React.createElement("span", { className: cn(styles.label, colorStyles[colors].label) }, label))),
43
+ hint && !errorMessage && (React.createElement(Skeleton, { visible: showSkeleton, borderRadius: 'pill', colors: colors, className: cn(styles.hintWrap, {
44
+ [styles.loading]: showSkeleton,
45
+ }) },
46
+ React.createElement("span", { className: cn(styles.hint, colorStyles[colors].hint) }, hint))),
37
47
  errorMessage && (React.createElement("span", { className: styles.errorMessage, role: 'alert' }, errorMessage)))),
38
48
  addons && (
39
49
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
@@ -1 +1 @@
1
- {"version":3,"file":"Component.js","sources":["../src/Component.tsx"],"sourcesContent":["import React, {\n type ChangeEvent,\n forwardRef,\n type InputHTMLAttributes,\n type ReactNode,\n useRef,\n} from 'react';\nimport mergeRefs from 'react-merge-refs';\nimport cn from 'classnames';\n\nimport { dom } from '@alfalab/core-components-shared';\nimport { useFocus } from '@alfalab/hooks';\n\nimport { type Colors } from './types/colors';\n\nimport defaultStyles from './default.module.css';\nimport styles from './index.module.css';\nimport invertedStyles from './inverted.module.css';\n\nconst colorStyles = {\n default: defaultStyles,\n inverted: invertedStyles,\n};\n\ntype Align = 'start' | 'center';\n\nexport type SwitchProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'hint' | 'onChange' | 'disabled' | 'enterKeyHint'\n> & {\n /**\n * Управление состоянием вкл/выкл компонента\n */\n checked?: boolean;\n\n /**\n * Текст подписи к переключателю\n */\n label?: ReactNode;\n\n /**\n * Текст подсказки снизу\n */\n hint?: ReactNode;\n\n /**\n * Переключатель будет отрисован справа от контента\n */\n reversed?: boolean;\n\n /**\n * Выравнивание\n */\n align?: Align;\n\n /**\n * Дополнительный слот\n */\n addons?: React.ReactNode;\n\n /**\n * Растягивать ли компонент на всю ширину\n */\n block?: boolean;\n\n /**\n * Управление состоянием включен / выключен\n */\n disabled?: boolean;\n\n /**\n * Отображение ошибки\n */\n error?: ReactNode | boolean;\n\n /**\n * Обработчик переключения компонента\n */\n onChange?: (\n event: ChangeEvent<HTMLInputElement>,\n payload: {\n checked: boolean;\n name: InputHTMLAttributes<HTMLInputElement>['name'];\n },\n ) => void;\n\n /**\n * Идентификатор для систем автоматизированного тестирования\n */\n dataTestId?: string;\n\n /**\n * Набор цветов для компонента\n * @default default\n */\n colors?: Colors;\n};\n\nexport const Switch = forwardRef<HTMLLabelElement, SwitchProps>(\n (\n {\n reversed = false,\n checked = false,\n align = 'start',\n addons,\n block,\n disabled,\n error,\n label,\n hint,\n name,\n value,\n className,\n onChange,\n dataTestId,\n colors = 'default',\n ...restProps\n },\n ref,\n ) => {\n const labelRef = useRef<HTMLLabelElement>(null);\n\n const [focused] = useFocus(labelRef, 'keyboard');\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (onChange) {\n onChange(e, { checked: e.target.checked, name });\n }\n };\n\n const errorMessage = typeof error === 'boolean' ? '' : error;\n\n return (\n <label\n className={cn(styles.component, styles[align], className, {\n [styles.disabled]: disabled,\n [colorStyles[colors].disabled]: disabled,\n\n [styles.checked]: checked,\n [colorStyles[colors].checked]: checked,\n\n [styles.reversed]: reversed,\n [styles.focused]: focused,\n [styles.block]: block,\n })}\n ref={mergeRefs([labelRef, ref])}\n >\n <input\n type='checkbox'\n onChange={handleChange}\n disabled={disabled}\n checked={checked}\n name={name}\n value={value}\n data-test-id={dataTestId}\n {...restProps}\n />\n\n <span className={cn(styles.switch, colorStyles[colors].switch)} />\n\n {(label || hint || errorMessage) && (\n <span className={styles.content}>\n {label && (\n <span className={cn(styles.label, colorStyles[colors].label)}>\n {label}\n </span>\n )}\n {hint && !errorMessage && (\n <span className={cn(styles.hint, colorStyles[colors].hint)}>\n {hint}\n </span>\n )}\n\n {errorMessage && (\n <span className={styles.errorMessage} role='alert'>\n {errorMessage}\n </span>\n )}\n </span>\n )}\n\n {addons && (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions\n <span className={styles.addons} onClick={dom.preventDefault}>\n {addons}\n </span>\n )}\n </label>\n );\n },\n);\n\nSwitch.displayName = 'Switch';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Component.js","sources":["../src/Component.tsx"],"sourcesContent":["import React, {\n type ChangeEvent,\n forwardRef,\n type InputHTMLAttributes,\n type ReactNode,\n useRef,\n} from 'react';\nimport mergeRefs from 'react-merge-refs';\nimport cn from 'classnames';\n\nimport { dom } from '@alfalab/core-components-shared';\nimport { Skeleton } from '@alfalab/core-components-skeleton';\nimport { useFocus } from '@alfalab/hooks';\n\nimport { type Colors } from './types/colors';\n\nimport defaultStyles from './default.module.css';\nimport styles from './index.module.css';\nimport invertedStyles from './inverted.module.css';\n\nconst colorStyles = {\n default: defaultStyles,\n inverted: invertedStyles,\n};\n\ntype Align = 'start' | 'center';\n\nexport type SwitchProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'hint' | 'onChange' | 'disabled' | 'enterKeyHint'\n> & {\n /**\n * Управление состоянием вкл/выкл компонента\n */\n checked?: boolean;\n\n /**\n * Текст подписи к переключателю\n */\n label?: ReactNode;\n\n /**\n * Текст подсказки снизу\n */\n hint?: ReactNode;\n\n /**\n * Переключатель будет отрисован справа от контента\n */\n reversed?: boolean;\n\n /**\n * Выравнивание\n */\n align?: Align;\n\n /**\n * Дополнительный слот\n */\n addons?: React.ReactNode;\n\n /**\n * Растягивать ли компонент на всю ширину\n */\n block?: boolean;\n\n /**\n * Управление состоянием включен / выключен\n */\n disabled?: boolean;\n\n /**\n * Отображение ошибки\n */\n error?: ReactNode | boolean;\n\n /**\n * Обработчик переключения компонента\n */\n onChange?: (\n event: ChangeEvent<HTMLInputElement>,\n payload: {\n checked: boolean;\n name: InputHTMLAttributes<HTMLInputElement>['name'];\n },\n ) => void;\n\n /**\n * Идентификатор для систем автоматизированного тестирования\n */\n dataTestId?: string;\n\n /**\n * Набор цветов для компонента\n * @default default\n */\n colors?: Colors;\n\n /**\n * Показать скелетон\n * @default false\n */\n showSkeleton?: boolean;\n};\n\nexport const Switch = forwardRef<HTMLLabelElement, SwitchProps>(\n (\n {\n reversed = false,\n checked = false,\n align = 'start',\n addons,\n block,\n disabled,\n error,\n label,\n hint,\n name,\n value,\n className,\n onChange,\n dataTestId,\n colors = 'default',\n showSkeleton = false,\n ...restProps\n },\n ref,\n ) => {\n const labelRef = useRef<HTMLLabelElement>(null);\n\n const [focused] = useFocus(labelRef, 'keyboard');\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (onChange) {\n onChange(e, { checked: e.target.checked, name });\n }\n };\n\n const errorMessage = typeof error === 'boolean' ? '' : error;\n\n return (\n <label\n className={cn(styles.component, styles[align], className, {\n [styles.disabled]: disabled,\n [colorStyles[colors].disabled]: disabled,\n\n [styles.checked]: checked,\n [colorStyles[colors].checked]: checked,\n\n [styles.reversed]: reversed,\n [styles.focused]: focused,\n [styles.block]: block,\n })}\n ref={mergeRefs([labelRef, ref])}\n >\n <input\n type='checkbox'\n onChange={handleChange}\n disabled={disabled}\n checked={checked}\n name={name}\n value={value}\n data-test-id={dataTestId}\n {...restProps}\n />\n\n <Skeleton\n visible={showSkeleton}\n borderRadius='pill'\n colors={colors}\n className={cn({\n [styles.switchSkeleton]: showSkeleton,\n })}\n >\n <span className={cn(styles.switch, colorStyles[colors].switch)} />\n </Skeleton>\n\n {(label || hint || errorMessage) && (\n <span className={styles.content}>\n {label && (\n <Skeleton\n visible={showSkeleton}\n borderRadius='pill'\n colors={colors}\n className={cn(styles.labelWrap, {\n [styles.loading]: showSkeleton,\n })}\n >\n <span className={cn(styles.label, colorStyles[colors].label)}>\n {label}\n </span>\n </Skeleton>\n )}\n\n {hint && !errorMessage && (\n <Skeleton\n visible={showSkeleton}\n borderRadius='pill'\n colors={colors}\n className={cn(styles.hintWrap, {\n [styles.loading]: showSkeleton,\n })}\n >\n <span className={cn(styles.hint, colorStyles[colors].hint)}>\n {hint}\n </span>\n </Skeleton>\n )}\n\n {errorMessage && (\n <span className={styles.errorMessage} role='alert'>\n {errorMessage}\n </span>\n )}\n </span>\n )}\n\n {addons && (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions\n <span className={styles.addons} onClick={dom.preventDefault}>\n {addons}\n </span>\n )}\n </label>\n );\n },\n);\n\nSwitch.displayName = 'Switch';\n"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@
39
39
 
40
40
  .switch {
41
41
  position: relative;
42
+ display: block;
42
43
  border-radius: var(--border-radius-16);
43
44
  width: 36px;
44
45
  height: 20px;
@@ -51,6 +52,12 @@
51
52
  box-sizing: border-box;
52
53
  }
53
54
 
55
+ .switchSkeleton {
56
+ width: 36px;
57
+ height: 20px;
58
+ margin: var(--gap-2);
59
+ }
60
+
54
61
  .switch:before {
55
62
  content: '';
56
63
  position: absolute;
@@ -78,9 +85,18 @@
78
85
  display: block;
79
86
  }
80
87
 
81
- .label:not(:only-child) {
82
- margin-bottom: var(--gap-4);
83
- }
88
+ .labelWrap:not(:only-child) {
89
+ margin-bottom: var(--gap-4);
90
+ }
91
+
92
+ .labelWrap.loading {
93
+ height: var(--gap-12);
94
+ margin: var(--gap-6) 0;
95
+ }
96
+
97
+ .labelWrap.loading:not(:only-child) {
98
+ margin-bottom: var(--gap-2s);
99
+ }
84
100
 
85
101
  .errorMessage {
86
102
  font-size: 14px;
@@ -98,6 +114,11 @@
98
114
  display: block;
99
115
  }
100
116
 
117
+ .hintWrap.loading {
118
+ height: var(--gap-10);
119
+ margin-bottom: var(--gap-4);
120
+ }
121
+
101
122
  .component.reversed {
102
123
  flex-direction: row-reverse;
103
124
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-switch",
3
- "version": "6.0.3",
3
+ "version": "6.1.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -11,6 +11,7 @@
11
11
  "module": "./esm/index.js",
12
12
  "dependencies": {
13
13
  "@alfalab/core-components-shared": "^2.1.1",
14
+ "@alfalab/core-components-skeleton": "^7.0.2",
14
15
  "@alfalab/hooks": "^1.13.1",
15
16
  "classnames": "^2.5.1",
16
17
  "react-merge-refs": "^1.1.0",
package/src/Component.tsx CHANGED
@@ -9,6 +9,7 @@ import mergeRefs from 'react-merge-refs';
9
9
  import cn from 'classnames';
10
10
 
11
11
  import { dom } from '@alfalab/core-components-shared';
12
+ import { Skeleton } from '@alfalab/core-components-skeleton';
12
13
  import { useFocus } from '@alfalab/hooks';
13
14
 
14
15
  import { type Colors } from './types/colors';
@@ -94,6 +95,12 @@ export type SwitchProps = Omit<
94
95
  * @default default
95
96
  */
96
97
  colors?: Colors;
98
+
99
+ /**
100
+ * Показать скелетон
101
+ * @default false
102
+ */
103
+ showSkeleton?: boolean;
97
104
  };
98
105
 
99
106
  export const Switch = forwardRef<HTMLLabelElement, SwitchProps>(
@@ -114,6 +121,7 @@ export const Switch = forwardRef<HTMLLabelElement, SwitchProps>(
114
121
  onChange,
115
122
  dataTestId,
116
123
  colors = 'default',
124
+ showSkeleton = false,
117
125
  ...restProps
118
126
  },
119
127
  ref,
@@ -156,19 +164,47 @@ export const Switch = forwardRef<HTMLLabelElement, SwitchProps>(
156
164
  {...restProps}
157
165
  />
158
166
 
159
- <span className={cn(styles.switch, colorStyles[colors].switch)} />
167
+ <Skeleton
168
+ visible={showSkeleton}
169
+ borderRadius='pill'
170
+ colors={colors}
171
+ className={cn({
172
+ [styles.switchSkeleton]: showSkeleton,
173
+ })}
174
+ >
175
+ <span className={cn(styles.switch, colorStyles[colors].switch)} />
176
+ </Skeleton>
160
177
 
161
178
  {(label || hint || errorMessage) && (
162
179
  <span className={styles.content}>
163
180
  {label && (
164
- <span className={cn(styles.label, colorStyles[colors].label)}>
165
- {label}
166
- </span>
181
+ <Skeleton
182
+ visible={showSkeleton}
183
+ borderRadius='pill'
184
+ colors={colors}
185
+ className={cn(styles.labelWrap, {
186
+ [styles.loading]: showSkeleton,
187
+ })}
188
+ >
189
+ <span className={cn(styles.label, colorStyles[colors].label)}>
190
+ {label}
191
+ </span>
192
+ </Skeleton>
167
193
  )}
194
+
168
195
  {hint && !errorMessage && (
169
- <span className={cn(styles.hint, colorStyles[colors].hint)}>
170
- {hint}
171
- </span>
196
+ <Skeleton
197
+ visible={showSkeleton}
198
+ borderRadius='pill'
199
+ colors={colors}
200
+ className={cn(styles.hintWrap, {
201
+ [styles.loading]: showSkeleton,
202
+ })}
203
+ >
204
+ <span className={cn(styles.hint, colorStyles[colors].hint)}>
205
+ {hint}
206
+ </span>
207
+ </Skeleton>
172
208
  )}
173
209
 
174
210
  {errorMessage && (
@@ -36,6 +36,7 @@
36
36
 
37
37
  .switch {
38
38
  position: relative;
39
+ display: block;
39
40
  border-radius: var(--border-radius-16);
40
41
  width: 36px;
41
42
  height: 20px;
@@ -48,6 +49,12 @@
48
49
  box-sizing: border-box;
49
50
  }
50
51
 
52
+ .switchSkeleton {
53
+ width: 36px;
54
+ height: 20px;
55
+ margin: var(--gap-2);
56
+ }
57
+
51
58
  .switch:before {
52
59
  content: '';
53
60
  position: absolute;
@@ -72,8 +79,19 @@
72
79
  display: block;
73
80
  }
74
81
 
75
- .label:not(:only-child) {
76
- margin-bottom: var(--gap-4);
82
+ .labelWrap {
83
+ &:not(:only-child) {
84
+ margin-bottom: var(--gap-4);
85
+ }
86
+
87
+ &.loading {
88
+ height: var(--gap-12);
89
+ margin: var(--gap-6) 0;
90
+
91
+ &:not(:only-child) {
92
+ margin-bottom: var(--gap-2s);
93
+ }
94
+ }
77
95
  }
78
96
 
79
97
  .errorMessage {
@@ -86,6 +104,13 @@
86
104
  display: block;
87
105
  }
88
106
 
107
+ .hintWrap {
108
+ &.loading {
109
+ height: var(--gap-10);
110
+ margin-bottom: var(--gap-4);
111
+ }
112
+ }
113
+
89
114
  /* Reversed state */
90
115
 
91
116
  .component.reversed {