react-native-ui-lib 7.46.3-snapshot.7352 → 7.46.3-snapshot.7356

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/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uilib-native",
3
- "version": "5.0.0-snapshot.7352",
3
+ "version": "5.0.0-snapshot.7356",
4
4
  "homepage": "https://github.com/wix/react-native-ui-lib",
5
5
  "description": "uilib native components (separated from js components)",
6
6
  "main": "components/index",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ui-lib",
3
- "version": "7.46.3-snapshot.7352",
3
+ "version": "7.46.3-snapshot.7356",
4
4
  "main": "src/index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "author": "Ethan Sharabi <ethan.shar@gmail.com>",
@@ -9,8 +9,7 @@ import { Constants, asBaseComponent, forwardRef } from "../../commons/new";
9
9
  import View from "../view";
10
10
  import { Colors, Spacings, Typography } from "../../style";
11
11
  import FadedScrollView from "../fadedScrollView";
12
- import useScrollToItem from "./useScrollToItem";
13
- import { useDidUpdate } from "../../hooks";
12
+ import { useDidUpdate, useScrollToItem } from "../../hooks";
14
13
  const DEFAULT_HEIGHT = 48;
15
14
  const DEFAULT_LABEL_STYLE = {
16
15
  ...Typography.text80M,
@@ -1,12 +1,14 @@
1
+ import { RefObject } from 'react';
1
2
  import { LayoutChangeEvent } from 'react-native';
2
- import { ScrollToProps, ScrollToSupportedViews, ScrollToResultProps } from '../useScrollTo';
3
+ import { ScrollToSupportedViews, ScrollToResultProps } from 'hooks';
3
4
  export declare enum OffsetType {
4
5
  CENTER = "CENTER",
5
6
  DYNAMIC = "DYNAMIC",
6
7
  LEFT = "LEFT",
7
8
  RIGHT = "RIGHT"
8
9
  }
9
- export type ScrollToItemProps<T extends ScrollToSupportedViews> = Pick<ScrollToProps<T>, 'scrollViewRef'> & {
10
+ export type ScrollToItemProps<T extends ScrollToSupportedViews> = {
11
+ scrollViewRef?: RefObject<T>;
10
12
  /**
11
13
  * The number of items
12
14
  */
@@ -15,6 +17,10 @@ export type ScrollToItemProps<T extends ScrollToSupportedViews> = Pick<ScrollToP
15
17
  * The selected item's index
16
18
  */
17
19
  selectedIndex?: number;
20
+ /**
21
+ * The container width, should update on orientation change
22
+ */
23
+ containerWidth: number;
18
24
  /**
19
25
  * Where would the item be located (default to CENTER)
20
26
  */
@@ -40,13 +46,21 @@ export type ScrollToItemResultProps<T extends ScrollToSupportedViews> = Pick<Scr
40
46
  */
41
47
  onItemLayout: (event: LayoutChangeEvent, index: number) => void;
42
48
  /**
43
- * The items' width
49
+ * The items' width as share animated value
50
+ */
51
+ itemsWidthsAnimated: any;
52
+ /**
53
+ * The items' offsets as share animated value
44
54
  */
45
- itemsWidths: number[];
55
+ itemsOffsetsAnimated: any;
46
56
  /**
47
57
  * Use in order to focus the item with the specified index (use when the selectedIndex is not changed)
48
58
  */
49
59
  focusIndex: (index: number, animated?: boolean) => void;
60
+ /**
61
+ * Use in order to reset the data.
62
+ */
63
+ reset: () => void;
50
64
  /**
51
65
  * onContentSizeChange callback (should be set to your onContentSizeChange).
52
66
  * Needed for RTL support on Android.
@@ -3,8 +3,10 @@ import _includes from "lodash/includes";
3
3
  import _isEmpty from "lodash/isEmpty";
4
4
  import _times from "lodash/times";
5
5
  import { useState, useCallback, useEffect, useRef } from 'react';
6
- import useScrollTo from "../useScrollTo";
6
+ import { useSharedValue } from 'react-native-reanimated';
7
+ import { useScrollTo } from "./..";
7
8
  import { Constants } from "../../commons/new";
9
+ const FIX_RTL = Constants.isRTL;
8
10
  export let OffsetType = /*#__PURE__*/function (OffsetType) {
9
11
  OffsetType["CENTER"] = "CENTER";
10
12
  OffsetType["DYNAMIC"] = "DYNAMIC";
@@ -20,12 +22,15 @@ const useScrollToItem = props => {
20
22
  scrollViewRef: propsScrollViewRef,
21
23
  itemsCount,
22
24
  selectedIndex,
25
+ containerWidth,
23
26
  offsetType = OffsetType.CENTER,
24
27
  addOffsetMargin = true,
25
28
  outerSpacing = 0,
26
29
  innerSpacing = 0
27
30
  } = props;
28
31
  const itemsWidths = useRef(_times(itemsCount, () => null));
32
+ const itemsWidthsAnimated = useSharedValue(_times(itemsCount, () => 0));
33
+ const itemsOffsetsAnimated = useSharedValue(_times(itemsCount, () => 0));
29
34
  const currentIndex = useRef(selectedIndex || 0);
30
35
  const [offsets, setOffsets] = useState({
31
36
  CENTER: [],
@@ -49,30 +54,31 @@ const useScrollToItem = props => {
49
54
  // const contentWidth = _.sum(itemsWidths);
50
55
  // TODO: const scrollEnabled = contentWidth.current > containerWidth;
51
56
 
52
- const setSnapBreakpoints = useCallback(itemsWidths => {
53
- if (_isEmpty(itemsWidths)) {
57
+ const setSnapBreakpoints = useCallback(widths => {
58
+ if (_isEmpty(widths)) {
54
59
  return;
55
60
  }
56
- const screenCenter = Constants.screenWidth / 2; // TODO: change to something more dynamic?
61
+ const screenCenter = containerWidth / 2;
57
62
  let index = 0;
58
63
  const centeredOffsets = [];
59
64
  let currentCenterOffset = outerSpacing;
60
65
  const leftOffsets = [];
61
66
  leftOffsets.push(outerSpacing - innerSpacing);
62
67
  const rightOffsets = [];
63
- rightOffsets.push(-Constants.screenWidth + itemsWidths[0] + outerSpacing + innerSpacing);
68
+ rightOffsets.push(-containerWidth + widths[0] + outerSpacing + innerSpacing);
64
69
  while (index < itemsCount) {
65
- centeredOffsets[index] = currentCenterOffset - screenCenter + itemsWidths[index] / 2;
70
+ /* calc center, left and right offsets */
71
+ centeredOffsets[index] = currentCenterOffset - screenCenter + widths[index] / 2;
66
72
  ++index;
67
- currentCenterOffset += itemsWidths[index - 1] + innerSpacing;
68
- leftOffsets[index] = leftOffsets[index - 1] + itemsWidths[index - 1] + innerSpacing;
69
- rightOffsets[index] = rightOffsets[index - 1] + itemsWidths[index] + innerSpacing;
73
+ currentCenterOffset += widths[index - 1] + innerSpacing;
74
+ leftOffsets[index] = leftOffsets[index - 1] + widths[index - 1] + innerSpacing;
75
+ rightOffsets[index] = rightOffsets[index - 1] + widths[index] + innerSpacing;
70
76
  }
71
77
  if (addOffsetMargin) {
72
78
  index = 1;
73
79
  while (index < itemsCount - 1) {
74
- leftOffsets[index] -= itemsWidths[index - 1];
75
- rightOffsets[index] += itemsWidths[index + 1] + innerSpacing;
80
+ leftOffsets[index] -= widths[index - 1];
81
+ rightOffsets[index] += widths[index + 1] + innerSpacing;
76
82
  ++index;
77
83
  }
78
84
  }
@@ -81,7 +87,25 @@ const useScrollToItem = props => {
81
87
  LEFT: leftOffsets,
82
88
  RIGHT: rightOffsets
83
89
  }); // default for DYNAMIC is CENTER
84
- }, [itemsCount, outerSpacing, innerSpacing, addOffsetMargin]);
90
+
91
+ // Update shared values
92
+ // @ts-expect-error pretty sure this is a bug in reanimated since itemsWidthsAnimated is defined as SharedValue<number[]>
93
+ itemsWidthsAnimated.modify(value => {
94
+ 'worklet';
95
+
96
+ return value.map((_, index) => widths[index]);
97
+ });
98
+ itemsOffsetsAnimated.modify(value => {
99
+ 'worklet';
100
+
101
+ value.forEach((_, index) => {
102
+ if (index > 0) {
103
+ value[index] = value[index - 1] + widths[index - 1];
104
+ }
105
+ });
106
+ return value;
107
+ });
108
+ }, [itemsCount, outerSpacing, innerSpacing, addOffsetMargin, containerWidth]);
85
109
  const onItemLayout = useCallback((event, index) => {
86
110
  const {
87
111
  width
@@ -93,25 +117,40 @@ const useScrollToItem = props => {
93
117
  }, [setSnapBreakpoints]);
94
118
  const focusIndex = useCallback((index, animated = true) => {
95
119
  if (index >= 0 && offsets.CENTER.length > index) {
120
+ const rtlIndex = FIX_RTL ? itemsCount - index - 1 : index;
96
121
  if (offsetType !== OffsetType.DYNAMIC) {
97
- scrollTo(offsets[offsetType][index], animated);
122
+ scrollTo(offsets[offsetType][rtlIndex], animated);
98
123
  } else {
99
124
  const movingLeft = index < currentIndex.current;
100
- currentIndex.current = index;
101
- scrollTo(movingLeft ? offsets[OffsetType.RIGHT][index] : offsets[OffsetType.LEFT][index], animated);
125
+ currentIndex.current = rtlIndex;
126
+ scrollTo(movingLeft ? offsets[OffsetType.RIGHT][rtlIndex] : offsets[OffsetType.LEFT][rtlIndex], animated);
102
127
  }
103
128
  }
104
129
  }, [offsets, offsetType, scrollTo]);
105
130
  useEffect(() => {
106
131
  if (!_isUndefined(selectedIndex)) {
107
- focusIndex(selectedIndex);
132
+ focusIndex(selectedIndex, false);
108
133
  }
109
134
  }, [selectedIndex, focusIndex]);
135
+ const reset = useCallback(() => {
136
+ for (let i = 0; i < itemsCount; ++i) {
137
+ itemsWidths.current[i] = null;
138
+ itemsWidthsAnimated.value[i] = 0;
139
+ itemsOffsetsAnimated.value[i] = 0;
140
+ }
141
+ setOffsets({
142
+ CENTER: [],
143
+ LEFT: [],
144
+ RIGHT: []
145
+ });
146
+ }, [itemsCount]);
110
147
  return {
111
148
  scrollViewRef,
112
149
  onItemLayout,
113
- itemsWidths: offsets.CENTER.length > 0 ? itemsWidths.current : [],
150
+ itemsWidthsAnimated,
151
+ itemsOffsetsAnimated,
114
152
  focusIndex,
153
+ reset,
115
154
  onContentSizeChange,
116
155
  onLayout
117
156
  };
@@ -1,79 +0,0 @@
1
- import { RefObject } from 'react';
2
- import { LayoutChangeEvent } from 'react-native';
3
- import { ScrollToSupportedViews, ScrollToResultProps } from 'hooks';
4
- export declare enum OffsetType {
5
- CENTER = "CENTER",
6
- DYNAMIC = "DYNAMIC",
7
- LEFT = "LEFT",
8
- RIGHT = "RIGHT"
9
- }
10
- export type ScrollToItemProps<T extends ScrollToSupportedViews> = {
11
- scrollViewRef?: RefObject<T>;
12
- /**
13
- * The number of items
14
- */
15
- itemsCount: number;
16
- /**
17
- * The selected item's index
18
- */
19
- selectedIndex?: number;
20
- /**
21
- * The container width, should update on orientation change
22
- */
23
- containerWidth: number;
24
- /**
25
- * Where would the item be located (default to CENTER)
26
- */
27
- offsetType?: OffsetType | `${OffsetType}`;
28
- /**
29
- * Add a margin to the offset (default to true)
30
- * This gives a better UX
31
- * Not relevant to OffsetType.CENTER
32
- */
33
- addOffsetMargin?: boolean;
34
- /**
35
- * How much space (padding \ margin) is there on the left\right of the items
36
- */
37
- outerSpacing?: number;
38
- /**
39
- * How much space (padding \ margin) is there between each item
40
- */
41
- innerSpacing?: number;
42
- };
43
- export type ScrollToItemResultProps<T extends ScrollToSupportedViews> = Pick<ScrollToResultProps<T>, 'scrollViewRef'> & {
44
- /**
45
- * This should be called by each ot the items' onLayout
46
- */
47
- onItemLayout: (event: LayoutChangeEvent, index: number) => void;
48
- /**
49
- * The items' width as share animated value
50
- */
51
- itemsWidthsAnimated: any;
52
- /**
53
- * The items' offsets as share animated value
54
- */
55
- itemsOffsetsAnimated: any;
56
- /**
57
- * Use in order to focus the item with the specified index (use when the selectedIndex is not changed)
58
- */
59
- focusIndex: (index: number, animated?: boolean) => void;
60
- /**
61
- * Use in order to reset the data.
62
- */
63
- reset: () => void;
64
- /**
65
- * onContentSizeChange callback (should be set to your onContentSizeChange).
66
- * Needed for RTL support on Android.
67
- */
68
- onContentSizeChange: (contentWidth: number, contentHeight: number) => void;
69
- /**
70
- * onLayout callback (should be set to your onLayout).
71
- * Needed for RTL support on Android.
72
- */
73
- onLayout: (event: LayoutChangeEvent) => void;
74
- };
75
- declare const useScrollToItem: {
76
- <T extends ScrollToSupportedViews>(props: ScrollToItemProps<T>): ScrollToItemResultProps<T>;
77
- offsetType: typeof OffsetType;
78
- };
79
- export default useScrollToItem;
@@ -1,159 +0,0 @@
1
- import _isUndefined from "lodash/isUndefined";
2
- import _includes from "lodash/includes";
3
- import _isEmpty from "lodash/isEmpty";
4
- import _times from "lodash/times";
5
- import { useState, useCallback, useEffect, useRef } from 'react';
6
- import { useSharedValue } from 'react-native-reanimated';
7
- import { useScrollTo } from "../../hooks";
8
- import { Constants } from "../../commons/new";
9
- const FIX_RTL = Constants.isRTL;
10
- export let OffsetType = /*#__PURE__*/function (OffsetType) {
11
- OffsetType["CENTER"] = "CENTER";
12
- OffsetType["DYNAMIC"] = "DYNAMIC";
13
- OffsetType["LEFT"] = "LEFT";
14
- OffsetType["RIGHT"] = "RIGHT";
15
- return OffsetType;
16
- }({});
17
-
18
- // TODO: this is what I want, is there a better way to do it?
19
-
20
- const useScrollToItem = props => {
21
- const {
22
- scrollViewRef: propsScrollViewRef,
23
- itemsCount,
24
- selectedIndex,
25
- containerWidth,
26
- offsetType = OffsetType.CENTER,
27
- addOffsetMargin = true,
28
- outerSpacing = 0,
29
- innerSpacing = 0
30
- } = props;
31
- const itemsWidths = useRef(_times(itemsCount, () => null));
32
- const itemsWidthsAnimated = useSharedValue(_times(itemsCount, () => 0));
33
- const itemsOffsetsAnimated = useSharedValue(_times(itemsCount, () => 0));
34
- const currentIndex = useRef(selectedIndex || 0);
35
- const [offsets, setOffsets] = useState({
36
- CENTER: [],
37
- LEFT: [],
38
- RIGHT: []
39
- });
40
- const {
41
- scrollViewRef,
42
- scrollTo,
43
- onContentSizeChange,
44
- onLayout
45
- } = useScrollTo({
46
- scrollViewRef: propsScrollViewRef
47
- });
48
-
49
- // TODO: reset?
50
- // useEffect(() => {
51
- // itemsWidths.current = _.times(itemsCount, () => null);
52
- // }, [itemsCount]);
53
-
54
- // const contentWidth = _.sum(itemsWidths);
55
- // TODO: const scrollEnabled = contentWidth.current > containerWidth;
56
-
57
- const setSnapBreakpoints = useCallback(widths => {
58
- if (_isEmpty(widths)) {
59
- return;
60
- }
61
- const screenCenter = containerWidth / 2;
62
- let index = 0;
63
- const centeredOffsets = [];
64
- let currentCenterOffset = outerSpacing;
65
- const leftOffsets = [];
66
- leftOffsets.push(outerSpacing - innerSpacing);
67
- const rightOffsets = [];
68
- rightOffsets.push(-containerWidth + widths[0] + outerSpacing + innerSpacing);
69
- while (index < itemsCount) {
70
- /* calc center, left and right offsets */
71
- centeredOffsets[index] = currentCenterOffset - screenCenter + widths[index] / 2;
72
- ++index;
73
- currentCenterOffset += widths[index - 1] + innerSpacing;
74
- leftOffsets[index] = leftOffsets[index - 1] + widths[index - 1] + innerSpacing;
75
- rightOffsets[index] = rightOffsets[index - 1] + widths[index] + innerSpacing;
76
- }
77
- if (addOffsetMargin) {
78
- index = 1;
79
- while (index < itemsCount - 1) {
80
- leftOffsets[index] -= widths[index - 1];
81
- rightOffsets[index] += widths[index + 1] + innerSpacing;
82
- ++index;
83
- }
84
- }
85
- setOffsets({
86
- CENTER: centeredOffsets,
87
- LEFT: leftOffsets,
88
- RIGHT: rightOffsets
89
- }); // default for DYNAMIC is CENTER
90
-
91
- // Update shared values
92
- // @ts-expect-error pretty sure this is a bug in reanimated since itemsWidthsAnimated is defined as SharedValue<number[]>
93
- itemsWidthsAnimated.modify(value => {
94
- 'worklet';
95
-
96
- return value.map((_, index) => widths[index]);
97
- });
98
- itemsOffsetsAnimated.modify(value => {
99
- 'worklet';
100
-
101
- value.forEach((_, index) => {
102
- if (index > 0) {
103
- value[index] = value[index - 1] + widths[index - 1];
104
- }
105
- });
106
- return value;
107
- });
108
- }, [itemsCount, outerSpacing, innerSpacing, addOffsetMargin, containerWidth]);
109
- const onItemLayout = useCallback((event, index) => {
110
- const {
111
- width
112
- } = event.nativeEvent.layout;
113
- itemsWidths.current[index] = width;
114
- if (!_includes(itemsWidths.current, null)) {
115
- setSnapBreakpoints(itemsWidths.current);
116
- }
117
- }, [setSnapBreakpoints]);
118
- const focusIndex = useCallback((index, animated = true) => {
119
- if (index >= 0 && offsets.CENTER.length > index) {
120
- const rtlIndex = FIX_RTL ? itemsCount - index - 1 : index;
121
- if (offsetType !== OffsetType.DYNAMIC) {
122
- scrollTo(offsets[offsetType][rtlIndex], animated);
123
- } else {
124
- const movingLeft = index < currentIndex.current;
125
- currentIndex.current = rtlIndex;
126
- scrollTo(movingLeft ? offsets[OffsetType.RIGHT][rtlIndex] : offsets[OffsetType.LEFT][rtlIndex], animated);
127
- }
128
- }
129
- }, [offsets, offsetType, scrollTo]);
130
- useEffect(() => {
131
- if (!_isUndefined(selectedIndex)) {
132
- focusIndex(selectedIndex, false);
133
- }
134
- }, [selectedIndex, focusIndex]);
135
- const reset = useCallback(() => {
136
- for (let i = 0; i < itemsCount; ++i) {
137
- itemsWidths.current[i] = null;
138
- itemsWidthsAnimated.value[i] = 0;
139
- itemsOffsetsAnimated.value[i] = 0;
140
- }
141
- setOffsets({
142
- CENTER: [],
143
- LEFT: [],
144
- RIGHT: []
145
- });
146
- }, [itemsCount]);
147
- return {
148
- scrollViewRef,
149
- onItemLayout,
150
- itemsWidthsAnimated,
151
- itemsOffsetsAnimated,
152
- focusIndex,
153
- reset,
154
- onContentSizeChange,
155
- onLayout
156
- };
157
- };
158
- useScrollToItem.offsetType = OffsetType;
159
- export default useScrollToItem;