unicorn-demo-app 7.11.3 → 7.12.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unicorn-demo-app",
3
- "version": "7.11.3",
3
+ "version": "7.12.0",
4
4
  "main": "src/index.js",
5
5
  "author": "Ethan Sharabi <ethan.shar@gmail.com>",
6
6
  "license": "MIT",
package/src/index.js CHANGED
@@ -66,6 +66,9 @@ module.exports = {
66
66
  get HintsScreen() {
67
67
  return require('./screens/componentScreens/HintsScreen').default;
68
68
  },
69
+ get HorizontalSortableListScreen() {
70
+ return require('./screens/componentScreens/HorizontalSortableListScreen').default;
71
+ },
69
72
  get IconScreen() {
70
73
  return require('./screens/componentScreens/IconScreen').default;
71
74
  },
@@ -99,6 +99,7 @@ export const navigationData = {
99
99
  {title: 'Conversation List', tags: 'list conversation', screen: 'unicorn.lists.ConversationListScreen'},
100
100
  {title: 'Drawer', tags: 'drawer', screen: 'unicorn.components.DrawerScreen'},
101
101
  {title: 'SortableList', tags: 'sortable list drag', screen: 'unicorn.components.SortableListScreen'},
102
+ {title: 'HorizontalSortableList', tags: 'sortable horizontal list drag', screen: 'unicorn.components.HorizontalSortableListScreen'},
102
103
  {title: 'GridList', tags: 'grid list', screen: 'unicorn.components.GridListScreen'},
103
104
  {title: 'SortableGridList', tags: 'sort grid list drag', screen: 'unicorn.components.SortableGridListScreen'}
104
105
  ]
@@ -0,0 +1,120 @@
1
+ import React, {useCallback, useState, useRef} from 'react';
2
+ import {StyleSheet} from 'react-native';
3
+ import {SortableList, View, Text, Colors, Button, Card, BorderRadiuses} from 'react-native-ui-lib';
4
+ import {renderHeader} from '../ExampleScreenPresenter';
5
+ import products from '../../data/products';
6
+
7
+ const data = products.map((product, index) => ({...product, locked: index === 3}));
8
+ type Item = (typeof data)[0];
9
+
10
+ const HorizontalSortableListScreen = () => {
11
+ const [items, setItems] = useState<Item[]>(data);
12
+ const [selectedItems, setSelectedItems] = useState<Item[]>([]);
13
+ const [removedItems, setRemovedItems] = useState<Item[]>([]);
14
+ const orderedItems = useRef<Item[]>(data);
15
+
16
+ const toggleItemSelection = useCallback((item: Item) => {
17
+ if (selectedItems.includes(item)) {
18
+ setSelectedItems(selectedItems.filter(selectedItem => ![item.id].includes(selectedItem.id)));
19
+ } else {
20
+ setSelectedItems(selectedItems.concat(item));
21
+ }
22
+ },
23
+ [selectedItems, setSelectedItems]);
24
+
25
+ const addItem = useCallback(() => {
26
+ if (removedItems.length > 0) {
27
+ orderedItems.current = orderedItems.current.concat(removedItems[0]);
28
+ setItems(orderedItems.current);
29
+ setRemovedItems(removedItems.slice(1));
30
+ }
31
+ }, [removedItems, setItems, setRemovedItems]);
32
+
33
+ const removeSelectedItems = useCallback(() => {
34
+ setRemovedItems(removedItems.concat(selectedItems));
35
+ setSelectedItems([]);
36
+ orderedItems.current = orderedItems.current.filter(item => !selectedItems.includes(item));
37
+ setItems(orderedItems.current);
38
+ }, [setRemovedItems, removedItems, selectedItems, setItems, setSelectedItems]);
39
+
40
+ const keyExtractor = useCallback((item: Item) => {
41
+ return `${item.id}`;
42
+ }, []);
43
+
44
+ const onOrderChange = useCallback((newData: Item[]) => {
45
+ console.log('New order:', newData);
46
+ orderedItems.current = newData;
47
+ }, []);
48
+
49
+ const renderItem = useCallback(({item, index: _index}: {item: Item; index: number}) => {
50
+ const selected = selectedItems.includes(item);
51
+ const {locked} = item;
52
+ const Container = locked ? View : Card;
53
+ return (
54
+ <Container
55
+ style={styles.itemContainer}
56
+ onPress={() => toggleItemSelection(item)}
57
+ customValue={item.id}
58
+ selected={selected}
59
+ margin-s1
60
+ >
61
+ <Card.Section
62
+ imageSource={{uri: item.mediaUrl}}
63
+ imageStyle={styles.itemImage}
64
+ imageProps={{
65
+ customOverlayContent: (
66
+ <Text margin-s1={!locked} h1={!locked} h4={locked} center={locked} orange30>
67
+ {locked ? 'Locked' : item.id}
68
+ </Text>
69
+ )
70
+ }}
71
+ />
72
+ </Container>
73
+ );
74
+ },
75
+ [selectedItems, toggleItemSelection]);
76
+
77
+ return (
78
+ <View flex bg-$backgroundDefault>
79
+ {renderHeader('Sortable List', {'margin-10': true})}
80
+ <View row center marginB-s2>
81
+ <Button label="Add Item" size={Button.sizes.xSmall} disabled={removedItems.length === 0} onPress={addItem}/>
82
+ <Button
83
+ label="Remove Items"
84
+ size={Button.sizes.xSmall}
85
+ disabled={selectedItems.length === 0}
86
+ marginL-s3
87
+ onPress={removeSelectedItems}
88
+ />
89
+ </View>
90
+ <View flex useSafeArea>
91
+ <SortableList
92
+ horizontal
93
+ data={items}
94
+ renderItem={renderItem}
95
+ keyExtractor={keyExtractor}
96
+ onOrderChange={onOrderChange}
97
+ scale={1.02}
98
+ />
99
+ </View>
100
+ </View>
101
+ );
102
+ };
103
+
104
+ export default HorizontalSortableListScreen;
105
+ const styles = StyleSheet.create({
106
+ itemContainer: {
107
+ overflow: 'hidden',
108
+ borderColor: Colors.$outlineDefault,
109
+ borderBottomWidth: 1
110
+ },
111
+ selectedItemContainer: {
112
+ borderLeftColor: Colors.$outlinePrimary,
113
+ borderLeftWidth: 5
114
+ },
115
+ itemImage: {
116
+ width: 80,
117
+ height: 80,
118
+ borderRadius: BorderRadiuses.br10
119
+ }
120
+ });
@@ -50,6 +50,7 @@ export function registerScreens(registrar) {
50
50
  registrar('unicorn.components.SliderScreen', () => require('./SliderScreen').default);
51
51
  registrar('unicorn.components.SortableGridListScreen', () => require('./SortableGridListScreen').default);
52
52
  registrar('unicorn.components.SortableListScreen', () => require('./SortableListScreen').default);
53
+ registrar('unicorn.components.HorizontalSortableListScreen', () => require('./HorizontalSortableListScreen').default);
53
54
  registrar('unicorn.components.StackAggregatorScreen', () => require('./StackAggregatorScreen').default);
54
55
  registrar('unicorn.components.StepperScreen', () => require('./StepperScreen').default);
55
56
  registrar('unicorn.components.SwitchScreen', () => require('./SwitchScreen').default);
@@ -19,7 +19,6 @@ const TOAST_MESSAGES = {
19
19
  offline: 'Check Your Internet Connection'
20
20
  };
21
21
 
22
- // TODO: "ReactImageView: Image source "null" doesn't exist" (Android + preset "none")
23
22
  class ToastsScreen extends Component {
24
23
  showToast = false; // keep this state in class instance for immediate response
25
24
  state = {