@korsolutions/ui 0.0.62 → 0.0.64

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.
Files changed (124) hide show
  1. package/dist/module/components/avatar/components/avatar-image.js.map +1 -1
  2. package/dist/module/components/badge/badge.js +30 -0
  3. package/dist/module/components/badge/badge.js.map +1 -0
  4. package/dist/module/components/badge/context.js.map +1 -1
  5. package/dist/module/components/badge/index.js +1 -6
  6. package/dist/module/components/badge/index.js.map +1 -1
  7. package/dist/module/components/badge/variants/default.js +17 -14
  8. package/dist/module/components/badge/variants/default.js.map +1 -1
  9. package/dist/module/components/badge/variants/secondary.js +17 -14
  10. package/dist/module/components/badge/variants/secondary.js.map +1 -1
  11. package/dist/module/components/input/input.js.map +1 -1
  12. package/dist/module/components/menu/components/menu-checkbox-item.js +4 -2
  13. package/dist/module/components/menu/components/menu-checkbox-item.js.map +1 -1
  14. package/dist/module/components/menu/components/menu-item.js +4 -2
  15. package/dist/module/components/menu/components/menu-item.js.map +1 -1
  16. package/dist/module/components/menu/components/menu-radio-item.js +4 -2
  17. package/dist/module/components/menu/components/menu-radio-item.js.map +1 -1
  18. package/dist/module/components/menu/components/menu-trigger.js +2 -7
  19. package/dist/module/components/menu/components/menu-trigger.js.map +1 -1
  20. package/dist/module/components/popover/components/popover-trigger.js +3 -8
  21. package/dist/module/components/popover/components/popover-trigger.js.map +1 -1
  22. package/dist/module/components/portal/portal.js +5 -4
  23. package/dist/module/components/portal/portal.js.map +1 -1
  24. package/dist/module/components/select/components/select-overlay.js +1 -0
  25. package/dist/module/components/select/components/select-overlay.js.map +1 -1
  26. package/dist/module/components/select/variants/default.js +5 -2
  27. package/dist/module/components/select/variants/default.js.map +1 -1
  28. package/dist/module/components/tabs/components/tabs-item.js +1 -1
  29. package/dist/module/components/tabs/components/tabs-item.js.map +1 -1
  30. package/dist/module/components/toast/components/toast-icon.js.map +1 -1
  31. package/dist/module/hooks/use-is-react-navigation-modal.js +41 -0
  32. package/dist/module/hooks/use-is-react-navigation-modal.js.map +1 -0
  33. package/dist/module/{components/tabs → hooks}/use-organized-children.js +2 -2
  34. package/dist/module/hooks/use-organized-children.js.map +1 -0
  35. package/dist/module/hooks/use-relative-position.js +20 -12
  36. package/dist/module/hooks/use-relative-position.js.map +1 -1
  37. package/dist/module/index.js +3 -0
  38. package/dist/module/index.js.map +1 -1
  39. package/dist/module/themes/provider.js.map +1 -1
  40. package/dist/module/utils/normalize-layout.js +10 -0
  41. package/dist/module/utils/normalize-layout.js.map +1 -1
  42. package/dist/typescript/src/components/avatar/components/avatar-image.d.ts.map +1 -1
  43. package/dist/typescript/src/components/badge/badge.d.ts +12 -0
  44. package/dist/typescript/src/components/badge/badge.d.ts.map +1 -0
  45. package/dist/typescript/src/components/badge/context.d.ts +1 -2
  46. package/dist/typescript/src/components/badge/context.d.ts.map +1 -1
  47. package/dist/typescript/src/components/badge/index.d.ts +1 -8
  48. package/dist/typescript/src/components/badge/index.d.ts.map +1 -1
  49. package/dist/typescript/src/components/badge/types.d.ts +6 -5
  50. package/dist/typescript/src/components/badge/types.d.ts.map +1 -1
  51. package/dist/typescript/src/components/badge/variants/default.d.ts.map +1 -1
  52. package/dist/typescript/src/components/badge/variants/secondary.d.ts.map +1 -1
  53. package/dist/typescript/src/components/input/input.d.ts +1 -1
  54. package/dist/typescript/src/components/input/input.d.ts.map +1 -1
  55. package/dist/typescript/src/components/menu/components/menu-checkbox-item.d.ts.map +1 -1
  56. package/dist/typescript/src/components/menu/components/menu-item.d.ts.map +1 -1
  57. package/dist/typescript/src/components/menu/components/menu-radio-item.d.ts.map +1 -1
  58. package/dist/typescript/src/components/menu/components/menu-trigger.d.ts.map +1 -1
  59. package/dist/typescript/src/components/menu/types.d.ts +2 -1
  60. package/dist/typescript/src/components/menu/types.d.ts.map +1 -1
  61. package/dist/typescript/src/components/popover/components/popover-trigger.d.ts +1 -1
  62. package/dist/typescript/src/components/popover/components/popover-trigger.d.ts.map +1 -1
  63. package/dist/typescript/src/components/portal/portal.d.ts.map +1 -1
  64. package/dist/typescript/src/components/select/components/select-overlay.d.ts.map +1 -1
  65. package/dist/typescript/src/components/select/variants/default.d.ts.map +1 -1
  66. package/dist/typescript/src/components/toast/components/toast-icon.d.ts +1 -1
  67. package/dist/typescript/src/components/toast/components/toast-icon.d.ts.map +1 -1
  68. package/dist/typescript/src/hooks/use-is-react-navigation-modal.d.ts +3 -0
  69. package/dist/typescript/src/hooks/use-is-react-navigation-modal.d.ts.map +1 -0
  70. package/dist/typescript/src/hooks/use-organized-children.d.ts +5 -0
  71. package/dist/typescript/src/hooks/use-organized-children.d.ts.map +1 -0
  72. package/dist/typescript/src/hooks/use-relative-position.d.ts +1 -1
  73. package/dist/typescript/src/hooks/use-relative-position.d.ts.map +1 -1
  74. package/dist/typescript/src/index.d.ts.map +1 -1
  75. package/dist/typescript/src/themes/provider.d.ts +3 -3
  76. package/dist/typescript/src/themes/provider.d.ts.map +1 -1
  77. package/dist/typescript/src/types/props.types.d.ts +2 -1
  78. package/dist/typescript/src/types/props.types.d.ts.map +1 -1
  79. package/dist/typescript/src/utils/normalize-layout.d.ts.map +1 -1
  80. package/package.json +1 -1
  81. package/src/components/avatar/components/avatar-image.tsx +14 -2
  82. package/src/components/badge/badge.tsx +46 -0
  83. package/src/components/badge/context.ts +1 -2
  84. package/src/components/badge/index.ts +1 -10
  85. package/src/components/badge/types.ts +6 -6
  86. package/src/components/badge/variants/default.tsx +17 -14
  87. package/src/components/badge/variants/secondary.tsx +17 -14
  88. package/src/components/input/input.tsx +6 -2
  89. package/src/components/menu/components/menu-checkbox-item.tsx +9 -2
  90. package/src/components/menu/components/menu-item.tsx +9 -2
  91. package/src/components/menu/components/menu-radio-item.tsx +9 -2
  92. package/src/components/menu/components/menu-trigger.tsx +2 -7
  93. package/src/components/menu/types.ts +2 -1
  94. package/src/components/popover/components/popover-trigger.tsx +8 -10
  95. package/src/components/portal/portal.tsx +4 -3
  96. package/src/components/select/components/select-overlay.tsx +1 -0
  97. package/src/components/select/variants/default.tsx +4 -1
  98. package/src/components/tabs/components/tabs-item.tsx +1 -1
  99. package/src/components/toast/components/toast-icon.tsx +1 -1
  100. package/src/hooks/use-is-react-navigation-modal.ts +56 -0
  101. package/src/{components/tabs → hooks}/use-organized-children.tsx +3 -3
  102. package/src/hooks/use-relative-position.ts +33 -18
  103. package/src/index.tsx +4 -0
  104. package/src/themes/provider.tsx +5 -3
  105. package/src/types/props.types.ts +2 -1
  106. package/src/utils/normalize-layout.ts +10 -0
  107. package/dist/module/components/badge/components/badge-label.js +0 -17
  108. package/dist/module/components/badge/components/badge-label.js.map +0 -1
  109. package/dist/module/components/badge/components/badge-root.js +0 -27
  110. package/dist/module/components/badge/components/badge-root.js.map +0 -1
  111. package/dist/module/components/menu/use-organized-children.js +0 -39
  112. package/dist/module/components/menu/use-organized-children.js.map +0 -1
  113. package/dist/module/components/tabs/use-organized-children.js.map +0 -1
  114. package/dist/typescript/src/components/badge/components/badge-label.d.ts +0 -9
  115. package/dist/typescript/src/components/badge/components/badge-label.d.ts.map +0 -1
  116. package/dist/typescript/src/components/badge/components/badge-root.d.ts +0 -13
  117. package/dist/typescript/src/components/badge/components/badge-root.d.ts.map +0 -1
  118. package/dist/typescript/src/components/menu/use-organized-children.d.ts +0 -3
  119. package/dist/typescript/src/components/menu/use-organized-children.d.ts.map +0 -1
  120. package/dist/typescript/src/components/tabs/use-organized-children.d.ts +0 -5
  121. package/dist/typescript/src/components/tabs/use-organized-children.d.ts.map +0 -1
  122. package/src/components/badge/components/badge-label.tsx +0 -21
  123. package/src/components/badge/components/badge-root.tsx +0 -36
  124. package/src/components/menu/use-organized-children.tsx +0 -38
@@ -1,8 +1,7 @@
1
1
  import { createContext, useContext } from "react";
2
- import type { BadgeState, BadgeStyles } from "./types";
2
+ import type { BadgeStyles } from "./types";
3
3
 
4
4
  export interface BadgeContext {
5
- state: BadgeState;
6
5
  styles?: BadgeStyles;
7
6
  }
8
7
 
@@ -1,11 +1,2 @@
1
- import { BadgeLabel } from "./components/badge-label";
2
- import { BadgeRoot } from "./components/badge-root";
3
-
4
- export const Badge = {
5
- Root: BadgeRoot,
6
- Label: BadgeLabel,
7
- };
8
-
9
- export type { BadgeLabelProps } from "./components/badge-label";
10
- export type { BadgeRootProps } from "./components/badge-root";
1
+ export { Badge, type BadgeProps } from "./badge";
11
2
  export type { BadgeStyles } from "./types";
@@ -1,9 +1,9 @@
1
- import type { BadgeLabelProps } from "./components/badge-label";
2
- import type { BadgeRootProps } from "./components/badge-root";
3
-
4
- export type BadgeState = "default";
1
+ import type { TextStyle } from "react-native";
2
+ import type { IconProps } from "../icon";
3
+ import type { BadgeProps } from "./badge";
5
4
 
6
5
  export interface BadgeStyles {
7
- root?: Partial<Record<BadgeState, BadgeRootProps["style"]>>;
8
- label?: Partial<Record<BadgeState, BadgeLabelProps["style"]>>;
6
+ root?: BadgeProps["style"];
7
+ text?: TextStyle;
8
+ icon?: IconProps;
9
9
  }
@@ -5,21 +5,24 @@ export const useBadgeVariantDefault = (): BadgeStyles => {
5
5
  return useThemedStyles(
6
6
  ({ colors, radius, fontFamily, fontSize }): BadgeStyles => ({
7
7
  root: {
8
- default: {
9
- backgroundColor: colors.primary,
10
- paddingVertical: 4,
11
- paddingHorizontal: 8,
12
- borderRadius: radius,
13
- alignSelf: "flex-start",
14
- },
8
+ flexDirection: "row",
9
+ gap: 4,
10
+ alignItems: "center",
11
+ alignSelf: "flex-start",
12
+ backgroundColor: colors.primary,
13
+ paddingVertical: 4,
14
+ paddingHorizontal: 8,
15
+ borderRadius: radius,
15
16
  },
16
- label: {
17
- default: {
18
- color: colors.primaryForeground,
19
- fontSize: fontSize * 0.75,
20
- fontWeight: "600",
21
- fontFamily,
22
- },
17
+ text: {
18
+ color: colors.primaryForeground,
19
+ fontSize: fontSize * 0.75,
20
+ fontWeight: "600",
21
+ fontFamily,
22
+ },
23
+ icon: {
24
+ color: colors.primaryForeground,
25
+ size: fontSize * 0.75,
23
26
  },
24
27
  }),
25
28
  );
@@ -5,21 +5,24 @@ export const useBadgeVariantSecondary = (): BadgeStyles => {
5
5
  return useThemedStyles(
6
6
  ({ colors, radius, fontFamily, fontSize }): BadgeStyles => ({
7
7
  root: {
8
- default: {
9
- backgroundColor: colors.secondary,
10
- paddingVertical: 4,
11
- paddingHorizontal: 8,
12
- borderRadius: radius,
13
- alignSelf: "flex-start",
14
- },
8
+ flexDirection: "row",
9
+ gap: 4,
10
+ alignItems: "center",
11
+ alignSelf: "flex-start",
12
+ backgroundColor: colors.secondary,
13
+ paddingVertical: 4,
14
+ paddingHorizontal: 8,
15
+ borderRadius: radius,
15
16
  },
16
- label: {
17
- default: {
18
- color: colors.secondaryForeground,
19
- fontSize: fontSize * 0.75,
20
- fontWeight: "600",
21
- fontFamily,
22
- },
17
+ text: {
18
+ color: colors.secondaryForeground,
19
+ fontSize: fontSize * 0.75,
20
+ fontWeight: "600",
21
+ fontFamily,
22
+ },
23
+ icon: {
24
+ color: colors.secondaryForeground,
25
+ size: fontSize * 0.75,
23
26
  },
24
27
  }),
25
28
  );
@@ -1,6 +1,6 @@
1
- import type { TextInputRef } from "../../types/element.types";
2
1
  import { forwardRef, useState } from "react";
3
2
  import { StyleSheet, TextInput, type TextInputProps } from "react-native";
3
+ import type { TextInputRef } from "../../types/element.types";
4
4
  import { useFieldOptional } from "../field/context";
5
5
  import type { InputState } from "./types";
6
6
  import { InputVariants } from "./variants";
@@ -29,7 +29,11 @@ export const Input = forwardRef<TextInputRef, InputProps>((props, ref) => {
29
29
  const state = calculateState(props, isFocused);
30
30
  const field = useFieldOptional();
31
31
 
32
- const composedStyles = StyleSheet.flatten([variantStyles.default?.style, variantStyles[state]?.style, props.style]);
32
+ const composedStyles = StyleSheet.flatten([
33
+ variantStyles.default?.style,
34
+ variantStyles[state]?.style,
35
+ props.style,
36
+ ]);
33
37
  const composedProps = {
34
38
  ...variantStyles.default,
35
39
  ...variantStyles[state],
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from "react";
2
2
  import { Pressable, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useOrganizedChildren } from "../../../hooks/use-organized-children";
3
4
  import { useMenu } from "../context";
4
5
  import type { MenuCheckboxItemState } from "../types";
5
- import { useOrganizedChildren } from "../use-organized-children";
6
6
  import { MenuSelectionIndicator } from "./menu-selection-indicator";
7
7
 
8
8
  export interface MenuCheckboxItemProps {
@@ -43,7 +43,14 @@ export function MenuCheckboxItem(props: MenuCheckboxItemProps) {
43
43
  }
44
44
  };
45
45
 
46
- const organizedChildren = useOrganizedChildren(props.children);
46
+ const textStyles = menu.styles?.itemText;
47
+ const iconStyles = menu.styles?.itemIcon;
48
+
49
+ const organizedChildren = useOrganizedChildren(
50
+ props.children,
51
+ textStyles,
52
+ iconStyles,
53
+ );
47
54
 
48
55
  if (props.render) {
49
56
  return (
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from "react";
2
2
  import { Pressable, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useOrganizedChildren } from "../../../hooks/use-organized-children";
3
4
  import { useMenu } from "../context";
4
5
  import type { MenuButtonState } from "../types";
5
- import { useOrganizedChildren } from "../use-organized-children";
6
6
 
7
7
  export interface MenuItemProps {
8
8
  children: React.ReactNode;
@@ -34,7 +34,14 @@ export function MenuItem(props: MenuItemProps) {
34
34
  menu.setIsOpen((prev) => !prev);
35
35
  };
36
36
 
37
- const organizedChildren = useOrganizedChildren(props.children);
37
+ const textStyles = menu.styles?.itemText;
38
+ const iconStyles = menu.styles?.itemIcon;
39
+
40
+ const organizedChildren = useOrganizedChildren(
41
+ props.children,
42
+ textStyles,
43
+ iconStyles,
44
+ );
38
45
 
39
46
  if (props.render) {
40
47
  return (
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from "react";
2
2
  import { Pressable, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useOrganizedChildren } from "../../../hooks/use-organized-children";
3
4
  import { useMenu, useMenuRadioGroup } from "../context";
4
5
  import type { MenuRadioItemState } from "../types";
5
- import { useOrganizedChildren } from "../use-organized-children";
6
6
  import { MenuSelectionIndicator } from "./menu-selection-indicator";
7
7
 
8
8
  export interface MenuRadioItemProps {
@@ -46,7 +46,14 @@ export function MenuRadioItem(props: MenuRadioItemProps) {
46
46
  }
47
47
  };
48
48
 
49
- const organizedChildren = useOrganizedChildren(props.children);
49
+ const textStyles = menu.styles?.itemText;
50
+ const iconStyles = menu.styles?.itemIcon;
51
+
52
+ const organizedChildren = useOrganizedChildren(
53
+ props.children,
54
+ textStyles,
55
+ iconStyles,
56
+ );
50
57
 
51
58
  if (props.render) {
52
59
  return (
@@ -31,13 +31,8 @@ export const MenuTrigger = forwardRef<MenuTriggerRef, MenuTriggerProps>(
31
31
 
32
32
  useImperativeHandle(ref, () => ({
33
33
  open: () => {
34
- triggerRef.current?.measureInWindow((pageX, pageY, width, height) => {
35
- menu.setTriggerPosition({
36
- height,
37
- width,
38
- pageX,
39
- pageY,
40
- });
34
+ measureLayoutPosition(triggerRef.current, (layout) => {
35
+ menu.setTriggerPosition(layout);
41
36
  menu.setIsOpen(true);
42
37
  });
43
38
  },
@@ -1,5 +1,6 @@
1
1
  import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
2
  import type { SvgProps } from "../../types/props.types";
3
+ import type { IconProps } from "../icon";
3
4
  import type { MenuContentProps } from "./components/menu-content";
4
5
  import type { MenuOverlayProps } from "./components/menu-overlay";
5
6
 
@@ -15,7 +16,7 @@ export interface MenuStyles {
15
16
  content?: MenuContentProps["style"];
16
17
  item?: Partial<Record<MenuButtonState, StyleProp<ViewStyle>>>;
17
18
  itemText?: StyleProp<TextStyle>;
18
- itemIcon?: SvgProps;
19
+ itemIcon?: IconProps;
19
20
  overlay?: MenuOverlayProps["style"];
20
21
 
21
22
  group?: StyleProp<ViewStyle>;
@@ -1,7 +1,7 @@
1
- import type { ViewRef } from "../../../types/element.types";
2
- import { measureLayoutPosition } from "../../../utils/normalize-layout";
3
1
  import React, { forwardRef, useImperativeHandle, useRef } from "react";
4
2
  import { type PressableProps } from "react-native";
3
+ import type { ViewRef } from "../../../types/element.types";
4
+ import { measureLayoutPosition } from "../../../utils/normalize-layout";
5
5
  import { usePopover } from "../context";
6
6
 
7
7
  export interface PopoverTriggerProps extends PressableProps {
@@ -13,7 +13,10 @@ export interface PopoverTriggerRef {
13
13
  close: () => void;
14
14
  }
15
15
 
16
- export const PopoverTrigger = forwardRef<PopoverTriggerRef, PopoverTriggerProps>((props, ref) => {
16
+ export const PopoverTrigger = forwardRef<
17
+ PopoverTriggerRef,
18
+ PopoverTriggerProps
19
+ >((props, ref) => {
17
20
  const popover = usePopover();
18
21
  const triggerRef = useRef<ViewRef>(null);
19
22
 
@@ -30,13 +33,8 @@ export const PopoverTrigger = forwardRef<PopoverTriggerRef, PopoverTriggerProps>
30
33
 
31
34
  useImperativeHandle(ref, () => ({
32
35
  open: () => {
33
- triggerRef.current?.measureInWindow((pageX, pageY, width, height) => {
34
- popover.setTriggerPosition({
35
- height,
36
- width,
37
- pageX,
38
- pageY,
39
- });
36
+ measureLayoutPosition(triggerRef.current, (layout) => {
37
+ popover.setTriggerPosition(layout);
40
38
  popover.setIsOpen(true);
41
39
  });
42
40
  },
@@ -7,6 +7,7 @@ import React, {
7
7
  useSyncExternalStore,
8
8
  } from "react";
9
9
  import { Platform, View, type HostInstance } from "react-native";
10
+ import { measureLayoutPosition } from "../../utils/normalize-layout";
10
11
  import { PortalOffsetContext, type PortalOffset } from "./portal-offset";
11
12
  import {
12
13
  DEFAULT_PORTAL_HOST,
@@ -72,10 +73,10 @@ function DefaultContainer(props: React.PropsWithChildren) {
72
73
  const [offset, setOffset] = useState<PortalOffset | null>(null);
73
74
 
74
75
  const onLayout = useCallback(() => {
75
- containerRef.current?.measureInWindow((pageX: number, pageY: number) => {
76
+ measureLayoutPosition(containerRef.current, (layout) => {
76
77
  setOffset((prev) => {
77
- if (prev?.x === pageX && prev?.y === pageY) return prev;
78
- return { x: pageX, y: pageY };
78
+ if (prev?.x === layout.pageX && prev?.y === layout.pageY) return prev;
79
+ return { x: layout.pageX, y: layout.pageY };
79
80
  });
80
81
  });
81
82
  }, []);
@@ -24,6 +24,7 @@ export function SelectOverlay(props: SelectOverlayProps) {
24
24
  onPress={() => {
25
25
  select.setIsOpen(false);
26
26
  }}
27
+ pointerEvents="auto"
27
28
  style={[StyleSheet.absoluteFill, composedStyles]}
28
29
  >
29
30
  {props.children}
@@ -44,7 +44,9 @@ export function useSelectVariantDefault(): SelectStyles {
44
44
  },
45
45
  },
46
46
  overlay: {
47
- default: {},
47
+ default: {
48
+ zIndex: 999,
49
+ },
48
50
  disabled: {},
49
51
  },
50
52
  content: {
@@ -55,6 +57,7 @@ export function useSelectVariantDefault(): SelectStyles {
55
57
  borderColor: colors.border,
56
58
  padding: 4,
57
59
  gap: 4,
60
+ zIndex: 1000,
58
61
  },
59
62
  disabled: {},
60
63
  },
@@ -6,9 +6,9 @@ import {
6
6
  type StyleProp,
7
7
  type ViewStyle,
8
8
  } from "react-native";
9
+ import { useOrganizedChildren } from "../../../hooks/use-organized-children";
9
10
  import { useTabsContext } from "../context";
10
11
  import type { TabsItemState } from "../types";
11
- import { useOrganizedChildren } from "../use-organized-children";
12
12
 
13
13
  export interface TabsItemProps extends PressableProps {
14
14
  children: React.ReactNode;
@@ -10,7 +10,7 @@ export type ToastIconProps = SvgProps;
10
10
  export function ToastIcon({
11
11
  render: Component,
12
12
  ...props
13
- }: PropsWithRequiredRender<ToastIconProps>) {
13
+ }: PropsWithRequiredRender<SvgProps>) {
14
14
  const toast = useToast();
15
15
 
16
16
  const composedProps = {
@@ -0,0 +1,56 @@
1
+ import { useEffect, useMemo } from "react";
2
+
3
+ type NavigationContainerRef =
4
+ import("@react-navigation/native").NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>;
5
+
6
+ let useCachedNavigationContainerRef: (() => NavigationContainerRef) | null =
7
+ null;
8
+
9
+ export function useInitializeNavigationContainerRef() {
10
+ useEffect(() => {
11
+ try {
12
+ const expoRouter = require("expo-router");
13
+ if (expoRouter) {
14
+ useCachedNavigationContainerRef = expoRouter.useNavigationContainerRef;
15
+ return;
16
+ }
17
+ const reactNavigation = require("@react-navigation/native");
18
+ if (reactNavigation) {
19
+ useCachedNavigationContainerRef =
20
+ reactNavigation.useNavigationContainerRef;
21
+ }
22
+ } catch (error) {
23
+ console.warn(
24
+ "[useIsReactNavigationModal] Failed to load navigation ref:",
25
+ error,
26
+ );
27
+ }
28
+ }, []);
29
+ }
30
+
31
+ const getIsModal = () => {
32
+ const useNavigationContainerRef = useCachedNavigationContainerRef;
33
+
34
+ if (!useNavigationContainerRef) {
35
+ return false;
36
+ }
37
+
38
+ const navigationRef = useNavigationContainerRef();
39
+ if (!navigationRef) {
40
+ return false;
41
+ }
42
+ const state = navigationRef.getCurrentOptions();
43
+ if (
44
+ state &&
45
+ "presentation" in state &&
46
+ typeof state.presentation === "string"
47
+ ) {
48
+ return state.presentation === "modal";
49
+ }
50
+ return false;
51
+ };
52
+
53
+ export function useIsReactNavigationModal() {
54
+ const isModal = useMemo(getIsModal, []);
55
+ return isModal;
56
+ }
@@ -1,13 +1,13 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { Text, type StyleProp, type TextStyle } from "react-native";
3
- import { getElementProp } from "../../utils/element-utils";
4
- import { Icon, type IconProps } from "../icon";
3
+ import { Icon, type IconProps } from "../components/icon";
4
+ import { getElementProp } from "../utils/element-utils";
5
5
 
6
6
  export function useOrganizedChildren(
7
7
  children: React.ReactNode,
8
8
  textStyle: StyleProp<TextStyle> | undefined,
9
9
  iconProps: IconProps | undefined,
10
- ) {
10
+ ): React.ReactNode {
11
11
  const organizedChildren = useMemo(() => {
12
12
  if (typeof children === "string") {
13
13
  return <Text style={textStyle}>{children}</Text>;
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import {
3
+ Platform,
3
4
  useWindowDimensions,
4
5
  type DisplayMetrics,
5
6
  type LayoutRectangle,
@@ -7,12 +8,17 @@ import {
7
8
  } from "react-native";
8
9
  import { usePortalOffset } from "../components/portal";
9
10
  import { useSafeAreaInsets, type SafeAreaInsets } from "../safe-area";
11
+ import { useIsReactNavigationModal } from "./use-is-react-navigation-modal";
10
12
 
11
13
  type UseRelativePositionArgs = Omit<
12
14
  GetContentStyleArgs,
13
15
  "dimensions" | "insets"
14
16
  >;
15
17
 
18
+ type GetContentStyleArgs = GetPositionArgs &
19
+ GetSidePositionArgs &
20
+ GetAlignPositionArgs;
21
+
16
22
  export function useRelativePosition({
17
23
  align,
18
24
  triggerPosition,
@@ -25,6 +31,8 @@ export function useRelativePosition({
25
31
  const insets = useSafeAreaInsets();
26
32
  const portalOffset = usePortalOffset();
27
33
 
34
+ const isReactNavigationModal = useIsReactNavigationModal();
35
+
28
36
  return useMemo(() => {
29
37
  const hasLayout =
30
38
  triggerPosition.width > 0 &&
@@ -53,7 +61,7 @@ export function useRelativePosition({
53
61
  pageY: triggerPosition.pageY - portalOffset.value.y,
54
62
  };
55
63
 
56
- const style = getContentStyle({
64
+ const args: GetContentStyleArgs = {
57
65
  align,
58
66
  contentLayout,
59
67
  preferredSide,
@@ -62,7 +70,23 @@ export function useRelativePosition({
62
70
  insets,
63
71
  sideOffset,
64
72
  dimensions,
65
- });
73
+ };
74
+
75
+ const sidePosition = getSidePosition(args);
76
+ const alignPosition = getAlignPosition(args);
77
+
78
+ const style: ViewStyle = {
79
+ position: "absolute",
80
+ ...sidePosition,
81
+ ...alignPosition,
82
+ // Temporary fix to calculate portal content relative position correctly when rendered in a React Navigation modal.
83
+ top: Platform.select({
84
+ default: sidePosition.top,
85
+ ios: isReactNavigationModal
86
+ ? sidePosition.top + insets.top
87
+ : sidePosition.top,
88
+ }),
89
+ };
66
90
 
67
91
  return style;
68
92
  }, [
@@ -76,6 +100,7 @@ export function useRelativePosition({
76
100
  dimensions.height,
77
101
  sideOffset,
78
102
  portalOffset,
103
+ isReactNavigationModal,
79
104
  ]);
80
105
  }
81
106
 
@@ -181,11 +206,13 @@ function getSidePosition({
181
206
  };
182
207
  }
183
208
 
209
+ let top = Math.min(
210
+ dimensions.height - insets.bottom - contentLayout.height,
211
+ positionBottom,
212
+ );
213
+
184
214
  return {
185
- top: Math.min(
186
- dimensions.height - insets.bottom - contentLayout.height,
187
- positionBottom,
188
- ),
215
+ top,
189
216
  };
190
217
  }
191
218
 
@@ -265,15 +292,3 @@ function getLeftPosition(
265
292
  ),
266
293
  );
267
294
  }
268
-
269
- type GetContentStyleArgs = GetPositionArgs &
270
- GetSidePositionArgs &
271
- GetAlignPositionArgs;
272
-
273
- function getContentStyle(args: GetContentStyleArgs): ViewStyle {
274
- return {
275
- position: "absolute",
276
- ...getSidePosition(args),
277
- ...getAlignPosition(args),
278
- };
279
- }
package/src/index.tsx CHANGED
@@ -2,6 +2,7 @@ import { AsyncAlertDialogManager } from "./components/alert-dialog/async-alert-d
2
2
  import { PortalHost } from "./components/portal";
3
3
  import { type PortalHostProps } from "./components/portal/portal.constants";
4
4
  import { ToastContainer } from "./components/toast/manager";
5
+ import { useInitializeNavigationContainerRef } from "./hooks/use-is-react-navigation-modal";
5
6
  import { SafeAreaProvider, type SafeAreaInsets } from "./safe-area";
6
7
  import {
7
8
  ThemeProvider,
@@ -24,6 +25,9 @@ export const UIProvider = ({
24
25
  safeAreaInsets,
25
26
  components,
26
27
  }: ProviderProps) => {
28
+ // Temporary fix to calculate portal content relative position correctly when rendered in a React Navigation modal.
29
+ useInitializeNavigationContainerRef();
30
+
27
31
  return (
28
32
  <SafeAreaProvider insets={safeAreaInsets}>
29
33
  <ThemeProvider theme={theme} components={components}>
@@ -7,7 +7,7 @@ import {
7
7
  } from "react";
8
8
  import { useColorScheme } from "react-native";
9
9
  import type { ToastVariants } from "../components/toast/variants";
10
- import type { IconComponent } from "../types/element.types";
10
+ import type { SvgProps } from "../types/props.types";
11
11
  import type { DeepPartial } from "../types/util.types";
12
12
  import { defaultThemeAssets } from "./default";
13
13
  import type {
@@ -34,10 +34,12 @@ interface ThemeContext {
34
34
 
35
35
  export interface ComponentsConfig {
36
36
  toast?: {
37
- icons?: Partial<Record<keyof typeof ToastVariants, IconComponent>>;
37
+ icons?: Partial<
38
+ Record<keyof typeof ToastVariants, React.ComponentType<SvgProps>>
39
+ >;
38
40
  };
39
41
  menu?: {
40
- selectionIcon?: IconComponent;
42
+ selectionIcon?: React.ComponentType<SvgProps>;
41
43
  };
42
44
  }
43
45
 
@@ -1,3 +1,4 @@
1
+ import type React from "react";
1
2
  import type { ColorValue, StyleProp, TextStyle, ViewStyle } from "react-native";
2
3
 
3
4
  export type PropsWithRender<P> = P & {
@@ -5,7 +6,7 @@ export type PropsWithRender<P> = P & {
5
6
  };
6
7
 
7
8
  export type PropsWithRequiredRender<P> = P & {
8
- render: (props: P) => React.ReactNode;
9
+ render: React.ComponentType<P>;
9
10
  };
10
11
 
11
12
  export type SvgProps = {
@@ -25,6 +25,16 @@ export const measureLayoutPosition = (
25
25
  ref: HostInstance | null,
26
26
  callback: (layout: LayoutPosition) => void,
27
27
  ) => {
28
+ if (ref && "getBoundingClientRect" in ref) {
29
+ const rect = (ref as unknown as { getBoundingClientRect: () => DOMRect }).getBoundingClientRect();
30
+ callback({
31
+ height: isValidNumber(rect.height) ? rect.height : 0,
32
+ width: isValidNumber(rect.width) ? rect.width : 0,
33
+ pageX: isValidNumber(rect.x) ? rect.x : 0,
34
+ pageY: isValidNumber(rect.y) ? rect.y : 0,
35
+ });
36
+ return;
37
+ }
28
38
  ref?.measureInWindow((pageX, pageY, width, height) => {
29
39
  callback({
30
40
  height: isValidNumber(height) ? height : 0,
@@ -1,17 +0,0 @@
1
- "use strict";
2
-
3
- import { calculateComposedStyles } from "../../../utils/calculate-styles.js";
4
- import React from "react";
5
- import { Text } from "react-native";
6
- import { useBadge } from "../context.js";
7
- import { jsx as _jsx } from "react/jsx-runtime";
8
- export function BadgeLabel(props) {
9
- const badge = useBadge();
10
- const composedStyle = calculateComposedStyles(badge.styles, badge.state, "label", props.style);
11
- const Component = props.render ?? Text;
12
- return /*#__PURE__*/_jsx(Component, {
13
- ...props,
14
- style: composedStyle
15
- });
16
- }
17
- //# sourceMappingURL=badge-label.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["calculateComposedStyles","React","Text","useBadge","jsx","_jsx","BadgeLabel","props","badge","composedStyle","styles","state","style","Component","render"],"sourceRoot":"../../../../../src","sources":["components/badge/components/badge-label.tsx"],"mappings":";;AAAA,SAASA,uBAAuB,QAAQ,oCAAiC;AACzE,OAAOC,KAAK,MAAM,OAAO;AACzB,SAAyBC,IAAI,QAAwB,cAAc;AACnE,SAASC,QAAQ,QAAQ,eAAY;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAUtC,OAAO,SAASC,UAAUA,CAACC,KAAsB,EAAE;EACjD,MAAMC,KAAK,GAAGL,QAAQ,CAAC,CAAC;EAExB,MAAMM,aAAa,GAAGT,uBAAuB,CAACQ,KAAK,CAACE,MAAM,EAAEF,KAAK,CAACG,KAAK,EAAE,OAAO,EAAEJ,KAAK,CAACK,KAAK,CAAC;EAE9F,MAAMC,SAAS,GAAGN,KAAK,CAACO,MAAM,IAAIZ,IAAI;EACtC,oBAAOG,IAAA,CAACQ,SAAS;IAAA,GAAKN,KAAK;IAAEK,KAAK,EAAEH;EAAc,CAAE,CAAC;AACvD","ignoreList":[]}