@hoddy-ui/next
Version:
Core rich react native components written in typescript, with support for expo-router
1,473 lines (1,444 loc) • 100 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// index.ts
var next_exports = {};
__export(next_exports, {
AdaptiveStatusBar: () => AdaptiveStatusBarNext_default,
AlertX: () => AlertX_default,
Animator: () => Animator,
Avatar: () => Avatar_default,
Button: () => Button_default,
CheckBox: () => CheckBox,
Divider: () => Divider,
FormWrapper: () => FormWrapper,
Grid: () => Grid,
GridItem: () => GridItem,
IconButton: () => IconButton,
LinkButton: () => LinkButton,
Locator: () => Locator,
OTPInput: () => OTPInput,
Popup: () => Popup,
RatingInput: () => RatingInput,
RatingStars: () => RatingStars,
SafeAreaView: () => SafeAreaView,
SelectMenu: () => SelectMenu_default,
Spinner: () => Spinner_default,
TextField: () => TextField_default,
TextField2: () => TextField2,
TextFieldBase: () => TextFieldBase,
Typography: () => Typography_default,
UIThemeContext: () => UIThemeContext,
UIThemeProvider: () => UIThemeProvider,
default: () => next_default,
getLocationFromPlaceId: () => getLocationFromPlaceId,
getPredictionsFromCoords: () => getPredictionsFromCoords,
getPredictionsFromQuery: () => getPredictionsFromQuery,
showFlashMessage: () => showFlashMessage,
useAppState: () => useAppState_default,
useBlinkAnimation: () => useBlinkAnimation,
useColors: () => useColors,
useFadeAnimation: () => useFadeAnimation,
useFloatAnimation: () => useFloatAnimation,
useGrowAnimation: () => useGrowAnimation,
useNavScreenOptions: () => useNavScreenOptions,
useRollAnimation: () => useRollAnimation,
useSlideAnimation: () => useSlideAnimation,
useTheme: () => useTheme,
useThemeContext: () => useThemeContext,
useThrownUpAnimation: () => useThrownUpAnimation
});
module.exports = __toCommonJS(next_exports);
// ../src/theme/colors.ts
var extraColors = {};
var setExtraColors = (c) => extraColors = c;
var defaultPalettes = {
primary: {
main: "#ff8800",
light: "#feffd3",
dark: "#ffaa00",
text: "#ffffff"
},
secondary: {
main: "#ff1111",
light: "#ff4433",
dark: "#dd0000",
text: "#ffffff"
},
light: {
main: "#ffffff",
light: "#ffffff",
dark: "#dddddd",
text: "#000000"
},
dark: {
main: "#000000",
light: "#777777",
dark: "#111111",
text: "#ffffff"
},
textSecondary: {
main: "#aaaaaa",
light: "#bbbbbb",
dark: "#777777",
text: "#ffffff"
},
blue: {
main: "#0099ff",
light: "#3399ff",
dark: "#002288",
text: "#ffffff"
},
info: {
main: "#0099ff",
light: "#33aaff",
dark: "#0088aa",
text: "#ffffff"
},
success: {
main: "#00aa44",
light: "#55cc33",
dark: "#006622",
text: "#ffffff"
},
warning: {
main: "#ffaa22",
light: "#ffcc77",
dark: "#ff9900",
text: "#ffffff"
},
error: {
main: "#dd2222",
light: "#ff4433",
dark: "#aa2200",
text: "#ffffff"
}
};
var lightNeutrals = {
white: { 1: "#ffffff", 2: "#f7f7f7", 3: "#eeeeee", 4: "#dddddd", 5: "#bbbbbb" },
black: { 1: "#888888", 2: "#777777", 3: "#555555", 4: "#333333", 5: "#000000" }
};
var darkNeutrals = {
white: { 1: "#060606", 2: "#222222", 3: "#333333", 4: "#444444", 5: "#555555" },
black: { 1: "#ffffff", 2: "#f7f7f7", 3: "#eeeeee", 4: "#dddddd", 5: "#aaaaaa" }
};
var darkPaletteOverrides = {
dark: {
main: "#f2f3f4",
light: "#ffffff",
dark: "#dddddd",
text: "#000000"
},
light: {
main: "#111111",
light: "#555555",
dark: "#333333",
text: "#ffffff"
},
textSecondary: {
main: "#666666",
light: "#777777",
dark: "#444444",
text: "#ffffff"
}
};
function colors(theme) {
const isDark = theme === "dark";
const neutrals = isDark ? darkNeutrals : lightNeutrals;
const overrides = isDark ? darkPaletteOverrides : {};
const baseDefaults = {
...neutrals,
...defaultPalettes
};
const keys = /* @__PURE__ */ new Set([
...Object.keys(baseDefaults),
...Object.keys(extraColors.light ?? {}),
...Object.keys(extraColors.dark ?? {})
]);
const themeInvertingKeys = /* @__PURE__ */ new Set([
"white",
"black",
"textSecondary",
"dark",
"light"
]);
const result = {};
keys.forEach((key) => {
const skipLightExtras = isDark && themeInvertingKeys.has(key);
result[key] = {
...baseDefaults[key],
...overrides[key],
...skipLightExtras ? {} : extraColors.light?.[key],
...isDark ? extraColors.dark?.[key] : {}
};
});
return result;
}
// ../src/config/KeyManager.ts
var config = {
GOOGLE_MAP_API_KEY: "",
EDGE_TO_EDGE: false
};
function setConfig(key) {
config = key;
}
function getConfig() {
return config;
}
// ../src/config/index.ts
function initialize(config2) {
try {
setConfig({
GOOGLE_MAP_API_KEY: config2.googleMapApiKey,
TYPOGRAPHY: config2.typography,
EDGE_TO_EDGE: config2.edgeToEdge ?? false
});
if (config2.colors)
setExtraColors(config2.colors);
} catch (error) {
console.error("Error reading the config file:", error);
}
}
// components/AdaptiveStatusBarNext.tsx
var import_expo_router = require("expo-router");
var import_react5 = __toESM(require("react"));
var import_react_native5 = require("react-native");
// ../src/hooks.ts
var import_react4 = require("react");
var import_react_native4 = require("react-native");
// ../src/theme/index.tsx
var import_async_storage = __toESM(require("@react-native-async-storage/async-storage"));
var NavigationBar = __toESM(require("expo-navigation-bar"));
var SystemUI = __toESM(require("expo-system-ui"));
var import_react3 = __toESM(require("react"));
var import_react_native3 = require("react-native");
var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
// ../src/Components/FlashMessage.tsx
var import_react2 = __toESM(require("react"));
var import_react_native2 = require("react-native");
var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
var import_react_native_safe_area_context = require("react-native-safe-area-context");
var import_react_native_size_matters2 = require("react-native-size-matters");
// ../src/Components/Typography.tsx
var import_react = __toESM(require("react"));
var import_react_native = require("react-native");
var import_react_native_size_matters = require("react-native-size-matters");
// ../src/utility.ts
var getFontFamily = (fontWeight) => {
return getConfig().TYPOGRAPHY?.fontWeights?.[fontWeight] || getConfig().TYPOGRAPHY?.fontFamily || void 0;
};
// ../src/Components/Typography.tsx
var DEFAULT_FONT_SIZES = {
h1: (0, import_react_native_size_matters.ms)(42),
h2: (0, import_react_native_size_matters.ms)(37),
h3: (0, import_react_native_size_matters.ms)(32),
h4: (0, import_react_native_size_matters.ms)(27),
h5: (0, import_react_native_size_matters.ms)(22),
h6: (0, import_react_native_size_matters.ms)(17),
body1: (0, import_react_native_size_matters.ms)(15),
body2: (0, import_react_native_size_matters.ms)(12),
caption: (0, import_react_native_size_matters.ms)(10)
};
var Typography = (0, import_react.forwardRef)(
({
children,
color = "dark",
style = {},
textCase,
variant = "body1",
align = "left",
gutterBottom = 0,
adjustsFontSizeToFit,
fontWeight = 400,
fontFamily,
// NEW PROP ADDED
fontSize,
lineHeight,
...props
}, ref) => {
const colors2 = useColors();
const config2 = getConfig();
const customFontSizes = config2.TYPOGRAPHY?.fontSizes;
const baseFontSize = customFontSizes?.[variant] ?? DEFAULT_FONT_SIZES[variant];
const f = fontSize || style?.fontSize || baseFontSize;
const lh = lineHeight || f * 1.2;
const styles = import_react_native.StyleSheet.create({
text: {
lineHeight: lh,
fontSize: f,
marginBottom: (0, import_react_native_size_matters.ms)(gutterBottom) || 0,
color: colors2[color]?.main || color,
textTransform: textCase,
alignItems: "center",
textAlign: align,
fontWeight,
fontFamily: fontFamily || getFontFamily(fontWeight)
}
});
return /* @__PURE__ */ import_react.default.createElement(
import_react_native.Text,
{
ref,
adjustsFontSizeToFit,
style: [styles.text, style],
...props
},
children
);
}
);
var Typography_default = Typography;
// ../src/Components/FlashMessage.tsx
var flashListeners = /* @__PURE__ */ new Set();
var showFlashMessage = (msg) => {
flashListeners.forEach((listener) => listener(msg));
};
var subscribeToFlashMessages = (listener) => {
flashListeners.add(listener);
return () => {
flashListeners.delete(listener);
};
};
var FlashMessage = () => {
const { top } = (0, import_react_native_safe_area_context.useSafeAreaInsets)();
const [message, setMessage] = (0, import_react2.useState)(null);
const colors2 = useColors();
const type = message?.type || "success";
const timeoutRef = (0, import_react2.useRef)(null);
const translateY = (0, import_react_native_reanimated.useSharedValue)(-200);
const opacity = (0, import_react_native_reanimated.useSharedValue)(0);
const hideMessage = () => {
setMessage(null);
};
const closeMessage = () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
translateY.value = (0, import_react_native_reanimated.withTiming)(-200, { duration: 300 });
opacity.value = (0, import_react_native_reanimated.withTiming)(0, { duration: 300 }, () => {
(0, import_react_native_reanimated.runOnJS)(hideMessage)();
});
};
(0, import_react2.useEffect)(() => {
const listener = (msg) => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
translateY.value = -200;
opacity.value = 0;
setMessage(msg);
translateY.value = (0, import_react_native_reanimated.withTiming)(0, { duration: 300 });
opacity.value = (0, import_react_native_reanimated.withTiming)(1, { duration: 300 });
const duration = msg.duration || 3e3;
timeoutRef.current = setTimeout(() => {
translateY.value = (0, import_react_native_reanimated.withTiming)(-200, { duration: 300 });
opacity.value = (0, import_react_native_reanimated.withTiming)(0, { duration: 300 }, () => {
(0, import_react_native_reanimated.runOnJS)(hideMessage)();
});
timeoutRef.current = null;
}, duration);
};
const unsubscribe = subscribeToFlashMessages(listener);
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
unsubscribe();
};
}, []);
const animatedStyle = (0, import_react_native_reanimated.useAnimatedStyle)(() => {
return {
transform: [{ translateY: translateY.value }],
opacity: opacity.value
};
});
const textColor = type === "default" ? "#fff" : colors2[type].text;
const styles = import_react_native_size_matters2.ScaledSheet.create({
root: {
position: "absolute",
top: 0,
zIndex: 1e3,
left: 0,
paddingTop: top + 10,
paddingHorizontal: "15@ms",
backgroundColor: type === "default" ? "#333" : colors2[type].main,
width: "100%",
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
paddingBottom: "15@ms"
},
action: {
borderRadius: 20,
marginTop: "10@vs",
flexDirection: "row",
justifyContent: "center",
paddingHorizontal: "20@ms",
paddingVertical: "8@vs",
backgroundColor: "#fff3"
}
});
if (!message)
return null;
return /* @__PURE__ */ import_react2.default.createElement(import_react_native_reanimated.default.View, { style: [styles.root, animatedStyle] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: closeMessage, activeOpacity: 0.9 }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { flexDirection: "row" } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { flex: 1, marginRight: 10 } }, message?.title && /* @__PURE__ */ import_react2.default.createElement(
Typography_default,
{
variant: "h6",
fontWeight: 600,
gutterBottom: 3,
color: textColor
},
message?.title
), /* @__PURE__ */ import_react2.default.createElement(Typography_default, { color: textColor }, message?.message)))), message?.actions?.map((cur, i) => /* @__PURE__ */ import_react2.default.createElement(
import_react_native2.TouchableOpacity,
{
key: i,
style: styles.action,
onPress: () => {
cur.onPress?.();
closeMessage();
}
},
/* @__PURE__ */ import_react2.default.createElement(Typography_default, { fontWeight: 700, style: { color: "#fff" } }, cur.title)
)));
};
var FlashMessage_default = FlashMessage;
// ../src/theme/index.tsx
var UIThemeContext = (0, import_react3.createContext)({
themeState: { mode: "default", value: "light" }
});
function themeReducer(state, { type, payload }) {
import_async_storage.default.setItem("theme", type);
switch (type) {
case "dark":
return { mode: "dark", value: "dark" };
case "default":
return { mode: "default", value: payload };
case "light":
return { mode: "light", value: "light" };
default:
return state;
}
}
var ConfigureSystemUI = () => {
const theme = useTheme();
const colors2 = useColors();
(0, import_react3.useEffect)(() => {
const config2 = getConfig();
if (colors2) {
SystemUI.setBackgroundColorAsync(colors2.white[1]);
if (import_react_native3.Platform.OS === "android") {
if (config2.EDGE_TO_EDGE) {
if (theme === "dark") {
NavigationBar.setStyle("light");
} else {
NavigationBar.setStyle("dark");
}
} else {
NavigationBar.setBackgroundColorAsync(colors2.white[1]);
if (theme === "dark") {
NavigationBar.setButtonStyleAsync("light");
} else {
NavigationBar.setButtonStyleAsync("dark");
}
}
}
}
}, [colors2, theme]);
return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null);
};
var UIThemeProvider = ({ children }) => {
const [themeState, themeDispatch] = (0, import_react3.useReducer)(themeReducer, {
mode: "default",
value: "light"
});
const colorScheme = (0, import_react_native3.useColorScheme)();
import_react3.default.useEffect(() => {
import_async_storage.default.getItem("theme").then((val) => {
if (val) {
if (val === "default") {
themeDispatch({
type: "default",
payload: colorScheme
});
} else {
themeDispatch({
type: val
});
import_react_native3.Appearance.setColorScheme(val);
}
} else {
themeDispatch({
type: "default",
payload: colorScheme
});
}
});
}, [colorScheme]);
return /* @__PURE__ */ import_react3.default.createElement(import_react_native_safe_area_context2.SafeAreaProvider, null, /* @__PURE__ */ import_react3.default.createElement(
UIThemeContext.Provider,
{
value: {
themeState,
themeDispatch
}
},
children,
/* @__PURE__ */ import_react3.default.createElement(FlashMessage_default, null),
/* @__PURE__ */ import_react3.default.createElement(ConfigureSystemUI, null)
));
};
// ../src/hooks.ts
var useColors = () => {
const { themeState } = (0, import_react4.useContext)(UIThemeContext);
return colors(themeState.value);
};
var useTheme = () => {
const { themeState } = (0, import_react4.useContext)(UIThemeContext);
return themeState.value;
};
var useThemeContext = () => {
const { themeState: theme, themeDispatch } = (0, import_react4.useContext)(UIThemeContext);
const colorScheme = (0, import_react_native4.useColorScheme)();
const setTheme = (theme2) => {
if (theme2 === "default") {
themeDispatch?.({ type: "default", payload: colorScheme });
} else {
themeDispatch?.({ type: theme2 });
}
};
return { theme, setTheme };
};
var useNavScreenOptions = (type) => {
const colors2 = useColors();
const options = {
stack: {
headerShown: false,
headerStyle: {
backgroundColor: colors2.white[1]
},
headerShadowVisible: false,
contentStyle: {
backgroundColor: colors2.white[1]
},
headerTitleStyle: {
color: colors2.black[1]
},
headerTintColor: import_react_native4.Platform.OS === "android" ? colors2.black[1] : colors2.blue.light
},
tab: {
headerShown: false,
headerTintColor: colors2.dark.main,
tabBarStyle: {
borderTopColor: colors2.white[2],
borderColor: colors2.white[2],
borderTopWidth: 1,
backgroundColor: colors2.white[1]
},
tabBarActiveTintColor: colors2.primary.main,
tabBarInactiveTintColor: colors2.textSecondary.main,
tabBarLabelStyle: {
// fontSize: ms(12),
}
},
drawer: {
headerShown: false,
drawerActiveTintColor: colors2.primary.main,
drawerInactiveTintColor: colors2.textSecondary.main,
sceneContainerStyle: {
backgroundColor: colors2.white[2]
},
drawerStyle: {
backgroundColor: colors2.white[1]
},
headerStyle: {
backgroundColor: colors2.white[1]
},
headerTitleStyle: {
color: colors2.dark.main
}
}
};
return options[type];
};
// components/AdaptiveStatusBarNext.tsx
var AdaptiveStatusBar = ({ translucent = false }) => {
const colors2 = useColors();
const theme = useTheme();
const statusbarHandler = () => {
import_react_native5.StatusBar.setBarStyle(theme === "dark" ? "light-content" : "dark-content");
if (import_react_native5.Platform.OS === "android") {
import_react_native5.StatusBar.setTranslucent(true);
}
};
(0, import_expo_router.useFocusEffect)(
import_react5.default.useCallback(() => {
statusbarHandler();
}, [theme])
);
import_react5.default.useEffect(() => {
statusbarHandler();
}, [theme]);
return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null);
};
var AdaptiveStatusBarNext_default = AdaptiveStatusBar;
// ../src/Components/AlertX.tsx
var import_vector_icons = require("@expo/vector-icons");
var import_react6 = __toESM(require("react"));
var import_react_native6 = require("react-native");
var import_react_native_size_matters3 = require("react-native-size-matters");
var AlertX = ({
type = "info",
variant = "contained",
title,
gutterBottom = 0,
body,
style = {}
}) => {
const colors2 = useColors();
const styles = import_react_native_size_matters3.ScaledSheet.create({
container: {
padding: 20,
paddingTop: 10,
paddingBottom: 10,
borderRadius: 8,
alignItems: "center",
flexDirection: "row",
marginBottom: (0, import_react_native_size_matters3.ms)(gutterBottom),
backgroundColor: colors2[type].main + (variant === "contained" ? "" : "3")
},
title: {
color: variant === "contained" ? "#fff" : colors2[type].main
},
body: {
color: variant === "contained" ? "#fff" : colors2[type].main
}
});
return /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: [styles.container, style] }, /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: { width: "80%" } }, /* @__PURE__ */ import_react6.default.createElement(Typography_default, { style: styles.title, gutterBottom: 3, fontWeight: 700 }, title), body && /* @__PURE__ */ import_react6.default.createElement(Typography_default, { fontWeight: 700, variant: "body2", style: styles.body }, body)), /* @__PURE__ */ import_react6.default.createElement(import_react_native6.View, { style: { marginLeft: "auto" } }, /* @__PURE__ */ import_react6.default.createElement(
import_vector_icons.MaterialIcons,
{
color: variant === "contained" ? "#fff" : colors2[type].main,
size: 36,
name: type === "success" ? "check" : type
}
)));
};
var AlertX_default = AlertX;
// ../src/Components/Avatar.tsx
var import_vector_icons2 = require("@expo/vector-icons");
var import_react7 = __toESM(require("react"));
var import_react_native7 = require("react-native");
var import_react_native_size_matters4 = require("react-native-size-matters");
var Avatar = ({
color = "dark",
label,
variant = "contained",
source,
size = 48,
style = {},
icon
}) => {
const colors2 = useColors();
const [imageError, setImageError] = (0, import_react7.useState)(false);
const styles = import_react_native_size_matters4.ScaledSheet.create({
root: {
borderRadius: 150,
height: (0, import_react_native_size_matters4.ms)(size),
width: (0, import_react_native_size_matters4.ms)(size),
alignItems: "center",
justifyContent: "center",
overflow: "hidden",
borderWidth: variant === "outlined" ? 5 : 0,
borderColor: variant === "outlined" ? "#fff" : "#0000",
backgroundColor: variant === "outlined" ? void 0 : label ? colors2[color].main : colors2.white[4],
...style
},
image: {
height: "110%",
width: "110%"
}
});
return /* @__PURE__ */ import_react7.default.createElement(import_react_native7.View, { style: styles.root }, source && !imageError ? /* @__PURE__ */ import_react7.default.createElement(
import_react_native7.Image,
{
resizeMode: "cover",
style: styles.image,
source,
onError: () => setImageError(true)
}
) : label ? /* @__PURE__ */ import_react7.default.createElement(Typography_default, { style: { color: colors2[color].text } }, label[0]) : icon ? icon : /* @__PURE__ */ import_react7.default.createElement(import_vector_icons2.Ionicons, { name: "person", color: "#fff", size: Math.round(size / 1.5) }));
};
var Avatar_default = Avatar;
// ../src/Components/Button.tsx
var import_vector_icons3 = require("@expo/vector-icons");
var import_react8 = __toESM(require("react"));
var import_react_native8 = require("react-native");
var import_react_native_size_matters5 = require("react-native-size-matters");
var LinkButton = ({
title,
style = {},
color = "blue",
fontSize = 12,
fontWeight = 400,
disabled,
onPress = () => {
}
}) => {
const colors2 = useColors();
const styles = import_react_native_size_matters5.ScaledSheet.create({
text: {
fontSize: (0, import_react_native_size_matters5.moderateScale)(fontSize),
fontWeight: fontWeight.toString(),
fontFamily: getFontFamily(fontWeight),
color: disabled ? "#777" : colors2[color].main
}
});
return /* @__PURE__ */ import_react8.default.createElement(import_react_native8.TouchableOpacity, { onPress, disabled }, /* @__PURE__ */ import_react8.default.createElement(import_react_native8.Text, { style: { ...styles.text, ...style } }, title));
};
var IconButton = ({
style = {},
color = "dark",
disabled,
icon,
elevation,
bg = false,
size = 24,
containerStyles = {},
onPress = () => {
},
iconType = "material"
}) => {
const colors2 = useColors();
const theme = useTheme();
const bgColor = theme === "light" ? "#fff" : "#222";
const styles = import_react_native_size_matters5.ScaledSheet.create({
container: {
alignSelf: "flex-start",
flexGrow: 0,
backgroundColor: bg ? bgColor : elevation > 0 ? bgColor : void 0,
padding: "5@ms",
shadowColor: "#000",
shadowOpacity: 0.1,
shadowOffset: {
height: 1,
width: 0
},
height: bg ? (0, import_react_native_size_matters5.ms)(size + 20) : void 0,
width: bg ? (0, import_react_native_size_matters5.ms)(size + 20) : void 0,
alignItems: "center",
justifyContent: "center",
shadowRadius: elevation,
elevation,
borderRadius: size * 5
},
text: {
color: disabled ? "#777" : colors2[color].main
}
});
const IconComp = {
material: import_vector_icons3.MaterialIcons,
ion: import_vector_icons3.Ionicons
}[iconType];
return /* @__PURE__ */ import_react8.default.createElement(
import_react_native8.TouchableOpacity,
{
onPress,
activeOpacity: 0.3,
style: { ...styles.container, ...containerStyles }
},
/* @__PURE__ */ import_react8.default.createElement(IconComp, { style: { ...styles.text, ...style }, name: icon, size })
);
};
var Button = (0, import_react8.forwardRef)(
({
elevation = 0,
onPress = () => {
},
disabled = false,
title,
loading,
size = "normal",
rounded = false,
gutterBottom,
style = {},
fullWidth = false,
translucent = false,
color = "primary",
variant = "contained",
start,
end
}, ref) => {
const colors2 = useColors();
const styles = import_react_native_size_matters5.ScaledSheet.create({
con: {
flexDirection: "row",
alignItems: "center",
alignSelf: "flex-start",
justifyContent: "center",
backgroundColor: variant === "text" || variant === "outlined" ? void 0 : variant === "translucent" ? colors2[color].main + "22" : translucent ? translucent === "dark" ? colors2.white[3] + "22" : colors2.black[3] + "22" : loading ? colors2[color].light : disabled ? colors2.white[4] : colors2[color].main,
borderRadius: rounded ? 30 : 10,
elevation: variant === "text" ? 0 : elevation,
paddingVertical: size === "small" ? 8 : size === "large" ? "15@mvs" : "13@mvs",
paddingHorizontal: size === "small" ? "10@ms" : "18@ms",
borderColor: colors2[color].main,
borderWidth: variant === "outlined" ? 1 : 0,
shadowColor: "#000",
shadowRadius: elevation,
marginBottom: gutterBottom,
shadowOffset: {
height: elevation / 2,
width: 0
},
shadowOpacity: variant === "text" ? 0 : 0.3,
width: fullWidth ? "100%" : void 0,
...style
},
text: {
color: disabled ? variant === "text" || variant === "outlined" || variant === "translucent" ? colors2.black[1] : colors2[color].text : colors2[color][variant === "text" || variant === "outlined" || variant === "translucent" ? "main" : "text"],
fontWeight: variant === "outlined" ? "700" : variant === "translucent" ? "600" : "500",
fontSize: size === "small" ? "12@ms" : "13@ms",
fontFamily: getFontFamily(
variant === "outlined" ? 700 : variant === "translucent" ? 600 : 500
)
}
});
return /* @__PURE__ */ import_react8.default.createElement(
import_react_native8.TouchableOpacity,
{
ref,
onPress,
disabled,
style: styles.con
},
start,
loading && /* @__PURE__ */ import_react8.default.createElement(
import_react_native8.ActivityIndicator,
{
size: "small",
color: variant === "text" || variant === "outlined" || variant === "translucent" ? colors2[color].main : colors2[color].text,
style: { marginRight: 10 }
}
),
/* @__PURE__ */ import_react8.default.createElement(import_react_native8.Text, { style: styles.text }, title),
end
);
}
);
var Button_default = Button;
// ../src/Components/Checkbox.tsx
var import_vector_icons4 = require("@expo/vector-icons");
var import_react9 = __toESM(require("react"));
var import_react_native9 = require("react-native");
var import_react_native_size_matters6 = require("react-native-size-matters");
var CheckBox = ({
color = "primary",
checked,
size = 24,
label,
style = {},
onChange
}) => {
const iconName = checked ? "checkbox-marked" : "checkbox-blank-outline";
const colors2 = useColors();
const styles = import_react_native_size_matters6.ScaledSheet.create({
container: {
alignItems: "center",
flexDirection: "row",
...style
}
});
return /* @__PURE__ */ import_react9.default.createElement(import_react_native9.View, { style: styles.container }, /* @__PURE__ */ import_react9.default.createElement(import_react_native9.TouchableOpacity, { onPress: onChange }, /* @__PURE__ */ import_react9.default.createElement(
import_vector_icons4.MaterialCommunityIcons,
{
name: iconName,
size,
color: colors2[color].main
}
)), label);
};
// ../src/Components/FormWrapper.tsx
var import_react10 = __toESM(require("react"));
var import_react_native10 = require("react-native");
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
var import_react_native_size_matters7 = require("react-native-size-matters");
var FormWrapper = (0, import_react10.forwardRef)(
({
children,
behavior = import_react_native10.Platform.OS === "ios" ? "padding" : "height",
contentContainerStyle,
mode = "scroll",
keyboardVerticalOffset = 10,
style = {},
onScroll
}, ref) => {
const { bottom } = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
const defaultOffset = import_react_native10.Platform.OS === "ios" ? -bottom : -bottom * 2;
const styles = import_react_native_size_matters7.ScaledSheet.create({
root: {
width: "100%",
flex: 1,
...style
}
});
return mode === "static" ? /* @__PURE__ */ import_react10.default.createElement(import_react_native10.TouchableWithoutFeedback, { onPress: import_react_native10.Keyboard.dismiss, accessible: false }, /* @__PURE__ */ import_react10.default.createElement(
import_react_native10.KeyboardAvoidingView,
{
style: styles.root,
behavior,
contentContainerStyle: styles.root,
keyboardVerticalOffset: keyboardVerticalOffset || defaultOffset
},
children
)) : /* @__PURE__ */ import_react10.default.createElement(
import_react_native10.KeyboardAvoidingView,
{
behavior,
style: styles.root,
keyboardVerticalOffset: keyboardVerticalOffset || defaultOffset
},
/* @__PURE__ */ import_react10.default.createElement(
import_react_native10.ScrollView,
{
ref,
onScroll,
showsVerticalScrollIndicator: false,
scrollEventThrottle: 40,
keyboardDismissMode: "interactive",
contentContainerStyle,
keyboardShouldPersistTaps: "handled"
},
children
)
);
}
);
// ../src/Components/StarRating.tsx
var import_vector_icons5 = require("@expo/vector-icons");
var Haptics = __toESM(require("expo-haptics"));
var import_react12 = __toESM(require("react"));
var import_react_native12 = require("react-native");
var import_react_native_size_matters9 = require("react-native-size-matters");
// ../src/Components/Popup.tsx
var import_react_native11 = require("react-native");
var import_react11 = __toESM(require("react"));
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
var import_react_native_size_matters8 = require("react-native-size-matters");
var Popup = ({
title,
sheet = true,
bare = false,
keyboardVerticalOffset,
children,
open,
onClose = () => {
},
style,
onModalShow,
onModalHide,
disableAutoKeyboardManagement = false
}) => {
const theme = useTheme();
const colors2 = useColors();
const [modalVisible, setModalVisible] = (0, import_react11.useState)(false);
const [modalOpen, setModalOpen] = (0, import_react11.useState)(false);
const [keyboardVisible, setKeyboardVisible] = (0, import_react11.useState)(false);
const { bottom } = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
const backdropOpacity = (0, import_react_native_reanimated2.useSharedValue)(0);
const contentTranslateY = (0, import_react_native_reanimated2.useSharedValue)(1e3);
const keyboardVerticalOffsetValue = import_react_native11.Platform.OS === "ios" ? -bottom : -bottom * 2;
(0, import_react11.useEffect)(() => {
const keyboardDidShowListener = import_react_native11.Keyboard.addListener(
"keyboardDidShow",
() => {
setKeyboardVisible(true);
}
);
const keyboardDidHideListener = import_react_native11.Keyboard.addListener(
"keyboardDidHide",
() => {
setKeyboardVisible(false);
}
);
return () => {
keyboardDidHideListener?.remove();
keyboardDidShowListener?.remove();
};
}, []);
const _onModalShow = () => {
setModalVisible(true);
onModalShow?.();
};
const _onModalHide = () => {
onModalHide?.();
setModalOpen(false);
};
(0, import_react11.useEffect)(() => {
if (open) {
setModalOpen(true);
backdropOpacity.value = (0, import_react_native_reanimated2.withTiming)(1, { duration: 300 });
contentTranslateY.value = (0, import_react_native_reanimated2.withTiming)(0, { duration: 300 }, () => {
(0, import_react_native_reanimated2.runOnJS)(_onModalShow)();
});
} else {
setModalVisible(false);
backdropOpacity.value = (0, import_react_native_reanimated2.withTiming)(0, { duration: 200 });
contentTranslateY.value = (0, import_react_native_reanimated2.withTiming)(1e3, { duration: 200 }, () => {
(0, import_react_native_reanimated2.runOnJS)(_onModalHide)();
});
}
}, [open]);
const backdropAnimatedStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
opacity: backdropOpacity.value
}));
const contentAnimatedStyle = (0, import_react_native_reanimated2.useAnimatedStyle)(() => ({
transform: [{ translateY: contentTranslateY.value }]
}));
const styles = import_react_native_size_matters8.ScaledSheet.create({
root: {
height: "100%",
width: "100%",
justifyContent: sheet ? "flex-end" : "center"
},
keyboardView: {
flex: 1,
zIndex: 1e3
},
avoidingView: {
zIndex: 2,
minHeight: typeof sheet === "number" ? sheet : void 0,
maxHeight: "90%",
alignSelf: "center",
maxWidth: sheet ? void 0 : "90%",
width: sheet ? "100%" : void 0,
marginBottom: import_react_native11.Platform.OS === "android" && keyboardVisible ? bottom : 0
},
container: {
paddingBottom: sheet && !bare ? bottom + (0, import_react_native_size_matters8.ms)(0) : void 0,
backgroundColor: theme === "dark" ? "#111" : colors2.white[1],
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
borderBottomRightRadius: sheet ? 0 : 20,
borderBottomLeftRadius: sheet ? 0 : 20,
width: "100%",
overflow: "hidden",
...style
},
content: {
maxHeight: sheet && !bare ? import_react_native11.Dimensions.get("screen").height * 0.9 - bottom - (0, import_react_native_size_matters8.ms)(60) : void 0,
paddingHorizontal: bare ? void 0 : "15@ms"
// backgroundColor : "#f94",
},
title: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
height: "50@ms"
},
titleIcon: {
position: "absolute",
left: "15@ms"
},
backdrop: {
position: "absolute",
height: "100%",
zIndex: 1,
width: "100%",
backgroundColor: "#000b"
}
});
const closeAction = () => {
onClose();
};
return /* @__PURE__ */ import_react11.default.createElement(
import_react_native11.Modal,
{
transparent: true,
animationType: "none",
statusBarTranslucent: true,
visible: modalOpen,
onRequestClose: closeAction,
navigationBarTranslucent: true
},
/* @__PURE__ */ import_react11.default.createElement(UIThemeProvider, null, /* @__PURE__ */ import_react11.default.createElement(import_react_native_reanimated2.default.View, { style: [styles.backdrop, backdropAnimatedStyle] }), /* @__PURE__ */ import_react11.default.createElement(
import_react_native11.KeyboardAvoidingView,
{
style: styles.keyboardView,
behavior: import_react_native11.Platform.OS === "ios" ? "padding" : "height",
keyboardVerticalOffset: keyboardVerticalOffset || keyboardVerticalOffsetValue
},
/* @__PURE__ */ import_react11.default.createElement(
import_react_native11.TouchableWithoutFeedback,
{
onPress: import_react_native11.Keyboard.dismiss,
disabled: disableAutoKeyboardManagement
},
/* @__PURE__ */ import_react11.default.createElement(import_react_native11.View, { style: styles.root }, modalOpen && /* @__PURE__ */ import_react11.default.createElement(
import_react_native11.Pressable,
{
style: [import_react_native11.StyleSheet.absoluteFill, { zIndex: 1 }],
onPress: closeAction
}
), /* @__PURE__ */ import_react11.default.createElement(
import_react_native_reanimated2.default.View,
{
style: [styles.avoidingView, contentAnimatedStyle],
layout: modalVisible ? import_react_native_reanimated2.LinearTransition.springify().stiffness(200).mass(0.5).damping(100) : void 0
},
/* @__PURE__ */ import_react11.default.createElement(import_react_native11.View, { style: styles.container }, !bare && /* @__PURE__ */ import_react11.default.createElement(import_react_native11.View, { style: styles.title }, /* @__PURE__ */ import_react11.default.createElement(import_react_native11.View, { style: styles.titleIcon }, /* @__PURE__ */ import_react11.default.createElement(
IconButton,
{
size: 20,
icon: "close",
onPress: closeAction
}
)), /* @__PURE__ */ import_react11.default.createElement(Typography_default, { align: "center", fontWeight: 500 }, title)), /* @__PURE__ */ import_react11.default.createElement(import_react_native11.View, { style: styles.content }, children))
))
)
))
);
};
// ../src/Components/StarRating.tsx
var RatingInput = ({
onSubmit: _onSubmit,
rating = 0,
size = 16,
color = "primary"
}) => {
const [showReviewsModal, setShowReviewsModal] = (0, import_react12.useState)(false);
const [rate, setRate] = (0, import_react12.useState)(0);
const colors2 = useColors();
const [loading, setLoading] = (0, import_react12.useState)(false);
const [review, setReview] = (0, import_react12.useState)("");
const styles = import_react_native_size_matters9.ScaledSheet.create({
root: {
flexDirection: "row",
alignItems: "center"
},
inputCon: {
marginBottom: "20@vs",
backgroundColor: colors2.white[3],
padding: "15@ms",
borderRadius: 20
},
input: {
fontSize: "16@ms",
color: colors2.dark.main,
height: "100@vs"
}
});
(0, import_react12.useEffect)(() => {
setRate(rating);
}, [rating]);
const onRate = (index) => {
setRate(index + 1);
Haptics.selectionAsync();
setTimeout(() => {
setShowReviewsModal(true);
}, 500);
};
const onSubmit = async () => {
setLoading(true);
setShowReviewsModal(false);
_onSubmit && await _onSubmit({ rating: rate, review });
setLoading(false);
};
return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement(import_react_native12.View, { style: styles.root }, loading ? /* @__PURE__ */ import_react12.default.createElement(import_react_native12.ActivityIndicator, null) : [...Array(5)].map((_, index) => /* @__PURE__ */ import_react12.default.createElement(
import_react_native12.TouchableOpacity,
{
key: index,
activeOpacity: 0.9,
onPress: () => {
onRate(index);
}
},
/* @__PURE__ */ import_react12.default.createElement(
import_vector_icons5.Ionicons,
{
style: { marginLeft: 10 },
name: index < rate ? "star" : "star-outline",
size,
color: colors2[color]?.main || color
}
)
))), /* @__PURE__ */ import_react12.default.createElement(
Popup,
{
sheet: true,
open: showReviewsModal,
onClose: () => {
setShowReviewsModal(false);
}
},
/* @__PURE__ */ import_react12.default.createElement(
import_react_native12.View,
{
style: {
alignItems: "center",
marginBottom: 5
}
},
/* @__PURE__ */ import_react12.default.createElement(RatingStars, { rating: rate, size: 24 })
),
/* @__PURE__ */ import_react12.default.createElement(
Typography_default,
{
align: "center",
fontWeight: 700,
variant: "h5",
gutterBottom: 20
},
"Add to your review"
),
/* @__PURE__ */ import_react12.default.createElement(import_react_native12.View, { style: styles.inputCon }, /* @__PURE__ */ import_react12.default.createElement(
import_react_native12.TextInput,
{
style: styles.input,
multiline: true,
value: review,
onChangeText: (text) => setReview(text),
placeholder: "Type review here..",
verticalAlign: "top"
}
)),
/* @__PURE__ */ import_react12.default.createElement(
Button_default,
{
gutterBottom: 40,
title: "Submit Review",
loading,
disabled: loading,
onPress: () => {
onSubmit();
}
}
)
));
};
var RatingStars = ({
rating = 0,
size = 16,
color = "#FFD700",
inactiveColor = "textSecondary"
}) => {
const colors2 = useColors();
const styles = import_react_native_size_matters9.ScaledSheet.create({
root: {
flexDirection: "row",
alignItems: "center"
}
});
return /* @__PURE__ */ import_react12.default.createElement(import_react_native12.View, { style: styles.root }, [...Array(Math.floor(rating))].map((_, index) => /* @__PURE__ */ import_react12.default.createElement(
import_vector_icons5.Ionicons,
{
key: index,
name: "star",
size,
color: colors2[color]?.main || color
}
)), [...Array(5 - Math.floor(rating))].map((_, index) => /* @__PURE__ */ import_react12.default.createElement(
import_vector_icons5.Ionicons,
{
key: index,
name: "star",
size,
color: colors2[inactiveColor]?.main || inactiveColor
}
)));
};
// ../src/Components/Grid.tsx
var import_react13 = __toESM(require("react"));
var import_react_native13 = require("react-native");
var import_react_native_size_matters10 = require("react-native-size-matters");
var GridItem = ({
children,
col = 2,
alignItems,
spacing = 1,
style = {}
}) => {
const styles = import_react_native_size_matters10.ScaledSheet.create({
gridItem: {
width: `${100 / col}%`,
padding: (0, import_react_native_size_matters10.ms)(spacing * 10),
alignItems
}
});
return /* @__PURE__ */ import_react13.default.createElement(import_react_native13.View, { children, style: [styles.gridItem, style] });
};
var Grid = ({
children,
spacing = 1,
style = {}
}) => {
const styles = import_react_native_size_matters10.ScaledSheet.create({
grid: {
flexWrap: "wrap",
margin: `${-spacing * 10}@ms`,
flexDirection: "row"
}
});
return /* @__PURE__ */ import_react13.default.createElement(import_react_native13.View, { children, style: [styles.grid, style] });
};
// ../src/Components/Locator.tsx
var import_vector_icons9 = require("@expo/vector-icons");
var import_react17 = __toESM(require("react"));
var import_react_native17 = require("react-native");
// ../src/Components/List.tsx
var import_vector_icons6 = require("@expo/vector-icons");
var import_react14 = __toESM(require("react"));
var import_react_native14 = require("react-native");
var import_react_native_size_matters11 = require("react-native-size-matters");
var ListItem = ({
link = false,
divider = false,
onPress,
index = 1,
style = {},
children
}) => {
const colors2 = useColors();
const styles = import_react_native_size_matters11.ScaledSheet.create({
root: {
flexDirection: "row",
alignItems: "center",
paddingHorizontal: "10@s",
borderBottomColor: colors2.white[2],
borderBottomWidth: divider ? 1 : 0,
paddingVertical: "10@vs"
}
});
return /* @__PURE__ */ import_react14.default.createElement(
import_react_native14.View,
null,
/* @__PURE__ */ import_react14.default.createElement(import_react_native14.TouchableOpacity, { disabled: Boolean(!onPress), onPress }, /* @__PURE__ */ import_react14.default.createElement(import_react_native14.View, { style: { ...styles.root, ...style } }, children, link && /* @__PURE__ */ import_react14.default.createElement(
import_vector_icons6.MaterialIcons,
{
color: colors2.white[5],
style: { marginLeft: "auto" },
name: "arrow-forward-ios",
size: 15
}
)))
);
};
// ../src/Components/TextField.tsx
var import_vector_icons8 = require("@expo/vector-icons");
var import_react16 = __toESM(require("react"));
var import_react_native16 = require("react-native");
var import_react_native_modal_datetime_picker = __toESM(require("react-native-modal-datetime-picker"));
var import_react_native_size_matters13 = require("react-native-size-matters");
// ../src/Components/SelectMenu.tsx
var import_vector_icons7 = require("@expo/vector-icons");
var import_react15 = __toESM(require("react"));
var import_react_native15 = require("react-native");
var import_react_native_safe_area_context5 = require("react-native-safe-area-context");
var import_react_native_size_matters12 = require("react-native-size-matters");
var SelectMenu = ({
open = false,
onClose,
value,
options = [],
onChange,
disableAutoClose = false,
label,
secondary,
helperText,
searchEnabled = false,
searchPlaceholder = "Search"
}) => {
const colors2 = useColors();
const { bottom } = (0, import_react_native_safe_area_context5.useSafeAreaInsets)();
const [search, setSearch] = (0, import_react15.useState)("");
const styles = import_react_native_size_matters12.ScaledSheet.create({
header: {
marginBottom: "20@vs"
},
option: {
paddingHorizontal: "10@s",
paddingVertical: "10@vs",
borderRadius: 8,
flexDirection: "row",
alignItems: "center",
marginBottom: "10@vs"
}
});
const renderItem = (0, import_react15.useCallback)(
({ item }) => /* @__PURE__ */ import_react15.default.createElement(
import_react_native15.TouchableOpacity,
{
style: {
...styles.option,
backgroundColor: item.value === value ? colors2.blue.light + "22" : colors2.white[2]
},
onPress: () => {
onChange(item.value);
if (!disableAutoClose)
onClose();
},
key: item.label
},
item.start && /* @__PURE__ */ import_react15.default.createElement(import_react_native15.View, { style: { marginRight: 10 } }, item.start),
/* @__PURE__ */ import_react15.default.createElement(import_react_native15.View, { style: { flex: 1 } }, /* @__PURE__ */ import_react15.default.createElement(
Typography_default,
{
variant: "body2",
style: {
color: item.value === value ? colors2.blue.light : colors2.black[2]
}
},
item.label
), item.secondary ? /* @__PURE__ */ import_react15.default.createElement(
Typography_default,
{
variant: "body2",
style: {
marginTop: 2,
color: item.value === value ? colors2.blue.light : colors2.white[5]
}
},
item.secondary
) : null),
value === item.value && /* @__PURE__ */ import_react15.default.createElement(
import_vector_icons7.MaterialIcons,
{
name: "check",
color: colors2.blue.light,
size: 24,
style: { marginLeft: "auto" }
}
)
),
[value, colors2]
);
return /* @__PURE__ */ import_react15.default.createElement(
Popup,
{
open,