rnnovaui 0.11.2 → 0.11.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnnovaui",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "react-native": "src/index.js",
@@ -11,6 +11,7 @@ import {
11
11
  } from "react-native";
12
12
 
13
13
  import { Ionicons } from "@expo/vector-icons";
14
+
14
15
  import Animated, {
15
16
  useAnimatedStyle,
16
17
  useSharedValue,
@@ -107,52 +108,102 @@ function resolveTheme(theme) {
107
108
  ...(theme?.radius || {}),
108
109
  },
109
110
 
110
- sizes: theme?.sizes || {},
111
+ animation: {
112
+ ...(theme?.animation || {}),
113
+ },
111
114
 
115
+ sizes: theme?.sizes || {},
112
116
  typography: theme?.typography || {},
113
-
114
117
  shadows: theme?.shadows || {},
115
-
116
- animation: theme?.animation || {},
117
118
  };
118
119
  }
119
120
 
120
121
  /* -------------------------------------------------------------------------- */
121
- /* Image Helpers */
122
+ /* Image Source */
122
123
  /* -------------------------------------------------------------------------- */
123
124
 
124
- function getImageSource(image) {
125
- if (!image) {
125
+ function resolveImageSource(source) {
126
+ if (!source) {
126
127
  return null;
127
128
  }
128
129
 
129
- if (typeof image === "number") {
130
- return image;
130
+ /*
131
+ * Local image:
132
+ *
133
+ * require("./image.png")
134
+ *
135
+ * React Native gives this as a number.
136
+ */
137
+ if (typeof source === "number") {
138
+ return source;
131
139
  }
132
140
 
133
- if (typeof image === "string") {
141
+ /*
142
+ * Remote image:
143
+ *
144
+ * "https://example.com/image.jpg"
145
+ */
146
+ if (typeof source === "string") {
134
147
  return {
135
- uri: image,
148
+ uri: source,
136
149
  };
137
150
  }
138
151
 
139
- if (typeof image === "object") {
140
- return image;
152
+ /*
153
+ * Remote image:
154
+ *
155
+ * { uri: "https://..." }
156
+ */
157
+ if (typeof source === "object" && source !== null) {
158
+ if (source.uri) {
159
+ return source;
160
+ }
161
+
162
+ /*
163
+ * Also support:
164
+ *
165
+ * { source: require(...) }
166
+ */
167
+ if (source.source) {
168
+ return resolveImageSource(source.source);
169
+ }
170
+
171
+ return source;
141
172
  }
142
173
 
143
174
  return null;
144
175
  }
145
176
 
146
- function normalizeImages(images, fallbackImage) {
147
- if (Array.isArray(images) && images.length > 0) {
148
- return images.filter(Boolean);
149
- }
177
+ /* -------------------------------------------------------------------------- */
178
+ /* Normalize Images */
179
+ /* -------------------------------------------------------------------------- */
180
+
181
+ function normalizeImages({ images, image, restaurant }) {
182
+ let result = [];
150
183
 
151
- if (fallbackImage) {
152
- return [fallbackImage];
184
+ /*
185
+ * Priority:
186
+ *
187
+ * images prop
188
+ * restaurant.images
189
+ * image prop
190
+ * restaurant.image
191
+ */
192
+
193
+ if (Array.isArray(images) && images.length > 0) {
194
+ result = images;
195
+ } else if (
196
+ Array.isArray(restaurant?.images) &&
197
+ restaurant.images.length > 0
198
+ ) {
199
+ result = restaurant.images;
200
+ } else if (image) {
201
+ result = [image];
202
+ } else if (restaurant?.image) {
203
+ result = [restaurant.image];
153
204
  }
154
205
 
155
- return [];
206
+ return result.filter(Boolean).map(resolveImageSource).filter(Boolean);
156
207
  }
157
208
 
158
209
  /* -------------------------------------------------------------------------- */
@@ -165,14 +216,16 @@ function renderIcon({ icon, size = 20, color = "#000000", style }) {
165
216
  }
166
217
 
167
218
  /*
168
- * Already rendered icon:
219
+ * Already rendered:
169
220
  *
170
221
  * <Ionicons name="star" />
171
222
  */
172
223
  if (React.isValidElement(icon)) {
173
224
  return React.cloneElement(icon, {
174
225
  size: icon.props?.size ?? size,
226
+
175
227
  color: icon.props?.color ?? color,
228
+
176
229
  style: [style, icon.props?.style],
177
230
  });
178
231
  }
@@ -180,11 +233,9 @@ function renderIcon({ icon, size = 20, color = "#000000", style }) {
180
233
  /*
181
234
  * Component:
182
235
  *
183
- * icon: Ionicons
236
+ * icon={Ionicons}
184
237
  *
185
- * or
186
- *
187
- * icon: SomeCustomIcon
238
+ * icon={MyCustomIcon}
188
239
  */
189
240
  if (
190
241
  typeof icon === "function" ||
@@ -218,7 +269,7 @@ const RestaurantImage = memo(function RestaurantImage({
218
269
  resizeMode = "cover",
219
270
  style,
220
271
  }) {
221
- const imageSource = getImageSource(source);
272
+ const imageSource = resolveImageSource(source);
222
273
 
223
274
  if (!imageSource) {
224
275
  return (
@@ -232,7 +283,7 @@ const RestaurantImage = memo(function RestaurantImage({
232
283
  style,
233
284
  ]}
234
285
  >
235
- <Ionicons name="restaurant-outline" size={38} color="#B5BAC3" />
286
+ <Ionicons name="restaurant-outline" size={42} color="#AEB4BE" />
236
287
  </View>
237
288
  );
238
289
  }
@@ -242,6 +293,7 @@ const RestaurantImage = memo(function RestaurantImage({
242
293
  source={imageSource}
243
294
  resizeMode={resizeMode}
244
295
  style={[
296
+ styles.image,
245
297
  {
246
298
  width,
247
299
  height,
@@ -253,7 +305,7 @@ const RestaurantImage = memo(function RestaurantImage({
253
305
  });
254
306
 
255
307
  /* -------------------------------------------------------------------------- */
256
- /* Image Carousel */
308
+ /* Restaurant Image Carousel */
257
309
  /* -------------------------------------------------------------------------- */
258
310
 
259
311
  const RestaurantImageCarousel = memo(function RestaurantImageCarousel({
@@ -261,23 +313,40 @@ const RestaurantImageCarousel = memo(function RestaurantImageCarousel({
261
313
  width,
262
314
  height,
263
315
  resizeMode = "cover",
316
+
264
317
  showPagination = true,
318
+
265
319
  paginationStyle,
266
320
  activeDotStyle,
267
321
  inactiveDotStyle,
322
+
268
323
  onImageChange,
269
324
  }) {
270
- const listRef = useRef(null);
271
-
272
325
  const [activeIndex, setActiveIndex] = useState(0);
273
326
 
327
+ const listRef = useRef(null);
328
+
274
329
  const data = Array.isArray(images) ? images : [];
275
330
 
331
+ /*
332
+ * Use the actual layout width of the
333
+ * FlatList rather than the width prop.
334
+ *
335
+ * This fixes width="100%".
336
+ */
276
337
  const handleScroll = useCallback(
277
338
  (event) => {
278
- const offsetX = event.nativeEvent.contentOffset.x;
339
+ const { contentOffset, layoutMeasurement } = event.nativeEvent;
279
340
 
280
- const index = Math.round(offsetX / Math.max(width, 1));
341
+ const pageWidth =
342
+ layoutMeasurement?.width ||
343
+ (typeof width === "number" ? width : SCREEN_WIDTH);
344
+
345
+ if (!pageWidth) {
346
+ return;
347
+ }
348
+
349
+ const index = Math.round(contentOffset.x / pageWidth);
281
350
 
282
351
  if (index < 0 || index >= data.length) {
283
352
  return;
@@ -294,27 +363,43 @@ const RestaurantImageCarousel = memo(function RestaurantImageCarousel({
294
363
  [activeIndex, data.length, onImageChange, width],
295
364
  );
296
365
 
366
+ /*
367
+ * No images.
368
+ */
297
369
  if (data.length === 0) {
298
370
  return <RestaurantImage source={null} width={width} height={height} />;
299
371
  }
300
372
 
373
+ /*
374
+ * One image.
375
+ */
301
376
  if (data.length === 1) {
302
377
  return (
303
- <RestaurantImage
304
- source={data[0]}
305
- width={width}
306
- height={height}
307
- resizeMode={resizeMode}
308
- />
378
+ <View
379
+ style={{
380
+ width: "100%",
381
+ height,
382
+ }}
383
+ >
384
+ <RestaurantImage
385
+ source={data[0]}
386
+ width="100%"
387
+ height={height}
388
+ resizeMode={resizeMode}
389
+ />
390
+ </View>
309
391
  );
310
392
  }
311
393
 
394
+ /*
395
+ * Multiple images.
396
+ */
312
397
  return (
313
398
  <View
314
399
  style={[
315
400
  styles.carouselContainer,
316
401
  {
317
- width,
402
+ width: "100%",
318
403
  height,
319
404
  },
320
405
  ]}
@@ -325,16 +410,27 @@ const RestaurantImageCarousel = memo(function RestaurantImageCarousel({
325
410
  horizontal
326
411
  pagingEnabled
327
412
  showsHorizontalScrollIndicator={false}
413
+ bounces={false}
414
+ nestedScrollEnabled
415
+ directionalLockEnabled
328
416
  scrollEventThrottle={16}
417
+ decelerationRate="fast"
329
418
  onScroll={handleScroll}
330
419
  keyExtractor={(_, index) => `restaurant-image-${index}`}
331
420
  renderItem={({ item }) => (
332
- <RestaurantImage
333
- source={item}
334
- width={width}
335
- height={height}
336
- resizeMode={resizeMode}
337
- />
421
+ <View
422
+ style={{
423
+ width: "100%",
424
+ height,
425
+ }}
426
+ >
427
+ <RestaurantImage
428
+ source={item}
429
+ width="100%"
430
+ height={height}
431
+ resizeMode={resizeMode}
432
+ />
433
+ </View>
338
434
  )}
339
435
  />
340
436
 
@@ -345,7 +441,7 @@ const RestaurantImageCarousel = memo(function RestaurantImageCarousel({
345
441
 
346
442
  return (
347
443
  <View
348
- key={`dot-${index}`}
444
+ key={`pagination-${index}`}
349
445
  style={[
350
446
  styles.paginationDot,
351
447
 
@@ -396,7 +492,6 @@ const RestaurantBadge = memo(function RestaurantBadge({
396
492
  icon,
397
493
  size: fontSize + 3,
398
494
  color,
399
- style: styles.badgeIcon,
400
495
  })
401
496
  : null}
402
497
 
@@ -424,13 +519,21 @@ const RestaurantBadge = memo(function RestaurantBadge({
424
519
  const RestaurantRating = memo(function RestaurantRating({
425
520
  rating,
426
521
  reviewCount,
522
+
427
523
  ratingIcon = "star",
524
+
428
525
  ratingIconSize = 17,
526
+
429
527
  ratingIconColor = "#FFB020",
528
+
430
529
  ratingTextColor,
530
+
431
531
  reviewTextColor,
532
+
432
533
  showReviewCount = true,
534
+
433
535
  style,
536
+
434
537
  textStyle,
435
538
  }) {
436
539
  if (rating === null || rating === undefined || rating === "") {
@@ -492,12 +595,19 @@ const RestaurantRating = memo(function RestaurantRating({
492
595
  const CuisineTags = memo(function CuisineTags({
493
596
  cuisines,
494
597
  maxTags = 3,
598
+
495
599
  backgroundColor,
600
+
496
601
  textColor,
602
+
497
603
  borderRadius = 999,
604
+
498
605
  style,
606
+
499
607
  textStyle,
608
+
500
609
  moreStyle,
610
+
501
611
  moreTextStyle,
502
612
  }) {
503
613
  if (!Array.isArray(cuisines) || cuisines.length === 0) {
@@ -570,14 +680,23 @@ const CuisineTags = memo(function CuisineTags({
570
680
 
571
681
  const RestaurantInfoItem = memo(function RestaurantInfoItem({
572
682
  icon,
683
+
573
684
  iconSize = 23,
685
+
574
686
  iconColor,
687
+
575
688
  value,
689
+
576
690
  label,
691
+
577
692
  valueColor,
693
+
578
694
  labelColor,
695
+
579
696
  style,
697
+
580
698
  valueStyle,
699
+
581
700
  labelStyle,
582
701
  }) {
583
702
  if (!value && !label) {
@@ -628,23 +747,21 @@ const RestaurantInfoItem = memo(function RestaurantInfoItem({
628
747
  });
629
748
 
630
749
  /* -------------------------------------------------------------------------- */
631
- /* Main Restaurant Card */
750
+ /* Main Component */
632
751
  /* -------------------------------------------------------------------------- */
633
752
 
634
753
  export const UIRestaurantCard = memo(function UIRestaurantCard({
635
754
  restaurant = {},
636
755
 
637
- /* -------------------------------------------------------------------- */
638
- /* Interaction */
639
- /* -------------------------------------------------------------------- */
756
+ /* Interaction */
640
757
 
641
758
  onPress,
759
+
642
760
  onLongPress,
761
+
643
762
  disabled = false,
644
763
 
645
- /* -------------------------------------------------------------------- */
646
- /* Animation */
647
- /* -------------------------------------------------------------------- */
764
+ /* Animation */
648
765
 
649
766
  reanimated = false,
650
767
 
@@ -652,9 +769,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
652
769
 
653
770
  pressedScale = 0.985,
654
771
 
655
- /* -------------------------------------------------------------------- */
656
- /* Card */
657
- /* -------------------------------------------------------------------- */
772
+ /* Card */
658
773
 
659
774
  width = SCREEN_WIDTH - 24,
660
775
 
@@ -668,9 +783,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
668
783
 
669
784
  shadow = true,
670
785
 
671
- /* -------------------------------------------------------------------- */
672
- /* Images */
673
- /* -------------------------------------------------------------------- */
786
+ /* Images */
674
787
 
675
788
  image,
676
789
 
@@ -690,9 +803,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
690
803
 
691
804
  onImageChange,
692
805
 
693
- /* -------------------------------------------------------------------- */
694
- /* Logo */
695
- /* -------------------------------------------------------------------- */
806
+ /* Logo */
696
807
 
697
808
  logo,
698
809
 
@@ -708,9 +819,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
708
819
 
709
820
  logoImageStyle,
710
821
 
711
- /* -------------------------------------------------------------------- */
712
- /* Badge */
713
- /* -------------------------------------------------------------------- */
822
+ /* Badge */
714
823
 
715
824
  badge,
716
825
 
@@ -728,9 +837,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
728
837
 
729
838
  badgeTextStyle,
730
839
 
731
- /* -------------------------------------------------------------------- */
732
- /* Favorite */
733
- /* -------------------------------------------------------------------- */
840
+ /* Favorite */
734
841
 
735
842
  showFavorite = true,
736
843
 
@@ -756,9 +863,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
756
863
 
757
864
  favoriteStyle,
758
865
 
759
- /* -------------------------------------------------------------------- */
760
- /* Discount */
761
- /* -------------------------------------------------------------------- */
866
+ /* Discount */
762
867
 
763
868
  discount,
764
869
 
@@ -772,9 +877,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
772
877
 
773
878
  discountTextStyle,
774
879
 
775
- /* -------------------------------------------------------------------- */
776
- /* Restaurant Name */
777
- /* -------------------------------------------------------------------- */
880
+ /* Name */
778
881
 
779
882
  name,
780
883
 
@@ -788,9 +891,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
788
891
 
789
892
  subtitleStyle,
790
893
 
791
- /* -------------------------------------------------------------------- */
792
- /* Rating */
793
- /* -------------------------------------------------------------------- */
894
+ /* Rating */
794
895
 
795
896
  rating,
796
897
 
@@ -814,9 +915,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
814
915
 
815
916
  ratingTextStyle,
816
917
 
817
- /* -------------------------------------------------------------------- */
818
- /* Cuisine */
819
- /* -------------------------------------------------------------------- */
918
+ /* Cuisine */
820
919
 
821
920
  cuisines,
822
921
 
@@ -832,9 +931,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
832
931
 
833
932
  tagTextStyle,
834
933
 
835
- /* -------------------------------------------------------------------- */
836
- /* Delivery */
837
- /* -------------------------------------------------------------------- */
934
+ /* Delivery */
838
935
 
839
936
  deliveryTime,
840
937
 
@@ -848,9 +945,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
848
945
 
849
946
  deliveryLabelStyle,
850
947
 
851
- /* -------------------------------------------------------------------- */
852
- /* Distance */
853
- /* -------------------------------------------------------------------- */
948
+ /* Distance */
854
949
 
855
950
  distance,
856
951
 
@@ -864,9 +959,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
864
959
 
865
960
  distanceLabelStyle,
866
961
 
867
- /* -------------------------------------------------------------------- */
868
- /* Free Delivery */
869
- /* -------------------------------------------------------------------- */
962
+ /* Free delivery */
870
963
 
871
964
  freeDelivery = false,
872
965
 
@@ -888,9 +981,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
888
981
 
889
982
  freeDeliverySubtextStyle,
890
983
 
891
- /* -------------------------------------------------------------------- */
892
- /* Divider */
893
- /* -------------------------------------------------------------------- */
984
+ /* Divider */
894
985
 
895
986
  showDivider = true,
896
987
 
@@ -898,17 +989,13 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
898
989
 
899
990
  dividerStyle,
900
991
 
901
- /* -------------------------------------------------------------------- */
902
- /* Layout */
903
- /* -------------------------------------------------------------------- */
992
+ /* Layout */
904
993
 
905
994
  infoStyle,
906
995
 
907
996
  tagsStyle,
908
997
 
909
- /* -------------------------------------------------------------------- */
910
- /* Custom render */
911
- /* -------------------------------------------------------------------- */
998
+ /* Custom rendering */
912
999
 
913
1000
  renderImage,
914
1001
 
@@ -934,9 +1021,7 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
934
1021
 
935
1022
  renderContent,
936
1023
 
937
- /* -------------------------------------------------------------------- */
938
- /* Press */
939
- /* -------------------------------------------------------------------- */
1024
+ /* Press */
940
1025
 
941
1026
  pressStyle,
942
1027
 
@@ -946,26 +1031,22 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
946
1031
 
947
1032
  children,
948
1033
  }) {
949
- /* -------------------------------------------------------------------- */
950
- /* Theme */
951
- /* -------------------------------------------------------------------- */
952
-
953
1034
  const { theme } = useUITheme();
954
1035
 
955
1036
  const { colors, spacing, radius, animation } = resolveTheme(theme);
956
1037
 
957
- /* -------------------------------------------------------------------- */
958
- /* Spring */
959
- /* -------------------------------------------------------------------- */
1038
+ /* ---------------------------------------------------------------------- */
1039
+ /* Spring */
1040
+ /* ---------------------------------------------------------------------- */
960
1041
 
961
1042
  const resolvedSpring = useMemo(
962
1043
  () => animationSpring ?? animation?.spring ?? DEFAULT_SPRING,
963
1044
  [animationSpring, animation?.spring],
964
1045
  );
965
1046
 
966
- /* -------------------------------------------------------------------- */
967
- /* Restaurant */
968
- /* -------------------------------------------------------------------- */
1047
+ /* ---------------------------------------------------------------------- */
1048
+ /* Restaurant data */
1049
+ /* ---------------------------------------------------------------------- */
969
1050
 
970
1051
  const resolvedName = name ?? restaurant?.name ?? "";
971
1052
 
@@ -989,8 +1070,12 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
989
1070
 
990
1071
  const resolvedImages = useMemo(
991
1072
  () =>
992
- normalizeImages(images ?? restaurant?.images, image ?? restaurant?.image),
993
- [images, image, restaurant?.images, restaurant?.image],
1073
+ normalizeImages({
1074
+ images,
1075
+ image,
1076
+ restaurant,
1077
+ }),
1078
+ [images, image, restaurant],
994
1079
  );
995
1080
 
996
1081
  const resolvedFreeDelivery =
@@ -1002,9 +1087,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1002
1087
  const resolvedFreeDeliverySubtext =
1003
1088
  freeDeliverySubtext ?? restaurant?.freeDeliverySubtext;
1004
1089
 
1005
- /* -------------------------------------------------------------------- */
1006
- /* Resolved theme values */
1007
- /* -------------------------------------------------------------------- */
1090
+ /* ---------------------------------------------------------------------- */
1091
+ /* Colors */
1092
+ /* ---------------------------------------------------------------------- */
1008
1093
 
1009
1094
  const cardRadius = borderRadius ?? radius.card ?? 18;
1010
1095
 
@@ -1030,43 +1115,46 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1030
1115
 
1031
1116
  const resolvedBadgeColor = badgeColor ?? colors.onPrimary ?? "#FFFFFF";
1032
1117
 
1033
- const resolvedFreeDeliveryColor = freeDeliveryColor ?? colors.success;
1118
+ const resolvedFreeDeliveryColor =
1119
+ freeDeliveryColor ?? colors.success ?? "#20A34A";
1034
1120
 
1035
1121
  const resolvedFreeDeliveryIconColor = freeDeliveryIconColor ?? colors.primary;
1036
1122
 
1037
- /* -------------------------------------------------------------------- */
1038
- /* Reanimated */
1039
- /* -------------------------------------------------------------------- */
1123
+ /* ---------------------------------------------------------------------- */
1124
+ /* Reanimated */
1125
+ /* ---------------------------------------------------------------------- */
1040
1126
 
1041
1127
  const scale = useSharedValue(1);
1042
1128
 
1043
- const animatedCardStyle = useAnimatedStyle(() => ({
1044
- transform: [
1045
- {
1046
- scale: scale.value,
1047
- },
1048
- ],
1049
- }));
1129
+ const animatedCardStyle = useAnimatedStyle(() => {
1130
+ return {
1131
+ transform: [
1132
+ {
1133
+ scale: scale.value,
1134
+ },
1135
+ ],
1136
+ };
1137
+ });
1050
1138
 
1051
1139
  const handlePressIn = useCallback(() => {
1052
- if (disabled || !reanimated) {
1140
+ if (!reanimated || disabled) {
1053
1141
  return;
1054
1142
  }
1055
1143
 
1056
1144
  scale.value = withSpring(pressedScale, resolvedSpring);
1057
- }, [disabled, reanimated, pressedScale, resolvedSpring, scale]);
1145
+ }, [reanimated, disabled, pressedScale, resolvedSpring, scale]);
1058
1146
 
1059
1147
  const handlePressOut = useCallback(() => {
1060
- if (disabled || !reanimated) {
1148
+ if (!reanimated || disabled) {
1061
1149
  return;
1062
1150
  }
1063
1151
 
1064
1152
  scale.value = withSpring(1, resolvedSpring);
1065
- }, [disabled, reanimated, resolvedSpring, scale]);
1153
+ }, [reanimated, disabled, resolvedSpring, scale]);
1066
1154
 
1067
- /* -------------------------------------------------------------------- */
1068
- /* Press */
1069
- /* -------------------------------------------------------------------- */
1155
+ /* ---------------------------------------------------------------------- */
1156
+ /* Card press */
1157
+ /* ---------------------------------------------------------------------- */
1070
1158
 
1071
1159
  const handlePress = useCallback(() => {
1072
1160
  if (disabled) {
@@ -1088,9 +1176,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1088
1176
  }
1089
1177
  }, [disabled, onLongPress, restaurant]);
1090
1178
 
1091
- /* -------------------------------------------------------------------- */
1092
- /* Image */
1093
- /* -------------------------------------------------------------------- */
1179
+ /* ---------------------------------------------------------------------- */
1180
+ /* Image */
1181
+ /* ---------------------------------------------------------------------- */
1094
1182
 
1095
1183
  const imageContent =
1096
1184
  typeof renderImage === "function" ? (
@@ -1114,9 +1202,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1114
1202
  />
1115
1203
  );
1116
1204
 
1117
- /* -------------------------------------------------------------------- */
1118
- /* Logo */
1119
- /* -------------------------------------------------------------------- */
1205
+ /* ---------------------------------------------------------------------- */
1206
+ /* Logo */
1207
+ /* ---------------------------------------------------------------------- */
1120
1208
 
1121
1209
  const logoContent =
1122
1210
  showLogo && resolvedLogo ? (
@@ -1150,9 +1238,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1150
1238
  )
1151
1239
  ) : null;
1152
1240
 
1153
- /* -------------------------------------------------------------------- */
1154
- /* Badge */
1155
- /* -------------------------------------------------------------------- */
1241
+ /* ---------------------------------------------------------------------- */
1242
+ /* Badge */
1243
+ /* ---------------------------------------------------------------------- */
1156
1244
 
1157
1245
  const badgeContent =
1158
1246
  showBadge && resolvedBadge ? (
@@ -1174,9 +1262,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1174
1262
  )
1175
1263
  ) : null;
1176
1264
 
1177
- /* -------------------------------------------------------------------- */
1178
- /* Favorite */
1179
- /* -------------------------------------------------------------------- */
1265
+ /* ---------------------------------------------------------------------- */
1266
+ /* Favorite */
1267
+ /* ---------------------------------------------------------------------- */
1180
1268
 
1181
1269
  const favoriteContent = showFavorite ? (
1182
1270
  typeof renderFavorite === "function" ? (
@@ -1221,9 +1309,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1221
1309
  )
1222
1310
  ) : null;
1223
1311
 
1224
- /* -------------------------------------------------------------------- */
1225
- /* Discount */
1226
- /* -------------------------------------------------------------------- */
1312
+ /* ---------------------------------------------------------------------- */
1313
+ /* Discount */
1314
+ /* ---------------------------------------------------------------------- */
1227
1315
 
1228
1316
  const discountContent =
1229
1317
  showDiscount && resolvedDiscount ? (
@@ -1257,9 +1345,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1257
1345
  )
1258
1346
  ) : null;
1259
1347
 
1260
- /* -------------------------------------------------------------------- */
1261
- /* Rating */
1262
- /* -------------------------------------------------------------------- */
1348
+ /* ---------------------------------------------------------------------- */
1349
+ /* Rating */
1350
+ /* ---------------------------------------------------------------------- */
1263
1351
 
1264
1352
  const ratingContent =
1265
1353
  showRating && resolvedRating !== null && resolvedRating !== undefined ? (
@@ -1285,9 +1373,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1285
1373
  )
1286
1374
  ) : null;
1287
1375
 
1288
- /* -------------------------------------------------------------------- */
1289
- /* Tags */
1290
- /* -------------------------------------------------------------------- */
1376
+ /* ---------------------------------------------------------------------- */
1377
+ /* Tags */
1378
+ /* ---------------------------------------------------------------------- */
1291
1379
 
1292
1380
  const tagsContent =
1293
1381
  typeof renderTags === "function" ? (
@@ -1307,9 +1395,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1307
1395
  />
1308
1396
  );
1309
1397
 
1310
- /* -------------------------------------------------------------------- */
1311
- /* Delivery */
1312
- /* -------------------------------------------------------------------- */
1398
+ /* ---------------------------------------------------------------------- */
1399
+ /* Delivery */
1400
+ /* ---------------------------------------------------------------------- */
1313
1401
 
1314
1402
  const deliveryContent =
1315
1403
  typeof renderDelivery === "function" ? (
@@ -1332,9 +1420,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1332
1420
  />
1333
1421
  );
1334
1422
 
1335
- /* -------------------------------------------------------------------- */
1336
- /* Distance */
1337
- /* -------------------------------------------------------------------- */
1423
+ /* ---------------------------------------------------------------------- */
1424
+ /* Distance */
1425
+ /* ---------------------------------------------------------------------- */
1338
1426
 
1339
1427
  const distanceContent =
1340
1428
  typeof renderDistance === "function" ? (
@@ -1357,9 +1445,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1357
1445
  />
1358
1446
  );
1359
1447
 
1360
- /* -------------------------------------------------------------------- */
1361
- /* Free Delivery */
1362
- /* -------------------------------------------------------------------- */
1448
+ /* ---------------------------------------------------------------------- */
1449
+ /* Free Delivery */
1450
+ /* ---------------------------------------------------------------------- */
1363
1451
 
1364
1452
  const freeDeliveryContent = resolvedFreeDelivery ? (
1365
1453
  typeof renderFreeDelivery === "function" ? (
@@ -1409,9 +1497,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1409
1497
  )
1410
1498
  ) : null;
1411
1499
 
1412
- /* -------------------------------------------------------------------- */
1413
- /* Default Content */
1414
- /* -------------------------------------------------------------------- */
1500
+ /* ---------------------------------------------------------------------- */
1501
+ /* Content */
1502
+ /* ---------------------------------------------------------------------- */
1415
1503
 
1416
1504
  const defaultContent = (
1417
1505
  <View
@@ -1511,9 +1599,9 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1511
1599
  })
1512
1600
  : defaultContent;
1513
1601
 
1514
- /* -------------------------------------------------------------------- */
1515
- /* Final Card */
1516
- /* -------------------------------------------------------------------- */
1602
+ /* ---------------------------------------------------------------------- */
1603
+ /* Final Card */
1604
+ /* ---------------------------------------------------------------------- */
1517
1605
 
1518
1606
  return (
1519
1607
  <Animated.View
@@ -1532,71 +1620,79 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1532
1620
  style,
1533
1621
  ]}
1534
1622
  >
1535
- <Pressable
1536
- disabled={disabled}
1537
- onPress={handlePress}
1538
- onLongPress={handleLongPress}
1539
- onPressIn={handlePressIn}
1540
- onPressOut={handlePressOut}
1541
- accessibilityRole="button"
1542
- accessibilityLabel={accessibilityLabel ?? resolvedName}
1543
- accessibilityHint={accessibilityHint}
1544
- style={({ pressed }) => [
1545
- styles.pressable,
1546
-
1623
+ <View
1624
+ style={[
1625
+ styles.cardInner,
1547
1626
  {
1548
1627
  borderRadius: cardRadius,
1549
1628
  },
1550
-
1551
- pressed && !reanimated ? pressStyle : null,
1552
1629
  ]}
1553
1630
  >
1554
- {/* -------------------------------------------------------------- */}
1555
- {/* Image */}
1556
- {/* -------------------------------------------------------------- */}
1631
+ {/* ================================================================ */}
1632
+ {/* IMAGE */}
1633
+ {/* ================================================================ */}
1557
1634
 
1558
1635
  <View
1559
1636
  style={[
1560
1637
  styles.imageSection,
1561
1638
  {
1562
1639
  height: imageHeight,
1640
+
1563
1641
  borderTopLeftRadius: cardRadius,
1642
+
1564
1643
  borderTopRightRadius: cardRadius,
1565
1644
  },
1566
1645
  ]}
1567
1646
  >
1568
1647
  {imageContent}
1569
1648
 
1570
- <View
1571
- pointerEvents="box-none"
1572
- style={[
1573
- styles.imageOverlay,
1574
- {
1575
- borderTopLeftRadius: cardRadius,
1576
- borderTopRightRadius: cardRadius,
1577
- },
1578
- ]}
1579
- >
1649
+ {/* Image overlays */}
1650
+
1651
+ <View pointerEvents="box-none" style={styles.imageOverlay}>
1580
1652
  {/* Badge */}
1653
+
1581
1654
  {badgeContent ? (
1582
1655
  <View style={styles.badgePosition}>{badgeContent}</View>
1583
1656
  ) : null}
1584
1657
 
1585
1658
  {/* Favorite */}
1659
+
1586
1660
  {favoriteContent ? (
1587
1661
  <View style={styles.favoritePosition}>{favoriteContent}</View>
1588
1662
  ) : null}
1589
1663
 
1590
1664
  {/* Discount */}
1665
+
1591
1666
  {discountContent ? (
1592
1667
  <View style={styles.discountPosition}>{discountContent}</View>
1593
1668
  ) : null}
1594
1669
  </View>
1595
1670
  </View>
1596
1671
 
1597
- {/* -------------------------------------------------------------- */}
1598
- {/* Logo */}
1599
- {/* -------------------------------------------------------------- */}
1672
+ {/* ================================================================ */}
1673
+ {/* IMAGE PRESS AREA */}
1674
+ {/* ================================================================ */}
1675
+
1676
+ <Pressable
1677
+ disabled={disabled}
1678
+ onPress={handlePress}
1679
+ onLongPress={handleLongPress}
1680
+ onPressIn={handlePressIn}
1681
+ onPressOut={handlePressOut}
1682
+ accessibilityRole="button"
1683
+ accessibilityLabel={accessibilityLabel ?? resolvedName}
1684
+ accessibilityHint={accessibilityHint}
1685
+ style={[
1686
+ styles.imagePressOverlay,
1687
+ {
1688
+ height: imageHeight,
1689
+ },
1690
+ ]}
1691
+ />
1692
+
1693
+ {/* ================================================================ */}
1694
+ {/* LOGO */}
1695
+ {/* ================================================================ */}
1600
1696
 
1601
1697
  {logoPosition === "overlap" && logoContent ? (
1602
1698
  <View
@@ -1629,12 +1725,22 @@ export const UIRestaurantCard = memo(function UIRestaurantCard({
1629
1725
  </View>
1630
1726
  ) : null}
1631
1727
 
1632
- {/* -------------------------------------------------------------- */}
1633
- {/* Content */}
1634
- {/* -------------------------------------------------------------- */}
1635
-
1636
- {finalContent}
1637
- </Pressable>
1728
+ {/* ================================================================ */}
1729
+ {/* CONTENT PRESS AREA */}
1730
+ {/* ================================================================ */}
1731
+
1732
+ <Pressable
1733
+ disabled={disabled}
1734
+ onPress={handlePress}
1735
+ onLongPress={handleLongPress}
1736
+ onPressIn={handlePressIn}
1737
+ onPressOut={handlePressOut}
1738
+ accessibilityRole="button"
1739
+ style={({ pressed }) => [pressed && !reanimated ? pressStyle : null]}
1740
+ >
1741
+ {finalContent}
1742
+ </Pressable>
1743
+ </View>
1638
1744
  </Animated.View>
1639
1745
  );
1640
1746
  });
@@ -1648,6 +1754,11 @@ const styles = StyleSheet.create({
1648
1754
  overflow: "visible",
1649
1755
  },
1650
1756
 
1757
+ cardInner: {
1758
+ overflow: "hidden",
1759
+ width: "100%",
1760
+ },
1761
+
1651
1762
  cardShadow: {
1652
1763
  shadowColor: "#000000",
1653
1764
 
@@ -1668,10 +1779,6 @@ const styles = StyleSheet.create({
1668
1779
  elevation: 0,
1669
1780
  },
1670
1781
 
1671
- pressable: {
1672
- overflow: "hidden",
1673
- },
1674
-
1675
1782
  /* ---------------------------------------------------------------------- */
1676
1783
  /* Image */
1677
1784
  /* ---------------------------------------------------------------------- */
@@ -1682,9 +1789,8 @@ const styles = StyleSheet.create({
1682
1789
  overflow: "hidden",
1683
1790
  },
1684
1791
 
1685
- imageOverlay: {
1686
- ...StyleSheet.absoluteFillObject,
1687
- zIndex: 10,
1792
+ image: {
1793
+ width: "100%",
1688
1794
  },
1689
1795
 
1690
1796
  imagePlaceholder: {
@@ -1694,17 +1800,44 @@ const styles = StyleSheet.create({
1694
1800
  },
1695
1801
 
1696
1802
  carouselContainer: {
1803
+ width: "100%",
1697
1804
  overflow: "hidden",
1698
1805
  },
1699
1806
 
1807
+ imagePressOverlay: {
1808
+ position: "absolute",
1809
+ left: 0,
1810
+ right: 0,
1811
+ top: 0,
1812
+
1813
+ /*
1814
+ * IMPORTANT:
1815
+ *
1816
+ * This is behind the carousel.
1817
+ * The carousel itself remains touchable.
1818
+ */
1819
+ zIndex: -1,
1820
+ },
1821
+
1822
+ imageOverlay: {
1823
+ ...StyleSheet.absoluteFillObject,
1824
+
1825
+ zIndex: 20,
1826
+
1827
+ pointerEvents: "box-none",
1828
+ },
1829
+
1700
1830
  /* ---------------------------------------------------------------------- */
1701
1831
  /* Badge */
1702
1832
  /* ---------------------------------------------------------------------- */
1703
1833
 
1704
1834
  badgePosition: {
1705
1835
  position: "absolute",
1836
+
1706
1837
  left: 14,
1707
1838
  top: 14,
1839
+
1840
+ zIndex: 30,
1708
1841
  },
1709
1842
 
1710
1843
  badge: {
@@ -1721,11 +1854,9 @@ const styles = StyleSheet.create({
1721
1854
  justifyContent: "center",
1722
1855
  },
1723
1856
 
1724
- badgeIcon: {
1725
- marginRight: 6,
1726
- },
1727
-
1728
1857
  badgeText: {
1858
+ marginLeft: 6,
1859
+
1729
1860
  fontWeight: "700",
1730
1861
  },
1731
1862
 
@@ -1735,8 +1866,11 @@ const styles = StyleSheet.create({
1735
1866
 
1736
1867
  favoritePosition: {
1737
1868
  position: "absolute",
1869
+
1738
1870
  right: 12,
1739
1871
  top: 12,
1872
+
1873
+ zIndex: 30,
1740
1874
  },
1741
1875
 
1742
1876
  favoriteButton: {
@@ -1750,8 +1884,11 @@ const styles = StyleSheet.create({
1750
1884
 
1751
1885
  discountPosition: {
1752
1886
  position: "absolute",
1887
+
1753
1888
  right: 14,
1754
1889
  bottom: 14,
1890
+
1891
+ zIndex: 30,
1755
1892
  },
1756
1893
 
1757
1894
  discountBadge: {
@@ -1768,17 +1905,57 @@ const styles = StyleSheet.create({
1768
1905
 
1769
1906
  discountText: {
1770
1907
  fontSize: 15,
1908
+
1771
1909
  lineHeight: 20,
1910
+
1772
1911
  fontWeight: "700",
1773
1912
  },
1774
1913
 
1914
+ /* ---------------------------------------------------------------------- */
1915
+ /* Pagination */
1916
+ /* ---------------------------------------------------------------------- */
1917
+
1918
+ pagination: {
1919
+ position: "absolute",
1920
+
1921
+ left: 0,
1922
+ right: 0,
1923
+ bottom: 12,
1924
+
1925
+ flexDirection: "row",
1926
+
1927
+ justifyContent: "center",
1928
+
1929
+ alignItems: "center",
1930
+
1931
+ zIndex: 40,
1932
+ },
1933
+
1934
+ paginationDot: {
1935
+ width: 8,
1936
+ height: 8,
1937
+
1938
+ borderRadius: 999,
1939
+
1940
+ marginHorizontal: 4,
1941
+ },
1942
+
1943
+ paginationDotActive: {
1944
+ backgroundColor: "#FFFFFF",
1945
+ },
1946
+
1947
+ paginationDotInactive: {
1948
+ backgroundColor: "rgba(255,255,255,0.5)",
1949
+ },
1950
+
1775
1951
  /* ---------------------------------------------------------------------- */
1776
1952
  /* Logo */
1777
1953
  /* ---------------------------------------------------------------------- */
1778
1954
 
1779
1955
  logoPosition: {
1780
1956
  position: "absolute",
1781
- zIndex: 20,
1957
+
1958
+ zIndex: 50,
1782
1959
  },
1783
1960
 
1784
1961
  logoInline: {
@@ -1817,20 +1994,27 @@ const styles = StyleSheet.create({
1817
1994
 
1818
1995
  titleContainer: {
1819
1996
  flex: 1,
1997
+
1820
1998
  minWidth: 0,
1999
+
1821
2000
  paddingRight: 12,
1822
2001
  },
1823
2002
 
1824
2003
  name: {
1825
2004
  fontSize: 23,
2005
+
1826
2006
  lineHeight: 29,
2007
+
1827
2008
  fontWeight: "700",
1828
2009
  },
1829
2010
 
1830
2011
  subtitle: {
1831
2012
  marginTop: 3,
2013
+
1832
2014
  fontSize: 14,
2015
+
1833
2016
  lineHeight: 20,
2017
+
1834
2018
  fontWeight: "400",
1835
2019
  },
1836
2020
 
@@ -1840,21 +2024,29 @@ const styles = StyleSheet.create({
1840
2024
 
1841
2025
  ratingContainer: {
1842
2026
  flexDirection: "row",
2027
+
1843
2028
  alignItems: "center",
2029
+
1844
2030
  minHeight: 30,
1845
2031
  },
1846
2032
 
1847
2033
  ratingText: {
1848
2034
  marginLeft: 4,
2035
+
1849
2036
  fontSize: 18,
2037
+
1850
2038
  lineHeight: 24,
2039
+
1851
2040
  fontWeight: "700",
1852
2041
  },
1853
2042
 
1854
2043
  reviewCount: {
1855
2044
  marginLeft: 3,
2045
+
1856
2046
  fontSize: 13,
2047
+
1857
2048
  lineHeight: 18,
2049
+
1858
2050
  fontWeight: "400",
1859
2051
  },
1860
2052
 
@@ -1868,7 +2060,9 @@ const styles = StyleSheet.create({
1868
2060
 
1869
2061
  tagsContainer: {
1870
2062
  flexDirection: "row",
2063
+
1871
2064
  alignItems: "center",
2065
+
1872
2066
  overflow: "hidden",
1873
2067
  },
1874
2068
 
@@ -1888,7 +2082,9 @@ const styles = StyleSheet.create({
1888
2082
 
1889
2083
  tagText: {
1890
2084
  fontSize: 14,
2085
+
1891
2086
  lineHeight: 18,
2087
+
1892
2088
  fontWeight: "500",
1893
2089
  },
1894
2090
 
@@ -1898,7 +2094,9 @@ const styles = StyleSheet.create({
1898
2094
 
1899
2095
  divider: {
1900
2096
  width: "100%",
2097
+
1901
2098
  height: StyleSheet.hairlineWidth,
2099
+
1902
2100
  marginVertical: 16,
1903
2101
  },
1904
2102
 
@@ -1930,20 +2128,27 @@ const styles = StyleSheet.create({
1930
2128
 
1931
2129
  infoTextContainer: {
1932
2130
  flex: 1,
2131
+
1933
2132
  minWidth: 0,
2133
+
1934
2134
  marginLeft: 9,
1935
2135
  },
1936
2136
 
1937
2137
  infoValue: {
1938
2138
  fontSize: 16,
2139
+
1939
2140
  lineHeight: 22,
2141
+
1940
2142
  fontWeight: "700",
1941
2143
  },
1942
2144
 
1943
2145
  infoLabel: {
1944
2146
  marginTop: 2,
2147
+
1945
2148
  fontSize: 13,
2149
+
1946
2150
  lineHeight: 18,
2151
+
1947
2152
  fontWeight: "400",
1948
2153
  },
1949
2154
 
@@ -1963,56 +2168,28 @@ const styles = StyleSheet.create({
1963
2168
 
1964
2169
  freeDeliveryTextContainer: {
1965
2170
  flex: 1,
2171
+
1966
2172
  minWidth: 0,
2173
+
1967
2174
  marginLeft: 8,
1968
2175
  },
1969
2176
 
1970
2177
  freeDeliveryText: {
1971
2178
  fontSize: 15,
2179
+
1972
2180
  lineHeight: 21,
2181
+
1973
2182
  fontWeight: "700",
1974
2183
  },
1975
2184
 
1976
2185
  freeDeliverySubtext: {
1977
2186
  marginTop: 2,
1978
- fontSize: 12,
1979
- lineHeight: 17,
1980
- fontWeight: "400",
1981
- },
1982
-
1983
- /* ---------------------------------------------------------------------- */
1984
- /* Pagination */
1985
- /* ---------------------------------------------------------------------- */
1986
2187
 
1987
- pagination: {
1988
- position: "absolute",
1989
-
1990
- left: 0,
1991
- right: 0,
1992
- bottom: 12,
1993
-
1994
- flexDirection: "row",
1995
-
1996
- justifyContent: "center",
1997
-
1998
- alignItems: "center",
1999
- },
2000
-
2001
- paginationDot: {
2002
- width: 8,
2003
- height: 8,
2004
-
2005
- borderRadius: 999,
2006
-
2007
- marginHorizontal: 4,
2008
- },
2188
+ fontSize: 12,
2009
2189
 
2010
- paginationDotActive: {
2011
- backgroundColor: "#FFFFFF",
2012
- },
2190
+ lineHeight: 17,
2013
2191
 
2014
- paginationDotInactive: {
2015
- backgroundColor: "rgba(255,255,255,0.45)",
2192
+ fontWeight: "400",
2016
2193
  },
2017
2194
  });
2018
2195