@korsolutions/ui 0.0.57 → 0.0.59

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 (101) hide show
  1. package/dist/module/components/icon/icon.js +3 -3
  2. package/dist/module/components/icon/icon.js.map +1 -1
  3. package/dist/module/components/menu/components/menu-checkbox-item.js +51 -0
  4. package/dist/module/components/menu/components/menu-checkbox-item.js.map +1 -0
  5. package/dist/module/components/menu/components/menu-content.js +1 -1
  6. package/dist/module/components/menu/components/menu-content.js.map +1 -1
  7. package/dist/module/components/menu/components/menu-group.js +18 -0
  8. package/dist/module/components/menu/components/menu-group.js.map +1 -0
  9. package/dist/module/components/menu/components/menu-item.js +14 -6
  10. package/dist/module/components/menu/components/menu-item.js.map +1 -1
  11. package/dist/module/components/menu/components/menu-label.js +17 -0
  12. package/dist/module/components/menu/components/menu-label.js.map +1 -0
  13. package/dist/module/components/menu/components/menu-overlay.js +1 -1
  14. package/dist/module/components/menu/components/menu-overlay.js.map +1 -1
  15. package/dist/module/components/menu/components/menu-radio-group.js +24 -0
  16. package/dist/module/components/menu/components/menu-radio-group.js.map +1 -0
  17. package/dist/module/components/menu/components/menu-radio-item.js +54 -0
  18. package/dist/module/components/menu/components/menu-radio-item.js.map +1 -0
  19. package/dist/module/components/menu/components/menu-separator.js +17 -0
  20. package/dist/module/components/menu/components/menu-separator.js.map +1 -0
  21. package/dist/module/components/menu/components/menu-shortcut.js +17 -0
  22. package/dist/module/components/menu/components/menu-shortcut.js.map +1 -0
  23. package/dist/module/components/menu/context.js +8 -0
  24. package/dist/module/components/menu/context.js.map +1 -1
  25. package/dist/module/components/menu/index.js +15 -1
  26. package/dist/module/components/menu/index.js.map +1 -1
  27. package/dist/module/components/menu/use-organized-children.js +39 -0
  28. package/dist/module/components/menu/use-organized-children.js.map +1 -0
  29. package/dist/module/components/menu/variants/default.js +82 -6
  30. package/dist/module/components/menu/variants/default.js.map +1 -1
  31. package/dist/module/components/portal/portal.js.map +1 -1
  32. package/dist/module/components/touchable/touchable.js +1 -1
  33. package/dist/module/components/touchable/touchable.js.map +1 -1
  34. package/dist/module/components/touchable/variants/default.js +4 -2
  35. package/dist/module/components/touchable/variants/default.js.map +1 -1
  36. package/dist/module/themes/provider.js.map +1 -1
  37. package/dist/module/utils/element-utils.js +11 -0
  38. package/dist/module/utils/element-utils.js.map +1 -0
  39. package/dist/typescript/src/components/icon/icon.d.ts +2 -2
  40. package/dist/typescript/src/components/icon/icon.d.ts.map +1 -1
  41. package/dist/typescript/src/components/menu/components/menu-checkbox-item.d.ts +13 -0
  42. package/dist/typescript/src/components/menu/components/menu-checkbox-item.d.ts.map +1 -0
  43. package/dist/typescript/src/components/menu/components/menu-content.d.ts.map +1 -1
  44. package/dist/typescript/src/components/menu/components/menu-group.d.ts +9 -0
  45. package/dist/typescript/src/components/menu/components/menu-group.d.ts.map +1 -0
  46. package/dist/typescript/src/components/menu/components/menu-item.d.ts +3 -3
  47. package/dist/typescript/src/components/menu/components/menu-item.d.ts.map +1 -1
  48. package/dist/typescript/src/components/menu/components/menu-label.d.ts +9 -0
  49. package/dist/typescript/src/components/menu/components/menu-label.d.ts.map +1 -0
  50. package/dist/typescript/src/components/menu/components/menu-overlay.d.ts.map +1 -1
  51. package/dist/typescript/src/components/menu/components/menu-radio-group.d.ts +10 -0
  52. package/dist/typescript/src/components/menu/components/menu-radio-group.d.ts.map +1 -0
  53. package/dist/typescript/src/components/menu/components/menu-radio-item.d.ts +12 -0
  54. package/dist/typescript/src/components/menu/components/menu-radio-item.d.ts.map +1 -0
  55. package/dist/typescript/src/components/menu/components/menu-separator.d.ts +8 -0
  56. package/dist/typescript/src/components/menu/components/menu-separator.d.ts.map +1 -0
  57. package/dist/typescript/src/components/menu/components/menu-shortcut.d.ts +9 -0
  58. package/dist/typescript/src/components/menu/components/menu-shortcut.d.ts.map +1 -0
  59. package/dist/typescript/src/components/menu/context.d.ts +7 -1
  60. package/dist/typescript/src/components/menu/context.d.ts.map +1 -1
  61. package/dist/typescript/src/components/menu/index.d.ts +21 -0
  62. package/dist/typescript/src/components/menu/index.d.ts.map +1 -1
  63. package/dist/typescript/src/components/menu/types.d.ts +17 -2
  64. package/dist/typescript/src/components/menu/types.d.ts.map +1 -1
  65. package/dist/typescript/src/components/menu/use-organized-children.d.ts +3 -0
  66. package/dist/typescript/src/components/menu/use-organized-children.d.ts.map +1 -0
  67. package/dist/typescript/src/components/menu/variants/default.d.ts.map +1 -1
  68. package/dist/typescript/src/components/portal/portal.d.ts +2 -2
  69. package/dist/typescript/src/components/portal/portal.d.ts.map +1 -1
  70. package/dist/typescript/src/components/touchable/touchable.d.ts +2 -3
  71. package/dist/typescript/src/components/touchable/touchable.d.ts.map +1 -1
  72. package/dist/typescript/src/components/touchable/variants/default.d.ts.map +1 -1
  73. package/dist/typescript/src/themes/provider.d.ts +2 -2
  74. package/dist/typescript/src/themes/provider.d.ts.map +1 -1
  75. package/dist/typescript/src/types/element.types.d.ts +2 -0
  76. package/dist/typescript/src/types/element.types.d.ts.map +1 -1
  77. package/dist/typescript/src/utils/element-utils.d.ts +3 -0
  78. package/dist/typescript/src/utils/element-utils.d.ts.map +1 -0
  79. package/package.json +1 -1
  80. package/src/components/icon/icon.tsx +9 -3
  81. package/src/components/menu/components/menu-checkbox-item.tsx +74 -0
  82. package/src/components/menu/components/menu-content.tsx +2 -1
  83. package/src/components/menu/components/menu-group.tsx +25 -0
  84. package/src/components/menu/components/menu-item.tsx +25 -9
  85. package/src/components/menu/components/menu-label.tsx +21 -0
  86. package/src/components/menu/components/menu-overlay.tsx +11 -2
  87. package/src/components/menu/components/menu-radio-group.tsx +35 -0
  88. package/src/components/menu/components/menu-radio-item.tsx +80 -0
  89. package/src/components/menu/components/menu-separator.tsx +22 -0
  90. package/src/components/menu/components/menu-shortcut.tsx +21 -0
  91. package/src/components/menu/context.ts +18 -1
  92. package/src/components/menu/index.ts +21 -0
  93. package/src/components/menu/types.ts +25 -2
  94. package/src/components/menu/use-organized-children.tsx +38 -0
  95. package/src/components/menu/variants/default.tsx +82 -6
  96. package/src/components/portal/portal.tsx +23 -5
  97. package/src/components/touchable/touchable.tsx +3 -9
  98. package/src/components/touchable/variants/default.tsx +2 -0
  99. package/src/themes/provider.tsx +2 -4
  100. package/src/types/element.types.ts +10 -1
  101. package/src/utils/element-utils.ts +12 -0
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { View, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useMenu } from "../context";
4
+
5
+ export interface MenuGroupProps {
6
+ children?: React.ReactNode;
7
+ render?: (props: MenuGroupProps) => React.ReactNode;
8
+ style?: StyleProp<ViewStyle>;
9
+ }
10
+
11
+ export function MenuGroup(props: MenuGroupProps) {
12
+ const menu = useMenu();
13
+ const composedStyle = [menu.styles?.group, props.style];
14
+
15
+ const Component = props.render ?? View;
16
+ return (
17
+ <Component
18
+ {...props}
19
+ role="group"
20
+ style={composedStyle}
21
+ >
22
+ {props.children}
23
+ </Component>
24
+ );
25
+ }
@@ -1,14 +1,15 @@
1
1
  import React, { useState } from "react";
2
- import { type StyleProp, Text, type TextStyle } from "react-native";
2
+ import { Pressable, type StyleProp, type ViewStyle } from "react-native";
3
3
  import { useMenu } from "../context";
4
4
  import type { MenuButtonState } from "../types";
5
+ import { useOrganizedChildren } from "../use-organized-children";
5
6
 
6
7
  export interface MenuItemProps {
7
- children: string;
8
+ children: React.ReactNode;
8
9
  onPress?: () => void;
9
10
 
10
11
  render?: (props: MenuItemProps) => React.ReactNode;
11
- style?: StyleProp<TextStyle>;
12
+ style?: StyleProp<ViewStyle>;
12
13
  }
13
14
 
14
15
  const calculateState = (isHovered: boolean): MenuButtonState => {
@@ -22,23 +23,38 @@ export function MenuItem(props: MenuItemProps) {
22
23
  const menu = useMenu();
23
24
  const [isHovered, setIsHovered] = useState(false);
24
25
  const state = calculateState(isHovered);
25
- const composedStyle = [menu.styles?.item?.default, menu.styles?.item?.[state], props.style];
26
+ const composedStyle = [
27
+ menu.styles?.item?.default,
28
+ menu.styles?.item?.[state],
29
+ props.style,
30
+ ];
26
31
 
27
32
  const handlePress = () => {
28
33
  props.onPress?.();
29
34
  menu.setIsOpen((prev) => !prev);
30
35
  };
31
36
 
32
- const Component = props.render ?? Text;
37
+ const organizedChildren = useOrganizedChildren(props.children);
38
+
39
+ if (props.render) {
40
+ return (
41
+ <>
42
+ {props.render({
43
+ ...props,
44
+ children: organizedChildren,
45
+ })}
46
+ </>
47
+ );
48
+ }
49
+
33
50
  return (
34
- <Component
35
- {...props}
51
+ <Pressable
36
52
  onPress={handlePress}
37
53
  onPointerEnter={() => setIsHovered(true)}
38
54
  onPointerLeave={() => setIsHovered(false)}
39
55
  style={composedStyle}
40
56
  >
41
- {props.children}
42
- </Component>
57
+ {organizedChildren}
58
+ </Pressable>
43
59
  );
44
60
  }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { Text, type StyleProp, type TextStyle } from "react-native";
3
+ import { useMenu } from "../context";
4
+
5
+ export interface MenuLabelProps {
6
+ children: string;
7
+ render?: (props: MenuLabelProps) => React.ReactNode;
8
+ style?: StyleProp<TextStyle>;
9
+ }
10
+
11
+ export function MenuLabel(props: MenuLabelProps) {
12
+ const menu = useMenu();
13
+ const composedStyle = [menu.styles?.label, props.style];
14
+
15
+ const Component = props.render ?? Text;
16
+ return (
17
+ <Component {...props} style={composedStyle}>
18
+ {props.children}
19
+ </Component>
20
+ );
21
+ }
@@ -1,5 +1,10 @@
1
1
  import React from "react";
2
- import { Pressable, type StyleProp, StyleSheet, type ViewStyle } from "react-native";
2
+ import {
3
+ Pressable,
4
+ type StyleProp,
5
+ StyleSheet,
6
+ type ViewStyle,
7
+ } from "react-native";
3
8
  import { useMenu } from "../context";
4
9
 
5
10
  export interface MenuOverlayProps {
@@ -13,7 +18,11 @@ export interface MenuOverlayProps {
13
18
  export function MenuOverlay(props: MenuOverlayProps) {
14
19
  const menu = useMenu();
15
20
 
16
- const composedStyle = [StyleSheet.absoluteFill, menu.styles?.overlay, props.style];
21
+ const composedStyle = StyleSheet.flatten([
22
+ StyleSheet.absoluteFill,
23
+ menu.styles?.overlay,
24
+ props.style,
25
+ ]);
17
26
 
18
27
  const Component = props.render ?? Pressable;
19
28
  return (
@@ -0,0 +1,35 @@
1
+ import React, { useMemo } from "react";
2
+ import { View, type StyleProp, type ViewStyle } from "react-native";
3
+ import { MenuRadioGroupContext, useMenu } from "../context";
4
+
5
+ export interface MenuRadioGroupProps {
6
+ children?: React.ReactNode;
7
+ value: string;
8
+ onValueChange: (value: string) => void;
9
+ style?: StyleProp<ViewStyle>;
10
+ }
11
+
12
+ export function MenuRadioGroup(props: MenuRadioGroupProps) {
13
+ const menu = useMenu();
14
+ const composedStyle = [menu.styles?.radioGroup, props.style];
15
+
16
+ const contextValue = useMemo(
17
+ () => ({
18
+ value: props.value,
19
+ onValueChange: props.onValueChange,
20
+ }),
21
+ [props.value, props.onValueChange],
22
+ );
23
+
24
+ return (
25
+ <MenuRadioGroupContext.Provider value={contextValue}>
26
+ <View
27
+ accessibilityRole="radiogroup"
28
+ role="radiogroup"
29
+ style={composedStyle}
30
+ >
31
+ {props.children}
32
+ </View>
33
+ </MenuRadioGroupContext.Provider>
34
+ );
35
+ }
@@ -0,0 +1,80 @@
1
+ import React, { useState } from "react";
2
+ import { Pressable, View, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useMenu, useMenuRadioGroup } from "../context";
4
+ import type { MenuRadioItemState } from "../types";
5
+ import { useOrganizedChildren } from "../use-organized-children";
6
+
7
+ export interface MenuRadioItemProps {
8
+ children: React.ReactNode;
9
+ value: string;
10
+ disabled?: boolean;
11
+ closeOnPress?: boolean;
12
+ render?: (props: MenuRadioItemProps) => React.ReactNode;
13
+ style?: StyleProp<ViewStyle>;
14
+ }
15
+
16
+ const calculateState = (
17
+ isHovered: boolean,
18
+ isSelected: boolean,
19
+ disabled?: boolean,
20
+ ): MenuRadioItemState => {
21
+ if (disabled) return "disabled";
22
+ if (isSelected) return "selected";
23
+ if (isHovered) return "hovered";
24
+ return "default";
25
+ };
26
+
27
+ export function MenuRadioItem(props: MenuRadioItemProps) {
28
+ const menu = useMenu();
29
+ const radioGroup = useMenuRadioGroup();
30
+ const [isHovered, setIsHovered] = useState(false);
31
+ const isSelected = radioGroup.value === props.value;
32
+ const state = calculateState(isHovered, isSelected, props.disabled);
33
+
34
+ const composedStyle = [
35
+ menu.styles?.radioItem?.default,
36
+ menu.styles?.radioItem?.[state],
37
+ props.style,
38
+ ];
39
+
40
+ const indicatorStyle = [
41
+ menu.styles?.radioIndicator?.default,
42
+ isSelected ? menu.styles?.radioIndicator?.selected : undefined,
43
+ ];
44
+
45
+ const handlePress = () => {
46
+ if (props.disabled) return;
47
+ radioGroup.onValueChange(props.value);
48
+ if (props.closeOnPress) {
49
+ menu.setIsOpen(false);
50
+ }
51
+ };
52
+
53
+ const organizedChildren = useOrganizedChildren(props.children);
54
+
55
+ if (props.render) {
56
+ return (
57
+ <>
58
+ {props.render({
59
+ ...props,
60
+ children: organizedChildren,
61
+ })}
62
+ </>
63
+ );
64
+ }
65
+
66
+ return (
67
+ <Pressable
68
+ onPress={handlePress}
69
+ onPointerEnter={() => setIsHovered(true)}
70
+ onPointerLeave={() => setIsHovered(false)}
71
+ disabled={props.disabled}
72
+ accessibilityRole="radio"
73
+ accessibilityState={{ checked: isSelected, disabled: props.disabled }}
74
+ style={composedStyle}
75
+ >
76
+ {organizedChildren}
77
+ <View style={indicatorStyle} />
78
+ </Pressable>
79
+ );
80
+ }
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import { View, type StyleProp, type ViewStyle } from "react-native";
3
+ import { useMenu } from "../context";
4
+
5
+ export interface MenuSeparatorProps {
6
+ render?: (props: MenuSeparatorProps) => React.ReactNode;
7
+ style?: StyleProp<ViewStyle>;
8
+ }
9
+
10
+ export function MenuSeparator(props: MenuSeparatorProps) {
11
+ const menu = useMenu();
12
+ const composedStyle = [menu.styles?.separator, props.style];
13
+
14
+ const Component = props.render ?? View;
15
+ return (
16
+ <Component
17
+ {...props}
18
+ role="separator"
19
+ style={composedStyle}
20
+ />
21
+ );
22
+ }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { Text, type StyleProp, type TextStyle } from "react-native";
3
+ import { useMenu } from "../context";
4
+
5
+ export interface MenuShortcutProps {
6
+ children: string;
7
+ render?: (props: MenuShortcutProps) => React.ReactNode;
8
+ style?: StyleProp<TextStyle>;
9
+ }
10
+
11
+ export function MenuShortcut(props: MenuShortcutProps) {
12
+ const menu = useMenu();
13
+ const composedStyle = [menu.styles?.shortcut, props.style];
14
+
15
+ const Component = props.render ?? Text;
16
+ return (
17
+ <Component {...props} style={composedStyle}>
18
+ {props.children}
19
+ </Component>
20
+ );
21
+ }
@@ -1,6 +1,6 @@
1
- import type { LayoutPosition } from "../../hooks/use-relative-position";
2
1
  import { createContext, type Dispatch, useContext } from "react";
3
2
  import type { LayoutRectangle } from "react-native";
3
+ import type { LayoutPosition } from "../../hooks/use-relative-position";
4
4
  import type { MenuStyles } from "./types";
5
5
 
6
6
  export interface MenuContext {
@@ -23,3 +23,20 @@ export const useMenu = () => {
23
23
  }
24
24
  return context;
25
25
  };
26
+
27
+ export interface MenuRadioGroupContextValue {
28
+ value: string;
29
+ onValueChange: (value: string) => void;
30
+ }
31
+
32
+ export const MenuRadioGroupContext = createContext<
33
+ MenuRadioGroupContextValue | undefined
34
+ >(undefined);
35
+
36
+ export const useMenuRadioGroup = () => {
37
+ const context = useContext(MenuRadioGroupContext);
38
+ if (!context) {
39
+ throw new Error("useMenuRadioGroup must be used within a Menu.RadioGroup");
40
+ }
41
+ return context;
42
+ };
@@ -1,8 +1,15 @@
1
+ import { MenuCheckboxItem } from "./components/menu-checkbox-item";
1
2
  import { MenuContent } from "./components/menu-content";
3
+ import { MenuGroup } from "./components/menu-group";
2
4
  import { MenuItem } from "./components/menu-item";
5
+ import { MenuLabel } from "./components/menu-label";
3
6
  import { MenuOverlay } from "./components/menu-overlay";
4
7
  import { MenuPortal } from "./components/menu-portal";
8
+ import { MenuRadioGroup } from "./components/menu-radio-group";
9
+ import { MenuRadioItem } from "./components/menu-radio-item";
5
10
  import { MenuRoot } from "./components/menu-root";
11
+ import { MenuSeparator } from "./components/menu-separator";
12
+ import { MenuShortcut } from "./components/menu-shortcut";
6
13
  import { MenuTrigger } from "./components/menu-trigger";
7
14
 
8
15
  export const Menu = {
@@ -12,12 +19,26 @@ export const Menu = {
12
19
  Overlay: MenuOverlay,
13
20
  Content: MenuContent,
14
21
  Item: MenuItem,
22
+ Group: MenuGroup,
23
+ Label: MenuLabel,
24
+ Separator: MenuSeparator,
25
+ CheckboxItem: MenuCheckboxItem,
26
+ RadioGroup: MenuRadioGroup,
27
+ RadioItem: MenuRadioItem,
28
+ Shortcut: MenuShortcut,
15
29
  };
16
30
 
31
+ export type { MenuCheckboxItemProps } from "./components/menu-checkbox-item";
17
32
  export type { MenuContentProps } from "./components/menu-content";
33
+ export type { MenuGroupProps } from "./components/menu-group";
18
34
  export type { MenuItemProps } from "./components/menu-item";
35
+ export type { MenuLabelProps } from "./components/menu-label";
19
36
  export type { MenuOverlayProps } from "./components/menu-overlay";
20
37
  export type { MenuPortalProps } from "./components/menu-portal";
38
+ export type { MenuRadioGroupProps } from "./components/menu-radio-group";
39
+ export type { MenuRadioItemProps } from "./components/menu-radio-item";
21
40
  export type { MenuRootProps } from "./components/menu-root";
41
+ export type { MenuSeparatorProps } from "./components/menu-separator";
42
+ export type { MenuShortcutProps } from "./components/menu-shortcut";
22
43
  export type { MenuTriggerProps } from "./components/menu-trigger";
23
44
  export type { MenuStyles } from "./types";
@@ -1,11 +1,34 @@
1
+ import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ import type { SvgProps } from "../../types/props.types";
1
3
  import type { MenuContentProps } from "./components/menu-content";
2
- import type { MenuItemProps } from "./components/menu-item";
3
4
  import type { MenuOverlayProps } from "./components/menu-overlay";
4
5
 
5
6
  export type MenuButtonState = "default" | "hovered";
7
+ export type MenuCheckboxItemState = "default" | "hovered" | "disabled";
8
+ export type MenuRadioItemState =
9
+ | "default"
10
+ | "hovered"
11
+ | "selected"
12
+ | "disabled";
13
+
14
+ export type MenuRadioIndicatorState = "default" | "selected";
6
15
 
7
16
  export interface MenuStyles {
8
17
  content?: MenuContentProps["style"];
9
- item?: Partial<Record<MenuButtonState, MenuItemProps["style"]>>;
18
+ item?: Partial<Record<MenuButtonState, StyleProp<ViewStyle>>>;
19
+ itemText?: StyleProp<TextStyle>;
20
+ itemIcon?: SvgProps;
10
21
  overlay?: MenuOverlayProps["style"];
22
+
23
+ group?: StyleProp<ViewStyle>;
24
+ label?: StyleProp<TextStyle>;
25
+ separator?: StyleProp<ViewStyle>;
26
+ checkboxItem?: Partial<Record<MenuCheckboxItemState, StyleProp<ViewStyle>>>;
27
+ checkboxIndicator?: StyleProp<TextStyle>;
28
+ radioGroup?: StyleProp<ViewStyle>;
29
+ radioItem?: Partial<Record<MenuRadioItemState, StyleProp<ViewStyle>>>;
30
+ radioIndicator?: Partial<
31
+ Record<MenuRadioIndicatorState, StyleProp<ViewStyle>>
32
+ >;
33
+ shortcut?: StyleProp<TextStyle>;
11
34
  }
@@ -0,0 +1,38 @@
1
+ import React, { useMemo } from "react";
2
+ import { Text } from "react-native";
3
+ import { getElementProp } from "../../utils/element-utils";
4
+ import { Icon } from "../icon";
5
+ import { useMenu } from "./context";
6
+
7
+ export function useOrganizedChildren(children: React.ReactNode) {
8
+ const menu = useMenu();
9
+
10
+ const organizedChildren = useMemo(() => {
11
+ if (typeof children === "string") {
12
+ return <Text style={menu.styles?.itemText}>{children}</Text>;
13
+ }
14
+ if (Array.isArray(children)) {
15
+ return children.map((child, index) => {
16
+ if (typeof child === "string") {
17
+ return (
18
+ <Text key={index} style={menu.styles?.itemText}>
19
+ {child}
20
+ </Text>
21
+ );
22
+ } else if (React.isValidElement(child) && child.type === Icon) {
23
+ return React.cloneElement(child as React.ReactElement<any>, {
24
+ key: child.key,
25
+ ...menu.styles?.itemIcon,
26
+ style: [
27
+ menu.styles?.itemIcon?.style,
28
+ getElementProp(child, "style"),
29
+ ],
30
+ });
31
+ }
32
+ return child;
33
+ });
34
+ }
35
+ return children;
36
+ }, [children, menu.styles?.itemIcon]);
37
+ return organizedChildren;
38
+ }
@@ -4,9 +4,7 @@ import { useThemedStyles } from "../../../utils/use-themed-styles";
4
4
  export const useMenuVariantDefault = (): MenuStyles => {
5
5
  return useThemedStyles(
6
6
  ({ colors, radius, fontFamily, fontSize }): MenuStyles => ({
7
- overlay: {
8
- backgroundColor: "rgba(0, 0, 0, 0.5)",
9
- },
7
+ overlay: {},
10
8
  content: {
11
9
  overflow: "hidden",
12
10
  backgroundColor: colors.surface,
@@ -21,16 +19,94 @@ export const useMenuVariantDefault = (): MenuStyles => {
21
19
  },
22
20
  item: {
23
21
  default: {
22
+ flexDirection: "row",
23
+ alignItems: "center",
24
24
  paddingVertical: 12,
25
25
  paddingHorizontal: 16,
26
- fontFamily: fontFamily,
27
- fontSize: fontSize,
28
- color: colors.foreground,
26
+ gap: 8,
29
27
  },
30
28
  hovered: {
31
29
  backgroundColor: colors.muted,
32
30
  },
33
31
  },
32
+ itemText: {
33
+ fontFamily: fontFamily,
34
+ fontSize: fontSize,
35
+ color: colors.foreground,
36
+ },
37
+ itemIcon: {
38
+ color: colors.foreground,
39
+ size: fontSize * 1.25,
40
+ },
41
+ label: {
42
+ paddingVertical: 8,
43
+ paddingHorizontal: 16,
44
+ fontFamily: fontFamily,
45
+ fontSize: fontSize * 0.75,
46
+ fontWeight: "600",
47
+ color: colors.mutedForeground,
48
+ },
49
+ separator: {
50
+ height: 1,
51
+ backgroundColor: colors.border,
52
+ marginVertical: 4,
53
+ marginHorizontal: 8,
54
+ },
55
+ checkboxItem: {
56
+ default: {
57
+ flexDirection: "row",
58
+ alignItems: "center",
59
+ paddingVertical: 12,
60
+ paddingHorizontal: 16,
61
+ gap: 8,
62
+ },
63
+ hovered: {
64
+ backgroundColor: colors.muted,
65
+ },
66
+ disabled: {
67
+ opacity: 0.5,
68
+ },
69
+ },
70
+ checkboxIndicator: {
71
+ fontSize: fontSize * 0.75,
72
+ fontWeight: "bold",
73
+ color: colors.foreground,
74
+ width: fontSize,
75
+ textAlign: "center",
76
+ marginLeft: "auto",
77
+ },
78
+ radioItem: {
79
+ default: {
80
+ flexDirection: "row",
81
+ alignItems: "center",
82
+ paddingVertical: 12,
83
+ paddingHorizontal: 16,
84
+ gap: 8,
85
+ },
86
+ hovered: {
87
+ backgroundColor: colors.muted,
88
+ },
89
+ disabled: {
90
+ opacity: 0.5,
91
+ },
92
+ },
93
+ radioIndicator: {
94
+ default: {
95
+ width: 8,
96
+ height: 8,
97
+ borderRadius: 4,
98
+ backgroundColor: "transparent",
99
+ marginLeft: "auto",
100
+ },
101
+ selected: {
102
+ backgroundColor: colors.foreground,
103
+ },
104
+ },
105
+ shortcut: {
106
+ fontSize: fontSize * 0.75,
107
+ fontFamily: fontFamily,
108
+ color: colors.mutedForeground,
109
+ },
34
110
  }),
35
111
  );
36
112
  };
@@ -1,6 +1,10 @@
1
1
  import { useEffect, useSyncExternalStore } from "react";
2
2
  import { Platform, View } from "react-native";
3
- import { DEFAULT_PORTAL_HOST, type PortalHostProps, type PortalProps } from "./portal.constants";
3
+ import {
4
+ DEFAULT_PORTAL_HOST,
5
+ type PortalHostProps,
6
+ type PortalProps,
7
+ } from "./portal.constants";
4
8
 
5
9
  type PortalMap = Map<string, React.ReactNode>;
6
10
  type PortalHostMap = Map<string, PortalMap>;
@@ -11,7 +15,10 @@ type PortalStore = {
11
15
  };
12
16
 
13
17
  const store: PortalStore = {
14
- map: new Map<string, PortalMap>().set(DEFAULT_PORTAL_HOST, new Map<string, React.ReactNode>()),
18
+ map: new Map<string, PortalMap>().set(
19
+ DEFAULT_PORTAL_HOST,
20
+ new Map<string, React.ReactNode>(),
21
+ ),
15
22
  listeners: new Set(),
16
23
  };
17
24
 
@@ -30,7 +37,11 @@ function subscribe(cb: () => void) {
30
37
  };
31
38
  }
32
39
 
33
- function updatePortal(hostName: string, name: string, children: React.ReactNode) {
40
+ function updatePortal(
41
+ hostName: string,
42
+ name: string,
43
+ children: React.ReactNode,
44
+ ) {
34
45
  const next = new Map(store.map);
35
46
  const portal = next.get(hostName) ?? new Map<string, React.ReactNode>();
36
47
  portal.set(name, children);
@@ -48,7 +59,10 @@ function removePortal(hostName: string, name: string) {
48
59
  emit();
49
60
  }
50
61
 
51
- export function PortalHost({ name = DEFAULT_PORTAL_HOST, container }: PortalHostProps) {
62
+ export function PortalHost({
63
+ name = DEFAULT_PORTAL_HOST,
64
+ container,
65
+ }: PortalHostProps) {
52
66
  const map = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
53
67
  const portalMap = map.get(name) ?? new Map<string, React.ReactNode>();
54
68
  if (portalMap.size === 0) return null;
@@ -75,7 +89,11 @@ export function PortalHost({ name = DEFAULT_PORTAL_HOST, container }: PortalHost
75
89
  return <Container>{Array.from(portalMap.values())}</Container>;
76
90
  }
77
91
 
78
- export function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }: PortalProps) {
92
+ export function Portal({
93
+ name,
94
+ hostName = DEFAULT_PORTAL_HOST,
95
+ children,
96
+ }: PortalProps) {
79
97
  useEffect(() => {
80
98
  updatePortal(hostName, name, children);
81
99
  }, [hostName, name, children]);
@@ -1,20 +1,14 @@
1
1
  import React, { useState } from "react";
2
- import {
3
- Pressable,
4
- type PressableProps,
5
- type PressableStateCallbackType,
6
- type ViewStyle,
7
- } from "react-native";
2
+ import { Pressable, type PressableProps } from "react-native";
8
3
  import type { PressableState } from "./types";
9
4
  import { PressableVariants } from "./variants";
10
5
 
11
- type ExtendablePressableProps = Omit<PressableProps, "style" | "disabled">;
6
+ type ExtendablePressableProps = Omit<PressableProps, "disabled">;
12
7
 
13
8
  export interface TouchableProps extends ExtendablePressableProps {
14
9
  variant?: keyof typeof PressableVariants;
15
10
  children?: React.ReactNode;
16
11
  isDisabled?: boolean;
17
- style?: (state: PressableStateCallbackType) => ViewStyle;
18
12
  }
19
13
 
20
14
  const calculateState = (
@@ -61,7 +55,7 @@ export function Touchable(props: TouchableProps) {
61
55
  return [
62
56
  variantStyles?.default,
63
57
  variantStyles?.[currentState],
64
- style ? style(styleState) : null,
58
+ typeof style === "function" ? style(styleState) : style,
65
59
  ];
66
60
  }}
67
61
  >
@@ -4,6 +4,7 @@ export const usePressableVariantDefault = (): PressableStyles => {
4
4
  return {
5
5
  default: {
6
6
  cursor: "pointer",
7
+ pointerEvents: "box-only",
7
8
  },
8
9
  pressed: {
9
10
  opacity: 0.8,
@@ -14,6 +15,7 @@ export const usePressableVariantDefault = (): PressableStyles => {
14
15
  },
15
16
  disabled: {
16
17
  cursor: "not-allowed" as any,
18
+ pointerEvents: "none",
17
19
  },
18
20
  };
19
21
  };
@@ -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 { SvgProps } from "../types/props.types";
10
+ import type { IconComponent } from "../types/element.types";
11
11
  import type { DeepPartial } from "../types/util.types";
12
12
  import { defaultThemeAssets } from "./default";
13
13
  import type {
@@ -34,9 +34,7 @@ interface ThemeContext {
34
34
 
35
35
  export interface ComponentsConfig {
36
36
  toast?: {
37
- icons?: Partial<
38
- Record<keyof typeof ToastVariants, (props: SvgProps) => React.ReactNode>
39
- >;
37
+ icons?: Partial<Record<keyof typeof ToastVariants, IconComponent>>;
40
38
  };
41
39
  }
42
40