@sincpro/mobile-ui 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Actions/Actions.Button.d.ts +151 -0
- package/dist/Actions/Actions.Button.js +217 -0
- package/dist/Actions/Actions.FAB.d.ts +10 -0
- package/dist/Actions/Actions.FAB.js +17 -0
- package/dist/Actions/Actions.FilterButton.d.ts +10 -0
- package/dist/Actions/Actions.FilterButton.js +28 -0
- package/dist/Actions/Actions.IconButton.d.ts +67 -0
- package/dist/Actions/Actions.IconButton.js +38 -0
- package/dist/Actions/index.d.ts +22 -0
- package/dist/Actions/index.js +17 -0
- package/dist/Dialog/BottomSheet/BottomSheet.Root.js +1 -0
- package/dist/Dialog/Confirmation.context.js +1 -6
- package/dist/Dialog/Dialog.Sheet.js +6 -4
- package/dist/Display/Display.CircleButton.d.ts +15 -0
- package/dist/Display/Display.CircleButton.js +39 -0
- package/dist/Display/Display.MenuButton.d.ts +51 -8
- package/dist/Display/Display.MenuButton.js +79 -13
- package/dist/Display/Display.MenuCard.d.ts +15 -0
- package/dist/Display/Display.MenuCard.js +24 -0
- package/dist/Display/Display.MenuGrid.d.ts +19 -0
- package/dist/Display/Display.MenuGrid.js +7 -0
- package/dist/Display/Display.SwipeableRow.js +2 -1
- package/dist/Display/Display.Tooltip.d.ts +1 -1
- package/dist/Display/Display.Tooltip.js +16 -5
- package/dist/Display/index.d.ts +9 -0
- package/dist/Display/index.js +6 -0
- package/dist/Feedback/Feedback.Empty.js +2 -2
- package/dist/Feedback/Feedback.Error.js +2 -2
- package/dist/Feedback/Feedback.Loading.d.ts +3 -7
- package/dist/Feedback/Feedback.Loading.js +2 -8
- package/dist/Feedback/Feedback.Progress.js +2 -2
- package/dist/Feedback/Feedback.Skeleton.js +2 -2
- package/dist/Feedback/Feedback.Spinner.d.ts +3 -0
- package/dist/Feedback/Feedback.Spinner.js +52 -2
- package/dist/Feedback/Feedback.Splash.js +1 -0
- package/dist/Feedback/index.d.ts +0 -2
- package/dist/Feedback/index.js +0 -2
- package/dist/Form/Form.Button.d.ts +3 -151
- package/dist/Form/Form.Button.js +1 -283
- package/dist/Form/Form.FAB.d.ts +3 -10
- package/dist/Form/Form.FAB.js +1 -17
- package/dist/Form/Form.FilterButton.d.ts +3 -12
- package/dist/Form/Form.FilterButton.js +1 -34
- package/dist/Form/Form.IconButton.d.ts +3 -67
- package/dist/Form/Form.IconButton.js +1 -64
- package/dist/Form/Form.PasswordInput.js +4 -2
- package/dist/Navigation/Navigation.AppBar.d.ts +56 -1
- package/dist/Navigation/Navigation.AppBar.js +43 -12
- package/dist/Navigation/Navigation.BottomNav.js +2 -1
- package/dist/Navigation/Navigation.Header.js +3 -2
- package/dist/Navigation/Navigation.Menu.js +6 -3
- package/dist/Navigation/Navigation.MenuSection.d.ts +19 -0
- package/dist/Navigation/Navigation.MenuSection.js +25 -0
- package/dist/Navigation/Navigation.SegmentedControl.d.ts +15 -1
- package/dist/Navigation/Navigation.SegmentedControl.js +22 -4
- package/dist/Navigation/Navigation.TabIcon.js +1 -2
- package/dist/Navigation/Navigation.TabItem.js +2 -2
- package/dist/Navigation/Navigation.Tabs.d.ts +8 -3
- package/dist/Navigation/Navigation.Tabs.js +19 -6
- package/dist/Navigation/index.d.ts +7 -6
- package/dist/Navigation/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/layouts/AuthContainer.d.ts +4 -1
- package/dist/layouts/AuthContainer.js +7 -5
- package/dist/layouts/BottomInset.d.ts +16 -0
- package/dist/layouts/BottomInset.js +17 -0
- package/dist/layouts/TabNavigatorLayout.js +2 -2
- package/dist/primitives/BaseButton.js +3 -3
- package/dist/theme/default.js +1 -1
- package/dist/views/AppSplashView.d.ts +18 -0
- package/dist/views/AppSplashView.js +9 -0
- package/dist/views/AuthFormView.d.ts +3 -1
- package/dist/views/AuthFormView.js +2 -2
- package/dist/views/FormViewV2.d.ts +18 -6
- package/dist/views/FormViewV2.js +14 -11
- package/dist/views/ListViewV2.d.ts +12 -1
- package/dist/views/ListViewV2.js +16 -10
- package/dist/widgets/CircleButton.d.ts +3 -19
- package/dist/widgets/CircleButton.js +1 -41
- package/dist/widgets/JSONViewer.js +7 -7
- package/dist/widgets/MenuCard.d.ts +3 -13
- package/dist/widgets/MenuCard.js +1 -8
- package/dist/widgets/MenuGrid.d.ts +5 -17
- package/dist/widgets/MenuGrid.js +1 -6
- package/dist/widgets/MenuSection.d.ts +3 -0
- package/dist/widgets/MenuSection.js +1 -0
- package/dist/widgets/PromoBanner.d.ts +38 -0
- package/dist/widgets/PromoBanner.js +61 -0
- package/dist/widgets/PromoModal.d.ts +41 -0
- package/dist/widgets/PromoModal.js +75 -0
- package/dist/widgets/QuickActions.d.ts +26 -0
- package/dist/widgets/QuickActions.js +41 -0
- package/dist/widgets/index.d.ts +11 -1
- package/dist/widgets/index.js +4 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { Actions } from "./Actions";
|
|
1
2
|
export { Dialog } from "./Dialog";
|
|
2
3
|
export { Display } from "./Display";
|
|
3
4
|
export { Feedback } from "./Feedback";
|
|
@@ -8,6 +9,7 @@ export { Box, Row, Stack } from "./primitives";
|
|
|
8
9
|
export { type BrandingConfig, getBrandingLogo, setBranding, } from "./branding";
|
|
9
10
|
export { cn, tv, type VariantProps } from "./theme/tw";
|
|
10
11
|
export { fontFamilies, fontSizes, fontWeights, letterSpacing, lineHeights, typographyVariants, } from "./theme/typography";
|
|
12
|
+
export { BottomInsetContext } from "./layouts/BottomInset";
|
|
11
13
|
export { default as Container } from "./layouts/Container";
|
|
12
14
|
export { default as GradientContainer } from "./layouts/GradientContainer";
|
|
13
15
|
export { default as PlainLayout } from "./layouts/PlainLayout";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Design System - Compound Components
|
|
2
|
+
export { Actions } from "./Actions";
|
|
2
3
|
export { Dialog } from "./Dialog";
|
|
3
4
|
export { Display } from "./Display";
|
|
4
5
|
export { Feedback } from "./Feedback";
|
|
@@ -13,6 +14,7 @@ export { getBrandingLogo, setBranding, } from "./branding";
|
|
|
13
14
|
export { cn, tv } from "./theme/tw";
|
|
14
15
|
export { fontFamilies, fontSizes, fontWeights, letterSpacing, lineHeights, typographyVariants, } from "./theme/typography";
|
|
15
16
|
// Layouts
|
|
17
|
+
export { BottomInsetContext } from "./layouts/BottomInset";
|
|
16
18
|
export { default as Container } from "./layouts/Container";
|
|
17
19
|
export { default as GradientContainer } from "./layouts/GradientContainer";
|
|
18
20
|
export { default as PlainLayout } from "./layouts/PlainLayout";
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import type { AppBarBackground } from "../Navigation/Navigation.AppBar";
|
|
1
2
|
import { ReactNode } from "react";
|
|
2
3
|
interface AuthContainerProps {
|
|
3
4
|
header: ReactNode;
|
|
4
5
|
children: ReactNode;
|
|
5
6
|
onBackPress?: () => void;
|
|
6
7
|
className?: string;
|
|
8
|
+
/** Gradient + pattern surface for the header area. Defaults to `night-green` preset. */
|
|
9
|
+
background?: AppBarBackground;
|
|
7
10
|
}
|
|
8
|
-
declare function AuthContainer({ header, children, onBackPress, className }: AuthContainerProps): import("react").JSX.Element;
|
|
11
|
+
declare function AuthContainer({ header, children, onBackPress, background, className, }: AuthContainerProps): import("react").JSX.Element;
|
|
9
12
|
export default AuthContainer;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
2
|
import { Display } from "../Display";
|
|
3
3
|
import GradientSurface from "../Display/Display.GradientSurface";
|
|
4
|
-
import {
|
|
4
|
+
import { Pattern } from "../Display/Display.Pattern";
|
|
5
|
+
import { useTheme } from "../theme";
|
|
5
6
|
import { cn } from "../theme/tw";
|
|
6
|
-
import {
|
|
7
|
+
import { Keyboard, TouchableOpacity, TouchableWithoutFeedback, useWindowDimensions, View, } from "react-native";
|
|
7
8
|
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
|
|
8
9
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
9
|
-
function AuthContainer({ header, children, onBackPress, className }) {
|
|
10
|
-
const screenHeight =
|
|
11
|
-
|
|
10
|
+
function AuthContainer({ header, children, onBackPress, background, className, }) {
|
|
11
|
+
const { height: screenHeight } = useWindowDimensions();
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
return (_jsxs(GradientSurface, { className: cn("flex-1", className), colors: background?.colors, end: background?.end ?? (background?.colors ? { x: 0, y: 1 } : undefined), preset: background?.surface ?? "night-green", radius: "none", start: background?.start ?? (background?.colors ? { x: 0, y: 0 } : undefined), style: { flex: 1 }, children: [background?.pattern ? (_jsx(Pattern, { color: background.patternColor ?? "#FFFFFF", kind: background.pattern, opacity: background.patternOpacity ?? 0.18 })) : null, _jsx(SafeAreaView, { className: "flex-1", edges: ["top"], children: _jsxs(View, { className: "flex-1", children: [_jsx(TouchableWithoutFeedback, { onPress: Keyboard.dismiss, children: _jsxs(View, { className: "justify-center items-center relative", style: { height: screenHeight * 0.3 }, children: [onBackPress && (_jsx(TouchableOpacity, { className: "absolute top-4 left-4 p-2 z-[1]", onPress: onBackPress, children: _jsx(Display.Icon, { color: background?.textColor ?? theme.text.inverse, name: "arrow-back", size: 24, type: "ionicons" }) })), header] }) }), _jsx(View, { className: "flex-1 bg-bg-card rounded-t-3xl shadow-lg", style: { minHeight: screenHeight * 0.7 }, children: _jsx(KeyboardAwareScrollView, { bottomOffset: 50, bounces: false, className: "flex-1", contentContainerClassName: "flex-grow pb-10", keyboardShouldPersistTaps: "handled", showsVerticalScrollIndicator: false, children: _jsx(View, { className: "p-4", children: children }) }) })] }) })] }));
|
|
12
14
|
}
|
|
13
15
|
export default AuthContainer;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra bottom inset for scroll views, provided by the host app when a floating
|
|
3
|
+
* element (e.g. position:absolute tab bar) sits above the native safe area.
|
|
4
|
+
*
|
|
5
|
+
* FormViewV2.Content and ListViewV2.Content add this value as extra
|
|
6
|
+
* `contentContainerStyle.paddingBottom` so content can scroll fully above the bar.
|
|
7
|
+
*
|
|
8
|
+
* Usage in the host app:
|
|
9
|
+
* <BottomInsetContext.Provider value={72}>
|
|
10
|
+
* <Tabs.Navigator ...>
|
|
11
|
+
*
|
|
12
|
+
* Default: 0 — no extra inset (backwards compatible).
|
|
13
|
+
* The native safe-area inset is already handled by Container (SafeAreaView edges=["bottom"]).
|
|
14
|
+
*/
|
|
15
|
+
export declare const BottomInsetContext: import("react").Context<number>;
|
|
16
|
+
export declare const useBottomInset: () => number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Extra bottom inset for scroll views, provided by the host app when a floating
|
|
4
|
+
* element (e.g. position:absolute tab bar) sits above the native safe area.
|
|
5
|
+
*
|
|
6
|
+
* FormViewV2.Content and ListViewV2.Content add this value as extra
|
|
7
|
+
* `contentContainerStyle.paddingBottom` so content can scroll fully above the bar.
|
|
8
|
+
*
|
|
9
|
+
* Usage in the host app:
|
|
10
|
+
* <BottomInsetContext.Provider value={72}>
|
|
11
|
+
* <Tabs.Navigator ...>
|
|
12
|
+
*
|
|
13
|
+
* Default: 0 — no extra inset (backwards compatible).
|
|
14
|
+
* The native safe-area inset is already handled by Container (SafeAreaView edges=["bottom"]).
|
|
15
|
+
*/
|
|
16
|
+
export const BottomInsetContext = createContext(0);
|
|
17
|
+
export const useBottomInset = () => useContext(BottomInsetContext);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "nativewind/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import DisplayIcon from "../Display/Display.Icon";
|
|
3
3
|
import Container from "../layouts/Container";
|
|
4
4
|
import { Typography } from "../Typography";
|
|
5
5
|
import { Children, isValidElement } from "react";
|
|
6
6
|
import { TouchableOpacity, View } from "react-native";
|
|
7
7
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
8
8
|
function TabIcon({ focused, Icon }) {
|
|
9
|
-
return (_jsxs(View, { className: "justify-center items-center w-10 h-10", children: [focused && _jsx(View, { className: "absolute w-10 h-10 rounded-full bg-primary" }), _jsx(
|
|
9
|
+
return (_jsxs(View, { className: "justify-center items-center w-10 h-10", children: [focused && _jsx(View, { className: "absolute w-10 h-10 rounded-full bg-primary" }), _jsx(DisplayIcon, { color: focused ? "#FFFFFF" : "#6B7280", customIcon: Icon, size: 24, type: "custom" })] }));
|
|
10
10
|
}
|
|
11
11
|
function TabNavigator({ items, currentPath, onTabPress, }) {
|
|
12
12
|
const insets = useSafeAreaInsets();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import Icon from "../Display/Display.Icon";
|
|
3
3
|
import { theme } from "../theme";
|
|
4
4
|
import { tv } from "../theme/tw";
|
|
5
5
|
import { Typography } from "../Typography";
|
|
@@ -222,9 +222,9 @@ export const BaseButtonIcon = ({ icon, onPress, variant = "primary", size = "med
|
|
|
222
222
|
return (_jsx(LinearGradient, { colors: gradientColors, end: { x: 1, y: 1 }, start: { x: 0, y: 0 }, style: {
|
|
223
223
|
borderRadius: 8,
|
|
224
224
|
opacity: disabled ? 0.7 : 1,
|
|
225
|
-
}, children: _jsx(TouchableOpacity, { activeOpacity: 0.8, disabled: disabled || loading, onPress: onPress, children: _jsx(View, { className: buttonIcon({ size, disabled }), style: { backgroundColor: "transparent" }, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(
|
|
225
|
+
}, children: _jsx(TouchableOpacity, { activeOpacity: 0.8, disabled: disabled || loading, onPress: onPress, children: _jsx(View, { className: buttonIcon({ size, disabled }), style: { backgroundColor: "transparent" }, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Icon, { color: iconColorValue, name: icon, size: iconSizeValue })) }) }) }));
|
|
226
226
|
}
|
|
227
|
-
return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: buttonIcon({ variant, size, disabled, className }), disabled: disabled || loading, onPress: onPress, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(
|
|
227
|
+
return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: buttonIcon({ variant, size, disabled, className }), disabled: disabled || loading, onPress: onPress, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Icon, { color: iconColorValue, name: icon, size: iconSizeValue })) }));
|
|
228
228
|
};
|
|
229
229
|
// ============================================================================
|
|
230
230
|
// COMPOUND COMPONENT
|
package/dist/theme/default.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type SpinnerVariant } from "../Feedback/Feedback.Spinner";
|
|
2
|
+
import type { AppBarBackground } from "../Navigation/Navigation.AppBar";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { type ImageSourcePropType, type ViewStyle } from "react-native";
|
|
5
|
+
export interface AppSplashViewProps {
|
|
6
|
+
/** Gradient + pattern background. Defaults to `night-green` preset. */
|
|
7
|
+
background?: AppBarBackground;
|
|
8
|
+
/** App logo shown centered above the loading indicator. */
|
|
9
|
+
logo?: ImageSourcePropType;
|
|
10
|
+
/** Built-in loading animation variant. Ignored when `loader` is provided. Defaults to `"dots"`. */
|
|
11
|
+
loadingVariant?: SpinnerVariant;
|
|
12
|
+
/** Fully custom loading element. Takes precedence over `loadingVariant`. */
|
|
13
|
+
loader?: ReactNode;
|
|
14
|
+
/** Override the outer container style. */
|
|
15
|
+
style?: ViewStyle;
|
|
16
|
+
}
|
|
17
|
+
export declare function AppSplashView({ background, logo, loadingVariant, loader, style, }: AppSplashViewProps): import("react").JSX.Element;
|
|
18
|
+
export default AppSplashView;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
|
+
import GradientSurface from "../Display/Display.GradientSurface";
|
|
3
|
+
import { Pattern } from "../Display/Display.Pattern";
|
|
4
|
+
import Spinner from "../Feedback/Feedback.Spinner";
|
|
5
|
+
import { Image, View } from "react-native";
|
|
6
|
+
export function AppSplashView({ background, logo, loadingVariant = "dots", loader, style, }) {
|
|
7
|
+
return (_jsxs(GradientSurface, { className: "flex-1", colors: background?.colors, end: background?.end, padding: "none", preset: background?.surface ?? "night-green", radius: "none", start: background?.start, style: { flex: 1, ...style }, children: [background?.pattern ? (_jsx(Pattern, { color: background.patternColor ?? "#FFFFFF", kind: background.pattern, opacity: background.patternOpacity ?? 0.18 })) : null, _jsxs(View, { style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: [logo ? (_jsx(Image, { source: logo, style: { width: 140, height: 140, resizeMode: "contain", marginBottom: 40 } })) : null, loader ?? (_jsx(Spinner, { color: "rgba(255,255,255,0.9)", size: "large", variant: loadingVariant }))] })] }));
|
|
8
|
+
}
|
|
9
|
+
export default AppSplashView;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AppBarBackground } from "../Navigation/Navigation.AppBar";
|
|
1
2
|
import { ReactNode } from "react";
|
|
2
3
|
import { type ImageSourcePropType } from "react-native";
|
|
3
4
|
interface AuthFormProps {
|
|
@@ -6,6 +7,7 @@ interface AuthFormProps {
|
|
|
6
7
|
logoSource?: ImageSourcePropType;
|
|
7
8
|
onBack?: () => void;
|
|
8
9
|
FormNode: ReactNode;
|
|
10
|
+
background?: AppBarBackground;
|
|
9
11
|
}
|
|
10
|
-
declare function AuthFormView({ title, description, logoSource, onBack, FormNode }: AuthFormProps): import("react").JSX.Element;
|
|
12
|
+
declare function AuthFormView({ title, description, logoSource, onBack, FormNode, background, }: AuthFormProps): import("react").JSX.Element;
|
|
11
13
|
export default AuthFormView;
|
|
@@ -5,7 +5,7 @@ import { Typography } from "../Typography";
|
|
|
5
5
|
import { View } from "react-native";
|
|
6
6
|
const Logo = Display.Logo;
|
|
7
7
|
const Text = Typography.Text;
|
|
8
|
-
function AuthFormView({ title, description, logoSource, onBack, FormNode }) {
|
|
8
|
+
function AuthFormView({ title, description, logoSource, onBack, FormNode, background, }) {
|
|
9
9
|
const renderTitle = () => {
|
|
10
10
|
if (!title)
|
|
11
11
|
return null;
|
|
@@ -16,6 +16,6 @@ function AuthFormView({ title, description, logoSource, onBack, FormNode }) {
|
|
|
16
16
|
return null;
|
|
17
17
|
return _jsx(Text, { variant: "body", children: description });
|
|
18
18
|
};
|
|
19
|
-
return (_jsx(AuthContainer, { header: _jsx(Logo, { size: "large", source: logoSource }), onBackPress: onBack, children: _jsxs(View, { className: "m-4", children: [_jsxs(View, { className: "mb-5", children: [renderTitle(), renderDescription()] }), FormNode] }) }));
|
|
19
|
+
return (_jsx(AuthContainer, { background: background, header: _jsx(Logo, { size: "large", source: logoSource }), onBackPress: onBack, children: _jsxs(View, { className: "m-4", children: [_jsxs(View, { className: "mb-5", children: [renderTitle(), renderDescription()] }), FormNode] }) }));
|
|
20
20
|
}
|
|
21
21
|
export default AuthFormView;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AppBarBackground } from "../Navigation/Navigation.AppBar";
|
|
1
2
|
import { type SegmentedControlProps } from "../Navigation/Navigation.SegmentedControl";
|
|
2
3
|
import React, { ReactNode } from "react";
|
|
3
4
|
import { type ImageSourcePropType } from "react-native";
|
|
@@ -26,10 +27,20 @@ interface HeaderProps {
|
|
|
26
27
|
actions?: ReactNode;
|
|
27
28
|
/** Subheader content rendered below the title bar (SearchBar, SegmentedControl, etc.). */
|
|
28
29
|
children?: ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* [large variant] Extra top padding (px) above the title.
|
|
32
|
+
* Use ~16 on root screens (no back button) for more breathing room.
|
|
33
|
+
*/
|
|
34
|
+
topSpacing?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Gradient + texture surface. Automatically activates white text/icons — no need to set `tone="dark"`.
|
|
37
|
+
* See `AppBarBackground` for the full shape.
|
|
38
|
+
*/
|
|
39
|
+
background?: AppBarBackground;
|
|
29
40
|
/** @deprecated Pass `variant` prop instead. */
|
|
30
41
|
logoSource?: ImageSourcePropType;
|
|
31
42
|
}
|
|
32
|
-
declare function Header({ variant, tone, actions, children }: HeaderProps): React.JSX.Element;
|
|
43
|
+
declare function Header({ variant, tone, actions, children, topSpacing, background, }: HeaderProps): React.JSX.Element;
|
|
33
44
|
declare function HeaderActions({ children }: {
|
|
34
45
|
children: ReactNode;
|
|
35
46
|
}): React.JSX.Element;
|
|
@@ -94,14 +105,15 @@ declare function Group({ children, withMargin, elevation, padding, variant, titl
|
|
|
94
105
|
title?: string;
|
|
95
106
|
}): React.JSX.Element;
|
|
96
107
|
/**
|
|
97
|
-
* Settings-style section:
|
|
98
|
-
*
|
|
99
|
-
*
|
|
108
|
+
* Settings-style section: titled card grouping Display.MenuButton rows.
|
|
109
|
+
* Delegates to the standalone `MenuSection` widget — single source of truth
|
|
110
|
+
* for this pattern whether used inside a FormView or on a standalone screen.
|
|
100
111
|
*/
|
|
101
|
-
declare function Section({ title,
|
|
112
|
+
declare function Section({ title, footer, children, }: {
|
|
102
113
|
title?: string;
|
|
114
|
+
/** Hint text rendered below the card (e.g. "Toca para cambiar la configuración"). */
|
|
115
|
+
footer?: string;
|
|
103
116
|
children: ReactNode;
|
|
104
|
-
withMargin?: boolean;
|
|
105
117
|
}): React.JSX.Element;
|
|
106
118
|
declare function Footer({ children }: {
|
|
107
119
|
children: ReactNode;
|
package/dist/views/FormViewV2.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
2
|
import { Display } from "../Display";
|
|
3
3
|
import { ErrorBoundary, Feedback } from "../Feedback";
|
|
4
|
+
import { useBottomInset } from "../layouts/BottomInset";
|
|
4
5
|
import Container from "../layouts/Container";
|
|
5
6
|
import { AppBar } from "../Navigation/Navigation.AppBar";
|
|
7
|
+
import { MenuSection } from "../Navigation/Navigation.MenuSection";
|
|
6
8
|
import { SegmentedControl, } from "../Navigation/Navigation.SegmentedControl";
|
|
7
|
-
import {
|
|
9
|
+
import { useTheme } from "../theme";
|
|
8
10
|
import { FormViewProvider, useFormView } from "../views/FormViewV2.context";
|
|
9
11
|
import React from "react";
|
|
10
12
|
import { RefreshControl, View } from "react-native";
|
|
11
13
|
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
|
|
12
14
|
function FormViewRoot({ name, description, item, isLoading = false, isEmpty = false, hasError = false, errorMessage, readonly = false, onRefresh, onRetry, onBack, withContainer = true, children, }) {
|
|
13
15
|
const Wrapper = withContainer ? Container : View;
|
|
14
|
-
// The header (AppBar) / parent layout owns the TOP safe-area; the inner Container only
|
|
15
|
-
// reserves the remaining edges to avoid stacking the top inset (double padding).
|
|
16
16
|
const wrapperProps = withContainer
|
|
17
17
|
? { edges: ["bottom", "left", "right"] }
|
|
18
18
|
: { style: { flex: 1 } };
|
|
19
19
|
return (_jsx(FormViewProvider, { description: description, errorMessage: errorMessage, hasError: hasError, isEmpty: isEmpty, isLoading: isLoading, item: item, name: name, onBack: onBack, onRefresh: onRefresh, onRetry: onRetry, readonly: readonly, children: _jsx(ErrorBoundary, { children: _jsx(Wrapper, { ...wrapperProps, children: children }) }) }));
|
|
20
20
|
}
|
|
21
|
-
function Header({ variant = "default", tone, actions, children }) {
|
|
21
|
+
function Header({ variant = "default", tone, actions, children, topSpacing, background, }) {
|
|
22
22
|
const { name, description, onBack } = useFormView();
|
|
23
|
-
return (_jsx(AppBar, { actions: actions, onBack: onBack, safeArea: false, subheader: children, subtitle: description ?? undefined, title: name, tone: tone, variant: variant }));
|
|
23
|
+
return (_jsx(AppBar, { actions: actions, background: background, onBack: onBack, safeArea: false, subheader: children, subtitle: description ?? undefined, title: name, tone: tone, topSpacing: topSpacing, variant: variant }));
|
|
24
24
|
}
|
|
25
25
|
function HeaderActions({ children }) {
|
|
26
26
|
return (_jsx(View, { className: "flex-row px-4 my-2 items-center justify-between flex-1 gap-2", children: children }));
|
|
@@ -38,6 +38,8 @@ function HeaderSegmented(props) {
|
|
|
38
38
|
}
|
|
39
39
|
function Content({ withMargin = false, children, }) {
|
|
40
40
|
const { name, isLoading, isEmpty, hasError, errorMessage, item, onRefresh, onRetry, onBack, showRefreshing, setShowRefreshing, } = useFormView();
|
|
41
|
+
const bottomInset = useBottomInset();
|
|
42
|
+
const theme = useTheme();
|
|
41
43
|
const handleRefresh = React.useCallback(async () => {
|
|
42
44
|
setShowRefreshing(true);
|
|
43
45
|
if (onRefresh) {
|
|
@@ -50,7 +52,8 @@ function Content({ withMargin = false, children, }) {
|
|
|
50
52
|
flexGrow: 1,
|
|
51
53
|
justifyContent: isCenteredContent ? "center" : "flex-start",
|
|
52
54
|
alignItems: isCenteredContent ? "center" : "stretch",
|
|
53
|
-
|
|
55
|
+
paddingBottom: bottomInset,
|
|
56
|
+
}, keyboardShouldPersistTaps: "handled", refreshControl: _jsx(RefreshControl, { colors: [theme.primary], onRefresh: handleRefresh, refreshing: showRefreshing }), style: { flex: 1, backgroundColor: theme.bg.page }, children: isCenteredContent ? (_jsx(_Fragment, { children: isLoading ? (_jsx(Feedback.Loading, { message: `Cargando ${name}...` })) : hasError ? (_jsx(Feedback.Error, { message: errorMessage, onBack: onBack, onRetry: onRetry })) : (_jsx(Feedback.Empty, {})) })) : (_jsx(View, { style: withMargin ? { paddingHorizontal: 16 } : undefined, children: children })) }));
|
|
54
57
|
}
|
|
55
58
|
/**
|
|
56
59
|
* @deprecated Content already handles isEmpty/!item by rendering Feedback.Empty internally.
|
|
@@ -91,12 +94,12 @@ function Group({ children, withMargin = true, elevation = "none", padding = "md"
|
|
|
91
94
|
return (_jsxs(_Fragment, { children: [header, body] }));
|
|
92
95
|
}
|
|
93
96
|
/**
|
|
94
|
-
* Settings-style section:
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
+
* Settings-style section: titled card grouping Display.MenuButton rows.
|
|
98
|
+
* Delegates to the standalone `MenuSection` widget — single source of truth
|
|
99
|
+
* for this pattern whether used inside a FormView or on a standalone screen.
|
|
97
100
|
*/
|
|
98
|
-
function Section({ title,
|
|
99
|
-
return (
|
|
101
|
+
function Section({ title, footer, children, }) {
|
|
102
|
+
return (_jsx(MenuSection, { footer: footer, title: title, children: children }));
|
|
100
103
|
}
|
|
101
104
|
function Footer({ children }) {
|
|
102
105
|
const { isEmpty, isLoading } = useFormView();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type SearchHistoryProps } from "../Display/Display.SearchHistory";
|
|
2
|
+
import type { AppBarBackground } from "../Navigation/Navigation.AppBar";
|
|
2
3
|
import { type SegmentedControlProps } from "../Navigation/Navigation.SegmentedControl";
|
|
3
4
|
import React, { ReactNode } from "react";
|
|
4
5
|
import { StyleProp, ViewStyle } from "react-native";
|
|
@@ -34,8 +35,18 @@ interface HeaderProps {
|
|
|
34
35
|
actions?: ReactNode;
|
|
35
36
|
/** Subheader content rendered below the title bar (SearchBar, SegmentedControl, etc.). */
|
|
36
37
|
children?: ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* Gradient + texture surface. Automatically activates white text/icons.
|
|
40
|
+
* See `AppBarBackground` for the full shape.
|
|
41
|
+
*/
|
|
42
|
+
background?: AppBarBackground;
|
|
43
|
+
/**
|
|
44
|
+
* [large variant] Extra top padding (px) above the large title.
|
|
45
|
+
* Use ~16 on root screens (no back button) for breathing room.
|
|
46
|
+
*/
|
|
47
|
+
topSpacing?: number;
|
|
37
48
|
}
|
|
38
|
-
declare function Header({ variant, tone, actions, children }: HeaderProps): React.JSX.Element;
|
|
49
|
+
declare function Header({ variant, tone, actions, children, background, topSpacing, }: HeaderProps): React.JSX.Element;
|
|
39
50
|
declare function HeaderSearch({ searchQuery }: {
|
|
40
51
|
searchQuery?: string;
|
|
41
52
|
}): React.JSX.Element | null;
|
package/dist/views/ListViewV2.js
CHANGED
|
@@ -2,10 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "nativewind/js
|
|
|
2
2
|
import { Display } from "../Display";
|
|
3
3
|
import SearchHistory from "../Display/Display.SearchHistory";
|
|
4
4
|
import { ErrorBoundary, Feedback } from "../Feedback";
|
|
5
|
+
import { useBottomInset } from "../layouts/BottomInset";
|
|
5
6
|
import Container from "../layouts/Container";
|
|
6
7
|
import { Navigation } from "../Navigation";
|
|
7
8
|
import { SegmentedControl, } from "../Navigation/Navigation.SegmentedControl";
|
|
8
|
-
import {
|
|
9
|
+
import { useTheme } from "../theme";
|
|
9
10
|
import { cn, tv } from "../theme/tw";
|
|
10
11
|
import { Typography } from "../Typography";
|
|
11
12
|
import { ListViewProvider, useListView } from "../views/ListViewV2.context";
|
|
@@ -14,17 +15,15 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
14
15
|
import { FlatList, RefreshControl, ScrollView, TouchableOpacity, View, } from "react-native";
|
|
15
16
|
function ListViewRoot({ name, description, items, isLoading = false, hasError = false, errorMessage, readonly = false, onRefresh, onRetry, onPressItem, onDeleteItem, onSearch, onBack, onLoadMore, loadingMore = false, backgroundColor, withContainer = true, children, }) {
|
|
16
17
|
const Wrapper = withContainer ? Container : View;
|
|
17
|
-
// The header (AppBar) / parent layout owns the TOP safe-area; the Container only reserves
|
|
18
|
-
// the remaining edges to avoid stacking the top inset (double padding).
|
|
19
18
|
const wrapperProps = withContainer
|
|
20
19
|
? { edges: ["bottom", "left", "right"] }
|
|
21
20
|
: { className: "flex-1 bg-bg-page" };
|
|
22
21
|
// Propagate contentWithMargin to ContentList via context
|
|
23
22
|
return (_jsx(ListViewProvider, { description: description, errorMessage: errorMessage, hasError: hasError, isLoading: isLoading, items: items, loadingMore: loadingMore, name: name, onBack: onBack, onDeleteItem: onDeleteItem, onLoadMore: onLoadMore, onPressItem: onPressItem, onRefresh: onRefresh, onRetry: onRetry, onSearch: onSearch, readonly: readonly, children: _jsx(ErrorBoundary, { children: _jsx(Wrapper, { ...wrapperProps, children: children }) }) }));
|
|
24
23
|
}
|
|
25
|
-
function Header({ variant = "large", tone, actions, children }) {
|
|
24
|
+
function Header({ variant = "large", tone, actions, children, background, topSpacing, }) {
|
|
26
25
|
const { name, description, onBack } = useListView();
|
|
27
|
-
return (_jsx(Navigation.AppBar, { actions: actions, onBack: onBack, safeArea: false, subheader: children, subtitle: description ?? undefined, title: name, tone: tone, variant: variant }));
|
|
26
|
+
return (_jsx(Navigation.AppBar, { actions: actions, background: background, onBack: onBack, safeArea: false, subheader: children, subtitle: description ?? undefined, title: name, tone: tone, topSpacing: topSpacing, variant: variant }));
|
|
28
27
|
}
|
|
29
28
|
function HeaderSearch({ searchQuery = "" }) {
|
|
30
29
|
const { name, onSearch } = useListView();
|
|
@@ -40,7 +39,7 @@ function HeaderSearch({ searchQuery = "" }) {
|
|
|
40
39
|
if (onSearch && debouncedQuery !== undefined) {
|
|
41
40
|
onSearch(debouncedQuery);
|
|
42
41
|
}
|
|
43
|
-
}, [debouncedQuery]);
|
|
42
|
+
}, [debouncedQuery, onSearch]);
|
|
44
43
|
if (!onSearch) {
|
|
45
44
|
return null;
|
|
46
45
|
}
|
|
@@ -98,6 +97,8 @@ function FilterChips({ children }) {
|
|
|
98
97
|
}
|
|
99
98
|
function Content({ children, withMargin = true, }) {
|
|
100
99
|
const { name, items, isLoading, hasError, errorMessage, onRefresh, onRetry, onBack, showRefreshing, setShowRefreshing, } = useListView();
|
|
100
|
+
const bottomInset = useBottomInset();
|
|
101
|
+
const theme = useTheme();
|
|
101
102
|
const handleRefresh = useCallback(async () => {
|
|
102
103
|
setShowRefreshing(true);
|
|
103
104
|
if (onRefresh) {
|
|
@@ -113,19 +114,23 @@ function Content({ children, withMargin = true, }) {
|
|
|
113
114
|
flexGrow: 1,
|
|
114
115
|
justifyContent: "center",
|
|
115
116
|
alignItems: "center",
|
|
116
|
-
|
|
117
|
+
paddingBottom: bottomInset,
|
|
118
|
+
}, refreshControl: _jsx(RefreshControl, { colors: [theme.primary], onRefresh: handleRefresh, refreshing: showRefreshing }), style: { backgroundColor: theme.bg.page }, children: _jsx(Feedback.Error, { message: errorMessage, onBack: onBack, onRetry: onRetry }) }));
|
|
117
119
|
}
|
|
118
120
|
if (items.length === 0) {
|
|
119
121
|
return (_jsx(ScrollView, { contentContainerStyle: {
|
|
120
122
|
flexGrow: 1,
|
|
121
123
|
justifyContent: "center",
|
|
122
124
|
alignItems: "center",
|
|
123
|
-
|
|
125
|
+
paddingBottom: bottomInset,
|
|
126
|
+
}, refreshControl: _jsx(RefreshControl, { colors: [theme.primary], onRefresh: handleRefresh, refreshing: showRefreshing }), style: { backgroundColor: theme.bg.page }, children: _jsx(Feedback.Empty, {}) }));
|
|
124
127
|
}
|
|
125
|
-
return (_jsxs(View, { style: { flex: 1 }, children: [_jsx(Display.CountRecords, { count: items.length || 0, name: name }), _jsx(ContentList, { contentWithMargin: withMargin, children: children })] }));
|
|
128
|
+
return (_jsxs(View, { style: { flex: 1, backgroundColor: theme.bg.page }, children: [_jsx(Display.CountRecords, { count: items.length || 0, name: name }), _jsx(ContentList, { contentWithMargin: withMargin, children: children })] }));
|
|
126
129
|
}
|
|
127
130
|
function ContentList({ children, contentWithMargin, }) {
|
|
128
131
|
const { items, onRefresh, showRefreshing, setShowRefreshing, onPressItem, onDeleteItem, readonly, onLoadMore, loadingMore, } = useListView();
|
|
132
|
+
const bottomInset = useBottomInset();
|
|
133
|
+
const theme = useTheme();
|
|
129
134
|
const rowItems = useMemo(() => toRowItems(items), [items]);
|
|
130
135
|
const handleRefresh = useCallback(async () => {
|
|
131
136
|
setShowRefreshing(true);
|
|
@@ -147,7 +152,8 @@ function ContentList({ children, contentWithMargin, }) {
|
|
|
147
152
|
flex: 1,
|
|
148
153
|
marginTop: 2,
|
|
149
154
|
paddingHorizontal: contentWithMargin ? 4 : 0,
|
|
150
|
-
|
|
155
|
+
backgroundColor: theme.bg.page,
|
|
156
|
+
}, children: _jsx(FlatList, { contentContainerStyle: bottomInset ? { paddingBottom: bottomInset } : undefined, data: rowItems, keyExtractor: (item) => String(item.index), ListFooterComponent: loadingMore ? (_jsx(View, { className: "py-4", children: _jsx(Feedback.Spinner, { size: "small" }) })) : null, onEndReached: onLoadMore ? () => onLoadMore() : undefined, onEndReachedThreshold: 0.5, refreshControl: _jsx(RefreshControl, { colors: [theme.primary], onRefresh: handleRefresh, refreshing: showRefreshing }), renderItem: renderItem, scrollEnabled: true, showsVerticalScrollIndicator: false }) }));
|
|
151
157
|
}
|
|
152
158
|
function Footer({ children }) {
|
|
153
159
|
const { items } = useListView();
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
iconType?: IconType;
|
|
5
|
-
size?: "sm" | "md" | "lg";
|
|
6
|
-
color?: string;
|
|
7
|
-
variant?: "primary" | "secondary" | "accent" | "success" | "danger" | "warning";
|
|
8
|
-
className?: string;
|
|
9
|
-
customIcon?: ComponentType<{
|
|
10
|
-
size?: number;
|
|
11
|
-
color?: string;
|
|
12
|
-
}>;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* @deprecated Duplicates the icon-button. Use `Form.IconButton` (general) or
|
|
16
|
-
* `Navigation.AppBar.Action` (headers). Kept for backwards compatibility.
|
|
17
|
-
*/
|
|
18
|
-
export declare function CircleButton({ iconType, size, color, variant, className, customIcon, }: CircleButtonProps): React.JSX.Element;
|
|
19
|
-
export {};
|
|
1
|
+
/** @deprecated Import from `@sincpro/mobile-ui/Display` → `Display.CircleButton` instead. */
|
|
2
|
+
export type { CircleButtonProps } from "../Display/Display.CircleButton";
|
|
3
|
+
export { CircleButton } from "../Display/Display.CircleButton";
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Display } from "../Display";
|
|
3
|
-
import { theme } from "../theme";
|
|
4
|
-
import { cn } from "../theme/tw";
|
|
5
|
-
import { View } from "react-native";
|
|
6
|
-
import { tv } from "tailwind-variants";
|
|
7
|
-
const circleButtonVariants = tv({
|
|
8
|
-
base: "rounded-full items-center justify-center shadow-sm",
|
|
9
|
-
variants: {
|
|
10
|
-
size: {
|
|
11
|
-
sm: "w-12 h-12", // 48px
|
|
12
|
-
md: "w-15 h-15", // 60px
|
|
13
|
-
lg: "w-20 h-20", // 80px
|
|
14
|
-
},
|
|
15
|
-
variant: {
|
|
16
|
-
primary: "bg-primary",
|
|
17
|
-
secondary: "bg-secondary",
|
|
18
|
-
accent: "bg-accent",
|
|
19
|
-
success: "bg-success",
|
|
20
|
-
danger: "bg-danger",
|
|
21
|
-
warning: "bg-warning",
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
defaultVariants: {
|
|
25
|
-
size: "md",
|
|
26
|
-
variant: "accent",
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
const SIZE_MAP = {
|
|
30
|
-
sm: { container: 48, icon: 24 },
|
|
31
|
-
md: { container: 60, icon: 30 },
|
|
32
|
-
lg: { container: 80, icon: 40 },
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* @deprecated Duplicates the icon-button. Use `Form.IconButton` (general) or
|
|
36
|
-
* `Navigation.AppBar.Action` (headers). Kept for backwards compatibility.
|
|
37
|
-
*/
|
|
38
|
-
export function CircleButton({ iconType = "ionicons", size = "md", color = theme.text.inverse, variant = "accent", className, customIcon, }) {
|
|
39
|
-
const iconSize = SIZE_MAP[size].icon;
|
|
40
|
-
return (_jsx(View, { className: cn(circleButtonVariants({ size, variant }), className), children: _jsx(Display.Icon, { color: color, customIcon: customIcon, size: iconSize, type: iconType }) }));
|
|
41
|
-
}
|
|
1
|
+
export { CircleButton } from "../Display/Display.CircleButton";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
2
|
import { ThemedActivityIndicator } from "../theme";
|
|
3
3
|
import { fontFamilies } from "../theme/typography";
|
|
4
|
-
import { useMemo, useState } from "react";
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
5
|
import { Text, View } from "react-native";
|
|
6
6
|
const parseDeepJson = (value) => {
|
|
7
7
|
if (typeof value === "string") {
|
|
@@ -116,19 +116,19 @@ const JsonPreview = ({ selectedJson }) => {
|
|
|
116
116
|
}, [selectedJson]);
|
|
117
117
|
// Guard 4: colorize with processing control
|
|
118
118
|
const coloredLines = useMemo(() => {
|
|
119
|
-
setIsProcessing(true);
|
|
120
119
|
try {
|
|
121
120
|
return parseJsonToColoredLines(formattedJson);
|
|
122
121
|
}
|
|
123
122
|
catch (error) {
|
|
124
123
|
console.warn("[JSONViewer] Error coloring JSON:", error);
|
|
125
|
-
// Fallback a texto plano si falla el coloreado
|
|
126
124
|
return [{ text: formattedJson, color: "#333333" }];
|
|
127
125
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
}, [formattedJson]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
129
|
+
setIsProcessing(true);
|
|
130
|
+
const t = setTimeout(() => setIsProcessing(false), 50);
|
|
131
|
+
return () => clearTimeout(t);
|
|
132
132
|
}, [formattedJson]);
|
|
133
133
|
// Guard 5: show loading while processing large JSON
|
|
134
134
|
if (isProcessing && formattedJson.length > 50_000) {
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
title: string;
|
|
5
|
-
iconType?: IconType;
|
|
6
|
-
onPress?: () => void;
|
|
7
|
-
customIcon?: ComponentType<{
|
|
8
|
-
size?: number;
|
|
9
|
-
color?: string;
|
|
10
|
-
}>;
|
|
11
|
-
}
|
|
12
|
-
export declare function MenuCard({ title, iconType, onPress, customIcon, }: MenuCardProps): import("react").JSX.Element;
|
|
13
|
-
export {};
|
|
1
|
+
/** @deprecated Import from `@sincpro/mobile-ui/Display` → `Display.MenuCard` instead. */
|
|
2
|
+
export type { MenuCardProps } from "../Display/Display.MenuCard";
|
|
3
|
+
export { MenuCard } from "../Display/Display.MenuCard";
|
package/dist/widgets/MenuCard.js
CHANGED
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { theme } from "../theme/useTheme";
|
|
3
|
-
import { Typography } from "../Typography";
|
|
4
|
-
import { CircleButton } from "../widgets/CircleButton";
|
|
5
|
-
import { TouchableOpacity, View } from "react-native";
|
|
6
|
-
export function MenuCard({ title, iconType = "ionicons", onPress, customIcon, }) {
|
|
7
|
-
return (_jsx(TouchableOpacity, { activeOpacity: 0.7, className: "bg-bg-card rounded-2xl p-4 m-2 w-[45%] shadow-sm", onPress: onPress, style: theme.shadow["sm"], children: _jsxs(View, { className: "items-center justify-center", children: [_jsx(CircleButton, { customIcon: customIcon, iconType: iconType }), _jsx(Typography.Text, { className: "text-text-primary mt-3 text-center", variant: "label", children: title })] }) }));
|
|
8
|
-
}
|
|
1
|
+
export { MenuCard } from "../Display/Display.MenuCard";
|
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
iconType?: IconType;
|
|
7
|
-
onPress?: () => void;
|
|
8
|
-
customIcon?: ComponentType<{
|
|
9
|
-
size?: number;
|
|
10
|
-
color?: string;
|
|
11
|
-
}>;
|
|
12
|
-
}
|
|
13
|
-
interface MenuGridProps {
|
|
14
|
-
readonly items: MenuItem[];
|
|
15
|
-
}
|
|
16
|
-
export declare const MenuGrid: React.FC<MenuGridProps>;
|
|
17
|
-
export {};
|
|
1
|
+
/** @deprecated Import from `@sincpro/mobile-ui/Display` → `Display.MenuGrid` instead. */
|
|
2
|
+
export type { MenuGridItem, MenuGridProps, } from "../Display/Display.MenuGrid";
|
|
3
|
+
export { MenuGrid } from "../Display/Display.MenuGrid";
|
|
4
|
+
/** @deprecated Renamed to `MenuGridItem`. */
|
|
5
|
+
export type { MenuGridItem as MenuItem } from "../Display/Display.MenuGrid";
|
package/dist/widgets/MenuGrid.js
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { MenuCard } from "../widgets/MenuCard";
|
|
3
|
-
import { View } from "react-native";
|
|
4
|
-
export const MenuGrid = ({ items }) => {
|
|
5
|
-
return (_jsx(View, { className: "flex-row flex-wrap justify-start p-2 bg-bg-page", children: items.map((item) => (_jsx(MenuCard, { customIcon: item.customIcon, iconType: item.iconType, onPress: item.onPress, title: item.title }, item.id))) }));
|
|
6
|
-
};
|
|
1
|
+
export { MenuGrid } from "../Display/Display.MenuGrid";
|