From 96573d94030324579b1eb101dd33ff55fefce7db Mon Sep 17 00:00:00 2001
From: Inbal Tish <33805983+Inbal-Tish@users.noreply.github.com>
Date: Mon, 29 Jul 2024 10:22:59 +0300
Subject: [PATCH 01/14] TextField - add margin btw bottom elements and char
counter (#3185)
* TestField - add margin btw bottom elements and char counter
* TestField - add tests for changing validationMassage
* fix margin condition
* fix snap tests
---
.../TextFieldScreen.spec.js.snap | 10 ++++++--
.../textField/__tests__/index.driver.spec.tsx | 25 +++++++++++++++++++
src/components/textField/index.tsx | 2 +-
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap b/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
index b3311c5eb7..59a61c4514 100644
--- a/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
+++ b/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
@@ -2205,6 +2205,7 @@ exports[`TextField Screen renders screen 1`] = `
}
>
{
expect(textFieldDriver.getValidationMessage().exists()).toBe(!!defaultProps?.preset);
});
+ it('should render validationMessage if validationMessage passed and remove it when validationMessage is changed to undefined', () => {
+ const renderTree = render();
+ const textFieldDriver = TextFieldDriver({renderTree, testID: TEXT_FIELD_TEST_ID});
+
+ expect(textFieldDriver.getValidationMessage().exists()).toBe(true);
+ expect(textFieldDriver.getValidationMessage().getText()).toEqual('mock message');
+
+ renderTree.rerender();
+
+ expect(textFieldDriver.getValidationMessage().exists()).toBe(false);
+ });
+
+ it('should not render validationMessage if validationMessage is undefined and add it when validationMessage is passed', () => {
+ const renderTree = render();
+ const textFieldDriver = TextFieldDriver({renderTree, testID: TEXT_FIELD_TEST_ID});
+
+ expect(textFieldDriver.getValidationMessage().exists()).toBe(false);
+
+ renderTree.rerender();
+
+ expect(textFieldDriver.getValidationMessage().exists()).toBe(true);
+ expect(textFieldDriver.getValidationMessage().getText()).toEqual('mock message');
+ });
+
+
it('should render validationMessage on start if input required and validateOnStart passed', () => {
const renderTree = render();
const textFieldDriver = TextFieldDriver({renderTree, testID: TEXT_FIELD_TEST_ID});
diff --git a/src/components/textField/index.tsx b/src/components/textField/index.tsx
index 3fc4e308ab..e2e1ac8a53 100644
--- a/src/components/textField/index.tsx
+++ b/src/components/textField/index.tsx
@@ -209,7 +209,7 @@ const TextField = (props: InternalTextFieldProps) => {
{/* */}
-
+
{validationMessagePosition === ValidationMessagePosition.BOTTOM && (
Date: Mon, 29 Jul 2024 10:53:39 +0300
Subject: [PATCH 02/14] fix: broken links in docs (#3186)
Co-authored-by: Ethan Sharabi <1780255+ethanshar@users.noreply.github.com>
---
docs/foundation/modifiers.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/foundation/modifiers.md b/docs/foundation/modifiers.md
index fd8c874450..31b1d34cc4 100644
--- a/docs/foundation/modifiers.md
+++ b/docs/foundation/modifiers.md
@@ -112,9 +112,9 @@ The last type of modifiers is for styling your components
```
-! all styling modifiers are based on our [`Colors` & `Typography` presets](/docs/foundation/style).
+! all styling modifiers are based on our [`Colors` & `Typography` presets](/docs/foundation/style.md).
You can load your own presets and use them as modifiers.
-Check out [this example](/docs/getting-started/usage) where we use most of these props.
+Check out [this example](/docs/getting-started/usage.md) where we use most of these props.
From 1efcf9761f709bf3726e578f09fb4a82661c5ca6 Mon Sep 17 00:00:00 2001
From: Ethan Sharabi <1780255+ethanshar@users.noreply.github.com>
Date: Mon, 29 Jul 2024 11:50:26 +0300
Subject: [PATCH 03/14] Revert "fix: broken links in docs (#3186)" (#3187)
This reverts commit 318052002b4764fe4911ca9c816e626763fa04fa.
---
docs/foundation/modifiers.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/foundation/modifiers.md b/docs/foundation/modifiers.md
index 31b1d34cc4..fd8c874450 100644
--- a/docs/foundation/modifiers.md
+++ b/docs/foundation/modifiers.md
@@ -112,9 +112,9 @@ The last type of modifiers is for styling your components
```
-! all styling modifiers are based on our [`Colors` & `Typography` presets](/docs/foundation/style.md).
+! all styling modifiers are based on our [`Colors` & `Typography` presets](/docs/foundation/style).
You can load your own presets and use them as modifiers.
-Check out [this example](/docs/getting-started/usage.md) where we use most of these props.
+Check out [this example](/docs/getting-started/usage) where we use most of these props.
From df555a67cef3ca04cef5ae2912f06e27b7eb146c Mon Sep 17 00:00:00 2001
From: Inbal Tish <33805983+Inbal-Tish@users.noreply.github.com>
Date: Tue, 30 Jul 2024 09:40:28 +0300
Subject: [PATCH 04/14] TextField - show validation icon only with validation
massage (#3189)
---
src/components/textField/ValidationMessage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/textField/ValidationMessage.tsx b/src/components/textField/ValidationMessage.tsx
index 8c6b5a3f95..1ed180f7da 100644
--- a/src/components/textField/ValidationMessage.tsx
+++ b/src/components/textField/ValidationMessage.tsx
@@ -39,7 +39,7 @@ const ValidationMessage = ({
if (validationIcon?.source) {
return (
- {showValidationMessage &&
+ {showValidationMessage && validationMessage &&
}
{renderMessage()}
From e74ea4cbc6531002c7eccdbe37162760c7b8a981 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 30 Jul 2024 13:37:16 +0300
Subject: [PATCH 05/14] Bump fast-xml-parser from 4.3.6 to 4.4.1 (#3188)
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.3.6 to 4.4.1.
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.3.6...v4.4.1)
---
updated-dependencies:
- dependency-name: fast-xml-parser
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
yarn.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index bcf5d50ea5..38a19e9cb7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4204,9 +4204,9 @@ fast-levenshtein@^2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-xml-parser@^4.0.12:
- version "4.3.6"
- resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz#190f9d99097f0c8f2d3a0e681a10404afca052ff"
- integrity sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f"
+ integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==
dependencies:
strnum "^1.0.5"
From 684fa1b05b053de8b9d2d7f75ed557ac456d074d Mon Sep 17 00:00:00 2001
From: Miki Leib <38354019+M-i-k-e-l@users.noreply.github.com>
Date: Tue, 30 Jul 2024 14:17:21 +0300
Subject: [PATCH 06/14] Remove some old unused drivers (#3190)
---
src/components/button/Button.driver.ts | 36 -----------
src/components/carousel/Carousel.driver.ts | 7 ---
src/components/picker/Picker.driver.ts | 7 ---
.../sortableList/SortableListItem.driver.ts | 36 -----------
src/incubator/Dialog/__tests__/index.spec.tsx | 60 -------------------
5 files changed, 146 deletions(-)
delete mode 100644 src/components/button/Button.driver.ts
delete mode 100644 src/components/carousel/Carousel.driver.ts
delete mode 100644 src/components/picker/Picker.driver.ts
delete mode 100644 src/components/sortableList/SortableListItem.driver.ts
delete mode 100644 src/incubator/Dialog/__tests__/index.spec.tsx
diff --git a/src/components/button/Button.driver.ts b/src/components/button/Button.driver.ts
deleted file mode 100644
index eb609483f3..0000000000
--- a/src/components/button/Button.driver.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import {ButtonProps} from './types';
-import {ImageDriver} from '../image/Image.driver';
-import {ComponentDriver, ComponentDriverArgs} from '../../testkit/Component.driver';
-import {TextDriver} from '../text/Text.driver';
-
-/**
- * Please run clear after each test
- */
-export class ButtonDriver extends ComponentDriver {
- private readonly labelDriver: TextDriver;
- private readonly iconDriver: ImageDriver;
-
- constructor(componentDriverArgs: ComponentDriverArgs) {
- super(componentDriverArgs);
-
- this.labelDriver = new TextDriver({...componentDriverArgs, testID: `${this.testID}.label`});
- this.iconDriver = new ImageDriver({...componentDriverArgs, testID: `${this.testID}.icon`});
- }
-
- isPressable = async () => {
- if (await this.exists()) {
- return typeof (await this.getElementProps()).onPress === 'function';
- } else {
- console.warn(`TextDriver: cannot click because testID:${this.testID} were not found`);
- return null;
- }
- };
-
- // label
- getLabelRootElement = () => this.labelDriver.getElement();
- isLabelExists = () => this.labelDriver.exists();
- getLabelContent = () => this.labelDriver.getTextContent();
- // icon
- getIconElement = () => this.iconDriver.getElement();
- isIconExists = () => this.iconDriver.exists();
-}
diff --git a/src/components/carousel/Carousel.driver.ts b/src/components/carousel/Carousel.driver.ts
deleted file mode 100644
index 0b8303a920..0000000000
--- a/src/components/carousel/Carousel.driver.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import {CarouselProps} from './types';
-import {ComponentDriver} from '../../testkit/Component.driver';
-
-export class CarouselDriver extends ComponentDriver {
- getContentOffset = async () => (await this.getElementProps()).contentOffset;
- scroll = async (delta: number) => (await this.uniDriver.selectorByTestId(this.testID)).scrollX(delta);
-}
diff --git a/src/components/picker/Picker.driver.ts b/src/components/picker/Picker.driver.ts
deleted file mode 100644
index 6056991456..0000000000
--- a/src/components/picker/Picker.driver.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import {PickerProps} from './types';
-import {ComponentDriver} from '../../testkit/Component.driver';
-
-export class PickerDriver extends ComponentDriver {
- getPickerOverlay = async () => await this.getByTestId(`${this.testID}.overlay`);
- getPickerOverlayProps = async () => await this.getPropsByTestId(`${this.testID}.overlay`);
-}
diff --git a/src/components/sortableList/SortableListItem.driver.ts b/src/components/sortableList/SortableListItem.driver.ts
deleted file mode 100644
index 0e14a50bb4..0000000000
--- a/src/components/sortableList/SortableListItem.driver.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import _ from 'lodash';
-import {SortableListProps, SortableListItemProps} from './types';
-import {ComponentDriver} from '../../testkit/Component.driver';
-
-/**
- * Please run clear after each test
- */
-export class SortableListItemDriver extends ComponentDriver> {
- dragUp = async (indices: number) => {
- this.validateIndices(indices);
- const data = _.times(indices, index => {
- return {
- translationY: -52 * (index + 1)
- };
- });
-
- await this.uniDriver.selectorByTestId(this.testID).then(driver => driver.drag(data));
- };
-
- dragDown = async (indices: number) => {
- this.validateIndices(indices);
- const data = _.times(indices, index => {
- return {
- translationY: 52 * (index + 1)
- };
- });
-
- await this.uniDriver.selectorByTestId(this.testID).then(driver => driver.drag(data));
- };
-
- private validateIndices = (indices: number) => {
- if (indices <= 0 || !Number.isInteger(indices)) {
- throw Error('indices must be a positive integer');
- }
- };
-}
diff --git a/src/incubator/Dialog/__tests__/index.spec.tsx b/src/incubator/Dialog/__tests__/index.spec.tsx
deleted file mode 100644
index b2432bb7a3..0000000000
--- a/src/incubator/Dialog/__tests__/index.spec.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import React, {useCallback, useEffect, useState} from 'react';
-import Button from '../../../components/button';
-import View from '../../../components/view';
-import Dialog from '../index';
-import {ComponentDriver} from '../../../testkit/Component.driver';
-import {ButtonDriver} from '../../../components/button/Button.driver';
-
-const onDismiss = () => {};
-
-const defaultProps = {
- testID: 'dialog',
- useSafeArea: true,
- onDismiss,
- bottom: true,
- centerH: true
-};
-
-const TestCase = props => {
- const [visible, setVisible] = useState(props.visible);
-
- useEffect(() => {
- setVisible(props.visible);
- }, [props.visible]);
-
- const openDialog = useCallback(() => {
- setVisible(true);
- }, []);
-
- const closeDialog = useCallback(() => {
- setVisible(false);
- }, []);
-
- return (
-
-
-
- );
-};
-
-describe('Incubator.Dialog', () => {
- it('Incubator.Dialog should exist only if visible', async () => {
- const onDismiss = jest.fn();
- const component = ;
- const dialogDriver = new ComponentDriver({component, testID: 'dialog'});
- expect(await dialogDriver.exists()).toBeFalsy();
- const openButtonDriver = new ButtonDriver({component, testID: 'openButton'});
- await openButtonDriver.press();
- expect(await dialogDriver.exists()).toBeTruthy();
- expect(onDismiss).toHaveBeenCalledTimes(0);
- const closeButtonDriver = new ButtonDriver({component, testID: 'closeButton'});
- await closeButtonDriver.press();
- expect(await dialogDriver.exists()).toBeFalsy();
- expect(onDismiss).toHaveBeenCalledTimes(1);
- });
-});
From dfdb5f51e684ee1ca02f7177b8aac797b74dc893 Mon Sep 17 00:00:00 2001
From: Nitzan Yizhar
Date: Wed, 31 Jul 2024 12:01:29 +0300
Subject: [PATCH 07/14] SortableGridList - Order items by index (#3171)
* added option for items to move by index and not by switching places
* fixed toggling of ordering method
* props rename
* updated api.json
* added tests for index ordering
* fixed description
* changed inner prop to be optional
* chaned custom switch to use renderBooleanOption
* renamed to test case
* changed replace to swap
* removed extra component import
* added more documentation
* renamed prop
* renamed prop
* added test for swapping items
* moved import location
---
.../SortableGridListScreen.tsx | 16 ++++--
.../sortableGridList/SortableItem.tsx | 23 +++++++--
.../sortableGridList/__tests__/index.spec.tsx | 50 +++++++++++++++++++
src/components/sortableGridList/index.tsx | 5 +-
.../sortableGridList.api.json | 5 ++
src/components/sortableGridList/types.ts | 6 +++
6 files changed, 94 insertions(+), 11 deletions(-)
create mode 100644 src/components/sortableGridList/__tests__/index.spec.tsx
diff --git a/demo/src/screens/componentScreens/SortableGridListScreen.tsx b/demo/src/screens/componentScreens/SortableGridListScreen.tsx
index c68f51d42f..dfad103b0a 100644
--- a/demo/src/screens/componentScreens/SortableGridListScreen.tsx
+++ b/demo/src/screens/componentScreens/SortableGridListScreen.tsx
@@ -14,16 +14,18 @@ import {
} from 'react-native-ui-lib';
import _ from 'lodash';
import products from '../../data/products';
+import {renderBooleanOption} from '../ExampleScreenPresenter';
-const productsWithIds = products.map((product) => ({...product}));
-type Item = typeof productsWithIds[0];
+const productsWithIds = products.map(product => ({...product}));
+type Item = (typeof productsWithIds)[0];
class SortableGridListScreen extends Component {
state = {
orientation: Constants.orientation,
selectedItemId: undefined,
items: productsWithIds,
- removedItems: [] as Item[]
+ removedItems: [] as Item[],
+ shouldOrderByIndex: false
};
itemsOrdered = this.state.items;
@@ -44,7 +46,7 @@ class SortableGridListScreen extends Component {
removeSelectedItem = () => {
const {selectedItemId, removedItems} = this.state;
if (!_.isUndefined(selectedItemId)) {
- const newItems = [...this.itemsOrdered];
+ const newItems = [...this.itemsOrdered];
const removed = _.remove(newItems, item => item.id === selectedItemId);
removedItems.push(removed[0]);
this.setState({items: newItems, selectedItemId: undefined, removedItems});
@@ -83,7 +85,7 @@ class SortableGridListScreen extends Component {
};
render() {
- const {items, removedItems, selectedItemId} = this.state;
+ const {items, removedItems, selectedItemId, shouldOrderByIndex} = this.state;
return (
@@ -98,6 +100,9 @@ class SortableGridListScreen extends Component {
/>
+
+ {renderBooleanOption.call(this, 'Order by index', 'shouldOrderByIndex')}
+
diff --git a/src/components/sortableGridList/SortableItem.tsx b/src/components/sortableGridList/SortableItem.tsx
index a42cf9e75d..6f7c4ee023 100644
--- a/src/components/sortableGridList/SortableItem.tsx
+++ b/src/components/sortableGridList/SortableItem.tsx
@@ -26,7 +26,8 @@ function SortableItem(props: PropsWithChildren {
isDragging.value = true;
-
const translation = getTranslationByOrderChange(currIndex.value, initialIndex.value);
translateX.value = translation.x;
translateY.value = translation.y;
@@ -134,8 +134,23 @@ function SortableItem(props: PropsWithChildren oldOrder;
+ if (shouldMoveOthersDown) {
+ for (let i = oldOrder; i < newOrder; i++) {
+ newItemsOrder[i] = itemsOrder.value[i + 1];
+ }
+ } else {
+ for (let i = oldOrder; i > newOrder; i--) {
+ newItemsOrder[i] = itemsOrder.value[i - 1];
+ }
+ }
+ newItemsOrder[newOrder] = id;
+ } else {
+ newItemsOrder[newOrder] = id;
+ newItemsOrder[oldOrder] = itemIdToSwap;
+ }
+
itemsOrder.value = newItemsOrder;
}
}
diff --git a/src/components/sortableGridList/__tests__/index.spec.tsx b/src/components/sortableGridList/__tests__/index.spec.tsx
new file mode 100644
index 0000000000..663fb496e7
--- /dev/null
+++ b/src/components/sortableGridList/__tests__/index.spec.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+import {render} from '@testing-library/react-native';
+import View from '../../view';
+import Text from '../../text';
+import SortableGridList, {SortableGridListProps} from '../';
+import {useDraggableDriver} from '../../../testkit/new/useDraggable.driver';
+import {useComponentDriver} from '../../../testkit/new/Component.driver';
+
+const testID = 'sortable-grid-list';
+const TEST_DATA = Array(9)
+ .fill(0)
+ .map((_, index) => ({id: `${index}`}));
+const itemsTestId = (id: string) => `${testID}.item.${id}`;
+const testRenderItem: SortableGridListProps<(typeof TEST_DATA)[number]>['renderItem'] = ({item}) => {
+ return (
+
+ {item.id}
+
+ );
+};
+
+const TestCase = (props: Omit) => {
+ return ;
+};
+
+describe('SortableGridlist', () => {
+ it('should render a sortable grid list', () => {
+ render();
+ });
+ it('should reorder by index', () => {
+ const onOrderChange = jest.fn();
+ const renderTree = render();
+ const driverItem = useDraggableDriver(useComponentDriver({renderTree, testID: itemsTestId('0')}));
+ driverItem.drag(150); // Items height is 50 but dragging 100 doesn't work for some reason. 150 works and drags one row down.
+ expect(onOrderChange).toHaveBeenCalledTimes(1);
+ const newOrder = [1, 2, 3, 0, 4, 5, 6, 7, 8];
+ expect(onOrderChange).toHaveBeenCalledWith(newOrder.map(index => TEST_DATA[index]),
+ newOrder.map(index => TEST_DATA[index].id));
+ });
+ it('should reorder by swapping', () => {
+ const onOrderChange = jest.fn();
+ const renderTree = render();
+ const driverItem = useDraggableDriver(useComponentDriver({renderTree, testID: itemsTestId('0')}));
+ driverItem.drag(150);
+ expect(onOrderChange).toHaveBeenCalledTimes(1);
+ const newOrder = [3, 1, 2, 0, 4, 5, 6, 7, 8];
+ expect(onOrderChange).toHaveBeenCalledWith(newOrder.map(index => TEST_DATA[index]),
+ newOrder.map(index => TEST_DATA[index].id));
+ });
+});
diff --git a/src/components/sortableGridList/index.tsx b/src/components/sortableGridList/index.tsx
index 0dbed5eb5a..e231582681 100644
--- a/src/components/sortableGridList/index.tsx
+++ b/src/components/sortableGridList/index.tsx
@@ -17,7 +17,7 @@ function generateItemsOrder(data: SortableGridListProps['data']) {
}
function SortableGridList(props: SortableGridListProps) {
- const {renderItem, onOrderChange, flexMigration, ...others} = props;
+ const {renderItem, onOrderChange, flexMigration, orderByIndex = false, ...others} = props;
const {itemContainerStyle, numberOfColumns, listStyle, listContentStyle, listColumnWrapperStyle} =
useGridLayout(props);
@@ -60,13 +60,14 @@ function SortableGridList(props: SortableGridListProps) {
itemsOrder={itemsOrder}
id={item.id}
onChange={onChange}
+ orderByIndex={orderByIndex}
>
{/* @ts-expect-error */}
{renderItem({item, index})}
);
},
- [data, itemContainerStyle, onChange, renderItem]);
+ [data, itemContainerStyle, onChange, renderItem, orderByIndex]);
return (
diff --git a/src/components/sortableGridList/sortableGridList.api.json b/src/components/sortableGridList/sortableGridList.api.json
index b4b20023a8..d0cab53927 100644
--- a/src/components/sortableGridList/sortableGridList.api.json
+++ b/src/components/sortableGridList/sortableGridList.api.json
@@ -27,6 +27,11 @@
"name": "flexMigration",
"type": "boolean",
"description": "A temporary migration flag for enabling flex on the list's container (like it should be by default)"
+ },
+ {
+ "name": "orderByIndex",
+ "type": "boolean",
+ "description": "Wether to reorder the items by index instead of by swapping locations.\nItems will move to the new index by pushing other items ahead or aback instead of swapping places with the item at the new index."
}
],
"snippet": [
diff --git a/src/components/sortableGridList/types.ts b/src/components/sortableGridList/types.ts
index 44ced27dcf..2e072bba12 100644
--- a/src/components/sortableGridList/types.ts
+++ b/src/components/sortableGridList/types.ts
@@ -16,6 +16,11 @@ export interface SortableGridListProps extends GridListBaseProps, Scrol
* Temporary migration flag for enabling flex on the container of the list (like it should be by default)
*/
flexMigration?: boolean;
+ /**
+ * Wether to reorder the items by index instead of by replacing locations.
+ * Items will move to the new index by pushing other items ahead or aback instead of swapping places with the item at the new index.
+ */
+ orderByIndex?: boolean
}
export interface SortableItemProps {
@@ -24,4 +29,5 @@ export interface SortableItemProps {
itemsOrder: Animated.SharedValue;
onChange: () => void;
style: StyleProp;
+ orderByIndex?: boolean;
}
From 6c5f8b2aa242f6b0a12e11bf1e70b654315c640b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=96=9B=E5=A4=A7=E4=BE=A0?=
<46771139+crazyshakalaka@users.noreply.github.com>
Date: Thu, 1 Aug 2024 19:22:30 +0800
Subject: [PATCH 08/14] bugfix: remove TabController.TabBar defaultProps, use
JavaScript default parameters instead. (#3155)
Co-authored-by: Spring Xue
---
src/components/tabController/TabBar.tsx | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/src/components/tabController/TabBar.tsx b/src/components/tabController/TabBar.tsx
index 4c7c50f89f..adda6923bf 100644
--- a/src/components/tabController/TabBar.tsx
+++ b/src/components/tabController/TabBar.tsx
@@ -142,8 +142,8 @@ const TabBar = (props: Props) => {
enableShadow,
shadowStyle: propsShadowStyle,
indicatorStyle,
- labelStyle,
- selectedLabelStyle,
+ labelStyle = DEFAULT_LABEL_STYLE,
+ selectedLabelStyle = DEFAULT_SELECTED_LABEL_STYLE,
labelColor,
selectedLabelColor,
uppercase,
@@ -151,10 +151,10 @@ const TabBar = (props: Props) => {
selectedIconColor,
activeBackgroundColor,
backgroundColor = Colors.$backgroundElevated,
- faderProps,
+ faderProps = DEFAULT_FADER_PROPS,
containerWidth: propsContainerWidth,
centerSelected,
- spreadItems,
+ spreadItems = true,
indicatorInsets = Spacings.s4,
indicatorWidth,
containerStyle,
@@ -319,12 +319,6 @@ const TabBar = (props: Props) => {
};
TabBar.displayName = 'TabController.TabBar';
-TabBar.defaultProps = {
- labelStyle: DEFAULT_LABEL_STYLE,
- selectedLabelStyle: DEFAULT_SELECTED_LABEL_STYLE,
- faderProps: DEFAULT_FADER_PROPS,
- spreadItems: true
-};
const styles = StyleSheet.create({
container: {
From 9c31199725e192ba70293dc0a8daa3e4544b7156 Mon Sep 17 00:00:00 2001
From: Inbal Tish
Date: Sun, 4 Aug 2024 11:15:38 +0300
Subject: [PATCH 09/14] menu entry fix
---
demo/src/screens/MenuStructure.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/demo/src/screens/MenuStructure.js b/demo/src/screens/MenuStructure.js
index 05014f74ef..4b85987a68 100644
--- a/demo/src/screens/MenuStructure.js
+++ b/demo/src/screens/MenuStructure.js
@@ -194,7 +194,7 @@ export const navigationData = {
tags: 'text field expandable input picker',
screen: 'unicorn.components.IncubatorExpandableOverlayScreen'
},
- {title: 'Pan View', tags: 'pan swipe drag', screen: 'unicorn.incubator.PanViewScreen'}
+ {title: 'PanView', tags: 'pan swipe drag', screen: 'unicorn.incubator.PanViewScreen'}
]
},
Inspirations: {
From c2eee8fd3ada8bf7eb65790991fe1b0335459131 Mon Sep 17 00:00:00 2001
From: Nitzan Yizhar
Date: Sun, 4 Aug 2024 14:52:47 +0300
Subject: [PATCH 10/14] added handling for custom testid in the sections
(#3193)
---
.../sectionsWheelPicker/SectionsWheelPicker.driver.tsx | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/components/sectionsWheelPicker/SectionsWheelPicker.driver.tsx b/src/components/sectionsWheelPicker/SectionsWheelPicker.driver.tsx
index a823230601..2c8e02b492 100644
--- a/src/components/sectionsWheelPicker/SectionsWheelPicker.driver.tsx
+++ b/src/components/sectionsWheelPicker/SectionsWheelPicker.driver.tsx
@@ -1,16 +1,17 @@
import _ from 'lodash';
+import type {ReactTestInstance} from 'react-test-renderer';
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';
import {WheelPickerDriver} from '../WheelPicker/WheelPicker.driver';
-import {SectionsWheelPickerProps} from './index';
+import type {SectionsWheelPickerProps} from './index';
export const SectionsWheelPickerDriver = (props: ComponentProps) => {
const driver = useComponentDriver(props);
- const sections = driver.getElement().children as SectionsWheelPickerProps['sections'];
+ const sections = _.map(driver.getElement().children as ReactTestInstance[], (child) => child.props) as SectionsWheelPickerProps['sections'];
const sectionsDrivers = _.map(sections, (section, index) => {
const sectionTestID = `${props.testID}.${index}`;
return WheelPickerDriver({
renderTree: props.renderTree,
- testID: section?.testID || sectionTestID
+ testID: section.testID || sectionTestID
});
});
return {...driver, sections, sectionsDrivers};
From d141e7b3634ef875e349b36d6e4b74a0df9ebe31 Mon Sep 17 00:00:00 2001
From: Inbal Tish
Date: Mon, 5 Aug 2024 15:15:33 +0300
Subject: [PATCH 11/14] TextFieldScreen - preset to undefined
---
demo/src/screens/componentScreens/TextFieldScreen.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/demo/src/screens/componentScreens/TextFieldScreen.tsx b/demo/src/screens/componentScreens/TextFieldScreen.tsx
index cc10fb77be..b69d580883 100644
--- a/demo/src/screens/componentScreens/TextFieldScreen.tsx
+++ b/demo/src/screens/componentScreens/TextFieldScreen.tsx
@@ -31,7 +31,7 @@ export default class TextFieldScreen extends Component {
isReadonly: false,
value: 'Initial Value',
isSearching: false,
- preset: TextField.presets.UNDERLINE,
+ preset: undefined,
price: ''
};
From f673889227e1f522bb74b3076a77ff7083c4146e Mon Sep 17 00:00:00 2001
From: Inbal Tish <33805983+Inbal-Tish@users.noreply.github.com>
Date: Tue, 6 Aug 2024 12:03:16 +0300
Subject: [PATCH 12/14] TextField screen - fix (#3199)
* TextFieldScreen - fix and improve
* update snap tests
* add label
* validate and focus
* update snap tests
* removing presets text
* helperText
---
.../TextFieldScreen.spec.js.snap | 2845 +++++++++++------
.../componentScreens/TextFieldScreen.tsx | 142 +-
2 files changed, 1934 insertions(+), 1053 deletions(-)
diff --git a/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap b/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
index 59a61c4514..b5e809facf 100644
--- a/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
+++ b/demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap
@@ -306,7 +306,7 @@ exports[`TextField Screen renders screen 1`] = `
Presets
-
- Preset:
-
-
- Static vs Floating Placeholder
-
-
+ Disabled vs Readonly
+
+
-
-
-
-
-
+
+
+ Disabled
+
+
+
+
+ Readonly
+
+
+
+
+
+
+
+
+
+ Name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Static vs Floating Placeholder
+
+
+
+
+
+
+
+
+
+
+ FloatingPlaceholder
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hint vs HelperText
+
+
+
+
+
+
+
+
+
+
- FloatingPlaceholder
+ Enter code
+ >
+
+
+
+
+ Enter code
+
+
+ subtext={true}
+ testID="undefined.helperText"
+ >
+ 1-6 numbers
+
- Email
-
-
-
-
-
-
-
-
-
-
-
-
+ testID="undefined.label"
+ >
+ Email
+
-
-
-
- Name
-
-
-
-
-
-
-
-
-
+ underlineColorAndroid="transparent"
+ validate={
+ [
+ "required",
+ "email",
+ ]
+ }
+ validateOnBlur={true}
+ validateOnChange={true}
+ validationMessage={
+ [
+ "Email is required",
+ "Email is invalid",
+ ]
+ }
+ value="Initial Value"
+ />
+
+
-
-
- Enter first and last name
-
-
-
-
- 0/20
-
-
+ ],
+ ]
+ }
+ testID="undefined.validationMessage"
+ />
-
-
-
- Validate
-
-
-
-
- Hint
-
+ />
+
+
-
+
-
-
+ Name
+
+
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ ]
+ }
+ >
+
+
+
-
- Enter password
-
-
-
+ ]
+ }
+ underlineColorAndroid="transparent"
+ validate="required"
+ validateOnBlur={true}
+ validateOnChange={true}
+ validationMessage="This field is required. That means you have to enter some value"
+ />
+
-
-
-
+
+ Enter first and last name
+
+
+
+
+ ]
+ }
+ testID="undefined.charCounter"
+ >
+ 0/20
+
+
-
+
+
+ testID="undefined.label"
+ >
+ Validate
+
- Email
+ Color
@@ -5221,7 +6056,7 @@ exports[`TextField Screen renders screen 1`] = `
}
testID="undefined.label"
>
- Email
+ Required
@@ -6010,6 +6845,7 @@ exports[`TextField Screen renders screen 1`] = `
underlineColorAndroid="transparent"
validate="required"
validateOnBlur={true}
+ validateOnChange={true}
validationMessage="This field is required"
/>
@@ -6375,7 +7211,7 @@ exports[`TextField Screen renders screen 1`] = `
();
input2 = React.createRef();
@@ -32,7 +35,8 @@ export default class TextFieldScreen extends Component {
value: 'Initial Value',
isSearching: false,
preset: undefined,
- price: ''
+ price: '',
+ editable: false
};
componentDidMount() {
@@ -62,8 +66,7 @@ export default class TextFieldScreen extends Component {
Presets
-
- Preset:
+
@@ -73,6 +76,26 @@ export default class TextFieldScreen extends Component {
);
}
+ renderReadonlyExample() {
+ const {editable, preset} = this.state;
+
+ return (
+ <>
+
+
+ Disabled vs Readonly
+
+
+
+
+
+
+
+
+ >
+ );
+ }
+
renderPlaceholdersExample() {
return (
<>
@@ -103,6 +126,35 @@ export default class TextFieldScreen extends Component {
);
}
+ renderHintExample() {
+ return (
+ <>
+
+ Hint vs HelperText
+
+
+
+
+
+
+ >
+ );
+ }
+
renderTrailingAccessory() {
const {isSearching} = this.state;
@@ -237,7 +289,8 @@ export default class TextFieldScreen extends Component {
switch (index) {
case 0:
- // this.input3.current?.clear();
+ this.input3.current?.blur();
+ this.input3.current?.clear();
break;
case 1:
this.input3.current?.focus();
@@ -274,21 +327,28 @@ export default class TextFieldScreen extends Component {
>
);
@@ -298,30 +358,35 @@ export default class TextFieldScreen extends Component {
this.setState({preset: index === 0 ? 'underline' : 'outline'});
};
+ onChangeIndexEditable = (index: number) => {
+ this.setState({editable: index === 1});
+ };
+
getDynamicFieldStyle = (context: FieldContextType, props: TextFieldProps) => {
let color = Colors.$outlineNeutral;
if (context?.isFocused) {
color = Colors.$outlinePrimary;
}
- if (context?.hasValue && context?.isValid === false) {
+ if ((context?.hasValue && context?.isValid === false) ||
+ (context?.failingValidatorIndex !== undefined && context?.isMandatory && !context?.hasValue)) {
color = Colors.$outlineDanger;
}
- if (context?.hasValue && context?.isValid) {
+ if (context?.hasValue && context?.isValid && context?.isFocused) {
color = Colors.$textSuccess;
}
if (context?.disabled) {
- color = Colors.$outlineDefault;
+ color = Colors.$outlineDisabled;
}
if (context?.readonly) {
- color = Colors.$outlineDisabled;
+ color = Colors.$outlineNeutralHeavy;
}
return props?.preset === TextField.presets.UNDERLINE ? {borderBottomColor: color} : {borderColor: color};
};
renderDynamicFieldExample() {
- const {preset, isDisabled, isReadonly} = this.state;
+ const {preset} = this.state;
return (
<>
@@ -330,14 +395,12 @@ export default class TextFieldScreen extends Component {
>
@@ -386,24 +449,6 @@ export default class TextFieldScreen extends Component {
);
}
- renderHintExample() {
- return (
- <>
-
- Hint
-
-
-
- >
- );
- }
-
renderFormatterExample() {
const {price, preset} = this.state;
@@ -446,7 +491,7 @@ export default class TextFieldScreen extends Component {
topTrailingAccessory={}
validate={'required'}
validationMessage={'This field is required'}
- validateOnBlur
+ validateOnChange
validationMessagePosition={errorPosition}
preset={preset}
/>
@@ -475,9 +520,10 @@ export default class TextFieldScreen extends Component {
{this.renderDefaultExample()}
{this.renderPresetExample()}
+ {this.renderReadonlyExample()}
{this.renderPlaceholdersExample()}
- {this.renderValidationExample()}
{this.renderHintExample()}
+ {this.renderValidationExample()}
{this.renderClearButtonExample()}
{this.renderCharCounterExample()}
{this.renderAccessoriesExample()}
From c30ec6fa01553a71b6f061eedbeb076444519fcf Mon Sep 17 00:00:00 2001
From: Daniel Kochavi
Date: Wed, 7 Aug 2024 10:22:30 +0300
Subject: [PATCH 13/14] infra: Gradle 8 changes (#3200)
---
lib/android/build.gradle | 1 +
lib/android/src/main/AndroidManifest.xml | 3 +--
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/android/build.gradle b/lib/android/build.gradle
index 320499e5fd..5f0b7d690d 100644
--- a/lib/android/build.gradle
+++ b/lib/android/build.gradle
@@ -9,6 +9,7 @@ project.ext {
}
android {
+ namespace "com.wix.reactnativeuilib"
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
diff --git a/lib/android/src/main/AndroidManifest.xml b/lib/android/src/main/AndroidManifest.xml
index d7a52b40f8..b2d79a44f7 100644
--- a/lib/android/src/main/AndroidManifest.xml
+++ b/lib/android/src/main/AndroidManifest.xml
@@ -1,5 +1,4 @@
+ xmlns:android="http://schemas.android.com/apk/res/android">
From 0b5aea3bfa60bc06debd9130d79857283c4a6f5f Mon Sep 17 00:00:00 2001
From: adids1221
Date: Wed, 7 Aug 2024 12:25:36 +0300
Subject: [PATCH 14/14] bump native versione
---
lib/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/package.json b/lib/package.json
index 1903983f61..2accaaaf3f 100644
--- a/lib/package.json
+++ b/lib/package.json
@@ -1,6 +1,6 @@
{
"name": "uilib-native",
- "version": "4.1.3",
+ "version": "4.2.0",
"homepage": "https://github.com/wix/react-native-ui-lib",
"description": "uilib native components (separated from js components)",
"main": "components/index.js",