react-native-molecules 0.5.0-beta.22 → 0.5.0-beta.24

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 (82) hide show
  1. package/components/Accordion/Accordion.tsx +1 -1
  2. package/components/Accordion/AccordionItem.tsx +1 -1
  3. package/components/Button/Button.tsx +3 -1
  4. package/components/Checkbox/Checkbox.tsx +2 -1
  5. package/components/DateField/useDateFieldState.ts +2 -2
  6. package/components/DatePicker/DatePickerProvider.tsx +1 -1
  7. package/components/DatePicker/utils.ts +2 -0
  8. package/components/DatePickerInline/DatePickerInline.tsx +1 -1
  9. package/components/DatePickerInline/DatePickerInlineBase.tsx +1 -1
  10. package/components/DatePickerInline/Day.tsx +1 -1
  11. package/components/DatePickerInline/MonthPicker.tsx +24 -40
  12. package/components/DatePickerInline/Swiper.tsx +1 -1
  13. package/components/DatePickerInline/SwiperUtils.ts +1 -1
  14. package/components/DatePickerInline/YearPicker.tsx +44 -79
  15. package/components/DatePickerInline/dateUtils.tsx +1 -1
  16. package/components/DatePickerInline/store.tsx +2 -1
  17. package/components/Divider/index.tsx +2 -3
  18. package/components/ElementGroup/ElementGroup.tsx +1 -1
  19. package/components/FilePicker/FilePicker.tsx +1 -1
  20. package/components/Icon/iconFactory.tsx +2 -1
  21. package/components/IconButton/IconButton.tsx +39 -13
  22. package/components/IconButton/index.tsx +1 -0
  23. package/components/IconButton/types.ts +2 -0
  24. package/components/List/List.tsx +156 -387
  25. package/components/List/context.tsx +4 -5
  26. package/components/List/index.ts +0 -1
  27. package/components/List/types.ts +77 -109
  28. package/components/List/utils.ts +4 -37
  29. package/components/Menu/Menu.tsx +13 -30
  30. package/components/Menu/index.tsx +0 -2
  31. package/components/Popover/Popover.tsx +7 -10
  32. package/components/Popover/PopoverRoot.tsx +6 -20
  33. package/components/Popover/common.ts +4 -0
  34. package/components/Popover/index.ts +2 -8
  35. package/components/Popover/usePlatformMeasure.ts +4 -2
  36. package/components/Portal/Portal.tsx +1 -2
  37. package/components/RadioButton/RadioButtonGroup.tsx +1 -2
  38. package/components/Rating/Rating.tsx +1 -1
  39. package/components/Select/Select.tsx +304 -71
  40. package/components/Select/context.tsx +30 -3
  41. package/components/Select/index.ts +20 -2
  42. package/components/Select/types.ts +43 -25
  43. package/components/Select/utils.ts +18 -4
  44. package/components/Switch/Switch.ios.tsx +1 -1
  45. package/components/Switch/Switch.tsx +2 -1
  46. package/components/Tabs/Tabs.tsx +2 -2
  47. package/components/TextInput/TextInput.tsx +4 -3
  48. package/components/TimePicker/AnalogClock.tsx +1 -1
  49. package/components/TimePicker/TimeInputs.tsx +1 -1
  50. package/components/TimePicker/TimePicker.tsx +1 -1
  51. package/components/TimePicker/TimePickerModal.tsx +1 -1
  52. package/components/Tooltip/Tooltip.tsx +1 -1
  53. package/components/TouchableRipple/TouchableRipple.tsx +76 -152
  54. package/hocs/index.tsx +1 -1
  55. package/hocs/withKeyboardAccessibility.tsx +2 -3
  56. package/hooks/index.tsx +2 -6
  57. package/hooks/useContrastColor.ts +1 -2
  58. package/hooks/useFilePicker.tsx +1 -1
  59. package/hooks/useHandleNumberFormat.tsx +2 -2
  60. package/hooks/useMediaQuery.tsx +1 -2
  61. package/package.json +5 -28
  62. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +1 -1
  63. package/shortcuts-manager/ShortcutsManager/utils.tsx +1 -1
  64. package/shortcuts-manager/useSetScopes/useSetScopes.tsx +1 -1
  65. package/shortcuts-manager/useShortcut/useShortcut.tsx +1 -1
  66. package/utils/extractTextStyles.ts +1 -2
  67. package/utils/formatNumberWithMask/formatNumberWithMask.ts +2 -1
  68. package/utils/index.ts +0 -3
  69. package/utils/normalizeToNumberString/normalizeToNumberString.ts +1 -1
  70. package/context-bridge/index.tsx +0 -87
  71. package/fast-context/index.tsx +0 -190
  72. package/hocs/typedMemo.tsx +0 -5
  73. package/hooks/useControlledValue.tsx +0 -84
  74. package/hooks/useLatest.tsx +0 -9
  75. package/hooks/useMergedRefs.ts +0 -14
  76. package/hooks/usePrevious.ts +0 -13
  77. package/hooks/useToggle.tsx +0 -24
  78. package/hooks/useWhatHasUpdated.tsx +0 -48
  79. package/utils/color.ts +0 -22
  80. package/utils/compare/index.ts +0 -54
  81. package/utils/lodash.ts +0 -121
  82. package/utils/repository.ts +0 -53
@@ -1,68 +1,35 @@
1
- import {
2
- type ComponentType,
3
- memo,
4
- type RefObject,
5
- useCallback,
6
- useMemo,
7
- useRef,
8
- useState,
9
- } from 'react';
10
- import { ScrollView, type StyleProp, View, type ViewStyle } from 'react-native';
1
+ import { useControlledValue, useLatest } from '@react-native-molecules/utils/hooks';
2
+ import { memo, useCallback, useMemo } from 'react';
3
+ import { ScrollView, type StyleProp, type ViewStyle } from 'react-native';
11
4
 
12
5
  import { typedMemo } from '../../hocs';
13
- import { useActionState, useControlledValue, useLatest } from '../../hooks';
14
- import type { WithElements } from '../../types';
6
+ import { useActionState } from '../../hooks';
15
7
  import { resolveStateVariant } from '../../utils';
16
- import { Divider } from '../Divider';
17
- import { Icon } from '../Icon';
18
- import { IconButton } from '../IconButton';
19
8
  import { StateLayer } from '../StateLayer';
20
- import { Text } from '../Text';
21
- import { TextInput, type TextInputHandles, type TextInputProps } from '../TextInput';
22
- import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
9
+ import { TouchableRipple } from '../TouchableRipple';
23
10
  import { ListContextProvider, useListContextValue } from './context';
24
11
  import type {
25
12
  DefaultListItemT,
26
13
  ListContentProps,
27
14
  ListContextValue,
28
- ListGroupProps,
29
- ListItemOptionProps,
15
+ ListItemId,
16
+ ListItemProps,
30
17
  ListProps,
31
- ListSearchInputProps,
32
18
  } from './types';
33
- import { listItemStyles, listStyles } from './utils';
34
-
35
- const emptyArr: unknown[] = [];
36
-
37
- type InternalListItemProps = Omit<TouchableRippleProps, 'children'> &
38
- WithElements<React.ReactNode | ((renderArgs: { hovered: boolean }) => React.ReactNode)> & {
39
- ref?: RefObject<any>;
40
- hovered?: boolean;
41
- children: React.ReactNode;
42
- style?: StyleProp<ViewStyle>;
43
- divider?: boolean;
44
- variant?: 'default' | 'menuItem';
45
- selected?: boolean;
46
- hoverable?: boolean;
47
- contentStyle?: StyleProp<ViewStyle>;
48
- };
49
-
50
- const _InternalListItem = ({
19
+ import { listItemStyles } from './utils';
20
+
21
+ const _ListItemBase = ({
51
22
  ref,
52
- left,
53
- right,
54
23
  children,
55
24
  style: styleProp,
56
25
  disabled = false,
57
- divider = false,
58
- variant = 'default',
26
+ variant = 'menuItem',
59
27
  selected = false,
60
28
  onPress,
61
29
  hoverable: hoverableProp = false,
62
30
  hovered: hoveredProp = false,
63
- contentStyle: contentStyleProp,
64
31
  ...props
65
- }: InternalListItemProps) => {
32
+ }: ListItemProps) => {
66
33
  const {
67
34
  hovered: _hovered,
68
35
  focused,
@@ -77,63 +44,140 @@ const _InternalListItem = ({
77
44
  disabled,
78
45
  hovered: hoverable && hovered,
79
46
  focused,
80
- }) as any;
47
+ });
81
48
 
82
49
  listItemStyles.useVariants({
83
- state,
84
- variant: variant as any,
50
+ state: state as never,
51
+ variant: variant as never,
85
52
  });
86
53
 
87
- const {
88
- containerStyles,
89
- innerContainerStyle,
90
- contentStyle,
91
- leftElementStyle,
92
- rightElementStyle,
93
- } = useMemo(() => {
94
- const { innerContainer, content, leftElement, rightElement } = listItemStyles;
95
- return {
96
- containerStyles: [listItemStyles.root, styleProp],
97
- innerContainerStyle: innerContainer,
98
- contentStyle: content,
99
- leftElementStyle: leftElement,
100
- rightElementStyle: rightElement,
101
- };
54
+ const containerStyles = useMemo(
55
+ () => [listItemStyles.root, styleProp],
102
56
  // eslint-disable-next-line react-hooks/exhaustive-deps
103
- }, [styleProp, state, variant]);
57
+ [styleProp, state, variant],
58
+ );
104
59
 
105
60
  return (
106
61
  <TouchableRipple
107
62
  {...props}
108
- style={containerStyles}
63
+ style={containerStyles as StyleProp<ViewStyle>}
109
64
  disabled={disabled}
110
65
  onPress={onPress}
111
66
  ref={actionsRef}>
112
67
  <>
113
- <View style={innerContainerStyle}>
114
- {left ? (
115
- <View style={leftElementStyle}>
116
- {typeof left === 'function' ? left({ hovered }) : left}
117
- </View>
118
- ) : null}
119
- <View style={[contentStyle, contentStyleProp]}>{children}</View>
120
- {right ? (
121
- <View style={rightElementStyle}>
122
- {typeof right === 'function' ? right({ hovered }) : right}
123
- </View>
124
- ) : null}
125
- </View>
126
- {divider ? <Divider /> : null}
68
+ {children}
127
69
  <StateLayer style={listItemStyles.stateLayer} />
128
70
  </>
129
71
  </TouchableRipple>
130
72
  );
131
73
  };
132
74
 
133
- const ListItem = memo(_InternalListItem);
75
+ const ListItemBase = memo(_ListItemBase);
76
+
77
+ const _ListItemSelectable = <Option extends object = DefaultListItemT>({
78
+ value,
79
+ children,
80
+ onPress,
81
+ onBeforeToggle,
82
+ disabled: itemDisabledProp = false,
83
+ shouldToggleOnPress = true,
84
+ accessibilityRole,
85
+ accessibilityState,
86
+ variant,
87
+ ...rest
88
+ }: ListItemProps<Option> & { value: ListItemId }) => {
89
+ const {
90
+ onAdd,
91
+ onRemove,
92
+ disabled: listDisabled,
93
+ allowDeselect,
94
+ isSelectedId,
95
+ } = useListContextValue(state => ({
96
+ onAdd: state.onAdd as (item: Option) => void,
97
+ onRemove: state.onRemove as (item: Option) => void,
98
+ disabled: state.disabled,
99
+ allowDeselect: state.allowDeselect,
100
+ isSelectedId: state.isSelectedId,
101
+ }));
102
+
103
+ const option = useMemo(
104
+ () =>
105
+ ({
106
+ id: value,
107
+ ...(itemDisabledProp ? { selectable: false } : {}),
108
+ } as Option),
109
+ [itemDisabledProp, value],
110
+ );
111
+
112
+ const isSelected = isSelectedId(value);
113
+
114
+ const isSelectable = (option as Record<string, unknown>).selectable;
115
+ const isOptionDisabled = Boolean(listDisabled || itemDisabledProp || isSelectable === false);
116
+
117
+ const handlePress = useCallback(
118
+ (
119
+ event: NonNullable<ListItemProps<Option>['onPress']> extends (event: infer E) => void
120
+ ? E
121
+ : never,
122
+ ) => {
123
+ if (isOptionDisabled) return;
124
+ onPress?.(event);
125
+
126
+ if (!shouldToggleOnPress) return;
127
+ onBeforeToggle?.(event);
128
+
129
+ if (isSelected) {
130
+ if (allowDeselect) onRemove(option);
131
+ return;
132
+ }
133
+ onAdd(option);
134
+ },
135
+ [
136
+ allowDeselect,
137
+ isOptionDisabled,
138
+ isSelected,
139
+ onAdd,
140
+ onBeforeToggle,
141
+ onPress,
142
+ onRemove,
143
+ option,
144
+ shouldToggleOnPress,
145
+ ],
146
+ );
147
+
148
+ return (
149
+ <ListItemBase
150
+ {...(rest as ListItemProps)}
151
+ selected={isSelected}
152
+ disabled={isOptionDisabled}
153
+ onPress={handlePress}
154
+ variant={variant ?? 'menuItem'}
155
+ accessibilityRole={accessibilityRole}
156
+ accessibilityState={
157
+ accessibilityState ?? { selected: isSelected, disabled: isOptionDisabled }
158
+ }>
159
+ {children}
160
+ </ListItemBase>
161
+ );
162
+ };
163
+
164
+ const ListItemSelectable = typedMemo(_ListItemSelectable);
165
+
166
+ const _ListItem = <Option extends object = DefaultListItemT>(props: ListItemProps<Option>) => {
167
+ if (props.value !== undefined) {
168
+ return <ListItemSelectable {...(props as ListItemProps<Option> & { value: ListItemId })} />;
169
+ }
170
+ return <ListItemBase {...(props as ListItemProps)} />;
171
+ };
172
+
173
+ const ListItem = typedMemo(_ListItem);
174
+
175
+ type ControlledListValue = ListItemId | ListItemId[] | null;
176
+
177
+ const emptyArr: ListItemId[] = [];
134
178
 
135
179
  const ListProvider = typedMemo(
136
- <Option extends DefaultListItemT = DefaultListItemT>({
180
+ <Option extends object = DefaultListItemT>({
137
181
  children,
138
182
  value: valueProp,
139
183
  defaultValue,
@@ -141,81 +185,54 @@ const ListProvider = typedMemo(
141
185
  multiple = false,
142
186
  disabled = false,
143
187
  error = false,
144
- items = emptyArr as Option[],
145
- searchKey,
146
- onSearchChange,
147
- hideSelected: hideSelectedProp,
188
+ allowDeselect: allowDeselectProp,
148
189
  }: ListProps<Option>) => {
149
- type ControlledListValue = Option['id'] | Option['id'][] | null;
150
- const [value, onValueChange] = useControlledValue<Option['id'] | Option['id'][] | null>({
190
+ const [value, onValueChange] = useControlledValue<ControlledListValue>({
151
191
  value: valueProp,
152
- defaultValue: defaultValue ?? (multiple ? (emptyArr as Option['id'][]) : null),
192
+ defaultValue: defaultValue ?? (multiple ? (emptyArr as ListItemId[]) : null),
153
193
  onChange: onChange as
154
- | ((value: ControlledListValue, item: Option, event?: any) => void)
194
+ | ((value: ControlledListValue, item: Option, event?: unknown) => void)
155
195
  | undefined,
156
196
  });
157
197
  const valueRef = useLatest(value);
158
- const [searchQuery, setSearchQuery] = useState('');
159
198
 
160
- const handleSearchQueryChange = useCallback(
161
- (query: string) => {
162
- setSearchQuery(query);
163
- onSearchChange?.(query);
199
+ const allowDeselect = allowDeselectProp !== undefined ? allowDeselectProp : multiple;
200
+ const isSelectedId = useCallback(
201
+ (id: ListItemId) => {
202
+ if (multiple) {
203
+ const values = (value as ListItemId[] | null | undefined) ?? [];
204
+ return values.some(v => v === id);
205
+ }
206
+ return (value as ListItemId | null) === id;
164
207
  },
165
- [onSearchChange],
208
+ [multiple, value],
166
209
  );
167
210
 
168
- const hideSelected = hideSelectedProp !== undefined ? hideSelectedProp : multiple;
169
-
170
- const filteredItems = useMemo(() => {
171
- let result = items;
172
-
173
- if (hideSelected) {
174
- result = result.filter(item => {
175
- if (multiple) {
176
- const values = (value as Option['id'][]) || [];
177
- return !values.some(v => v === item.id);
178
- }
179
-
180
- const singleValue = value as Option['id'] | null;
181
- return singleValue !== item.id;
182
- });
183
- }
184
-
185
- if (searchQuery) {
186
- const key = searchKey || 'label';
187
- const lowerQuery = searchQuery.toLowerCase();
188
- result = result.filter(item => {
189
- const itemValue = item[key];
190
- return String(itemValue || '')
191
- .toLowerCase()
192
- .includes(lowerQuery);
193
- });
194
- }
195
-
196
- return result;
197
- }, [hideSelected, items, multiple, searchKey, searchQuery, value]);
198
-
199
211
  const onAdd = useCallback(
200
212
  (item: Option) => {
213
+ const id = (item as { id?: ListItemId }).id as ListItemId;
201
214
  if (multiple) {
202
- const currentValue = (valueRef.current as Option['id'][]) || [];
203
- if (!currentValue.find(v => v === item.id)) {
204
- onValueChange([...currentValue, item.id] as Option['id'][], item);
215
+ const currentValue = (valueRef.current as ListItemId[]) || [];
216
+ if (!currentValue.find(v => v === id)) {
217
+ onValueChange([...currentValue, id], item);
205
218
  }
206
219
  return;
207
220
  }
208
221
 
209
- onValueChange(item.id, item);
222
+ onValueChange(id, item);
210
223
  },
211
224
  [multiple, onValueChange, valueRef],
212
225
  );
213
226
 
214
227
  const onRemove = useCallback(
215
228
  (item: Option) => {
229
+ const id = (item as { id?: ListItemId }).id as ListItemId;
216
230
  if (multiple) {
217
- const currentValue = (valueRef.current as Option['id'][]) || [];
218
- onValueChange(currentValue.filter(v => v !== item.id) as Option['id'][], item);
231
+ const currentValue = (valueRef.current as ListItemId[]) || [];
232
+ onValueChange(
233
+ currentValue.filter(v => v !== id),
234
+ item,
235
+ );
219
236
  return;
220
237
  }
221
238
 
@@ -229,12 +246,10 @@ const ListProvider = typedMemo(
229
246
  multiple,
230
247
  onAdd: onAdd as (item: DefaultListItemT) => void,
231
248
  onRemove: onRemove as (item: DefaultListItemT) => void,
249
+ isSelectedId,
232
250
  disabled,
233
251
  error,
234
- items,
235
- searchQuery,
236
- setSearchQuery: handleSearchQueryChange,
237
- filteredItems,
252
+ allowDeselect,
238
253
  } as ListContextValue<DefaultListItemT>;
239
254
 
240
255
  return <ListContextProvider value={contextValue}>{children}</ListContextProvider>;
@@ -242,266 +257,20 @@ const ListProvider = typedMemo(
242
257
  );
243
258
 
244
259
  const ListContent = typedMemo(
245
- <
246
- Option extends DefaultListItemT = DefaultListItemT,
247
- C extends ComponentType<any> = typeof ScrollView,
248
- >({
249
- ref,
250
- children,
251
- ContainerComponent,
252
- style,
253
- emptyState,
254
- processProps,
255
- ...rest
256
- }: ListContentProps<Option, C> & { ref?: React.ForwardedRef<any> }) => {
257
- const { filteredItems, value, multiple, searchQuery, items } = useListContextValue(
258
- state => ({
259
- filteredItems: state.filteredItems,
260
- value: state.value,
261
- multiple: state.multiple,
262
- searchQuery: state.searchQuery,
263
- items: state.items,
264
- }),
265
- );
266
-
267
- const selectedIds = useMemo(() => {
268
- const map: Record<string, true> = {};
269
- const values = multiple ? (value as any[]) ?? [] : value == null ? [] : [value];
270
- for (const v of values) {
271
- const id = v?.id ?? v;
272
- if (id != null) map[id] = true;
273
- }
274
- return map;
275
- }, [multiple, value]);
276
-
277
- const isSelected = useCallback(
278
- (item: DefaultListItemT) => selectedIds[item.id as any] === true,
279
- [selectedIds],
280
- );
281
-
282
- const content = useMemo(() => {
283
- if (children === undefined) {
284
- return null;
285
- }
286
- return filteredItems.map(item =>
287
- children(item as Option, isSelected(item as DefaultListItemT)),
288
- );
289
- }, [children, filteredItems, isSelected]);
290
-
291
- const defaultEmptyState = useMemo(() => {
292
- const hasSearchQuery = searchQuery && searchQuery.trim().length > 0;
293
- const hasNoItems = items.length === 0;
294
-
295
- if (hasNoItems) {
296
- return (
297
- <View style={listStyles.emptyState}>
298
- <Text style={listStyles.emptyStateText}>No items available</Text>
299
- </View>
300
- );
301
- }
302
-
303
- if (hasSearchQuery) {
304
- return (
305
- <View style={listStyles.emptyState}>
306
- <Text style={listStyles.emptyStateText}>No results found</Text>
307
- </View>
308
- );
309
- }
310
-
311
- return (
312
- <View style={listStyles.emptyState}>
313
- <Text style={listStyles.emptyStateText}>No items</Text>
314
- </View>
315
- );
316
- }, [items.length, searchQuery]);
317
-
318
- const resolvedEmptyState = emptyState ?? defaultEmptyState;
319
- const isEmpty = filteredItems.length === 0;
320
-
321
- const Container = (ContainerComponent ?? ScrollView) as ComponentType<any>;
322
-
323
- if (processProps) {
324
- const baseProps = { style, ...rest, accessibilityRole: 'listbox' } as Record<
325
- string,
326
- any
327
- >;
328
- const processedProps = processProps({
329
- props: baseProps as any,
330
- items: filteredItems as Option[],
331
- isEmpty,
332
- emptyState: resolvedEmptyState,
333
- isSelected,
334
- });
335
-
336
- return <Container {...(processedProps as any)} ref={ref} />;
337
- }
338
-
260
+ ({ ref, children, style, ...rest }: ListContentProps & { ref?: React.ForwardedRef<any> }) => {
339
261
  return (
340
- <Container style={style} {...rest} ref={ref} accessibilityRole="listbox">
341
- {isEmpty ? resolvedEmptyState : content}
342
- </Container>
343
- );
344
- },
345
- );
346
-
347
- const ListGroup = memo(({ children, label, style, ...rest }: ListGroupProps) => {
348
- return (
349
- <View style={style} {...rest}>
350
- {label ? <Text style={listStyles.groupLabel}>{label}</Text> : null}
351
- {children}
352
- </View>
353
- );
354
- });
355
-
356
- const ListOption = memo(
357
- <Option extends DefaultListItemT = DefaultListItemT>({
358
- value,
359
- children,
360
- onPress,
361
- disabled: itemDisabledProp = false,
362
- shouldToggleOnPress = true,
363
- accessibilityRole,
364
- accessibilityState,
365
- ...rest
366
- }: ListItemOptionProps<Option>) => {
367
- const {
368
- multiple,
369
- onAdd,
370
- onRemove,
371
- disabled: listDisabled,
372
- items,
373
- } = useListContextValue(state => ({
374
- multiple: state.multiple,
375
- onAdd: state.onAdd,
376
- onRemove: state.onRemove,
377
- disabled: state.disabled,
378
- items: state.items,
379
- }));
380
-
381
- const option = useMemo(() => {
382
- const foundItem = items.find(i => i.id === value);
383
- if (foundItem) return foundItem as Option;
384
-
385
- return {
386
- id: value,
387
- ...(itemDisabledProp ? { selectable: false } : {}),
388
- } as Option;
389
- }, [itemDisabledProp, items, value]);
390
-
391
- const isSelected = useListContextValue(state => {
392
- if (multiple) {
393
- const values = state.value as any[];
394
- return values?.some(v => (v?.id ?? v) === option.id) || false;
395
- }
396
-
397
- const singleValue = state.value as any;
398
- return (singleValue?.id ?? singleValue) === option.id || false;
399
- });
400
-
401
- const isOptionDisabled = Boolean(
402
- listDisabled || itemDisabledProp || option.selectable === false,
403
- );
404
-
405
- const handlePress = useCallback(
406
- (event: any) => {
407
- if (isOptionDisabled) return;
408
- onPress?.(option, event);
409
-
410
- if (shouldToggleOnPress) {
411
- if (isSelected) {
412
- onRemove(option);
413
- } else {
414
- onAdd(option);
415
- }
416
- }
417
- },
418
- [isOptionDisabled, isSelected, onAdd, onPress, onRemove, option, shouldToggleOnPress],
419
- );
420
-
421
- return (
422
- <ListItem
423
- {...rest}
424
- selected={isSelected}
425
- disabled={isOptionDisabled}
426
- onPress={handlePress}
427
- variant={rest.variant || 'menuItem'}
428
- accessibilityRole={accessibilityRole}
429
- accessibilityState={
430
- accessibilityState ?? { selected: isSelected, disabled: isOptionDisabled }
431
- }>
262
+ <ScrollView style={style} {...rest} ref={ref}>
432
263
  {children}
433
- </ListItem>
264
+ </ScrollView>
434
265
  );
435
266
  },
436
267
  );
437
268
 
438
- const ListSearchInput = memo(({ children, ...textInputProps }: ListSearchInputProps) => {
439
- const { searchQuery, setSearchQuery } = useListContextValue(state => ({
440
- searchQuery: state.searchQuery,
441
- setSearchQuery: state.setSearchQuery,
442
- }));
443
-
444
- const textInputRef = useRef<TextInputHandles>(null);
445
-
446
- const handleChangeText = useCallback(
447
- (text: string) => {
448
- setSearchQuery(text);
449
- },
450
- [setSearchQuery],
451
- );
452
-
453
- const inputProps = {
454
- ...textInputProps,
455
- value: searchQuery,
456
- onChangeText: handleChangeText,
457
- placeholder: textInputProps.placeholder || 'Search...',
458
- inputStyle: listStyles.searchInputInput,
459
- } as TextInputProps;
460
-
461
- const onPressLeftIcon = useCallback(() => {
462
- textInputRef.current?.focus();
463
- }, []);
464
-
465
- const onClearSearchQuery = useCallback(() => {
466
- handleChangeText('');
467
- }, [handleChangeText]);
468
-
469
- return (
470
- <TextInput
471
- ref={textInputRef}
472
- style={listStyles.searchInput}
473
- size="sm"
474
- variant="outlined"
475
- {...inputProps}>
476
- <TextInput.Left>
477
- <Icon onPress={onPressLeftIcon} name="magnify" size={20} />
478
- </TextInput.Left>
479
- {searchQuery ? (
480
- <TextInput.Right>
481
- <IconButton name="close" size={20} onPress={onClearSearchQuery} />
482
- </TextInput.Right>
483
- ) : null}
484
- {children}
485
- </TextInput>
486
- );
487
- });
488
-
489
269
  const List = Object.assign(ListProvider, {
490
270
  Content: ListContent,
491
- Item: ListOption,
492
- SearchInput: ListSearchInput,
493
- Group: ListGroup,
494
- Row: ListItem,
271
+ Item: ListItem,
495
272
  });
496
273
 
497
274
  export default List;
498
275
 
499
- export {
500
- type InternalListItemProps,
501
- ListContent,
502
- ListGroup,
503
- ListItem,
504
- ListOption,
505
- ListProvider,
506
- ListSearchInput,
507
- };
276
+ export { ListContent, ListItem, ListProvider };
@@ -1,4 +1,5 @@
1
- import { createFastContext } from '../../fast-context';
1
+ import { createFastContext } from '@react-native-molecules/utils/fast-context';
2
+
2
3
  import { registerPortalContext } from '../Portal';
3
4
  import type { DefaultListItemT, ListContextValue } from './types';
4
5
 
@@ -7,12 +8,10 @@ const listContextDefaultValue: ListContextValue<DefaultListItemT> = {
7
8
  multiple: false,
8
9
  onAdd: () => {},
9
10
  onRemove: () => {},
11
+ isSelectedId: () => false,
10
12
  disabled: false,
11
13
  error: false,
12
- items: [],
13
- searchQuery: '',
14
- setSearchQuery: () => {},
15
- filteredItems: [],
14
+ allowDeselect: false,
16
15
  };
17
16
 
18
17
  const {
@@ -1,6 +1,5 @@
1
1
  import { getRegisteredComponentWithFallback } from '../../core';
2
2
  import ListDefault from './List';
3
- export type { InternalListItemProps as ListItemProps } from './List';
4
3
 
5
4
  export const List = getRegisteredComponentWithFallback('List', ListDefault);
6
5