vision-accessibility 1.0.2 → 1.0.3
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/README.md +70 -1
- package/dist/components/AccessibilityPanel/AccessibilityPanel.d.ts.map +1 -1
- package/dist/components/AccessibilityToggle/AccessibilityToggle.d.ts +2 -0
- package/dist/components/AccessibilityToggle/AccessibilityToggle.d.ts.map +1 -1
- package/dist/components/ColorSchemeControl/ColorSchemeControl.d.ts +2 -0
- package/dist/components/ColorSchemeControl/ColorSchemeControl.d.ts.map +1 -1
- package/dist/components/FontSizeControl/FontSizeControl.d.ts +2 -0
- package/dist/components/FontSizeControl/FontSizeControl.d.ts.map +1 -1
- package/dist/components/ImageControl/ImageControl.d.ts +2 -0
- package/dist/components/ImageControl/ImageControl.d.ts.map +1 -1
- package/dist/config/translations.d.ts +57 -0
- package/dist/config/translations.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +371 -202
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +3 -3
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/css-applier.d.ts +1 -0
- package/dist/lib/css-applier.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +39 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AccessibilityPanel/AccessibilityPanel.module.scss +22 -31
- package/src/components/AccessibilityPanel/AccessibilityPanel.stories.tsx +50 -10
- package/src/components/AccessibilityPanel/AccessibilityPanel.tsx +72 -44
- package/src/components/AccessibilityToggle/AccessibilityToggle.stories.tsx +11 -0
- package/src/components/AccessibilityToggle/AccessibilityToggle.tsx +17 -10
- package/src/components/ColorSchemeControl/ColorSchemeControl.stories.tsx +15 -0
- package/src/components/ColorSchemeControl/ColorSchemeControl.tsx +99 -61
- package/src/components/FontSizeControl/FontSizeControl.stories.tsx +15 -0
- package/src/components/FontSizeControl/FontSizeControl.tsx +99 -61
- package/src/components/ImageControl/ImageControl.stories.tsx +11 -0
- package/src/components/ImageControl/ImageControl.tsx +17 -10
- package/src/config/translations.ts +82 -0
- package/src/hooks/useAccessibilitySettings.ts +12 -12
- package/src/index.ts +12 -8
- package/src/lib/css-applier.ts +54 -38
- package/src/styles/global.scss +1 -4
- package/src/types/index.ts +43 -1
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { ColorScheme } from '../../types';
|
|
13
13
|
import { useAccessibilityContext } from '../../context/AccessibilityContext';
|
|
14
|
+
import { defaultTranslations } from '../../config/translations';
|
|
14
15
|
import styles from './ColorSchemeControl.module.scss';
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -19,42 +20,23 @@ import styles from './ColorSchemeControl.module.scss';
|
|
|
19
20
|
interface ColorSchemeControlProps {
|
|
20
21
|
/** CSS класс для дополнительной стилизации */
|
|
21
22
|
className?: string;
|
|
23
|
+
/** Объект с переводами */
|
|
24
|
+
translations?: Record<string, string>;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
/**
|
|
25
|
-
* Опции цветовых схем с описаниями
|
|
26
|
-
*/
|
|
27
|
-
const COLOR_SCHEME_OPTIONS: Array<{
|
|
28
|
-
value: ColorScheme;
|
|
29
|
-
label: string;
|
|
30
|
-
description: string;
|
|
31
|
-
}> = [
|
|
32
|
-
{
|
|
33
|
-
value: 'standard',
|
|
34
|
-
label: 'Стандартный',
|
|
35
|
-
description: 'Обычная цветовая схема сайта'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
value: 'high-contrast',
|
|
39
|
-
label: 'Контрастный белый на черном',
|
|
40
|
-
description: 'Высококонтрастная схема для лучшей читаемости'
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
value: 'grayscale',
|
|
44
|
-
label: 'Черно-белый',
|
|
45
|
-
description: 'Преобразование всех цветов в оттенки серого'
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
|
|
49
27
|
/**
|
|
50
28
|
* Компонент управления цветовой схемой
|
|
51
|
-
*
|
|
29
|
+
*
|
|
52
30
|
* @param props - Свойства компонента
|
|
53
31
|
* @returns JSX элемент с радио-кнопками для выбора цветовой схемы
|
|
54
32
|
*/
|
|
55
|
-
export const ColorSchemeControl: React.FC<ColorSchemeControlProps> = ({
|
|
56
|
-
className
|
|
33
|
+
export const ColorSchemeControl: React.FC<ColorSchemeControlProps> = ({
|
|
34
|
+
className,
|
|
35
|
+
translations = {}
|
|
57
36
|
}) => {
|
|
37
|
+
// Объединяем переданные переводы с переводами по умолчанию
|
|
38
|
+
const mergedTranslations = { ...defaultTranslations, ...translations };
|
|
39
|
+
|
|
58
40
|
// Используем контекст для получения состояния и методов управления
|
|
59
41
|
const { settings, updateSettings } = useAccessibilityContext();
|
|
60
42
|
const colorScheme = settings.colorScheme;
|
|
@@ -62,7 +44,7 @@ export const ColorSchemeControl: React.FC<ColorSchemeControlProps> = ({
|
|
|
62
44
|
|
|
63
45
|
/**
|
|
64
46
|
* Обработчик изменения цветовой схемы
|
|
65
|
-
*
|
|
47
|
+
*
|
|
66
48
|
* @param event - Событие изменения радио-кнопки
|
|
67
49
|
*/
|
|
68
50
|
const handleColorSchemeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -73,41 +55,97 @@ export const ColorSchemeControl: React.FC<ColorSchemeControlProps> = ({
|
|
|
73
55
|
return (
|
|
74
56
|
<div className={`${styles.colorSchemeControl} ${className || ''} ${!isEnabled ? styles.disabled : ''} ${colorScheme === 'high-contrast' ? styles.highContrastMode : ''}`}>
|
|
75
57
|
<h4 className={styles.title}>
|
|
76
|
-
|
|
58
|
+
{mergedTranslations.colorSchemeTitle}
|
|
77
59
|
</h4>
|
|
78
60
|
|
|
79
61
|
<div className={styles.optionsContainer} role="radiogroup" aria-labelledby="color-scheme-title">
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
62
|
+
<label
|
|
63
|
+
key="standard"
|
|
64
|
+
className={`${styles.option} ${colorScheme === 'standard' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
65
|
+
>
|
|
66
|
+
<input
|
|
67
|
+
type="radio"
|
|
68
|
+
name="colorScheme"
|
|
69
|
+
value="standard"
|
|
70
|
+
checked={colorScheme === 'standard'}
|
|
71
|
+
onChange={handleColorSchemeChange}
|
|
72
|
+
className={styles.radioInput}
|
|
73
|
+
aria-describedby="color-scheme-standard-description"
|
|
74
|
+
disabled={!isEnabled}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<div className={styles.optionContent}>
|
|
78
|
+
<span className={styles.optionLabel}>
|
|
79
|
+
{mergedTranslations.colorSchemeStandardLabel}
|
|
80
|
+
</span>
|
|
81
|
+
<span
|
|
82
|
+
id="color-scheme-standard-description"
|
|
83
|
+
className={styles.optionDescription}
|
|
84
|
+
>
|
|
85
|
+
{mergedTranslations.colorSchemeStandardDescription}
|
|
86
|
+
</span>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
90
|
+
</label>
|
|
91
|
+
<label
|
|
92
|
+
key="high-contrast"
|
|
93
|
+
className={`${styles.option} ${colorScheme === 'high-contrast' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
94
|
+
>
|
|
95
|
+
<input
|
|
96
|
+
type="radio"
|
|
97
|
+
name="colorScheme"
|
|
98
|
+
value="high-contrast"
|
|
99
|
+
checked={colorScheme === 'high-contrast'}
|
|
100
|
+
onChange={handleColorSchemeChange}
|
|
101
|
+
className={styles.radioInput}
|
|
102
|
+
aria-describedby="color-scheme-high-contrast-description"
|
|
103
|
+
disabled={!isEnabled}
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<div className={styles.optionContent}>
|
|
107
|
+
<span className={styles.optionLabel}>
|
|
108
|
+
{mergedTranslations.colorSchemeHighContrastLabel}
|
|
109
|
+
</span>
|
|
110
|
+
<span
|
|
111
|
+
id="color-scheme-high-contrast-description"
|
|
112
|
+
className={styles.optionDescription}
|
|
113
|
+
>
|
|
114
|
+
{mergedTranslations.colorSchemeHighContrastDescription}
|
|
115
|
+
</span>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
119
|
+
</label>
|
|
120
|
+
<label
|
|
121
|
+
key="grayscale"
|
|
122
|
+
className={`${styles.option} ${colorScheme === 'grayscale' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
123
|
+
>
|
|
124
|
+
<input
|
|
125
|
+
type="radio"
|
|
126
|
+
name="colorScheme"
|
|
127
|
+
value="grayscale"
|
|
128
|
+
checked={colorScheme === 'grayscale'}
|
|
129
|
+
onChange={handleColorSchemeChange}
|
|
130
|
+
className={styles.radioInput}
|
|
131
|
+
aria-describedby="color-scheme-grayscale-description"
|
|
132
|
+
disabled={!isEnabled}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<div className={styles.optionContent}>
|
|
136
|
+
<span className={styles.optionLabel}>
|
|
137
|
+
{mergedTranslations.colorSchemeGrayscaleLabel}
|
|
138
|
+
</span>
|
|
139
|
+
<span
|
|
140
|
+
id="color-scheme-grayscale-description"
|
|
141
|
+
className={styles.optionDescription}
|
|
142
|
+
>
|
|
143
|
+
{mergedTranslations.colorSchemeGrayscaleDescription}
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
148
|
+
</label>
|
|
111
149
|
</div>
|
|
112
150
|
</div>
|
|
113
151
|
);
|
|
@@ -31,4 +31,19 @@ export const WithCustomClass: Story = {
|
|
|
31
31
|
args: {
|
|
32
32
|
className: 'custom-font-size-class',
|
|
33
33
|
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const WithTranslations: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
className: 'custom-font-size-class',
|
|
39
|
+
translations: {
|
|
40
|
+
fontSizeTitle: "Font Size",
|
|
41
|
+
fontSizeSmallLabel: "Small",
|
|
42
|
+
fontSizeSmallDescription: "Reduced text size (80%)",
|
|
43
|
+
fontSizeStandardLabel: "Standard",
|
|
44
|
+
fontSizeStandardDescription: "Normal text size",
|
|
45
|
+
fontSizeLargeLabel: "Large",
|
|
46
|
+
fontSizeLargeDescription: "Increased text size (130%)",
|
|
47
|
+
}
|
|
48
|
+
},
|
|
34
49
|
};
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { FontSize } from '../../types';
|
|
13
13
|
import { useAccessibilityContext } from '../../context/AccessibilityContext';
|
|
14
|
+
import { defaultTranslations } from '../../config/translations';
|
|
14
15
|
import styles from './FontSizeControl.module.scss';
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -19,42 +20,23 @@ import styles from './FontSizeControl.module.scss';
|
|
|
19
20
|
interface FontSizeControlProps {
|
|
20
21
|
/** CSS класс для дополнительной стилизации */
|
|
21
22
|
className?: string;
|
|
23
|
+
/** Объект с переводами */
|
|
24
|
+
translations?: Record<string, string>;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
/**
|
|
25
|
-
* Опции размеров шрифта с описаниями
|
|
26
|
-
*/
|
|
27
|
-
const FONT_SIZE_OPTIONS: Array<{
|
|
28
|
-
value: FontSize;
|
|
29
|
-
label: string;
|
|
30
|
-
description: string;
|
|
31
|
-
}> = [
|
|
32
|
-
{
|
|
33
|
-
value: 'small',
|
|
34
|
-
label: 'Мелкий',
|
|
35
|
-
description: 'Уменьшенный размер текста (80%)'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
value: 'standard',
|
|
39
|
-
label: 'Стандартный',
|
|
40
|
-
description: 'Обычный размер текста'
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
value: 'large',
|
|
44
|
-
label: 'Крупный',
|
|
45
|
-
description: 'Увеличенный размер текста (130%)'
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
|
|
49
27
|
/**
|
|
50
28
|
* Компонент управления размером шрифта
|
|
51
|
-
*
|
|
29
|
+
*
|
|
52
30
|
* @param props - Свойства компонента
|
|
53
31
|
* @returns JSX элемент с радио-кнопками для выбора размера шрифта
|
|
54
32
|
*/
|
|
55
|
-
export const FontSizeControl: React.FC<FontSizeControlProps> = ({
|
|
56
|
-
className
|
|
33
|
+
export const FontSizeControl: React.FC<FontSizeControlProps> = ({
|
|
34
|
+
className,
|
|
35
|
+
translations = {}
|
|
57
36
|
}) => {
|
|
37
|
+
// Объединяем переданные переводы с переводами по умолчанию
|
|
38
|
+
const mergedTranslations = { ...defaultTranslations, ...translations };
|
|
39
|
+
|
|
58
40
|
// Используем контекст для получения состояния и методов управления
|
|
59
41
|
const { settings, updateSettings } = useAccessibilityContext();
|
|
60
42
|
const fontSize = settings.fontSize;
|
|
@@ -62,7 +44,7 @@ export const FontSizeControl: React.FC<FontSizeControlProps> = ({
|
|
|
62
44
|
|
|
63
45
|
/**
|
|
64
46
|
* Обработчик изменения размера шрифта
|
|
65
|
-
*
|
|
47
|
+
*
|
|
66
48
|
* @param event - Событие изменения радио-кнопки
|
|
67
49
|
*/
|
|
68
50
|
const handleFontSizeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -73,41 +55,97 @@ export const FontSizeControl: React.FC<FontSizeControlProps> = ({
|
|
|
73
55
|
return (
|
|
74
56
|
<div className={`${styles.fontSizeControl} ${className || ''} ${!isEnabled ? styles.disabled : ''} ${settings.colorScheme === 'high-contrast' ? styles.highContrastMode : ''}`}>
|
|
75
57
|
<h4 className={styles.title}>
|
|
76
|
-
|
|
58
|
+
{mergedTranslations.fontSizeTitle}
|
|
77
59
|
</h4>
|
|
78
60
|
|
|
79
61
|
<div className={styles.optionsContainer} role="radiogroup" aria-labelledby="font-size-title">
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
62
|
+
<label
|
|
63
|
+
key="small"
|
|
64
|
+
className={`${styles.option} ${fontSize === 'small' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
65
|
+
>
|
|
66
|
+
<input
|
|
67
|
+
type="radio"
|
|
68
|
+
name="fontSize"
|
|
69
|
+
value="small"
|
|
70
|
+
checked={fontSize === 'small'}
|
|
71
|
+
onChange={handleFontSizeChange}
|
|
72
|
+
className={styles.radioInput}
|
|
73
|
+
aria-describedby="font-size-small-description"
|
|
74
|
+
disabled={!isEnabled}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<div className={styles.optionContent}>
|
|
78
|
+
<span className={styles.optionLabel}>
|
|
79
|
+
{mergedTranslations.fontSizeSmallLabel}
|
|
80
|
+
</span>
|
|
81
|
+
<span
|
|
82
|
+
id="font-size-small-description"
|
|
83
|
+
className={styles.optionDescription}
|
|
84
|
+
>
|
|
85
|
+
{mergedTranslations.fontSizeSmallDescription}
|
|
86
|
+
</span>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
90
|
+
</label>
|
|
91
|
+
<label
|
|
92
|
+
key="standard"
|
|
93
|
+
className={`${styles.option} ${fontSize === 'standard' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
94
|
+
>
|
|
95
|
+
<input
|
|
96
|
+
type="radio"
|
|
97
|
+
name="fontSize"
|
|
98
|
+
value="standard"
|
|
99
|
+
checked={fontSize === 'standard'}
|
|
100
|
+
onChange={handleFontSizeChange}
|
|
101
|
+
className={styles.radioInput}
|
|
102
|
+
aria-describedby="font-size-standard-description"
|
|
103
|
+
disabled={!isEnabled}
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<div className={styles.optionContent}>
|
|
107
|
+
<span className={styles.optionLabel}>
|
|
108
|
+
{mergedTranslations.fontSizeStandardLabel}
|
|
109
|
+
</span>
|
|
110
|
+
<span
|
|
111
|
+
id="font-size-standard-description"
|
|
112
|
+
className={styles.optionDescription}
|
|
113
|
+
>
|
|
114
|
+
{mergedTranslations.fontSizeStandardDescription}
|
|
115
|
+
</span>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
119
|
+
</label>
|
|
120
|
+
<label
|
|
121
|
+
key="large"
|
|
122
|
+
className={`${styles.option} ${fontSize === 'large' ? styles.selected : ''} ${!isEnabled ? styles.optionDisabled : ''}`}
|
|
123
|
+
>
|
|
124
|
+
<input
|
|
125
|
+
type="radio"
|
|
126
|
+
name="fontSize"
|
|
127
|
+
value="large"
|
|
128
|
+
checked={fontSize === 'large'}
|
|
129
|
+
onChange={handleFontSizeChange}
|
|
130
|
+
className={styles.radioInput}
|
|
131
|
+
aria-describedby="font-size-large-description"
|
|
132
|
+
disabled={!isEnabled}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<div className={styles.optionContent}>
|
|
136
|
+
<span className={styles.optionLabel}>
|
|
137
|
+
{mergedTranslations.fontSizeLargeLabel}
|
|
138
|
+
</span>
|
|
139
|
+
<span
|
|
140
|
+
id="font-size-large-description"
|
|
141
|
+
className={styles.optionDescription}
|
|
142
|
+
>
|
|
143
|
+
{mergedTranslations.fontSizeLargeDescription}
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div className={styles.radioIndicator} aria-hidden="true" />
|
|
148
|
+
</label>
|
|
111
149
|
</div>
|
|
112
150
|
</div>
|
|
113
151
|
);
|
|
@@ -40,4 +40,15 @@ export const WithCustomClass: Story = {
|
|
|
40
40
|
args: {
|
|
41
41
|
className: 'custom-image-control-class',
|
|
42
42
|
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const WithTranslations: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
className: 'custom-image-control-class',
|
|
48
|
+
translations: {
|
|
49
|
+
imageControlTitle: "Images",
|
|
50
|
+
imageControlShowLabel: "Show Images",
|
|
51
|
+
imageControlHideLabel: "Hide Images",
|
|
52
|
+
}
|
|
53
|
+
},
|
|
43
54
|
};
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import { useAccessibilityContext } from '../../context/AccessibilityContext';
|
|
12
|
+
import { defaultTranslations } from '../../config/translations';
|
|
12
13
|
import styles from './ImageControl.module.scss';
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -17,17 +18,23 @@ import styles from './ImageControl.module.scss';
|
|
|
17
18
|
interface ImageControlProps {
|
|
18
19
|
/** CSS класс для дополнительной стилизации */
|
|
19
20
|
className?: string;
|
|
21
|
+
/** Объект с переводами */
|
|
22
|
+
translations?: Record<string, string>;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
26
|
* Компонент управления отображением изображений
|
|
24
|
-
*
|
|
27
|
+
*
|
|
25
28
|
* @param props - Свойства компонента
|
|
26
29
|
* @returns JSX элемент с переключателем для управления изображениями
|
|
27
30
|
*/
|
|
28
|
-
export const ImageControl: React.FC<ImageControlProps> = ({
|
|
29
|
-
className
|
|
31
|
+
export const ImageControl: React.FC<ImageControlProps> = ({
|
|
32
|
+
className,
|
|
33
|
+
translations = {}
|
|
30
34
|
}) => {
|
|
35
|
+
// Объединяем переданные переводы с переводами по умолчанию
|
|
36
|
+
const mergedTranslations = { ...defaultTranslations, ...translations };
|
|
37
|
+
|
|
31
38
|
// Используем контекст для получения состояния и методов управления
|
|
32
39
|
const { settings, updateSettings } = useAccessibilityContext();
|
|
33
40
|
const showImages = settings.showImages;
|
|
@@ -35,7 +42,7 @@ export const ImageControl: React.FC<ImageControlProps> = ({
|
|
|
35
42
|
|
|
36
43
|
/**
|
|
37
44
|
* Обработчик изменения настройки отображения изображений
|
|
38
|
-
*
|
|
45
|
+
*
|
|
39
46
|
* @param event - Событие изменения чекбокса
|
|
40
47
|
*/
|
|
41
48
|
const handleImageVisibilityChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -45,7 +52,7 @@ export const ImageControl: React.FC<ImageControlProps> = ({
|
|
|
45
52
|
return (
|
|
46
53
|
<div className={`${styles.imageControl} ${className || ''} ${!isEnabled ? styles.disabled : ''} ${settings.colorScheme === 'high-contrast' ? styles.highContrastMode : ''}`}>
|
|
47
54
|
<h4 className={styles.title}>
|
|
48
|
-
|
|
55
|
+
{mergedTranslations.imageControlTitle}
|
|
49
56
|
</h4>
|
|
50
57
|
|
|
51
58
|
<div className={styles.switchContainer}>
|
|
@@ -64,17 +71,17 @@ export const ImageControl: React.FC<ImageControlProps> = ({
|
|
|
64
71
|
</span>
|
|
65
72
|
|
|
66
73
|
<span className={styles.switchText}>
|
|
67
|
-
{showImages ?
|
|
74
|
+
{showImages ? mergedTranslations.imageControlShowLabel : mergedTranslations.imageControlHideLabel}
|
|
68
75
|
</span>
|
|
69
76
|
</label>
|
|
70
77
|
|
|
71
|
-
<p
|
|
78
|
+
<p
|
|
72
79
|
id="image-control-description"
|
|
73
80
|
className={styles.description}
|
|
74
81
|
>
|
|
75
|
-
{showImages
|
|
76
|
-
?
|
|
77
|
-
:
|
|
82
|
+
{showImages
|
|
83
|
+
? mergedTranslations.imageControlShowDescription
|
|
84
|
+
: mergedTranslations.imageControlHideDescription
|
|
78
85
|
}
|
|
79
86
|
</p>
|
|
80
87
|
</div>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Конфигурация переводов для панели доступности
|
|
3
|
+
* Содержит текстовые строки по умолчанию на русском языке
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface AccessibilityTranslations {
|
|
7
|
+
/** Заголовок панели настроек доступности */
|
|
8
|
+
panelTitle?: string;
|
|
9
|
+
/** Описание панели настроек доступности */
|
|
10
|
+
panelDescription?: string;
|
|
11
|
+
/** Текст для кнопки закрытия панели */
|
|
12
|
+
closePanelLabel?: string;
|
|
13
|
+
/** Заголовок секции цветовой схемы */
|
|
14
|
+
colorSchemeTitle?: string;
|
|
15
|
+
/** Значение опции стандартной цветовой схемы */
|
|
16
|
+
colorSchemeStandardLabel?: string;
|
|
17
|
+
/** Описание опции стандартной цветовой схемы */
|
|
18
|
+
colorSchemeStandardDescription?: string;
|
|
19
|
+
/** Значение опции высококонтрастной цветовой схемы */
|
|
20
|
+
colorSchemeHighContrastLabel?: string;
|
|
21
|
+
/** Описание опции высококонтрастной цветовой схемы */
|
|
22
|
+
colorSchemeHighContrastDescription?: string;
|
|
23
|
+
/** Значение опции черно-белой цветовой схемы */
|
|
24
|
+
colorSchemeGrayscaleLabel?: string;
|
|
25
|
+
/** Описание опции черно-белой цветовой схемы */
|
|
26
|
+
colorSchemeGrayscaleDescription?: string;
|
|
27
|
+
/** Заголовок секции размера шрифта */
|
|
28
|
+
fontSizeTitle?: string;
|
|
29
|
+
/** Значение опции маленького шрифта */
|
|
30
|
+
fontSizeSmallLabel?: string;
|
|
31
|
+
/** Описание опции маленького шрифта */
|
|
32
|
+
fontSizeSmallDescription?: string;
|
|
33
|
+
/** Значение опции стандартного шрифта */
|
|
34
|
+
fontSizeStandardLabel?: string;
|
|
35
|
+
/** Описание опции стандартного шрифта */
|
|
36
|
+
fontSizeStandardDescription?: string;
|
|
37
|
+
/** Значение опции большого шрифта */
|
|
38
|
+
fontSizeLargeLabel?: string;
|
|
39
|
+
/** Описание опции большого шрифта */
|
|
40
|
+
fontSizeLargeDescription?: string;
|
|
41
|
+
/** Заголовок секции изображений */
|
|
42
|
+
imageControlTitle?: string;
|
|
43
|
+
/** Текст для переключателя показа изображений */
|
|
44
|
+
imageControlShowLabel?: string;
|
|
45
|
+
/** Текст для переключателя скрытия изображений */
|
|
46
|
+
imageControlHideLabel?: string;
|
|
47
|
+
/** Текст для переключателя доступности */
|
|
48
|
+
accessibilityToggleLabel?: string;
|
|
49
|
+
/** Описание для включенного состояния переключателя доступности */
|
|
50
|
+
accessibilityEnableDescription?: string;
|
|
51
|
+
/** Описание для выключенного состояния переключателя доступности */
|
|
52
|
+
accessibilityDisableDescription?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Переводы по умолчанию на русском языке
|
|
57
|
+
*/
|
|
58
|
+
export const defaultTranslations: AccessibilityTranslations = {
|
|
59
|
+
panelTitle: 'Настройки доступности',
|
|
60
|
+
panelDescription: 'Настройте отображение страницы для улучшения доступности',
|
|
61
|
+
closePanelLabel: 'Закрыть панель настроек доступности',
|
|
62
|
+
colorSchemeTitle: 'Цветовая схема',
|
|
63
|
+
colorSchemeStandardLabel: 'Стандартный',
|
|
64
|
+
colorSchemeStandardDescription: 'Обычная цветовая схема сайта',
|
|
65
|
+
colorSchemeHighContrastLabel: 'Контрастный белый на черном',
|
|
66
|
+
colorSchemeHighContrastDescription: 'Высококонтрастная схема для лучшей читаемости',
|
|
67
|
+
colorSchemeGrayscaleLabel: 'Черно-белый',
|
|
68
|
+
colorSchemeGrayscaleDescription: 'Преобразование всех цветов в оттенки серого',
|
|
69
|
+
fontSizeTitle: 'Размер шрифта',
|
|
70
|
+
fontSizeSmallLabel: 'Мелкий',
|
|
71
|
+
fontSizeSmallDescription: 'Уменьшенный размер текста (80%)',
|
|
72
|
+
fontSizeStandardLabel: 'Стандартный',
|
|
73
|
+
fontSizeStandardDescription: 'Обычный размер текста',
|
|
74
|
+
fontSizeLargeLabel: 'Крупный',
|
|
75
|
+
fontSizeLargeDescription: 'Увеличенный размер текста (130%)',
|
|
76
|
+
imageControlTitle: 'Изображения',
|
|
77
|
+
imageControlShowLabel: 'Показывать изображения',
|
|
78
|
+
imageControlHideLabel: 'Скрывать изображения',
|
|
79
|
+
accessibilityToggleLabel: 'Режим доступности',
|
|
80
|
+
accessibilityEnableDescription: 'Все настройки доступности активны. Используйте элементы управления ниже для точной настройки.',
|
|
81
|
+
accessibilityDisableDescription: 'Включите режим доступности для активации всех настроек. При выключении все изменения будут сброшены.',
|
|
82
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Хук для управления настройками доступности
|
|
3
3
|
* Обеспечивает централизованное управление состоянием настроек доступности
|
|
4
4
|
* с автоматическим сохранением в localStorage и применением к DOM
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Реализует требования:
|
|
7
7
|
* - 5.1: Включение режима доступности с активацией всех сохраненных настроек
|
|
8
8
|
* - 5.2: Выключение режима доступности с удалением всех CSS классов и стилей
|
|
@@ -11,25 +11,25 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { useState, useEffect, useCallback } from 'react';
|
|
14
|
-
import {
|
|
15
|
-
AccessibilitySettings,
|
|
14
|
+
import {
|
|
15
|
+
AccessibilitySettings,
|
|
16
16
|
DEFAULT_ACCESSIBILITY_SETTINGS,
|
|
17
|
-
AccessibilityContextType
|
|
17
|
+
AccessibilityContextType
|
|
18
18
|
} from '../types';
|
|
19
|
-
import {
|
|
20
|
-
saveToStorage,
|
|
21
|
-
loadFromStorage,
|
|
22
|
-
clearStorage
|
|
19
|
+
import {
|
|
20
|
+
saveToStorage,
|
|
21
|
+
loadFromStorage,
|
|
22
|
+
clearStorage
|
|
23
23
|
} from '../lib/accessibility-storage';
|
|
24
|
-
import {
|
|
25
|
-
applyAllSettings,
|
|
26
|
-
removeAllAccessibilityStyles
|
|
24
|
+
import {
|
|
25
|
+
applyAllSettings,
|
|
26
|
+
removeAllAccessibilityStyles
|
|
27
27
|
} from '../lib/css-applier';
|
|
28
28
|
import { updateNewElementsFontSize } from '../lib/font-size-manager';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Хук для управления настройками доступности
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
33
|
* @returns Объект с текущими настройками и методами для их управления
|
|
34
34
|
*/
|
|
35
35
|
export const useAccessibilitySettings = (): AccessibilityContextType => {
|