manuo
Version:
UI component library for React Native + NativeWind, mobile-first and platform-specific.
1,405 lines (1,361 loc) • 111 kB
JavaScript
// src/nativeWindInterop.ts
import { Text } from "react-native";
import { cssInterop } from "nativewind";
cssInterop(Text, { className: "style" });
// src/components/Button.tsx
import { Platform } from "react-native";
// src/components/ios/ButtonIOS.tsx
import {
Text as RNText,
View as RNView,
ActivityIndicator,
Pressable
} from "react-native";
import { cssInterop as cssInterop2 } from "nativewind";
import { jsx, jsxs } from "react/jsx-runtime";
var Text2 = cssInterop2(RNText, { className: "style" });
var View = cssInterop2(RNView, { className: "style" });
var ButtonIOS = ({
title,
icon,
onPress,
className,
textClassName,
variant = "primary",
loading = false,
loaderColor,
...rest
}) => {
const baseContainer = "px-4 py-2 min-w-[44px] min-h-[44px] rounded-xl flex-row items-center justify-center gap-2 active:opacity-70 transition";
const variants = {
primary: "bg-blue-500",
secondary: "bg-white border border-blue-500",
tonal: "bg-blue-100",
plain: "bg-transparent"
};
const textStyles = {
primary: "text-white text-xl font-semibold",
// ⬅️ mai mare, bold
secondary: "text-blue-500 text-xl font-medium",
// ⬅️ mai mic, ca în poză
tonal: "text-blue-700 text-base font-semibold",
// ⬅️ ca primary, dar cu altă culoare
plain: "text-blue-500 text-base font-medium"
// ⬅️ subtil
};
const defaultLoaderColor = loaderColor ?? (variant === "primary" ? "#ffffff" : "#007AFF");
return /* @__PURE__ */ jsx(
Pressable,
{
onPress,
disabled: loading,
accessibilityRole: "button",
accessibilityLabel: title,
...rest,
children: /* @__PURE__ */ jsxs(View, { className: `${baseContainer} ${variants[variant]} ${className ?? ""}`, children: [
loading ? /* @__PURE__ */ jsx(ActivityIndicator, { size: "small", color: defaultLoaderColor }) : icon,
!!title && /* @__PURE__ */ jsx(
Text2,
{
className: `${textStyles[variant]} ${textClassName ?? ""}`,
children: title
}
)
] })
}
);
};
// src/components/android/ButtonAndroid.tsx
import {
Text as RNText2,
View as RNView2,
ActivityIndicator as ActivityIndicator2,
TouchableNativeFeedback
} from "react-native";
import { cssInterop as cssInterop3 } from "nativewind";
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var Text3 = cssInterop3(RNText2, { className: "style" });
var View2 = cssInterop3(RNView2, { className: "style" });
var ButtonAndroid = ({
title,
icon,
onPress,
className,
textClassName,
variant = "primary",
loading = false,
loaderColor
}) => {
const baseContainer = "px-4 py-2 min-w-[48px] min-h-[48px] rounded-full flex-row items-center justify-center gap-2 overflow-hidden";
const variants = {
primary: "bg-blue-500",
secondary: "bg-white border border-gray-400",
tonal: "bg-blue-100",
plain: "bg-transparent"
};
const textStyles = {
primary: "text-white text-lg font-semibold uppercase",
secondary: "text-black text-lg font-medium uppercase",
tonal: "text-blue-800 text-base font-semibold uppercase",
plain: "text-black text-base font-medium uppercase"
};
const defaultLoaderColor = loaderColor ?? (variant === "primary" ? "#fff" : "#2196F3");
return /* @__PURE__ */ jsx2(
TouchableNativeFeedback,
{
onPress,
disabled: loading,
background: TouchableNativeFeedback.Ripple("#B0BEC5", false),
children: /* @__PURE__ */ jsxs2(View2, { className: `${baseContainer} ${variants[variant]} ${className ?? ""}`, children: [
loading ? /* @__PURE__ */ jsx2(ActivityIndicator2, { size: "small", color: defaultLoaderColor }) : icon,
!!title && /* @__PURE__ */ jsx2(Text3, { className: `${textStyles[variant]} ${textClassName ?? ""}`, children: title })
] })
}
);
};
// src/components/Button.tsx
import { jsx as jsx3 } from "react/jsx-runtime";
var Button = (props) => {
const isIOS2 = Platform.OS === "ios" || Platform.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx3(ButtonIOS, { ...props }) : /* @__PURE__ */ jsx3(ButtonAndroid, { ...props });
};
// src/components/TextDemo.tsx
import { Text as RNText3 } from "react-native";
import { cssInterop as cssInterop4 } from "nativewind";
import { jsx as jsx4 } from "react/jsx-runtime";
var Text4 = cssInterop4(RNText3, { className: "style" });
var TextDemo = ({ children, className, ...props }) => {
return /* @__PURE__ */ jsx4(Text4, { className: `text-base ${className ?? ""}`, ...props, children });
};
// src/utils/cn.ts
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
// src/components/Card.tsx
import { Platform as Platform2 } from "react-native";
// src/components/ios/CardIOS.tsx
import {
View as RNView3,
Text as RNText4,
Image as RNImage,
Pressable as RNPressable
} from "react-native";
import { cssInterop as cssInterop5 } from "nativewind";
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var View3 = cssInterop5(RNView3, { className: "style" });
var Text5 = cssInterop5(RNText4, { className: "style" });
var Image = cssInterop5(RNImage, { className: "style" });
var Pressable2 = cssInterop5(RNPressable, { className: "style" });
var CardIOS = ({
image,
badge,
title,
subtitle,
description,
buttonLabel = "GET",
icon,
onPress,
className,
style,
bodyClassName = "p-4",
bodyStyle,
imageContainerClassName,
imageClassName,
imageStyle,
imageAspectRatio,
imageResizeMode = "cover"
}) => {
return /* @__PURE__ */ jsxs3(
Pressable2,
{
onPress,
className: `rounded-2xl bg-white shadow-md overflow-hidden ${className ?? ""}`,
style,
children: [
!!image && /* @__PURE__ */ jsx5(View3, { className: imageContainerClassName, children: /* @__PURE__ */ jsx5(
Image,
{
source: { uri: image },
className: imageClassName ?? "w-full h-48",
style: imageAspectRatio ? [{ aspectRatio: imageAspectRatio }, imageStyle] : imageStyle,
resizeMode: imageResizeMode
}
) }),
/* @__PURE__ */ jsxs3(View3, { className: bodyClassName, style: bodyStyle, children: [
!!badge && /* @__PURE__ */ jsx5(Text5, { className: "mb-2 self-start rounded-full bg-gray-100 px-2 py-0.5 text-xs font-semibold uppercase text-gray-500", children: badge }),
/* @__PURE__ */ jsx5(Text5, { className: "text-3xl font-bold text-black", children: title }),
!!subtitle && /* @__PURE__ */ jsx5(Text5, { className: "text-sm text-gray-500", children: subtitle }),
!!description && /* @__PURE__ */ jsx5(Text5, { className: "mt-1 text-sm text-gray-600", children: description }),
/* @__PURE__ */ jsxs3(View3, { className: "mt-4 flex-row items-center justify-between", children: [
/* @__PURE__ */ jsxs3(View3, { className: "flex-row items-center", children: [
icon,
!!subtitle && /* @__PURE__ */ jsxs3(View3, { className: "ml-2", children: [
/* @__PURE__ */ jsx5(Text5, { className: "text-sm font-medium text-black", children: subtitle }),
!!description && /* @__PURE__ */ jsx5(Text5, { className: "text-xs text-gray-400", children: description })
] })
] }),
/* @__PURE__ */ jsx5(View3, { className: "rounded-full bg-blue-500 px-4 py-1.5", children: /* @__PURE__ */ jsx5(Text5, { className: "text-sm font-bold text-white", children: buttonLabel }) })
] })
] })
]
}
);
};
// src/components/android/CardAndroid.tsx
import {
View as RNView4,
Text as RNText5,
Image as RNImage2,
TouchableNativeFeedback as TouchableNativeFeedback2
} from "react-native";
import { cssInterop as cssInterop6 } from "nativewind";
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
var View4 = cssInterop6(RNView4, { className: "style" });
var Text6 = cssInterop6(RNText5, { className: "style" });
var Image2 = cssInterop6(RNImage2, { className: "style" });
var CardAndroid = ({
image,
title,
subtitle,
description,
buttonLabel = "Install",
onPress,
className,
icon
}) => {
return /* @__PURE__ */ jsx6(
TouchableNativeFeedback2,
{
onPress,
background: TouchableNativeFeedback2.Ripple("#E0E0E0", false),
children: /* @__PURE__ */ jsxs4(View4, { className: `bg-white rounded-xl shadow-sm p-4 ${className ?? ""}`, children: [
image && /* @__PURE__ */ jsx6(
Image2,
{
source: { uri: image },
className: "mb-4 h-40 w-full rounded-lg",
resizeMode: "cover"
}
),
/* @__PURE__ */ jsx6(Text6, { className: "text-3xl font-bold text-black", children: title }),
!!subtitle && /* @__PURE__ */ jsx6(Text6, { className: "mt-0.5 text-xs uppercase text-gray-500 tracking-wider", children: subtitle }),
!!description && /* @__PURE__ */ jsx6(Text6, { className: "mt-1 text-sm text-gray-600 leading-tight", children: description }),
/* @__PURE__ */ jsxs4(View4, { className: "mt-4 flex-row items-center justify-between", children: [
/* @__PURE__ */ jsxs4(View4, { className: "flex-row items-center gap-2", children: [
icon,
!!subtitle && /* @__PURE__ */ jsx6(Text6, { className: "text-xs text-gray-500", children: subtitle })
] }),
/* @__PURE__ */ jsx6(View4, { className: "rounded-full bg-gray-100 px-4 py-1", children: /* @__PURE__ */ jsx6(Text6, { className: "text-sm font-semibold text-blue-600", children: buttonLabel }) })
] })
] })
}
);
};
// src/components/Card.tsx
import { jsx as jsx7 } from "react/jsx-runtime";
var Card = (props) => {
const isIOS2 = Platform2.OS === "ios" || Platform2.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx7(CardIOS, { ...props }) : /* @__PURE__ */ jsx7(CardAndroid, { ...props });
};
// src/components/ListItem.tsx
import {
SectionList,
Platform as Platform3,
Text as Text9
} from "react-native";
// src/components/ios/ListItemIOS.tsx
import {
Text as RNText6,
View as RNView5,
Pressable as Pressable3,
Image as RNImage3
} from "react-native";
import { cssInterop as cssInterop7 } from "nativewind";
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
var View5 = cssInterop7(RNView5, { className: "style" });
var Text7 = cssInterop7(RNText6, { className: "style" });
var Image3 = cssInterop7(RNImage3, { className: "style" });
var ListItemIOS = ({
title,
subtitle,
rightText = "100+",
icon,
className,
onPress
}) => {
return /* @__PURE__ */ jsx8(Pressable3, { onPress, children: /* @__PURE__ */ jsxs5(View5, { className: `flex-row items-center justify-between bg-white px-4 py-3 ${className ?? ""}`, children: [
/* @__PURE__ */ jsxs5(View5, { className: "flex-row items-center gap-3", children: [
icon ?? /* @__PURE__ */ jsx8(View5, { className: "h-10 w-10 rounded-xl bg-blue-500" }),
/* @__PURE__ */ jsxs5(View5, { children: [
/* @__PURE__ */ jsx8(Text7, { className: "text-base font-semibold text-black", children: title }),
/* @__PURE__ */ jsx8(Text7, { className: "text-sm text-gray-500", children: subtitle })
] })
] }),
/* @__PURE__ */ jsx8(Text7, { className: "text-xs text-gray-500", children: rightText })
] }) });
};
// src/components/android/ListItemAndroid.tsx
import {
Text as RNText7,
View as RNView6,
TouchableNativeFeedback as TouchableNativeFeedback3
} from "react-native";
import { cssInterop as cssInterop8 } from "nativewind";
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
var View6 = cssInterop8(RNView6, { className: "style" });
var Text8 = cssInterop8(RNText7, { className: "style" });
var ListItemAndroid = ({
title,
subtitle,
rightText = "100+",
icon,
className,
onPress
}) => {
return /* @__PURE__ */ jsx9(TouchableNativeFeedback3, { onPress, background: TouchableNativeFeedback3.Ripple("#E0E0E0", false), children: /* @__PURE__ */ jsxs6(View6, { className: `flex-row items-center justify-between bg-white px-4 py-3 border-b border-gray-100 ${className ?? ""}`, children: [
/* @__PURE__ */ jsxs6(View6, { className: "flex-row items-center gap-3", children: [
icon ?? /* @__PURE__ */ jsx9(View6, { className: "h-10 w-10 rounded-md bg-blue-500" }),
/* @__PURE__ */ jsxs6(View6, { children: [
/* @__PURE__ */ jsx9(Text8, { className: "text-sm font-semibold text-black", children: title }),
/* @__PURE__ */ jsx9(Text8, { className: "text-xs text-gray-500", children: subtitle })
] })
] }),
/* @__PURE__ */ jsx9(Text8, { className: "text-xs text-gray-500", children: rightText })
] }) });
};
// src/components/ListItem.tsx
import { jsx as jsx10 } from "react/jsx-runtime";
var ListSection = ({
sections,
renderItem,
sectionHeaderClassName
}) => {
const renderDefaultItem = ({ item }) => Platform3.OS === "ios" ? /* @__PURE__ */ jsx10(ListItemIOS, { ...item }) : /* @__PURE__ */ jsx10(ListItemAndroid, { ...item });
return /* @__PURE__ */ jsx10(
SectionList,
{
sections,
keyExtractor: (item, index) => `${item.title}-${index}`,
renderItem: renderItem ?? renderDefaultItem,
renderSectionHeader: ({ section }) => /* @__PURE__ */ jsx10(
Text9,
{
className: `text-xs uppercase font-bold text-gray-400 px-4 py-2 ${sectionHeaderClassName ?? ""}`,
children: section.title
}
),
stickySectionHeadersEnabled: true,
contentContainerStyle: { paddingBottom: 24 }
}
);
};
// src/components/ProgressIndicator.tsx
import { useEffect, useRef } from "react";
import { Animated, View as RNView7, Text as RNText8 } from "react-native";
import { cssInterop as cssInterop9 } from "nativewind";
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
var View8 = cssInterop9(RNView7, { className: "style" });
var Text10 = cssInterop9(RNText8, { className: "style" });
var AnimatedView = cssInterop9(Animated.View, { className: "style" });
var ProgressBar = ({
progress,
label = "Progress Indicator",
className = "",
barClassName = "",
trackClassName = "",
thickness = 5
}) => {
const animatedWidth = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(animatedWidth, {
toValue: progress,
duration: 300,
useNativeDriver: false
}).start();
}, [progress]);
const widthInterpolation = animatedWidth.interpolate({
inputRange: [0, 1],
outputRange: ["0%", "100%"]
});
return /* @__PURE__ */ jsxs7(View8, { className: `w-full ${className}`, children: [
!!label && /* @__PURE__ */ jsx11(Text10, { className: "mb-2 text-center text-xs font-medium text-gray-600", children: label }),
/* @__PURE__ */ jsx11(
View8,
{
style: { height: thickness },
className: `w-full overflow-hidden rounded-full bg-gray-200 ${trackClassName}`,
children: /* @__PURE__ */ jsx11(
AnimatedView,
{
style: { width: widthInterpolation, height: thickness },
className: `rounded-full bg-blue-500 ${barClassName}`
}
)
}
)
] });
};
// src/components/SegmentControl.tsx
import { Platform as Platform4 } from "react-native";
// src/components/ios/SegmentedControlIOS.tsx
import { useEffect as useEffect2, useRef as useRef2, useState } from "react";
import {
Animated as Animated2,
Pressable as Pressable4,
View as RNView8,
Text as RNText9
} from "react-native";
import { cssInterop as cssInterop10 } from "nativewind";
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
var View9 = cssInterop10(RNView8, { className: "style" });
var Text11 = cssInterop10(RNText9, { className: "style" });
var AnimatedView2 = cssInterop10(Animated2.View, { className: "style" });
var SegmentedControlIOS = ({
options,
selectedIndex = 0,
onChange
}) => {
const [containerWidth, setContainerWidth] = useState(0);
const [itemWidth, setItemWidth] = useState(0);
const translateX = useRef2(new Animated2.Value(selectedIndex)).current;
const [currentIndex, setCurrentIndex] = useState(selectedIndex);
useEffect2(() => {
if (itemWidth === 0) return;
animateTo(selectedIndex);
setCurrentIndex(selectedIndex);
}, [selectedIndex, itemWidth]);
const animateTo = (toIndex) => {
Animated2.timing(translateX, {
toValue: toIndex,
duration: 400,
useNativeDriver: false
}).start();
};
const onLayout = (e) => {
const width = e.nativeEvent.layout.width;
const totalGap = 4;
const adjustedItemWidth = (width - totalGap) / options.length;
setContainerWidth(width);
setItemWidth(adjustedItemWidth);
};
const interpolatedX = translateX.interpolate({
inputRange: options.map((_, i) => i),
outputRange: options.map((_, i) => 2 + i * itemWidth),
extrapolate: "clamp"
});
return /* @__PURE__ */ jsxs8(
View9,
{
onLayout,
className: "flex-row overflow-hidden rounded-[9px] bg-[#f0f0f5] p-[2px]",
children: [
itemWidth > 0 && /* @__PURE__ */ jsx12(
AnimatedView2,
{
style: {
width: itemWidth,
transform: [{ translateX: interpolatedX }]
},
className: "absolute bottom-[2px] left-0 top-[2px] z-0 rounded-[7px] bg-white shadow-sm"
}
),
options.map((label, index) => {
const isActive = index === currentIndex;
const isBeforeActive = index === currentIndex + 1;
const showDivider = index > 0 && !isActive && !isBeforeActive;
return /* @__PURE__ */ jsxs8(
Pressable4,
{
onPress: () => onChange?.(index),
className: "relative z-10 flex-1 items-center justify-center px-3 py-[7px]",
children: [
showDivider && /* @__PURE__ */ jsx12(View9, { className: "absolute bottom-[7px] left-0 top-[7px] w-[1px] bg-gray-300" }),
/* @__PURE__ */ jsx12(
Text11,
{
className: `text-base font-semibold ${isActive ? "text-black" : "text-gray-500"}`,
children: label
}
)
]
},
index
);
})
]
}
);
};
// src/components/android/SegmentedControlAndroid.tsx
import { Pressable as Pressable5, View as View10, Text as Text12 } from "react-native";
import { jsx as jsx13 } from "react/jsx-runtime";
var SegmentedControlAndroid = ({
options,
selectedIndex = 0,
onChange
}) => {
return /* @__PURE__ */ jsx13(
View10,
{
style: {
flexDirection: "row",
borderWidth: 1,
borderColor: "#D1D5DB",
borderRadius: 24,
overflow: "hidden"
},
children: options.map((option, index) => {
const isFirst = index === 0;
const isLast = index === options.length - 1;
const isSelected = selectedIndex === index;
return /* @__PURE__ */ jsx13(
Pressable5,
{
onPress: () => onChange?.(index),
style: {
flex: 1,
backgroundColor: isSelected ? "#E0F2FE" : "#fff",
paddingVertical: 10,
alignItems: "center",
borderRightWidth: index < options.length - 1 ? 1 : 0,
borderRightColor: "#D1D5DB",
borderTopLeftRadius: isFirst ? 999 : 0,
borderBottomLeftRadius: isFirst ? 999 : 0,
borderTopRightRadius: isLast ? 999 : 0,
borderBottomRightRadius: isLast ? 999 : 0
},
children: /* @__PURE__ */ jsx13(
Text12,
{
style: {
fontSize: 14,
fontWeight: isSelected ? "600" : "400",
color: "#111827"
},
children: option
}
)
},
index
);
})
}
);
};
// src/components/web/SegmentControlWeb.tsx
import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
import {
Animated as Animated3,
Pressable as RNPressable2,
View as RNView9,
Text as RNText10
} from "react-native";
import { cssInterop as cssInterop11 } from "nativewind";
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
var View11 = cssInterop11(RNView9, { className: "style" });
var Text13 = cssInterop11(RNText10, { className: "style" });
var Pressable6 = cssInterop11(RNPressable2, { className: "style" });
var AnimatedView3 = cssInterop11(Animated3.View, { className: "style" });
function SegmentedControlWeb({
options,
selectedIndex = 0,
onChange
}) {
const [itemWidth, setItemWidth] = useState2(0);
const [currentIndex, setCurrentIndex] = useState2(selectedIndex);
const animIndex = useRef3(new Animated3.Value(selectedIndex)).current;
useEffect3(() => {
if (!itemWidth) return;
Animated3.timing(animIndex, {
toValue: selectedIndex,
duration: 400,
useNativeDriver: false
}).start(() => setCurrentIndex(selectedIndex));
}, [selectedIndex, itemWidth]);
const onLayout = (e) => {
const width = e.nativeEvent.layout.width;
const w = Math.floor((width - 4) / options.length);
setItemWidth(w);
};
const translateX = Animated3.add(new Animated3.Value(2), Animated3.multiply(animIndex, itemWidth));
return /* @__PURE__ */ jsxs9(
View11,
{
onLayout,
className: "flex-row items-stretch overflow-hidden rounded-[9px] bg-[#f0f0f5] p-[2px]",
style: { willChange: "transform" },
children: [
itemWidth > 0 && /* @__PURE__ */ jsx14(
AnimatedView3,
{
pointerEvents: "none",
className: "absolute bottom-[2px] left-0 top-[2px] z-0 rounded-[7px] bg-white",
style: { width: itemWidth, transform: [{ translateX }] }
}
),
options.map((label, index) => {
const isActive = index === currentIndex;
const isBeforeActive = index === currentIndex + 1;
const showDivider = index > 0 && !isActive && !isBeforeActive;
return /* @__PURE__ */ jsxs9(
Pressable6,
{
onPress: () => onChange?.(index),
className: "relative z-10 flex-1 basis-0 items-center justify-center px-3 py-[7px]",
accessibilityRole: "button",
accessibilityState: { selected: isActive },
children: [
showDivider && /* @__PURE__ */ jsx14(View11, { className: "absolute bottom-[7px] left-0 top-[7px] w-[1px] bg-gray-300 opacity-60" }),
/* @__PURE__ */ jsx14(Text13, { className: `text-base font-semibold ${isActive ? "text-black" : "text-gray-500"}`, children: label })
]
},
index
);
})
]
}
);
}
// src/components/SegmentControl.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
var SegmentedControl = (props) => {
if (Platform4.OS === "web") return /* @__PURE__ */ jsx15(SegmentedControlWeb, { ...props });
if (Platform4.OS === "ios") return /* @__PURE__ */ jsx15(SegmentedControlIOS, { ...props });
return /* @__PURE__ */ jsx15(SegmentedControlAndroid, { ...props });
};
// src/components/Text.tsx
import { Platform as Platform5 } from "react-native";
// src/components/ios/TextIOS.tsx
import { Text as RNText11 } from "react-native";
import { cssInterop as cssInterop12 } from "nativewind";
import { jsx as jsx16 } from "react/jsx-runtime";
var Text14 = cssInterop12(RNText11, { className: "style" });
var iosVariants = {
hero: "text-[34px] font-bold",
pageTitle: "text-[28px] font-semibold",
sectionTitle: "text-[22px] font-semibold",
cardTitle: "text-[20px] font-semibold",
header: "text-[17px] font-semibold",
paragraph: "text-[16px] font-normal",
hint: "text-[16px] font-normal",
label: "text-[15px] font-normal",
footnote: "text-[13px] font-normal",
caption: "text-[12px] font-normal",
captionSmall: "text-[11px] font-normal"
};
var TextIOS = ({ variant = "paragraph", className = "", ...props }) => {
return /* @__PURE__ */ jsx16(Text14, { className: `${iosVariants[variant]} ${className}`, ...props });
};
// src/components/android/TextAndroid.tsx
import { Text as RNText12 } from "react-native";
import { cssInterop as cssInterop13 } from "nativewind";
import { jsx as jsx17 } from "react/jsx-runtime";
var Text15 = cssInterop13(RNText12, { className: "style" });
var androidVariants = {
hero: "text-[34px] font-bold",
pageTitle: "text-[28px] font-bold",
sectionTitle: "text-[22px] font-semibold",
cardTitle: "text-[20px] font-semibold",
header: "text-[18px] font-medium",
paragraph: "text-[16px] font-normal",
hint: "text-[15px] font-normal",
label: "text-[14px] font-normal",
footnote: "text-[13px] font-normal",
caption: "text-[12px] font-normal",
captionSmall: "text-[11px] font-normal"
};
var TextAndroid = ({
variant = "paragraph",
className = "",
...props
}) => {
return /* @__PURE__ */ jsx17(Text15, { className: `${androidVariants[variant]} ${className}`, ...props });
};
// src/components/Text.tsx
import { jsx as jsx18 } from "react/jsx-runtime";
var Text16 = (props) => {
const isIOS2 = Platform5.OS === "ios" || Platform5.OS === "macos" || Platform5.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx18(TextIOS, { ...props }) : /* @__PURE__ */ jsx18(TextAndroid, { ...props });
};
// src/components/PlatformDrawer.tsx
import { forwardRef as forwardRef2 } from "react";
import { Platform as Platform7 } from "react-native";
// src/components/ios/SimplePlatformDrawerIOS.tsx
import { MaterialIcons } from "@expo/vector-icons";
import { forwardRef, useImperativeHandle, useRef as useRef4, useState as useState3 } from "react";
import { Animated as Animated4, Text as Text17, TouchableOpacity, View as View12 } from "react-native";
import { Fragment, jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
var renderIcon = (icon, isSelected = false) => {
const { library, name, size = 26 } = icon;
const iconColor = isSelected ? "#FFFFFF" : "#007AFF";
return /* @__PURE__ */ jsx19(MaterialIcons, { name, size, color: iconColor });
};
var PlatformDrawerIOS = forwardRef((props, ref) => {
const {
title = "",
sections = [],
onOpen,
onClose,
className = "",
drawerWidth = 320,
backgroundColor = "#F8F9FA",
activeColor = "#007AFF",
inactiveColor = "#000000",
activeBackgroundColor = "#007AFF",
enableBackdropPress = true,
animationDuration = 300,
hasNavigationBar = true
} = props;
const [isOpen, setIsOpen] = useState3(false);
const slideAnim = useRef4(new Animated4.Value(-drawerWidth)).current;
useImperativeHandle(ref, () => ({
open: () => {
setIsOpen(true);
onOpen?.();
Animated4.timing(slideAnim, {
toValue: 0,
duration: animationDuration,
useNativeDriver: true
}).start();
},
close: () => {
Animated4.timing(slideAnim, {
toValue: -drawerWidth,
duration: animationDuration,
useNativeDriver: true
}).start(() => {
setIsOpen(false);
onClose?.();
});
},
toggle: () => {
if (isOpen) {
ref?.current?.close();
} else {
ref?.current?.open();
}
}
}));
const handleBackdropPress = () => {
if (enableBackdropPress && isOpen) {
ref?.current?.close();
}
};
if (!isOpen) return null;
return /* @__PURE__ */ jsxs10(Fragment, { children: [
/* @__PURE__ */ jsx19(
TouchableOpacity,
{
style: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0, 0, 0, 0.4)",
zIndex: 999
},
activeOpacity: 1,
onPress: handleBackdropPress
}
),
/* @__PURE__ */ jsx19(
Animated4.View,
{
style: {
position: "absolute",
top: 0,
left: 0,
width: drawerWidth,
height: "100%",
backgroundColor,
transform: [{ translateX: slideAnim }],
zIndex: hasNavigationBar ? 999 : 1e3,
shadowColor: "#000",
shadowOffset: {
width: 1,
height: 0
},
shadowOpacity: 0.15,
shadowRadius: 10
},
children: /* @__PURE__ */ jsxs10(View12, { style: { flex: 1, paddingTop: 60 }, children: [
/* @__PURE__ */ jsx19(View12, { style: { paddingHorizontal: 24, paddingBottom: 30 }, children: /* @__PURE__ */ jsx19(
Text17,
{
style: {
fontSize: 38,
fontWeight: "700",
color: "#000000",
letterSpacing: -1,
lineHeight: 46
},
children: title
}
) }),
/* @__PURE__ */ jsx19(View12, { style: { flex: 1, paddingHorizontal: 20 }, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs10(View12, { style: { marginBottom: 30 }, children: [
section.title && /* @__PURE__ */ jsx19(
Text17,
{
style: {
fontSize: 22,
fontWeight: "600",
color: "#000000",
marginBottom: 16,
marginLeft: 4
},
children: section.title
}
),
section.items.map((item) => /* @__PURE__ */ jsxs10(
TouchableOpacity,
{
style: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 15,
paddingHorizontal: 16,
marginBottom: 3,
backgroundColor: item.isSelected ? "#007AFF" : "transparent",
borderRadius: 12
},
onPress: item.onPress,
activeOpacity: 0.8,
children: [
item.icon && /* @__PURE__ */ jsx19(View12, { style: { marginRight: 15 }, children: renderIcon(item.icon, item.isSelected) }),
/* @__PURE__ */ jsx19(
Text17,
{
style: {
flex: 1,
fontSize: 17,
fontWeight: item.isSelected ? "600" : "400",
color: item.isSelected ? "#FFFFFF" : "#000000",
letterSpacing: -0.3
},
children: item.label
}
),
item.badge && /* @__PURE__ */ jsx19(
View12,
{
style: {
backgroundColor: item.isSelected ? "rgba(255,255,255,0.25)" : "#FF3B30",
borderRadius: 15,
paddingHorizontal: 8,
paddingVertical: 4,
minWidth: 26,
alignItems: "center",
justifyContent: "center"
},
children: /* @__PURE__ */ jsx19(
Text17,
{
style: {
fontSize: 13,
fontWeight: "600",
color: "#FFFFFF"
},
children: item.badge
}
)
}
)
]
},
item.id
))
] }, sectionIndex)) })
] })
}
)
] });
});
PlatformDrawerIOS.displayName = "PlatformDrawer";
// src/components/PlatformDrawer.tsx
import { jsx as jsx20 } from "react/jsx-runtime";
var PlatformDrawer = forwardRef2((props, ref) => {
const isIOS2 = Platform7.OS === "ios" || Platform7.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx20(PlatformDrawerIOS, { ref, ...props }) : /* @__PURE__ */ jsx20(PlatformDrawer, { ref, ...props });
});
PlatformDrawer.displayName = "";
// src/components/Toggle.tsx
import { Platform as Platform8 } from "react-native";
// src/components/ios/ToggleIOS.tsx
import { Switch } from "react-native";
import { cssInterop as cssInterop14 } from "nativewind";
import { jsx as jsx21 } from "react/jsx-runtime";
var NativeSwitch = cssInterop14(Switch, { className: "style" });
var ToggleIOS = ({ className = "", ...props }) => {
return /* @__PURE__ */ jsx21(
NativeSwitch,
{
className: `ios-toggle-base ${className}`,
ios_backgroundColor: "#E5E7EB",
trackColor: { false: "#E5E7EB", true: "#007AFF" },
thumbColor: "#FFFFFF",
...props
}
);
};
// src/components/android/ToggleAndroid.tsx
import { Switch as Switch2 } from "react-native";
import { cssInterop as cssInterop15 } from "nativewind";
import { jsx as jsx22 } from "react/jsx-runtime";
var NativeSwitch2 = cssInterop15(Switch2, { className: "style" });
var ToggleAndroid = ({ className = "", ...props }) => {
return /* @__PURE__ */ jsx22(
NativeSwitch2,
{
className: `android-toggle-base ${className}`,
trackColor: { false: "#9CA3AF", true: "#2563EB" },
thumbColor: props.value ? "#FFFFFF" : "#F3F4F6",
...props
}
);
};
// src/components/Toggle.tsx
import { jsx as jsx23 } from "react/jsx-runtime";
var Toggle = (props) => {
const isIOS2 = Platform8.OS === "ios" || Platform8.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx23(ToggleIOS, { ...props }) : /* @__PURE__ */ jsx23(ToggleAndroid, { ...props });
};
// src/components/ActivityIndicator.tsx
import { Platform as Platform9 } from "react-native";
// src/components/ios/ActivityIndicatorIOS.tsx
import { ActivityIndicator as RNActivityIndicator } from "react-native";
import { jsx as jsx24 } from "react/jsx-runtime";
var ActivityIndicatorIOS = ({
size = "small",
className = ""
}) => {
return /* @__PURE__ */ jsx24(
RNActivityIndicator,
{
className,
size,
color: "#007AFF"
}
);
};
// src/components/android/ActivityIndicatorAndroid.tsx
import { ActivityIndicator as RNActivityIndicator2 } from "react-native";
import { jsx as jsx25 } from "react/jsx-runtime";
var ActivityIndicatorAndroid = ({
size = "small",
className = ""
}) => {
return /* @__PURE__ */ jsx25(
RNActivityIndicator2,
{
className,
size,
color: "#2563EB"
}
);
};
// src/components/ActivityIndicator.tsx
import { jsx as jsx26 } from "react/jsx-runtime";
var ActivityIndicator3 = (props) => {
const isIOS2 = Platform9.OS === "ios" || Platform9.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx26(ActivityIndicatorIOS, { ...props }) : /* @__PURE__ */ jsx26(ActivityIndicatorAndroid, { ...props });
};
// src/components/Checkbox.tsx
import { Platform as Platform10 } from "react-native";
// src/components/ios/CheckBoxIOS.tsx
import { Pressable as Pressable7, View as View13 } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { jsx as jsx27 } from "react/jsx-runtime";
var CheckboxIOS = ({ value, onValueChange, className = "" }) => {
return /* @__PURE__ */ jsx27(Pressable7, { onPress: () => onValueChange(!value), children: /* @__PURE__ */ jsx27(
View13,
{
className: `
h-5 w-5 items-center justify-center rounded-full border
${value ? "border-[#007AFF] bg-[#007AFF]" : "border-gray-300 bg-white"}
${className}
`,
children: value && /* @__PURE__ */ jsx27(Ionicons, { name: "checkmark", size: 12, color: "white" })
}
) });
};
// src/components/android/CheckBoxAndroid.tsx
import { Pressable as Pressable8, View as View14 } from "react-native";
import { Ionicons as Ionicons2 } from "@expo/vector-icons";
import { jsx as jsx28 } from "react/jsx-runtime";
var CheckboxAndroid = ({ value, onValueChange, className = "" }) => {
return /* @__PURE__ */ jsx28(Pressable8, { onPress: () => onValueChange(!value), children: /* @__PURE__ */ jsx28(
View14,
{
className: `
h-5 w-5 items-center justify-center rounded-sm border
${value ? "border-[#2563EB] bg-[#2563EB]" : "border-gray-400 bg-white"}
${className}
`,
children: value && /* @__PURE__ */ jsx28(Ionicons2, { name: "checkmark", size: 14, color: "white" })
}
) });
};
// src/components/Checkbox.tsx
import { jsx as jsx29 } from "react/jsx-runtime";
var Checkbox = (props) => {
const isIOS2 = Platform10.OS === "ios" || Platform10.OS === "web";
return isIOS2 ? /* @__PURE__ */ jsx29(CheckboxIOS, { ...props }) : /* @__PURE__ */ jsx29(CheckboxAndroid, { ...props });
};
// src/components/DateTimeField.tsx
import { useMemo, useState as useState4 } from "react";
import {
Pressable as RNPressable3,
View as RNView10,
Text as RNText13,
Platform as Platform11
} from "react-native";
import DateTimePicker from "@react-native-community/datetimepicker";
import { cssInterop as cssInterop16 } from "nativewind";
import { jsx as jsx30, jsxs as jsxs11 } from "react/jsx-runtime";
var View15 = cssInterop16(RNView10, { className: "style" });
var Text18 = cssInterop16(RNText13, { className: "style" });
var Pressable9 = cssInterop16(RNPressable3, { className: "style" });
var VALID_MINUTE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30];
var DateTimeField = ({
value,
onChange,
label,
helperText,
errorText,
className = "",
triggerClassName = "",
showInlineOnIOS = true,
locale,
format = { dateStyle: "medium", timeStyle: "short" },
mode = "date",
minimumDate,
maximumDate,
// iOS/web
minuteInterval,
themeVariant,
accentColor,
textColor,
// Android
is24Hour,
positiveButtonLabel,
negativeButtonLabel,
neutralButtonLabel,
// nou
pickerBackgroundColor,
pickerContainerClassName
}) => {
const [open, setOpen] = useState4(false);
const formatted = useMemo(() => {
try {
return new Intl.DateTimeFormat(locale || void 0, format).format(value);
} catch {
return value.toLocaleString();
}
}, [value, locale, format]);
const handleChange = (e, selected) => {
if (Platform11.OS === "android") {
setOpen(false);
if (e.type === "set" && selected) onChange(selected);
if (e.type === "neutralButtonPressed") onChange(null);
} else {
if (selected) onChange(selected);
}
};
const safeMinuteInterval = minuteInterval && VALID_MINUTE_INTERVALS.includes(minuteInterval) ? minuteInterval : void 0;
const isCupertino = Platform11.OS === "ios" || Platform11.OS === "web";
const cupertinoDisplay = showInlineOnIOS ? "inline" : "compact";
const resolvedPickerBg = isCupertino ? pickerBackgroundColor ?? "#ffffff" : void 0;
return /* @__PURE__ */ jsxs11(View15, { className: `w-full ${className}`, children: [
!!label && /* @__PURE__ */ jsx30(Text18, { className: "mb-1 text-sm text-gray-500", children: label }),
/* @__PURE__ */ jsx30(
Pressable9,
{
onPress: () => setOpen(true),
accessibilityRole: "button",
accessibilityLabel: label || "Open date time picker",
className: `rounded-xl border border-gray-200 bg-white px-3 py-2 ${triggerClassName}`,
children: /* @__PURE__ */ jsx30(Text18, { className: "text-base text-gray-900", children: formatted })
}
),
!!helperText && !errorText && /* @__PURE__ */ jsx30(Text18, { className: "mt-1 text-xs text-gray-500", children: helperText }),
!!errorText && /* @__PURE__ */ jsx30(Text18, { className: "mt-1 text-xs text-red-600", children: errorText }),
open && (isCupertino ? (
// iOS și WEB
cupertinoDisplay === "inline" ? (
// placă albă cu colțuri ca în iOS
/* @__PURE__ */ jsx30(
View15,
{
className: `mt-2 rounded-2xl border border-black/5 shadow-sm p-2 ${pickerContainerClassName || ""}`,
style: { backgroundColor: resolvedPickerBg },
children: /* @__PURE__ */ jsx30(View15, { className: "overflow-hidden rounded-xl", children: /* @__PURE__ */ jsx30(
DateTimePicker,
{
value,
mode,
display: "inline",
onChange: handleChange,
minimumDate,
maximumDate,
minuteInterval: safeMinuteInterval,
themeVariant,
accentColor,
textColor
}
) })
}
)
) : (
// compact: lăsăm nativ (arată ca field-ul iOS)
/* @__PURE__ */ jsx30(View15, { className: "mt-2", children: /* @__PURE__ */ jsx30(
DateTimePicker,
{
value,
mode,
display: "compact",
onChange: handleChange,
minimumDate,
maximumDate,
minuteInterval: safeMinuteInterval,
themeVariant,
accentColor,
textColor
}
) })
)
) : (
// ANDROID (dialog nativ)
/* @__PURE__ */ jsx30(
DateTimePicker,
{
value,
mode,
display: "default",
onChange: handleChange,
minimumDate,
maximumDate,
is24Hour,
positiveButton: { label: positiveButtonLabel },
negativeButton: { label: negativeButtonLabel },
neutralButton: neutralButtonLabel ? { label: neutralButtonLabel } : void 0
}
)
))
] });
};
// src/components/Stepper.tsx
import { Platform as Platform12 } from "react-native";
// src/components/ios/StepperIOS.tsx
import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5 } from "react";
import { View as View16, Text as Text19, Pressable as Pressable10 } from "react-native";
import { Ionicons as Ionicons3 } from "@expo/vector-icons";
import { jsx as jsx31, jsxs as jsxs12 } from "react/jsx-runtime";
var StepperIOS = ({
value,
onChange,
min = Number.NEGATIVE_INFINITY,
max = Number.POSITIVE_INFINITY,
step = 1,
disabled = false,
allowDecimals = false,
className = "",
buttonClassName = "",
valueClassName = "",
accentColor = "#007AFF",
neutralColor = "#F2F3F5",
longPressIntervalMs = 100,
valueSlotWidth = 56
}) => {
const timerRef = useRef5(null);
const clamped = Math.min(max, Math.max(min, value));
const canDec = !disabled && clamped > min;
const canInc = !disabled && clamped < max;
const displayText = useMemo2(() => {
if (allowDecimals) return clamped.toFixed(1);
return String(Math.round(clamped));
}, [clamped, allowDecimals]);
const clamp = (v) => Math.min(max, Math.max(min, v));
const inc = () => canInc && onChange(clamp(clamped + step));
const dec = () => canDec && onChange(clamp(clamped - step));
const clearHold = () => {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = null;
}
};
const startHold = (fn) => {
clearHold();
timerRef.current = setInterval(fn, longPressIntervalMs);
};
useEffect4(() => {
return () => clearHold();
}, []);
const onAccessibilityAction = (e) => {
if (e.nativeEvent.actionName === "increment") inc();
if (e.nativeEvent.actionName === "decrement") dec();
};
return /* @__PURE__ */ jsxs12(
View16,
{
className: `flex-row items-center rounded-full border border-gray-200 bg-white px-1 py-1 ${disabled ? "opacity-50" : ""} ${className}`,
accessibilityRole: "adjustable",
accessibilityActions: [{ name: "increment" }, { name: "decrement" }],
onAccessibilityAction,
children: [
/* @__PURE__ */ jsx31(
Pressable10,
{
accessibilityRole: "button",
accessibilityLabel: "Decrement",
disabled: !canDec,
onPress: dec,
onPressIn: () => startHold(dec),
onPressOut: clearHold,
hitSlop: 8,
className: `h-8 w-8 items-center justify-center rounded-full ${buttonClassName}`,
style: { backgroundColor: canDec ? neutralColor : "#F5F6F7", opacity: canDec ? 1 : 0.6 },
children: /* @__PURE__ */ jsx31(Ionicons3, { name: "remove", size: 16, color: canDec ? "#111827" : "#9CA3AF" })
}
),
/* @__PURE__ */ jsx31(View16, { className: "items-center justify-center px-3", style: { minWidth: valueSlotWidth }, children: /* @__PURE__ */ jsx31(
Text19,
{
className: `text-base font-semibold text-gray-900 ${valueClassName}`,
style: { fontVariant: ["tabular-nums"] },
children: displayText
}
) }),
/* @__PURE__ */ jsx31(
Pressable10,
{
accessibilityRole: "button",
accessibilityLabel: "Increment",
disabled: !canInc,
onPress: inc,
onPressIn: () => startHold(inc),
onPressOut: clearHold,
hitSlop: 8,
className: `h-8 w-8 items-center justify-center rounded-full ${buttonClassName}`,
style: { backgroundColor: canInc ? accentColor : "#C7D7FE", opacity: canInc ? 1 : 0.7 },
children: /* @__PURE__ */ jsx31(Ionicons3, { name: "add", size: 16, color: "white" })
}
)
]
}
);
};
// src/components/android/StepperAndroid.tsx
import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef6 } from "react";
import {
View as RNView11,
Text as RNText14,
Pressable as RNPressable4
} from "react-native";
import { Ionicons as Ionicons4 } from "@expo/vector-icons";
import { cssInterop as cssInterop17 } from "nativewind";
import { jsx as jsx32, jsxs as jsxs13 } from "react/jsx-runtime";
var View17 = cssInterop17(RNView11, { className: "style" });
var Text20 = cssInterop17(RNText14, { className: "style" });
var Pressable11 = cssInterop17(RNPressable4, { className: "style" });
var StepperAndroid = ({
value,
onChange,
min = Number.NEGATIVE_INFINITY,
max = Number.POSITIVE_INFINITY,
step = 1,
disabled = false,
allowDecimals = false,
className = "",
buttonClassName = "",
valueClassName = "",
accentColor = "#2563EB",
// Material Blue 600
neutralColor = "#EEF2FF",
longPressIntervalMs = 100,
valueSlotWidth = 64
}) => {
const timerRef = useRef6(null);
const clamped = useMemo3(() => Math.min(max, Math.max(min, value)), [value, min, max]);
const canDec = !disabled && clamped > min;
const canInc = !disabled && clamped < max;
const displayText = useMemo3(() => {
if (allowDecimals) return clamped.toFixed(1);
return String(Math.round(clamped));
}, [clamped, allowDecimals]);
const clamp = (v) => Math.min(max, Math.max(min, v));
const inc = () => canInc && onChange(clamp(clamped + step));
const dec = () => canDec && onChange(clamp(clamped - step));
const clearHold = () => {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = null;
}
};
const startHold = (fn) => {
clearHold();
timerRef.current = setInterval(fn, longPressIntervalMs);
};
useEffect5(() => {
return () => clearHold();
}, []);
const onAccessibilityAction = (e) => {
if (e.nativeEvent.actionName === "increment") inc();
if (e.nativeEvent.actionName === "decrement") dec();
};
return /* @__PURE__ */ jsxs13(
View17,
{
className: `flex-row items-center overflow-hidden rounded-xl border border-gray-200 bg-white ${disabled ? "opacity-50" : ""} ${className}`,
accessibilityRole: "adjustable",
accessibilityActions: [{ name: "increment" }, { name: "decrement" }],
onAccessibilityAction,
children: [
/* @__PURE__ */ jsx32(
Pressable11,
{
android_ripple: { color: "#E5E7EB", borderless: false },
accessibilityRole: "button",
accessibilityLabel: "Decrement",
disabled: !canDec,
onPress: dec,
onPressIn: () => startHold(dec),
onPressOut: clearHold,
hitSlop: 8,
className: `h-10 w-10 items-center justify-center ${buttonClassName}`,
style: { backgroundColor: canDec ? neutralColor : "#F3F4F6", opacity: canDec ? 1 : 0.6 },
children: /* @__PURE__ */ jsx32(Ionicons4, { name: "remove", size: 18, color: canDec ? accentColor : "#9CA3AF" })
}
),
/* @__PURE__ */ jsx32(View17, { className: "items-center justify-center px-3", style: { minWidth: valueSlotWidth }, children: /* @__PURE__ */ jsx32(
Text20,
{
className: `text-base font-medium text-gray-900 ${valueClassName}`,
style: { fontVariant: ["tabular-nums"] },
children: displayText
}
) }),
/* @__PURE__ */ jsx32(
Pressable11,
{
android_ripple: { color: "#E5E7EB", borderless: false },
accessibilityRole: "button",
accessibilityLabel: "Increment",
disabled: !canInc,
onPress: inc,
onPressIn: () => startHold(inc),
onPressOut: clearHold,
hitSlop: 8,
className: `h-10 w-10 items-center justify-center ${buttonClassName}`,
style: { backgroundColor: canInc ? accentColor : "#C7D7FE", opacity: canInc ? 1 : 0.7 },
children: /* @__PURE__ */ jsx32(Ionicons4, { name: "add", size: 18, color: "white" })
}
)
]
}
);
};
// src/components/Stepper.tsx
import { jsx as jsx33 } from "react/jsx-runtime";
var Stepper = (props) => {
const isIO