@proximus/lavender-carousel-native 0.1.0-alpha.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/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [0.1.0-alpha.3](https://github.com/Pxs-Corporate/react-native-lavender/compare/@proximus/lavender-carousel-native@0.1.0-alpha.2...@proximus/lavender-carousel-native@0.1.0-alpha.3) (2025-09-26)
7
+
8
+ **Note:** Version bump only for package @proximus/lavender-carousel-native
9
+
10
+ # 0.1.0-alpha.2 (2025-09-25)
11
+
12
+ ### Bug Fixes
13
+
14
+ - **BCRI-000000:** no free space on gh runner during build ([#27](https://github.com/Pxs-Corporate/react-native-lavender/issues/27)) ([a7c8604](https://github.com/Pxs-Corporate/react-native-lavender/commit/a7c86043b5cefcb10fd768d449c5718fbabe87ec))
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare function PxAppleSeed({ numberOfItems, selectedItemIndex, }: {
3
+ numberOfItems: number;
4
+ selectedItemIndex: number;
5
+ }): React.JSX.Element;
6
+ //# sourceMappingURL=AppleSeed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppleSeed.d.ts","sourceRoot":"","sources":["../src/AppleSeed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AASjD,wBAAgB,WAAW,CAAC,EAC1B,aAAa,EACb,iBAAiB,GAClB,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,qBAiGA"}
@@ -0,0 +1,81 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { Animated, View } from 'react-native';
3
+ import { useTheme } from '@proximus/lavender-styling-native';
4
+ const appleSeedSizeL = 14;
5
+ const appleSeedSizeM = 10;
6
+ const appleSeedSizeS = 6;
7
+ const appleSeedSizeXS = 4;
8
+ export function PxAppleSeed({ numberOfItems, selectedItemIndex, }) {
9
+ const { theme } = useTheme();
10
+ const tx = useRef(new Animated.Value(0)).current;
11
+ const prevSelectedItemIndex = useRef(selectedItemIndex);
12
+ useEffect(() => {
13
+ if ((selectedItemIndex <= 2 && prevSelectedItemIndex.current != 3) ||
14
+ numberOfItems - selectedItemIndex < 3) {
15
+ return;
16
+ }
17
+ const translateLeft = selectedItemIndex > prevSelectedItemIndex.current ? -1 : 1;
18
+ const toValue = translateLeft
19
+ ? -1 * (selectedItemIndex - 2) * theme.t('SizeIconS').number
20
+ : (selectedItemIndex - 3) * theme.t('SizeIconS').number;
21
+ Animated.spring(tx, {
22
+ toValue,
23
+ useNativeDriver: true,
24
+ }).start();
25
+ prevSelectedItemIndex.current = selectedItemIndex;
26
+ }, [numberOfItems, selectedItemIndex, theme, tx]);
27
+ return (React.createElement(View, { style: {
28
+ flexDirection: 'row',
29
+ width: 5 * theme.t('SizeIconS').number,
30
+ justifyContent: numberOfItems < 5 ? 'center' : 'flex-start',
31
+ alignSelf: 'center',
32
+ overflow: 'hidden',
33
+ alignItems: 'center',
34
+ } }, Array.from({ length: numberOfItems }).map((_, index) => (React.createElement(Animated.View, { key: index, style: {
35
+ width: theme.t('SizeIconS').number,
36
+ height: theme.t('SizeIconS').number,
37
+ alignItems: 'center',
38
+ justifyContent: 'center',
39
+ transform: [
40
+ {
41
+ translateX: tx,
42
+ },
43
+ ],
44
+ } },
45
+ React.createElement(View, { key: index, style: {
46
+ borderWidth: theme.t('SizeBorderS').number,
47
+ height: numberOfItems > 5 ? appleSeedSizeXS : appleSeedSizeM,
48
+ width: numberOfItems > 5 ? appleSeedSizeXS : appleSeedSizeM,
49
+ borderRadius: theme.t('RadiusMain').number,
50
+ borderColor: theme.t('ColorBackgroundStateActiveDefault'),
51
+ ...(index === numberOfItems - 2 &&
52
+ numberOfItems > 6 && {
53
+ height: appleSeedSizeM,
54
+ width: appleSeedSizeM,
55
+ }),
56
+ ...(index === numberOfItems - 3 &&
57
+ numberOfItems > 5 && {
58
+ height: appleSeedSizeS,
59
+ width: appleSeedSizeS,
60
+ }),
61
+ ...((index === selectedItemIndex - 2 ||
62
+ index === selectedItemIndex + 2) &&
63
+ numberOfItems > 5 && {
64
+ height: appleSeedSizeS,
65
+ width: appleSeedSizeS,
66
+ }),
67
+ ...((index === selectedItemIndex - 1 ||
68
+ index === selectedItemIndex + 1) &&
69
+ numberOfItems > 5 && {
70
+ height: appleSeedSizeM,
71
+ width: appleSeedSizeM,
72
+ }),
73
+ ...(index === selectedItemIndex && {
74
+ backgroundColor: theme.t('ColorBackgroundStateActiveDefault'),
75
+ ...(numberOfItems > 5 && {
76
+ height: appleSeedSizeL,
77
+ width: appleSeedSizeL,
78
+ }),
79
+ }),
80
+ } }))))));
81
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { AccessibilityProps, StyleProp, ViewStyle } from 'react-native';
3
+ export declare function PxCarousel({ numberOfItemsVisible, children, withAppleSeed, containerStyle, testID, accessibilityProps, }: {
4
+ numberOfItemsVisible?: number;
5
+ children?: React.ReactNode;
6
+ withAppleSeed?: boolean;
7
+ containerStyle?: StyleProp<ViewStyle>;
8
+ testID?: string;
9
+ accessibilityProps?: AccessibilityProps;
10
+ }): React.JSX.Element;
11
+ //# sourceMappingURL=Carousel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../src/Carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EACL,kBAAkB,EAGlB,SAAS,EAET,SAAS,EACV,MAAM,cAAc,CAAC;AAOtB,wBAAgB,UAAU,CAAC,EACzB,oBAAwB,EACxB,QAAQ,EACR,aAAoB,EACpB,cAAc,EACd,MAAM,EACN,kBAAkB,GACnB,EAAE;IACD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,qBAgFA"}
@@ -0,0 +1,45 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Dimensions, FlatList, View, } from 'react-native';
3
+ import { useTheme } from '@proximus/lavender-styling-native';
4
+ import { PxAppleSeed } from './AppleSeed';
5
+ import { a11y, e2eID } from '@proximus/lavender-common-native';
6
+ const inset = 24;
7
+ export function PxCarousel({ numberOfItemsVisible = 1, children, withAppleSeed = true, containerStyle, testID, accessibilityProps, }) {
8
+ const [width, setWidth] = useState(0);
9
+ const [computedGap, setComputedGap] = useState(0);
10
+ const [elementsCount, setElementsCount] = useState(0);
11
+ const [selectedItemIndex, setSelectedItemIndex] = useState(0);
12
+ const [offsets, setOffsets] = useState([]);
13
+ const { theme } = useTheme();
14
+ useEffect(() => {
15
+ setWidth((Dimensions.get('window').width -
16
+ numberOfItemsVisible * computedGap -
17
+ 2 * inset) /
18
+ numberOfItemsVisible);
19
+ }, [numberOfItemsVisible, computedGap, theme]);
20
+ useEffect(() => {
21
+ setElementsCount(React.Children.count(children));
22
+ }, [children]);
23
+ useEffect(() => {
24
+ setComputedGap(theme.t(`SpacingSMobile`).number);
25
+ }, [theme]);
26
+ useEffect(() => {
27
+ setOffsets(new Array(elementsCount).fill(0).reduce((prev, _, i) => {
28
+ return [...prev, prev[i] + width + computedGap];
29
+ }, [width]));
30
+ }, [computedGap, elementsCount, width]);
31
+ return (React.createElement(View, { style: [containerStyle, { flexDirection: 'column', gap: 27.15, flex: 1 }], ...e2eID(testID), ...a11y(accessibilityProps) },
32
+ React.createElement(FlatList, { data: new Array(React.Children.count(children)).fill(0), renderItem: ({ index }) => (React.createElement(View, { style: { width } }, [...children]?.[index])), contentContainerStyle: {
33
+ gap: computedGap,
34
+ alignItems: 'stretch',
35
+ paddingLeft: computedGap,
36
+ }, horizontal: true, snapToOffsets: offsets, decelerationRate: "fast", snapToAlignment: numberOfItemsVisible === 1 ? 'center' : 'start', showsHorizontalScrollIndicator: false, onViewableItemsChanged: (event) => {
37
+ if (event.viewableItems.length === 2 &&
38
+ event.viewableItems?.[0]?.index === 0) {
39
+ setSelectedItemIndex(0);
40
+ return;
41
+ }
42
+ setSelectedItemIndex(event.viewableItems?.[1]?.index ?? 0);
43
+ } }, children),
44
+ withAppleSeed && elementsCount > 1 && (React.createElement(PxAppleSeed, { numberOfItems: React.Children.count(children), selectedItemIndex: selectedItemIndex }))));
45
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@proximus/lavender-carousel-native",
3
+ "version": "0.1.0-alpha.3",
4
+ "description": "Carousel component",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "peerDependencies": {
8
+ "@proximus/lavender-common-native": "*",
9
+ "@proximus/lavender-styling-native": "*"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "lerna": {
15
+ "command": {
16
+ "publish": {
17
+ "assets": [
18
+ {
19
+ "from": "dist/far/away/package.json",
20
+ "to": "."
21
+ },
22
+ "dist/*.js",
23
+ "dist/*.d.ts",
24
+ "dist/*.d.ts.map",
25
+ "src",
26
+ "package.json"
27
+ ]
28
+ }
29
+ }
30
+ },
31
+ "gitHead": "e50a17526561b3eafb159e36c737173956093e0d"
32
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Carousel';
2
+ export * from './AppleSeed';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './Carousel';
2
+ export * from './AppleSeed';
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@proximus/lavender-carousel-native",
3
+ "version": "0.1.0-alpha.3",
4
+ "description": "Carousel component",
5
+ "license": "MIT",
6
+ "main": "src/index.ts",
7
+ "scripts": {
8
+ "clean": "rm -rf dist",
9
+ "transform-package-json": "node ../../../scripts/tranformPackageJson.js package.json dist/far/away",
10
+ "prepublish": "yarn clean && yarn transform-package-json && yarn build",
11
+ "build": "npx tsc -p tsconfig.json"
12
+ },
13
+ "peerDependencies": {
14
+ "@proximus/lavender-common-native": "workspace:*",
15
+ "@proximus/lavender-styling-native": "workspace:*"
16
+ },
17
+ "devDependencies": {
18
+ "@proximus/lavender-common-native": "0.1.0-alpha.6",
19
+ "@proximus/lavender-styling-native": "0.1.0-alpha.5"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "lerna": {
25
+ "command": {
26
+ "publish": {
27
+ "assets": [
28
+ {
29
+ "from": "dist/far/away/package.json",
30
+ "to": "."
31
+ },
32
+ "dist/*.js",
33
+ "dist/*.d.ts",
34
+ "dist/*.d.ts.map",
35
+ "src",
36
+ "package.json"
37
+ ]
38
+ }
39
+ }
40
+ },
41
+ "gitHead": "e50a17526561b3eafb159e36c737173956093e0d"
42
+ }
@@ -0,0 +1,113 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { Animated, View } from 'react-native';
3
+ import { useTheme } from '@proximus/lavender-styling-native';
4
+
5
+ const appleSeedSizeL = 14;
6
+ const appleSeedSizeM = 10;
7
+ const appleSeedSizeS = 6;
8
+ const appleSeedSizeXS = 4;
9
+
10
+ export function PxAppleSeed({
11
+ numberOfItems,
12
+ selectedItemIndex,
13
+ }: {
14
+ numberOfItems: number;
15
+ selectedItemIndex: number;
16
+ }) {
17
+ const { theme } = useTheme();
18
+ const tx = useRef(new Animated.Value(0)).current;
19
+ const prevSelectedItemIndex = useRef(selectedItemIndex);
20
+
21
+ useEffect(() => {
22
+ if (
23
+ (selectedItemIndex <= 2 && prevSelectedItemIndex.current != 3) ||
24
+ numberOfItems - selectedItemIndex < 3
25
+ ) {
26
+ return;
27
+ }
28
+
29
+ const translateLeft =
30
+ selectedItemIndex > prevSelectedItemIndex.current ? -1 : 1;
31
+
32
+ const toValue = translateLeft
33
+ ? -1 * (selectedItemIndex - 2) * theme.t('SizeIconS').number
34
+ : (selectedItemIndex - 3) * theme.t('SizeIconS').number;
35
+
36
+ Animated.spring(tx, {
37
+ toValue,
38
+ useNativeDriver: true,
39
+ }).start();
40
+
41
+ prevSelectedItemIndex.current = selectedItemIndex;
42
+ }, [numberOfItems, selectedItemIndex, theme, tx]);
43
+
44
+ return (
45
+ <View
46
+ style={{
47
+ flexDirection: 'row',
48
+ width: 5 * theme.t('SizeIconS').number,
49
+ justifyContent: numberOfItems < 5 ? 'center' : 'flex-start',
50
+ alignSelf: 'center',
51
+ overflow: 'hidden',
52
+ alignItems: 'center',
53
+ }}
54
+ >
55
+ {Array.from({ length: numberOfItems }).map((_, index) => (
56
+ <Animated.View
57
+ key={index}
58
+ style={{
59
+ width: theme.t('SizeIconS').number,
60
+ height: theme.t('SizeIconS').number,
61
+ alignItems: 'center',
62
+ justifyContent: 'center',
63
+ transform: [
64
+ {
65
+ translateX: tx,
66
+ },
67
+ ],
68
+ }}
69
+ >
70
+ <View
71
+ key={index}
72
+ style={{
73
+ borderWidth: theme.t('SizeBorderS').number,
74
+ height: numberOfItems > 5 ? appleSeedSizeXS : appleSeedSizeM,
75
+ width: numberOfItems > 5 ? appleSeedSizeXS : appleSeedSizeM,
76
+ borderRadius: theme.t('RadiusMain').number,
77
+ borderColor: theme.t('ColorBackgroundStateActiveDefault'),
78
+ ...(index === numberOfItems - 2 &&
79
+ numberOfItems > 6 && {
80
+ height: appleSeedSizeM,
81
+ width: appleSeedSizeM,
82
+ }),
83
+ ...(index === numberOfItems - 3 &&
84
+ numberOfItems > 5 && {
85
+ height: appleSeedSizeS,
86
+ width: appleSeedSizeS,
87
+ }),
88
+ ...((index === selectedItemIndex - 2 ||
89
+ index === selectedItemIndex + 2) &&
90
+ numberOfItems > 5 && {
91
+ height: appleSeedSizeS,
92
+ width: appleSeedSizeS,
93
+ }),
94
+ ...((index === selectedItemIndex - 1 ||
95
+ index === selectedItemIndex + 1) &&
96
+ numberOfItems > 5 && {
97
+ height: appleSeedSizeM,
98
+ width: appleSeedSizeM,
99
+ }),
100
+ ...(index === selectedItemIndex && {
101
+ backgroundColor: theme.t('ColorBackgroundStateActiveDefault'),
102
+ ...(numberOfItems > 5 && {
103
+ height: appleSeedSizeL,
104
+ width: appleSeedSizeL,
105
+ }),
106
+ }),
107
+ }}
108
+ />
109
+ </Animated.View>
110
+ ))}
111
+ </View>
112
+ );
113
+ }
@@ -0,0 +1,110 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import {
3
+ AccessibilityProps,
4
+ Dimensions,
5
+ FlatList,
6
+ StyleProp,
7
+ View,
8
+ ViewStyle,
9
+ } from 'react-native';
10
+ import { useTheme } from '@proximus/lavender-styling-native';
11
+ import { PxAppleSeed } from './AppleSeed';
12
+ import { a11y, e2eID } from '@proximus/lavender-common-native';
13
+
14
+ const inset = 24;
15
+
16
+ export function PxCarousel({
17
+ numberOfItemsVisible = 1,
18
+ children,
19
+ withAppleSeed = true,
20
+ containerStyle,
21
+ testID,
22
+ accessibilityProps,
23
+ }: {
24
+ numberOfItemsVisible?: number;
25
+ children?: React.ReactNode;
26
+ withAppleSeed?: boolean;
27
+ containerStyle?: StyleProp<ViewStyle>;
28
+ testID?: string;
29
+ accessibilityProps?: AccessibilityProps;
30
+ }) {
31
+ const [width, setWidth] = useState(0);
32
+ const [computedGap, setComputedGap] = useState(0);
33
+ const [elementsCount, setElementsCount] = useState(0);
34
+ const [selectedItemIndex, setSelectedItemIndex] = useState(0);
35
+ const [offsets, setOffsets] = useState([]);
36
+ const { theme } = useTheme();
37
+
38
+ useEffect(() => {
39
+ setWidth(
40
+ (Dimensions.get('window').width -
41
+ numberOfItemsVisible * computedGap -
42
+ 2 * inset) /
43
+ numberOfItemsVisible
44
+ );
45
+ }, [numberOfItemsVisible, computedGap, theme]);
46
+
47
+ useEffect(() => {
48
+ setElementsCount(React.Children.count(children));
49
+ }, [children]);
50
+
51
+ useEffect(() => {
52
+ setComputedGap(theme.t(`SpacingSMobile`).number);
53
+ }, [theme]);
54
+
55
+ useEffect(() => {
56
+ setOffsets(
57
+ new Array(elementsCount).fill(0).reduce(
58
+ (prev, _, i) => {
59
+ return [...prev, prev[i] + width + computedGap];
60
+ },
61
+ [width]
62
+ )
63
+ );
64
+ }, [computedGap, elementsCount, width]);
65
+
66
+ return (
67
+ <View
68
+ style={[containerStyle, { flexDirection: 'column', gap: 27.15, flex: 1 }]}
69
+ {...e2eID(testID)}
70
+ {...a11y(accessibilityProps)}
71
+ >
72
+ <FlatList
73
+ data={new Array(React.Children.count(children)).fill(0)}
74
+ renderItem={({ index }) => (
75
+ <View style={{ width }}>
76
+ {[...(children as Iterable<any>)]?.[index]}
77
+ </View>
78
+ )}
79
+ contentContainerStyle={{
80
+ gap: computedGap,
81
+ alignItems: 'stretch',
82
+ paddingLeft: computedGap,
83
+ }}
84
+ horizontal
85
+ snapToOffsets={offsets}
86
+ decelerationRate="fast"
87
+ snapToAlignment={numberOfItemsVisible === 1 ? 'center' : 'start'}
88
+ showsHorizontalScrollIndicator={false}
89
+ onViewableItemsChanged={(event) => {
90
+ if (
91
+ event.viewableItems.length === 2 &&
92
+ event.viewableItems?.[0]?.index === 0
93
+ ) {
94
+ setSelectedItemIndex(0);
95
+ return;
96
+ }
97
+ setSelectedItemIndex(event.viewableItems?.[1]?.index ?? 0);
98
+ }}
99
+ >
100
+ {children}
101
+ </FlatList>
102
+ {withAppleSeed && elementsCount > 1 && (
103
+ <PxAppleSeed
104
+ numberOfItems={React.Children.count(children)}
105
+ selectedItemIndex={selectedItemIndex}
106
+ />
107
+ )}
108
+ </View>
109
+ );
110
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './Carousel';
2
+ export * from './AppleSeed';
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../tsconfig.npm.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ },
6
+ "include": ["src","../../../lib.d.ts"],
7
+ "exclude": ["dist", "node_modules", "src/**/*.spec.tsx", "src/**/*.spec.ts"]
8
+ }