浏览代码

Feature: Menu component start.

lfabl 1 月之前
父节点
当前提交
e1793bc459

+ 33 - 7
example/src/pages/home/index.tsx

@@ -1,6 +1,6 @@
 import {
-    useEffect,
-    useLayoutEffect
+    useLayoutEffect,
+    useEffect
 } from "react";
 import {
     Image,
@@ -14,10 +14,8 @@ import {
     NCoreUIKitMenu,
     PageContainer,
     ThemeSwitcher,
-    AvatarGroup,
     RowCard,
     Button,
-    Avatar,
     Text
 } from "ncore-ui-kit";
 import {
@@ -46,9 +44,37 @@ const Home = () => {
 
     useEffect(() => {
         NCoreUIKitMenu.load({
-            buttons: [{
-                title: "Ana Sayfa"
-            }],
+            siteLogoProps: {
+                imageUrl: "https://www.nibgat.com/assets/images/logo.png",
+                onPress: () => {
+                    navigation.navigate("Home");
+                },
+                imageProps: {
+                    resizeMode: "stretch"
+                },
+                imageSpace: "spacingLg",
+                isWorkWithAction: true,
+                subTitle: "Core Tech",
+                title: "NİBGAT®"
+            },
+            buttons: [
+                {
+                    redirectMain: "Home",
+                    isCollabsable: true,
+                    title: "Ana Sayfa",
+                    subButtons: [
+                        {
+                            title: "Text",
+                            redirectMain: "TextPage"
+                        }
+                    ]
+                },
+                {
+                    title: "Text",
+                    redirectMain: "TextPage"
+                }
+            ],
+            navigation,
             id: "test"
         });
     }, []);

+ 0 - 14
example/web/index.ts

@@ -1,14 +0,0 @@
-import {
-    type RootTag,
-    AppRegistry
-} from "react-native";
-import {
-    name as appName
-} from "./app.json";
-import App from "../src/index";
-
-AppRegistry.registerComponent(appName, () => App);
-AppRegistry.runApplication(appName, {
-    initialProps: {},
-    rootTag: document.getElementById("app-root") as unknown as RootTag
-});

+ 18 - 0
example/web/index.tsx

@@ -0,0 +1,18 @@
+import {
+    createRoot
+} from "react-dom/client";
+import App from "../src/index";
+
+const originalWarn = console.warn;
+console.warn = (...args) => {
+    if (typeof args[0] === "string" && (
+        args[0].includes("pointerEvents") ||
+        args[0].includes("useNativeDriver") ||
+        args[0].includes("TouchableWithoutFeedback") ||
+        args[0].includes("Cannot record touch")
+    )) return;
+    originalWarn(...args);
+};
+
+const root = createRoot(document.getElementById("app-root")!);
+root.render(<App />);

+ 1 - 1
example/web/package.json

@@ -1,7 +1,7 @@
 {
     "name": "ncore-ui-kit-example-web",
     "version": "1.0.0-pre-alpha.0",
-    "main": "index.ts",
+    "main": "index.tsx",
     "type": "commonjs",
     "private": true,
     "scripts": {

+ 21 - 24
example/web/public/index.html

@@ -1,27 +1,24 @@
 <!DOCTYPE html>
 <html>
-<head>
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width, initial-scale=1" />
-  <link
-      rel="stylesheet"
-      href="https://fonts.nibgat.com/ncore.css"
-  />
-  <title>React Native Web Test</title>
-  <style>
-    /* Uygulamanın tüm ekrana yayılması için */
-    html, body, #app-root {
-      height: 100%;
-      margin: 0;
-      padding: 0;
-      display: flex;
-      flex-direction: column;
-    }
-  </style>
-</head>
-<body>
-  <div id="app-root"></div>
-  
-  <script src="/bundle.web.js"></script>
-</body>
+    <head>
+        <meta charset="utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <link
+            rel="stylesheet"
+            href="https://fonts.nibgat.com/ncore.css"
+        />
+        <title>React Native Web Test</title>
+        <style>
+            html, body, #app-root {
+                flex-direction: column;
+                display: flex;
+                height: 100%;
+                padding: 0;
+                margin: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <div id="app-root"></div>
+    </body>
 </html>

+ 5 - 2
example/web/webpack.config.js

@@ -13,7 +13,7 @@ const rootDirectory = path.resolve(__dirname, "../../");
 const babelLoaderConfiguration = {
     test: /\.(tsx|ts|js|jsx)$/,
     include: [
-        path.resolve(appDirectory, "index.ts"),
+        path.resolve(appDirectory, "index.tsx"),
         path.resolve(srcDirectory, "index.tsx"),
         path.resolve(srcDirectory),
 
@@ -59,7 +59,7 @@ const imageLoaderConfiguration = {
 
 module.exports = {
     entry: [
-        path.resolve(appDirectory, "index.ts")
+        path.resolve(appDirectory, "index.tsx")
     ],
     mode: "development",
     devtool: "source-map",
@@ -72,6 +72,7 @@ module.exports = {
         port: 3000,
         historyApiFallback: true,
         client: {
+            logging: "none",
             overlay: {
                 errors: true,
                 warnings: false
@@ -125,6 +126,8 @@ module.exports = {
         new webpack.DefinePlugin({
             "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
             __DEV__: JSON.stringify(process.env.NODE_ENV !== "production"),
+            "__REACT_DEVTOOLS_GLOBAL_HOOK__": "({ isDisabled: true })",
+            "process.env.EXPO_OS": JSON.stringify("web"),
             "process.env": JSON.stringify({})
         }),
         new ESLintPlugin({

+ 3 - 2
package.json

@@ -99,6 +99,7 @@
         "@types/jest": "29.5.13",
         "@types/node": "25.9.3",
         "@types/react": "19.2.0",
+        "@types/react-dom": "19.2.3",
         "@types/react-native": "0.73.0",
         "@types/react-test-renderer": "19.1.0",
         "babel-loader": "10.1.1",
@@ -107,7 +108,7 @@
         "babel-preset-expo": "56.0.15",
         "copy-webpack-plugin": "11.0.0",
         "copyfiles": "2.4.1",
-        "cross-env": "^10.1.0",
+        "cross-env": "10.1.0",
         "del-cli": "6.0.0",
         "eslint": "9.37.0",
         "eslint-import-resolver-typescript": "4.4.4",
@@ -207,7 +208,7 @@
     "dependencies": {
         "lucide-react-native": "1.16.0",
         "moment": "https://git.nibgat.space/nibgat-community/moment.git",
-        "ncore-context": "1.0.7",
+        "ncore-context": "1.0.8",
         "react-native-safe-area-context": "5.5.2",
         "react-native-svg": "15.15.5",
         "rrule": "https://git.nibgat.space/nibgat-community/rrule.git"

+ 5 - 5
src/components/bottomSheet/index.tsx

@@ -28,18 +28,18 @@ import {
     useSafeAreaInsets
 } from "react-native-safe-area-context";
 import {
-    safeGlobal,
-    webStyle,
     type RefForwardingComponent,
-    type SafePointerEvent
+    type SafePointerEvent,
+    safeGlobal
 } from "../../types";
 import type {
     IModalRef
 } from "../modal/type";
 import {
     windowHeight,
-    uuid,
-    windowWidth
+    windowWidth,
+    webStyle,
+    uuid
 } from "../../utils";
 import Modal from "../modal";
 

+ 1 - 1
src/components/header/index.tsx

@@ -27,7 +27,7 @@ import Text from "../text";
 
 const Header = <T extends NavigationType>({
     backgroundColor = "default" as keyof NCoreUIKit.ContainerContentColors,
-    isWrapSafeareaContext = false,
+    isWrapSafeareaContext = true,
     renderTitle: renderTitleProp,
     renderRight: renderRightProp,
     safeAreaViewBackgroundColor,

+ 3 - 5
src/components/header/stylesheet.ts

@@ -7,11 +7,11 @@ import type {
     HeaderDynamicStyleType
 } from "./type";
 import {
-    type Mutable,
-    webStyle
+    type Mutable
 } from "../../types";
 import {
-    windowHeight
+    windowHeight,
+    webStyle
 } from "../../utils";
 
 const stylesheet = StyleSheet.create({
@@ -23,13 +23,11 @@ const stylesheet = StyleSheet.create({
         position: "relative",
         minHeight: 100,
         width: "100%",
-        flex: 1,
         ...webStyle({
             userSelect: "none"
         })
     },
     safeAreaViewContainer: {
-        flex: 1
     },
     titleContainer: {
         justifyContent: "center",

+ 12 - 0
src/components/index.ts

@@ -158,6 +158,18 @@ export {
     default as AvatarGroup
 } from "./avatarGroup";
 
+export {
+    default as Menu
+} from "./menu";
+
+export {
+    default as SiteLogo
+} from "./siteLogo";
+
+export {
+    default as Seperator
+} from "./seperator";
+
 export type {
     EnterMarkdownTypes,
     CodeMarkdownTypes,

+ 235 - 19
src/components/menu/index.tsx

@@ -4,14 +4,17 @@ import {
     forwardRef,
     useEffect,
     useState,
+    Fragment,
     useRef
 } from "react";
 import {
+    Platform,
     Animated,
     Easing,
     View
 } from "react-native";
 import type {
+    MenuButton,
     IMenuRef
 } from "./type";
 import type IMenuProps from "./type";
@@ -24,21 +27,39 @@ import {
 import type {
     RefForwardingComponent
 } from "../../types";
-import Modal from "../modal";
+import {
+    ChevronRight as ChevronRightIcon,
+    ChevronLeft as ChevronLeftIcon,
+    ChevronDown as ChevronDownIcon
+} from "lucide-react-native";
+import {
+    SafeAreaView
+} from "react-native-safe-area-context";
 import {
     Portal
 } from "../../helpers/portalize";
+import Seperator from "../seperator";
+import SiteLogo from "../siteLogo";
+import RowCard from "../rowCard";
+import Modal from "../modal";
 
 const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
-    portalName = "menu-system",
+    isWorkWithSafeAreaView = true,
     isWorkWithAnimation = true,
+    renderHeader: RenderHeader,
+    renderFooter: RenderFooter,
+    portalName = "menu-system",
     isWorkWithPortal = true,
     isWorkWithModal = true,
+    close: closeAction,
+    siteLogoProps,
     customTheme,
+    navigation,
     modalProps,
     isCollabs,
     onClosed,
     onOpened,
+    buttons,
     onClose,
     onOpen,
     style,
@@ -51,6 +72,8 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
     } = NCoreUIKitTheme.useContext(customTheme);
 
     const {
+        headerContainer: headerContainerDynamicStyle,
+        seperator: seperatorDynamicStyle,
         container: containerDynamicStyle
     } = useStyles({
         colors,
@@ -70,10 +93,10 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
     const [
         isActive,
         setIsActive
-    ] = useState(measures === null ? true : isCollabs);
+    ] = useState(false);
 
     const animatedX = useRef(new Animated.Value(0)).current;
-    console.log("aha da ranza:", id);
+
     useImperativeHandle(
         ref,
         () => ({
@@ -84,19 +107,17 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
     );
 
     useEffect(() => {
-        console.log("z", new Date().toISOString());
         if(measures !== null) {
             animatedX.setValue(measures * -1);
 
             if(!isOpacityVisible) setIsOpacityVisible(true);
-            console.log("x", new Date().toISOString());
+
             if(isActive) setIsActive(false);
         }
     }, [measures]);
 
     useEffect(() => {
-        console.log("y", new Date().toISOString(), isCollabs);
-        setIsActive(isCollabs);
+        if(isCollabs !== undefined) setIsActive(isCollabs);
     }, [isCollabs]);
 
     useLayoutEffect(() => {
@@ -162,7 +183,7 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
         });
 
         Animated.timing(animatedX, {
-            useNativeDriver: true,
+            useNativeDriver: Platform.OS !== "web",
             easing: Easing.linear,
             duration: 300,
             toValue: 0
@@ -183,8 +204,8 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
         });
 
         Animated.timing(animatedX, {
+            useNativeDriver: Platform.OS !== "web",
             toValue: measures! * -1,
-            useNativeDriver: true,
             easing: Easing.linear,
             duration: 300
         }).start(({
@@ -198,6 +219,207 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
         });
     };
 
+    const renderHeader = () => {
+        if(RenderHeader) {
+            return <RenderHeader/>;
+        }
+
+        return <View
+            style={[
+                stylesheet.headerContainer,
+                headerContainerDynamicStyle
+            ]}
+        >
+            <SiteLogo
+                {...siteLogoProps}
+            />
+            <Seperator
+                style={[
+                    stylesheet.seperator,
+                    seperatorDynamicStyle
+                ]}
+            />
+        </View>;
+    };
+
+    const isPageActive = ((buttonItem: MenuButton) => {
+        const state = navigation.getState();
+        const currentRoute = state?.routes?.[state.index];
+
+        if(!currentRoute) return false;
+
+        if(currentRoute.state) {
+            const nestedRoute = currentRoute.state.routes?.[currentRoute.state.index];
+            return nestedRoute?.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
+        } else if(currentRoute.name) {
+            return currentRoute.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
+        }
+
+        return currentRoute.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
+    });
+
+    const renderMenuButton = (buttonItem: MenuButton, buttonIndex: number) => {
+        const [
+            isCollabs,
+            setIsCollabs
+        ] = useState(buttonItem.isCollabs);
+
+        const [
+            measure,
+            setMeasure
+        ] = useState<null | number>(null);
+
+        const [
+            isPActive,
+            setIsPActive
+        ] = useState(isPageActive(buttonItem));
+
+        const animatedCollabs = useRef(new Animated.Value(0)).current;
+
+        if(buttonItem.isCollabsable) {
+            useLayoutEffect(() => {
+                if(measure === null) return;
+
+                if(isCollabs) {
+                    Animated.timing(animatedCollabs, {
+                        useNativeDriver: Platform.OS !== "web",
+                        toValue: Number(measure),
+                        easing: Easing.linear,
+                        duration: 150
+                    }).start();
+                } else {
+                    Animated.timing(animatedCollabs, {
+                        useNativeDriver: Platform.OS !== "web",
+                        easing: Easing.linear,
+                        duration: 150,
+                        toValue: 0
+                    }).start();
+                }
+            }, [isCollabs]);
+        }
+
+        return <View
+            key={`menu-button-${id}-${buttonIndex}`}
+        >
+            <RowCard
+                {...buttonItem.props}
+                rightIcon={
+                    buttonItem.isCollabsable || buttonItem.isShowRedirectIcon ?
+                        () => {
+                            if(buttonItem.isCollabsable) {
+                                if(isCollabs) {
+                                    return <ChevronDownIcon
+                                        color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
+                                        size={18}
+                                    />;
+                                } else {
+                                    return <ChevronLeftIcon
+                                        color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
+                                        size={18}
+                                    />;
+                                }
+                            } else {
+                                return <ChevronRightIcon
+                                    color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
+                                    size={18}
+                                />;
+                            }
+                        }
+                        :
+                        undefined
+                }
+                backgroundColor={isPActive ? "primary" : undefined}
+                titleColor={isPActive ? "onPrimary" : undefined}
+                title={buttonItem.title}
+                icon={buttonItem.icon}
+                onPress={() => {
+                    if(buttonItem.isCollabsable) {
+                        setIsCollabs(!isCollabs);
+                    } else {
+                        if(buttonItem.redirectMain || buttonItem.redirectSub) {
+                            if(buttonItem.redirectMain && buttonItem.redirectSub) {
+                                navigation.navigate(buttonItem.redirectMain, {
+                                    screen: buttonItem.redirectSub
+                                });
+                            } else if(buttonItem.redirectMain) {
+                                navigation.navigate(buttonItem.redirectMain);
+                            }
+                        }
+
+                        if(buttonItem.props?.onPress) buttonItem.props.onPress();
+                    }
+
+                    setIsPActive(isPageActive(buttonItem));
+
+                    // if(closeAction && !buttonItem.isCollabsable) closeAction();
+                }}
+            />
+            {
+                buttonItem.subButtons && buttonItem.subButtons.length ?
+                    <Animated.View
+                        onLayout={buttonItem.isCollabsable ? (event) => {
+                            const height = event.nativeEvent.layout.height;
+
+                            if(height !== 0 && measure === null) setMeasure(height);
+                        } : undefined}
+                        style={[
+                            {
+                                height: measure === null ? "auto" : animatedCollabs
+                            }
+                        ]}
+                    >
+                        {buttonItem.subButtons.map((subButtonItem, subButtonIndex) => {
+                            return renderMenuButton(subButtonItem, subButtonIndex);
+                        })}
+                    </Animated.View>
+                    :
+                    null
+            }
+        </View>;
+    };
+
+    const renderButtons = () => {
+        if(!buttons || !buttons.length) {
+            return null;
+        }
+
+        return buttons.map((buttonItem, buttonIndex) => {
+            return renderMenuButton(buttonItem, buttonIndex);
+        });
+    };
+
+    const renderFooter = () => {
+        if(!RenderFooter) {
+            return null;
+        }
+
+        return <RenderFooter/>;
+    };
+
+    const renderSafeAreaContext = () => {
+        if(!isWorkWithSafeAreaView) {
+            return <Fragment>
+                {renderHeader()}
+            </Fragment>;
+        }
+
+        return <SafeAreaView
+            style={[
+                stylesheet.safeAreaView
+            ]}
+        >
+            {renderHeader()}
+            <View
+                style={[
+                    stylesheet.content
+                ]}
+            >
+                {renderButtons()}
+            </View>
+            {renderFooter()}
+        </SafeAreaView>;
+    };
+
     const renderContent = () => {
         return <Animated.View
             {...props}
@@ -218,17 +440,11 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
                 setMeasures(width);
             }}
         >
-            <View
-                style={{
-                    backgroundColor: "red",
-                    height: 300,
-                    width: 100
-                }}
-            />
+            {renderSafeAreaContext()}
         </Animated.View>;
     };
 
-    if(isWorkWithModal) {
+    if(isWorkWithModal && measures !== null) {
         return <Modal
             {...modalProps}
             isWorkWithPortal={isWorkWithPortal}
@@ -244,7 +460,7 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
         </Modal>;
     }
 
-    if(isWorkWithPortal) {
+    if(isWorkWithPortal && measures !== null) {
         return <Portal
             name={portalName}
         >

+ 39 - 1
src/components/menu/stylesheet.ts

@@ -1,6 +1,7 @@
 import {
+    type ViewStyle,
     StyleSheet,
-    type ViewStyle
+    Platform
 } from "react-native";
 import type {
     MenuDynamicStyle
@@ -11,11 +12,40 @@ import type {
 
 const stylesheet = StyleSheet.create({
     container: {
+        flexDirection: "column",
+        ...Platform.select({
+            web: {
+                minWidth: 280,
+                maxWidth: 340,
+                width: "auto"
+            },
+            default: {
+                width: "82%"
+            }
+        }),
         position: "absolute",
+        display: "flex",
+        height: "100%",
         zIndex: 99997,
         bottom: 0,
         left: 0,
         top: 0
+    },
+    content: {
+        justifyContent: "flex-start",
+        flexDirection: "column",
+        alignItems: "stretch",
+        flex: 1
+    },
+    safeAreaView: {
+        flex: 1
+    },
+    headerContainer: {
+        justifyContent: "center",
+        alignItems: "flex-start",
+        width: "100%"
+    },
+    seperator: {
     }
 });
 
@@ -25,6 +55,14 @@ export const useStyles = ({
 }: MenuDynamicStyle) => {
     const styles = {
         container: {
+            backgroundColor: colors.content.container.default
+        } as Mutable<ViewStyle>,
+        headerContainer: {
+            paddingHorizontal: spaces.spacingMd,
+            paddingTop: spaces.spacingMd
+        } as Mutable<ViewStyle>,
+        seperator: {
+            marginVertical: spaces.spacingMd
         } as Mutable<ViewStyle>
     };
 

+ 29 - 3
src/components/menu/type.ts

@@ -1,6 +1,6 @@
 import type {
     ComponentType,
-    ReactElement
+    ReactNode
 } from "react";
 import type {
     ImageProps,
@@ -10,6 +10,7 @@ import type {
 import type {
     NCoreUIKitIcon
 } from "../../types";
+import type ISiteLogoProps from "../siteLogo/type";
 import type IRowCardProps from "../rowCard/type";
 import type IModalProps from "../modal/type";
 
@@ -30,6 +31,7 @@ export type MenuLogoType = {
 };
 
 export type MenuButton = {
+    isShowRedirectIcon?: NCoreUIKitIcon;
     subButtons?: Array<MenuButton>;
     isCollabsable?: boolean;
     redirectMain?: string;
@@ -37,7 +39,7 @@ export type MenuButton = {
     icon?: NCoreUIKitIcon;
     redirectSub?: string;
     isCollabs?: boolean;
-    title?: string;
+    title: string;
 };
 
 interface IMenuProps {
@@ -48,7 +50,30 @@ interface IMenuProps {
         paletteKey?: keyof NCoreUIKit.PaletteKey;
         themeKey?: keyof NCoreUIKit.ThemeKey;
     };
-    renderFooter?: () => ReactElement;
+    navigation: {
+        navigate: (page: string, config?: {
+            screen: string
+        }) => void;
+        getState: () => {
+        index: number;
+        routes: Array<{
+            params?: Record<string, unknown>;
+            state?: {
+                routes: Array<{
+                    name: string;
+                    key: string;
+                }>;
+                index: number;
+            };
+            name: string;
+            key: string;
+        }>;
+    };
+    };
+    isWorkWithSafeAreaView?: boolean;
+    siteLogoProps?: ISiteLogoProps;
+    renderHeader?: () => ReactNode;
+    renderFooter?: () => ReactNode;
     isWorkWithAnimation?: boolean;
     isShowCollabsButton?: boolean;
     isWorkWithPortal?: boolean;
@@ -69,6 +94,7 @@ interface IMenuProps {
     onClose?: (props: {
         id?: string
     }) => void;
+    close?: () => void;
     onOpen?: (props: {
         id?: string
     }) => void;

+ 4 - 2
src/components/monthSelector/index.tsx

@@ -29,8 +29,7 @@ import {
     NCoreUIKitToast
 } from "../../core/hooks";
 import {
-    type Mutable,
-    webStyle
+    type Mutable
 } from "../../types";
 import {
     ChevronRight as ChevronRightIcon,
@@ -38,6 +37,9 @@ import {
 } from "lucide-react-native";
 import moment from "moment";
 import Text from "../text";
+import {
+    webStyle
+} from "../../utils";
 
 const MONTH_LINES = [
     [

+ 2 - 0
src/components/rowCard/index.tsx

@@ -30,6 +30,7 @@ const RowCard: FC<IRowCardProps> = ({
     rightSubTitleColor,
     leftSubTitleStyle,
     icon: CustomIcon,
+    backgroundColor,
     rightTitleColor,
     rightTitleStyle,
     rightIconStyle,
@@ -63,6 +64,7 @@ const RowCard: FC<IRowCardProps> = ({
         title: titleDynamicStyle
     } = useStyles({
         isTransparentBackground,
+        backgroundColor,
         radiuses,
         subTitle,
         spaces,

+ 2 - 1
src/components/rowCard/stylesheet.ts

@@ -49,13 +49,14 @@ const stylesheet = StyleSheet.create({
 
 export const useStyles = ({
     isTransparentBackground,
+    backgroundColor,
     spaces,
     colors,
     type
 }: RowCardDynamicStyleType) => {
     const styles = {
         container: {
-            backgroundColor: isTransparentBackground ? "transparent" : colors.content.container.mid,
+            backgroundColor: backgroundColor ? colors.content.container[backgroundColor] : isTransparentBackground ? "transparent" : colors.content.container.mid,
             padding: spaces.spacingMd
         } as Mutable<ViewStyle>,
         title: {

+ 8 - 6
src/components/rowCard/type.ts

@@ -7,6 +7,7 @@ import type {
 } from "../../types";
 
 export type RowCardDynamicStyleType = {
+    backgroundColor?: keyof NCoreUIKit.ContainerContentColors;
     radiuses: NCoreUIKit.ActivePalette["radiuses"];
     spaces: NCoreUIKit.ActivePalette["spaces"];
     colors: NCoreUIKit.ActivePalette["colors"];
@@ -27,8 +28,15 @@ type IRowCardProps = {
     rightTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
     leftTitleStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
     rightIconStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
+    backgroundColor?: keyof NCoreUIKit.ContainerContentColors;
     iconStyle?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
     rightSubTitleColor?: keyof NCoreUIKit.TextContentColors;
+    customTheme?: {
+        gapPropagation?: keyof NCoreUIKit.GapPropagationKey;
+        sharpness?: keyof NCoreUIKit.SharpnessKey;
+        paletteKey?: keyof NCoreUIKit.PaletteKey;
+        themeKey?: keyof NCoreUIKit.ThemeKey;
+    };
     style?: StyleProp<ViewStyle>[] | StyleProp<ViewStyle>;
     rightTitleColor?: keyof NCoreUIKit.TextContentColors;
     rightSubTitleVariant?: keyof NCoreUIKit.Typography;
@@ -46,12 +54,6 @@ type IRowCardProps = {
     type?: RowCardType;
     subTitle?: string;
     title: string;
-    customTheme?: {
-        gapPropagation?: keyof NCoreUIKit.GapPropagationKey;
-        sharpness?: keyof NCoreUIKit.SharpnessKey;
-        paletteKey?: keyof NCoreUIKit.PaletteKey;
-        themeKey?: keyof NCoreUIKit.ThemeKey;
-    };
 };
 
 export type {

+ 101 - 0
src/components/seperator/index.tsx

@@ -0,0 +1,101 @@
+import {
+    type FC
+} from "react";
+import {
+    View
+} from "react-native";
+import type ISeperatorProps from "./type";
+import stylesheet, {
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitLocalize,
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import Text from "../text";
+
+const Seperator: FC<ISeperatorProps> = ({
+    direction = "horizontal",
+    isShowTitle,
+    customColor,
+    length,
+    title,
+    style,
+    color,
+    ...props
+}) => {
+    const {
+        borders,
+        colors,
+        spaces
+    } = NCoreUIKitTheme.useContext();
+
+    const {
+        localize
+    } = NCoreUIKitLocalize.useContext();
+
+    const {
+        container: containerDynamicStyle,
+        indicator: indicatorDynamicStyle,
+        title: titleDynamicStyle
+    } = useStyles({
+        customColor,
+        direction,
+        borders,
+        length,
+        colors,
+        spaces,
+        color
+    });
+
+    const renderIndicator = (order: "first" | "last") => {
+        if(order === "first") {
+            if(isShowTitle) {
+                return <View
+                    style={[
+                        stylesheet.indicator,
+                        indicatorDynamicStyle
+                    ]}
+                />;
+            } else {
+                return null;
+            }
+        }
+
+        return <View
+            style={[
+                stylesheet.indicator,
+                indicatorDynamicStyle
+            ]}
+        />;
+    };
+
+    const renderTitle = () => {
+        if(!isShowTitle) {
+            return null;
+        }
+
+        return <Text
+            style={{
+                ...stylesheet.title,
+                ...titleDynamicStyle
+            }}
+        >
+            {title ? title : localize("or")}
+        </Text>;
+    };
+
+    return <View
+        {...props}
+        style={[
+            style,
+            stylesheet.container,
+            containerDynamicStyle
+        ]}
+    >
+        {renderIndicator("first")}
+        {renderTitle()}
+        {renderIndicator("last")}
+    </View>;
+};
+export default Seperator;

+ 70 - 0
src/components/seperator/stylesheet.ts

@@ -0,0 +1,70 @@
+import {
+    type TextStyle,
+    type ViewStyle,
+    StyleSheet
+} from "react-native";
+import type {
+    SeperatorDynamicStyle
+} from "./type";
+import type {
+    Mutable
+} from "../../types";
+
+const stylesheet = StyleSheet.create({
+    container: {
+        justifyContent: "center",
+        alignItems: "center",
+        display: "flex"
+    },
+    indicator: {
+        flex: 1
+    },
+    title: {
+    }
+});
+
+export const useStyles = ({
+    customColor,
+    direction,
+    borders,
+    length,
+    colors,
+    spaces,
+    color
+}: SeperatorDynamicStyle) => {
+    const styles = {
+        container: {
+        } as Mutable<ViewStyle>,
+        indicator: {
+            backgroundColor: customColor ? customColor : color ? colors.content.border[color] : colors.content.border.subtle
+        } as Mutable<ViewStyle>,
+        title: {
+            marginHorizontal: spaces.spacingSm
+        } as Mutable<TextStyle>
+    };
+
+    if(length !== undefined) {
+        if(direction === "horizontal") {
+            styles.container.width = length;
+        } else {
+            styles.container.height = length;
+        }
+    }
+
+    if(direction === "horizontal") {
+        styles.container.flexDirection = "row";
+        styles.container.width = "90%";
+
+        styles.indicator.height = borders.line;
+        styles.indicator.width = "100%";
+    } else {
+        styles.container.flexDirection = "column";
+        styles.container.height = "90%";
+
+        styles.indicator.width = borders.line;
+        styles.indicator.height = "100%";
+    }
+
+    return styles;
+};
+export default stylesheet;

+ 28 - 0
src/components/seperator/type.ts

@@ -0,0 +1,28 @@
+import {
+    type SvgProps
+} from "react-native-svg";
+
+export type SeperatorDynamicStyle = {
+    color?: keyof NCoreUIKit.BorderContentColors;
+    borders: NCoreUIKit.ActivePalette["borders"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    direction?: SeperatorDirectionType;
+    customColor?: string;
+    length?: number;
+};
+
+export type SeperatorDirectionType = "horizontal" | "vertical";
+
+interface ISeperatorProps {
+    color?: keyof NCoreUIKit.BorderContentColors;
+    direction?: SeperatorDirectionType;
+    style?: SvgProps["style"];
+    isShowTitle?: boolean;
+    customColor?: string;
+    length?: number;
+    title?: string;
+}
+export type {
+    ISeperatorProps as default
+};

+ 235 - 0
src/components/siteLogo/index.tsx

@@ -0,0 +1,235 @@
+import {
+    useState
+} from "react";
+import {
+    TouchableOpacity,
+    Image,
+    View
+} from "react-native";
+import type ISiteLogoProps from "./type";
+import stylesheet, {
+    getSiteLogoSize,
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import {
+    Home as HomeIcon
+} from "lucide-react-native";
+import Loading from "../loading";
+import Text from "../text";
+
+const SiteLogo = ({
+    logoBackgroundColor = "default",
+    isShowBorder = false,
+    isCustomImageSize,
+    isWorkWithAction,
+    image: ImageProp,
+    backgroundColor,
+    subTitleVariant,
+    icon: IconProp,
+    size = "large",
+    titleVariant,
+    imageSource,
+    customTheme,
+    borderColor,
+    imageSpace,
+    isDisabled,
+    titleColor,
+    imageProps,
+    isLoading,
+    iconColor,
+    imageUrl,
+    subTitle,
+    onPress,
+    title,
+    style
+}: ISiteLogoProps) => {
+    const {
+        borders,
+        colors,
+        spaces
+    } = NCoreUIKitTheme.useContext(customTheme);
+
+    const currentSize = getSiteLogoSize({
+        spaces,
+        size
+    });
+
+    const [
+        imageLoadError,
+        setImageLoadError
+    ] = useState(false);
+
+    const {
+        contentContainer: contentContainerDynamicStyle,
+        titlesContainer: titlesContainerDynamicStyle,
+        container: containerDynamicStyle,
+        image: imageDynamicStyle,
+        icon: iconDynamicStyle
+    } = useStyles({
+        logoBackgroundColor,
+        isCustomImageSize,
+        image: ImageProp,
+        backgroundColor,
+        isShowBorder,
+        borderColor,
+        currentSize,
+        isDisabled,
+        imageSpace,
+        isLoading,
+        imageUrl,
+        borders,
+        colors,
+        spaces
+    });
+
+    const renderIcon = () => {
+        if(IconProp) {
+            return <IconProp
+                size={currentSize.iconSize}
+                customColor={iconColor}
+                color="default"
+                style={{
+                    ...iconDynamicStyle
+                }}
+            />;
+        }
+
+        return <HomeIcon
+            color={iconColor ? iconColor : colors.content.icon.default}
+            size={currentSize.iconSize}
+            style={{
+                ...iconDynamicStyle
+            }}
+        />;
+    };
+
+    const renderLoading = () => {
+        let loadingColor: keyof NCoreUIKit.IconContentColors = "default";
+
+        if(title) {
+            loadingColor = "onPrimary";
+        } else if(imageUrl || ImageProp) {
+            loadingColor = "mid";
+        }
+
+        return <Loading
+            color={loadingColor}
+        />;
+    };
+
+    const renderContent = () => {
+        if(isLoading) {
+            return renderLoading();
+        }
+
+        if(IconProp) {
+            return renderIcon();
+        }
+
+        if(!ImageProp && !imageUrl) {
+            return renderIcon();
+        }
+
+        if((imageUrl || ImageProp) && imageLoadError) {
+            return renderIcon();
+        }
+
+        if(ImageProp) {
+            return <ImageProp
+                {...imageProps}
+                onError={() => setImageLoadError(true)}
+                height={currentSize.size}
+                width={currentSize.size}
+                style={[
+                    stylesheet.image,
+                    imageDynamicStyle,
+                    imageProps?.style
+                ]}
+            />;
+        }
+
+        if(imageUrl) {
+            return <Image
+                {...imageProps}
+                onError={() => setImageLoadError(true)}
+                height={currentSize.size}
+                width={currentSize.size}
+                source={{
+                    uri: imageUrl,
+                    ...imageSource
+                }}
+                style={[
+                    stylesheet.image,
+                    imageDynamicStyle,
+                    imageProps?.style
+                ]}
+            />;
+        }
+
+        return null;
+    };
+
+    const renderTitles = () => {
+        if(!title) {
+            return null;
+        }
+
+        return <View
+            style={[
+                stylesheet.titlesContainer,
+                titlesContainerDynamicStyle
+            ]}
+        >
+            <Text
+                variant={titleVariant ? titleVariant : currentSize.titleSize}
+                customColor={titleColor}
+                numberOfLines={1}
+                color="high"
+            >
+                {title}
+            </Text>
+            {
+                subTitle ?
+                    <Text
+                        variant={subTitleVariant ? subTitleVariant : currentSize.subTitleSize}
+                        numberOfLines={1}
+                        color="low"
+                    >
+                        {subTitle}
+                    </Text>
+                    :
+                    null
+            }
+        </View>;
+    };
+
+    const renderContentContainer = () => {
+        return <View
+            style={[
+                stylesheet.contentContainer,
+                contentContainerDynamicStyle
+            ]}
+        >
+            {renderContent()}
+        </View>;
+    };
+
+    return <TouchableOpacity
+        disabled={!isWorkWithAction || isDisabled || isLoading}
+        onPress={!isWorkWithAction || isDisabled || isLoading ? undefined : () => {
+            if(onPress) onPress();
+        }}
+        style={[
+            style,
+            stylesheet.container,
+            containerDynamicStyle
+        ]}
+    >
+        {renderContentContainer()}
+        {renderTitles()}
+    </TouchableOpacity>;
+};
+export default SiteLogo;

+ 184 - 0
src/components/siteLogo/stylesheet.ts

@@ -0,0 +1,184 @@
+import {
+    type ImageStyle,
+    type ViewStyle,
+    StyleSheet
+} from "react-native";
+import type {
+    SiteLogoSizeConstantType,
+    SiteLogoDynamicStyleType,
+    SiteLogoMeasuresKeys,
+    SiteLogoSizeType,
+    SiteLogoMeasures
+} from "./type";
+import type {
+    Mutable
+} from "../../types";
+
+export const SITE_LOGO_SIZES: Record<SiteLogoSizeType, SiteLogoMeasuresKeys> = {
+    xxSmall: {
+        subTitleSize: "labelSmallSize",
+        titleSize: "labelSmallSize",
+        iconSize: 18,
+        size: 32
+    },
+    xSmall: {
+        subTitleSize: "labelSmallSize",
+        titleSize: "labelMediumSize",
+        iconSize: 22,
+        size: 40
+    },
+    small: {
+        subTitleSize: "labelMediumSize",
+        titleSize: "labelLargeSize",
+        iconSize: 26,
+        size: 48
+    },
+    medium: {
+        subTitleSize: "labelLargeSize",
+        titleSize: "bodyLargeSize",
+        iconSize: 32,
+        size: 64
+    },
+    large: {
+        titleSize: "headlineSmallSize",
+        subTitleSize: "bodyLargeSize",
+        iconSize: 40,
+        size: 80
+    },
+    xLarge: {
+        subTitleSize: "headlineSmallSize",
+        titleSize: "headlineMediumSize",
+        iconSize: 60,
+        size: 120
+    },
+    xxLarge: {
+        subTitleSize: "headlineMediumSize",
+        titleSize: "displaySmallSize",
+        iconSize: 76,
+        size: 150
+    },
+    xxxLarge: {
+        subTitleSize: "displaySmallSize",
+        titleSize: "displayMediumSize",
+        iconSize: 96,
+        size: 180
+    }
+};
+
+export const getSiteLogoSize = ({
+    size
+}: SiteLogoSizeConstantType): SiteLogoMeasures => {
+    const currentSize = SITE_LOGO_SIZES[size];
+
+    return {
+        subTitleSize: currentSize.subTitleSize,
+        titleSize: currentSize.titleSize,
+        iconSize: currentSize.iconSize,
+        size: currentSize.size
+    };
+};
+
+const stylesheet = StyleSheet.create({
+    container: {
+        justifyContent: "center",
+        flexDirection: "row",
+        alignItems: "center",
+        position: "relative",
+        overflow: "visible",
+        display: "flex"
+    },
+    image: {
+        objectFit: "cover"
+    },
+    icon: {
+    },
+    contentContainer: {
+        justifyContent: "center",
+        flexDirection: "row",
+        alignItems: "center",
+        position: "relative",
+        overflow: "visible",
+        display: "flex"
+    },
+    titlesContainer: {
+        justifyContent: "center",
+        flexDirection: "column",
+        display: "flex"
+    }
+});
+
+export const useStyles = ({
+    logoBackgroundColor,
+    isCustomImageSize,
+    backgroundColor,
+    isShowBorder,
+    borderColor,
+    currentSize,
+    isDisabled,
+    imageSpace,
+    isLoading,
+    imageUrl,
+    borders,
+    colors,
+    spaces,
+    image
+}: SiteLogoDynamicStyleType) => {
+    const styles = {
+        container: {
+        } as Mutable<ViewStyle>,
+        image: {
+        } as Mutable<ImageStyle>,
+        icon: {
+        } as Mutable<ViewStyle>,
+        titlesContainer: {
+            marginLeft: spaces.spacingSm * 1.5
+        } as Mutable<ViewStyle>,
+        contentContainer: {
+        } as Mutable<ViewStyle>
+    };
+
+    if(isCustomImageSize) {
+        styles.image.width = currentSize.size * 3 - (imageSpace ? spaces[imageSpace] : 0);
+        styles.image.height = currentSize.size - (imageSpace ? spaces[imageSpace] : 0);
+
+        styles.contentContainer.borderRadius = currentSize.size / 2;
+        styles.contentContainer.width = currentSize.size * 3;
+        styles.contentContainer.height = currentSize.size;
+    } else {
+        styles.image.borderColor = borderColor && borderColor !== "transparent" ? colors.content.border[borderColor] : logoBackgroundColor ? colors.content.container[logoBackgroundColor] : "transparent";
+
+        styles.image.height = currentSize.size - (imageSpace ? spaces[imageSpace] : 0);
+        styles.image.width = currentSize.size - (imageSpace ? spaces[imageSpace] : 0);
+        styles.image.borderRadius = currentSize.size / 2;
+
+        styles.contentContainer.borderColor = borderColor && borderColor !== "transparent" ? colors.content.border[borderColor] : logoBackgroundColor ? colors.content.container[logoBackgroundColor] : "transparent";
+        styles.contentContainer.backgroundColor = backgroundColor ? backgroundColor === "transparent" ? "transparent" : colors.content.container[backgroundColor] : colors.content.container.subtle;
+
+        styles.contentContainer.borderRadius = currentSize.size / 2;
+        styles.contentContainer.height = currentSize.size;
+        styles.contentContainer.width = currentSize.size;
+    }
+
+    if(isShowBorder) {
+        styles.contentContainer.borderWidth = borders.subtract;
+        styles.image.borderWidth = borders.subtract;
+    }
+
+    if(!image && !imageUrl && !backgroundColor) {
+        styles.contentContainer.backgroundColor = colors.content.container.subtle;
+
+        styles.contentContainer.justifyContent = "center";
+        styles.contentContainer.alignItems = "center";
+    }
+
+    if(isDisabled) {
+        styles.container.opacity = 0.33;
+    }
+
+    if(isLoading) {
+        styles.container.opacity = 0.33;
+    }
+
+    return styles;
+};
+export default stylesheet;

+ 85 - 0
src/components/siteLogo/type.ts

@@ -0,0 +1,85 @@
+import type {
+    ComponentType
+} from "react";
+import {
+    type ImageURISource,
+    type ImageProps,
+    type TextStyle,
+    type StyleProp
+} from "react-native";
+import type {
+    NCoreUIKitIcon
+} from "../../types";
+
+export type SiteLogoDynamicStyleType = {
+    backgroundColor?: keyof NCoreUIKit.ContainerContentColors | "transparent";
+    borderColor?: keyof NCoreUIKit.BorderContentColors | "transparent";
+    logoBackgroundColor: keyof NCoreUIKit.ContainerContentColors;
+    imageSpace?: keyof NCoreUIKit.ActivePalette["spaces"];
+    borders: NCoreUIKit.ActivePalette["borders"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    image?: ComponentType<ImageProps>;
+    currentSize: SiteLogoMeasures;
+    isCustomImageSize?: boolean;
+    isShowBorder?: boolean;
+    isDisabled?: boolean;
+    isLoading?: boolean;
+    imageUrl?: string;
+};
+
+export type SiteLogoMeasuresKeys = {
+    subTitleSize: keyof NCoreUIKit.Typography;
+    titleSize: keyof NCoreUIKit.Typography;
+    iconSize: number;
+    size: number;
+};
+
+export type SiteLogoMeasures = {
+    subTitleSize: keyof NCoreUIKit.Typography;
+    titleSize: keyof NCoreUIKit.Typography;
+    iconSize: number;
+    size: number;
+};
+
+export type SiteLogoSizeConstantType = {
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    size: SiteLogoSizeType;
+};
+
+export type SiteLogoSizeType = "xxSmall" | "xSmall" | "small" | "medium" | "large" | "xLarge" | "xxLarge" | "xxxLarge";
+
+interface ISiteLogoProps {
+    backgroundColor?: keyof NCoreUIKit.ContainerContentColors | "transparent";
+    borderColor?: keyof NCoreUIKit.BorderContentColors | "transparent";
+    logoBackgroundColor?: keyof NCoreUIKit.ContainerContentColors;
+    iconColor?: keyof NCoreUIKit.ProjectColorPalette;
+    customTheme?: {
+        gapPropagation?: keyof NCoreUIKit.GapPropagationKey;
+        sharpness?: keyof NCoreUIKit.SharpnessKey;
+        paletteKey?: keyof NCoreUIKit.PaletteKey;
+        themeKey?: keyof NCoreUIKit.ThemeKey;
+    };
+    style?: StyleProp<TextStyle>[] | StyleProp<TextStyle>;
+    imageSpace?: keyof NCoreUIKit.ActivePalette["spaces"];
+    titleColor?: keyof NCoreUIKit.TextContentColors;
+    subTitleVariant?: keyof NCoreUIKit.Typography;
+    titleVariant?: keyof NCoreUIKit.Typography;
+    image?: ComponentType<ImageProps>;
+    imageSource?: ImageURISource;
+    isCustomImageSize?: boolean;
+    isWorkWithAction?: boolean;
+    imageProps?: ImageProps;
+    size?: SiteLogoSizeType;
+    isShowBorder?: boolean;
+    icon?: NCoreUIKitIcon;
+    isDisabled?: boolean;
+    onPress?: () => void;
+    isLoading?: boolean;
+    imageUrl?: string;
+    subTitle?: string;
+    title?: string;
+}
+export type {
+    ISiteLogoProps as default
+};

+ 4 - 2
src/components/yearSelector/index.tsx

@@ -29,8 +29,7 @@ import {
     NCoreUIKitToast
 } from "../../core/hooks";
 import {
-    type Mutable,
-    webStyle
+    type Mutable
 } from "../../types";
 import {
     ChevronRight as ChevronRightIcon,
@@ -38,6 +37,9 @@ import {
 } from "lucide-react-native";
 import moment from "moment";
 import Text from "../text";
+import {
+    webStyle
+} from "../../utils";
 
 const YEAR_LINES = [
     [

+ 8 - 5
src/context/menu.tsx

@@ -32,8 +32,7 @@ class NCoreUIKitMenu extends NCoreContext<MenuContextType, ConfigType<MenuContex
     };
 
     load = (menuData: MenuDataType) => {
-        console.log("e geldi buu");
-        const currentData = JSON.parse(JSON.stringify(this.state.data));
+        const currentData = this.state.data;
 
         const menuID = menuData.id ? menuData.id : uuid();
 
@@ -156,14 +155,18 @@ class NCoreUIKitMenu extends NCoreContext<MenuContextType, ConfigType<MenuContex
         const {
             data
         } = this.useContext();
-        console.log("nasıl gelmek la bu ?", data);
+
         return <Fragment>
             {children}
             {data.map((item: MenuDataType) => {
-                console.log("hii");
                 return <Menu
-                    key={`NCoreUIKit-Menu-${item.id}}`}
+                    key={`NCoreUIKit-Menu-${item.id}`}
                     id={item.id as string}
+                    close={() => {
+                        this.close({
+                            id: item.id
+                        });
+                    }}
                     onClosed={() => {
                         if(item.onClosed) {
                             item.onClosed({

+ 4 - 1
src/index.tsx

@@ -31,9 +31,11 @@ export {
     AvatarGroup,
     SelectSheet,
     RadioButton,
+    SelectBox,
     StateCard,
     TextInput,
-    SelectBox,
+    Seperator,
+    SiteLogo,
     SnackBar,
     CheckBox,
     Sticker,
@@ -46,6 +48,7 @@ export {
     Header,
     Modal,
     Toast,
+    Menu,
     Chip,
     Text
 } from "./components";

+ 0 - 5
src/types/index.ts

@@ -1,9 +1,6 @@
 import {
     type ForwardRefRenderFunction
 } from "react";
-import {
-    Platform
-} from "react-native";
 import {
     type INCoreUIKitIconCallbackProps
 } from "./icon";
@@ -58,8 +55,6 @@ export type {
     ThemeType
 };
 
-export const webStyle = (styles: Record<string, unknown>): Record<string, unknown> => Platform.OS === "web" ? styles : {};
-
 export type RecursiveRecord = {
   [key: string]: string | RecursiveRecord;
 };

+ 2 - 0
src/utils/index.ts

@@ -8,6 +8,8 @@ const dimensions = Dimensions.get("window");
 export const windowHeight = dimensions.height;
 export const windowWidth = dimensions.width;
 
+export const webStyle = (styles: Record<string, unknown>): Record<string, unknown> => Platform.OS === "web" ? styles : {};
+
 export const uuid = () => {
     return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
         const r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);

+ 4 - 2
src/variants/locales/default.json

@@ -30,7 +30,8 @@
             "cancel": "İptal",
             "daily": "Günlük",
             "search": "Ara",
-            "ok": "Tamam"
+            "ok": "Tamam",
+            "or": "ya da"
         },
         "rruleConfig": {
             "dayNames": [
@@ -133,7 +134,8 @@
             "search": "Search",
             "yearly": "Yearly",
             "daily": "Daily",
-            "ok": "Okey"
+            "ok": "Okey",
+            "or": "or"
         },
         "rruleConfig": {
             "dayNames": [

+ 15 - 5
yarn.lock

@@ -4792,6 +4792,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/react-dom@npm:^19.2.3":
+  version: 19.2.3
+  resolution: "@types/react-dom@npm:19.2.3"
+  peerDependencies:
+    "@types/react": ^19.2.0
+  checksum: 10c0/b486ebe0f4e2fb35e2e108df1d8fc0927ca5d6002d5771e8a739de11239fe62d0e207c50886185253c99eb9dedfeeb956ea7429e5ba17f6693c7acb4c02f8cd1
+  languageName: node
+  linkType: hard
+
 "@types/react-native@npm:0.73.0":
   version: 0.73.0
   resolution: "@types/react-native@npm:0.73.0"
@@ -12893,13 +12902,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ncore-context@npm:1.0.7":
-  version: 1.0.7
-  resolution: "ncore-context@npm:1.0.7"
+"ncore-context@npm:^1.0.8":
+  version: 1.0.8
+  resolution: "ncore-context@npm:1.0.8"
   peerDependencies:
     react: ">= 19.2.3"
     react-dom: ">= 19.2.3"
-  checksum: 10c0/0faff8865544f6418cf1e1f2709cda2fea79127eba4e468cb317eb84b227f5b0979a46fe47e907f5b914e3558a7d30e826a67760848635bf01ba5a6a953f8d84
+  checksum: 10c0/57c3fd21441312960c3705eaf35943056087d761aa872f6eaa255f8e3a359f6d9347f955ab9f6eb4a96e67f8472ce529b71bdf7e4b99f740e75ba98ec2cf3c0c
   languageName: node
   linkType: hard
 
@@ -12946,6 +12955,7 @@ __metadata:
     "@types/jest": "npm:29.5.13"
     "@types/node": "npm:25.9.3"
     "@types/react": "npm:19.2.0"
+    "@types/react-dom": "npm:^19.2.3"
     "@types/react-native": "npm:0.73.0"
     "@types/react-test-renderer": "npm:19.1.0"
     babel-loader: "npm:10.1.1"
@@ -12975,7 +12985,7 @@ __metadata:
     jsonc-eslint-parser: "npm:2.4.1"
     lucide-react-native: "npm:1.16.0"
     moment: "https://git.nibgat.space/nibgat-community/moment.git"
-    ncore-context: "npm:1.0.7"
+    ncore-context: "npm:^1.0.8"
     react: "npm:19.2.3"
     react-dom: "npm:19.2.3"
     react-native: "npm:0.85.3"