diff --git a/node_modules/react-native-ui-lib/src/components/WheelPicker/index.js b/node_modules/react-native-ui-lib/src/components/WheelPicker/index.js
index 718a3a9..3c3cca8 100644
--- a/node_modules/react-native-ui-lib/src/components/WheelPicker/index.js
+++ b/node_modules/react-native-ui-lib/src/components/WheelPicker/index.js
@@ -94,6 +94,7 @@ const WheelPicker = props => {
value,
index
} = getRowItemAtOffset(event.nativeEvent.contentOffset.y);
+ offset.value = event.nativeEvent.contentOffset.y;
_onChange(value, index);
}, [_onChange, getRowItemAtOffset]);
const onMomentumScrollEndAndroid = index => {
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.d.ts
new file mode 100644
index 0000000..969128a
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { AgendaProps } from './types';
+declare function Agenda(props: AgendaProps): React.JSX.Element;
+export default Agenda;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.js
new file mode 100644
index 0000000..b997a29
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Agenda.js
@@ -0,0 +1,175 @@
+import React, { useContext, useCallback, useRef } from 'react';
+import { ActivityIndicator, StyleSheet } from 'react-native';
+import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated';
+import { FlashListPackage } from "../../optionalDependencies";
+import { BorderRadiuses, Colors } from "../../style";
+import View from "../../components/view";
+import Text from "../../components/text";
+import { isSameDay, isSameMonth } from "./helpers/DateUtils";
+import { UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+const FlashList = FlashListPackage?.FlashList;
+
+// TODO: Fix initial scrolling
+function Agenda(props) {
+ const {
+ renderEvent,
+ renderHeader,
+ itemHeight = 50,
+ onEndReached,
+ showLoader
+ } = props;
+ const {
+ data,
+ selectedDate,
+ setDate,
+ updateSource
+ } = useContext(CalendarContext);
+ const flashList = useRef(null);
+ const closestSectionHeader = useSharedValue(null);
+ const scrolledByUser = useSharedValue(false);
+
+ /* const keyExtractor = useCallback((item: InternalEvent) => {
+ return item.type === 'Event' ? item.id : item.header;
+ }, []); */
+
+ const _renderEvent = useCallback(eventItem => {
+ if (renderEvent) {
+ return
+ {renderEvent(eventItem)}
+ ;
+ }
+ return
+
+ Item for
+ {new Date(eventItem.start).toLocaleString('en-GB', {
+ month: 'short',
+ day: 'numeric',
+ hour12: false,
+ hour: '2-digit',
+ minute: '2-digit'
+ })}
+ -{new Date(eventItem.end).toLocaleString('en-GB', {
+ hour12: false,
+ hour: '2-digit',
+ minute: '2-digit'
+ })}
+
+ ;
+ }, [renderEvent, itemHeight]);
+ const _renderHeader = useCallback(headerItem => {
+ if (renderHeader) {
+ return {renderHeader(headerItem)};
+ }
+ return
+ {headerItem.header}
+ ;
+ }, [renderHeader, itemHeight]);
+ const renderItem = useCallback(({
+ item
+ }) => {
+ switch (item.type) {
+ case 'Event':
+ return _renderEvent(item);
+ case 'Header':
+ return _renderHeader(item);
+ }
+ }, [_renderEvent, _renderHeader]);
+ const getItemType = useCallback(item => item.type, []);
+ const findClosestDateAfter = useCallback(selected => {
+ 'worklet';
+
+ for (let index = 0; index < data.length; ++index) {
+ const item = data[index];
+ if (item.type === 'Header') {
+ if (item.date >= selected) {
+ return {
+ dateSectionHeader: item,
+ index
+ };
+ }
+ }
+ }
+ return null;
+ }, [data]);
+ const scrollToIndex = useCallback((index, animated) => {
+ flashList.current?.scrollToIndex({
+ index,
+ animated
+ });
+ }, []);
+ useAnimatedReaction(() => {
+ return selectedDate.value;
+ }, (selected, previous) => {
+ if (updateSource.value !== UpdateSource.AGENDA_SCROLL) {
+ if (selected !== previous && (closestSectionHeader.value?.date === undefined || !isSameDay(selected, closestSectionHeader.value?.date))) {
+ const result = findClosestDateAfter(selected);
+ if (result !== null) {
+ const {
+ dateSectionHeader,
+ index
+ } = result;
+ closestSectionHeader.value = dateSectionHeader;
+ scrolledByUser.value = false;
+ // TODO: Can the animation be improved (not in JS)?
+ if (previous) {
+ const _isSameMonth = isSameMonth(selected, previous);
+ runOnJS(scrollToIndex)(index, _isSameMonth);
+ }
+ }
+ }
+ }
+ }, [findClosestDateAfter]);
+
+ // TODO: look at https://docs.swmansion.com/react-native-reanimated/docs/api/hooks/useAnimatedScrollHandler
+ const onViewableItemsChanged = useCallback(({
+ viewableItems
+ }) => {
+ if (scrolledByUser.value) {
+ const result = viewableItems.find(item => item.item.type === 'Header');
+ if (result) {
+ const {
+ item
+ } = result;
+ if (closestSectionHeader.value?.date !== item.date) {
+ closestSectionHeader.value = item;
+ setDate(item.date, UpdateSource.AGENDA_SCROLL);
+ }
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const onMomentumScrollBegin = useCallback(() => {
+ scrolledByUser.value = true;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const onScrollBeginDrag = useCallback(() => {
+ scrolledByUser.value = true;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const _onEndReached = useCallback(() => {
+ onEndReached?.(selectedDate.value);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [onEndReached]);
+ return
+
+ {showLoader &&
+
+ }
+ ;
+}
+export default Agenda;
+const styles = StyleSheet.create({
+ eventContainer: {
+ overflow: 'hidden'
+ },
+ event: {
+ borderWidth: 1,
+ borderRadius: BorderRadiuses.br20
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.d.ts
new file mode 100644
index 0000000..3a3ccf0
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.d.ts
@@ -0,0 +1,4 @@
+///
+import { CalendarContextProps } from './types';
+declare const CalendarContext: import("react").Context;
+export default CalendarContext;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.js
new file mode 100644
index 0000000..552fcfe
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarContext.js
@@ -0,0 +1,8 @@
+import { createContext } from 'react';
+import { FirstDayOfWeek } from "./types";
+
+// @ts-ignore
+const CalendarContext = createContext({
+ firstDayOfWeek: FirstDayOfWeek.MONDAY
+});
+export default CalendarContext;
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.d.ts
new file mode 100644
index 0000000..d5d2032
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.d.ts
@@ -0,0 +1,5 @@
+import React from 'react';
+import { CalendarItemProps } from './types';
+declare function CalendarItem(props: CalendarItemProps): React.JSX.Element | null;
+declare const _default: React.MemoExoticComponent;
+export default _default;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.js
new file mode 100644
index 0000000..f29c05a
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/CalendarItem.js
@@ -0,0 +1,39 @@
+import React, { useContext, useMemo } from 'react';
+import { StyleSheet } from 'react-native';
+import { Constants } from "../../commons/new";
+import View from "../../components/view";
+import CalendarContext from "./CalendarContext";
+import Month from "./Month";
+import Header from "./Header";
+const CALENDAR_HEIGHT = Constants.isAndroid ? 280 : 270;
+function CalendarItem(props) {
+ const {
+ year,
+ month
+ } = props;
+ const {
+ staticHeader,
+ headerHeight
+ } = useContext(CalendarContext);
+ const calendarStyle = useMemo(() => {
+ // TODO: dynamic height: calc calendar height with month's number of weeks
+ return [styles.container, {
+ height: CALENDAR_HEIGHT - (staticHeader ? headerHeight.value : 0)
+ }];
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [staticHeader]);
+ if (month !== undefined) {
+ return
+ {!staticHeader && }
+
+ ;
+ }
+ return null;
+}
+export default React.memo(CalendarItem);
+const styles = StyleSheet.create({
+ container: {
+ width: Constants.windowWidth,
+ borderBottomWidth: 1
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.d.ts
new file mode 100644
index 0000000..4470505
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { DayProps } from './types';
+declare const Day: (props: DayProps) => React.JSX.Element;
+export default Day;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.js
new file mode 100644
index 0000000..82be2a1
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day.js
@@ -0,0 +1,97 @@
+import React, { useContext, useCallback, useMemo, useState } from 'react';
+import { StyleSheet, View, Text, TouchableWithoutFeedback } from 'react-native';
+import { useAnimatedReaction, runOnJS } from 'react-native-reanimated';
+import { Colors } from "../../style";
+import { getDateObject, isSameDay } from "./helpers/DateUtils";
+import { UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+const DAY_SIZE = 32;
+const NO_COLOR = Colors.transparent;
+const TEXT_COLOR = Colors.$textPrimary;
+const TODAY_BACKGROUND_COLOR = Colors.$backgroundPrimaryLight;
+const SELECTED_BACKGROUND_COLOR = Colors.$backgroundPrimaryHeavy;
+const SELECTED_TEXT_COLOR = Colors.$textDefaultLight;
+const INACTIVE_TEXT_COLOR = Colors.$textNeutralLight;
+const Day = props => {
+ const {
+ date,
+ onPress,
+ currentMonth
+ } = props;
+ const {
+ selectedDate,
+ setDate,
+ showExtraDays,
+ today
+ } = useContext(CalendarContext);
+ const [selected, setSelected] = useState(false);
+ const dateObject = useMemo(() => getDateObject(date), [date]);
+ const day = dateObject ? dateObject.day : '';
+ useAnimatedReaction(() => date ? isSameDay(selectedDate.value, date) : false, (selected, prevSelected) => {
+ if (selected !== prevSelected) {
+ runOnJS(setSelected)(selected);
+ }
+ });
+ const _onPress = useCallback(() => {
+ setDate(date, UpdateSource.DAY_SELECT);
+ onPress?.(date);
+ }, [setDate, date, onPress]);
+ const isToday = isSameDay(today, date);
+ const inactive = dateObject ? dateObject.month !== currentMonth : false;
+ const isHidden = !showExtraDays && inactive;
+ const textStyle = useMemo(() => {
+ if (isHidden) {
+ return styles.textHidden;
+ } else if (inactive) {
+ return styles.textInactive;
+ } else if (selected) {
+ return styles.textSelected;
+ }
+ return styles.text;
+ }, [selected, inactive, isHidden]);
+ return
+
+ {isToday && }
+ {selected && }
+ {day}
+
+ ;
+};
+export default Day;
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: DAY_SIZE,
+ height: DAY_SIZE
+ },
+ text: {
+ color: TEXT_COLOR
+ },
+ textSelected: {
+ color: SELECTED_TEXT_COLOR
+ },
+ textInactive: {
+ color: INACTIVE_TEXT_COLOR
+ },
+ textHidden: {
+ color: NO_COLOR
+ },
+ selectedIndicator: {
+ position: 'absolute',
+ width: DAY_SIZE,
+ height: DAY_SIZE,
+ flex: 1,
+ borderRadius: 999,
+ backgroundColor: SELECTED_BACKGROUND_COLOR
+ },
+ todayIndicator: {
+ position: 'absolute',
+ width: DAY_SIZE,
+ height: DAY_SIZE,
+ flex: 1,
+ borderRadius: 999,
+ backgroundColor: TODAY_BACKGROUND_COLOR
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.d.ts
new file mode 100644
index 0000000..4470505
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { DayProps } from './types';
+declare const Day: (props: DayProps) => React.JSX.Element;
+export default Day;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.js
new file mode 100644
index 0000000..fbafb0f
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Day_OLD.js
@@ -0,0 +1,102 @@
+import isNull from 'lodash/isNull';
+import React, { useContext, useCallback, useMemo } from 'react';
+import { StyleSheet } from 'react-native';
+import Reanimated, { useSharedValue, useAnimatedStyle, useAnimatedReaction, withTiming } from 'react-native-reanimated';
+import { Colors } from "../../style";
+import View from "../../components/view";
+import TouchableOpacity from "../../components/touchableOpacity";
+import Text from "../../components/text";
+import { getDateObject, isSameDay } from "./helpers/DateUtils";
+import { UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+const DAY_SIZE = 32;
+const SELECTION_SIZE = 24;
+const NO_COLOR = Colors.transparent;
+const TEXT_COLOR = Colors.$textPrimary;
+const TODAY_BACKGROUND_COLOR = Colors.$backgroundPrimaryLight;
+const INACTIVE_TODAY_BACKGROUND_COLOR = Colors.$backgroundNeutral;
+const SELECTED_BACKGROUND_COLOR = Colors.$backgroundPrimaryHeavy;
+const SELECTED_TEXT_COLOR = Colors.$textDefaultLight;
+const INACTIVE_TEXT_COLOR = Colors.$textNeutralLight;
+const AnimatedText = Reanimated.createAnimatedComponent(Text);
+const Day = props => {
+ const {
+ date,
+ onPress,
+ currentMonth
+ } = props;
+ const {
+ selectedDate,
+ setDate,
+ showExtraDays,
+ today
+ } = useContext(CalendarContext);
+ const dateObject = useMemo(() => {
+ return !isNull(date) && getDateObject(date);
+ }, [date]);
+ const day = dateObject ? dateObject.day : '';
+ const isSelected = useSharedValue(!isNull(date) ? isSameDay(selectedDate.value, date) : false);
+ const inactive = useMemo(() => {
+ // inactive have different look but is still pressable
+ if (dateObject) {
+ const dayMonth = dateObject.month;
+ return dayMonth !== currentMonth;
+ }
+ }, [dateObject, currentMonth]);
+ const isHidden = !showExtraDays && inactive;
+ const backgroundColor = useMemo(() => {
+ return !isSameDay(date, today) ? NO_COLOR : inactive ? INACTIVE_TODAY_BACKGROUND_COLOR : TODAY_BACKGROUND_COLOR;
+ }, [date, inactive, today]);
+ const textColor = useMemo(() => {
+ return inactive ? showExtraDays ? INACTIVE_TEXT_COLOR : NO_COLOR : TEXT_COLOR;
+ }, [inactive, showExtraDays]);
+ useAnimatedReaction(() => {
+ return selectedDate.value;
+ }, selected => {
+ isSelected.value = !inactive && isSameDay(selected, date);
+ }, []);
+ const animatedTextStyles = useAnimatedStyle(() => {
+ return {
+ color: withTiming(isSelected.value ? SELECTED_TEXT_COLOR : textColor, {
+ duration: 100
+ })
+ };
+ });
+ const animatedSelectionStyles = useAnimatedStyle(() => {
+ return {
+ backgroundColor: withTiming(isSelected.value ? SELECTED_BACKGROUND_COLOR : backgroundColor, {
+ duration: 100
+ })
+ };
+ });
+ const selectionStyle = useMemo(() => {
+ return [styles.selection, animatedSelectionStyles];
+ }, [animatedSelectionStyles]);
+ const _onPress = useCallback(() => {
+ if (date !== null && !isHidden) {
+ isSelected.value = true;
+ setDate(date, UpdateSource.DAY_SELECT);
+ onPress?.(date);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [date, setDate, onPress]);
+ return
+
+
+ {day}
+
+ ;
+};
+export default Day;
+const styles = StyleSheet.create({
+ dayContainer: {
+ width: DAY_SIZE,
+ height: DAY_SIZE
+ },
+ selection: {
+ position: 'absolute',
+ width: SELECTION_SIZE,
+ height: SELECTION_SIZE,
+ borderRadius: SELECTION_SIZE / 2
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.d.ts
new file mode 100644
index 0000000..ab7cc77
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { HeaderProps } from './types';
+declare const Header: (props: HeaderProps) => React.JSX.Element;
+export default Header;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.js
new file mode 100644
index 0000000..b443aef
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Header.js
@@ -0,0 +1,103 @@
+import throttle from 'lodash/throttle';
+import React, { useContext, useCallback } from 'react';
+import { StyleSheet, TextInput, Text } from 'react-native';
+import Reanimated, { useAnimatedProps } from 'react-native-reanimated';
+import { Colors, Typography } from "../../style";
+import View from "../../components/view";
+import Button from "../../components/button";
+import { getDateObject, getMonthForIndex, addMonths } from "./helpers/DateUtils";
+import { DayNamesFormat, UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+import WeekDaysNames from "./WeekDaysNames";
+const WEEK_NUMBER_WIDTH = 32;
+const ARROW_NEXT = require("./assets/arrowNext.png");
+const ARROW_BACK = require("./assets/arrowBack.png");
+const AnimatedTextInput = Reanimated.createAnimatedComponent(TextInput);
+const Header = props => {
+ const {
+ month,
+ year
+ } = props;
+ const {
+ selectedDate,
+ setDate,
+ showWeeksNumbers,
+ staticHeader,
+ setHeaderHeight
+ } = useContext(CalendarContext);
+ const getNewDate = useCallback(count => {
+ return addMonths(selectedDate.value, count, true);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const onLeftArrowPress = useCallback(throttle(() => {
+ setDate(getNewDate(-1), UpdateSource.MONTH_ARROW);
+ }, 300), [setDate, getNewDate]);
+ const onRightArrowPress = useCallback(throttle(() => {
+ setDate(getNewDate(1), UpdateSource.MONTH_ARROW);
+ }, 300), [setDate, getNewDate]);
+ const getTitle = useCallback(date => {
+ 'worklet';
+
+ const dateObject = getDateObject(date);
+ const m = dateObject.month;
+ const y = dateObject.year;
+ return getMonthForIndex(m) + ` ${y}`;
+ }, []);
+ const animatedProps = useAnimatedProps(() => {
+ // get called only on value update
+ return {
+ text: getTitle(selectedDate.value)
+ };
+ });
+ const onLayout = useCallback(event => {
+ setHeaderHeight?.(event.nativeEvent.layout.height);
+ }, [setHeaderHeight]);
+ const renderTitle = () => {
+ if (!staticHeader) {
+ const title = getMonthForIndex(month) + ` ${year}`;
+ return {title};
+ }
+ return (
+ //@ts-expect-error - hack to animate the title text change
+
+ );
+ };
+ const renderArrow = (source, onPress) => {
+ return ;
+ };
+ const renderNavigation = () => {
+ return
+ {renderArrow(ARROW_BACK, onLeftArrowPress)}
+ {renderTitle()}
+ {renderArrow(ARROW_NEXT, onRightArrowPress)}
+ ;
+ };
+ return
+ {renderNavigation()}
+
+ ;
+};
+export default Header;
+const styles = StyleSheet.create({
+ container: {},
+ navigation: {
+ marginTop: 12,
+ marginBottom: 16,
+ marginHorizontal: 8
+ },
+ title: {
+ color: Colors.$textDefault,
+ paddingVertical: 0,
+ // for Android inner paddings
+ ...Typography.text60
+ },
+ weekDaysNames: {
+ marginBottom: 8,
+ marginHorizontal: 16
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.d.ts
new file mode 100644
index 0000000..7d1df9a
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { MonthProps } from './types';
+declare function Month(props: MonthProps): React.JSX.Element;
+export default Month;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.js
new file mode 100644
index 0000000..cbedf8c
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Month.js
@@ -0,0 +1,24 @@
+import React, { useContext, useMemo } from 'react';
+import View from "../../components/view";
+import { getWeekNumbersOfMonth } from "./helpers/DateUtils";
+import CalendarContext from "./CalendarContext";
+import Week from "./Week";
+function Month(props) {
+ const {
+ year,
+ month
+ } = props;
+ const {
+ firstDayOfWeek
+ } = useContext(CalendarContext);
+ const weekNumbers = useMemo(() => {
+ return getWeekNumbersOfMonth(year, month, Number(firstDayOfWeek));
+ }, [year, month, firstDayOfWeek]);
+ return
+ {weekNumbers.map(weekNumber => {
+ // eslint-disable-next-line react/jsx-key
+ return ;
+ })}
+ ;
+}
+export default Month;
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.d.ts
new file mode 100644
index 0000000..3eb8cbf
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { TodayButtonProps } from './types';
+declare const TodayButton: (props: TodayButtonProps) => React.JSX.Element;
+export default TodayButton;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.js
new file mode 100644
index 0000000..db5fd15
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/TodayButton.js
@@ -0,0 +1,64 @@
+import React, { useContext, useCallback } from 'react';
+import { StyleSheet } from 'react-native';
+import { /* Animated, */useAnimatedStyle /* , useSharedValue */ } from 'react-native-reanimated';
+import { Colors } from "../../style";
+import View from "../../components/view";
+import Button from "../../components/button";
+import { isSameDay /*, isPastDate*/ } from "./helpers/DateUtils";
+import { UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+const UP_ICON = require("./assets/up.png");
+// const DOWN_ICON = require('./assets/down.png');
+
+const TodayButton = props => {
+ //TODO: memoize
+ const {
+ containerStyle,
+ buttonProps
+ } = props;
+ const {
+ selectedDate,
+ setDate
+ } = useContext(CalendarContext);
+ const animatedStyle = useAnimatedStyle(() => {
+ return {
+ transform: [{
+ translateY: isSameDay(selectedDate.value, Date.now()) ? 100 : 0
+ }]
+ };
+ });
+
+ /** animate button's icon */
+ // const source = useSharedValue(isPastDate(selectedDate.value) ? DOWN_ICON : UP_ICON);
+ // const renderIcon = useCallback((style) => {
+ // return ;
+ // }, []);
+
+ const onPress = useCallback(event => {
+ setDate(Date.now(), UpdateSource.TODAY_PRESS);
+ buttonProps?.onPress?.(event);
+ }, [buttonProps]);
+ return
+
+ ;
+};
+export default TodayButton;
+const styles = StyleSheet.create({
+ container: {
+ position: 'absolute',
+ bottom: 42,
+ left: 16
+ },
+ button: {
+ backgroundColor: Colors.$backgroundDefault,
+ shadowColor: '#79838A',
+ shadowOpacity: 0.3,
+ shadowRadius: 14,
+ shadowOffset: {
+ height: 6,
+ width: 0
+ },
+ elevation: 6
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.d.ts
new file mode 100644
index 0000000..ca5a097
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { WeekProps } from './types';
+declare const Week: (props: WeekProps) => React.JSX.Element;
+export default Week;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.js
new file mode 100644
index 0000000..3de84ad
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/Week.js
@@ -0,0 +1,41 @@
+import map from 'lodash/map';
+import React, { useContext, useMemo } from 'react';
+import { StyleSheet } from 'react-native';
+import View from "../../components/view";
+import Text from "../../components/text";
+import { getDaysOfWeekNumber } from "./helpers/DateUtils";
+import CalendarContext from "./CalendarContext";
+import Day from "./Day";
+const WEEK_NUMBER_WIDTH = 20;
+const Week = props => {
+ const {
+ weekNumber,
+ year,
+ month
+ } = props;
+ const {
+ firstDayOfWeek,
+ showWeeksNumbers
+ } = useContext(CalendarContext);
+ const days = useMemo(() => {
+ return getDaysOfWeekNumber(year, weekNumber, firstDayOfWeek);
+ }, [year, weekNumber, firstDayOfWeek]);
+ const renderWeekNumbers = () => {
+ if (showWeeksNumbers) {
+ return
+ {weekNumber}
+ ;
+ }
+ };
+ return
+ {renderWeekNumbers()}
+ {map(days, day => )}
+ ;
+};
+export default Week;
+const styles = StyleSheet.create({
+ weekNumber: {
+ width: WEEK_NUMBER_WIDTH,
+ alignSelf: 'center'
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.d.ts
new file mode 100644
index 0000000..06217a9
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { WeekDaysNamesProps } from './types';
+declare const WeekDaysNames: (props: WeekDaysNamesProps) => React.JSX.Element;
+export default WeekDaysNames;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.js
new file mode 100644
index 0000000..6c5d918
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/WeekDaysNames.js
@@ -0,0 +1,26 @@
+import React, { useContext } from 'react';
+import View from "../../components/view";
+import Text from "../../components/text";
+import { getWeekDayNames } from "./helpers/DateUtils";
+import CalendarContext from "./CalendarContext";
+const WeekDaysNames = props => {
+ //TODO: memoize
+ const {
+ containerStyle,
+ textStyle,
+ format
+ } = props;
+ const {
+ firstDayOfWeek
+ } = useContext(CalendarContext);
+ const dayNames = getWeekDayNames(firstDayOfWeek, format);
+ const renderWeekDaysNames = () => {
+ return dayNames.map((name, index) =>
+ {name}
+ );
+ };
+ return
+ {renderWeekDaysNames()}
+ ;
+};
+export default WeekDaysNames;
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack.png
new file mode 100644
index 0000000..e6369d8
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@1.5x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@1.5x.png
new file mode 100644
index 0000000..bdf6147
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@1.5x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@2x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@2x.png
new file mode 100644
index 0000000..40f7077
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@2x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@3x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@3x.png
new file mode 100644
index 0000000..8a20aff
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@3x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@4x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@4x.png
new file mode 100644
index 0000000..0c5f639
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowBack@4x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext.png
new file mode 100644
index 0000000..e8bec5d
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@1.5x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@1.5x.png
new file mode 100644
index 0000000..65a37de
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@1.5x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@2x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@2x.png
new file mode 100644
index 0000000..f2ca5d2
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@2x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@3x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@3x.png
new file mode 100644
index 0000000..20d11aa
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@3x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@4x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@4x.png
new file mode 100644
index 0000000..35b1d1a
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/arrowNext@4x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down.png
new file mode 100644
index 0000000..9695442
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@1.5x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@1.5x.png
new file mode 100644
index 0000000..a4b37ab
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@1.5x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@2x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@2x.png
new file mode 100644
index 0000000..3c6728c
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@2x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@3x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@3x.png
new file mode 100644
index 0000000..bbe1e7c
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@3x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@4x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@4x.png
new file mode 100644
index 0000000..606d706
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/down@4x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up.png
new file mode 100644
index 0000000..5c7116a
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@1.5x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@1.5x.png
new file mode 100644
index 0000000..eb4f127
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@1.5x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@2x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@2x.png
new file mode 100644
index 0000000..1584de2
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@2x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@3x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@3x.png
new file mode 100644
index 0000000..5e4c785
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@3x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@4x.png b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@4x.png
new file mode 100644
index 0000000..2fdd5a3
Binary files /dev/null and b/node_modules/react-native-ui-lib/src/incubator/Calendar/assets/up@4x.png differ
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.d.ts
new file mode 100644
index 0000000..12530b1
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.d.ts
@@ -0,0 +1,2 @@
+import { DateObjectWithOptionalDay } from '../types';
+export declare function generateMonthItems(date: number, pastRange: number, futureRange: number): DateObjectWithOptionalDay[];
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.js
new file mode 100644
index 0000000..94ec7b3
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/CalendarProcessor.js
@@ -0,0 +1,14 @@
+export function generateMonthItems(date, pastRange, futureRange) {
+ const currentYear = new Date(date).getFullYear();
+ const monthItems = [];
+ for (let year = currentYear - pastRange; year <= currentYear + futureRange; year++) {
+ for (let month = 0; month < 12; month++) {
+ monthItems.push({
+ timestamp: date,
+ year,
+ month
+ });
+ }
+ }
+ return monthItems;
+}
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.d.ts
new file mode 100644
index 0000000..6f0111d
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.d.ts
@@ -0,0 +1,2 @@
+import { Data, InternalData } from '../types';
+export declare function addHeaders(data: Data): InternalData;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.js
new file mode 100644
index 0000000..6a1fb4b
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DataProcessor.js
@@ -0,0 +1,36 @@
+function eventComparator(a, b) {
+ return a.start - b.start;
+}
+
+// TODO: do it properly with a format \ locale
+// TODO: what can the user do beforehand
+function getHeaderText(date) {
+ const _date = new Date(date);
+ const dd = String(_date.getDate()).padStart(2, '0');
+ const mm = String(_date.getMonth() + 1).padStart(2, '0'); //January is 0!
+ const yyyy = _date.getFullYear();
+ return `${dd}/${mm}/${yyyy}`;
+}
+
+// TODO: move this to processData
+export function addHeaders(data) {
+ const sortedData = data.sort(eventComparator);
+ const result = [];
+ let previousHeader, currentHeader;
+ sortedData.forEach(event => {
+ currentHeader = getHeaderText(event.start);
+ if (previousHeader !== currentHeader) {
+ result.push({
+ type: 'Header',
+ header: currentHeader,
+ date: event.start
+ });
+ previousHeader = currentHeader;
+ }
+ result.push({
+ type: 'Event',
+ ...event
+ });
+ });
+ return result;
+}
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.d.ts
new file mode 100644
index 0000000..ea18ffb
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.d.ts
@@ -0,0 +1,23 @@
+import { FirstDayOfWeek, DayNamesFormat, DateObjectWithOptionalDay, DateObjectWithDate } from '../types';
+export declare const HOUR_IN_MS: number;
+export declare function getWeekNumbersOfMonth(year: number, month: number, firstDayOfWeek: FirstDayOfWeek): number[];
+declare function getFirstDayInTheYear(year: number, firstDayOfWeek: FirstDayOfWeek): number;
+export declare function getDaysOfWeekNumber(year: number, weekNumber: number, firstDayOfWeek: FirstDayOfWeek): any[];
+export declare function getDateObject(date: number | DateObjectWithDate): {
+ day: number;
+ month: number;
+ year: number;
+ dayOfTheWeek: number;
+ timestamp: number;
+};
+export declare function addMonths(date: number, count: number, useFirstDay?: boolean): number;
+export declare function addYears(date: number, count: number): number;
+export declare function getMonthForIndex(index: number): string | undefined;
+export declare function getWeekDayNames(firstDayOfWeek?: number, format?: DayNamesFormat): string[];
+export declare function isPastDate(date: number): boolean;
+export declare function isSameDay(d1: number, d2: number): boolean;
+export declare function isSameMonth(d1: number | DateObjectWithOptionalDay, d2: number | DateObjectWithOptionalDay): boolean;
+export declare const _forTesting: {
+ getFirstDayInTheYear: typeof getFirstDayInTheYear;
+};
+export {};
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.js
new file mode 100644
index 0000000..e143b2f
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/helpers/DateUtils.js
@@ -0,0 +1,182 @@
+import _times from "lodash/times";
+import getWeek from 'date-fns/getWeek';
+export const HOUR_IN_MS = 60 * 60 * 1000;
+const DAY_IN_MS = 24 * HOUR_IN_MS;
+const WEEK_IN_MS = 7 * DAY_IN_MS;
+function getNumberOfWeeksInMonth(year, month, firstDayOfWeek) {
+ const numberOfDaysInMonth = new Date(year, month + 1, 0).getDate();
+ const dayOfTheWeek = new Date(year, month, 1).getDay();
+
+ // Modify day in the week based on the first day of the week
+ const fixedDayOfTheWeek = (7 - (firstDayOfWeek - dayOfTheWeek)) % 7;
+ const numberOfWeeks = Math.ceil((numberOfDaysInMonth + fixedDayOfTheWeek) / 7);
+ return numberOfWeeks;
+}
+export function getWeekNumbersOfMonth(year, month, firstDayOfWeek) {
+ if (month < 0 || month > 11) {
+ throw new Error('getWeekNumbersOfMonth util received an invalid month');
+ }
+ const firstDayOfMonth = new Date(year, month, 1);
+ const firstWeekNumber = getWeek(firstDayOfMonth, {
+ weekStartsOn: firstDayOfWeek
+ });
+ const numberOfWeeks = getNumberOfWeeksInMonth(year, month, firstDayOfWeek);
+ const weekNumbers = [];
+ _times(numberOfWeeks, i => weekNumbers.push(i + firstWeekNumber));
+ return weekNumbers;
+}
+function getFirstDayInTheWeek(date, firstDayOfWeek) {
+ let result = date.timestamp - DAY_IN_MS * ((date.dayOfTheWeek - firstDayOfWeek) % 7);
+ const dayInMonth = getDateObject(result).day;
+ if (dayInMonth > 1 && dayInMonth <= 7) {
+ result -= WEEK_IN_MS;
+ }
+ return result;
+}
+function getFirstDayInTheYear(year, firstDayOfWeek) {
+ const dayInFirstWeekOfYear = getDateObject({
+ year,
+ month: 0,
+ day: 1
+ });
+ return getFirstDayInTheWeek(dayInFirstWeekOfYear, firstDayOfWeek);
+}
+
+// TODO: Fix to use Default behavior for week number
+export function getDaysOfWeekNumber(year, weekNumber, firstDayOfWeek) {
+ const result = new Array(7).fill(null);
+ const firstDayOfYear = getFirstDayInTheYear(year, firstDayOfWeek);
+ const firstDayInRelevantWeek = firstDayOfYear + (weekNumber - 1) * WEEK_IN_MS;
+ for (let day = 0; day <= 6; ++day) {
+ result[day] = firstDayInRelevantWeek + DAY_IN_MS * day;
+ }
+ return result;
+}
+
+/* Worklets */
+
+export function getDateObject(date) {
+ 'worklet';
+
+ const isNumberType = typeof date === 'number';
+ const d = isNumberType ? new Date(date) : new Date(date.year, date.month, date.day);
+ return {
+ day: d.getDate(),
+ month: d.getMonth(),
+ year: d.getFullYear(),
+ dayOfTheWeek: d.getDay(),
+ timestamp: isNumberType ? date : d.getTime()
+ };
+}
+export function addMonths(date, count, useFirstDay = false) {
+ 'worklet';
+
+ if (count === 0) {
+ return date;
+ }
+ const d = new Date(date);
+ const month = d.getMonth();
+ d.setMonth(month + count);
+ if (useFirstDay) {
+ // feature: setting the new month to the first day of the month
+ d.setDate(1);
+ }
+ return d.getTime();
+}
+export function addYears(date, count) {
+ 'worklet';
+
+ if (count === 0) {
+ return date;
+ }
+ const d = new Date(date);
+ const year = d.getFullYear();
+ return d.setFullYear(year + count);
+}
+export function getMonthForIndex(index) {
+ 'worklet';
+
+ const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+ if (index >= 0 && index < 12) {
+ return months[index];
+ }
+}
+function getWeekDaysNames(format) {
+ //TODO: localize
+ switch (format) {
+ case 1:
+ return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+ case 2:
+ return ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
+ default:
+ return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+ }
+}
+export function getWeekDayNames(firstDayOfWeek = 0, format) {
+ //TODO: consider 'options' param
+ 'worklet';
+
+ let weekDaysNames = getWeekDaysNames(format);
+ const dayShift = firstDayOfWeek % 7;
+ if (dayShift) {
+ weekDaysNames = weekDaysNames.slice(dayShift).concat(weekDaysNames.slice(0, dayShift));
+ }
+ return weekDaysNames;
+}
+export function isPastDate(date) {
+ const today = new Date(); // TODO: try to move this somewhere so we don't need to create a new Date each time
+ const d = new Date(date);
+ if (today.getFullYear() > d.getFullYear()) {
+ return true;
+ }
+ if (today.getFullYear() === d.getFullYear()) {
+ if (today.getMonth() > d.getMonth()) {
+ return true;
+ }
+ if (today.getMonth() === d.getMonth()) {
+ if (today.getDate() > d.getDate()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+export function isSameDay(d1, d2) {
+ 'worklet';
+
+ const diff = Math.abs(d1 - d2);
+ if (diff > DAY_IN_MS) {
+ return false;
+ }
+ const a = getDateObject(d1);
+ const b = getDateObject(d2);
+ if (a.year === b.year) {
+ if (a.month === b.month) {
+ if (a.day === b.day) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+export function isSameMonth(d1, d2) {
+ 'worklet';
+
+ const timestamp1 = typeof d1 === 'number' ? d1 : d1.timestamp;
+ const timestamp2 = typeof d2 === 'number' ? d2 : d2.timestamp;
+ const diff = Math.abs(timestamp1 - timestamp2);
+ if (diff > DAY_IN_MS * 31) {
+ return false;
+ }
+ const a = typeof d1 === 'number' ? getDateObject(d1) : d1;
+ const b = typeof d2 === 'number' ? getDateObject(d2) : d2;
+ if (a.year === b.year) {
+ if (a.month === b.month) {
+ return true;
+ }
+ }
+ return false;
+}
+export const _forTesting = {
+ getFirstDayInTheYear
+}; // exporting private functions for testing only
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/index.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/index.d.ts
new file mode 100644
index 0000000..35a3270
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/index.d.ts
@@ -0,0 +1,7 @@
+import React, { PropsWithChildren } from 'react';
+import { CalendarProps } from './types';
+declare function Calendar(props: PropsWithChildren): React.JSX.Element;
+declare namespace Calendar {
+ var Agenda: typeof import("./Agenda").default;
+}
+export default Calendar;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/index.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/index.js
new file mode 100644
index 0000000..aaafbcc
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/index.js
@@ -0,0 +1,187 @@
+import React, { useCallback, useMemo, useRef, useState } from 'react';
+import { useSharedValue, useAnimatedReaction, runOnJS } from 'react-native-reanimated';
+import { FlashListPackage } from "../../optionalDependencies";
+import { Constants } from "../../commons/new";
+import { generateMonthItems } from "./helpers/CalendarProcessor";
+import { addHeaders } from "./helpers/DataProcessor";
+import { isSameMonth, /* addYears, */getDateObject } from "./helpers/DateUtils";
+import { FirstDayOfWeek, UpdateSource } from "./types";
+import CalendarContext from "./CalendarContext";
+import CalendarItem from "./CalendarItem";
+import Agenda from "./Agenda";
+import TodayButton from "./TodayButton";
+import Header from "./Header";
+import { useDidUpdate } from "../../hooks";
+const FlashList = FlashListPackage?.FlashList;
+const VIEWABILITY_CONFIG = {
+ itemVisiblePercentThreshold: 95,
+ minimumViewTime: 200
+};
+const YEARS_RANGE = 1;
+const PAGE_RELOAD_THRESHOLD = 3;
+const NOW = Date.now(); // so the 'initialDate' effect won't get called since the now different on every rerender
+
+function Calendar(props) {
+ const {
+ data,
+ children,
+ initialDate = NOW,
+ onChangeDate,
+ firstDayOfWeek = FirstDayOfWeek.MONDAY,
+ staticHeader = false,
+ showExtraDays = true
+ } = props;
+ const [items] = useState(() => generateMonthItems(initialDate, YEARS_RANGE, YEARS_RANGE));
+ const getItemIndex = useCallback(date => {
+ 'worklet';
+
+ const dateObject = getDateObject(date);
+ for (let i = 0; i < items.length; i++) {
+ if (items[i].month === dateObject.month && items[i].year === dateObject.year) {
+ return i;
+ }
+ }
+ return -1;
+ }, [items]);
+ const flashListRef = useRef();
+ const current = useSharedValue(initialDate);
+ const initialMonthIndex = useRef(getItemIndex(current.value));
+ const lastUpdateSource = useSharedValue(UpdateSource.INIT);
+ const processedData = useMemo(() => addHeaders(data), [data]);
+ const scrolledByUser = useSharedValue(false);
+ const headerHeight = useSharedValue(0);
+ const setDate = useCallback((date, updateSource) => {
+ current.value = date;
+ lastUpdateSource.value = updateSource;
+ if (updateSource !== UpdateSource.PROP_UPDATE) {
+ onChangeDate?.(date);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const scrollToIndex = useCallback(index => {
+ scrolledByUser.value = false;
+ // @ts-expect-error
+ flashListRef.current?.scrollToIndex({
+ index,
+ animated: true
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [getItemIndex]);
+ useDidUpdate(() => {
+ setDate(initialDate, UpdateSource.PROP_UPDATE);
+ }, [initialDate]);
+ useDidUpdate(() => {
+ console.log('Update items');
+ const index = getItemIndex(current.value);
+ scrollToIndex(index);
+ }, [items, getItemIndex]);
+ const setHeaderHeight = useCallback(height => {
+ headerHeight.value = height;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const contextValue = useMemo(() => {
+ return {
+ data: processedData,
+ firstDayOfWeek,
+ selectedDate: current,
+ setDate,
+ showWeeksNumbers: true,
+ showExtraDays,
+ updateSource: lastUpdateSource,
+ staticHeader,
+ setHeaderHeight,
+ headerHeight,
+ today: NOW
+ };
+ }, [processedData, staticHeader, showExtraDays, firstDayOfWeek]);
+
+ /** Pages reload */
+
+ // const mergeArrays = (prepend: boolean, array: DateObjectWithOptionalDay[], newArray: DateObjectWithOptionalDay[]) => {
+ // const arr: DateObjectWithOptionalDay[] = array.slice();
+ // if (prepend) {
+ // arr.unshift(...newArray);
+ // } else {
+ // arr.push(...newArray);
+ // }
+ // return arr;
+ // };
+
+ const addPages = useCallback((/* index: number */
+ ) => {
+ // const prepend = index < PAGE_RELOAD_THRESHOLD;
+ // const append = index > items.length - PAGE_RELOAD_THRESHOLD;
+ // const pastRange = prepend ? YEARS_RANGE : 0;
+ // const futureRange = append ? YEARS_RANGE : 0;
+ // const newDate = addYears(current.value, prepend ? -1 : 1);
+ // const newItems = generateMonthItems(newDate, pastRange, futureRange);
+ // const newArray = mergeArrays(prepend, items, newItems);
+ // setItems(newArray);
+ // // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [items]);
+ const shouldAddPages = useCallback(index => {
+ 'worklet';
+
+ return index !== -1 && (index < PAGE_RELOAD_THRESHOLD || index > items.length - PAGE_RELOAD_THRESHOLD);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [items]);
+ useAnimatedReaction(() => {
+ return current.value;
+ }, (selected, previous) => {
+ const index = getItemIndex(selected);
+ if (shouldAddPages(index)) {
+ console.log('Add new pages: ', index, items.length);
+ runOnJS(addPages)(/* index */);
+ } else if (lastUpdateSource.value !== UpdateSource.MONTH_SCROLL) {
+ if (previous && !isSameMonth(selected, previous)) {
+ runOnJS(scrollToIndex)(index);
+ }
+ }
+ }, [getItemIndex]);
+
+ /** Events */
+
+ // eslint-disable-next-line max-len
+ const onViewableItemsChanged = useCallback(({
+ viewableItems
+ }) => {
+ const item = viewableItems?.[0]?.item;
+ if (item && scrolledByUser.value) {
+ if (!isSameMonth(item, current.value)) {
+ const newDate = getDateObject({
+ year: item.year,
+ month: item.month,
+ day: 1
+ }).timestamp;
+ setDate(newDate, UpdateSource.MONTH_SCROLL);
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const onMomentumScrollBegin = useCallback(() => {
+ scrolledByUser.value = true;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const onScrollBeginDrag = useCallback(() => {
+ scrolledByUser.value = true;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const renderCalendarItem = useCallback(({
+ item
+ }) => {
+ if (!staticHeader || headerHeight.value) {
+ // item is rendered before static header height is calculated so it leaves extra space
+ return ;
+ }
+ }, []);
+ return
+ {staticHeader && }
+
+ {children}
+
+ ;
+}
+Calendar.Agenda = Agenda;
+export default Calendar;
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/types.d.ts b/node_modules/react-native-ui-lib/src/incubator/Calendar/types.d.ts
new file mode 100644
index 0000000..cf52504
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/types.d.ts
@@ -0,0 +1,119 @@
+///
+import { StyleProp, ViewStyle, TextStyle } from 'react-native';
+import { SharedValue } from 'react-native-reanimated';
+import { ButtonProps } from '../../components/button';
+export interface DateObject {
+ timestamp: number;
+ month: number;
+ year: number;
+ day: number;
+ dayOfTheWeek: number;
+}
+export interface DateObjectWithDate {
+ month: number;
+ year: number;
+ day: number;
+}
+export interface DateObjectWithOptionalDay {
+ timestamp: number;
+ month: number;
+ year: number;
+ day?: number;
+}
+export declare enum FirstDayOfWeek {
+ SUNDAY = 0,
+ MONDAY = 1,
+ SATURDAY = 6
+}
+export declare enum UpdateSource {
+ INIT = 0,
+ DAY_SELECT = 1,
+ MONTH_ARROW = 2,
+ MONTH_SCROLL = 3,
+ WEEK_ARROW = 4,
+ WEEK_SCROLL = 5,
+ AGENDA_SCROLL = 6,
+ TODAY_PRESS = 7,
+ PROP_UPDATE = 8
+}
+export interface Event {
+ id: string;
+ start: number;
+ end: number;
+}
+export type Data = Event[];
+export type DateSectionHeader = {
+ header: string;
+ date: number;
+};
+export type InternalEvent = (Event & {
+ type: 'Event';
+}) | (DateSectionHeader & {
+ type: 'Header';
+});
+export type InternalData = InternalEvent[];
+export interface CalendarContextProps {
+ firstDayOfWeek: FirstDayOfWeek;
+ selectedDate: SharedValue;
+ setDate: (date: number, updateSource: UpdateSource) => void;
+ data: InternalData;
+ showWeeksNumbers: boolean;
+ showExtraDays: boolean;
+ updateSource: SharedValue;
+ staticHeader?: boolean;
+ setHeaderHeight?: (height: number) => void;
+ headerHeight: SharedValue;
+ today: number;
+}
+export interface DayProps {
+ date: number;
+ onPress?: (date: number) => void;
+ currentMonth?: number;
+}
+export interface WeekProps {
+ weekNumber: number;
+ year: number;
+ month: number;
+}
+export interface MonthProps {
+ month: number;
+ year: number;
+}
+export interface CalendarItemProps {
+ weekNumber?: number;
+ month?: number;
+ year: number;
+}
+export interface HeaderProps {
+ year?: number;
+ month?: number;
+}
+export interface TodayButtonProps {
+ containerStyle?: StyleProp;
+ buttonProps?: ButtonProps;
+}
+export interface WeekDaysNamesProps {
+ containerStyle?: StyleProp;
+ textStyle?: StyleProp;
+ format?: DayNamesFormat;
+}
+export declare enum DayNamesFormat {
+ DEFAULT = 0,
+ LONG_ABBREVIATION = 1,
+ SHORT_ABBREVIATION = 2
+}
+export interface CalendarProps {
+ data: Data;
+ initialDate?: number;
+ onChangeDate?: (date: number) => void;
+ firstDayOfWeek?: FirstDayOfWeek;
+ staticHeader?: boolean;
+ showExtraDays?: boolean;
+}
+export interface AgendaProps {
+ renderEvent?: (event: Event) => React.ReactElement | null;
+ renderHeader?: (header: DateSectionHeader) => React.ReactElement | null;
+ itemHeight?: number;
+ showLoader?: boolean;
+ onEndReached?: (date: number) => void;
+}
diff --git a/node_modules/react-native-ui-lib/src/incubator/Calendar/types.js b/node_modules/react-native-ui-lib/src/incubator/Calendar/types.js
new file mode 100644
index 0000000..a185dfc
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Calendar/types.js
@@ -0,0 +1,24 @@
+export let FirstDayOfWeek = /*#__PURE__*/function (FirstDayOfWeek) {
+ FirstDayOfWeek[FirstDayOfWeek["SUNDAY"] = 0] = "SUNDAY";
+ FirstDayOfWeek[FirstDayOfWeek["MONDAY"] = 1] = "MONDAY";
+ FirstDayOfWeek[FirstDayOfWeek["SATURDAY"] = 6] = "SATURDAY";
+ return FirstDayOfWeek;
+}({});
+export let UpdateSource = /*#__PURE__*/function (UpdateSource) {
+ UpdateSource[UpdateSource["INIT"] = 0] = "INIT";
+ UpdateSource[UpdateSource["DAY_SELECT"] = 1] = "DAY_SELECT";
+ UpdateSource[UpdateSource["MONTH_ARROW"] = 2] = "MONTH_ARROW";
+ UpdateSource[UpdateSource["MONTH_SCROLL"] = 3] = "MONTH_SCROLL";
+ UpdateSource[UpdateSource["WEEK_ARROW"] = 4] = "WEEK_ARROW";
+ UpdateSource[UpdateSource["WEEK_SCROLL"] = 5] = "WEEK_SCROLL";
+ UpdateSource[UpdateSource["AGENDA_SCROLL"] = 6] = "AGENDA_SCROLL";
+ UpdateSource[UpdateSource["TODAY_PRESS"] = 7] = "TODAY_PRESS";
+ UpdateSource[UpdateSource["PROP_UPDATE"] = 8] = "PROP_UPDATE";
+ return UpdateSource;
+}({});
+export let DayNamesFormat = /*#__PURE__*/function (DayNamesFormat) {
+ DayNamesFormat[DayNamesFormat["DEFAULT"] = 0] = "DEFAULT";
+ DayNamesFormat[DayNamesFormat["LONG_ABBREVIATION"] = 1] = "LONG_ABBREVIATION";
+ DayNamesFormat[DayNamesFormat["SHORT_ABBREVIATION"] = 2] = "SHORT_ABBREVIATION";
+ return DayNamesFormat;
+}({});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.d.ts b/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.d.ts
new file mode 100644
index 0000000..0603037
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.d.ts
@@ -0,0 +1,6 @@
+import { ComponentProps } from '../../testkit/new/Component.driver';
+export declare const DialogDriver: (props: ComponentProps) => {
+ isVisible: () => boolean;
+ pressOnBackground: () => void;
+ exists: () => boolean;
+};
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.js b/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.js
new file mode 100644
index 0000000..ab84a37
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/Dialog.driver.new.js
@@ -0,0 +1,25 @@
+import { ModalDriver } from "../../testkit/";
+export const DialogDriver = props => {
+ const {
+ renderTree,
+ testID
+ } = props;
+ const modalDriver = ModalDriver({
+ renderTree,
+ testID: `${testID}.modal`
+ });
+ const exists = () => {
+ return modalDriver.exists();
+ };
+ const isVisible = () => {
+ return modalDriver.isVisible();
+ };
+ const pressOnBackground = () => {
+ modalDriver.pressOnBackground();
+ };
+ return {
+ isVisible,
+ pressOnBackground,
+ exists
+ };
+};
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.d.ts b/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.d.ts
new file mode 100644
index 0000000..8b2dac5
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.d.ts
@@ -0,0 +1,4 @@
+import React from 'react';
+import { DialogHeaderProps } from './types';
+declare const _default: React.ForwardRefExoticComponent>;
+export default _default;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.js b/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.js
new file mode 100644
index 0000000..a016cf5
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/DialogHeader.js
@@ -0,0 +1,86 @@
+import _isEmpty from "lodash/isEmpty";
+import React, { useMemo } from 'react';
+import { StyleSheet } from 'react-native';
+import { asBaseComponent } from "../../commons/new";
+import { Spacings, Colors, BorderRadiuses, Dividers } from "../../style";
+import View from "../../components/view";
+import TouchableOpacity from "../../components/touchableOpacity";
+import Text from "../../components/text";
+const DialogHeader = (props = {}) => {
+ const {
+ title,
+ titleStyle,
+ titleProps,
+ subtitle,
+ subtitleStyle,
+ subtitleProps,
+ showKnob = true,
+ showDivider = true,
+ leadingAccessory,
+ trailingAccessory,
+ topAccessory,
+ bottomAccessory,
+ contentContainerStyle,
+ onPress,
+ style,
+ ...others
+ } = props;
+ const knob = useMemo(() => {
+ if (showKnob) {
+ return ;
+ }
+ }, [showKnob]);
+ const headerContent = useMemo(() => {
+ const Container = onPress ? TouchableOpacity : View;
+ if (!_isEmpty(title) || !_isEmpty(subtitle)) {
+ return
+ {!_isEmpty(title) &&
+ {title}
+ }
+ {!_isEmpty(subtitle) &&
+ {subtitle}
+ }
+ ;
+ }
+ return null;
+ }, [title, titleStyle, titleProps, subtitle, subtitleStyle, subtitleProps, onPress]);
+ const content = useMemo(() => {
+ if (headerContent || leadingAccessory || trailingAccessory) {
+ return
+ {leadingAccessory}
+ {headerContent}
+ {trailingAccessory}
+ ;
+ }
+ return null;
+ }, [headerContent, leadingAccessory, trailingAccessory, contentContainerStyle]);
+ const divider = useMemo(() => {
+ if (showDivider) {
+ return ;
+ }
+ }, [showDivider]);
+ if (knob || content || topAccessory || bottomAccessory || divider) {
+ return
+ {knob}
+ {topAccessory}
+ {content}
+ {bottomAccessory}
+ {divider}
+ ;
+ }
+ return null;
+};
+DialogHeader.displayName = 'Incubator.Dialog.Header';
+export default asBaseComponent(DialogHeader);
+const styles = StyleSheet.create({
+ knob: {
+ alignSelf: 'center',
+ width: 44,
+ height: Spacings.s1,
+ marginTop: Spacings.s2,
+ marginBottom: Spacings.s2,
+ borderRadius: BorderRadiuses.br10
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/dialog.api.json b/node_modules/react-native-ui-lib/src/incubator/Dialog/dialog.api.json
new file mode 100644
index 0000000..0a56b6f
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/dialog.api.json
@@ -0,0 +1,54 @@
+{
+ "name": "Dialog",
+ "category": "incubator",
+ "description": "Component for displaying custom content inside a popup dialog",
+ "note": "Use alignment modifiers to control the dialog position (top, bottom, centerV, centerH, etc... by default the dialog is aligned to center). \nWhen adding a `FlatList` \\ `ScrollView` to the content be sure to use one from `react-native-gesture-handler` (see [this link](https://github.com/software-mansion/react-native-gesture-handler/issues/1380) for `SectionList`).",
+ "modifiers": ["alignment"],
+ "example": "https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/incubatorScreens/IncubatorDialogScreen.tsx",
+ "props": [
+ {"name": "visible", "type": "boolean", "description": "The visibility of the dialog"},
+ {"name": "headerProps", "type": "DialogHeaderProps", "description": "The Dialog's header (title, subtitle etc)"},
+ {
+ "name": "containerStyle",
+ "type": "ViewStyle",
+ "description": "The Dialog`s container style (it is set to {position: 'absolute'})"
+ },
+ {
+ "name": "containerProps",
+ "type": "ViewProps",
+ "description": "Extra props for the container"
+ },
+ {
+ "name": "onDismiss",
+ "type": "(props?: DialogProps) => void",
+ "description": "Callback that is called after the dialog's dismiss (after the animation has ended)."
+ },
+ {
+ "name": "direction",
+ "type": "up | down | left | right",
+ "description": "The direction from which and to which the dialog is animating \\ panning (default down).",
+ "default": "down"
+ },
+ {
+ "name": "showClose",
+ "type": "boolean",
+ "description": "Show the close button"
+ },
+ {"name": "ignoreBackgroundPress", "type": "boolean", "description": "Whether or not to ignore background press."},
+ {"name": "modalProps", "type": "ModalProps", "description": "Pass props to the dialog modal"},
+ {
+ "name": "testID",
+ "type": "string",
+ "description": "Used to locate this view in end-to-end tests. \nThe container has the original id. \nSupported inner elements IDs: \n`${TestID}.modal` - the Modal's id. \n`${TestID}.overlayFadingBackground` - the fading background id."
+ }
+ ],
+ "snippet": [
+ ""
+ ]
+}
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/dialogHeader.api.json b/node_modules/react-native-ui-lib/src/incubator/Dialog/dialogHeader.api.json
new file mode 100644
index 0000000..47687bc
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/dialogHeader.api.json
@@ -0,0 +1,39 @@
+{
+ "name": "Dialog.Header",
+ "category": "incubator",
+ "description": "Component for displaying the header of a popup dialog",
+ "example": "https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/incubatorScreens/IncubatorDialogScreen.tsx",
+ "props": [
+ {"name": "title", "type": "string", "description": "Title"},
+ {"name": "titleStyle", "type": "StyleProp", "description": "Title text style"},
+ {"name": "titleProps", "type": "TextProps", "description": "Title extra props"},
+ {"name": "subtitle", "type": "string", "description": "Subtitle"},
+ {"name": "subtitleStyle", "type": "StyleProp", "description": "Subtitle text style"},
+ {"name": "subtitleProps", "type": "TextProps", "description": "Subtitle extra props"},
+ {"name": "showKnob", "type": "boolean", "description": "Show the header's knob", "default": "true"},
+ {"name": "showDivider", "type": "boolean", "description": "Show the header's divider", "default": "true"},
+ {"name": "leadingAccessory", "type": "ReactElement", "description": "Pass to render a leading element"},
+ {"name": "trailingAccessory", "type": "ReactElement", "description": "Pass to render a trailing element"},
+ {
+ "name": "topAccessory",
+ "type": "ReactElement",
+ "description": "Pass to render a top element above the title"
+ },
+ {
+ "name": "bottomAccessory",
+ "type": "ReactElement",
+ "description": "Pass to render a bottom element below the subtitle"
+ },
+ {
+ "name": "contentContainerStyle",
+ "type": "ViewProps['style']",
+ "description": "Style for the leading + content + trailing components (without the bottomAccessory)"
+ },
+ {
+ "name": "onPress",
+ "type": "() => void",
+ "description": "onPress callback for the inner content"
+ }
+ ],
+ "snippet": [""]
+}
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/index.d.ts b/node_modules/react-native-ui-lib/src/incubator/Dialog/index.d.ts
new file mode 100644
index 0000000..47059d9
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/index.d.ts
@@ -0,0 +1,15 @@
+import React from 'react';
+import DialogHeader from './DialogHeader';
+import { DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogMigrationProps } from './types';
+export { DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogMigrationProps };
+export interface DialogStatics {
+ directions: typeof DialogDirectionsEnum;
+ Header: typeof DialogHeader;
+}
+export interface DialogImperativeMethods {
+ dismiss: () => void;
+}
+declare const _default: React.ForwardRefExoticComponent> & DialogStatics;
+export default _default;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/index.js b/node_modules/react-native-ui-lib/src/incubator/Dialog/index.js
new file mode 100644
index 0000000..bf902c9
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/index.js
@@ -0,0 +1,218 @@
+import React, { useMemo, useCallback, useImperativeHandle, forwardRef, useEffect, useState } from 'react';
+import { StyleSheet } from 'react-native';
+import hoistStatics from 'hoist-non-react-statics';
+import { Extrapolation, interpolate, runOnJS, useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
+import { Gesture, GestureDetector } from 'react-native-gesture-handler';
+import { Spacings, Colors, BorderRadiuses } from "../../style";
+import { useDidUpdate } from "../../hooks";
+import { asBaseComponent, Constants } from "../../commons/new";
+import View from "../../components/view";
+import Modal from "../../components/modal";
+import { extractAlignmentsValues } from "../../commons/modifiers";
+import useHiddenLocation from "../hooks/useHiddenLocation";
+import DialogHeader from "./DialogHeader";
+import useDialogContent from "./useDialogContent";
+import { DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogMigrationProps } from "./types";
+export { DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogMigrationProps };
+const THRESHOLD_VELOCITY = 750;
+const Dialog = (props, ref) => {
+ const {
+ visible = false,
+ headerProps,
+ showCloseButton,
+ closeButtonProps,
+ containerStyle: propsContainerStyle,
+ containerProps: propsContainerProps,
+ width,
+ height,
+ onDismiss,
+ direction = DialogDirectionsEnum.DOWN,
+ ignoreBackgroundPress,
+ modalProps = {},
+ useSafeArea,
+ testID,
+ children
+ } = props;
+ const {
+ overlayBackgroundColor = Colors.rgba(Colors.grey10, 0.65),
+ ...otherModalProps
+ } = modalProps;
+ const visibility = useSharedValue(0); // value between 0 (closed) and 1 (open)
+ const initialTranslation = useSharedValue(0);
+ const [modalVisibility, setModalVisibility] = useState(visible); // unfortunately this is needed when changing visibility by the user (clicking on an option etc)
+
+ const {
+ setRef,
+ onLayout,
+ hiddenLocation: _hiddenLocation
+ } = useHiddenLocation();
+ const hiddenLocation = _hiddenLocation[direction];
+ const wasMeasured = _hiddenLocation.wasMeasured;
+ const isVertical = useMemo(() => {
+ 'worklet';
+
+ return direction === DialogDirectionsEnum.DOWN || direction === DialogDirectionsEnum.UP;
+ }, [direction]);
+ const getTranslationInterpolation = useCallback(value => {
+ 'worklet';
+
+ return interpolate(value, [0, 1], [hiddenLocation, 0], Extrapolation.CLAMP);
+ }, [hiddenLocation]);
+ const getTranslationReverseInterpolation = useCallback(value => {
+ 'worklet';
+
+ return interpolate(value, [hiddenLocation, 0], [0, 1]);
+ }, [hiddenLocation]);
+ const _onDismiss = useCallback(() => {
+ 'worklet';
+
+ runOnJS(setModalVisibility)(false);
+ }, []);
+ const close = useCallback(() => {
+ 'worklet';
+
+ visibility.value = withTiming(0, undefined, _onDismiss);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [_onDismiss]);
+ const open = useCallback(() => {
+ 'worklet';
+
+ visibility.value = withSpring(1);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ useEffect(() => {
+ if (visible) {
+ setModalVisibility(true);
+ } else if (wasMeasured && modalVisibility) {
+ // Close when sending visible = false
+ close();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [visible, wasMeasured]);
+ useDidUpdate(() => {
+ if (wasMeasured) {
+ if (modalVisibility) {
+ open();
+ } else if (Constants.isAndroid) {
+ onDismiss?.();
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [modalVisibility, wasMeasured]);
+ const alignmentStyle = useMemo(() => {
+ return {
+ flex: 1,
+ alignItems: 'center',
+ ...extractAlignmentsValues(props)
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const {
+ renderDialogContent,
+ containerProps,
+ containerStyle
+ } = useDialogContent({
+ showCloseButton,
+ close,
+ closeButtonProps,
+ containerStyle: propsContainerStyle,
+ containerProps: propsContainerProps,
+ headerProps,
+ children
+ });
+ const animatedStyle = useAnimatedStyle(() => {
+ if (isVertical) {
+ return {
+ transform: [{
+ translateY: getTranslationInterpolation(visibility.value)
+ }]
+ };
+ } else {
+ return {
+ transform: [{
+ translateX: getTranslationInterpolation(visibility.value)
+ }]
+ };
+ }
+ });
+ const style = useMemo(() => {
+ return [styles.defaultDialogStyle, {
+ backgroundColor: Colors.$backgroundDefault
+ }, containerStyle, animatedStyle, width ? {
+ width
+ } : undefined, height ? {
+ height
+ } : undefined];
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [containerStyle, width, height]);
+ const shouldClose = event => {
+ 'worklet';
+
+ const wasPannedOverThreshold = Math.abs(getTranslationInterpolation(visibility.value)) >= Math.abs(hiddenLocation / 3);
+ let velocity;
+ switch (direction) {
+ case DialogDirectionsEnum.DOWN:
+ default:
+ velocity = event.velocityY;
+ break;
+ case DialogDirectionsEnum.UP:
+ velocity = -event.velocityY;
+ break;
+ case DialogDirectionsEnum.LEFT:
+ velocity = -event.velocityX;
+ break;
+ case DialogDirectionsEnum.RIGHT:
+ velocity = event.velocityX;
+ break;
+ }
+ const wasFlung = velocity >= THRESHOLD_VELOCITY;
+ return wasPannedOverThreshold || wasFlung;
+ };
+ const panGesture = Gesture.Pan().onStart(event => {
+ initialTranslation.value = getTranslationReverseInterpolation(isVertical ? event.translationY : event.translationX) - visibility.value;
+ }).onUpdate(event => {
+ visibility.value = getTranslationReverseInterpolation(isVertical ? event.translationY : event.translationX) - initialTranslation.value;
+ }).onEnd(event => {
+ if (shouldClose(event)) {
+ close();
+ } else {
+ open();
+ }
+ });
+ useImperativeHandle(ref, () => ({
+ dismiss: close
+ }));
+ const renderDialog = () =>
+
+ {renderDialogContent()}
+
+ ;
+ const overlayStyle = useAnimatedStyle(() => {
+ return {
+ opacity: visibility.value,
+ backgroundColor: overlayBackgroundColor
+ };
+ }, [overlayBackgroundColor]);
+ const renderOverlayView = () => ;
+ return
+ {renderOverlayView()}
+
+ {renderDialog()}
+
+ ;
+};
+Dialog.displayName = 'Incubator.Dialog';
+Dialog.directions = DialogDirectionsEnum;
+Dialog.Header = DialogHeader;
+const _Dialog = forwardRef(Dialog);
+hoistStatics(_Dialog, Dialog);
+export default asBaseComponent(_Dialog);
+const styles = StyleSheet.create({
+ defaultDialogStyle: {
+ marginBottom: Spacings.s5,
+ maxHeight: '60%',
+ width: 250,
+ borderRadius: BorderRadiuses.br20,
+ overflow: 'hidden'
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/types.d.ts b/node_modules/react-native-ui-lib/src/incubator/Dialog/types.d.ts
new file mode 100644
index 0000000..a9d90e4
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/types.d.ts
@@ -0,0 +1,150 @@
+import { PropsWithChildren, ReactElement } from 'react';
+import { type DimensionValue, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';
+import { AlignmentModifiers } from '../../commons/modifiers';
+import { DialogProps as DialogPropsOld } from '../../components/dialog';
+import { ButtonProps } from '../../components/button';
+import { ModalProps } from '../../components/modal';
+import { PanningDirections, PanningDirectionsEnum } from '../panView';
+import { TextProps } from '../../components/text';
+import { ViewProps } from '../../components/view';
+type DialogDirections = PanningDirections;
+declare const DialogDirectionsEnum: typeof PanningDirectionsEnum;
+export { DialogDirections, DialogDirectionsEnum };
+export interface DialogHeaderProps extends ViewProps {
+ /**
+ * Title
+ */
+ title?: string;
+ /**
+ * Title text style
+ */
+ titleStyle?: StyleProp;
+ /**
+ * Title extra props
+ */
+ titleProps?: TextProps;
+ /**
+ * Subtitle
+ */
+ subtitle?: string;
+ /**
+ * Subtitle text style
+ */
+ subtitleStyle?: StyleProp;
+ /**
+ * Subtitle extra props
+ */
+ subtitleProps?: TextProps;
+ /**
+ * Show the header's knob (default is true)
+ */
+ showKnob?: boolean;
+ /**
+ * Show the header's divider (default is true)
+ */
+ showDivider?: boolean;
+ /**
+ * Pass to render a leading element
+ */
+ leadingAccessory?: ReactElement;
+ /**
+ * Pass to render a trailing element
+ */
+ trailingAccessory?: ReactElement;
+ /**
+ * Pass to render a top element above the title
+ */
+ topAccessory?: ReactElement;
+ /**
+ * Pass to render a bottom element below the subtitle
+ */
+ bottomAccessory?: ReactElement;
+ /**
+ * Style for the leading + content + trailing components (without the topAccessory\bottomAccessory)
+ */
+ contentContainerStyle?: ViewProps['style'];
+ /**
+ * onPress callback for the inner content
+ */
+ onPress?: () => void;
+}
+export interface DialogCloseButtonProps {
+ /**
+ * The Dialog's header (title, subtitle etc)
+ */
+ headerProps?: DialogHeaderProps;
+ /**
+ * The Dialog`s container style (it is set to {position: 'absolute'})
+ */
+ containerStyle?: StyleProp;
+ /**
+ * Extra props for the container
+ */
+ containerProps?: Omit;
+ /**
+ * Whether to show the close button or not
+ */
+ showCloseButton?: boolean;
+ /**
+ * The close button props
+ */
+ closeButtonProps?: Pick;
+}
+export interface _DialogProps extends AlignmentModifiers, Pick, DialogCloseButtonProps {
+ /**
+ * The visibility of the dialog.
+ */
+ visible?: boolean;
+ /**
+ * The dialog width.
+ */
+ width?: DimensionValue;
+ /**
+ * The dialog height.
+ */
+ height?: DimensionValue;
+ /**
+ * Callback that is called after the dialog's dismiss (after the animation has ended).
+ */
+ onDismiss?: () => void;
+ /**
+ * The direction from which and to which the dialog is animating \ panning (default down).
+ */
+ direction?: DialogDirections;
+ /**
+ * Whether or not to ignore background press.
+ */
+ ignoreBackgroundPress?: boolean;
+ /**
+ * Additional props for the modal.
+ */
+ modalProps?: ModalProps;
+ /**
+ * Used to locate this view in end-to-end tests
+ * The container has the unchanged id.
+ * Currently supported inner IDs:
+ * TODO: add missing (s?)
+ * .modal - the Modal's id.
+ * .overlayFadingBackground - the fading background id.
+ */
+ testID?: string;
+}
+export type DialogProps = PropsWithChildren<_DialogProps>;
+export interface _DialogPropsOld {
+ /**
+ * The props to pass to the dialog expandable container
+ */
+ dialogProps?: DialogPropsOld;
+ migrateDialog?: false;
+}
+export interface _DialogPropsNew {
+ /**
+ * The props to pass to the dialog expandable container
+ */
+ dialogProps?: DialogProps;
+ /**
+ * Migrate the Dialog to DialogNew (make sure you use only new props in dialogProps)
+ */
+ migrateDialog: true;
+}
+export type DialogMigrationProps = _DialogPropsOld | _DialogPropsNew;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/types.js b/node_modules/react-native-ui-lib/src/incubator/Dialog/types.js
new file mode 100644
index 0000000..5583c2d
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/types.js
@@ -0,0 +1,5 @@
+import { PanningDirectionsEnum } from "../panView";
+const DialogDirectionsEnum = PanningDirectionsEnum;
+export { DialogDirectionsEnum };
+
+// For migration purposes
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.d.ts b/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.d.ts
new file mode 100644
index 0000000..4de1075
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.d.ts
@@ -0,0 +1,13 @@
+import React, { PropsWithChildren } from 'react';
+import { DialogCloseButtonProps } from './types';
+interface InternalDialogCloseButtonProps extends PropsWithChildren {
+ close: () => void;
+}
+declare const useDialogContent: (props: InternalDialogCloseButtonProps) => {
+ renderDialogContent: () => React.JSX.Element;
+ containerStyle: false | import("react-native").ViewStyle | import("react-native").RegisteredStyle | import("react-native").RecursiveArray> | (import("react-native").StyleProp | {
+ backgroundColor: string;
+ })[] | null | undefined;
+ containerProps: Omit | undefined;
+};
+export default useDialogContent;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.js b/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.js
new file mode 100644
index 0000000..483d887
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Dialog/useDialogContent.js
@@ -0,0 +1,73 @@
+import React, { useMemo } from 'react';
+import { BorderRadiuses, Colors } from "../../style";
+import { StyleSheet } from 'react-native';
+import Assets from "../../assets";
+import DialogHeader from "./DialogHeader";
+import Icon from "../../components/icon";
+import Text from "../../components/text";
+import TouchableOpacity from "../../components/touchableOpacity";
+import View from "../../components/view";
+const useDialogContent = props => {
+ const {
+ showCloseButton,
+ close,
+ closeButtonProps,
+ containerStyle: propsContainerStyle,
+ containerProps: propsContainerProps,
+ headerProps,
+ children
+ } = props;
+ const DialogCloseButton = useMemo(() => {
+ if (!showCloseButton) {
+ return null;
+ }
+ return
+
+
+
+ {closeButtonProps?.label || 'Close'}
+
+
+ ;
+ }, [showCloseButton, close, closeButtonProps]);
+ const containerProps = useMemo(() => {
+ return showCloseButton ? {
+ ...propsContainerProps,
+ pointerEvents: 'box-none'
+ } : propsContainerProps;
+ }, [showCloseButton, propsContainerProps]);
+ const containerStyle = useMemo(() => {
+ return showCloseButton ? [propsContainerStyle, styles.transparent] : propsContainerStyle;
+ }, [showCloseButton, propsContainerStyle]);
+ const renderDialogContent = () => {
+ const DialogContent = <>
+ {headerProps && }
+ {children}
+ >;
+ if (DialogCloseButton) {
+ return <>
+ {DialogCloseButton}
+ {DialogContent}
+ >;
+ } else {
+ return DialogContent;
+ }
+ };
+ return {
+ renderDialogContent,
+ containerStyle,
+ containerProps
+ };
+};
+export default useDialogContent;
+const styles = StyleSheet.create({
+ transparent: {
+ backgroundColor: Colors.transparent
+ },
+ dialogContentContainer: {
+ flexShrink: 1,
+ backgroundColor: Colors.$backgroundDefault,
+ overflow: 'hidden',
+ borderRadius: BorderRadiuses.br60
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.d.ts b/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.d.ts
new file mode 100644
index 0000000..f5ddcaf
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.d.ts
@@ -0,0 +1,5 @@
+import { SliderProps } from './index';
+import { ComponentDriver } from '../../testkit/Component.driver';
+export declare class SliderDriver extends ComponentDriver {
+ isDisabled: () => Promise;
+}
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.js b/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.js
new file mode 100644
index 0000000..674edca
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Slider.driver.js
@@ -0,0 +1,4 @@
+import { ComponentDriver } from "../../testkit/Component.driver";
+export class SliderDriver extends ComponentDriver {
+ isDisabled = async () => (await this.getElementProps()).accessibilityState?.disabled === true;
+}
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.d.ts b/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.d.ts
new file mode 100644
index 0000000..2fad583
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.d.ts
@@ -0,0 +1,6 @@
+import { SharedValue } from 'react-native-reanimated';
+import { SliderProps } from './index';
+export declare function getOffsetForValue(value: number, span: number, minimumValue?: number, maximumValue?: number): number;
+export declare function getValueForOffset(offset: number, span: number, minimum?: number, maximum?: number, step?: number): number;
+export declare function validateValues(props: SliderProps): void;
+export declare function getStepInterpolated(trackWidth: number, minimumValue: number, maximumValue: number, stepXValue: SharedValue): number;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.js b/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.js
new file mode 100644
index 0000000..37ddb5a
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/SliderPresenter.js
@@ -0,0 +1,64 @@
+import { interpolate } from 'react-native-reanimated';
+export function getOffsetForValue(value, span, minimumValue = 0, maximumValue = 1) {
+ const range = maximumValue - minimumValue;
+ const relativeValue = minimumValue - value;
+ const v = minimumValue < 0 ? Math.abs(relativeValue) : value - minimumValue; // for negative values
+ const ratio = v / range;
+ const x = ratio * span;
+ return x;
+}
+function countDecimals(value) {
+ 'worklet';
+
+ if (Math.floor(value.valueOf()) === value.valueOf()) {
+ return 0;
+ }
+ return value.toString().split('.')[1].length || 0;
+}
+export function getValueForOffset(offset, span, minimum = 0, maximum = 1, step = 0) {
+ 'worklet';
+
+ if (span) {
+ const ratio = offset / span;
+ const range = maximum - minimum;
+ let val = ratio * range;
+ if (step > 0) {
+ const decimals = countDecimals(step);
+ val = Number((Math.round(ratio * range / step) * step).toFixed(decimals));
+ }
+ return Math.max(minimum, Math.min(maximum, minimum + val));
+ }
+ return 0;
+}
+function inRange(value, min, max) {
+ return value >= min && value <= max;
+}
+export function validateValues(props) {
+ const {
+ useRange,
+ value,
+ minimumValue = 0,
+ maximumValue = 1,
+ initialMinimumValue,
+ initialMaximumValue
+ } = props;
+ if (minimumValue > maximumValue || useRange && initialMinimumValue && initialMaximumValue && initialMinimumValue > initialMaximumValue) {
+ console.error('Your passed values are invalid. Please check if minimum values are not higher than maximum values');
+ }
+ if (value !== undefined && minimumValue && maximumValue && !inRange(value, minimumValue, maximumValue)) {
+ console.error(`Your passed value (${value}) is invalid.
+ Please check that it is in range of the minimum (${minimumValue}) and maximum (${maximumValue}) values`);
+ }
+ if (useRange && initialMinimumValue && initialMaximumValue) {
+ if (!inRange(initialMinimumValue, minimumValue, maximumValue) || !inRange(initialMaximumValue, minimumValue, maximumValue)) {
+ console.error('Your passed values are invalid. Please check that they are in range of the minimum and maximum values');
+ }
+ }
+}
+export function getStepInterpolated(trackWidth, minimumValue, maximumValue, stepXValue) {
+ 'worklet';
+
+ const outputRange = [0, trackWidth];
+ const inputRange = minimumValue < 0 ? [0, Math.abs(minimumValue) + maximumValue] : [0, maximumValue - minimumValue];
+ return interpolate(stepXValue.value, inputRange, outputRange);
+}
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.d.ts b/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.d.ts
new file mode 100644
index 0000000..404848b
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.d.ts
@@ -0,0 +1,24 @@
+import React from 'react';
+import { ViewProps, ViewStyle } from 'react-native';
+import { SharedValue } from 'react-native-reanimated';
+interface ThumbProps extends ViewProps {
+ start: SharedValue;
+ end: SharedValue;
+ offset: SharedValue;
+ stepInterpolatedValue: SharedValue;
+ stepInterpolation?: () => number;
+ shouldBounceToStep?: boolean;
+ gap?: number;
+ disabled?: boolean;
+ secondary?: boolean;
+ defaultStyle?: SharedValue;
+ activeStyle?: SharedValue;
+ disableActiveStyling?: boolean;
+ hitSlop?: ViewProps['hitSlop'];
+ shouldDisableRTL?: boolean;
+ onSeekStart?: () => void;
+ onSeekEnd?: () => void;
+ enableShadow?: boolean;
+}
+declare const Thumb: (props: ThumbProps) => React.JSX.Element;
+export default Thumb;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.js b/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.js
new file mode 100644
index 0000000..a7a9ba9
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Thumb.js
@@ -0,0 +1,100 @@
+import React, { useCallback } from 'react';
+import { StyleSheet } from 'react-native';
+import { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
+import { GestureDetector, Gesture } from 'react-native-gesture-handler';
+import { Colors } from "../../style";
+import View from "../../components/view";
+import { Constants } from "../../commons/new";
+const SHADOW_RADIUS = 4;
+const THUMB_SIZE = 24;
+const Thumb = props => {
+ const {
+ disabled,
+ disableActiveStyling,
+ activeStyle,
+ defaultStyle,
+ hitSlop,
+ onSeekStart,
+ onSeekEnd,
+ start,
+ end,
+ offset,
+ shouldDisableRTL,
+ shouldBounceToStep,
+ stepInterpolatedValue,
+ gap = 0,
+ secondary,
+ enableShadow
+ } = props;
+ const rtlFix = Constants.isRTL ? -1 : 1;
+ const isPressed = useSharedValue(false);
+ const thumbSize = useSharedValue({
+ width: THUMB_SIZE,
+ height: THUMB_SIZE
+ });
+ const lastOffset = useSharedValue(0);
+ const gesture = Gesture.Pan().onBegin(() => {
+ onSeekStart?.();
+ isPressed.value = true;
+ lastOffset.value = offset.value;
+ }).onUpdate(e => {
+ let newX = lastOffset.value + e.translationX * (shouldDisableRTL ? 1 : rtlFix);
+ if (newX < start.value) {
+ // adjust start edge
+ newX = start.value;
+ } else if (newX > end.value) {
+ // adjust end edge
+ newX = end.value;
+ }
+ if (!secondary && newX <= gap || secondary && newX >= end.value - gap || newX < end.value - gap && newX > start.value + gap) {
+ offset.value = newX;
+ }
+ }).onEnd(() => {
+ onSeekEnd?.();
+ }).onFinalize(() => {
+ isPressed.value = false;
+ if (shouldBounceToStep) {
+ offset.value = Math.round(offset.value / stepInterpolatedValue.value) * stepInterpolatedValue.value;
+ }
+ });
+ gesture.enabled(!disabled);
+ const animatedStyle = useAnimatedStyle(() => {
+ const customStyle = isPressed.value ? activeStyle?.value : defaultStyle?.value;
+ return {
+ ...customStyle,
+ transform: [{
+ translateX: (offset.value - thumbSize.value.width / 2) * rtlFix
+ }, {
+ scale: withSpring(!disableActiveStyling && isPressed.value ? 1.3 : 1)
+ }]
+ };
+ });
+ const onThumbLayout = useCallback(event => {
+ const width = event.nativeEvent.layout.width;
+ const height = event.nativeEvent.layout.height;
+ thumbSize.value = {
+ width,
+ height
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ return
+
+ ;
+};
+const styles = StyleSheet.create({
+ thumbPosition: {
+ position: 'absolute'
+ },
+ thumbShadow: {
+ shadowColor: Colors.rgba(Colors.black, 0.3),
+ shadowOffset: {
+ width: 0,
+ height: 0
+ },
+ shadowOpacity: 0.9,
+ shadowRadius: SHADOW_RADIUS,
+ elevation: 2
+ }
+});
+export default Thumb;
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Track.d.ts b/node_modules/react-native-ui-lib/src/incubator/Slider/Track.d.ts
new file mode 100644
index 0000000..bf87910
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Track.d.ts
@@ -0,0 +1,13 @@
+import React, { ReactElement } from 'react';
+import { ViewProps, StyleProp, ViewStyle, GestureResponderEvent } from 'react-native';
+export interface Props extends ViewProps {
+ animatedStyle?: any;
+ disabled?: boolean;
+ maximumTrackTintColor?: string;
+ minimumTrackTintColor?: string;
+ trackStyle?: StyleProp;
+ renderTrack?: () => ReactElement | ReactElement[];
+ onPress?: ((event: GestureResponderEvent) => void) | undefined;
+}
+declare const Track: (props: Props) => React.JSX.Element;
+export default Track;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/Track.js b/node_modules/react-native-ui-lib/src/incubator/Slider/Track.js
new file mode 100644
index 0000000..7a6c92d
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/Track.js
@@ -0,0 +1,57 @@
+import isFunction from 'lodash/isFunction';
+import React from 'react';
+import { StyleSheet } from 'react-native';
+import { Colors } from "../../style";
+import View from "../../components/view";
+const TRACK_HEIGHT = 6;
+const Track = props => {
+ const {
+ onLayout,
+ onPress,
+ animatedStyle,
+ renderTrack,
+ disabled,
+ maximumTrackTintColor,
+ minimumTrackTintColor,
+ trackStyle
+ } = props;
+ const shouldRenderCustomTrack = isFunction(renderTrack);
+ const renderCustomTrack = () => {
+ return
+ {renderTrack?.()}
+ ;
+ };
+ const renderBackgroundTrack = () => {
+ return ;
+ };
+ const renderActiveTrack = () => {
+ return ;
+ };
+ return <>
+ {shouldRenderCustomTrack ? renderCustomTrack() : renderBackgroundTrack()}
+ {!shouldRenderCustomTrack && renderActiveTrack()}
+
+ >;
+};
+export default Track;
+const styles = StyleSheet.create({
+ track: {
+ height: TRACK_HEIGHT,
+ borderRadius: TRACK_HEIGHT / 2
+ },
+ activeTrack: {
+ position: 'absolute',
+ left: 0,
+ right: 0
+ },
+ touchArea: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: Colors.transparent
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/index.d.ts b/node_modules/react-native-ui-lib/src/incubator/Slider/index.d.ts
new file mode 100644
index 0000000..172f9cb
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/index.d.ts
@@ -0,0 +1,139 @@
+import React, { ReactElement } from 'react';
+import { StyleProp, ViewStyle, ViewProps, AccessibilityProps } from 'react-native';
+import { ForwardRefInjectedProps } from '../../commons/new';
+import { ComponentStatics } from '../../typings/common';
+export interface SliderProps extends AccessibilityProps {
+ /**
+ * Initial value
+ */
+ value?: number;
+ /**
+ * Track minimum value
+ */
+ minimumValue?: number;
+ /**
+ * Track maximum value
+ */
+ maximumValue?: number;
+ /**
+ * Initial minimum value (when useRange is true)
+ */
+ initialMinimumValue?: number;
+ /**
+ * Initial maximum value (when useRange is true)
+ */
+ initialMaximumValue?: number;
+ /**
+ * Step value of the slider. The value should be between 0 and (maximumValue - minimumValue)
+ */
+ step?: number;
+ /**
+ * Callback for onValueChange
+ */
+ onValueChange?: (value: number) => void;
+ /**
+ * Callback that notifies about slider seeking is started
+ */
+ onSeekStart?: () => void;
+ /**
+ * Callback that notifies about slider seeking is finished
+ */
+ onSeekEnd?: () => void;
+ /**
+ * Callback that notifies when the reset function was invoked
+ */
+ onReset?: () => void;
+ /**
+ * The container style
+ */
+ containerStyle?: StyleProp;
+ /**
+ * The color used for the track from minimum value to current value
+ */
+ minimumTrackTintColor?: string;
+ /**
+ * The track color
+ */
+ maximumTrackTintColor?: string;
+ /**
+ * The track style
+ */
+ trackStyle?: StyleProp;
+ /**
+ * Custom render instead of rendering the track
+ */
+ renderTrack?: () => ReactElement | ReactElement[];
+ /**
+ * The thumb style
+ */
+ thumbStyle?: ViewStyle;
+ /**
+ * The active (during press) thumb style
+ */
+ activeThumbStyle?: ViewStyle;
+ /**
+ * If true the Slider will not change it's style on press
+ */
+ disableActiveStyling?: boolean;
+ /**
+ * Defines how far a touch event can start away from the thumb
+ */
+ thumbHitSlop?: ViewProps['hitSlop'];
+ /**
+ * Whether the thumb will have a shadow
+ */
+ enableThumbShadow?: boolean;
+ /**
+ * Thumb color
+ */
+ thumbTintColor?: string;
+ /**
+ * Disabled thumb tint color
+ */
+ disabledThumbTintColor?: string;
+ /**
+ * If true the Slider will be disabled and will appear in disabled color
+ */
+ disabled?: boolean;
+ /**
+ * If true the Slider will display a second thumb for the min value
+ */
+ useRange?: boolean;
+ /**
+ * If true the min and max thumbs will not overlap
+ */
+ useGap?: boolean;
+ /**
+ * Callback for onRangeChange. Returns values object with the min and max values
+ */
+ onRangeChange?: (values: {
+ min: number;
+ max: number;
+ }) => void;
+ /**
+ * If true the Slider will stay in LTR mode even if the app is on RTL mode
+ */
+ disableRTL?: boolean;
+ /**
+ * If true the component will have accessibility features enabled
+ */
+ accessible?: boolean;
+ /**
+ * The slider's test identifier
+ */
+ testID?: string;
+ /**
+ * Whether to use the new Slider implementation using Reanimated
+ */
+ migrate?: boolean;
+ /**
+ * Control the throttle time of the onValueChange and onRangeChange callbacks
+ */
+ throttleTime?: number;
+}
+type Props = SliderProps & ForwardRefInjectedProps;
+export interface SliderRef {
+ reset: () => void;
+}
+declare const _default: React.ForwardRefExoticComponent> & ComponentStatics React.JSX.Element>>;
+export default _default;
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/index.js b/node_modules/react-native-ui-lib/src/incubator/Slider/index.js
new file mode 100644
index 0000000..f46af2c
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/index.js
@@ -0,0 +1,269 @@
+import _throttle from "lodash/throttle";
+import React, { useImperativeHandle, useCallback, useMemo, useEffect, useRef } from 'react';
+import { StyleSheet } from 'react-native';
+import { useSharedValue, useAnimatedStyle, runOnJS, useAnimatedReaction, withTiming } from 'react-native-reanimated';
+import { GestureHandlerRootView } from 'react-native-gesture-handler';
+import { forwardRef, Constants } from "../../commons/new";
+import { extractAccessibilityProps } from "../../commons/modifiers";
+import { Colors, Spacings } from "../../style";
+import { StyleUtils } from "../../utils";
+import { useThemeProps, useDidUpdate } from "../../hooks";
+import { validateValues, getOffsetForValue, getValueForOffset, getStepInterpolated } from "./SliderPresenter";
+import Thumb from "./Thumb";
+import Track from "./Track";
+var ThumbType = /*#__PURE__*/function (ThumbType) {
+ ThumbType["DEFAULT"] = "default";
+ ThumbType["RANGE"] = "range";
+ return ThumbType;
+}(ThumbType || {});
+const TRACK_HEIGHT = 6;
+const THUMB_SIZE = 24;
+const THUMB_BORDER_WIDTH = 6;
+const SHADOW_RADIUS = 4;
+const GAP = Spacings.s2;
+const Slider = React.memo(props => {
+ const themeProps = useThemeProps(props, 'Incubator.Slider');
+ const {
+ forwardedRef,
+ useRange,
+ onValueChange,
+ onRangeChange,
+ onReset,
+ minimumValue = 0,
+ maximumValue = 1,
+ value = minimumValue,
+ initialMinimumValue = minimumValue,
+ initialMaximumValue = maximumValue,
+ step = 0,
+ onSeekStart,
+ onSeekEnd,
+ disableRTL,
+ containerStyle,
+ trackStyle,
+ minimumTrackTintColor,
+ maximumTrackTintColor,
+ renderTrack,
+ thumbStyle,
+ activeThumbStyle,
+ thumbTintColor = Colors.$backgroundPrimaryHeavy,
+ disabledThumbTintColor = Colors.$backgroundDisabled,
+ thumbHitSlop,
+ disableActiveStyling,
+ disabled,
+ useGap = true,
+ accessible = true,
+ testID,
+ enableThumbShadow = true,
+ throttleTime = 200
+ } = themeProps;
+ const accessibilityProps = useMemo(() => {
+ if (accessible) {
+ return {
+ accessibilityLabel: 'Slider',
+ accessible: true,
+ accessibilityRole: 'adjustable',
+ accessibilityState: disabled ? {
+ disabled
+ } : undefined,
+ accessibilityActions: [{
+ name: 'increment',
+ label: 'increment'
+ }, {
+ name: 'decrement',
+ label: 'decrement'
+ }],
+ ...extractAccessibilityProps(props)
+ };
+ }
+ }, [accessible, disabled, props]);
+ const rangeGap = useRange && useGap ? GAP + THUMB_SIZE : 0;
+ const rtlFix = Constants.isRTL ? -1 : 1;
+ const shouldDisableRTL = Constants.isRTL && disableRTL;
+ const shouldBounceToStep = step > 0;
+ const stepXValue = useSharedValue(step);
+ const stepInterpolatedValue = useSharedValue(0);
+ const trackSize = useSharedValue({
+ width: 0,
+ height: TRACK_HEIGHT
+ });
+ const start = useSharedValue(0);
+ const end = useSharedValue(0);
+ const defaultThumbOffset = useSharedValue(0);
+ const rangeThumbOffset = useSharedValue(0);
+ const didValueUpdate = useRef(false);
+ const thumbBackground = useMemo(() => [{
+ backgroundColor: disabled ? disabledThumbTintColor : thumbTintColor
+ }], [disabled, thumbTintColor, disabledThumbTintColor]);
+ const defaultThumbStyle = useMemo(() => [styles.thumb, thumbBackground], [thumbBackground]);
+ const customThumbStyle = useMemo(() => [thumbStyle, thumbBackground], [thumbStyle, thumbBackground]);
+ const _thumbStyle = useSharedValue(StyleUtils.unpackStyle(thumbStyle ? customThumbStyle : defaultThumbStyle, {
+ flatten: true
+ }));
+ const _activeThumbStyle = useSharedValue(StyleUtils.unpackStyle(activeThumbStyle, {
+ flatten: true
+ }));
+ const setInitialPositions = useCallback(trackWidth => {
+ validateValues(props);
+ const defaultThumbPosition = getOffsetForValue(useRange ? initialMinimumValue : value, trackWidth, minimumValue, maximumValue);
+ const rangeThumbPosition = getOffsetForValue(initialMaximumValue, trackWidth, minimumValue, maximumValue);
+ defaultThumbOffset.value = defaultThumbPosition;
+ rangeThumbOffset.value = useRange ? rangeThumbPosition : trackWidth;
+ }, [value]);
+ const reset = () => {
+ setInitialPositions(trackSize.value.width);
+ onReset?.();
+ };
+ useImperativeHandle(forwardedRef, () => ({
+ reset: () => reset()
+ }));
+ useDidUpdate(() => {
+ didValueUpdate.current = true;
+ setInitialPositions(trackSize.value.width);
+ }, [value, setInitialPositions]);
+ useEffect(() => {
+ _thumbStyle.value = StyleUtils.unpackStyle(thumbStyle ? customThumbStyle : defaultThumbStyle, {
+ flatten: true
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [defaultThumbStyle, customThumbStyle, thumbStyle]);
+ const onValueChangeThrottled = useCallback(_throttle(value => {
+ if (!didValueUpdate.current) {
+ // NOTE: don't invoke onValueChange when slider's value prop updated programmatically
+ onValueChange?.(value);
+ } else {
+ didValueUpdate.current = false;
+ }
+ }, throttleTime), [onValueChange]);
+ const onRangeChangeThrottled = useCallback(_throttle((min, max) => {
+ onRangeChange?.({
+ min,
+ max
+ });
+ }, throttleTime), [onRangeChange]);
+ useAnimatedReaction(() => {
+ return Math.round(defaultThumbOffset.value);
+ }, (offset, prevOffset) => {
+ if (offset !== prevOffset) {
+ const value = getValueForOffset(offset, trackSize.value.width, minimumValue, maximumValue, stepXValue.value);
+ if (useRange) {
+ const maxValue = getValueForOffset(rangeThumbOffset.value, trackSize.value.width, minimumValue, maximumValue, stepXValue.value);
+ runOnJS(onRangeChangeThrottled)(value, maxValue);
+ } else if (prevOffset) {
+ // don't invoke onChange when setting the slider
+ runOnJS(onValueChangeThrottled)(value);
+ }
+ }
+ });
+ useAnimatedReaction(() => {
+ return Math.round(rangeThumbOffset.value);
+ }, (offset, _prevOffset) => {
+ const maxValue = getValueForOffset(offset, trackSize.value.width, minimumValue, maximumValue, stepXValue.value);
+ const minValue = getValueForOffset(Math.round(defaultThumbOffset.value), trackSize.value.width, minimumValue, maximumValue, stepXValue.value);
+ runOnJS(onRangeChangeThrottled)(minValue, maxValue);
+ });
+
+ /** events */
+
+ const onTrackLayout = useCallback(event => {
+ const width = event.nativeEvent.layout.width;
+ const height = event.nativeEvent.layout.height;
+ trackSize.value = {
+ width,
+ height
+ };
+ end.value = width;
+ stepInterpolatedValue.value = Math.abs(getStepInterpolated(width, minimumValue, maximumValue, stepXValue));
+ setInitialPositions(width);
+ }, [minimumValue, maximumValue, value, setInitialPositions]);
+ const onTrackPress = useCallback(event => {
+ if (disabled) {
+ return;
+ }
+ let locationX = Math.min(event.nativeEvent.locationX, trackSize.value.width);
+ if (Constants.isRTL) {
+ locationX = trackSize.value.width - locationX;
+ }
+ if (shouldBounceToStep) {
+ locationX = Math.round(locationX / stepInterpolatedValue.value) * stepInterpolatedValue.value;
+ }
+ if (!useRange) {
+ defaultThumbOffset.value = locationX;
+ } else {
+ const distanceFromDefaultThumb = Math.abs(defaultThumbOffset.value - locationX);
+ const distanceFromRangeThumb = Math.abs(rangeThumbOffset.value - locationX);
+ const thumbsDistance = Math.abs(defaultThumbOffset.value - rangeThumbOffset.value);
+ if (thumbsDistance > rangeGap) {
+ if (distanceFromDefaultThumb < distanceFromRangeThumb) {
+ defaultThumbOffset.value = locationX;
+ } else {
+ rangeThumbOffset.value = locationX;
+ }
+ }
+ }
+ }, [disabled, useRange, rangeGap, shouldBounceToStep]);
+ const _onSeekStart = () => {
+ 'worklet';
+
+ if (onSeekStart) {
+ runOnJS(onSeekStart)();
+ }
+ };
+ const _onSeekEnd = () => {
+ 'worklet';
+
+ if (onSeekEnd) {
+ runOnJS(onSeekEnd)();
+ }
+ };
+ const trackAnimatedStyles = useAnimatedStyle(() => {
+ if (useRange) {
+ return {
+ transform: [{
+ translateX: withTiming(defaultThumbOffset.value * rtlFix, {
+ duration: 10
+ })
+ }],
+ width: withTiming(Math.abs(rangeThumbOffset.value - defaultThumbOffset.value), {
+ duration: 10
+ })
+ };
+ } else {
+ return {
+ width: defaultThumbOffset.value
+ };
+ }
+ });
+
+ /** renders */
+ const renderThumb = type => {
+ return ;
+ };
+ const _renderTrack = () => {
+ return ;
+ };
+ return
+ {_renderTrack()}
+ {renderThumb(ThumbType.DEFAULT)}
+ {useRange && renderThumb(ThumbType.RANGE)}
+ ;
+});
+Slider.displayName = 'Incubator.Slider';
+export default forwardRef(Slider);
+const styles = StyleSheet.create({
+ container: {
+ height: THUMB_SIZE + SHADOW_RADIUS,
+ justifyContent: 'center'
+ },
+ disableRTL: {
+ transform: [{
+ scaleX: -1
+ }]
+ },
+ thumb: {
+ width: THUMB_SIZE,
+ height: THUMB_SIZE,
+ borderRadius: THUMB_SIZE / 2,
+ borderWidth: THUMB_BORDER_WIDTH,
+ borderColor: Colors.$backgroundElevatedLight
+ }
+});
\ No newline at end of file
diff --git a/node_modules/react-native-ui-lib/src/incubator/Slider/slider.api.json b/node_modules/react-native-ui-lib/src/incubator/Slider/slider.api.json
new file mode 100644
index 0000000..b15080a
--- /dev/null
+++ b/node_modules/react-native-ui-lib/src/incubator/Slider/slider.api.json
@@ -0,0 +1,109 @@
+{
+ "name": "Slider",
+ "category": "incubator",
+ "description": "A Slider component",
+ "example": "https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/incubatorScreens/IncubatorSliderScreen.tsx",
+ "images": [],
+ "props": [
+ {"name": "value", "type": "number", "description": "Initial value"},
+ {"name": "minimumValue", "type": "number", "description": "Track minimum value"},
+ {"name": "maximumValue", "type": "number", "description": "Track maximum value"},
+ {"name": "initialMinimumValue", "type": "number", "description": "Initial minimum value", "note": "Only when `useRange` is true"},
+ {"name": "initialMaximumValue", "type": "number", "description": "Initial maximum value", "note": "Only when `useRange` is true"},
+ {
+ "name": "step",
+ "type": "number",
+ "description": "Step value of the slider. The value should be between 0 and (maximumValue - minimumValue)"
+ },
+ {
+ "name": "useRange",
+ "type": "boolean",
+ "description": "If true the Slider will display a second thumb for the min value"
+ },
+ {
+ "name": "useGap",
+ "type": "boolean",
+ "description": "If true the min and max thumbs will not overlap",
+ "default": "true"
+ },
+ {"name": "onValueChange", "type": "SliderOnValueChange", "description": "Callback for onValueChange"},
+ {
+ "name": "onRangeChange",
+ "type": "SliderOnRangeChange",
+ "description": "Callback for onRangeChange. Returns values object with the min and max values"
+ },
+ {
+ "name": "onSeekStart",
+ "type": "() => void",
+ "description": "Callback that notifies about slider seeking is started"
+ },
+ {
+ "name": "onSeekEnd",
+ "type": "() => void",
+ "description": "Callback that notifies about slider seeking is finished"
+ },
+ {
+ "name": "onReset",
+ "type": "() => void",
+ "description": "Callback that notifies when the reset function was invoked"
+ },
+ {"name": "containerStyle", "type": "ViewStyle", "description": "The container style"},
+ {
+ "name": "minimumTrackTintColor",
+ "type": "string",
+ "description": "The color used for the track from minimum value to current value"
+ },
+ {"name": "maximumTrackTintColor", "type": "string", "description": "The track color"},
+ {"name": "trackStyle", "type": "ViewStyle", "description": "The track style"},
+ {
+ "name": "renderTrack",
+ "type": "() => ReactElement | ReactElement[]",
+ "description": "Custom render instead of rendering the track"
+ },
+ {"name": "thumbTintColor", "type": "string", "description": "Thumb color"},
+ {"name": "disabledThumbTintColor", "type": "string", "description": "Disabled thumb color"},
+ {"name": "thumbStyle", "type": "ViewStyle", "description": "The thumb style"},
+ {"name": "activeThumbStyle", "type": "ViewStyle", "description": "The active (during press) thumb style"},
+ {
+ "name": "enableThumbShadow",
+ "type": "boolean",
+ "description": "Whether the thumb will have a shadow (with 'migrate' true only)",
+ "default": "true"
+ },
+ {"name": "thumbHitSlop", "type": "number", "description": "Defines how far a touch event can start away from the thumb"},
+ {
+ "name": "disableActiveStyling",
+ "type": "boolean",
+ "description": "If true the Slider will not change it's style on press"
+ },
+ {
+ "name": "disabled",
+ "type": "boolean",
+ "description": "If true the Slider will be disabled and will appear in disabled color"
+ },
+ {
+ "name": "disableRTL",
+ "type": "boolean",
+ "description": "If true the Slider will stay in LTR mode even if the app is on RTL mode"
+ },
+ {
+ "name": "accessible",
+ "type": "boolean",
+ "description": "If true the component will have accessibility features enabled"
+ },
+ {
+ "name": "throttleTime",
+ "type": "number",
+ "description": "Control the throttle time of the onValueChange and onRangeChange callbacks"
+ },
+ {"name": "testID", "type": "string", "description": "The component test id"}
+ ],
+ "snippet": [
+ " console.log(\\`value changed: \\${value}\\`)$4}",
+ "/>"
+ ]
+}