Skip to content

Commit 88f1676

Browse files
committed
Merge branch 'master' into release
2 parents e846a5a + 7b97866 commit 88f1676

File tree

10 files changed

+1023
-411
lines changed

10 files changed

+1023
-411
lines changed

demo/src/screens/__tests__/__snapshots__/TextFieldScreen.spec.js.snap

Lines changed: 973 additions & 373 deletions
Large diffs are not rendered by default.

demo/src/screens/componentScreens/TextFieldScreen.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,14 @@ export default class TextFieldScreen extends Component {
209209
validate="required"
210210
validationMessage="This field is required. That means you have to enter some value"
211211
containerStyle={{flex: 1}}
212+
validateOnChange
212213
validationMessagePosition={errorPosition}
213214
helperText={'Enter first and last name'}
214215
validationIcon={{source: Assets.icons.demo.exclamation, style: {marginTop: 1}}}
215216
topTrailingAccessory={<Icon source={Assets.icons.demo.info} size={16}/>}
216217
preset={preset}
218+
maxLength={20}
219+
showCharCounter
217220
/>
218221
<Button
219222
outline

src/components/dateTimePicker/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ const DateTimePicker = forwardRef((props: DateTimePickerPropsInternal, ref: Forw
151151

152152
useImperativeHandle(ref, () => {
153153
return {
154+
isValid: () => textField.current?.isValid(),
154155
validate: () => textField.current?.validate()
155156
};
156157
});

src/components/sortableList/SortableList.api.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
},
1717
{
1818
"name": "onOrderChange",
19-
"type": "(data: ItemT[]) => void",
20-
"description": "A callback to get the new order (or swapped items).",
19+
"type": "(data: ItemT[], info: OrderChangeInfo) => void",
20+
"description": "A callback to get the new order (or swapped items) and info about the change (from and to indices).",
2121
"required": true
2222
},
2323
{

src/components/sortableList/SortableListItem.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const SortableListItem = (props: Props) => {
5454
const id: string = data[index].id;
5555
const locked: boolean = data[index].locked;
5656
const initialIndex = useSharedValue<number>(map(data, 'id').indexOf(id));
57+
const lastSwap = useSharedValue({from: -1, to: -1});
5758
const currIndex = useSharedValue(initialIndex.value);
5859
const translation = useSharedValue<number>(0);
5960

@@ -102,6 +103,7 @@ const SortableListItem = (props: Props) => {
102103
.onStart(() => {
103104
isDragging.value = true;
104105
translation.value = getTranslationByIndexChange(currIndex.value, initialIndex.value, itemSize.value);
106+
lastSwap.value = {...lastSwap.value, from: currIndex.value};
105107
tempTranslation.value = translation.value;
106108
tempItemsOrder.value = itemsOrder.value;
107109
})
@@ -140,6 +142,7 @@ const SortableListItem = (props: Props) => {
140142
newItemsOrder[newIndex] = id;
141143
newItemsOrder[oldIndex] = itemIdToSwap;
142144
itemsOrder.value = newItemsOrder;
145+
lastSwap.value = {...lastSwap.value, to: newIndex};
143146
}
144147
}
145148
})
@@ -150,7 +153,7 @@ const SortableListItem = (props: Props) => {
150153

151154
translation.value = withTiming(tempTranslation.value + _translation, animationConfig, () => {
152155
if (tempItemsOrder.value.toString() !== itemsOrder.value.toString()) {
153-
runOnJS(onChange)();
156+
runOnJS(onChange)({...lastSwap.value});
154157
}
155158
});
156159
})

src/components/sortableList/__tests__/index.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('SortableList', () => {
5353
{id: '1', text: '1'},
5454
{id: '3', text: '3'},
5555
{id: '4', text: '4'}
56-
]);
56+
], {from: 1, to: 2});
5757
});
5858

5959
it('SortableList onOrderChange is called - up', async () => {
@@ -72,6 +72,6 @@ describe('SortableList', () => {
7272
{id: '1', text: '1'},
7373
{id: '2', text: '2'},
7474
{id: '3', text: '3'}
75-
]);
75+
], {from: 4, to: 1});
7676
});
7777
});

src/components/sortableList/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {LogService} from 'services';
88
import SortableListContext from './SortableListContext';
99
import SortableListItem, {DEFAULT_LIST_ITEM_SIZE} from './SortableListItem';
1010
import {useDidUpdate, useThemeProps} from 'hooks';
11-
import {SortableListProps, SortableListItemProps} from './types';
11+
import type {SortableListProps, SortableListItemProps, OrderChangeInfo} from './types';
1212
import type {Dictionary} from '../../typings/common';
1313

1414
export {SortableListProps, SortableListItemProps};
@@ -46,7 +46,7 @@ const SortableList = <ItemT extends SortableListItemProps>(props: SortableListPr
4646
itemsOrder.value = generateItemsOrder(data);
4747
}, [data]);
4848

49-
const onChange = useCallback(() => {
49+
const onChange = useCallback((info: OrderChangeInfo) => {
5050
const newData: ItemT[] = [];
5151
const dataByIds = mapKeys(data, 'id');
5252
if (data?.length) {
@@ -55,7 +55,7 @@ const SortableList = <ItemT extends SortableListItemProps>(props: SortableListPr
5555
});
5656
}
5757

58-
onOrderChange?.(newData);
58+
onOrderChange?.(newData, info);
5959
}, [onOrderChange, data]);
6060

6161
const onItemLayout = useCallback((event: LayoutChangeEvent) => {

src/components/sortableList/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface SortableListItemProps {
99

1010
// Internal
1111
export type Data<ItemT extends SortableListItemProps> = FlatListProps<ItemT>['data'];
12+
export type OrderChangeInfo = {from: number, to: number};
1213

1314
export interface SortableListProps<ItemT extends SortableListItemProps>
1415
extends Omit<FlatListProps<ItemT>, 'extraData' | 'data'>,
@@ -21,7 +22,7 @@ export interface SortableListProps<ItemT extends SortableListItemProps>
2122
/**
2223
* A callback to get the new order (or swapped items).
2324
*/
24-
onOrderChange: (data: ItemT[] /* TODO: add more data? */) => void;
25+
onOrderChange: (data: ItemT[], info: OrderChangeInfo /* TODO: add more data? */) => void;
2526
/**
2627
* Whether to enable the haptic feedback
2728
* (please note that react-native-haptic-feedback does not support the specific haptic type on Android starting on an unknown version, you can use 1.8.2 for it to work properly)

src/components/switch/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ function createStyles({
176176
width = DEFAULT_WIDTH,
177177
height = DEFAULT_HEIGHT,
178178
onColor = Colors.$backgroundPrimaryHeavy,
179-
offColor = Colors.$backgroundNeutralIdle,
179+
offColor = Colors.$backgroundNeutralHeavy,
180180
disabledColor = Colors.$backgroundDisabled,
181181
thumbColor = Colors.$iconDefaultLight,
182182
thumbSize = DEFAULT_THUMB_SIZE

src/components/textField/index.tsx

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const TextField = (props: InternalTextFieldProps) => {
8080
enableErrors, // TODO: rename to enableValidation
8181
validationMessageStyle,
8282
validationMessagePosition = ValidationMessagePosition.BOTTOM,
83-
retainValidationSpace = !helperText,
83+
retainValidationSpace = !helperText && !bottomAccessory,
8484
// Char Counter
8585
showCharCounter,
8686
charCounterStyle,
@@ -123,11 +123,11 @@ const TextField = (props: InternalTextFieldProps) => {
123123
const hidePlaceholder = shouldHidePlaceholder(props, fieldState.isFocused);
124124
const retainTopMessageSpace = !floatingPlaceholder && isEmpty(trim(label));
125125
const centeredContainerStyle = centered && styles.centeredContainer;
126-
const centeredTextStyle = centered && styles.centeredText;
126+
const centeredTextStyle = centered && !showCharCounter && styles.centeredText;
127127
const _labelStyle = useMemo(() => [labelStyle, centeredTextStyle], [labelStyle, centeredTextStyle]);
128128
const _validationMessageStyle = useMemo(() => [validationMessageStyle, centeredTextStyle],
129129
[validationMessageStyle, centeredTextStyle]);
130-
const hasValue = fieldState.value !== undefined;
130+
const hasValue = fieldState.value !== undefined; // NOTE: not pressable if centered without a value (so can't center placeholder)
131131
const inputStyle = useMemo(() => [typographyStyle, colorStyle, others.style, hasValue && centeredTextStyle],
132132
[typographyStyle, colorStyle, others.style, centeredTextStyle, hasValue]);
133133
const dummyPlaceholderStyle = useMemo(() => [inputStyle, styles.dummyPlaceholder], [inputStyle]);
@@ -208,32 +208,36 @@ const TextField = (props: InternalTextFieldProps) => {
208208
{trailingAccessory}
209209
{/* </View> */}
210210
</View>
211-
<View row spread>
212-
{validationMessagePosition === ValidationMessagePosition.BOTTOM && (
213-
<ValidationMessage
214-
enableErrors={enableErrors}
215-
validate={others.validate}
216-
validationMessage={others.validationMessage}
217-
validationIcon={validationIcon}
218-
validationMessageStyle={_validationMessageStyle}
219-
retainValidationSpace={retainValidationSpace}
220-
testID={`${props.testID}.validationMessage`}
221-
/>
222-
)}
223-
{bottomAccessory}
224-
{showCharCounter && (
225-
<CharCounter
226-
maxLength={others.maxLength}
227-
charCounterStyle={charCounterStyle}
228-
testID={`${props.testID}.charCounter`}
229-
/>
230-
)}
211+
<View row spread center={centered}>
212+
<View flex={!centered} flexG={centered}>
213+
{validationMessagePosition === ValidationMessagePosition.BOTTOM && (
214+
<ValidationMessage
215+
enableErrors={enableErrors}
216+
validate={others.validate}
217+
validationMessage={others.validationMessage}
218+
validationIcon={validationIcon}
219+
validationMessageStyle={_validationMessageStyle}
220+
retainValidationSpace={retainValidationSpace}
221+
testID={`${props.testID}.validationMessage`}
222+
/>
223+
)}
224+
{helperText && (
225+
<Text $textNeutralHeavy subtext marginT-s1 testID={`${props.testID}.helperText`}>
226+
{helperText}
227+
</Text>
228+
)}
229+
{bottomAccessory}
230+
</View>
231+
<View>
232+
{showCharCounter && (
233+
<CharCounter
234+
maxLength={others.maxLength}
235+
charCounterStyle={charCounterStyle}
236+
testID={`${props.testID}.charCounter`}
237+
/>
238+
)}
239+
</View>
231240
</View>
232-
{helperText && (
233-
<Text $textNeutralHeavy subtext marginT-s1 testID={`${props.testID}.helperText`}>
234-
{helperText}
235-
</Text>
236-
)}
237241
</View>
238242
</FieldContext.Provider>
239243
);

0 commit comments

Comments
 (0)