Browse Source

Feature: web build added.
Feature: Header component added.

lfabl 4 ngày trước cách đây
mục cha
commit
6ff1922f2e

+ 2 - 0
.gitignore

@@ -53,6 +53,8 @@ node_modules/
 npm-debug.log
 yarn-debug.log
 yarn-error.log
+**/*/dist
+**/dist
 
 # BUCK
 buck-out/

+ 2 - 0
.npmignore

@@ -12,4 +12,6 @@ example
 LICENSE
 CODE_OF_CONDUCT.md
 CONTRIBUTING.md
+**/*/dist
+**/dist
 src

+ 9 - 9
eslint.config.mjs

@@ -139,16 +139,16 @@ export default tseslint.config(
                 version: "detect"
             }
         },
-        languageOptions: {
-            plugins: {
-                "local-rules": {
-                    rules: localRulesPlugin.rules
-                },
-                "react-hooks": reactHooks,
-                import: importPlugin,
-                "jsx-a11y": jsxA11y,
-                react
+        plugins: {
+            "local-rules": {
+                rules: localRulesPlugin.rules
             },
+            "react-hooks": reactHooks,
+            import: importPlugin,
+            "jsx-a11y": jsxA11y,
+            react
+        },
+        languageOptions: {
             globals: {
                 "clearInterval": "readonly",
                 "clearTimeout": "readonly",

+ 35 - 0
example/mobile/global.d.ts

@@ -0,0 +1,35 @@
+import "../../src/types/index";
+import defaultLocaleJSON from "../src/variants/locales/default.json";
+
+declare global {
+    namespace NCoreUIKit {
+        type PaletteNames = "gmcore";
+
+        interface PaletteKey extends Record<PaletteType, unknown>, Record<PaletteNames, unknown> {
+        }
+
+        type ProjectLocalizationL = typeof defaultLocaleJSON[0];
+
+        type GeneratedProjectTranslations = {
+            [K in keyof ProjectLocalizationL["translations"]]: ProjectLocalizationL["translations"][K];
+        };
+
+        interface Translation extends GeneratedTranslations, GeneratedProjectTranslations {
+        }
+        /*
+        type DefaultPaletteL = typeof defaultThemeJSON.palettes[0];
+
+        type SystemDataL = DefaultPaletteL["themes"]["dark"]["system"];
+        type DefaultSystemColorsL = SystemDataL;
+
+        interface SystemColorPalette extends DefaultSystemColors, DefaultSystemColorsL {
+        }
+
+        type ContentDataL = DefaultPaletteL["themes"]["dark"]["content"];
+        type DefaultContentColorsL = ContentDataL;
+
+        interface ContentColorPalette extends DefaultContentColors, DefaultContentColorsL {
+        }
+        */
+    }
+}

+ 8 - 1
example/mobile/tsconfig.json

@@ -1,9 +1,16 @@
 {
     "extends": "../../tsconfig.json",
     "compilerOptions": {
+        "composite": true
     },
+    "references": [
+        {
+            "path": "../../"
+        }
+    ],
     "include": [
         "**/*",
-        "../src/**/*"
+        "../src/**/*",
+        "../src/**/*.json"
     ]
 }

+ 3 - 1
example/src/index.tsx

@@ -1,15 +1,17 @@
 import Navigation from "./navigation";
+import defaultLocaleJSON from "./variants/locales/default.json";
 import {
     useFonts
 } from "expo-font";
 import moment from "moment";
+import "moment/locale/tr";
 import {
     setupNCoreUIKit
 } from "ncore-ui-kit";
-import "moment/locale/tr";
 
 const NCoreUIKitBase = setupNCoreUIKit({
     initialSelectedGapPropagation: "spacious",
+    projectLocales: defaultLocaleJSON,
     initialSelectedTheme: "light"
 });
 

+ 17 - 4
example/src/navigation/index.tsx

@@ -4,8 +4,8 @@ import {
 import {
     createNativeStackNavigator
 } from "@react-navigation/native-stack";
+import TextPage from "../pages/text";
 import Home from "../pages/home";
-import TestSubPage from "../pages/testSubPage";
 
 const RootStack = createNativeStackNavigator();
 
@@ -18,14 +18,27 @@ const RootNav = () => {
             component={Home}
         />
         <RootStack.Screen
-            name="TestSubPage"
-            component={TestSubPage}
+            name="TextPage"
+            component={TextPage}
         />
     </RootStack.Navigator>;
 };
 
 const Navigation = () => {
-    return <NavigationContainer>
+    return <NavigationContainer
+        linking={{
+            prefixes: [
+                "http://localhost:3000",
+                "https://ncore.nibgat.space"
+            ],
+            config: {
+                screens: {
+                    Home: "",
+                    TestSubPage: "text"
+                }
+            }
+        }}
+    >
         <RootNav/>
     </NavigationContainer>;
 };

+ 25 - 630
example/src/pages/home/index.tsx

@@ -1,238 +1,50 @@
 import {
-    Fragment,
-    useState,
-    useRef
+    useLayoutEffect
 } from "react";
-import {
-    View
-} from "react-native";
 import stylesheet from "./stylesheet";
 import {
-    NCoreUIKitBottomSheet,
-    NotificationIndicator,
-    getNCoreUIKitVersion,
-    type IBottomSheetRef,
-    NCoreUIKitSnackBar,
-    NCoreUIKitDialog,
-    NCoreUIKitToast,
+    Header,
+    NCoreUIKitLocalize,
     NCoreUIKitTheme,
-    DateTimePicker,
-    MarkdownViewer,
-    PageContainer,
-    TextAreaInput,
-    BottomSheet,
-    RadioButton,
-    TextInput,
-    SelectBox,
-    StateCard,
-    CheckBox,
-    RowCard,
-    Sticker,
-    Button,
-    Dialog,
-    Switch,
-    Text,
-    Chip
+    PageContainer
 } from "ncore-ui-kit";
 import {
     useNavigation
 } from "@react-navigation/native";
+import type RootStackParamList from "../../navigation/type";
 import type {
     NativeStackNavigationProp
 } from "@react-navigation/native-stack";
-import type RootStackParamList from "../../navigation/type";
-import {
-    ChevronRight as ChevronRightIcon,
-    HomeIcon
-} from "lucide-react-native";
-import moment from "moment";
-
-const X = [
-    {
-        t: "xdfç.öhfdşkhdfşlhkfdşlhkdfşklhjmdfkhl3",
-        p: "ydfguıy8ı*pğ34erdx",
-        n: 90
-    },
-    {
-        t: "3t4uh5ıe6ıo6eıo6eoke6ıoke6ker6kr4ok",
-        p: "y3w46pjbd57ykdr",
-        n: 91
-    },
-    {
-        t: "xr*-0k4wkh-5w40k0*wek95ujk9*",
-        p: "y467o5*3evghe5",
-        n: 92
-    },
-    {
-        t: "x-40*tyg*0w4kyh*w0ko45u*ko0w",
-        p: "y3şçwl78570*fg",
-        n: 93
-    },
-    {
-        t: "*wrüsjh*ü9kws4*h0okdfhdhdfurdkex",
-        p: "yt7ıtot7ot",
-        n: 94
-    },
-    {
-        t: "x2-0*4woy-*w4opyu-*23wou*0wık*0jk",
-        p: "yasfa33",
-        n: 95
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    },
-    {
-        t: "x vmönöpwoı6-pğfş -*235*çda",
-        p: "ydfasdfasf",
-        n: 96
-    }
-];
 
 const Home = () => {
     const {
         colors
     } = NCoreUIKitTheme.useContext();
 
-    const bottomSheetRef = useRef<IBottomSheetRef>(null);
+    const {
+        localize
+    } = NCoreUIKitLocalize.useContext();
 
     const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
 
-    const [
-        isCheckboxActive,
-        setIsCheckboxActive
-    ] = useState<"partially" | "checked" | null>("checked");
-
-    const [
-        isDialogActive,
-        setIsDialogActive
-    ] = useState(false);
-
-    const [
-        isRadioActive,
-        setIsRadioActive
-    ] = useState(false);
+    useLayoutEffect(() => {
+        navigation.setOptions({
+            header: () => <Header
+                title={localize("home") + " dsgpıojsdf ıogjsdoıgjsdg lkjslkgjdskl gjsdklgjsdg asfkasf aslfk aslfşk aslşfkasfaslşkf asfasflşk"}
+                navigation={navigation}
+                isGoBackEnable={true}
+                actions={[
+                    {
+                        onPress: () => {
 
-    const [
-        isSwitchActive,
-        setIsSwitchActive
-    ] = useState(false);
+                        },
+                        size: "medium",
+                        title: "Tamam"
+                    }
+                ]}
+            />
+        });
+    }, []);
 
     return <PageContainer
         scrollViewStyle={stylesheet.container}
@@ -245,424 +57,7 @@ const Home = () => {
                 ...stylesheet.contentContainer
             }
         }}
-        renderOverlays={() => {
-            return <Fragment>
-                <Dialog
-                    isVisible={isDialogActive}
-                    content="etgweı09gı9w0eg"
-                    title="Merhaba Dünya!"
-                    contentJustify="centered"
-                    modalProps={{
-                        isWorkWithPortal: false
-                    }}
-                    onOverlayPress={({
-                        closeAnimation
-                    }) => {
-                        closeAnimation(() => setIsDialogActive(false));
-                    }}
-                    variant="yes-no"
-                    secondaryButtonProps={{
-                        title: "sdfgsdg",
-                        onPress: () => {
-
-                        }
-                    }}
-                    primaryButtonProps={{
-                        onPress: ({
-                            closeAnimation
-                        }) => {
-                            closeAnimation(() => setIsDialogActive(false));
-                        }
-                    }}
-                />
-                <BottomSheet
-                    ref={bottomSheetRef}
-                    renderHeader={() => {
-                        return <View
-                            style={[
-                                {
-                                    backgroundColor: "blue",
-                                    padding: 20
-                                }
-                            ]}
-                        >
-                            <Text>Burası header.</Text>
-                        </View>;
-                    }}
-                    isCanFullScreenOnSwipe={true}
-                    isWorkWithPortal={false}
-                    snapPoint={300}
-                    key="ahmet"
-                >
-                    <Button
-                        title="Open Toast"
-                        variant="filled"
-                        type="warning"
-                        onPress={() => {
-                            NCoreUIKitToast.open({
-                                title: "sdgfsdgsdg",
-                                type: "danger"
-                            });
-                        }}
-                    />
-                    <Button
-                        onPress={() => {
-                            navigation.navigate("TestSubPage");
-                        }}
-                        title="Git."
-                    />
-                    {[
-                        0,
-                        1,
-                        2,
-                        3,
-                        4,
-                        5,
-                        6,
-                        7,
-                        8,
-                        9,
-                        10,
-                        11,
-                        12,
-                        13,
-                        14,
-                        15,
-                        16,
-                        17,
-                        18,
-                        19,
-                        20,
-                        21,
-                        22,
-                        23,
-                        24,
-                        25,
-                        26,
-                        27,
-                        28,
-                        29,
-                        30,
-                        31,
-                        32,
-                        33,
-                        34,
-                        35
-                    ].map((it) => {
-                        return <View
-                            key={`fds-${it}`}
-                            style={{
-                                backgroundColor: `rgb(${it * 10}, ${it > 30 ? it * 5 : "0"}, ${it > 20 ? it * 4 : "0"})`,
-                                height: 150
-                            }}
-                        />;
-                    })}
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                    <Text>Deneme 123</Text>
-                </BottomSheet>
-            </Fragment>;
-        }}
     >
-        <Chip
-            spreadBehaviour="free"
-            title="test"
-            isLoading={false}
-            isDisabled={false}
-            icon={({
-                customColor,
-                style,
-                color,
-                size
-            }) => <HomeIcon
-                color={customColor ? customColor : colors.content.icon[color]}
-                size={size}
-                style={style}
-            />}
-        />
-        <Sticker
-            spreadBehaviour="free"
-            title="test"
-            icon={({
-                style,
-                color,
-                size
-            }) => <HomeIcon
-                color={colors.content.icon[color]}
-                size={size}
-                style={style}
-            />}
-        />
-        <StateCard
-            title="Deneme"
-            subTitle="Bu bir alt metindir ve uzun olması gerekmektedir. Ne kadar uzun olursa o kadar iyidir."
-            icon={({
-                color,
-                size
-            }) => <HomeIcon
-                color={colors.content.icon[color]}
-                size={size}
-            />}
-            action={{
-                title: "Me Action",
-                size: "small",
-                onPress: () => {
-
-                }
-            }}
-        />
-        <DateTimePicker
-            minDate={moment().subtract(2, "years").toDate()}
-            maxDate={moment().add(15, "years").toDate()}
-            isWorkWithRealtime={false}
-            isWorkWithSeconds={true}
-            isCleanEnabled={true}
-            variant="range"
-            initialDateRange={{
-                start: moment().subtract(2, "days").startOf("day").toDate(),
-                end: moment().add(6, "days").endOf("day").toDate()
-            }}
-            initialDate={new Date()}
-        />
-        <MarkdownViewer
-            content={`
-# Merhaba Furkan!.
-
-Nabersin ?
-
-<center>
-<link href="https://www.nibgat.com">
-## Deneme **title** 2
-</link>
-
-\`\`\`
-safasfasfasf
-\`\`\`
-</center>
-iyisindir **umarım.**
-
-\`\`\`
-Ahmet buraya gel.
-
-
-Geldin mi ?
-\`\`\`
-
-<<
-Burası alıntı metnidir.
->>
-
-* Merhaba __madd__e1.
-- Deneme madde2.
-
-[Alt text için deneme](https://static.vecteezy.com/system/resources/thumbnails/060/843/811/small/close-up-of-raindrops-on-leaves-hd-background-luxury-hd-wallpaper-image-trendy-background-illustration-free-photo.jpg)<100%x200>--cover--`}
-        />
-        <NotificationIndicator
-            type="danger"
-            title={53}
-        >
-            <Button
-                size="small"
-                icon={({
-                    color
-                }) => <HomeIcon
-                    color={colors.content.icon[color]}
-                />}
-                onPress={() => {
-
-                }}
-            />
-        </NotificationIndicator>
-        <Switch
-            spreadBehaviour="stretch"
-            isActive={isSwitchActive}
-            title="dsgojksdgpojk"
-            subTitle="SJFAJdfa"
-            isDisabled={false}
-            onPress={() => {
-                setIsSwitchActive(!isSwitchActive);
-            }}
-        />
-        <RowCard
-            title="Merhaba"
-            icon={({
-                color
-            }) => <HomeIcon
-                color={colors.content.icon[color]}
-            />}
-            rightIcon={({
-                color
-            }) => <ChevronRightIcon
-                color={colors.content.icon[color]}
-            />}
-        />
-        <RadioButton
-            isChecked={isRadioActive}
-            title="sadfasfsafasf"
-            isDisabled={false}
-            subTitle="asfgsaf"
-            onPress={() => {
-                setIsRadioActive(!isRadioActive);
-            }}
-        />
-        <CheckBox
-            isChecked={isCheckboxActive}
-            title="sadfasfsafasf"
-            isDisabled={false}
-            subTitle="asfgsaf"
-            onPress={() => {
-                setIsCheckboxActive(isCheckboxActive === "checked" ? null : isCheckboxActive === null ? "partially" : "checked");
-            }}
-        />
-        <TextAreaInput
-            isUpdateOnRealtime={true}
-            spreadBehaviour="stretch"
-            placeholder="efsdg"
-            maxLength={300}
-            title="Merhaba"
-            type="success"
-            isCleanEnabled={true}
-            icon={({
-                color
-            }) => <HomeIcon
-                color={colors.content.icon[color]}
-            />}
-        />
-        <SelectBox
-            keyExtractor={(data, index) => `${data.t}-${index}`}
-            titleExtractor={(data) => data.t}
-            initialSelectedItems={[{
-                __title: X[0]?.t as string,
-                __key: `${X[0]?.t}-0`
-            }]}
-            subTitle="Deneme Subtitle"
-            // isWorkWithRealtime={false}
-            isWorkWithRealtime={false}
-            spreadBehaviour="baseline"
-            isMultipleSelect={true}
-            isShowSubTitle={true}
-            hintText="Test deneme"
-            isCleanEnabled={true}
-            maxChoice={-1}
-            minChoice={0}
-            isSearchable={true}
-            title="Deneme Box"
-            isRequired={true}
-            data={X}
-            onMoreLoad={(props) => {
-                console.log("More Loaded:", props);
-            }}
-        />
-        <TextInput
-            variant="hidden"
-            placeholder="dsagdsag"
-        />
-        <Text>Version: v{getNCoreUIKitVersion()}</Text>
-        <Button
-            onPress={() => {
-                navigation.navigate("TestSubPage");
-            }}
-            title="Open Test Sub Page"
-            variant="filled"
-            spreadBehaviour="stretch"
-        />
-        <Button
-            onPress={() => {
-                bottomSheetRef.current?.open();
-            }}
-            type="success"
-            title="Open Local BottomSheet"
-            variant="filled"
-        />
-        <Button
-            onPress={() => {
-                NCoreUIKitBottomSheet.open({
-                    children: <View>
-                        <Text>Deneme 123</Text>
-                        <Text>Deneme 123</Text>
-                        <Text>Deneme 123</Text>
-                        <Text>Deneme 123</Text>
-                        <Text>Deneme 123</Text>
-                        <Text>Deneme 123</Text>
-                    </View>
-                });
-            }}
-            type="success"
-            title="Open BottomSheet"
-            variant="filled"
-        />
-        <Button
-            onPress={() => {
-                setIsDialogActive(!isDialogActive);
-            }}
-            type="neutral"
-            title="Open Local Dialog"
-            variant="filled"
-        />
-        <Button
-            title="Open Snackbar"
-            variant="filled"
-            type="danger"
-            onPress={() => {
-                NCoreUIKitSnackBar.open({
-                    title: "sdgdsgs",
-                    icon: ({
-                        color
-                    }) => <HomeIcon color={colors.content.icon[color ? color : "default"]}/>
-                });
-            }}
-        />
-        <Button
-            onPress={() => {
-                NCoreUIKitDialog.open({
-                    content: "etgweı09gı9w0eg",
-                    title: "Merhaba Dünya!",
-                    isVisible: true,
-                    onOverlayPress: ({
-                        closeAnimation
-                    }) => {
-                        closeAnimation();
-                    },
-                    variant: "info",
-                    secondaryButtonProps: {
-                        title: "sdfgsdg",
-                        onPress: () => {
-
-                        }
-                    },
-                    primaryButtonProps: {
-                        onPress: ({
-                            closeAnimation
-                        }) => {
-                            closeAnimation();
-                        }
-                    }
-                });
-            }}
-            type="neutral"
-            title="Open Dialog"
-            variant="filled"
-        />
-        <Button
-            title="Open Toast"
-            variant="filled"
-            type="warning"
-            onPress={() => {
-                NCoreUIKitToast.open({
-                    title: "sdgfsdgsdafs sdlşlgkdfşiklh",
-                    subTitle: "tr9uıdgfss 0dgklsd",
-                    isShowAction: true,
-                    icon: ({
-                        color
-                    }) => <HomeIcon color={colors.content.icon[color ? color : "default"]}/>
-                });
-            }}
-        />
     </PageContainer>;
 };
 export default Home;

+ 0 - 61
example/src/pages/testSubPage/index.tsx

@@ -1,61 +0,0 @@
-import {
-    useRef
-} from "react";
-import {
-    View
-} from "react-native";
-import stylesheet from "./stylesheet";
-import {
-    type IBottomSheetRef,
-    PageContainer,
-    BottomSheet,
-    Button,
-    Text
-} from "ncore-ui-kit";
-
-const TestSubPage = () => {
-    const bottomSheetRef = useRef<IBottomSheetRef>(null);
-
-    return <PageContainer
-        style={[
-            stylesheet.container
-        ]}
-    >
-        <Text>This is test sub page.</Text>
-        <Button
-            onPress={() => {
-                bottomSheetRef.current?.open();
-            }}
-            type="success"
-            title="Ahmet"
-            variant="filled"
-        />
-        <BottomSheet
-            isCanFullScreenOnSwipe={true}
-            isWorkWithPortal={false}
-            ref={bottomSheetRef}
-            snapPoint={300}
-        >
-            <Button
-                onPress={() => {
-
-                }}
-                title="Git."
-            />
-            <View
-                style={{
-                    backgroundColor: "red",
-                    height: 2400
-                }}
-            />
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-            <Text>Deneme 123</Text>
-        </BottomSheet>
-    </PageContainer>;
-};
-export default TestSubPage;

+ 17 - 0
example/src/pages/text/index.tsx

@@ -0,0 +1,17 @@
+import stylesheet from "./stylesheet";
+import {
+    PageContainer,
+    Text
+} from "ncore-ui-kit";
+
+const TextPage = () => {
+    return <PageContainer
+        style={[
+            stylesheet.container
+        ]}
+    >
+        <Text>This is test sub page.</Text>
+
+    </PageContainer>;
+};
+export default TextPage;

+ 0 - 0
example/src/pages/testSubPage/stylesheet.ts → example/src/pages/text/stylesheet.ts


+ 2 - 1
example/src/tsconfig.json

@@ -29,6 +29,7 @@
         "**/*.ts",
         "**/*.tsx",
         "../../src/**/*",
-        "../../src/types/index.ts"
+        "../../src/types/index.ts",
+        "**/*.json"
     ]
 }

+ 16 - 0
example/src/variants/locales/default.json

@@ -0,0 +1,16 @@
+[
+    {
+        "locale": "tr-TR",
+        "isRTL": false,
+        "translations": {
+            "home": "Ana Sayfa"
+        }
+    },
+    {
+        "locale": "en-US",
+        "isRTL": false,
+        "translations": {
+            "home": "Home Page"
+        }
+    }
+]

+ 3 - 2
example/web/package.json

@@ -9,8 +9,9 @@
         "ios": "react-native run-ios",
         "lint": "eslint .",
         "start": "react-native start",
-        "web": "webpack serve --config ./webpack.config.js",
-        "test": "jest"
+        "test": "jest",
+        "web": "webpack serve --mode development --config ./webpack.config.js",
+        "web:build": "cross-env NODE_ENV=production webpack --mode production --config ./webpack.config.js"
     },
     "engines": {
         "node": ">= 22.11.0"

BIN
example/web/src/assets/fonts/Geist-Black.ttf


BIN
example/web/src/assets/fonts/Geist-Bold.ttf


BIN
example/web/src/assets/fonts/Geist-ExtraBold.ttf


BIN
example/web/src/assets/fonts/Geist-ExtraLight.ttf


BIN
example/web/src/assets/fonts/Geist-Light.ttf


BIN
example/web/src/assets/fonts/Geist-Medium.ttf


BIN
example/web/src/assets/fonts/Geist-Regular.ttf


BIN
example/web/src/assets/fonts/Geist-SemiBold.ttf


BIN
example/web/src/assets/fonts/Geist-Thin.ttf


+ 3 - 2
example/web/tsconfig.json

@@ -6,9 +6,10 @@
         ]
     },
     "include": [
-        "**/*.ts",
+        "../src/**/*",
+        "**/*.json",
         "**/*.tsx",
-        "../src/**/*"
+        "**/*.ts"
     ],
     "exclude": [
         "**/node_modules",

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

@@ -1,8 +1,10 @@
 /* eslint-disable */
 
-const path = require("path");
-const webpack = require("webpack");
 const HtmlWebpackPlugin = require("html-webpack-plugin");
+const ESLintPlugin = require("eslint-webpack-plugin");
+const CopyPlugin = require("copy-webpack-plugin");
+const webpack = require("webpack");
+const path = require("path");
 
 const appDirectory = path.resolve(__dirname, "./");
 const srcDirectory = path.resolve(__dirname, "../src");
@@ -121,10 +123,40 @@ module.exports = {
             filename: "index.html"
         }),
         new webpack.DefinePlugin({
+            "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
             __DEV__: JSON.stringify(process.env.NODE_ENV !== "production"),
-
-            "process.env": JSON.stringify({}),
-            "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development")
+            "process.env": JSON.stringify({})
+        }),
+        new ESLintPlugin({
+            overrideConfigFile: path.resolve(rootDirectory, "eslint.config.mjs"),
+            failOnError: process.env.NODE_ENV === "production",
+            exclude: [
+                path.resolve(rootDirectory, "node_modules"),
+                path.resolve(appDirectory, "dist")
+            ],
+            eslintPath: "eslint/use-at-your-own-risk",
+            configType: "flat",
+            emitWarning: true,
+            extensions: [
+                "tsx",
+                "jsx",
+                "ts",
+                "js"
+            ]
+        }),
+        new CopyPlugin({
+            patterns: [
+                {
+                    globOptions: {
+                        ignore: [
+                            "**/index.html"
+                        ]
+                    },
+                    noErrorOnMissing: true,
+                    from: "public",
+                    to: "."
+                }
+            ]
         })
     ],
     resolve: {

+ 3 - 0
package.json

@@ -105,7 +105,9 @@
         "babel-plugin-module-resolver": "5.0.3",
         "babel-plugin-react-native-web": "0.21.2",
         "babel-preset-expo": "56.0.15",
+        "copy-webpack-plugin": "11.0.0",
         "copyfiles": "2.4.1",
+        "cross-env": "^10.1.0",
         "del-cli": "6.0.0",
         "eslint": "9.37.0",
         "eslint-import-resolver-typescript": "4.4.4",
@@ -116,6 +118,7 @@
         "eslint-plugin-react": "7.37.5",
         "eslint-plugin-react-hooks": "7.0.0",
         "eslint-plugin-react-native": "5.0.0",
+        "eslint-webpack-plugin": "5.0.1",
         "expo": "56.0.11",
         "expo-font": "56.0.6",
         "expo-status-bar": "56.0.4",

+ 279 - 0
src/components/header/index.tsx

@@ -0,0 +1,279 @@
+import {
+    useLayoutEffect,
+    useState,
+    Fragment
+} from "react";
+import {
+    View
+} from "react-native";
+import type IHeaderProps from "./type";
+import type {
+    NavigationType
+} from "./type";
+import stylesheet, {
+    useStyles
+} from "./stylesheet";
+import {
+    NCoreUIKitTheme
+} from "../../core/hooks";
+import {
+    ChevronLeftIcon
+} from "lucide-react-native";
+import {
+    SafeAreaView
+} from "react-native-safe-area-context";
+import Button from "../button";
+import Text from "../text";
+
+const Header = <T extends NavigationType>({
+    backgroundColor = "default" as keyof NCoreUIKit.ContainerContentColors,
+    isWrapSafeareaContext = false,
+    renderTitle: renderTitleProp,
+    renderRight: renderRightProp,
+    safeAreaViewBackgroundColor,
+    renderLeft: renderLeftProp,
+    safeAreaViewStyle,
+    isGoBackEnable,
+    customTheme,
+    titleProps,
+    navigation,
+    children,
+    actions,
+    title,
+    style,
+    ...props
+}: IHeaderProps<T>) => {
+    const {
+        colors,
+        spaces
+    } = NCoreUIKitTheme.useContext(customTheme);
+
+    const [
+        opacity,
+        setOpacity
+    ] = useState(false);
+
+    const [
+        leftContainerWidth,
+        setLeftContainerWidth
+    ] = useState<null | number>(null);
+
+    const [
+        rightContainerWidth,
+        setRightContainerWidth
+    ] = useState<null | number>(null);
+
+    useLayoutEffect(() => {
+        if(!opacity && leftContainerWidth !== null && rightContainerWidth !== null) {
+            setOpacity(true);
+        }
+    }, [
+        rightContainerWidth,
+        leftContainerWidth
+    ]);
+
+    const {
+        safeAreaView: safeAreaViewDynamicStyle,
+        content: contentDynamicStyle
+    } = useStyles({
+        safeAreaViewBackgroundColor,
+        backgroundColor,
+        spaces,
+        colors
+    });
+
+    const renderLeft = () => {
+        if(renderLeftProp) {
+            return <View
+                onLayout={(event) => {
+                    const xW = event.nativeEvent.layout.width;
+
+                    setLeftContainerWidth(xW);
+                }}
+                style={[
+                    stylesheet.leftContainer
+                ]}
+            >
+                {renderLeftProp({
+                    navigation
+                })}
+            </View>;
+        }
+
+        if(!isGoBackEnable || !navigation) {
+            if(leftContainerWidth === null) setLeftContainerWidth(0);
+            return null;
+        }
+
+        return <View
+            onLayout={(event) => {
+                const xW = event.nativeEvent.layout.width;
+
+                setLeftContainerWidth(xW);
+            }}
+            style={[
+                stylesheet.leftContainer
+            ]}
+        >
+            <Button
+                spreadBehaviour="free"
+                variant="ghost"
+                type="neutral"
+                size="small"
+                icon={({
+                    color,
+                    size
+                }) => {
+                    return <ChevronLeftIcon
+                        color={colors.content.icon[color]}
+                        size={size + 15}
+                    />;
+                }}
+                onPress={() => {
+                    if(navigation) {
+                        (navigation as unknown as { goBack: () => void }).goBack();
+                    }
+                }}
+            />
+        </View>;
+    };
+
+    const renderRight = () => {
+        if(renderRightProp) {
+            return <View
+                onLayout={(event) => {
+                    const xW = event.nativeEvent.layout.width;
+
+                    setRightContainerWidth(xW);
+                }}
+                style={[
+                    stylesheet.rightContainer
+                ]}
+            >
+                {renderRightProp({
+                    navigation
+                })}
+            </View>;
+        }
+
+        if(!actions || !actions.length) {
+            if(rightContainerWidth === null) setRightContainerWidth(0);
+            return null;
+        }
+
+        return <View
+            onLayout={(event) => {
+                const xW = event.nativeEvent.layout.width;
+
+                setRightContainerWidth(xW);
+            }}
+            style={[
+                stylesheet.rightContainer
+            ]}
+        >
+            {actions.map((actionItem) => {
+                return <Button
+                    spreadBehaviour="free"
+                    variant="ghost"
+                    type="neutral"
+                    size="small"
+                    {...actionItem}
+                />;
+            })}
+        </View>;
+    };
+
+    const renderTitle = () => {
+        if(renderTitleProp) {
+            return renderTitleProp({
+                navigation
+            });
+        }
+
+        if(!title) {
+            return null;
+        }
+
+        if(leftContainerWidth === null || rightContainerWidth === null) {
+            return null;
+        }
+
+        const sideWidth = leftContainerWidth > rightContainerWidth ? leftContainerWidth : rightContainerWidth;
+
+        return <View
+            style={[
+                stylesheet.titleContainer,
+                {
+                    padding: spaces.spacingMd,
+                    opacity: opacity ? 1 : 0
+                }
+            ]}
+        >
+            {<View
+                style={{
+                    width: sideWidth,
+                    height: 40
+                }}
+            />}
+            <Text
+                variant="headlineSmallSize"
+                numberOfLines={2}
+                {...titleProps}
+                style={{
+                    ...stylesheet.title,
+                    ...titleProps?.style
+                }}
+            >
+                {title}
+            </Text>
+            {<View
+                style={{
+                    width: sideWidth,
+                    height: 40
+                }}
+            />}
+        </View>;
+    };
+
+    const renderContent = () => {
+        return <View
+            {...props}
+            style={[
+                contentDynamicStyle,
+                stylesheet.container,
+                style
+            ]}
+        >
+            {renderTitle()}
+            <View
+                style={[
+                    stylesheet.contentContainer
+                ]}
+            >
+                {renderLeft()}
+                {renderRight()}
+            </View>
+        </View>;
+    };
+
+    const renderWithSafeareaView = () => {
+        return <SafeAreaView
+            style={[
+                safeAreaViewStyle,
+                safeAreaViewDynamicStyle,
+                stylesheet.safeAreaViewContainer
+            ]}
+        >
+            {children ? children : renderContent()}
+        </SafeAreaView>;
+    };
+
+    const renderSafeareaContext = () => {
+        return isWrapSafeareaContext ? renderWithSafeareaView() : <Fragment>
+            {children ? children : renderContent()}
+        </Fragment>;
+    };
+
+    return renderSafeareaContext();
+};
+export default Header;

+ 87 - 0
src/components/header/stylesheet.ts

@@ -0,0 +1,87 @@
+import {
+    type TextStyle,
+    type ViewStyle,
+    StyleSheet
+} from "react-native";
+import type {
+    HeaderDynamicStyleType
+} from "./type";
+import {
+    type Mutable,
+    webStyle
+} from "../../types";
+import {
+    windowHeight
+} from "../../utils";
+
+const stylesheet = StyleSheet.create({
+    container: {
+        maxHeight: windowHeight * 0.10,
+        justifyContent: "center",
+        flexDirection: "row",
+        alignItems: "center",
+        position: "relative",
+        minHeight: 100,
+        width: "100%",
+        flex: 1,
+        ...webStyle({
+            userSelect: "none"
+        })
+    },
+    safeAreaViewContainer: {
+        flex: 1
+    },
+    titleContainer: {
+        justifyContent: "center",
+        flexDirection: "row",
+        alignItems: "center",
+        position: "absolute",
+        alignSelf: "center",
+        bottom: 0,
+        right: 0,
+        left: 0,
+        top: 0
+    },
+    contentContainer: {
+        justifyContent: "space-between",
+        alignItems: "stretch",
+        flexDirection: "row",
+        position: "relative",
+        flex: 1
+    },
+    title: {
+        textAlign: "center",
+        flex: 1,
+        ...webStyle({
+            overflowWrap: "break-word",
+            wordBreak: "break-word"
+        })
+    },
+    rightContainer: {
+    },
+    leftContainer: {
+    }
+});
+
+export const useStyles = ({
+    safeAreaViewBackgroundColor,
+    backgroundColor,
+    spaces,
+    colors
+}: HeaderDynamicStyleType) => {
+    const styles = {
+        safeAreaView: {
+            backgroundColor: safeAreaViewBackgroundColor ? colors.content.container[safeAreaViewBackgroundColor] : colors.content.container[backgroundColor]
+        } as Mutable<ViewStyle>,
+        content: {
+            backgroundColor: colors.content.container[backgroundColor],
+            padding: spaces.spacingMd
+        } as Mutable<ViewStyle>,
+        title: {
+            paddingHorizontal: spaces.spacingMd
+        } as Mutable<TextStyle>
+    };
+
+    return styles;
+};
+export default stylesheet;

+ 52 - 0
src/components/header/type.ts

@@ -0,0 +1,52 @@
+import {
+    type ReactNode
+} from "react";
+import type {
+    StyleProp,
+    ViewStyle
+} from "react-native";
+import type IButtonProps from "../button/type";
+import type ITextProps from "../text/type";
+
+export type HeaderDynamicStyleType = {
+    safeAreaViewBackgroundColor?: keyof NCoreUIKit.ContainerContentColors;
+    backgroundColor: keyof NCoreUIKit.ContainerContentColors;
+    spaces: NCoreUIKit.ActivePalette["spaces"];
+    colors: NCoreUIKit.ActivePalette["colors"];
+};
+
+export type NavigationType = unknown;
+
+export type ActionItem = IButtonProps;
+
+interface IHeaderProps<T> {
+    safeAreaViewBackgroundColor?: keyof NCoreUIKit.ContainerContentColors;
+    backgroundColor?: keyof NCoreUIKit.ContainerContentColors;
+    customTheme?: {
+        gapPropagation?: keyof NCoreUIKit.GapPropagationKey;
+        sharpness?: keyof NCoreUIKit.SharpnessKey;
+        paletteKey?: keyof NCoreUIKit.PaletteKey;
+        themeKey?: keyof NCoreUIKit.ThemeKey;
+    };
+    safeAreaViewStyle?: StyleProp<ViewStyle>;
+    isWrapSafeareaContext?: boolean;
+    style?: StyleProp<ViewStyle>;
+    actions?: Array<ActionItem>;
+    isGoBackEnable?: boolean;
+    titleProps?: ITextProps;
+    renderTitle?: (props: {
+        navigation?: T
+    }) => ReactNode;
+    renderRight?: (props: {
+        navigation?: T
+    }) => ReactNode;
+    renderLeft?: (props: {
+        navigation?: T
+    }) => ReactNode;
+    children?: ReactNode;
+    navigation?: T;
+    title?: string;
+}
+export type {
+    IHeaderProps as default
+};

+ 4 - 0
src/components/index.ts

@@ -138,6 +138,10 @@ export {
     default as Chip
 } from "./chip";
 
+export {
+    default as Header
+} from "./header";
+
 export type {
     EnterMarkdownTypes,
     CodeMarkdownTypes,

+ 4 - 1
src/context/localize.tsx

@@ -109,7 +109,10 @@ class NCoreUIKitLocalize<T extends LocalizeType> extends NCoreContext<LocalizeCo
         const newState: LocalizeContextStateType = {
             activeLocale: currentProjectLocale.locale as keyof NCoreUIKit.LocaleKey,
             // localizeWithObject: this.localizeWithObject,
-            rruleConfig: currentProjectLocale.rruleConfig,
+            rruleConfig: {
+                ...defaultLocale.rruleConfig,
+                ...currentProjectLocale.rruleConfig
+            },
             isRTL: currentProjectLocale.isRTL,
             // localize: this.localize,
             translations: {

+ 1 - 0
src/index.tsx

@@ -38,6 +38,7 @@ export {
     Dialog,
     Switch,
     Button,
+    Header,
     Modal,
     Toast,
     Chip,

+ 5 - 7
src/types/index.ts

@@ -2,8 +2,6 @@ import {
     type ForwardRefRenderFunction
 } from "react";
 import {
-    type StyleProp,
-    type ViewStyle,
     Platform
 } from "react-native";
 import {
@@ -60,7 +58,7 @@ export type {
     ThemeType
 };
 
-export const webStyle = (styles: Record<string, unknown>): StyleProp<ViewStyle> => Platform.OS === "web" ? (styles as StyleProp<ViewStyle>) : {};
+export const webStyle = (styles: Record<string, unknown>): Record<string, unknown> => Platform.OS === "web" ? styles : {};
 
 export type RecursiveRecord = {
   [key: string]: string | RecursiveRecord;
@@ -195,8 +193,8 @@ declare global {
         type Locales = Array<Locale>;
 
         interface Locale {
-            rruleConfig: GeneratedRRuleConfigs;
-            translations: Translation;
+            rruleConfig?: GeneratedRRuleConfigs;
+            translations?: Translation;
             locale: string;
             isRTL: boolean;
         }
@@ -204,11 +202,11 @@ declare global {
         type DefaultLocalization = typeof defaultLocaleJSON[0];
 
         type GeneratedRRuleConfigs = {
-            [K in keyof DefaultLocalization["rruleConfig"]]: DefaultLocalization["rruleConfig"][K];
+            [K in keyof DefaultLocalization["rruleConfig"]]?: DefaultLocalization["rruleConfig"][K];
         };
 
         type GeneratedTranslations = {
-            [K in keyof DefaultLocalization["translations"]]: DefaultLocalization["translations"][K];
+            [K in keyof DefaultLocalization["translations"]]?: DefaultLocalization["translations"][K];
         };
 
         interface Translation extends GeneratedTranslations {

+ 1 - 0
tsconfig.json

@@ -49,6 +49,7 @@
     "exclude": [
         "node_modules",
         "version.mjs",
+        "**/dist",
         "lib"
     ]
 }

+ 109 - 16
yarn.lock

@@ -1842,6 +1842,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@epic-web/invariant@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "@epic-web/invariant@npm:1.0.0"
+  checksum: 10c0/72dbeb026e4e4eb3bc9c65739b91408ca77ab7d603a2494fa2eff3790ec22892c4caba751cffdf30f5ccf0e7ba79c1e9c96cf0a357404b9432bf1365baac23ca
+  languageName: node
+  linkType: hard
+
 "@eslint-community/eslint-utils@npm:^4.5.1, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1":
   version: 4.9.1
   resolution: "@eslint-community/eslint-utils@npm:4.9.1"
@@ -4596,7 +4603,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8":
+"@types/eslint@npm:^9.6.1":
+  version: 9.6.1
+  resolution: "@types/eslint@npm:9.6.1"
+  dependencies:
+    "@types/estree": "npm:*"
+    "@types/json-schema": "npm:*"
+  checksum: 10c0/69ba24fee600d1e4c5abe0df086c1a4d798abf13792d8cfab912d76817fe1a894359a1518557d21237fbaf6eda93c5ab9309143dee4c59ef54336d1b3570420e
+  languageName: node
+  linkType: hard
+
+"@types/estree@npm:*, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8":
   version: 1.0.9
   resolution: "@types/estree@npm:1.0.9"
   checksum: 10c0/3ad3286ca2988cd550dafb8f2ad599c8474868e954fa601a36655bdfefd8039f7c714b8c1c7f2ae219ffbd58bd4660e66fa7479a0120fc02d4777057d4865387
@@ -4717,7 +4734,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
+"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9":
   version: 7.0.15
   resolution: "@types/json-schema@npm:7.0.15"
   checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
@@ -7358,6 +7375,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"copy-webpack-plugin@npm:11.0.0":
+  version: 11.0.0
+  resolution: "copy-webpack-plugin@npm:11.0.0"
+  dependencies:
+    fast-glob: "npm:^3.2.11"
+    glob-parent: "npm:^6.0.1"
+    globby: "npm:^13.1.1"
+    normalize-path: "npm:^3.0.0"
+    schema-utils: "npm:^4.0.0"
+    serialize-javascript: "npm:^6.0.0"
+  peerDependencies:
+    webpack: ^5.1.0
+  checksum: 10c0/a667dd226b26f148584a35fb705f5af926d872584912cf9fd203c14f2b3a68f473a1f5cf768ec1dd5da23820823b850e5d50458b685c468e4a224b25c12a15b4
+  languageName: node
+  linkType: hard
+
 "copyfiles@npm:2.4.1":
   version: 2.4.1
   resolution: "copyfiles@npm:2.4.1"
@@ -7426,6 +7459,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"cross-env@npm:^10.1.0":
+  version: 10.1.0
+  resolution: "cross-env@npm:10.1.0"
+  dependencies:
+    "@epic-web/invariant": "npm:^1.0.0"
+    cross-spawn: "npm:^7.0.6"
+  bin:
+    cross-env: dist/bin/cross-env.js
+    cross-env-shell: dist/bin/cross-env-shell.js
+  checksum: 10c0/834a862db456ba1fedf6c6da43436b123ae38f514fa286d6f0937c14fa83f13469f77f70f2812db041ae2d84f82bac627040b8686030aca27fbdf113dfa38b63
+  languageName: node
+  linkType: hard
+
 "cross-fetch@npm:^3.1.5":
   version: 3.2.0
   resolution: "cross-fetch@npm:3.2.0"
@@ -8662,6 +8708,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-webpack-plugin@npm:5.0.1":
+  version: 5.0.1
+  resolution: "eslint-webpack-plugin@npm:5.0.1"
+  dependencies:
+    "@types/eslint": "npm:^9.6.1"
+    jest-worker: "npm:^29.7.0"
+    micromatch: "npm:^4.0.8"
+    normalize-path: "npm:^3.0.0"
+    schema-utils: "npm:^4.3.0"
+  peerDependencies:
+    eslint: ^8.0.0 || ^9.0.0
+    webpack: ^5.0.0
+  checksum: 10c0/bb20c8584086e9d1114f9830229c08b622ef2a198507c547a37bd6eff250e45f1cb91f202d5af2a6fa5f1ab13600675956564af959eb63e81629fb0c7e7eb6e0
+  languageName: node
+  linkType: hard
+
 "eslint@npm:9.37.0":
   version: 9.37.0
   resolution: "eslint@npm:9.37.0"
@@ -9177,7 +9239,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2, fast-glob@npm:^3.3.3":
+"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2, fast-glob@npm:^3.3.3":
   version: 3.3.3
   resolution: "fast-glob@npm:3.3.3"
   dependencies:
@@ -9753,7 +9815,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"glob-parent@npm:^6.0.2":
+"glob-parent@npm:^6.0.1, glob-parent@npm:^6.0.2":
   version: 6.0.2
   resolution: "glob-parent@npm:6.0.2"
   dependencies:
@@ -9866,6 +9928,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"globby@npm:^13.1.1":
+  version: 13.2.2
+  resolution: "globby@npm:13.2.2"
+  dependencies:
+    dir-glob: "npm:^3.0.1"
+    fast-glob: "npm:^3.3.0"
+    ignore: "npm:^5.2.4"
+    merge2: "npm:^1.4.1"
+    slash: "npm:^4.0.0"
+  checksum: 10c0/a8d7cc7cbe5e1b2d0f81d467bbc5bc2eac35f74eaded3a6c85fc26d7acc8e6de22d396159db8a2fc340b8a342e74cac58de8f4aee74146d3d146921a76062664
+  languageName: node
+  linkType: hard
+
 "globby@npm:^14.0.2":
   version: 14.1.0
   resolution: "globby@npm:14.1.0"
@@ -10320,7 +10395,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.3.1":
+"ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.1":
   version: 5.3.2
   resolution: "ignore@npm:5.3.2"
   checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337
@@ -12877,7 +12952,9 @@ __metadata:
     babel-plugin-module-resolver: "npm:5.0.3"
     babel-plugin-react-native-web: "npm:0.21.2"
     babel-preset-expo: "npm:56.0.15"
+    copy-webpack-plugin: "npm:11.0.0"
     copyfiles: "npm:2.4.1"
+    cross-env: "npm:^10.1.0"
     del-cli: "npm:6.0.0"
     eslint: "npm:9.37.0"
     eslint-import-resolver-typescript: "npm:4.4.4"
@@ -12888,6 +12965,7 @@ __metadata:
     eslint-plugin-react: "npm:7.37.5"
     eslint-plugin-react-hooks: "npm:7.0.0"
     eslint-plugin-react-native: "npm:5.0.0"
+    eslint-webpack-plugin: "npm:5.0.1"
     expo: "npm:56.0.11"
     expo-font: "npm:56.0.6"
     expo-status-bar: "npm:56.0.4"
@@ -12898,7 +12976,6 @@ __metadata:
     lucide-react-native: "npm:1.16.0"
     moment: "https://git.nibgat.space/nibgat-community/moment.git"
     ncore-context: "npm:1.0.7"
-    prettier: "npm:2.8.8"
     react: "npm:19.2.3"
     react-dom: "npm:19.2.3"
     react-native: "npm:0.85.3"
@@ -13876,15 +13953,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"prettier@npm:2.8.8":
-  version: 2.8.8
-  resolution: "prettier@npm:2.8.8"
-  bin:
-    prettier: bin-prettier.js
-  checksum: 10c0/463ea8f9a0946cd5b828d8cf27bd8b567345cf02f56562d5ecde198b91f47a76b7ac9eae0facd247ace70e927143af6135e8cf411986b8cb8478784a4d6d724a
-  languageName: node
-  linkType: hard
-
 "pretty-error@npm:^4.0.0":
   version: 4.0.0
   resolution: "pretty-error@npm:4.0.0"
@@ -14090,6 +14158,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"randombytes@npm:^2.1.0":
+  version: 2.1.0
+  resolution: "randombytes@npm:2.1.0"
+  dependencies:
+    safe-buffer: "npm:^5.1.0"
+  checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3
+  languageName: node
+  linkType: hard
+
 "range-parser@npm:^1.2.1, range-parser@npm:~1.2.1":
   version: 1.2.1
   resolution: "range-parser@npm:1.2.1"
@@ -14892,7 +14969,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:~5.2.0":
+"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0":
   version: 5.2.1
   resolution: "safe-buffer@npm:5.2.1"
   checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
@@ -15043,6 +15120,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"serialize-javascript@npm:^6.0.0":
+  version: 6.0.2
+  resolution: "serialize-javascript@npm:6.0.2"
+  dependencies:
+    randombytes: "npm:^2.1.0"
+  checksum: 10c0/2dd09ef4b65a1289ba24a788b1423a035581bef60817bea1f01eda8e3bda623f86357665fe7ac1b50f6d4f583f97db9615b3f07b2a2e8cbcb75033965f771dd2
+  languageName: node
+  linkType: hard
+
 "serve-index@npm:^1.9.1":
   version: 1.9.2
   resolution: "serve-index@npm:1.9.2"
@@ -15263,6 +15349,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"slash@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "slash@npm:4.0.0"
+  checksum: 10c0/b522ca75d80d107fd30d29df0549a7b2537c83c4c4ecd12cd7d4ea6c8aaca2ab17ada002e7a1d78a9d736a0261509f26ea5b489082ee443a3a810586ef8eff18
+  languageName: node
+  linkType: hard
+
 "slash@npm:^5.1.0":
   version: 5.1.0
   resolution: "slash@npm:5.1.0"