@umituz/react-native-photo-editor 1.0.10 → 1.0.12

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.
@@ -1,12 +1,16 @@
1
1
  import React from "react";
2
2
  import { View, TouchableOpacity } from "react-native";
3
- import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system";
3
+ import {
4
+ AtomicText,
5
+ AtomicIcon,
6
+ useAppDesignTokens
7
+ } from "@umituz/react-native-design-system";
4
8
 
5
9
  interface EditorToolbarProps {
6
10
  onAddText: () => void;
7
- onAddSticker: () => void;
8
- onAIMagic?: () => void; // Optional AI integration
9
- onOpenFilters: () => void;
11
+ onAddSticker?: () => void;
12
+ onAIMagic?: () => void;
13
+ onOpenFilters?: () => void;
10
14
  onOpenLayers: () => void;
11
15
  styles: Record<string, object>;
12
16
  t: (key: string) => string;
@@ -21,34 +25,56 @@ export const EditorToolbar: React.FC<EditorToolbarProps> = ({
21
25
  styles,
22
26
  t,
23
27
  }) => {
28
+ const tokens = useAppDesignTokens();
29
+
30
+ const ToolButton = ({
31
+ icon,
32
+ label,
33
+ onPress,
34
+ isActive
35
+ }: {
36
+ icon: string;
37
+ label: string;
38
+ onPress: () => void;
39
+ isActive?: boolean;
40
+ }) => (
41
+ <TouchableOpacity
42
+ style={[styles.toolButton, isActive && styles.toolButtonActive]}
43
+ onPress={onPress}
44
+ >
45
+ <AtomicIcon
46
+ name={icon}
47
+ size="md"
48
+ color={isActive ? "primary" : "textSecondary"}
49
+ />
50
+ <AtomicText
51
+ type="labelSmall"
52
+ color={isActive ? "primary" : "textSecondary"}
53
+ >
54
+ {label}
55
+ </AtomicText>
56
+ </TouchableOpacity>
57
+ );
58
+
24
59
  return (
25
60
  <View style={styles.bottomToolbar}>
26
- <TouchableOpacity
27
- style={[styles.toolButton, styles.toolButtonActive]}
28
- onPress={onAddText}
29
- >
30
- <AtomicIcon name="text" size="md" color="primary" />
31
- <AtomicText style={[styles.toolLabel, styles.toolLabelActive]}>
32
- Text
33
- </AtomicText>
34
- </TouchableOpacity>
35
- <TouchableOpacity style={styles.toolButton} onPress={onAddSticker}>
36
- <AtomicIcon name="happy" size="md" color="textSecondary" />
37
- <AtomicText style={styles.toolLabel}>{t("editor.sticker")}</AtomicText>
38
- </TouchableOpacity>
61
+ <ToolButton icon="text" label="Text" onPress={onAddText} />
62
+
63
+ {onAddSticker && (
64
+ <ToolButton icon="happy" label={t("editor.sticker")} onPress={onAddSticker} />
65
+ )}
66
+
39
67
  {onAIMagic && (
40
68
  <TouchableOpacity style={styles.aiMagicButton} onPress={onAIMagic}>
41
- <AtomicIcon name="sparkles" size="lg" customColor="#fff" />
69
+ <AtomicIcon name="sparkles" size="lg" customColor={tokens.colors.onPrimary} />
42
70
  </TouchableOpacity>
43
71
  )}
44
- <TouchableOpacity style={styles.toolButton} onPress={onOpenFilters}>
45
- <AtomicIcon name="color-filter" size="md" color="textSecondary" />
46
- <AtomicText style={styles.toolLabel}>{t("editor.filters")}</AtomicText>
47
- </TouchableOpacity>
48
- <TouchableOpacity style={styles.toolButton} onPress={onOpenLayers}>
49
- <AtomicIcon name="layers" size="md" color="textSecondary" />
50
- <AtomicText style={styles.toolLabel}>Layer</AtomicText>
51
- </TouchableOpacity>
72
+
73
+ {onOpenFilters && (
74
+ <ToolButton icon="color-filter" label={t("editor.filters")} onPress={onOpenFilters} />
75
+ )}
76
+
77
+ <ToolButton icon="layers" label="Layers" onPress={onOpenLayers} />
52
78
  </View>
53
79
  );
54
80
  };
@@ -1,18 +1,7 @@
1
1
  import React from "react";
2
2
  import { View, TouchableOpacity, StyleSheet } from "react-native";
3
- import {
4
- AtomicText,
5
- AtomicIcon,
6
- useAppDesignTokens,
7
- } from "@umituz/react-native-design-system";
8
- import { DEFAULT_FILTERS, type FilterType } from "../constants";
9
-
10
- interface FilterOption {
11
- id: FilterType;
12
- name: string;
13
- icon: string;
14
- value: number;
15
- }
3
+ import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
4
+ import { DEFAULT_FILTERS, type FilterOption } from "../constants";
16
5
 
17
6
  interface FilterPickerProps {
18
7
  selectedFilter: string;
@@ -28,65 +17,44 @@ export const FilterPicker: React.FC<FilterPickerProps> = ({
28
17
  const tokens = useAppDesignTokens();
29
18
 
30
19
  const styles = StyleSheet.create({
31
- container: { padding: 16 },
32
- title: {
33
- fontSize: 18,
34
- fontWeight: "bold",
35
- color: tokens.colors.textPrimary,
36
- marginBottom: 16,
37
- },
38
- grid: {
39
- flexDirection: "row",
40
- flexWrap: "wrap",
41
- gap: 12,
42
- },
20
+ container: { padding: tokens.spacing.md, gap: tokens.spacing.md },
21
+ grid: { flexDirection: "row", flexWrap: "wrap", gap: tokens.spacing.sm },
43
22
  filter: {
44
- width: 80,
45
- height: 80,
46
- borderRadius: 12,
23
+ width: 75,
24
+ height: 75,
25
+ borderRadius: tokens.borders.radius.md,
47
26
  backgroundColor: tokens.colors.surfaceVariant,
48
27
  alignItems: "center",
49
28
  justifyContent: "center",
50
29
  borderWidth: 2,
51
30
  borderColor: "transparent",
52
31
  },
53
- filterActive: {
32
+ active: {
54
33
  borderColor: tokens.colors.primary,
55
- backgroundColor: tokens.colors.primaryContainer,
56
- },
57
- filterName: {
58
- marginTop: 4,
59
- fontSize: 12,
60
- color: tokens.colors.textSecondary,
34
+ backgroundColor: tokens.colors.primary + "10",
61
35
  },
62
- filterNameActive: { color: tokens.colors.primary },
63
36
  });
64
37
 
65
38
  return (
66
39
  <View style={styles.container}>
67
- <AtomicText style={styles.title}>Filters</AtomicText>
40
+ <AtomicText type="headlineSmall">Filters</AtomicText>
68
41
  <View style={styles.grid}>
69
- {filters.map((filter) => (
42
+ {filters.map((f) => (
70
43
  <TouchableOpacity
71
- key={filter.id}
72
- style={[
73
- styles.filter,
74
- selectedFilter === filter.id && styles.filterActive,
75
- ]}
76
- onPress={() => onSelectFilter(filter.id, filter.value)}
44
+ key={f.id}
45
+ style={[styles.filter, selectedFilter === f.id && styles.active]}
46
+ onPress={() => onSelectFilter(f.id, f.value)}
77
47
  >
78
48
  <AtomicIcon
79
- name={filter.icon as "close-circle" | "color-palette" | "contrast" | "time" | "sunny" | "snow"}
49
+ name={f.icon as "close-circle" | "color-palette" | "contrast" | "time" | "sunny" | "snow"}
80
50
  size="lg"
81
- color={selectedFilter === filter.id ? "primary" : "textSecondary"}
51
+ color={selectedFilter === f.id ? "primary" : "textSecondary"}
82
52
  />
83
53
  <AtomicText
84
- style={[
85
- styles.filterName,
86
- selectedFilter === filter.id && styles.filterNameActive,
87
- ]}
54
+ type="labelSmall"
55
+ color={selectedFilter === f.id ? "primary" : "textSecondary"}
88
56
  >
89
- {filter.name}
57
+ {f.name}
90
58
  </AtomicText>
91
59
  </TouchableOpacity>
92
60
  ))}
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
- import { View, ScrollView, TouchableOpacity } from "react-native";
3
- import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system";
2
+ import { View, ScrollView, TouchableOpacity, StyleSheet } from "react-native";
3
+ import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
4
4
 
5
5
  interface FontControlsProps {
6
6
  fontSize: number;
@@ -17,65 +17,62 @@ export const FontControls: React.FC<FontControlsProps> = ({
17
17
  fonts,
18
18
  onFontSizeChange,
19
19
  onFontSelect,
20
- styles,
20
+ styles: externalStyles,
21
21
  }) => {
22
+ const tokens = useAppDesignTokens();
23
+
24
+ const styles = StyleSheet.create({
25
+ btn: {
26
+ padding: tokens.spacing.sm,
27
+ backgroundColor: tokens.colors.surface,
28
+ borderRadius: tokens.borders.radius.sm,
29
+ borderWidth: 1,
30
+ borderColor: tokens.colors.border,
31
+ minWidth: 44,
32
+ alignItems: "center",
33
+ }
34
+ });
35
+
22
36
  return (
23
- <View style={styles.controlsPanel}>
24
- <View style={styles.sliderRow}>
25
- <View style={styles.sliderLabel}>
37
+ <View style={externalStyles.controlsPanel}>
38
+ <View style={externalStyles.sliderRow}>
39
+ <View style={externalStyles.sliderLabel}>
26
40
  <AtomicIcon name="text" size="sm" color="textSecondary" />
27
- <AtomicText style={styles.sliderLabelText}>Text Size</AtomicText>
41
+ <AtomicText type="labelMedium" color="textSecondary">Text Size</AtomicText>
28
42
  </View>
29
- <AtomicText style={styles.sliderValue}>{fontSize}px</AtomicText>
30
- </View>
31
- <View style={styles.sliderTrack}>
32
- <View
33
- style={[
34
- styles.sliderFill,
35
- { width: `${((fontSize - 12) / 84) * 100}%` },
36
- ]}
37
- />
43
+ <AtomicText fontWeight="bold" color="primary">{fontSize}px</AtomicText>
38
44
  </View>
39
- <View style={{ flexDirection: "row", gap: 8, marginBottom: 16 }}>
40
- <TouchableOpacity
41
- onPress={() => onFontSizeChange(fontSize - 4)}
42
- style={styles.fontChip}
43
- >
44
- <AtomicText style={styles.fontChipText}>-</AtomicText>
45
+
46
+ <View style={{ flexDirection: "row", gap: tokens.spacing.sm, marginBottom: tokens.spacing.md }}>
47
+ <TouchableOpacity onPress={() => onFontSizeChange(fontSize - 4)} style={styles.btn}>
48
+ <AtomicText fontWeight="bold">-</AtomicText>
45
49
  </TouchableOpacity>
46
- <TouchableOpacity
47
- onPress={() => onFontSizeChange(fontSize + 4)}
48
- style={styles.fontChip}
49
- >
50
- <AtomicText style={styles.fontChipText}>+</AtomicText>
50
+ <TouchableOpacity onPress={() => onFontSizeChange(fontSize + 4)} style={styles.btn}>
51
+ <AtomicText fontWeight="bold">+</AtomicText>
51
52
  </TouchableOpacity>
52
53
  </View>
53
54
 
54
- <AtomicText style={styles.fontLabel}>Font Style</AtomicText>
55
- <ScrollView
56
- horizontal
57
- showsHorizontalScrollIndicator={false}
58
- contentContainerStyle={styles.fontRow}
59
- >
60
- {fonts.map((font) => (
61
- <TouchableOpacity
62
- key={font}
63
- style={[
64
- styles.fontChip,
65
- selectedFont === font && styles.fontChipActive,
66
- ]}
67
- onPress={() => onFontSelect(font)}
68
- >
69
- <AtomicText
70
- style={[
71
- styles.fontChipText,
72
- selectedFont === font && styles.fontChipTextActive,
73
- ]}
55
+ <AtomicText type="labelMedium" color="textSecondary" style={{ marginBottom: tokens.spacing.xs }}>
56
+ Font Style
57
+ </AtomicText>
58
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
59
+ <View style={externalStyles.fontRow}>
60
+ {fonts.map((font) => (
61
+ <TouchableOpacity
62
+ key={font}
63
+ style={[externalStyles.fontChip, selectedFont === font && externalStyles.fontChipActive]}
64
+ onPress={() => onFontSelect(font)}
74
65
  >
75
- {font}
76
- </AtomicText>
77
- </TouchableOpacity>
78
- ))}
66
+ <AtomicText
67
+ fontWeight="bold"
68
+ color={selectedFont === font ? "onPrimary" : "textSecondary"}
69
+ style={{ fontFamily: font }}
70
+ >
71
+ {font}
72
+ </AtomicText>
73
+ </TouchableOpacity>
74
+ ))}
75
+ </View>
79
76
  </ScrollView>
80
77
  </View>
81
78
  );
@@ -1,10 +1,6 @@
1
1
  import React from "react";
2
2
  import { View, ScrollView, TouchableOpacity, StyleSheet } from "react-native";
3
- import {
4
- AtomicText,
5
- AtomicIcon,
6
- useAppDesignTokens,
7
- } from "@umituz/react-native-design-system";
3
+ import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
8
4
  import { Layer, TextLayer } from "../types";
9
5
 
10
6
  interface LayerManagerProps {
@@ -25,58 +21,37 @@ export const LayerManager: React.FC<LayerManagerProps> = ({
25
21
  const tokens = useAppDesignTokens();
26
22
 
27
23
  const styles = StyleSheet.create({
28
- container: { padding: 16 },
29
- title: {
30
- fontSize: 18,
31
- fontWeight: "bold",
32
- color: tokens.colors.textPrimary,
33
- marginBottom: 16,
34
- },
35
- emptyText: {
36
- color: tokens.colors.textSecondary,
37
- textAlign: "center",
38
- padding: 24,
39
- },
40
- layerItem: {
24
+ container: { padding: tokens.spacing.md, gap: tokens.spacing.md },
25
+ item: {
41
26
  flexDirection: "row",
42
27
  alignItems: "center",
43
- padding: 12,
28
+ padding: tokens.spacing.md,
44
29
  backgroundColor: tokens.colors.surfaceVariant,
45
- borderRadius: 12,
46
- marginBottom: 8,
30
+ borderRadius: tokens.borders.radius.md,
31
+ marginBottom: tokens.spacing.xs,
47
32
  borderWidth: 2,
48
33
  borderColor: "transparent",
49
34
  },
50
- layerItemActive: {
35
+ active: {
51
36
  borderColor: tokens.colors.primary,
52
- backgroundColor: tokens.colors.primaryContainer,
53
- },
54
- layerInfo: { flex: 1, marginLeft: 12 },
55
- layerType: { fontSize: 12, color: tokens.colors.textSecondary },
56
- layerText: {
57
- fontSize: 14,
58
- color: tokens.colors.textPrimary,
59
- fontWeight: "500",
37
+ backgroundColor: tokens.colors.primary + "10",
60
38
  },
61
- deleteButton: { padding: 8 },
39
+ info: { flex: 1, marginLeft: tokens.spacing.sm },
62
40
  });
63
41
 
64
42
  return (
65
43
  <View style={styles.container}>
66
- <AtomicText style={styles.title}>Layers</AtomicText>
67
- {layers.length === 0 ? (
68
- <AtomicText style={styles.emptyText}>
69
- No layers yet. Add text or stickers!
70
- </AtomicText>
71
- ) : (
72
- <ScrollView showsVerticalScrollIndicator={false}>
73
- {layers.map((layer) => (
44
+ <AtomicText type="headlineSmall">Layers</AtomicText>
45
+ <ScrollView showsVerticalScrollIndicator={false}>
46
+ {layers.length === 0 ? (
47
+ <AtomicText color="textSecondary" style={{ textAlign: "center", padding: tokens.spacing.xl }}>
48
+ No layers yet
49
+ </AtomicText>
50
+ ) : (
51
+ layers.map((layer) => (
74
52
  <TouchableOpacity
75
53
  key={layer.id}
76
- style={[
77
- styles.layerItem,
78
- activeLayerId === layer.id && styles.layerItemActive,
79
- ]}
54
+ style={[styles.item, activeLayerId === layer.id && styles.active]}
80
55
  onPress={() => onSelectLayer(layer.id)}
81
56
  >
82
57
  <AtomicIcon
@@ -84,28 +59,21 @@ export const LayerManager: React.FC<LayerManagerProps> = ({
84
59
  size="md"
85
60
  color={activeLayerId === layer.id ? "primary" : "textSecondary"}
86
61
  />
87
- <View style={styles.layerInfo}>
88
- <AtomicText style={styles.layerType}>
89
- {layer.type === "text" ? "Text" : "Sticker"}
62
+ <View style={styles.info}>
63
+ <AtomicText type="labelSmall" color="textSecondary">
64
+ {layer.type.toUpperCase()}
90
65
  </AtomicText>
91
- <AtomicText style={styles.layerText} numberOfLines={1}>
92
- {layer.type === "text"
93
- ? (layer as TextLayer).text || t("editor.untitled")
94
- : "Emoji"}
66
+ <AtomicText fontWeight="bold" numberOfLines={1}>
67
+ {layer.type === "text" ? (layer as TextLayer).text || t("editor.untitled") : "Sticker"}
95
68
  </AtomicText>
96
69
  </View>
97
- {layers.length > 1 && (
98
- <TouchableOpacity
99
- style={styles.deleteButton}
100
- onPress={() => onDeleteLayer(layer.id)}
101
- >
102
- <AtomicIcon name="trash" size="sm" color="error" />
103
- </TouchableOpacity>
104
- )}
70
+ <TouchableOpacity onPress={() => onDeleteLayer(layer.id)} style={{ padding: tokens.spacing.xs }}>
71
+ <AtomicIcon name="trash" size="sm" color="error" />
72
+ </TouchableOpacity>
105
73
  </TouchableOpacity>
106
- ))}
107
- </ScrollView>
108
- )}
74
+ ))
75
+ )}
76
+ </ScrollView>
109
77
  </View>
110
78
  );
111
79
  };
@@ -1,9 +1,6 @@
1
1
  import React from "react";
2
2
  import { View, ScrollView, TouchableOpacity, StyleSheet } from "react-native";
3
- import {
4
- AtomicText,
5
- useAppDesignTokens,
6
- } from "@umituz/react-native-design-system";
3
+ import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
7
4
  import { DEFAULT_STICKERS } from "../constants";
8
5
 
9
6
  interface StickerPickerProps {
@@ -18,41 +15,26 @@ export const StickerPicker: React.FC<StickerPickerProps> = ({
18
15
  const tokens = useAppDesignTokens();
19
16
 
20
17
  const styles = StyleSheet.create({
21
- container: { padding: 16 },
22
- title: {
23
- fontSize: 18,
24
- fontWeight: "bold",
25
- color: tokens.colors.textPrimary,
26
- marginBottom: 16,
27
- },
28
- grid: {
29
- flexDirection: "row",
30
- flexWrap: "wrap",
31
- gap: 12,
32
- },
18
+ container: { padding: tokens.spacing.md, gap: tokens.spacing.md },
19
+ grid: { flexDirection: "row", flexWrap: "wrap", gap: tokens.spacing.sm },
33
20
  sticker: {
34
- width: 56,
35
- height: 56,
36
- borderRadius: 12,
21
+ width: 50,
22
+ height: 50,
23
+ borderRadius: tokens.borders.radius.sm,
37
24
  backgroundColor: tokens.colors.surfaceVariant,
38
25
  alignItems: "center",
39
26
  justifyContent: "center",
40
27
  },
41
- stickerText: { fontSize: 32 },
42
28
  });
43
29
 
44
30
  return (
45
31
  <View style={styles.container}>
46
- <AtomicText style={styles.title}>Emoji</AtomicText>
32
+ <AtomicText type="headlineSmall">Stickers</AtomicText>
47
33
  <ScrollView showsVerticalScrollIndicator={false}>
48
34
  <View style={styles.grid}>
49
- {stickers.map((sticker, index) => (
50
- <TouchableOpacity
51
- key={sticker || index}
52
- style={styles.sticker}
53
- onPress={() => onSelectSticker(sticker)}
54
- >
55
- <AtomicText style={styles.stickerText}>{sticker}</AtomicText>
35
+ {stickers.map((s, i) => (
36
+ <TouchableOpacity key={`${s}-${i}`} style={styles.sticker} onPress={() => onSelectSticker(s)}>
37
+ <AtomicText style={{ fontSize: 32 }}>{s}</AtomicText>
56
38
  </TouchableOpacity>
57
39
  ))}
58
40
  </View>
@@ -1,9 +1,6 @@
1
1
  import React from "react";
2
- import { View, TextInput, TouchableOpacity, StyleSheet } from "react-native";
3
- import {
4
- AtomicText,
5
- useAppDesignTokens,
6
- } from "@umituz/react-native-design-system";
2
+ import { View, TextInput, StyleSheet } from "react-native";
3
+ import { AtomicText, useAppDesignTokens, AtomicButton } from "@umituz/react-native-design-system";
7
4
 
8
5
  interface TextEditorSheetProps {
9
6
  value: string;
@@ -21,29 +18,22 @@ export const TextEditorSheet: React.FC<TextEditorSheetProps> = ({
21
18
  const tokens = useAppDesignTokens();
22
19
 
23
20
  const styles = StyleSheet.create({
24
- container: { padding: 16 },
25
- title: { fontSize: 18, fontWeight: "bold", marginBottom: 16 },
21
+ container: { padding: tokens.spacing.md, gap: tokens.spacing.md },
26
22
  input: {
27
23
  backgroundColor: tokens.colors.surfaceVariant,
28
- borderRadius: 12,
29
- padding: 16,
24
+ borderRadius: tokens.borders.radius.md,
25
+ padding: tokens.spacing.md,
30
26
  fontSize: 18,
31
27
  color: tokens.colors.textPrimary,
32
- marginBottom: 16,
33
28
  textAlign: "center",
29
+ minHeight: 120,
34
30
  },
35
- saveButton: {
36
- backgroundColor: tokens.colors.primary,
37
- borderRadius: 999,
38
- padding: 16,
39
- alignItems: "center",
40
- },
41
- saveButtonText: { color: tokens.colors.onPrimary, fontWeight: "bold" },
42
31
  });
43
32
 
44
33
  return (
45
34
  <View style={styles.container}>
46
- <AtomicText style={styles.title}>{t("editor.add_text")}</AtomicText>
35
+ <AtomicText type="headlineSmall">{t("editor.add_text")}</AtomicText>
36
+
47
37
  <TextInput
48
38
  value={value}
49
39
  onChangeText={onChange}
@@ -53,11 +43,10 @@ export const TextEditorSheet: React.FC<TextEditorSheetProps> = ({
53
43
  multiline
54
44
  autoFocus
55
45
  />
56
- <TouchableOpacity onPress={onSave} style={styles.saveButton}>
57
- <AtomicText style={styles.saveButtonText}>
58
- {t("common.save")}
59
- </AtomicText>
60
- </TouchableOpacity>
46
+
47
+ <AtomicButton variant="primary" onPress={onSave}>
48
+ {t("common.save")}
49
+ </AtomicButton>
61
50
  </View>
62
51
  );
63
52
  };
package/src/constants.ts CHANGED
@@ -42,6 +42,13 @@ export const DEFAULT_STICKERS = [
42
42
 
43
43
  export type FilterType = "none" | "sepia" | "grayscale" | "vintage" | "warm" | "cool";
44
44
 
45
+ export interface FilterOption {
46
+ id: FilterType;
47
+ name: string;
48
+ icon: string;
49
+ value: number;
50
+ }
51
+
45
52
  export const DEFAULT_FILTERS = [
46
53
  { id: "none" as FilterType, name: "None", icon: "close-circle", value: 0 },
47
54
  { id: "sepia" as FilterType, name: "Sepia", icon: "color-palette", value: 0.5 },
@@ -72,4 +72,4 @@ export class HistoryManager<T> {
72
72
  }
73
73
  }
74
74
 
75
- export const historyManager = new HistoryManager();
75
+