@umituz/react-native-design-system 4.28.10 → 4.28.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "4.28.10",
3
+ "version": "4.28.11",
4
4
  "description": "Universal design system for React Native apps with safe navigation hooks - updated SKILL.md with navigation documentation",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./dist/index.d.ts",
@@ -162,6 +162,11 @@
162
162
  "react-native": "./src/presentation/utils/variants.ts",
163
163
  "default": "./src/presentation/utils/variants.ts"
164
164
  },
165
+ "./core": {
166
+ "types": "./dist/core/index.d.ts",
167
+ "react-native": "./src/core/index.ts",
168
+ "default": "./src/core/index.ts"
169
+ },
165
170
  "./package.json": "./package.json"
166
171
  },
167
172
  "scripts": {
@@ -12,7 +12,7 @@ import { View, StyleSheet, TouchableOpacity, ViewStyle } from 'react-native';
12
12
  import { AtomicIcon } from './icon';
13
13
  import { AtomicText } from './AtomicText';
14
14
  import { useAppDesignTokens } from '../theme';
15
- import { calculateResponsiveSize } from '../utils/responsiveUtils';
15
+ import { calculateResponsiveSize } from '../responsive';
16
16
  import { EMPTY_STATE_ICON } from '../constants';
17
17
 
18
18
  export interface EmptyStateProps {
@@ -8,7 +8,7 @@
8
8
  import type { ViewStyle } from 'react-native';
9
9
  import type { FabSizeConfig, FabVariantConfig } from '../types';
10
10
  import { FAB_SIZES as BASE_FAB_SIZES } from '../../../constants';
11
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
11
+ import { calculateResponsiveSize } from '../../../responsive';
12
12
 
13
13
  /**
14
14
  * Get responsive FAB sizes based on spacing multiplier
@@ -8,7 +8,7 @@
8
8
  * @layer domain/entities
9
9
  */
10
10
 
11
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
11
+ import { calculateResponsiveSize } from '../../responsive';
12
12
 
13
13
  /**
14
14
  * Divider orientation
@@ -9,7 +9,7 @@ import { useAppDesignTokens } from '../../theme';
9
9
  import { AtomicIcon, useIconName } from '../../atoms';
10
10
  import { AtomicSpinner } from '../../atoms/AtomicSpinner';
11
11
  import type { SearchBarProps } from './types';
12
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
12
+ import { calculateResponsiveSize } from '../../responsive';
13
13
  import { MISC_SIZES } from '../../constants';
14
14
 
15
15
  export const SearchBar: React.FC<SearchBarProps> = ({
@@ -12,7 +12,7 @@ import { useAppDesignTokens } from "../../theme/hooks/useAppDesignTokens";
12
12
  import {
13
13
  calculateResponsiveSize,
14
14
  calculateLineHeight,
15
- } from "../../utils/responsiveUtils";
15
+ } from "../../responsive";
16
16
  import { SPACING, STEP_INDICATOR } from "../../constants";
17
17
  import { createMappedArray } from "../../utils";
18
18
 
@@ -1,7 +1,7 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { View, StyleSheet, ViewStyle } from "react-native";
3
3
  import { useAppDesignTokens } from '../../theme/hooks/useAppDesignTokens';
4
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
4
+ import { calculateResponsiveSize } from '../../responsive';
5
5
  import { STEP_INDICATOR } from '../../constants';
6
6
  import { createMappedArray } from '../../utils/arrayUtils';
7
7
 
@@ -5,7 +5,7 @@ import { AtomicText } from '../../atoms/AtomicText';
5
5
  import { AtomicIcon } from '../../atoms';
6
6
  import { useAppDesignTokens } from '../../theme';
7
7
  import type { ActionFooterProps } from './types';
8
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
8
+ import { calculateResponsiveSize } from '../../responsive';
9
9
  import { NAVIGATION } from '../../constants';
10
10
 
11
11
  const createStyles = (spacingMultiplier: number) => StyleSheet.create({
@@ -9,7 +9,7 @@ import { useAppDesignTokens } from '../../theme';
9
9
  import { Alert, AlertType } from './AlertTypes';
10
10
  import { getAlertBackgroundColor } from './utils/alertUtils';
11
11
  import { useAlertDismissHandler } from './hooks';
12
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
12
+ import { calculateResponsiveSize } from '../../responsive';
13
13
  import { MODAL_SIZES, ALERT_MODAL_ICON } from '../../constants';
14
14
 
15
15
  interface AlertModalProps {
@@ -82,6 +82,36 @@ export const AlertModal: React.FC<AlertModalProps> = ({ alert }) => {
82
82
  },
83
83
  }), [spacingMultiplier, tokens]);
84
84
 
85
+ const modalStyle = useMemo(() => [
86
+ styles.modal,
87
+ {
88
+ backgroundColor: tokens.colors.backgroundPrimary,
89
+ borderRadius: tokens.borders.radius.xl ?? 20,
90
+ borderWidth: 1,
91
+ borderColor: tokens.colors.border,
92
+ }
93
+ ], [styles.modal, tokens.colors.backgroundPrimary, tokens.borders.radius.xl, tokens.colors.border]);
94
+
95
+ const iconCircleStyle = useMemo(() => [
96
+ styles.iconCircle,
97
+ { backgroundColor: accentColor + '22' }
98
+ ], [styles.iconCircle, accentColor]);
99
+
100
+ const titleStyle = useMemo(() => [
101
+ styles.title,
102
+ { color: tokens.colors.textPrimary }
103
+ ], [styles.title, tokens.colors.textPrimary]);
104
+
105
+ const messageStyle = useMemo(() => [
106
+ styles.message,
107
+ { color: tokens.colors.textSecondary }
108
+ ], [styles.message, tokens.colors.textSecondary]);
109
+
110
+ const actionsContainerStyle = useMemo(() => [
111
+ hasTwoActions ? styles.actionsRow : styles.actionsColumn,
112
+ { marginTop: tokens.spacing.lg, gap: tokens.spacing.sm }
113
+ ], [hasTwoActions, styles.actionsRow, styles.actionsColumn, tokens.spacing.lg, tokens.spacing.sm]);
114
+
85
115
  return (
86
116
  <Modal
87
117
  visible
@@ -94,20 +124,9 @@ export const AlertModal: React.FC<AlertModalProps> = ({ alert }) => {
94
124
  style={styles.backdrop}
95
125
  onPress={alert.dismissible ? handleClose : undefined}
96
126
  />
97
- <View style={[
98
- styles.modal,
99
- {
100
- backgroundColor: tokens.colors.backgroundPrimary,
101
- borderRadius: tokens.borders.radius.xl ?? 20,
102
- borderWidth: 1,
103
- borderColor: tokens.colors.border,
104
- }
105
- ]}>
127
+ <View style={modalStyle}>
106
128
  {/* Icon circle */}
107
- <View style={[
108
- styles.iconCircle,
109
- { backgroundColor: accentColor + '22' }
110
- ]}>
129
+ <View style={iconCircleStyle}>
111
130
  <AtomicIcon
112
131
  name={iconName}
113
132
  customSize={calculateResponsiveSize(36, spacingMultiplier)}
@@ -118,7 +137,7 @@ export const AlertModal: React.FC<AlertModalProps> = ({ alert }) => {
118
137
  {/* Title */}
119
138
  <AtomicText
120
139
  type="titleLarge"
121
- style={[styles.title, { color: tokens.colors.textPrimary }]}
140
+ style={titleStyle}
122
141
  >
123
142
  {alert.title}
124
143
  </AtomicText>
@@ -127,17 +146,14 @@ export const AlertModal: React.FC<AlertModalProps> = ({ alert }) => {
127
146
  {!!alert.message && (
128
147
  <AtomicText
129
148
  type="bodyMedium"
130
- style={[styles.message, { color: tokens.colors.textSecondary }]}
149
+ style={messageStyle}
131
150
  >
132
151
  {alert.message}
133
152
  </AtomicText>
134
153
  )}
135
154
 
136
155
  {/* Actions */}
137
- <View style={[
138
- hasTwoActions ? styles.actionsRow : styles.actionsColumn,
139
- { marginTop: tokens.spacing.lg, gap: tokens.spacing.sm }
140
- ]}>
156
+ <View style={actionsContainerStyle}>
141
157
  {alert.actions.length === 0 ? (
142
158
  <AtomicButton
143
159
  title="Close"
@@ -12,7 +12,7 @@ import { AtomicText, AtomicIcon } from '../../atoms';
12
12
  import type { AvatarSize, AvatarShape } from './Avatar.types';
13
13
  import type { SizeConfig } from './Avatar.types';
14
14
  import { AVATAR_SIZES } from '../../constants';
15
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
15
+ import { calculateResponsiveSize } from '../../responsive';
16
16
  import { AvatarUtils } from './Avatar.utils';
17
17
 
18
18
  export interface AvatarProps {
@@ -52,19 +52,29 @@ const AvatarContent: React.FC<AvatarContentProps> = React.memo(({
52
52
  }) => {
53
53
  const tokens = useAppDesignTokens();
54
54
 
55
+ const imageStyle = useMemo(() => [
56
+ styles.image,
57
+ {
58
+ width: config.size,
59
+ height: config.size,
60
+ borderRadius,
61
+ },
62
+ imageStyle,
63
+ ], [config.size, borderRadius, imageStyle]);
64
+
65
+ const initialsStyle = useMemo(() => [
66
+ styles.initials,
67
+ {
68
+ fontSize: config.fontSize,
69
+ color: tokens.colors.textInverse,
70
+ },
71
+ ], [config.fontSize, tokens.colors.textInverse]);
72
+
55
73
  if (hasImage) {
56
74
  return (
57
75
  <Image
58
76
  source={{ uri }}
59
- style={[
60
- styles.image,
61
- {
62
- width: config.size,
63
- height: config.size,
64
- borderRadius,
65
- },
66
- imageStyle,
67
- ]}
77
+ style={imageStyle}
68
78
  />
69
79
  );
70
80
  }
@@ -73,13 +83,7 @@ const AvatarContent: React.FC<AvatarContentProps> = React.memo(({
73
83
  return (
74
84
  <AtomicText
75
85
  type="bodyMedium"
76
- style={[
77
- styles.initials,
78
- {
79
- fontSize: config.fontSize,
80
- color: tokens.colors.textInverse,
81
- },
82
- ]}
86
+ style={initialsStyle}
83
87
  >
84
88
  {initials}
85
89
  </AtomicText>
@@ -154,20 +158,35 @@ export const Avatar: React.FC<AvatarProps> = ({
154
158
  right: 0,
155
159
  }), []);
156
160
 
161
+ const containerStyle = useMemo(() => [
162
+ styles.container,
163
+ {
164
+ width: config.size,
165
+ height: config.size,
166
+ borderRadius,
167
+ backgroundColor: bgColor,
168
+ },
169
+ style,
170
+ ], [config.size, borderRadius, bgColor, style]);
171
+
172
+ const statusStyle = useMemo(() => [
173
+ styles.statusIndicator,
174
+ {
175
+ width: config.statusSize,
176
+ height: config.statusSize,
177
+ borderRadius: config.statusSize / 2,
178
+ backgroundColor: AvatarUtils.getStatusColor(status),
179
+ borderWidth: config.borderWidth,
180
+ borderColor: tokens.colors.onBackground,
181
+ ...statusPosition,
182
+ },
183
+ ], [config.statusSize, config.borderWidth, status, tokens.colors.onBackground, statusPosition]);
184
+
157
185
  const AvatarWrapper = onPress ? TouchableOpacity : View;
158
186
 
159
187
  return (
160
188
  <AvatarWrapper
161
- style={[
162
- styles.container,
163
- {
164
- width: config.size,
165
- height: config.size,
166
- borderRadius,
167
- backgroundColor: bgColor,
168
- },
169
- style,
170
- ]}
189
+ style={containerStyle}
171
190
  onPress={onPress}
172
191
  disabled={!onPress}
173
192
  accessibilityRole={onPress ? 'button' : 'image'}
@@ -187,18 +206,7 @@ export const Avatar: React.FC<AvatarProps> = ({
187
206
 
188
207
  {showStatus && (
189
208
  <View
190
- style={[
191
- styles.statusIndicator,
192
- {
193
- width: config.statusSize,
194
- height: config.statusSize,
195
- borderRadius: config.statusSize / 2,
196
- backgroundColor: AvatarUtils.getStatusColor(status),
197
- borderWidth: config.borderWidth,
198
- borderColor: tokens.colors.onBackground,
199
- ...statusPosition,
200
- },
201
- ]}
209
+ style={statusStyle}
202
210
  accessibilityLabel={`Status: ${status}`}
203
211
  accessibilityRole="none"
204
212
  />
@@ -12,7 +12,7 @@ import { AtomicText } from '../../atoms';
12
12
  import { Avatar } from './Avatar';
13
13
  import type { AvatarSize, AvatarShape } from './Avatar.types';
14
14
  import { AVATAR_SIZES } from '../../constants';
15
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
15
+ import { calculateResponsiveSize } from '../../responsive';
16
16
  import type { SizeConfig } from './Avatar.types';
17
17
 
18
18
  const AVATAR_CONSTANTS = {
@@ -3,7 +3,7 @@ import { Modal, View, StyleSheet, Pressable } from 'react-native';
3
3
  import { useAppDesignTokens } from '../../../theme';
4
4
  import { useSafeAreaInsets } from '../../../safe-area';
5
5
  import { getResponsiveBottomSheetLayout } from '../../../responsive';
6
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
6
+ import { calculateResponsiveSize } from '../../../responsive';
7
7
  import { BOTTOM_SHEET_HANDLE } from '../../../constants';
8
8
  import type {
9
9
  BottomSheetRef,
@@ -3,7 +3,7 @@ import { Modal, View, StyleSheet, Pressable } from 'react-native';
3
3
  import { useAppDesignTokens } from '../../../theme';
4
4
  import { useSafeAreaInsets } from '../../../safe-area';
5
5
  import { getResponsiveBottomSheetLayout } from '../../../responsive';
6
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
6
+ import { calculateResponsiveSize } from '../../../responsive';
7
7
  import { BOTTOM_SHEET_HANDLE } from '../../../constants';
8
8
  import type { BottomSheetModalRef, BottomSheetModalProps } from '../types/BottomSheet';
9
9
 
@@ -3,7 +3,7 @@ import { View, StyleSheet, ScrollView, Modal, Pressable, GestureResponderEvent }
3
3
  import { useSafeAreaInsets } from "../../../../safe-area";
4
4
  import { AtomicButton } from '../../../../atoms';
5
5
  import { useAppDesignTokens } from '../../../../theme';
6
- import { calculateResponsiveSize } from '../../../../utils/responsiveUtils';
6
+ import { calculateResponsiveSize } from '../../../../responsive';
7
7
  import { BOTTOM_SHEET_HANDLE } from '../../../../constants';
8
8
  import type { FilterOption } from "../../types/Filter";
9
9
  import { FilterUtils } from "../../types/Filter";
@@ -4,7 +4,7 @@ import { AtomicIcon } from "../../atoms";
4
4
  import { AtomicText } from "../../atoms";
5
5
  import { useAppDesignTokens } from "../../theme";
6
6
  import { LAYOUT } from "./constants";
7
- import { calculateResponsiveSize } from "../../utils/responsiveUtils";
7
+ import { calculateResponsiveSize } from "../../responsive";
8
8
 
9
9
  export interface CircularMenuItemProps {
10
10
  icon: string;
@@ -3,7 +3,7 @@ import { View, StyleSheet, TouchableOpacity } from 'react-native';
3
3
  import { AtomicText, AtomicIcon, useIconName } from '../../../atoms';
4
4
  import { useAppDesignTokens } from '../../../theme';
5
5
  import type { IconName } from '../../../atoms';
6
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
6
+ import { calculateResponsiveSize } from '../../../responsive';
7
7
  import { COUNTDOWN_TOGGLE } from '../../../constants';
8
8
 
9
9
  export interface CountdownHeaderProps {
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import { AtomicText } from '../../../atoms';
4
4
  import { useAppDesignTokens } from '../../../theme';
5
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
5
+ import { calculateResponsiveSize } from '../../../responsive';
6
6
  import { COUNTDOWN_SIZES } from '../../../constants';
7
7
 
8
8
  export interface TimeUnitProps {
@@ -3,7 +3,7 @@ import React, { useMemo } from 'react';
3
3
  import { View, StyleSheet, Text, Image } from 'react-native';
4
4
  import { useAppDesignTokens } from '../../theme';
5
5
  import type { HeroSectionProps } from './types';
6
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
6
+ import { calculateResponsiveSize } from '../../responsive';
7
7
  import { HERO_ICON } from '../../constants';
8
8
 
9
9
  export const HeroSection: React.FC<HeroSectionProps> = ({
@@ -21,7 +21,7 @@ import { AtomicIcon } from '../../atoms';
21
21
  import { AtomicText } from '../../atoms';
22
22
  import type { IconName } from '../../atoms';
23
23
  import { calculateGridItemWidth } from '../../utils/math';
24
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
24
+ import { calculateResponsiveSize } from '../../responsive';
25
25
  import { ICON_GRID } from '../../constants';
26
26
 
27
27
  export interface IconGridItem {
@@ -5,7 +5,7 @@ import { AtomicText } from '../../atoms/AtomicText';
5
5
  import { AtomicIcon } from '../../atoms';
6
6
  import { useAppDesignTokens } from '../../theme';
7
7
  import type { InfoGridProps } from './types';
8
- import { calculateResponsiveSize } from '../../utils/responsiveUtils';
8
+ import { calculateResponsiveSize } from '../../responsive';
9
9
  import { INFO_GRID_ICONS } from '../../constants';
10
10
 
11
11
  export const InfoGrid: React.FC<InfoGridProps> = ({
@@ -6,7 +6,7 @@ import type { TabNavigatorConfig, TabScreen } from "./types";
6
6
  import { NavigationValidator } from "./utils/NavigationValidator";
7
7
  import { createTabScreen } from "./utils/ScreenFactory";
8
8
  import { useAppDesignTokens } from "../../theme";
9
- import { calculateResponsiveSize } from "../../utils/responsiveUtils";
9
+ import { calculateResponsiveSize } from "../../responsive";
10
10
  import { NAVIGATION } from "../../constants";
11
11
 
12
12
  // Create the navigator instance ONCE outside the component
@@ -4,7 +4,7 @@ import { AtomicText } from '../../../atoms';
4
4
  import { AtomicIcon, useIconName } from '../../../atoms';
5
5
  import { useAppDesignTokens } from '../../../theme';
6
6
  import { useSafeAreaInsets } from '../../../safe-area';
7
- import { calculateResponsiveSize } from '../../../utils/responsiveUtils';
7
+ import { calculateResponsiveSize } from '../../../responsive';
8
8
  import { NAVIGATION } from '../../../constants';
9
9
 
10
10
  export interface NavigationHeaderProps {
@@ -2,11 +2,149 @@
2
2
  * Utils Module
3
3
  *
4
4
  * Centralized utility functions for the design system.
5
+ *
6
+ * Usage:
7
+ * import { createMappedArray, retryWithBackoff, formatFileSize, clamp, Logger, DesignSystemError } from '@umituz/react-native-design-system/utils';
5
8
  */
6
9
 
10
+ // =============================================================================
11
+ // ARRAY UTILITIES
12
+ // =============================================================================
13
+
7
14
  export {
8
15
  createMappedArray,
9
16
  safeSlice,
10
17
  filterById,
11
18
  findById,
12
19
  } from './arrayUtils';
20
+
21
+ // =============================================================================
22
+ // TIME CONSTANTS
23
+ // =============================================================================
24
+
25
+ export {
26
+ MILLISECONDS_PER_SECOND,
27
+ MILLISECONDS_PER_MINUTE,
28
+ MILLISECONDS_PER_HOUR,
29
+ MILLISECONDS_PER_DAY,
30
+ SECONDS_PER_MINUTE,
31
+ SECONDS_PER_HOUR,
32
+ SECONDS_PER_DAY,
33
+ MINUTES_PER_HOUR,
34
+ MINUTES_PER_DAY,
35
+ ONE_SECOND_MS,
36
+ FIVE_SECONDS_MS,
37
+ TEN_SECONDS_MS,
38
+ THIRTY_SECONDS_MS,
39
+ ONE_MINUTE_MS,
40
+ FIVE_MINUTES_MS,
41
+ TEN_MINUTES_MS,
42
+ THIRTY_MINUTES_MS,
43
+ ONE_HOUR_MS,
44
+ ONE_DAY_MS,
45
+ DEFAULT_TIMEOUT_MS,
46
+ DEFAULT_LONG_TIMEOUT_MS,
47
+ DEFAULT_CACHE_TTL_MS,
48
+ } from './constants/TimeConstants';
49
+
50
+ // =============================================================================
51
+ // ASYNC UTILITIES
52
+ // =============================================================================
53
+
54
+ export {
55
+ retryWithBackoff,
56
+ retryWithTimeout,
57
+ isNetworkError,
58
+ isRetryableHttpStatus,
59
+ type RetryOptions,
60
+ } from './async';
61
+
62
+ // =============================================================================
63
+ // FORMATTER UTILITIES
64
+ // =============================================================================
65
+
66
+ export {
67
+ formatFileSize,
68
+ formatDuration,
69
+ formatPhone,
70
+ truncateText,
71
+ capitalize,
72
+ toTitleCase,
73
+ toSlug,
74
+ type FileSizeFormatOptions,
75
+ type DurationFormatOptions,
76
+ type PhoneFormatOptions,
77
+ } from './formatters/stringFormatter';
78
+
79
+ // =============================================================================
80
+ // MATH UTILITIES
81
+ // =============================================================================
82
+
83
+ export {
84
+ clamp,
85
+ calculatePercentage,
86
+ roundTo,
87
+ calculateGridItemWidth,
88
+ isInRange,
89
+ lerp,
90
+ mapRange,
91
+ normalizeProgress,
92
+ formatPercentage,
93
+ calculateStepProgress,
94
+ isComplete,
95
+ hasStarted,
96
+ intensityToOpacity,
97
+ createRgbaColor,
98
+ ratioToOpacity,
99
+ } from './math';
100
+
101
+ // =============================================================================
102
+ // LOGGER
103
+ // =============================================================================
104
+
105
+ export {
106
+ Logger,
107
+ logger,
108
+ type LoggerConfig,
109
+ } from './logger';
110
+
111
+ // =============================================================================
112
+ // HOOKS
113
+ // =============================================================================
114
+
115
+ export {
116
+ useAsyncOperation,
117
+ type AsyncOperationOptions,
118
+ type AsyncOperationState,
119
+ type AsyncOperationActions,
120
+ type AsyncOperationReturn,
121
+ } from './hooks';
122
+
123
+ export type { ErrorHandler as AsyncErrorHandler } from './hooks';
124
+
125
+ // =============================================================================
126
+ // ERROR HANDLING
127
+ // =============================================================================
128
+
129
+ export {
130
+ DesignSystemError,
131
+ ErrorCodes,
132
+ ErrorCategory,
133
+ type ErrorCode,
134
+ type ErrorMetadata,
135
+ } from './errors';
136
+
137
+ export { ErrorHandler } from './errors/ErrorHandler';
138
+
139
+ export type {
140
+ Result,
141
+ } from './errors/types/Result';
142
+
143
+ export {
144
+ ok,
145
+ err,
146
+ unwrap,
147
+ unwrapOr,
148
+ map,
149
+ mapError,
150
+ } from './errors';