@fadyshawky/react-native-magic 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/template/src/common/components/Cards.tsx +5 -5
  3. package/template/src/common/components/EmptyView.tsx +1 -1
  4. package/template/src/common/components/ImageCropPickerButton.tsx +1 -1
  5. package/template/src/common/components/OTPInput.tsx +5 -5
  6. package/template/src/common/components/PhotoTakingButton.tsx +2 -2
  7. package/template/src/common/components/PrimaryButton.tsx +19 -19
  8. package/template/src/common/components/PrimaryTextInput.tsx +195 -129
  9. package/template/src/common/components/RadioButton.tsx +2 -2
  10. package/template/src/common/components/SearchBar.tsx +7 -7
  11. package/template/src/common/components/Separator.tsx +1 -1
  12. package/template/src/common/components/Stepper.tsx +153 -0
  13. package/template/src/common/components/TryAgain.tsx +1 -1
  14. package/template/src/common/helpers/defaultKeyIdExtractor.ts +1 -1
  15. package/template/src/common/helpers/shareHelpers.ts +47 -0
  16. package/template/src/common/helpers/stringsHelpers.ts +0 -4
  17. package/template/src/core/api/errorHandler.ts +1 -2
  18. package/template/src/core/store/app/appSlice.ts +5 -13
  19. package/template/src/core/store/app/appState.ts +2 -10
  20. package/template/src/core/theme/colors.ts +94 -72
  21. package/template/src/core/theme/commonSizes.ts +110 -43
  22. package/template/src/core/theme/commonStyles.ts +22 -22
  23. package/template/src/core/theme/fonts.ts +13 -14
  24. package/template/src/core/theme/shadows.ts +135 -0
  25. package/template/src/core/theme/themes.ts +386 -75
  26. package/template/src/core/theme/types.ts +145 -18
  27. package/template/src/navigation/HeaderComponents.tsx +1 -1
  28. package/template/src/navigation/MainNavigation.tsx +1 -2
  29. package/template/src/screens/Login/Login.tsx +0 -14
  30. package/template/src/screens/home/HomeScreen.tsx +8 -8
  31. package/template/src/screens/home/components/CarouselSection.tsx +6 -6
  32. package/template/src/screens/home/components/FeaturedCarousel.tsx +5 -5
  33. package/template/src/screens/registration/RegistrationScreen.tsx +3 -3
  34. package/template/src/screens/resetPassword/ForgotPasswordScreen.tsx +3 -3
  35. package/template/src/types/react-native-config.d.ts +8 -0
@@ -161,19 +161,19 @@ const styles = StyleSheet.create({
161
161
  height: 48,
162
162
  borderRadius: 16,
163
163
  borderWidth: 1,
164
- paddingHorizontal: CommonSizes.spacing.md,
165
- marginHorizontal: CommonSizes.spacing.lg,
166
- marginBottom: CommonSizes.spacing.lg,
164
+ paddingHorizontal: CommonSizes.spacing.medium,
165
+ marginHorizontal: CommonSizes.spacing.large,
166
+ marginBottom: CommonSizes.spacing.large,
167
167
  },
168
168
  input: {
169
169
  flex: 1,
170
- paddingVertical: CommonSizes.spacing.md,
171
- paddingHorizontal: CommonSizes.spacing.sm,
170
+ paddingVertical: CommonSizes.spacing.medium,
171
+ paddingHorizontal: CommonSizes.spacing.small,
172
172
  },
173
173
  searchIcon: {
174
- marginHorizontal: CommonSizes.spacing.sm,
174
+ marginHorizontal: CommonSizes.spacing.small,
175
175
  },
176
176
  clearButton: {
177
- padding: CommonSizes.spacing.sm,
177
+ padding: CommonSizes.spacing.small,
178
178
  },
179
179
  });
@@ -27,7 +27,7 @@ const sharedStyle: ViewStyle = {
27
27
  const styles = StyleSheet.create({
28
28
  container: {
29
29
  ...sharedStyle,
30
- marginHorizontal: CommonSizes.spacing.md,
30
+ marginHorizontal: CommonSizes.spacing.medium,
31
31
  } as ViewStyle,
32
32
  fullContainer: {
33
33
  ...sharedStyle,
@@ -0,0 +1,153 @@
1
+ import React from 'react';
2
+ import {View, Text, StyleSheet, Image, Pressable} from 'react-native';
3
+ import {useTheme} from '../../core/theme/ThemeProvider';
4
+ import {Theme} from '../../core/theme/types';
5
+ import {PrimaryColors} from '../../core/theme/colors';
6
+ import {ImageResources} from '../ImageResources.g';
7
+
8
+ interface Step {
9
+ title: string;
10
+ }
11
+
12
+ interface StepperProps {
13
+ steps: Step[];
14
+ currentStep: number;
15
+ orientation?: 'horizontal' | 'vertical';
16
+ onStepPress?: (index: number) => void;
17
+ }
18
+
19
+ const STEP_SIZE = 64;
20
+
21
+ const Stepper: React.FC<StepperProps> = ({
22
+ steps,
23
+ currentStep,
24
+ orientation = 'horizontal',
25
+ onStepPress,
26
+ }) => {
27
+ const {theme} = useTheme();
28
+ const isDarkMode = theme.mode === 'dark';
29
+ const styles = createStyles(theme, orientation, isDarkMode);
30
+
31
+ return (
32
+ <View style={styles.container}>
33
+ {steps.map((step, index) => {
34
+ const isCompleted = index < currentStep;
35
+ const isActive = index === currentStep;
36
+ const isLastStep = index === steps.length - 1;
37
+
38
+ const connectorStyle = [
39
+ styles.connector,
40
+ (isCompleted || isActive) && styles.connectorCompleted,
41
+ ];
42
+
43
+ return (
44
+ <React.Fragment key={index}>
45
+ <Pressable
46
+ style={styles.stepContainer}
47
+ onPress={() => onStepPress?.(index)}>
48
+ <View
49
+ style={[
50
+ styles.circle,
51
+ isCompleted && styles.circleCompleted,
52
+ isActive && styles.circleActive,
53
+ ]}>
54
+ {isCompleted ? (
55
+ <Image source={ImageResources.complete} style={styles.icon} />
56
+ ) : (
57
+ <Text style={styles.stepNumber}>{index + 1}</Text>
58
+ )}
59
+ </View>
60
+ <Text
61
+ style={[
62
+ styles.title,
63
+ (isCompleted || isActive) && styles.titleActive,
64
+ ]}>
65
+ {step.title}
66
+ </Text>
67
+ </Pressable>
68
+ {!isLastStep && <View style={connectorStyle} />}
69
+ </React.Fragment>
70
+ );
71
+ })}
72
+ </View>
73
+ );
74
+ };
75
+
76
+ const createStyles = (
77
+ theme: Theme,
78
+ orientation: 'horizontal' | 'vertical',
79
+ isDarkMode: boolean,
80
+ ) =>
81
+ StyleSheet.create({
82
+ container: {
83
+ flexDirection: orientation === 'horizontal' ? 'row' : 'column',
84
+ alignItems: orientation === 'horizontal' ? 'flex-start' : 'stretch',
85
+ },
86
+ stepContainer: {
87
+ alignItems: 'center',
88
+ flex: orientation === 'horizontal' ? 1 : undefined,
89
+ },
90
+ circle: {
91
+ width: STEP_SIZE,
92
+ height: STEP_SIZE,
93
+ borderRadius: STEP_SIZE / 2,
94
+ borderWidth: 1,
95
+ borderColor: isDarkMode
96
+ ? theme.colors.grayScale_400
97
+ : theme.colors.grayScale_50,
98
+ justifyContent: 'center',
99
+ alignItems: 'center',
100
+ backgroundColor: 'transparent',
101
+ },
102
+ circleCompleted: {
103
+ backgroundColor: PrimaryColors.PlatinateBlue_400,
104
+ borderColor: PrimaryColors.PlatinateBlue_400,
105
+ },
106
+ circleActive: {
107
+ borderColor: PrimaryColors.PlatinateBlue_400,
108
+ },
109
+ icon: {
110
+ width: STEP_SIZE / 2,
111
+ height: STEP_SIZE / 2,
112
+ tintColor: theme.colors.grayScale_0,
113
+ },
114
+ stepNumber: {
115
+ ...theme.text.bodyXLargeRegular,
116
+ color: isDarkMode
117
+ ? theme.colors.grayScale_400
118
+ : theme.colors.grayScale_50,
119
+ },
120
+ title: {
121
+ ...theme.text.bodyMediumRegular,
122
+ marginTop: theme.spacing.small,
123
+ color: isDarkMode
124
+ ? theme.colors.grayScale_400
125
+ : theme.colors.grayScale_50,
126
+ },
127
+ titleActive: {
128
+ color: theme.colors.cetaceanBlue_700,
129
+ },
130
+ connector: {
131
+ backgroundColor: isDarkMode
132
+ ? theme.colors.grayScale_400
133
+ : theme.colors.grayScale_50,
134
+ ...(orientation === 'horizontal'
135
+ ? {
136
+ height: 1,
137
+ flex: 1,
138
+ marginHorizontal: -STEP_SIZE / 4,
139
+ top: STEP_SIZE / 2,
140
+ }
141
+ : {
142
+ width: 1,
143
+ flex: 1,
144
+ marginVertical: -STEP_SIZE / 4,
145
+ left: '50%',
146
+ }),
147
+ },
148
+ connectorCompleted: {
149
+ backgroundColor: PrimaryColors.PlatinateBlue_400,
150
+ },
151
+ });
152
+
153
+ export default Stepper;
@@ -38,7 +38,7 @@ const styles = StyleSheet.create({
38
38
  title: {
39
39
  ...CommonStyles.normalText,
40
40
  textAlign: 'center',
41
- marginBottom: CommonSizes.spacing.xs,
41
+ marginBottom: CommonSizes.spacing.extraSmall,
42
42
  } as TextStyle,
43
43
  description: {
44
44
  ...CommonStyles.normalText,
@@ -1,5 +1,5 @@
1
1
  export function defaultKeyIdExtractor<T extends {id: string | number}>(
2
2
  item: T,
3
3
  ): string {
4
- return item?.id?.toString();
4
+ return item?._id;
5
5
  }
@@ -0,0 +1,47 @@
1
+ import {Linking} from 'react-native';
2
+ import Share, {ShareOptions} from 'react-native-share';
3
+ import {isAndroid, isIos} from '../../core/theme/commonConsts';
4
+ import {
5
+ ShareOpenResult,
6
+ ShareSingleOptions,
7
+ ShareSingleResult,
8
+ } from 'react-native-share/lib/typescript/src/types';
9
+
10
+ export async function showShareDialog(
11
+ options: ShareOptions,
12
+ completedCallback?: (result: ShareOpenResult) => void,
13
+ errorCallback?: (error: Error | unknown) => void,
14
+ ) {
15
+ try {
16
+ const result = await Share.open(options);
17
+ completedCallback?.(result);
18
+ } catch (error: Error | unknown) {
19
+ errorCallback?.(error);
20
+ }
21
+ }
22
+
23
+ export async function showShareSocialDialog(
24
+ options: ShareSingleOptions,
25
+ completedCallback?: (result: ShareSingleResult) => void,
26
+ errorCallback?: (error: Error | unknown) => void,
27
+ ) {
28
+ try {
29
+ const result = await Share.shareSingle(options);
30
+ completedCallback?.(result);
31
+ } catch (error: Error | unknown) {
32
+ errorCallback?.(error);
33
+ }
34
+ }
35
+
36
+ export async function isPackageInstalled(
37
+ androidPackageName?: string,
38
+ iosUrl?: string,
39
+ ): Promise<boolean> {
40
+ if (isAndroid && androidPackageName) {
41
+ return (await Share.isPackageInstalled(androidPackageName)).isInstalled;
42
+ } else if (isIos && iosUrl) {
43
+ return Linking.canOpenURL(iosUrl);
44
+ } else {
45
+ throw new Error('No arguments were given or the platform is not supported');
46
+ }
47
+ }
@@ -23,7 +23,3 @@ export function normalizeAndTrimWhitespace(text: string): string {
23
23
  ?.trimEnd() // Remove trailing whitespace
24
24
  ?.replace(/\s+/g, ' '); // Replace multiple whitespaces with single space
25
25
  }
26
-
27
- export function ensureString(text: string): string {
28
- return text != null ? text : '';
29
- }
@@ -4,8 +4,7 @@
4
4
  * @param error The error caught from an API request
5
5
  * @returns A structured error object with message (as string) and details
6
6
  */
7
-
8
- import {ensureString} from '../../common/helpers/stringsHelpers';
7
+ import {ensureString} from '../utils/stringUtils';
9
8
 
10
9
  export const extractServerError = (error: any) => {
11
10
  let errorObj = {
@@ -1,19 +1,11 @@
1
- import {createSlice, PayloadAction} from '@reduxjs/toolkit';
2
- import {newState} from '../../../common/utils/newState';
3
- import {Languages} from '../../../common/localization/localization';
4
- import {appInitialState, AppInitialEntity} from './appState';
1
+ import {createSlice} from '@reduxjs/toolkit';
2
+
3
+ import {appInitialState} from './appState';
5
4
 
6
5
  export const {reducer: AppReducer, actions} = createSlice({
7
6
  name: 'app',
8
7
  initialState: appInitialState,
9
- reducers: {
10
- setLanguage: (state, action: PayloadAction<Languages>) => {
11
- return newState(state, {
12
- language: action.payload,
13
- isRTL: action.payload === Languages.ar,
14
- });
15
- },
16
- },
8
+ reducers: {},
17
9
  });
18
10
 
19
- export const {setLanguage} = actions;
11
+ export const {} = actions;
@@ -1,11 +1,3 @@
1
- import {Languages} from '../../../common/localization/localization';
1
+ export interface AppInitialEntity {}
2
2
 
3
- export interface AppInitialEntity {
4
- language?: Languages;
5
- isRTL?: boolean;
6
- }
7
-
8
- export const appInitialState: AppInitialEntity = {
9
- language: undefined,
10
- isRTL: false,
11
- };
3
+ export const appInitialState: AppInitialEntity = {};
@@ -1,77 +1,99 @@
1
- export enum BlackColors {
2
- indigoBlue = '#6666FF',
3
- mutedLavender = '#B3B5FF',
4
- tintColor = '#B3B5FF',
5
- mutedLavender30 = 'rgba(184, 186, 255, 0.3)',
6
- balanceBackground = 'rgba(41, 45, 50, 0.8)',
7
- white = '#FFFFFF',
8
- backgroundOpacity = 'rgba(36, 40, 44, 0.8)',
9
- black = '#000000',
10
- background = '#000000',
11
- surface = '#121212',
12
- card = '#1E1E1E',
13
- shadow = '#FFFFFF',
14
- red = '#FB043E',
1
+ export enum PrimaryColors {
2
+ PlatinateBlue_0 = '#E9EDFF',
3
+ PlatinateBlue_25 = '#D3DAFF',
4
+ PlatinateBlue_50 = '#BDC8FF',
5
+ PlatinateBlue_100 = '#A7B5FF',
6
+ PlatinateBlue_200 = '#7C91FF',
7
+ PlatinateBlue_300 = '#506CFF',
8
+ PlatinateBlue_400 = '#2447FF',
9
+ PlatinateBlue_500 = '#1D39CC',
10
+ PlatinateBlue_600 = '#1D39CC',
11
+ PlatinateBlue_700 = '#0E1C66',
12
+ cetaceanBlue_0 = '#4C7CEA',
13
+ cetaceanBlue_25 = '#436FD5',
14
+ cetaceanBlue_50 = '#3B63BF',
15
+ cetaceanBlue_100 = '#3257AA',
16
+ cetaceanBlue_200 = '#223E80',
17
+ cetaceanBlue_300 = '#112655',
18
+ cetaceanBlue_400 = '#000D2B',
19
+ cetaceanBlue_500 = '#000A22',
20
+ cetaceanBlue_600 = '#00081A',
21
+ cetaceanBlue_700 = '#000511',
22
+ strokeDeactive = '#D3DAFF',
15
23
  }
16
24
 
17
- export enum WhiteColors {
18
- indigoBlue = '#6666FF',
19
- mutedLavender = '#B3B5FF',
20
- tintColor = '#6666FF',
21
- mutedLavender30 = 'rgba(184, 186, 255, 0.3)',
22
- balanceBackground = 'rgba(184, 186, 255, 0.3)',
23
- white = '#FFFFFF',
24
- backgroundOpacity = 'rgba(255, 255, 255, 0.7)',
25
- black = '#000000',
26
- background = '#FFFFFF',
27
- surface = '#FFFFFF',
28
- card = '#FFFFFF',
29
- shadow = 'rgba(0, 0, 0, 0.8)',
30
- red = '#FB043E',
25
+ export enum NaturalColors {
26
+ grayScale_0 = '#FAFAFA',
27
+ grayScale_25 = '#A3AAAD',
28
+ grayScale_50 = '#949C9E',
29
+ grayScale_100 = '#858D8F',
30
+ grayScale_200 = '#686F72',
31
+ grayScale_300 = '#4A5254',
32
+ grayScale_400 = '#2D3436',
33
+ grayScale_500 = '#242A2B',
34
+ grayScale_600 = '#1B1F20',
35
+ grayScale_700 = '#121516',
36
+ naturalColor_0 = '#9C97B3',
37
+ naturalColor_25 = '#8E89A4',
38
+ naturalColor_50 = '#7F7B94',
39
+ naturalColor_100 = '#716D85',
40
+ naturalColor_200 = '#555265',
41
+ naturalColor_300 = '#383646',
42
+ naturalColor_400 = '#1C1A27',
43
+ naturalColor_500 = '#16151F',
44
+ naturalColor_600 = '#111017',
45
+ naturalColor_700 = '#0B0A10',
31
46
  }
32
47
 
33
- export enum Colors {
34
- violetLight = '#F3F2FF',
35
- violetLightHover = '#E6E6FF',
36
- violetLightActive = '#C1C0FE',
37
- violetNormal = '#8481FD',
38
- violetNormalHover = '#5250D9',
39
- violetNormalActive = '#3331B8',
40
- violetDark = '#262626',
41
- violetDarkHover = '#1A1994',
42
- violetDarkActive = '#111066',
43
- violetDarker = '#000033',
44
- blueLight = '#F6FCFF',
45
- blueLightHover = '#E9F8FF',
46
- blueLightActive = '#C1E5FF',
47
- blueNormal = '#52BDFF',
48
- blueNormalHover = '#3399D9',
49
- blueNormalActive = '#1A7DB3',
50
- blueDarker = '#262626',
51
- greyLight = '#F9FCFF',
52
- greyLightHover = '#E0E0E0',
53
- greyLightActive = '#BDBDBD',
54
- greyNormal = '#929292',
55
- greyNormalHover = '#666666',
56
- greyNormalActive = '#4D4D4D',
57
- greyDarker = '#262626',
58
- orandeLight = '#FFFAF8',
59
- orandeLightHover = '#FDECE1',
60
- orandeLightActive = '#FBCEB4',
61
- orandeNormal = '#F2565E',
62
- orandeNormalHover = '#CE3C3E',
63
- orandeNormalActive = '#AD3335',
64
- orandeDarker = '#262626',
65
- lightBlueLight = '#FEF7F7',
66
- lightBlueLightHover = '#FCDDDF',
67
- lightBlueLightActive = '#F9AAAF',
68
- lightBlueNormal = '#CE3C3E',
69
- lightBlueNormalHover = '#AD3335',
70
- lightBlueNormalActive = '#8C292B',
71
- lightBlueDarker = '#262626',
72
- red = '#FFFCF1',
73
- green = '#F4FDFB',
74
- background = '#FAFAFA',
75
- white = 'white',
76
- gray = 'gray',
48
+ export enum AlertColors {
49
+ links_0 = '#E8F2FF',
50
+ links_25 = '#D2E4FE',
51
+ links_50 = '#BBD7FE',
52
+ links_100 = '#A5CAFE',
53
+ links_200 = '#77AFFD',
54
+ links_300 = '#4A95FD',
55
+ links_400 = '#1D7AFC',
56
+ links_500 = '#1762CA',
57
+ links_600 = '#114997',
58
+ links_700 = '#0C3165',
59
+ success_0 = '#C6FFE5',
60
+ success_25 = '#8FE6BE',
61
+ success_50 = '#7DDAB0',
62
+ success_100 = '#6CCEA1',
63
+ success_200 = '#48B684',
64
+ success_300 = '#259E67',
65
+ success_400 = '#02864A',
66
+ success_500 = '#026B3B',
67
+ success_600 = '#01502C',
68
+ success_700 = '#01361E',
69
+ warning_0 = '#FFF4E8',
70
+ warning_25 = '#FEE8D1',
71
+ warning_50 = '#FEDDBA',
72
+ warning_100 = '#FDD1A3',
73
+ warning_200 = '#FDBB76',
74
+ warning_300 = '#FCA448',
75
+ warning_400 = '#FB8D1A',
76
+ warning_500 = '#C97115',
77
+ warning_600 = '#975510',
78
+ warning_700 = '#64380A',
79
+ error_0 = '#FDE6EC',
80
+ error_25 = '#FACED8',
81
+ error_50 = '#F8B5C5',
82
+ error_100 = '#F69CB2',
83
+ error_200 = '#F16B8B',
84
+ error_300 = '#ED3965',
85
+ error_400 = '#E8083E',
86
+ error_500 = '#BA0632',
87
+ error_600 = '#8B0525',
88
+ error_700 = '#5D0319',
89
+ discover_0 = '#F1ECF6',
90
+ discover_25 = '#E4D9EC',
91
+ discover_50 = '#D6C5E3',
92
+ discover_100 = '#C8B2D9',
93
+ discover_200 = '#AD8CC7',
94
+ discover_300 = '#9165B4',
95
+ discover_400 = '#763FA1',
96
+ discover_500 = '#5E3281',
97
+ discover_600 = '#472661',
98
+ discover_700 = '#2F1940',
77
99
  }
@@ -2,59 +2,126 @@ import {ISize} from './types';
2
2
 
3
3
  export const CommonSizes = {
4
4
  font: {
5
- extraSmall: 11,
6
- extraSmallPlus: 12,
7
- small: 14,
8
- smallPlus: 15,
9
- medium: 16,
10
- mediumPlus: 18,
11
- extraMedium: 20,
12
- large: 22,
13
- largePlus: 28,
14
- extraLarge: 34,
15
- extraLargePlus: 44,
5
+ // Body Text Sizes
6
+ bodySmall: 12, // Body Small
7
+ bodyMedium: 14, // Body Medium
8
+ bodyLarge: 16, // Body Large
9
+ bodyXLarge: 18, // Body XLarge
10
+
11
+ // Heading Sizes
12
+ heading6: 18, // Heading 6 / Bold / 18px
13
+ heading4: 24, // Heading 4 / Bold / 24px
14
+ heading3: 32, // Heading 3 / Bold / 32px
15
+ heading2: 48, // Heading 2 / Bold / 48px
16
+ heading1: 64, // Heading 1 / Bold / 64px
17
+
18
+ // Legacy support - keeping these for backward compatibility
19
+ extraSmall: 12, // Maps to bodySmall
20
+ extraSmallPlus: 14, // Maps to bodyMedium
21
+ small: 14, // Maps to bodyMedium
22
+ smallPlus: 16, // Maps to bodyLarge
23
+ medium: 16, // Maps to bodyLarge
24
+ mediumPlus: 18, // Maps to bodyXLarge
25
+ extraMedium: 24, // Maps to heading4
26
+ large: 32, // Maps to heading3
27
+ largePlus: 48, // Maps to heading2
28
+ extraLarge: 64, // Maps to heading1
29
+ extraLargePlus: 64, // Maps to heading1
16
30
  } as Readonly<ISize['font']>,
17
31
  letterSpacing: {
18
- extraSmall: 0.07,
32
+ // Default letter spacing for Almarai
33
+ bodySmall: 0,
34
+ bodyMedium: 0,
35
+ bodyLarge: 0,
36
+ bodyXLarge: 0,
37
+ heading6: 0,
38
+ heading4: 0,
39
+ heading3: 0,
40
+ heading2: 0,
41
+ heading1: 0,
42
+
43
+ // Legacy support
44
+ extraSmall: 0,
19
45
  extraSmallPlus: 0,
20
- small: -0.08,
21
- smallPlus: -0.24,
22
- medium: -0.41,
23
- mediumPlus: 0.38,
24
- large: 0.35,
25
- largePlus: 0.36,
26
- extraLarge: 0.37,
27
- extraLargePlus: 0.37,
46
+ small: 0,
47
+ smallPlus: 0,
48
+ medium: 0,
49
+ mediumPlus: 0,
50
+ large: 0,
51
+ largePlus: 0,
52
+ extraLarge: 0,
53
+ extraLargePlus: 0,
28
54
  } as Readonly<ISize['letterSpacing']>,
29
55
  lineHeight: {
30
- extraSmall: 13,
31
- extraSmallPlus: 16,
32
- small: 19,
33
- smallPlus: 20,
34
- medium: 22,
35
- mediumPlus: 25,
36
- large: 28,
37
- largePlus: 34,
38
- extraLarge: 41,
39
- extraLargePlus: 52,
56
+ // Line heights optimized for Almarai's large x-height
57
+ bodySmall: 16, // ~1.33 line height
58
+ bodyMedium: 20, // ~1.43 line height
59
+ bodyLarge: 24, // ~1.5 line height
60
+ bodyXLarge: 26, // ~1.44 line height
61
+ heading6: 24, // ~1.33 line height
62
+ heading4: 32, // ~1.33 line height
63
+ heading3: 40, // ~1.25 line height
64
+ heading2: 56, // ~1.17 line height
65
+ heading1: 72, // ~1.125 line height
66
+
67
+ // Legacy support
68
+ extraSmall: 16,
69
+ extraSmallPlus: 20,
70
+ small: 20,
71
+ smallPlus: 24,
72
+ medium: 24,
73
+ mediumPlus: 26,
74
+ large: 40,
75
+ largePlus: 56,
76
+ extraLarge: 72,
77
+ extraLargePlus: 72,
40
78
  } as Readonly<ISize['lineHeight']>,
41
79
  spacing: {
42
- xs: 4,
43
- sm: 8,
44
- md: 16,
45
- lg: 24,
46
- xl: 32,
80
+ none: 0, // space / 0
81
+ xSmall: 2, // space / 2
82
+ small: 4, // space / 4
83
+ medium: 8, // space / 8
84
+ large: 12, // space / 12
85
+ xLarge: 16, // space / 16
86
+ xxLarge: 24, // space / 24 (2X-Large)
87
+ xxxLarge: 32, // space / 32 (3X-Large)
88
+ xxxxLarge: 48, // space / 48 (4X-Large)
89
+ xxxxxLarge: 64, // space / 64 (5X-Large)
90
+ xxxxxxLarge: 80, // space / 80 (6X-Large)
91
+ full: 100, // space / 100 (Full)
92
+
93
+ // Legacy support - keeping these for backward compatibility
94
+ xs: 4, // Maps to small
95
+ sm: 8, // Maps to medium
96
+ md: 16, // Maps to xLarge
97
+ lg: 24, // Maps to xxLarge
98
+ xl: 32, // Maps to xxxLarge
47
99
  } as Readonly<ISize['spacing']>,
48
100
  borderRadius: {
49
- xs: 4,
50
- sm: 8,
51
- md: 12,
52
- lg: 16,
53
- xl: 24,
101
+ none: 0, // Border / 0
102
+ xSmall: 2, // Border / 2
103
+ small: 4, // Border / 4
104
+ medium: 8, // Border / 8
105
+ large: 12, // Border / 12
106
+ xLarge: 16, // Border / 16
107
+ xxLarge: 24, // Border / 24 (2X-Large)
108
+ full: 1000, // Border / 1000 (Full)
109
+
110
+ // Legacy support - keeping these for backward compatibility
111
+ xs: 4, // Maps to small
112
+ sm: 8, // Maps to medium
113
+ md: 12, // Maps to large
114
+ lg: 16, // Maps to xLarge
115
+ xl: 24, // Maps to xxLarge
54
116
  } as Readonly<ISize['borderRadius']>,
55
117
  borderWidth: {
56
- small: 1,
57
- medium: 2,
58
- large: 3,
118
+ none: 0, // Stroke / 0
119
+ xSmall: 0.5, // Stroke / 0.5
120
+ small: 1, // Stroke / 1
121
+ medium: 1.5, // Stroke / 1.5
122
+ large: 2, // Stroke / 2
123
+
124
+ // Legacy support - keeping these for backward compatibility
125
+ extraSmall: 0.5, // Maps to xSmall
59
126
  } as Readonly<ISize['borderWidth']>,
60
127
  };