@hero-design/rn 8.92.0 → 8.92.1-alpha.0

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/es/index.js CHANGED
@@ -13204,11 +13204,17 @@ var setStartOrEndDate = function setStartOrEndDate(_ref2) {
13204
13204
  var date = _ref2.date,
13205
13205
  startDate = _ref2.startDate,
13206
13206
  endDate = _ref2.endDate;
13207
- // Prevent selecting same date when both dates are set
13208
- if (startDate && endDate && (isEqDate(date, startDate) || isEqDate(date, endDate))) {
13207
+ // If both dates are set, selecting start or end date will set the same date
13208
+ if (startDate && endDate && isEqDate(date, startDate)) {
13209
13209
  return {
13210
- startDate: startDate,
13211
- endDate: endDate
13210
+ startDate: date,
13211
+ endDate: date
13212
+ };
13213
+ }
13214
+ if (startDate && endDate && isEqDate(date, endDate)) {
13215
+ return {
13216
+ startDate: date,
13217
+ endDate: date
13212
13218
  };
13213
13219
  }
13214
13220
  // No start date yet - set as start
@@ -13235,13 +13241,10 @@ var setStartOrEndDate = function setStartOrEndDate(_ref2) {
13235
13241
  endDate: undefined
13236
13242
  };
13237
13243
  }
13238
- // Clicking outside range - extend range
13239
- return date < startDate ? {
13244
+ // Clicking outside range - reset range
13245
+ return {
13240
13246
  startDate: date,
13241
- endDate: endDate
13242
- } : {
13243
- startDate: startDate,
13244
- endDate: date
13247
+ endDate: undefined
13245
13248
  };
13246
13249
  };
13247
13250
 
@@ -18710,6 +18713,38 @@ var useKeyboard = function useKeyboard() {
18710
18713
  keyboardHeight: keyboardHeight
18711
18714
  };
18712
18715
  };
18716
+ var deepCompareValue = function deepCompareValue(a, b) {
18717
+ // Handle strict equality first (handles primitives, null, undefined)
18718
+ if (a === b) return true;
18719
+ // Special handling for NaN (NaN !== NaN in JS)
18720
+ if (typeof a === 'number' && typeof b === 'number' && Number.isNaN(a) && Number.isNaN(b)) {
18721
+ return false;
18722
+ }
18723
+ // If either is null or undefined (but they are not strictly equal), return false
18724
+ if (a == null || b == null) return false;
18725
+ // If types don't match, they can't be equal
18726
+ if (_typeof(a) !== _typeof(b)) return false;
18727
+ // Handle array comparison
18728
+ if (Array.isArray(a) && Array.isArray(b)) {
18729
+ if (a.length !== b.length) return false;
18730
+ return a.every(function (val, index) {
18731
+ return deepCompareValue(val, b[index]);
18732
+ });
18733
+ }
18734
+ // If one is array and the other isn't, return false
18735
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
18736
+ // Handle object comparison
18737
+ if (_typeof(a) === 'object' && _typeof(b) === 'object') {
18738
+ var keysA = Object.keys(a);
18739
+ var keysB = Object.keys(b);
18740
+ if (keysA.length !== keysB.length) return false;
18741
+ return keysA.every(function (key) {
18742
+ return keysB.includes(key) && deepCompareValue(a[key], b[key]);
18743
+ });
18744
+ }
18745
+ // If none of the above conditions matched, they're not equal
18746
+ return false;
18747
+ };
18713
18748
 
18714
18749
  var SectionSpacer = index$a(View)(function (_ref) {
18715
18750
  var theme = _ref.theme;
@@ -19038,7 +19073,7 @@ var OptionList = function OptionList(_ref) {
19038
19073
  rest = _objectWithoutProperties(_ref, _excluded$c);
19039
19074
  var renderItem = function renderItem(info) {
19040
19075
  var item = info.item;
19041
- var selected = item.value === value;
19076
+ var selected = deepCompareValue(item.value, value);
19042
19077
  var onItemPress = function onItemPress() {
19043
19078
  if (value === item.value) {
19044
19079
  onPress(null);
@@ -19109,7 +19144,7 @@ var SingleSelect = function SingleSelect(_ref) {
19109
19144
  var sections = toSections(options);
19110
19145
  var flatOptions = toFlatOptions(options);
19111
19146
  var displayedValue = (_flatOptions$find = flatOptions.find(function (opt) {
19112
- return value === opt.value;
19147
+ return deepCompareValue(opt.value, value);
19113
19148
  })) === null || _flatOptions$find === void 0 ? void 0 : _flatOptions$find.text;
19114
19149
  var rawValue = value ? String(value) : undefined;
19115
19150
  var bottomSheetVariant = bottomSheetConfig.variant,
package/lib/index.js CHANGED
@@ -13232,11 +13232,17 @@ var setStartOrEndDate = function setStartOrEndDate(_ref2) {
13232
13232
  var date = _ref2.date,
13233
13233
  startDate = _ref2.startDate,
13234
13234
  endDate = _ref2.endDate;
13235
- // Prevent selecting same date when both dates are set
13236
- if (startDate && endDate && (isEqDate(date, startDate) || isEqDate(date, endDate))) {
13235
+ // If both dates are set, selecting start or end date will set the same date
13236
+ if (startDate && endDate && isEqDate(date, startDate)) {
13237
13237
  return {
13238
- startDate: startDate,
13239
- endDate: endDate
13238
+ startDate: date,
13239
+ endDate: date
13240
+ };
13241
+ }
13242
+ if (startDate && endDate && isEqDate(date, endDate)) {
13243
+ return {
13244
+ startDate: date,
13245
+ endDate: date
13240
13246
  };
13241
13247
  }
13242
13248
  // No start date yet - set as start
@@ -13263,13 +13269,10 @@ var setStartOrEndDate = function setStartOrEndDate(_ref2) {
13263
13269
  endDate: undefined
13264
13270
  };
13265
13271
  }
13266
- // Clicking outside range - extend range
13267
- return date < startDate ? {
13272
+ // Clicking outside range - reset range
13273
+ return {
13268
13274
  startDate: date,
13269
- endDate: endDate
13270
- } : {
13271
- startDate: startDate,
13272
- endDate: date
13275
+ endDate: undefined
13273
13276
  };
13274
13277
  };
13275
13278
 
@@ -18738,6 +18741,38 @@ var useKeyboard = function useKeyboard() {
18738
18741
  keyboardHeight: keyboardHeight
18739
18742
  };
18740
18743
  };
18744
+ var deepCompareValue = function deepCompareValue(a, b) {
18745
+ // Handle strict equality first (handles primitives, null, undefined)
18746
+ if (a === b) return true;
18747
+ // Special handling for NaN (NaN !== NaN in JS)
18748
+ if (typeof a === 'number' && typeof b === 'number' && Number.isNaN(a) && Number.isNaN(b)) {
18749
+ return false;
18750
+ }
18751
+ // If either is null or undefined (but they are not strictly equal), return false
18752
+ if (a == null || b == null) return false;
18753
+ // If types don't match, they can't be equal
18754
+ if (_typeof(a) !== _typeof(b)) return false;
18755
+ // Handle array comparison
18756
+ if (Array.isArray(a) && Array.isArray(b)) {
18757
+ if (a.length !== b.length) return false;
18758
+ return a.every(function (val, index) {
18759
+ return deepCompareValue(val, b[index]);
18760
+ });
18761
+ }
18762
+ // If one is array and the other isn't, return false
18763
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
18764
+ // Handle object comparison
18765
+ if (_typeof(a) === 'object' && _typeof(b) === 'object') {
18766
+ var keysA = Object.keys(a);
18767
+ var keysB = Object.keys(b);
18768
+ if (keysA.length !== keysB.length) return false;
18769
+ return keysA.every(function (key) {
18770
+ return keysB.includes(key) && deepCompareValue(a[key], b[key]);
18771
+ });
18772
+ }
18773
+ // If none of the above conditions matched, they're not equal
18774
+ return false;
18775
+ };
18741
18776
 
18742
18777
  var SectionSpacer = index$a(reactNative.View)(function (_ref) {
18743
18778
  var theme = _ref.theme;
@@ -19066,7 +19101,7 @@ var OptionList = function OptionList(_ref) {
19066
19101
  rest = _objectWithoutProperties(_ref, _excluded$c);
19067
19102
  var renderItem = function renderItem(info) {
19068
19103
  var item = info.item;
19069
- var selected = item.value === value;
19104
+ var selected = deepCompareValue(item.value, value);
19070
19105
  var onItemPress = function onItemPress() {
19071
19106
  if (value === item.value) {
19072
19107
  onPress(null);
@@ -19137,7 +19172,7 @@ var SingleSelect = function SingleSelect(_ref) {
19137
19172
  var sections = toSections(options);
19138
19173
  var flatOptions = toFlatOptions(options);
19139
19174
  var displayedValue = (_flatOptions$find = flatOptions.find(function (opt) {
19140
- return value === opt.value;
19175
+ return deepCompareValue(opt.value, value);
19141
19176
  })) === null || _flatOptions$find === void 0 ? void 0 : _flatOptions$find.text;
19142
19177
  var rawValue = value ? String(value) : undefined;
19143
19178
  var bottomSheetVariant = bottomSheetConfig.variant,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn",
3
- "version": "8.92.0",
3
+ "version": "8.92.1-alpha.0",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -95,5 +95,6 @@
95
95
  "ts-jest": "^29.1.1",
96
96
  "typescript": "^5.7.3"
97
97
  },
98
- "prettier": "prettier-config-hd"
98
+ "prettier": "prettier-config-hd",
99
+ "react-native": "src/index.ts"
99
100
  }
@@ -54,15 +54,18 @@ export const setStartOrEndDate = ({
54
54
  startDate?: Date;
55
55
  endDate?: Date;
56
56
  }) => {
57
- // Prevent selecting same date when both dates are set
58
- if (
59
- startDate &&
60
- endDate &&
61
- (isEqDate(date, startDate) || isEqDate(date, endDate))
62
- ) {
57
+ // If both dates are set, selecting start or end date will set the same date
58
+ if (startDate && endDate && isEqDate(date, startDate)) {
63
59
  return {
64
- startDate,
65
- endDate,
60
+ startDate: date,
61
+ endDate: date,
62
+ };
63
+ }
64
+
65
+ if (startDate && endDate && isEqDate(date, endDate)) {
66
+ return {
67
+ startDate: date,
68
+ endDate: date,
66
69
  };
67
70
  }
68
71
 
@@ -95,14 +98,9 @@ export const setStartOrEndDate = ({
95
98
  };
96
99
  }
97
100
 
98
- // Clicking outside range - extend range
99
- return date < startDate
100
- ? {
101
- startDate: date,
102
- endDate,
103
- }
104
- : {
105
- startDate,
106
- endDate: date,
107
- };
101
+ // Clicking outside range - reset range
102
+ return {
103
+ startDate: date,
104
+ endDate: undefined,
105
+ };
108
106
  };
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import {
3
- SectionListRenderItemInfo,
4
- SectionList,
5
3
  Dimensions,
4
+ SectionList,
5
+ SectionListRenderItemInfo,
6
6
  } from 'react-native';
7
- import Option from './Option';
8
7
  import type { SingleSelectProps } from '.';
8
+ import { BaseOptionListProps } from '../BaseOptionList';
9
+ import { deepCompareValue } from '../helpers';
9
10
  import type { OptionType, SectionType } from '../types';
11
+ import Option from './Option';
10
12
  import { StyledOptionList } from './StyledSingleSelect';
11
- import { BaseOptionListProps } from '../BaseOptionList';
12
13
 
13
14
  type OptionListProps<V, T extends OptionType<V>> = Pick<
14
15
  SingleSelectProps<V, T>,
@@ -37,7 +38,7 @@ const OptionList = <V, T extends OptionType<V>>({
37
38
  }: OptionListProps<V, T>) => {
38
39
  const renderItem = (info: SectionListRenderItemInfo<T, SectionType>) => {
39
40
  const { item } = info;
40
- const selected = item.value === value;
41
+ const selected = deepCompareValue(item.value, value);
41
42
  const onItemPress = () => {
42
43
  if (value === item.value) {
43
44
  onPress(null);
@@ -58,4 +58,28 @@ describe('OptionList', () => {
58
58
  );
59
59
  expect(toJSON()).toMatchSnapshot();
60
60
  });
61
+
62
+ it('render object value correctly', () => {
63
+ const sectionsWithObjectValue = [
64
+ {
65
+ category: 'A',
66
+ data: [{ text: 'Item 1', value: { id: '1', label: 'Item 1' } }],
67
+ },
68
+ {
69
+ category: 'B',
70
+ data: [{ text: 'Item 2', value: { id: '2', label: 'Item 2' } }],
71
+ },
72
+ ];
73
+ const pressFn = jest.fn();
74
+ const { toJSON, getByText } = renderWithTheme(
75
+ <OptionList
76
+ sections={sectionsWithObjectValue}
77
+ value={sectionsWithObjectValue[0].data[0].value}
78
+ onPress={pressFn}
79
+ />
80
+ );
81
+ expect(toJSON()).toMatchSnapshot();
82
+ expect(getByText('Item 1')).toBeTruthy();
83
+ expect(getByText('Item 2')).toBeTruthy();
84
+ });
61
85
  });
@@ -863,6 +863,600 @@ exports[`OptionList render isLoading correctly 1`] = `
863
863
  </View>
864
864
  `;
865
865
 
866
+ exports[`OptionList render object value correctly 1`] = `
867
+ <View
868
+ style={
869
+ {
870
+ "flex": 1,
871
+ }
872
+ }
873
+ >
874
+ <RCTScrollView
875
+ ListFooterComponent={null}
876
+ data={
877
+ [
878
+ {
879
+ "category": "A",
880
+ "data": [
881
+ {
882
+ "text": "Item 1",
883
+ "value": {
884
+ "id": "1",
885
+ "label": "Item 1",
886
+ },
887
+ },
888
+ ],
889
+ },
890
+ {
891
+ "category": "B",
892
+ "data": [
893
+ {
894
+ "text": "Item 2",
895
+ "value": {
896
+ "id": "2",
897
+ "label": "Item 2",
898
+ },
899
+ },
900
+ ],
901
+ },
902
+ ]
903
+ }
904
+ getItem={[Function]}
905
+ getItemCount={[Function]}
906
+ keyExtractor={[Function]}
907
+ onContentSizeChange={[Function]}
908
+ onEndReached={[Function]}
909
+ onEndReachedThreshold={0.1}
910
+ onLayout={[Function]}
911
+ onMomentumScrollBegin={[Function]}
912
+ onMomentumScrollEnd={[Function]}
913
+ onScroll={[Function]}
914
+ onScrollBeginDrag={[Function]}
915
+ onScrollEndDrag={[Function]}
916
+ renderItem={[Function]}
917
+ scrollEventThrottle={0.0001}
918
+ stickyHeaderIndices={
919
+ [
920
+ 0,
921
+ 3,
922
+ ]
923
+ }
924
+ style={
925
+ [
926
+ {
927
+ "paddingHorizontal": 12,
928
+ },
929
+ [
930
+ {
931
+ "paddingBottom": 16,
932
+ },
933
+ {},
934
+ ],
935
+ ]
936
+ }
937
+ >
938
+ <View>
939
+ <View
940
+ onFocusCapture={[Function]}
941
+ onLayout={[Function]}
942
+ style={null}
943
+ >
944
+ <View
945
+ style={
946
+ [
947
+ {
948
+ "alignContent": "center",
949
+ "backgroundColor": "#f6f6f7",
950
+ "display": "flex",
951
+ "flexDirection": "row",
952
+ "justifyContent": "space-between",
953
+ "marginBottom": 16,
954
+ "paddingHorizontal": 16,
955
+ "paddingVertical": 8,
956
+ },
957
+ {
958
+ "marginBottom": 0,
959
+ },
960
+ ]
961
+ }
962
+ themeSize="medium"
963
+ >
964
+ <View
965
+ style={
966
+ [
967
+ {
968
+ "alignItems": "center",
969
+ "display": "flex",
970
+ "flexDirection": "row",
971
+ },
972
+ undefined,
973
+ ]
974
+ }
975
+ >
976
+ <View
977
+ style={
978
+ [
979
+ {
980
+ "marginRight": 12,
981
+ },
982
+ undefined,
983
+ ]
984
+ }
985
+ />
986
+ <Text
987
+ allowFontScaling={false}
988
+ style={
989
+ [
990
+ {
991
+ "color": "#001f23",
992
+ "fontFamily": "BeVietnamPro-Regular",
993
+ "fontSize": 14,
994
+ "letterSpacing": 0.48,
995
+ "lineHeight": 22,
996
+ },
997
+ undefined,
998
+ ]
999
+ }
1000
+ themeIntent="body"
1001
+ themeTypeface="neutral"
1002
+ themeVariant="small"
1003
+ >
1004
+ A
1005
+ </Text>
1006
+ </View>
1007
+ </View>
1008
+ </View>
1009
+ <View
1010
+ onFocusCapture={[Function]}
1011
+ onLayout={[Function]}
1012
+ style={null}
1013
+ >
1014
+ <View>
1015
+ <View
1016
+ highlighted={false}
1017
+ section={
1018
+ {
1019
+ "category": "A",
1020
+ "data": [
1021
+ {
1022
+ "text": "Item 1",
1023
+ "value": {
1024
+ "id": "1",
1025
+ "label": "Item 1",
1026
+ },
1027
+ },
1028
+ ],
1029
+ }
1030
+ }
1031
+ style={
1032
+ [
1033
+ {
1034
+ "marginTop": 12,
1035
+ },
1036
+ undefined,
1037
+ ]
1038
+ }
1039
+ trailingItem={
1040
+ {
1041
+ "text": "Item 1",
1042
+ "value": {
1043
+ "id": "1",
1044
+ "label": "Item 1",
1045
+ },
1046
+ }
1047
+ }
1048
+ trailingSection={
1049
+ {
1050
+ "category": "B",
1051
+ "data": [
1052
+ {
1053
+ "text": "Item 2",
1054
+ "value": {
1055
+ "id": "2",
1056
+ "label": "Item 2",
1057
+ },
1058
+ },
1059
+ ],
1060
+ }
1061
+ }
1062
+ />
1063
+ <View
1064
+ accessibilityState={
1065
+ {
1066
+ "disabled": false,
1067
+ }
1068
+ }
1069
+ accessibilityValue={
1070
+ {
1071
+ "max": undefined,
1072
+ "min": undefined,
1073
+ "now": undefined,
1074
+ "text": undefined,
1075
+ }
1076
+ }
1077
+ accessible={true}
1078
+ focusable={true}
1079
+ onClick={[Function]}
1080
+ onResponderGrant={[Function]}
1081
+ onResponderMove={[Function]}
1082
+ onResponderRelease={[Function]}
1083
+ onResponderTerminate={[Function]}
1084
+ onResponderTerminationRequest={[Function]}
1085
+ onStartShouldSetResponder={[Function]}
1086
+ style={
1087
+ [
1088
+ {
1089
+ "alignItems": "center",
1090
+ "backgroundColor": undefined,
1091
+ "borderRadius": 4,
1092
+ "flexDirection": "row",
1093
+ "opacity": 1,
1094
+ "padding": 16,
1095
+ },
1096
+ undefined,
1097
+ ]
1098
+ }
1099
+ >
1100
+ <View
1101
+ style={
1102
+ [
1103
+ {
1104
+ "flex": 1,
1105
+ },
1106
+ undefined,
1107
+ ]
1108
+ }
1109
+ >
1110
+ <Text
1111
+ allowFontScaling={false}
1112
+ style={
1113
+ [
1114
+ {
1115
+ "color": "#001f23",
1116
+ "fontFamily": "BeVietnamPro-Regular",
1117
+ "fontSize": 16,
1118
+ "letterSpacing": 0.48,
1119
+ "lineHeight": 24,
1120
+ },
1121
+ undefined,
1122
+ ]
1123
+ }
1124
+ themeIntent="body"
1125
+ themeTypeface="neutral"
1126
+ themeVariant="regular"
1127
+ >
1128
+ Item 1
1129
+ </Text>
1130
+ </View>
1131
+ </View>
1132
+ <View
1133
+ highlighted={false}
1134
+ leadingItem={
1135
+ {
1136
+ "text": "Item 1",
1137
+ "value": {
1138
+ "id": "1",
1139
+ "label": "Item 1",
1140
+ },
1141
+ }
1142
+ }
1143
+ section={
1144
+ {
1145
+ "category": "A",
1146
+ "data": [
1147
+ {
1148
+ "text": "Item 1",
1149
+ "value": {
1150
+ "id": "1",
1151
+ "label": "Item 1",
1152
+ },
1153
+ },
1154
+ ],
1155
+ }
1156
+ }
1157
+ style={
1158
+ [
1159
+ {
1160
+ "marginTop": 12,
1161
+ },
1162
+ undefined,
1163
+ ]
1164
+ }
1165
+ trailingSection={
1166
+ {
1167
+ "category": "B",
1168
+ "data": [
1169
+ {
1170
+ "text": "Item 2",
1171
+ "value": {
1172
+ "id": "2",
1173
+ "label": "Item 2",
1174
+ },
1175
+ },
1176
+ ],
1177
+ }
1178
+ }
1179
+ />
1180
+ </View>
1181
+ </View>
1182
+ <View
1183
+ onFocusCapture={[Function]}
1184
+ onLayout={[Function]}
1185
+ style={null}
1186
+ />
1187
+ <View
1188
+ onFocusCapture={[Function]}
1189
+ onLayout={[Function]}
1190
+ style={null}
1191
+ >
1192
+ <View
1193
+ style={
1194
+ [
1195
+ {
1196
+ "alignContent": "center",
1197
+ "backgroundColor": "#f6f6f7",
1198
+ "display": "flex",
1199
+ "flexDirection": "row",
1200
+ "justifyContent": "space-between",
1201
+ "marginBottom": 16,
1202
+ "paddingHorizontal": 16,
1203
+ "paddingVertical": 8,
1204
+ },
1205
+ {
1206
+ "marginBottom": 0,
1207
+ },
1208
+ ]
1209
+ }
1210
+ themeSize="medium"
1211
+ >
1212
+ <View
1213
+ style={
1214
+ [
1215
+ {
1216
+ "alignItems": "center",
1217
+ "display": "flex",
1218
+ "flexDirection": "row",
1219
+ },
1220
+ undefined,
1221
+ ]
1222
+ }
1223
+ >
1224
+ <View
1225
+ style={
1226
+ [
1227
+ {
1228
+ "marginRight": 12,
1229
+ },
1230
+ undefined,
1231
+ ]
1232
+ }
1233
+ />
1234
+ <Text
1235
+ allowFontScaling={false}
1236
+ style={
1237
+ [
1238
+ {
1239
+ "color": "#001f23",
1240
+ "fontFamily": "BeVietnamPro-Regular",
1241
+ "fontSize": 14,
1242
+ "letterSpacing": 0.48,
1243
+ "lineHeight": 22,
1244
+ },
1245
+ undefined,
1246
+ ]
1247
+ }
1248
+ themeIntent="body"
1249
+ themeTypeface="neutral"
1250
+ themeVariant="small"
1251
+ >
1252
+ B
1253
+ </Text>
1254
+ </View>
1255
+ </View>
1256
+ </View>
1257
+ <View
1258
+ onFocusCapture={[Function]}
1259
+ onLayout={[Function]}
1260
+ style={null}
1261
+ >
1262
+ <View>
1263
+ <View
1264
+ highlighted={false}
1265
+ leadingSection={
1266
+ {
1267
+ "category": "A",
1268
+ "data": [
1269
+ {
1270
+ "text": "Item 1",
1271
+ "value": {
1272
+ "id": "1",
1273
+ "label": "Item 1",
1274
+ },
1275
+ },
1276
+ ],
1277
+ }
1278
+ }
1279
+ section={
1280
+ {
1281
+ "category": "B",
1282
+ "data": [
1283
+ {
1284
+ "text": "Item 2",
1285
+ "value": {
1286
+ "id": "2",
1287
+ "label": "Item 2",
1288
+ },
1289
+ },
1290
+ ],
1291
+ }
1292
+ }
1293
+ style={
1294
+ [
1295
+ {
1296
+ "marginTop": 12,
1297
+ },
1298
+ undefined,
1299
+ ]
1300
+ }
1301
+ trailingItem={
1302
+ {
1303
+ "text": "Item 2",
1304
+ "value": {
1305
+ "id": "2",
1306
+ "label": "Item 2",
1307
+ },
1308
+ }
1309
+ }
1310
+ />
1311
+ <View
1312
+ accessibilityState={
1313
+ {
1314
+ "disabled": false,
1315
+ }
1316
+ }
1317
+ accessibilityValue={
1318
+ {
1319
+ "max": undefined,
1320
+ "min": undefined,
1321
+ "now": undefined,
1322
+ "text": undefined,
1323
+ }
1324
+ }
1325
+ accessible={true}
1326
+ focusable={true}
1327
+ onClick={[Function]}
1328
+ onResponderGrant={[Function]}
1329
+ onResponderMove={[Function]}
1330
+ onResponderRelease={[Function]}
1331
+ onResponderTerminate={[Function]}
1332
+ onResponderTerminationRequest={[Function]}
1333
+ onStartShouldSetResponder={[Function]}
1334
+ style={
1335
+ [
1336
+ {
1337
+ "alignItems": "center",
1338
+ "backgroundColor": "#ffffff",
1339
+ "borderRadius": 4,
1340
+ "flexDirection": "row",
1341
+ "opacity": 1,
1342
+ "padding": 16,
1343
+ },
1344
+ undefined,
1345
+ ]
1346
+ }
1347
+ >
1348
+ <View
1349
+ style={
1350
+ [
1351
+ {
1352
+ "flex": 1,
1353
+ },
1354
+ undefined,
1355
+ ]
1356
+ }
1357
+ >
1358
+ <Text
1359
+ allowFontScaling={false}
1360
+ style={
1361
+ [
1362
+ {
1363
+ "color": "#001f23",
1364
+ "fontFamily": "BeVietnamPro-Regular",
1365
+ "fontSize": 16,
1366
+ "letterSpacing": 0.48,
1367
+ "lineHeight": 24,
1368
+ },
1369
+ undefined,
1370
+ ]
1371
+ }
1372
+ themeIntent="body"
1373
+ themeTypeface="neutral"
1374
+ themeVariant="regular"
1375
+ >
1376
+ Item 2
1377
+ </Text>
1378
+ </View>
1379
+ </View>
1380
+ <View
1381
+ highlighted={false}
1382
+ leadingItem={
1383
+ {
1384
+ "text": "Item 2",
1385
+ "value": {
1386
+ "id": "2",
1387
+ "label": "Item 2",
1388
+ },
1389
+ }
1390
+ }
1391
+ leadingSection={
1392
+ {
1393
+ "category": "A",
1394
+ "data": [
1395
+ {
1396
+ "text": "Item 1",
1397
+ "value": {
1398
+ "id": "1",
1399
+ "label": "Item 1",
1400
+ },
1401
+ },
1402
+ ],
1403
+ }
1404
+ }
1405
+ section={
1406
+ {
1407
+ "category": "B",
1408
+ "data": [
1409
+ {
1410
+ "text": "Item 2",
1411
+ "value": {
1412
+ "id": "2",
1413
+ "label": "Item 2",
1414
+ },
1415
+ },
1416
+ ],
1417
+ }
1418
+ }
1419
+ style={
1420
+ [
1421
+ {
1422
+ "marginTop": 12,
1423
+ },
1424
+ undefined,
1425
+ ]
1426
+ }
1427
+ />
1428
+ </View>
1429
+ </View>
1430
+ <View
1431
+ onFocusCapture={[Function]}
1432
+ onLayout={[Function]}
1433
+ style={null}
1434
+ />
1435
+ </View>
1436
+ </RCTScrollView>
1437
+ <View
1438
+ pointerEvents="box-none"
1439
+ position="bottom"
1440
+ style={
1441
+ [
1442
+ {
1443
+ "bottom": 0,
1444
+ "elevation": 9999,
1445
+ "flexDirection": "column-reverse",
1446
+ "left": 0,
1447
+ "paddingHorizontal": 24,
1448
+ "paddingVertical": 16,
1449
+ "position": "absolute",
1450
+ "right": 0,
1451
+ "top": 0,
1452
+ },
1453
+ undefined,
1454
+ ]
1455
+ }
1456
+ />
1457
+ </View>
1458
+ `;
1459
+
866
1460
  exports[`OptionList renders correctly 1`] = `
867
1461
  <View
868
1462
  style={
@@ -267,6 +267,32 @@ describe('rendering', () => {
267
267
  expect(getByText('Monday')).toBeTruthy();
268
268
  expect(toJSON()).toMatchSnapshot();
269
269
  });
270
+
271
+ it('renders correct value when value is an object', () => {
272
+ const optionsWithObjectValue = [
273
+ {
274
+ value: { id: '1', label: 'Item 1' },
275
+ text: 'Option with object value 1',
276
+ },
277
+ {
278
+ value: { id: '2', label: 'Item 2' },
279
+ text: 'Option with object value 2',
280
+ },
281
+ ];
282
+ const { getByText, getByTestId } = renderWithTheme(
283
+ <SingleSelect
284
+ options={optionsWithObjectValue}
285
+ value={optionsWithObjectValue[0].value}
286
+ onConfirm={jest.fn()}
287
+ label="Select an item"
288
+ />
289
+ );
290
+
291
+ fireEvent.press(getByTestId('text-input'));
292
+
293
+ expect(getByText('Option with object value 1')).toBeVisible();
294
+ expect(getByText('Option with object value 2')).toBeVisible();
295
+ });
270
296
  });
271
297
 
272
298
  describe('behavior', () => {
@@ -7,6 +7,7 @@ import { TouchableOpacity, View } from 'react-native';
7
7
  import BottomSheet from '../../BottomSheet';
8
8
  import TextInput from '../../TextInput';
9
9
  import {
10
+ deepCompareValue,
10
11
  getScrollParams,
11
12
  toFlatOptions,
12
13
  toSections,
@@ -66,7 +67,10 @@ const SingleSelect = <V, T extends OptionType<V>>({
66
67
  const sectionListRef = useRef<SectionList<T, SectionType>>(null);
67
68
  const sections = toSections(options);
68
69
  const flatOptions = toFlatOptions(options);
69
- const displayedValue = flatOptions.find((opt) => value === opt.value)?.text;
70
+ const displayedValue = flatOptions.find((opt) =>
71
+ deepCompareValue(opt.value, value)
72
+ )?.text;
73
+
70
74
  const rawValue = value ? String(value) : undefined;
71
75
  const { variant: bottomSheetVariant, header: bottomSheetHeader } =
72
76
  bottomSheetConfig;
@@ -1,4 +1,5 @@
1
1
  import {
2
+ deepCompareValue,
2
3
  getScrollParams,
3
4
  isSections,
4
5
  toFlatOptions,
@@ -72,3 +73,38 @@ describe('getScrollParams', () => {
72
73
  });
73
74
  });
74
75
  });
76
+
77
+ describe('deepCompareValue', () => {
78
+ it.each`
79
+ a | b | expected
80
+ ${1} | ${1} | ${true}
81
+ ${'test'} | ${'test'} | ${true}
82
+ ${true} | ${true} | ${true}
83
+ ${null} | ${null} | ${true}
84
+ ${undefined} | ${undefined} | ${true}
85
+ ${1} | ${2} | ${false}
86
+ ${'test'} | ${'other'} | ${false}
87
+ ${true} | ${false} | ${false}
88
+ ${null} | ${undefined} | ${false}
89
+ ${NaN} | ${NaN} | ${false}
90
+ ${1} | ${NaN} | ${false}
91
+ ${[1, 2, 3]} | ${[1, 2, 3]} | ${true}
92
+ ${['a', 'b']} | ${['a', 'b']} | ${true}
93
+ ${[]} | ${[]} | ${true}
94
+ ${[1, 2]} | ${[1, 2, 3]} | ${false}
95
+ ${[1, 2]} | ${[2, 1]} | ${false}
96
+ ${[1, [2, 3]]} | ${[1, [2, 3]]} | ${true}
97
+ ${[1, [2, 3]]} | ${[1, [2, 4]]} | ${false}
98
+ ${{ a: 1, b: 2 }} | ${{ a: 1, b: 2 }} | ${true}
99
+ ${{}} | ${{}} | ${true}
100
+ ${{ a: 1 }} | ${{ a: 2 }} | ${false}
101
+ ${{ a: 1 }} | ${{ b: 1 }} | ${false}
102
+ ${{ a: 1 }} | ${{ a: 1, b: 2 }} | ${false}
103
+ ${{ a: { b: 1 } }} | ${{ a: { b: 1 } }} | ${true}
104
+ ${{ a: { b: 1 } }} | ${{ a: { b: 2 } }} | ${false}
105
+ ${1} | ${'1'} | ${false}
106
+ ${[]} | ${{}} | ${false}
107
+ `('should compare $a and $b correctly', ({ a, b, expected }) => {
108
+ expect(deepCompareValue(a, b)).toBe(expected);
109
+ });
110
+ });
@@ -99,3 +99,48 @@ export const useKeyboard = () => {
99
99
 
100
100
  return { isKeyboardVisible, keyboardHeight };
101
101
  };
102
+
103
+ export const deepCompareValue = <V,>(a: V, b: V): boolean => {
104
+ // Handle strict equality first (handles primitives, null, undefined)
105
+ if (a === b) return true;
106
+
107
+ // Special handling for NaN (NaN !== NaN in JS)
108
+ if (
109
+ typeof a === 'number' &&
110
+ typeof b === 'number' &&
111
+ Number.isNaN(a) &&
112
+ Number.isNaN(b)
113
+ ) {
114
+ return false;
115
+ }
116
+
117
+ // If either is null or undefined (but they are not strictly equal), return false
118
+ if (a == null || b == null) return false;
119
+
120
+ // If types don't match, they can't be equal
121
+ if (typeof a !== typeof b) return false;
122
+
123
+ // Handle array comparison
124
+ if (Array.isArray(a) && Array.isArray(b)) {
125
+ if (a.length !== b.length) return false;
126
+ return a.every((val, index) => deepCompareValue(val, b[index]));
127
+ }
128
+
129
+ // If one is array and the other isn't, return false
130
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
131
+
132
+ // Handle object comparison
133
+ if (typeof a === 'object' && typeof b === 'object') {
134
+ const keysA = Object.keys(a) as (keyof V)[];
135
+ const keysB = Object.keys(b) as (keyof V)[];
136
+
137
+ if (keysA.length !== keysB.length) return false;
138
+
139
+ return keysA.every(
140
+ (key) => keysB.includes(key) && deepCompareValue(a[key], b[key])
141
+ );
142
+ }
143
+
144
+ // If none of the above conditions matched, they're not equal
145
+ return false;
146
+ };
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { SectionList } from 'react-native';
3
3
  import type { SingleSelectProps } from '.';
4
- import type { OptionType, SectionType } from '../types';
5
4
  import { BaseOptionListProps } from '../BaseOptionList';
5
+ import type { OptionType, SectionType } from '../types';
6
6
  type OptionListProps<V, T extends OptionType<V>> = Pick<SingleSelectProps<V, T>, 'keyExtractor' | 'loading' | 'onEndReached' | 'onQueryChange' | 'value' | 'renderOption'> & {
7
7
  onPress: (value: V | null) => void;
8
8
  sectionListRef?: React.RefObject<SectionList<T, SectionType>>;
@@ -12,3 +12,4 @@ export declare const useKeyboard: () => {
12
12
  isKeyboardVisible: boolean;
13
13
  keyboardHeight: number;
14
14
  };
15
+ export declare const deepCompareValue: <V>(a: V, b: V) => boolean;
@@ -0,0 +1,9 @@
1
+ import type { ShadowPalette } from './types';
2
+ declare const getShadows: (shadowPalette: ShadowPalette) => {
3
+ default: import("./types").ShadowStyles;
4
+ cardDrawer: import("./types").ShadowStyles;
5
+ tabBar: import("./types").ShadowStyles;
6
+ };
7
+ type Shadows = ReturnType<typeof getShadows>;
8
+ export { getShadows };
9
+ export type { Shadows };
@@ -0,0 +1,3 @@
1
+ import type { ShadowPalette } from './types';
2
+ declare const swagLightShadowPalette: ShadowPalette;
3
+ export default swagLightShadowPalette;
@@ -0,0 +1,3 @@
1
+ import type { ShadowPalette } from './types';
2
+ declare const swagLightJobsShadowPalette: ShadowPalette;
3
+ export default swagLightJobsShadowPalette;
@@ -0,0 +1,16 @@
1
+ import type { SystemPalette } from '.';
2
+ declare const getShadows: (systemPalette: SystemPalette) => {
3
+ default: {
4
+ shadowOffset: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ shadowColor: string;
9
+ shadowOpacity: number;
10
+ shadowRadius: number;
11
+ elevation: number;
12
+ };
13
+ };
14
+ type Shadows = ReturnType<typeof getShadows>;
15
+ export { getShadows };
16
+ export type { Shadows };
@@ -1,13 +0,0 @@
1
- (node:3019) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
2
- (Use `node --trace-warnings ...` to show where the warning was created)
3
- 
4
- src/index.ts → lib/index.js, es/index.js...
5
- (!) [plugin replace] @rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`.
6
- (!) [plugin typescript] src/components/RichTextEditor/__tests__/RichTextEditor.spec.tsx (61:35): @rollup/plugin-typescript TS2307: Cannot find module '../../../../types' or its corresponding type declarations.
7
- /home/runner/work/hero-design/hero-design/packages/rn/src/components/RichTextEditor/__tests__/RichTextEditor.spec.tsx:61:35
8
- 
9
- 61 import { RichTextEditorRef } from "../../../../types";
10
-    ~~~~~~~~~~~~~~~~~~~
11
- 
12
- (!) [plugin node-resolve] preferring built-in module 'events' over local alternative at '/home/runner/work/hero-design/hero-design/node_modules/events/events.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning.or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.
13
- created lib/index.js, es/index.js in 52.9s