react-native-molecules 0.5.0-beta.2 → 0.5.0-beta.20

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 (157) hide show
  1. package/README.md +1 -1
  2. package/components/Accordion/Accordion.tsx +2 -6
  3. package/components/Accordion/AccordionItem.tsx +16 -12
  4. package/components/Accordion/AccordionItemContent.tsx +6 -1
  5. package/components/Accordion/AccordionItemHeader.tsx +1 -1
  6. package/components/Accordion/utils.ts +6 -0
  7. package/components/ActivityIndicator/ActivityIndicator.tsx +6 -15
  8. package/components/Appbar/AppbarBase.tsx +18 -13
  9. package/components/Button/Button.tsx +209 -264
  10. package/components/Button/index.tsx +9 -3
  11. package/components/Button/types.ts +16 -2
  12. package/components/Button/utils.ts +230 -208
  13. package/components/Checkbox/CheckboxBase.tsx +23 -128
  14. package/components/Checkbox/utils.ts +0 -25
  15. package/components/Chip/Chip.tsx +40 -52
  16. package/components/Chip/utils.ts +3 -7
  17. package/components/DateField/DateField.tsx +110 -0
  18. package/components/DateField/index.tsx +6 -0
  19. package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +17 -49
  20. package/components/DatePicker/DateCalendar.tsx +83 -0
  21. package/components/DatePicker/DatePickerActions.tsx +73 -0
  22. package/components/DatePicker/DatePickerModal.tsx +234 -0
  23. package/components/DatePicker/DatePickerPopover.tsx +79 -0
  24. package/components/DatePicker/DatePickerProvider.tsx +152 -0
  25. package/components/DatePicker/DatePickerTrigger.tsx +23 -0
  26. package/components/DatePicker/context.tsx +82 -0
  27. package/components/DatePicker/index.tsx +44 -0
  28. package/components/DatePicker/utils.ts +293 -0
  29. package/components/DatePickerInline/DatePickerContext.tsx +1 -0
  30. package/components/DatePickerInline/DatePickerDockedHeader.tsx +113 -0
  31. package/components/DatePickerInline/DatePickerInline.tsx +16 -15
  32. package/components/DatePickerInline/DatePickerInlineBase.tsx +7 -1
  33. package/components/DatePickerInline/Day.tsx +25 -1
  34. package/components/DatePickerInline/DayRange.tsx +2 -4
  35. package/components/DatePickerInline/HeaderItem.tsx +42 -27
  36. package/components/DatePickerInline/Month.tsx +45 -65
  37. package/components/DatePickerInline/MonthPicker.tsx +25 -41
  38. package/components/DatePickerInline/Swiper.native.tsx +21 -4
  39. package/components/DatePickerInline/Swiper.tsx +168 -13
  40. package/components/DatePickerInline/Week.tsx +6 -1
  41. package/components/DatePickerInline/YearPicker.tsx +206 -53
  42. package/components/DatePickerInline/dateUtils.tsx +17 -12
  43. package/components/DatePickerInline/types.ts +3 -0
  44. package/components/DatePickerInline/utils.ts +66 -29
  45. package/components/Drawer/Drawer.tsx +17 -6
  46. package/components/ElementGroup/ElementGroup.tsx +16 -14
  47. package/components/FilePicker/FilePicker.tsx +48 -78
  48. package/components/FilePicker/index.tsx +2 -1
  49. package/components/FilePicker/utils.ts +9 -0
  50. package/components/HelperText/HelperText.tsx +0 -35
  51. package/components/Icon/iconFactory.tsx +3 -3
  52. package/components/Icon/index.tsx +1 -1
  53. package/components/Icon/types.ts +17 -6
  54. package/components/IconButton/IconButton.tsx +42 -57
  55. package/components/IconButton/utils.ts +142 -33
  56. package/components/ListItem/ListItem.tsx +3 -1
  57. package/components/ListItem/utils.ts +1 -1
  58. package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
  59. package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
  60. package/components/LoadingIndicator/index.tsx +13 -0
  61. package/components/LoadingIndicator/utils.ts +117 -0
  62. package/components/Menu/Menu.tsx +3 -18
  63. package/components/NavigationRail/NavigationRail.tsx +15 -9
  64. package/components/Popover/Popover.tsx +122 -145
  65. package/components/Popover/PopoverRoot.tsx +74 -0
  66. package/components/Popover/common.ts +50 -34
  67. package/components/Popover/index.ts +18 -1
  68. package/components/Popover/usePlatformMeasure.native.ts +90 -0
  69. package/components/Popover/usePlatformMeasure.ts +118 -0
  70. package/components/Popover/utils.ts +34 -0
  71. package/components/Select/Select.tsx +368 -507
  72. package/components/Select/context.tsx +72 -0
  73. package/components/Select/index.ts +8 -14
  74. package/components/Select/types.ts +2 -4
  75. package/components/Select/utils.ts +144 -0
  76. package/components/Slot/Slot.tsx +244 -0
  77. package/components/Slot/compose-refs.tsx +62 -0
  78. package/components/Slot/index.tsx +8 -0
  79. package/components/Surface/Surface.android.tsx +34 -8
  80. package/components/Surface/Surface.ios.tsx +36 -29
  81. package/components/Surface/Surface.tsx +31 -4
  82. package/components/Surface/utils.ts +44 -30
  83. package/components/Switch/Switch.tsx +8 -2
  84. package/components/Tabs/TabItem.tsx +35 -58
  85. package/components/Tabs/TabLabel.tsx +5 -9
  86. package/components/Tabs/Tabs.tsx +154 -148
  87. package/components/Tabs/utils.ts +15 -2
  88. package/components/TextInput/TextInput.tsx +658 -575
  89. package/components/TextInput/index.tsx +19 -3
  90. package/components/TextInput/types.ts +76 -27
  91. package/components/TextInput/utils.ts +225 -145
  92. package/components/TimeField/TimeField.tsx +75 -0
  93. package/components/TimeField/index.tsx +6 -0
  94. package/components/TimeField/useTimeFieldState.ts +70 -0
  95. package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
  96. package/components/TimePicker/TimeInput.tsx +87 -37
  97. package/components/TimePicker/TimeInputs.tsx +137 -49
  98. package/components/TimePicker/TimePicker.tsx +73 -10
  99. package/components/TimePicker/TimePickerModal.tsx +186 -0
  100. package/components/TimePicker/context.tsx +17 -0
  101. package/components/TimePicker/index.tsx +15 -3
  102. package/components/TimePicker/utils.ts +93 -0
  103. package/components/Tooltip/Tooltip.tsx +42 -67
  104. package/components/Tooltip/TooltipContent.tsx +32 -5
  105. package/components/Tooltip/TooltipTrigger.tsx +20 -20
  106. package/components/Tooltip/index.tsx +1 -1
  107. package/components/TouchableRipple/TouchableRipple.native.tsx +50 -14
  108. package/components/TouchableRipple/TouchableRipple.tsx +137 -47
  109. package/hocs/withPortal.tsx +1 -1
  110. package/hooks/index.tsx +0 -6
  111. package/hooks/useActionState.tsx +19 -8
  112. package/hooks/useControlledValue.tsx +20 -4
  113. package/hooks/useFilePicker.tsx +6 -16
  114. package/hooks/useWhatHasUpdated.tsx +48 -0
  115. package/package.json +17 -13
  116. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +5 -2
  117. package/styles/shadow.ts +2 -1
  118. package/styles/themes/LightTheme.tsx +1 -1
  119. package/utils/DocumentPicker/documentPicker.ts +78 -27
  120. package/utils/DocumentPicker/types.ts +0 -1
  121. package/utils/extractPropertiesFromStyles.ts +25 -0
  122. package/utils/extractSubcomponents.ts +89 -0
  123. package/utils/lodash.ts +77 -5
  124. package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
  125. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
  126. package/components/DatePickerDocked/index.tsx +0 -17
  127. package/components/DatePickerDocked/types.ts +0 -11
  128. package/components/DatePickerDocked/utils.ts +0 -157
  129. package/components/DatePickerInput/DatePickerInput.tsx +0 -139
  130. package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
  131. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -77
  132. package/components/DatePickerInput/DateRangeInput.tsx +0 -88
  133. package/components/DatePickerInput/index.tsx +0 -10
  134. package/components/DatePickerInput/types.ts +0 -28
  135. package/components/DatePickerInput/utils.ts +0 -15
  136. package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
  137. package/components/DatePickerModal/CalendarEdit.tsx +0 -139
  138. package/components/DatePickerModal/DatePickerModal.tsx +0 -85
  139. package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
  140. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
  141. package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
  142. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
  143. package/components/DatePickerModal/index.tsx +0 -16
  144. package/components/DatePickerModal/types.ts +0 -92
  145. package/components/DatePickerModal/utils.ts +0 -122
  146. package/components/DateTimePicker/DateTimePicker.tsx +0 -172
  147. package/components/DateTimePicker/index.tsx +0 -10
  148. package/components/DateTimePicker/utils.ts +0 -12
  149. package/components/Popover/Popover.native.tsx +0 -185
  150. package/components/TimePickerField/TimePickerField.tsx +0 -152
  151. package/components/TimePickerField/index.tsx +0 -10
  152. package/components/TimePickerField/utils.ts +0 -94
  153. package/components/TimePickerModal/TimePickerModal.tsx +0 -115
  154. package/components/TimePickerModal/index.tsx +0 -10
  155. package/components/TimePickerModal/utils.ts +0 -47
  156. package/hooks/useSearchable.tsx +0 -74
  157. package/hooks/useSubcomponents.tsx +0 -59
@@ -0,0 +1,90 @@
1
+ import { useCallback, useEffect, useLayoutEffect } from 'react';
2
+ import { AppState, Dimensions, Platform } from 'react-native';
3
+
4
+ import { popoverDefaultStyles } from './common';
5
+ import type { UsePlatformMeasureArgs, UsePlatformMeasureResult } from './usePlatformMeasure';
6
+
7
+ export const usePlatformMeasure = ({
8
+ triggerRef,
9
+ isOpen,
10
+ calculatedPosition,
11
+ calculateAndSetPosition,
12
+ targetLayoutRef,
13
+ triggerDimensions,
14
+ }: UsePlatformMeasureArgs): UsePlatformMeasureResult => {
15
+ const measureTarget = useCallback(() => {
16
+ if (triggerRef?.current) {
17
+ triggerRef.current.measure(
18
+ (
19
+ _fx: number,
20
+ _fy: number,
21
+ width: number,
22
+ height: number,
23
+ px: number,
24
+ py: number,
25
+ ) => {
26
+ if (width !== 0 || height !== 0) {
27
+ const newLayout = { x: px, y: py, width, height };
28
+ const changed =
29
+ !targetLayoutRef.current ||
30
+ targetLayoutRef.current.x !== newLayout.x ||
31
+ targetLayoutRef.current.y !== newLayout.y ||
32
+ targetLayoutRef.current.width !== newLayout.width ||
33
+ targetLayoutRef.current.height !== newLayout.height;
34
+
35
+ if (changed) {
36
+ targetLayoutRef.current = newLayout;
37
+ calculateAndSetPosition();
38
+ }
39
+ } else {
40
+ targetLayoutRef.current = null;
41
+ calculateAndSetPosition();
42
+ }
43
+ },
44
+ () => {
45
+ console.error('Failed to measure target element for Popover.');
46
+ targetLayoutRef.current = null;
47
+ calculateAndSetPosition();
48
+ },
49
+ );
50
+ } else {
51
+ targetLayoutRef.current = null;
52
+ calculateAndSetPosition();
53
+ }
54
+ }, [triggerRef, calculateAndSetPosition, targetLayoutRef]);
55
+
56
+ useLayoutEffect(() => {
57
+ if (isOpen) {
58
+ measureTarget();
59
+ }
60
+ }, [isOpen, measureTarget, triggerDimensions]);
61
+
62
+ useEffect(() => {
63
+ if (!isOpen) return;
64
+ const subscription = Dimensions.addEventListener('change', measureTarget);
65
+ return () => {
66
+ if (typeof subscription?.remove === 'function') {
67
+ subscription.remove();
68
+ }
69
+ };
70
+ }, [isOpen, measureTarget]);
71
+
72
+ useEffect(() => {
73
+ if (!isOpen || Platform.OS === 'web') return;
74
+ const handleAppStateChange = (nextAppState: string) => {
75
+ if (nextAppState === 'active') {
76
+ setTimeout(measureTarget, 50);
77
+ }
78
+ };
79
+ const subscription = AppState.addEventListener('change', handleAppStateChange);
80
+ return () => {
81
+ if (typeof subscription?.remove === 'function') {
82
+ subscription.remove();
83
+ }
84
+ };
85
+ }, [isOpen, measureTarget]);
86
+
87
+ return {
88
+ popoverStyle: (calculatedPosition ?? popoverDefaultStyles) as any,
89
+ };
90
+ };
@@ -0,0 +1,118 @@
1
+ import { type RefObject, useCallback, useEffect, useLayoutEffect, useMemo } from 'react';
2
+ import type { LayoutRectangle, View, ViewStyle } from 'react-native';
3
+
4
+ import { popoverDefaultStyles } from './common';
5
+
6
+ export type UsePlatformMeasureArgs = {
7
+ triggerRef: RefObject<View | any> | undefined;
8
+ isOpen: boolean;
9
+ onClose?: () => void;
10
+ calculatedPosition: ViewStyle | null;
11
+ calculateAndSetPosition: () => void;
12
+ targetLayoutRef: RefObject<LayoutRectangle | null>;
13
+ popoverRef: RefObject<View | null>;
14
+ triggerDimensions?: { width: number; height: number } | null;
15
+ };
16
+
17
+ export type UsePlatformMeasureResult = {
18
+ /** Platform-adjusted popover position (includes scroll offset on web) */
19
+ popoverStyle: ViewStyle;
20
+ };
21
+
22
+ export const usePlatformMeasure = ({
23
+ triggerRef,
24
+ isOpen,
25
+ onClose,
26
+ calculatedPosition,
27
+ calculateAndSetPosition,
28
+ targetLayoutRef,
29
+ popoverRef,
30
+ triggerDimensions,
31
+ }: UsePlatformMeasureArgs): UsePlatformMeasureResult => {
32
+ const measureTarget = useCallback(() => {
33
+ if (triggerRef?.current) {
34
+ triggerRef.current.measureInWindow(
35
+ (x: number, y: number, width: number, height: number) => {
36
+ if (width !== 0 || height !== 0) {
37
+ const newLayout = { x, y, width, height };
38
+ const changed =
39
+ !targetLayoutRef.current ||
40
+ targetLayoutRef.current.x !== newLayout.x ||
41
+ targetLayoutRef.current.y !== newLayout.y ||
42
+ targetLayoutRef.current.width !== newLayout.width ||
43
+ targetLayoutRef.current.height !== newLayout.height;
44
+
45
+ if (changed) {
46
+ targetLayoutRef.current = newLayout;
47
+ calculateAndSetPosition();
48
+ }
49
+ } else {
50
+ targetLayoutRef.current = null;
51
+ calculateAndSetPosition();
52
+ }
53
+ },
54
+ );
55
+ } else {
56
+ targetLayoutRef.current = null;
57
+ calculateAndSetPosition();
58
+ }
59
+ }, [triggerRef, calculateAndSetPosition, targetLayoutRef]);
60
+
61
+ useLayoutEffect(() => {
62
+ if (isOpen) {
63
+ const timeoutId = setTimeout(measureTarget, 0);
64
+ return () => clearTimeout(timeoutId);
65
+ }
66
+ return;
67
+ }, [isOpen, measureTarget, triggerDimensions]);
68
+
69
+ useLayoutEffect(() => {
70
+ if (!isOpen) return;
71
+ const handleResize = () => {
72
+ if (triggerRef?.current && isOpen) {
73
+ window.requestAnimationFrame(measureTarget);
74
+ }
75
+ };
76
+ window.addEventListener('resize', handleResize);
77
+ window.addEventListener('scroll', handleResize, true);
78
+ return () => {
79
+ window.removeEventListener('resize', handleResize);
80
+ window.removeEventListener('scroll', handleResize, true);
81
+ };
82
+ }, [isOpen, measureTarget, triggerRef]);
83
+
84
+ useEffect(() => {
85
+ if (!isOpen || !onClose) return;
86
+ const handleClickOutside = (event: MouseEvent) => {
87
+ const popoverElement = popoverRef.current as any as HTMLElement;
88
+ const targetElement = triggerRef?.current as any as HTMLElement;
89
+ if (
90
+ popoverElement &&
91
+ !popoverElement.contains(event.target as Node) &&
92
+ targetElement &&
93
+ !targetElement.contains(event.target as Node)
94
+ ) {
95
+ onClose();
96
+ }
97
+ };
98
+ document.addEventListener('mousedown', handleClickOutside, { capture: true });
99
+ return () => {
100
+ document.removeEventListener('mousedown', handleClickOutside, { capture: true });
101
+ };
102
+ }, [isOpen, onClose, popoverRef, triggerRef]);
103
+
104
+ const popoverStyle = useMemo(() => {
105
+ if (!calculatedPosition) return popoverDefaultStyles;
106
+
107
+ const scrollX = window.scrollX ?? window.pageXOffset ?? 0;
108
+ const scrollY = window.scrollY ?? window.pageYOffset ?? 0;
109
+
110
+ return {
111
+ ...calculatedPosition,
112
+ left: (calculatedPosition.left as number) + scrollX,
113
+ top: (calculatedPosition.top as number) + scrollY,
114
+ };
115
+ }, [calculatedPosition]);
116
+
117
+ return { popoverStyle };
118
+ };
@@ -0,0 +1,34 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+
3
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
4
+ import { popoverDefaultStyles } from './common';
5
+
6
+ const popoverStylesDefault = StyleSheet.create(theme => ({
7
+ popoverContainer: {
8
+ ...popoverDefaultStyles,
9
+ backgroundColor: theme.colors.surface,
10
+ borderRadius: 4,
11
+ shadowColor: 'rgba(0, 0, 0, 1)',
12
+ shadowOffset: { width: 0, height: 2 },
13
+ shadowOpacity: theme.dark ? 0.7 : 0.3,
14
+ shadowRadius: 10,
15
+ elevation: 5,
16
+ zIndex: 100,
17
+ },
18
+ overlay: {
19
+ position: 'absolute',
20
+ top: 0,
21
+ left: 0,
22
+ right: 0,
23
+ bottom: 0,
24
+ backgroundColor: 'transparent',
25
+ _web: {
26
+ cursor: 'default',
27
+ },
28
+ },
29
+ }));
30
+
31
+ export const popoverStyles = getRegisteredComponentStylesWithFallback(
32
+ 'Popover',
33
+ popoverStylesDefault,
34
+ );