react-native-tinyui 0.5.0 → 1.1.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.
Files changed (140) hide show
  1. package/README.md +468 -28
  2. package/ios/ConcentricView/TinyuiConcentricView.h +12 -0
  3. package/ios/ConcentricView/TinyuiConcentricView.mm +60 -0
  4. package/ios/Core/Tinyui.mm +54 -0
  5. package/ios/Core/TinyuiComponentClasses.mm +44 -0
  6. package/ios/Menu/TinyuiMenuBuilder.swift +238 -0
  7. package/ios/Menu/TinyuiMenuProvider.swift +141 -75
  8. package/ios/Menu/TinyuiMenuView.mm +24 -35
  9. package/ios/Popover/TinyuiPopoverProvider.swift +198 -44
  10. package/ios/Popover/TinyuiPopoverView.mm +26 -1
  11. package/ios/SFSymbol/TinyuiSFSymbolEffects.h +9 -0
  12. package/ios/SFSymbol/TinyuiSFSymbolEffects.mm +180 -0
  13. package/ios/SFSymbol/TinyuiSFSymbolImage.h +8 -0
  14. package/ios/SFSymbol/TinyuiSFSymbolImage.mm +141 -0
  15. package/ios/SFSymbol/TinyuiSFSymbolShadowNode.h +31 -0
  16. package/ios/SFSymbol/TinyuiSFSymbolShadowNode.mm +30 -0
  17. package/ios/SFSymbol/TinyuiSFSymbolView.h +4 -0
  18. package/ios/SFSymbol/TinyuiSFSymbolView.mm +173 -0
  19. package/ios/Stepper/TinyuiStepperShadowNode.h +32 -0
  20. package/ios/Stepper/TinyuiStepperShadowNode.mm +28 -0
  21. package/ios/Stepper/TinyuiStepperView.h +12 -0
  22. package/ios/Stepper/TinyuiStepperView.mm +128 -0
  23. package/ios/TipKit/TinyuiTip.swift +31 -0
  24. package/ios/TipKit/TinyuiTipPopoverProvider.swift +276 -0
  25. package/ios/TipKit/TinyuiTipPopoverView.h +8 -0
  26. package/ios/TipKit/TinyuiTipPopoverView.mm +114 -0
  27. package/ios/TipKit/TinyuiTipsRuntime.swift +148 -0
  28. package/lib/module/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
  29. package/lib/module/ConcentricView/index.js +29 -0
  30. package/lib/module/ConcentricView/index.js.map +1 -0
  31. package/lib/module/ConcentricView/types.js +4 -0
  32. package/lib/module/ConcentricView/types.js.map +1 -0
  33. package/lib/module/Menu/MenuNativeComponent.ts +12 -3
  34. package/lib/module/Menu/index.js +17 -12
  35. package/lib/module/Menu/index.js.map +1 -1
  36. package/lib/module/Menu/options.js +4 -12
  37. package/lib/module/Menu/options.js.map +1 -1
  38. package/lib/module/NativeTinyui.js.map +1 -1
  39. package/lib/module/Popover/index.js +4 -2
  40. package/lib/module/Popover/index.js.map +1 -1
  41. package/lib/module/SFSymbol/SFSymbolNativeComponent.ts +20 -0
  42. package/lib/module/SFSymbol/index.js +73 -0
  43. package/lib/module/SFSymbol/index.js.map +1 -0
  44. package/lib/module/SFSymbol/options.js +79 -0
  45. package/lib/module/SFSymbol/options.js.map +1 -0
  46. package/lib/module/SFSymbol/types.js +4 -0
  47. package/lib/module/SFSymbol/types.js.map +1 -0
  48. package/lib/module/Stepper/StepperNativeComponent.ts +29 -0
  49. package/lib/module/Stepper/index.js +75 -0
  50. package/lib/module/Stepper/index.js.map +1 -0
  51. package/lib/module/Stepper/types.js +4 -0
  52. package/lib/module/Stepper/types.js.map +1 -0
  53. package/lib/module/TipKit/Popover.js +89 -0
  54. package/lib/module/TipKit/Popover.js.map +1 -0
  55. package/lib/module/TipKit/TipPopoverNativeComponent.ts +37 -0
  56. package/lib/module/TipKit/index.js +28 -0
  57. package/lib/module/TipKit/index.js.map +1 -0
  58. package/lib/module/TipKit/types.js +4 -0
  59. package/lib/module/TipKit/types.js.map +1 -0
  60. package/lib/module/TipKit/validation.js +24 -0
  61. package/lib/module/TipKit/validation.js.map +1 -0
  62. package/lib/module/index.js +4 -0
  63. package/lib/module/index.js.map +1 -1
  64. package/lib/module/utils/getNativeTinyui.js.map +1 -1
  65. package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts +7 -0
  66. package/lib/typescript/src/ConcentricView/ConcentricViewNativeComponent.d.ts.map +1 -0
  67. package/lib/typescript/src/ConcentricView/index.d.ts +4 -0
  68. package/lib/typescript/src/ConcentricView/index.d.ts.map +1 -0
  69. package/lib/typescript/src/ConcentricView/types.d.ts +6 -0
  70. package/lib/typescript/src/ConcentricView/types.d.ts.map +1 -0
  71. package/lib/typescript/src/Menu/MenuNativeComponent.d.ts +8 -4
  72. package/lib/typescript/src/Menu/MenuNativeComponent.d.ts.map +1 -1
  73. package/lib/typescript/src/Menu/index.d.ts +1 -1
  74. package/lib/typescript/src/Menu/index.d.ts.map +1 -1
  75. package/lib/typescript/src/Menu/options.d.ts +1 -5
  76. package/lib/typescript/src/Menu/options.d.ts.map +1 -1
  77. package/lib/typescript/src/Menu/types.d.ts +26 -7
  78. package/lib/typescript/src/Menu/types.d.ts.map +1 -1
  79. package/lib/typescript/src/NativeTinyui.d.ts +2 -0
  80. package/lib/typescript/src/NativeTinyui.d.ts.map +1 -1
  81. package/lib/typescript/src/Popover/index.d.ts.map +1 -1
  82. package/lib/typescript/src/Popover/types.d.ts +2 -0
  83. package/lib/typescript/src/Popover/types.d.ts.map +1 -1
  84. package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts +11 -0
  85. package/lib/typescript/src/SFSymbol/SFSymbolNativeComponent.d.ts.map +1 -0
  86. package/lib/typescript/src/SFSymbol/index.d.ts +4 -0
  87. package/lib/typescript/src/SFSymbol/index.d.ts.map +1 -0
  88. package/lib/typescript/src/SFSymbol/options.d.ts +86 -0
  89. package/lib/typescript/src/SFSymbol/options.d.ts.map +1 -0
  90. package/lib/typescript/src/SFSymbol/types.d.ts +113 -0
  91. package/lib/typescript/src/SFSymbol/types.d.ts.map +1 -0
  92. package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts +21 -0
  93. package/lib/typescript/src/Stepper/StepperNativeComponent.d.ts.map +1 -0
  94. package/lib/typescript/src/Stepper/index.d.ts +4 -0
  95. package/lib/typescript/src/Stepper/index.d.ts.map +1 -0
  96. package/lib/typescript/src/Stepper/types.d.ts +24 -0
  97. package/lib/typescript/src/Stepper/types.d.ts.map +1 -0
  98. package/lib/typescript/src/TipKit/Popover.d.ts +3 -0
  99. package/lib/typescript/src/TipKit/Popover.d.ts.map +1 -0
  100. package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts +38 -0
  101. package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts.map +1 -0
  102. package/lib/typescript/src/TipKit/index.d.ts +10 -0
  103. package/lib/typescript/src/TipKit/index.d.ts.map +1 -0
  104. package/lib/typescript/src/TipKit/types.d.ts +46 -0
  105. package/lib/typescript/src/TipKit/types.d.ts.map +1 -0
  106. package/lib/typescript/src/TipKit/validation.d.ts +4 -0
  107. package/lib/typescript/src/TipKit/validation.d.ts.map +1 -0
  108. package/lib/typescript/src/index.d.ts +9 -1
  109. package/lib/typescript/src/index.d.ts.map +1 -1
  110. package/lib/typescript/src/utils/getNativeTinyui.d.ts +1 -1
  111. package/lib/typescript/src/utils/getNativeTinyui.d.ts.map +1 -1
  112. package/package.json +37 -2
  113. package/{Tinyui.podspec → react-native-tinyui.podspec} +23 -2
  114. package/src/ConcentricView/ConcentricViewNativeComponent.ts +14 -0
  115. package/src/ConcentricView/index.tsx +34 -0
  116. package/src/ConcentricView/types.ts +6 -0
  117. package/src/Menu/MenuNativeComponent.ts +12 -3
  118. package/src/Menu/index.tsx +35 -12
  119. package/src/Menu/options.ts +2 -20
  120. package/src/Menu/types.ts +28 -7
  121. package/src/NativeTinyui.ts +2 -0
  122. package/src/Popover/index.tsx +8 -3
  123. package/src/Popover/types.ts +2 -0
  124. package/src/SFSymbol/SFSymbolNativeComponent.ts +20 -0
  125. package/src/SFSymbol/index.tsx +89 -0
  126. package/src/SFSymbol/options.ts +116 -0
  127. package/src/SFSymbol/types.ts +158 -0
  128. package/src/Stepper/StepperNativeComponent.ts +29 -0
  129. package/src/Stepper/index.tsx +91 -0
  130. package/src/Stepper/types.ts +24 -0
  131. package/src/TipKit/Popover.tsx +87 -0
  132. package/src/TipKit/TipPopoverNativeComponent.ts +37 -0
  133. package/src/TipKit/index.ts +47 -0
  134. package/src/TipKit/types.ts +57 -0
  135. package/src/TipKit/validation.ts +39 -0
  136. package/src/index.tsx +31 -0
  137. package/src/utils/getNativeTinyui.ts +8 -1
  138. package/ios/Core/TinyuiHostingHelpers.swift +0 -74
  139. package/ios/Menu/TinyuiMenuViewSwift.swift +0 -326
  140. package/ios/Popover/TinyuiPopoverViewSwift.swift +0 -88
@@ -0,0 +1,24 @@
1
+ import type { ViewProps } from 'react-native';
2
+ export interface StepperProps extends Omit<ViewProps, 'children'> {
3
+ /** Controlled value. Update it from onValueChange to accept user changes. */
4
+ value?: number;
5
+ /** Initial uncontrolled value. Defaults to 0. */
6
+ defaultValue?: number;
7
+ /** Lower bound. Defaults to 0. */
8
+ minimumValue?: number;
9
+ /** Upper bound, greater than or equal to minimumValue. Defaults to 100. */
10
+ maximumValue?: number;
11
+ /** Positive increment/decrement amount. Defaults to 1. */
12
+ stepValue?: number;
13
+ /** Emit changes while interacting, rather than only on release. Defaults to true. */
14
+ isContinuous?: boolean;
15
+ /** Repeatedly step while holding either button. Defaults to true. */
16
+ autorepeat?: boolean;
17
+ /** Wrap between the bounds instead of stopping at them. Defaults to false. */
18
+ wraps?: boolean;
19
+ /** Disable user interaction. Defaults to false. */
20
+ disabled?: boolean;
21
+ /** Called with the new value after a user interaction. */
22
+ onValueChange?: (value: number) => void;
23
+ }
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/Stepper/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/D,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC"}
@@ -0,0 +1,3 @@
1
+ import type { TipPopoverProps } from './types.js';
2
+ export declare const Popover: import("react").ForwardRefExoticComponent<TipPopoverProps & import("react").RefAttributes<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>>;
3
+ //# sourceMappingURL=Popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../../src/TipKit/Popover.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,YAAS,CAAC;AAG1D,eAAO,MAAM,OAAO,6LA4EnB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { type CodegenTypes, type ViewProps } from 'react-native';
2
+ import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
3
+ export interface NativeTipPopoverProps extends ViewProps {
4
+ tipId: string;
5
+ title: string;
6
+ message?: string;
7
+ systemImage?: string;
8
+ actions?: ReadonlyArray<Readonly<{
9
+ id: string;
10
+ title: string;
11
+ }>>;
12
+ enabled?: boolean;
13
+ maxDisplayCount?: CodegenTypes.Int32;
14
+ ignoresDisplayFrequency?: boolean;
15
+ arrowEdge?: string;
16
+ onTipStatusChange?: DirectEventHandler<Readonly<{
17
+ tipId: string;
18
+ status: string;
19
+ reason: string;
20
+ }>>;
21
+ onTipVisibleChange?: DirectEventHandler<Readonly<{
22
+ tipId: string;
23
+ visible: boolean;
24
+ }>>;
25
+ onTipAction?: DirectEventHandler<Readonly<{
26
+ tipId: string;
27
+ id: string;
28
+ title: string;
29
+ }>>;
30
+ onTipError?: DirectEventHandler<Readonly<{
31
+ tipId: string;
32
+ code: string;
33
+ message: string;
34
+ }>>;
35
+ }
36
+ declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeTipPopoverProps>;
37
+ export default _default;
38
+ //# sourceMappingURL=TipPopoverNativeComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TipPopoverNativeComponent.d.ts","sourceRoot":"","sources":["../../../../src/TipKit/TipPopoverNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC;IACrC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,kBAAkB,CACpC,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAC5D,CAAC;IACF,kBAAkB,CAAC,EAAE,kBAAkB,CACrC,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAC9C,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAC9B,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CACvD,CAAC;IACF,UAAU,CAAC,EAAE,kBAAkB,CAC7B,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAC3D,CAAC;CACH;;AAED,wBAKE"}
@@ -0,0 +1,10 @@
1
+ import type { TipInvalidationReason, TipKitConfiguration } from './types.js';
2
+ export declare const TipKit: {
3
+ Popover: import("react").ForwardRefExoticComponent<import("./types.js").TipPopoverProps & import("react").RefAttributes<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>>;
4
+ /** Configure TipKit once before mounting tips. Repeating the same options is safe. */
5
+ configure({ displayFrequency, }?: TipKitConfiguration): Promise<void>;
6
+ /** Persistently invalidate a tip, including when its view is not mounted. */
7
+ invalidate(tipId: string, reason?: TipInvalidationReason): Promise<void>;
8
+ };
9
+ export type { TipAction, TipDisplayFrequency, TipError, TipInvalidationReason, TipKitConfiguration, TipPopoverProps, TipStatus, } from './types.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/TipKit/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAS,CAAC;AAI1E,eAAO,MAAM,MAAM;;IAEjB,sFAAsF;sCAGnF,mBAAmB,GAAQ,OAAO,CAAC,IAAI,CAAC;IAc3C,6EAA6E;sBAEpE,MAAM,WACL,qBAAqB,GAC5B,OAAO,CAAC,IAAI,CAAC;CAQjB,CAAC;AAEF,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,SAAS,GACV,MAAM,YAAS,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ViewProps } from 'react-native';
3
+ export type TipDisplayFrequency = 'immediate' | 'hourly' | 'daily' | 'weekly' | 'monthly';
4
+ export interface TipKitConfiguration {
5
+ /** App-wide interval between new tips. Defaults to `daily`. */
6
+ displayFrequency?: TipDisplayFrequency;
7
+ }
8
+ export type TipInvalidationReason = 'actionPerformed' | 'tipClosed';
9
+ export type TipStatus = {
10
+ status: 'pending' | 'available';
11
+ } | {
12
+ status: 'invalidated';
13
+ reason: TipInvalidationReason | 'displayCountExceeded' | 'displayDurationExceeded' | 'unknown';
14
+ };
15
+ export interface TipAction {
16
+ id: string;
17
+ title: string;
18
+ }
19
+ export interface TipError {
20
+ code: string;
21
+ message: string;
22
+ }
23
+ export interface TipPopoverProps extends Omit<ViewProps, 'children'> {
24
+ /** Anchor content. Its existing touch handlers are preserved. */
25
+ children: ReactNode;
26
+ /** Stable identity used by TipKit to persist this tip's history. */
27
+ tipId: string;
28
+ title: string;
29
+ message?: string;
30
+ systemImage?: string;
31
+ actions?: readonly TipAction[];
32
+ /** Allows presentation when TipKit is also eligible. Defaults to true. */
33
+ enabled?: boolean;
34
+ /** Omit to leave the number of presentations unlimited. */
35
+ maxDisplayCount?: number;
36
+ ignoresDisplayFrequency?: boolean;
37
+ /** Preferred arrow edge on the bubble; UIKit may adapt to available space. */
38
+ arrowEdge?: 'top' | 'bottom' | 'leading' | 'trailing' | 'auto';
39
+ /** TipKit eligibility, independent of whether the bubble is on screen. */
40
+ onStatusChange?: (status: TipStatus) => void;
41
+ onVisibleChange?: (visible: boolean) => void;
42
+ /** Actions do not automatically invalidate the tip. */
43
+ onActionPress?: (action: TipAction) => void;
44
+ onError?: (error: TipError) => void;
45
+ }
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/TipKit/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,mBAAmB,GAC7B,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;CACxC;AAED,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG,WAAW,CAAC;AAEpE,MAAM,MAAM,SAAS,GACjB;IAAE,MAAM,EAAE,SAAS,GAAG,WAAW,CAAA;CAAE,GACnC;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EACF,qBAAqB,GACrB,sBAAsB,GACtB,yBAAyB,GACzB,SAAS,CAAC;CACf,CAAC;AAEN,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IAClE,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC/B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;IAC/D,0EAA0E;IAC1E,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACrC"}
@@ -0,0 +1,4 @@
1
+ import type { TipPopoverProps } from './types.js';
2
+ export declare function validateTipId(tipId: string): void;
3
+ export declare function validateTip(props: TipPopoverProps): void;
4
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../../src/TipKit/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAS,CAAC;AAE/C,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CA8BxD"}
@@ -1,5 +1,13 @@
1
1
  export { Menu } from './Menu/index.js';
2
- export type { MenuActionOption, MenuDividerOption, MenuItemState, MenuOption, MenuProps, MenuSectionOption, MenuSubmenuOption, } from './Menu/index.js';
2
+ export { TipKit } from './TipKit/index.js';
3
+ export type { TipAction, TipDisplayFrequency, TipError, TipInvalidationReason, TipPopoverProps, TipKitConfiguration, TipStatus, } from './TipKit/index.js';
4
+ export type { MenuActionOption, MenuActionPressEvent, MenuActionPressEventData, MenuDividerOption, MenuItemState, MenuOption, MenuProps, MenuRef, MenuSectionOption, MenuSubmenuOption, } from './Menu/index.js';
5
+ export { Stepper } from './Stepper/index.js';
6
+ export type { StepperProps } from './Stepper/index.js';
7
+ export { ConcentricView } from './ConcentricView/index.js';
8
+ export type { ConcentricViewProps } from './ConcentricView/index.js';
9
+ export { SFSymbol } from './SFSymbol/index.js';
10
+ export type { SFSymbolContentTransition, SFSymbolEffect, SFSymbolEffectOptions, SFSymbolProps, SFSymbolRenderingMode, SFSymbolScale, SFSymbolTextStyle, SFSymbolWeight, } from './SFSymbol/index.js';
3
11
  export { Popover, PopoverClose } from './Popover/index.js';
4
12
  export type { PopoverArrowEdge, PopoverAttachmentAnchor, PopoverCloseProps, PopoverContent, PopoverContentRenderArgs, PopoverProps, } from './Popover/index.js';
5
13
  export { getNativeTinyui, assertComponentEnabled } from './utils/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAQ,CAAC;AAC9B,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAQ,CAAC;AAEhB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAW,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,cAAc,EACd,wBAAwB,EACxB,YAAY,GACb,MAAM,oBAAW,CAAC;AAEnB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAS,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAS,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAAmB,CAAC;AACpD,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,4BAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAU,CAAC;AAClC,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,SAAS,GACV,MAAM,mBAAU,CAAC;AAClB,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,SAAS,EACT,OAAO,EACP,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAQ,CAAC;AAEhB,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAW,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAAkB,CAAC;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAY,CAAC;AACtC,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,cAAc,GACf,MAAM,qBAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAW,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,cAAc,EACd,wBAAwB,EACxB,YAAY,GACb,MAAM,oBAAW,CAAC;AAEnB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAS,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAS,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAAmB,CAAC;AACpD,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,4BAAmB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type Spec } from '../NativeTinyui.js';
2
- export type TinyuiComponent = 'Menu' | 'Popover' | 'LiquidGlassText';
2
+ export type TinyuiComponent = 'Menu' | 'Popover' | 'LiquidGlassText' | 'Stepper' | 'ConcentricView' | 'SFSymbol' | 'TipKit';
3
3
  /**
4
4
  * Returns the Tinyui TurboModule instance. The native module is always
5
5
  * compiled (Core), so this is safe to call.
@@ -1 +1 @@
1
- {"version":3,"file":"getNativeTinyui.d.ts","sourceRoot":"","sources":["../../../../src/utils/getNativeTinyui.ts"],"names":[],"mappings":"AAAA,OAAqB,EAAE,KAAK,IAAI,EAAE,MAAM,oBAAiB,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAAC;AAKrE;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAStC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAWvE"}
1
+ {"version":3,"file":"getNativeTinyui.d.ts","sourceRoot":"","sources":["../../../../src/utils/getNativeTinyui.ts"],"names":[],"mappings":"AAAA,OAAqB,EAAE,KAAK,IAAI,EAAE,MAAM,oBAAiB,CAAC;AAE1D,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,SAAS,GACT,iBAAiB,GACjB,SAAS,GACT,gBAAgB,GAChB,UAAU,GACV,QAAQ,CAAC;AAKb;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAStC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAWvE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-tinyui",
3
- "version": "0.5.0",
4
- "description": "Dependency-free native iOS Menu, Popover and LiquidGlassText components for React Native",
3
+ "version": "1.1.0",
4
+ "description": "Dependency-free native iOS Menu, Popover, TipKit, Stepper, ConcentricView, SFSymbol and LiquidGlassText components for React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
7
7
  "exports": {
@@ -20,6 +20,26 @@
20
20
  "types": "./lib/typescript/src/Popover/index.d.ts",
21
21
  "default": "./lib/module/Popover/index.js"
22
22
  },
23
+ "./stepper": {
24
+ "react-native-tinyui-source": "./src/Stepper/index.tsx",
25
+ "types": "./lib/typescript/src/Stepper/index.d.ts",
26
+ "default": "./lib/module/Stepper/index.js"
27
+ },
28
+ "./concentric-view": {
29
+ "react-native-tinyui-source": "./src/ConcentricView/index.tsx",
30
+ "types": "./lib/typescript/src/ConcentricView/index.d.ts",
31
+ "default": "./lib/module/ConcentricView/index.js"
32
+ },
33
+ "./sf-symbol": {
34
+ "react-native-tinyui-source": "./src/SFSymbol/index.tsx",
35
+ "types": "./lib/typescript/src/SFSymbol/index.d.ts",
36
+ "default": "./lib/module/SFSymbol/index.js"
37
+ },
38
+ "./tip-kit": {
39
+ "react-native-tinyui-source": "./src/TipKit/index.ts",
40
+ "types": "./lib/typescript/src/TipKit/index.d.ts",
41
+ "default": "./lib/module/TipKit/index.js"
42
+ },
23
43
  "./package.json": "./package.json",
24
44
  "./liquid-glass-text": {
25
45
  "react-native-tinyui-source": "./src/LiquidGlassText/index.tsx",
@@ -52,6 +72,7 @@
52
72
  "ios",
53
73
  "menu",
54
74
  "popover",
75
+ "stepper",
55
76
  "fabric",
56
77
  "liquid-glass"
57
78
  ],
@@ -78,6 +99,7 @@
78
99
  "@react-native/jest-preset": "0.85.0",
79
100
  "@release-it/conventional-changelog": "^11.0.1",
80
101
  "@types/react": "^19.2.0",
102
+ "@types/react-test-renderer": "^19.1.0",
81
103
  "del-cli": "^7.0.0",
82
104
  "eslint": "^9.39.4",
83
105
  "eslint-config-prettier": "^10.1.8",
@@ -88,6 +110,7 @@
88
110
  "react": "19.2.3",
89
111
  "react-native": "0.85.0",
90
112
  "react-native-builder-bob": "^0.43.0",
113
+ "react-test-renderer": "19.2.3",
91
114
  "release-it": "^20.2.0",
92
115
  "turbo": "^2.9.16",
93
116
  "typescript": "^6.0.3"
@@ -137,6 +160,18 @@
137
160
  },
138
161
  "TinyuiLiquidGlassTextView": {
139
162
  "className": "TinyuiLiquidGlassTextView"
163
+ },
164
+ "TinyuiStepperView": {
165
+ "className": "TinyuiStepperView"
166
+ },
167
+ "TinyuiConcentricView": {
168
+ "className": "TinyuiConcentricView"
169
+ },
170
+ "TinyuiSFSymbolView": {
171
+ "className": "TinyuiSFSymbolView"
172
+ },
173
+ "TinyuiTipPopoverView": {
174
+ "className": "TinyuiTipPopoverView"
140
175
  }
141
176
  }
142
177
  }
@@ -19,6 +19,26 @@ components = {
19
19
  :definition => "TINYUI_FEATURE_LIQUID_GLASS_TEXT=1",
20
20
  :frameworks => ["UIKit", "SwiftUI", "CoreText"],
21
21
  },
22
+ "Stepper" => {
23
+ :source_files => "ios/Stepper/**/*.{h,m,mm,swift,cpp}",
24
+ :definition => "TINYUI_FEATURE_STEPPER=1",
25
+ :frameworks => ["UIKit"],
26
+ },
27
+ "ConcentricView" => {
28
+ :source_files => "ios/ConcentricView/**/*.{h,m,mm,swift,cpp}",
29
+ :definition => "TINYUI_FEATURE_CONCENTRIC_VIEW=1",
30
+ :frameworks => ["UIKit"],
31
+ },
32
+ "SFSymbol" => {
33
+ :source_files => "ios/SFSymbol/**/*.{h,m,mm,swift,cpp}",
34
+ :definition => "TINYUI_FEATURE_SF_SYMBOL=1",
35
+ :frameworks => ["UIKit", "Symbols"],
36
+ },
37
+ "TipKit" => {
38
+ :source_files => "ios/TipKit/**/*.{h,m,mm,swift,cpp}",
39
+ :definition => "TINYUI_FEATURE_TIP_KIT=1",
40
+ :frameworks => ["UIKit", "SwiftUI", "TipKit"],
41
+ },
22
42
  }
23
43
 
24
44
  configured_components = nil
@@ -68,7 +88,8 @@ definitions = selected_components.map { |component| component[:definition] }
68
88
  frameworks = selected_components.flat_map { |component| component.fetch(:frameworks, []) }.uniq
69
89
 
70
90
  Pod::Spec.new do |s|
71
- s.name = "Tinyui"
91
+ s.name = "react-native-tinyui"
92
+ s.module_name = "Tinyui"
72
93
  s.version = package["version"]
73
94
  s.summary = package["description"]
74
95
  s.homepage = package["homepage"]
@@ -79,7 +100,7 @@ Pod::Spec.new do |s|
79
100
  s.source = { :git => "https://github.com/luoxuhai/react-native-tinyui.git", :tag => "#{s.version}" }
80
101
 
81
102
  s.source_files = source_files
82
- s.private_header_files = ["ios/Core/**/*.h", "ios/Menu/**/*.h", "ios/Popover/**/*.h", "ios/LiquidGlassText/**/*.h"]
103
+ s.private_header_files = ["ios/Core/**/*.h", "ios/Menu/**/*.h", "ios/Popover/**/*.h", "ios/LiquidGlassText/**/*.h", "ios/Stepper/**/*.h", "ios/ConcentricView/**/*.h", "ios/SFSymbol/**/*.h", "ios/TipKit/**/*.h"]
83
104
  s.preserve_paths = "ios/LiquidGlassText/GlassText-LICENSE"
84
105
  s.swift_version = "5.0"
85
106
  s.frameworks = frameworks unless frameworks.empty?
@@ -0,0 +1,14 @@
1
+ import {
2
+ codegenNativeComponent,
3
+ type CodegenTypes,
4
+ type ViewProps,
5
+ } from 'react-native';
6
+
7
+ export interface NativeConcentricViewProps extends ViewProps {
8
+ minimumRadius?: CodegenTypes.WithDefault<CodegenTypes.Double, 0>;
9
+ }
10
+
11
+ export default codegenNativeComponent<NativeConcentricViewProps>(
12
+ 'TinyuiConcentricView',
13
+ { excludedPlatforms: ['android'] }
14
+ );
@@ -0,0 +1,34 @@
1
+ import { forwardRef, type ComponentRef } from 'react';
2
+ import { StyleSheet, type View } from 'react-native';
3
+
4
+ import { assertComponentEnabled } from '../utils';
5
+ import NativeConcentricView from './ConcentricViewNativeComponent';
6
+ import type { ConcentricViewProps } from './types';
7
+
8
+ export const ConcentricView = forwardRef<
9
+ ComponentRef<typeof View>,
10
+ ConcentricViewProps
11
+ >(function ConcentricViewRoot({ minimumRadius = 0, style, ...viewProps }, ref) {
12
+ assertComponentEnabled('ConcentricView');
13
+
14
+ if (!Number.isFinite(minimumRadius) || minimumRadius < 0) {
15
+ throw new RangeError(
16
+ '[TinyUI] ConcentricView minimumRadius must be a finite, nonnegative number.'
17
+ );
18
+ }
19
+
20
+ return (
21
+ <NativeConcentricView
22
+ {...viewProps}
23
+ ref={ref}
24
+ minimumRadius={minimumRadius}
25
+ style={[styles.container, style]}
26
+ />
27
+ );
28
+ });
29
+
30
+ const styles = StyleSheet.create({
31
+ container: { overflow: 'hidden' },
32
+ });
33
+
34
+ export type { ConcentricViewProps } from './types';
@@ -0,0 +1,6 @@
1
+ import type { ViewProps } from 'react-native';
2
+
3
+ export interface ConcentricViewProps extends ViewProps {
4
+ /** Fixed fallback radius on iOS < 26. Defaults to 0. Ignored on iOS 26+. */
5
+ minimumRadius?: number;
6
+ }
@@ -1,6 +1,9 @@
1
+ import type * as React from 'react';
1
2
  import {
2
3
  codegenNativeComponent,
4
+ codegenNativeCommands,
3
5
  type CodegenTypes,
6
+ type HostComponent,
4
7
  type ViewProps,
5
8
  } from 'react-native';
6
9
  import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
@@ -9,11 +12,17 @@ export interface NativeMenuProps extends ViewProps {
9
12
  menuConfig: CodegenTypes.UnsafeMixed;
10
13
  title?: string;
11
14
  disabled?: boolean;
12
- hasPrimaryAction?: boolean;
13
- onItemPress?: DirectEventHandler<Readonly<{ id: string }>>;
14
- onPrimaryAction?: DirectEventHandler<null>;
15
+ onActionPress?: DirectEventHandler<Readonly<{ id: string; title: string }>>;
15
16
  }
16
17
 
18
+ interface NativeCommands {
19
+ open: (viewRef: React.ComponentRef<HostComponent<NativeMenuProps>>) => void;
20
+ }
21
+
22
+ export const Commands = codegenNativeCommands<NativeCommands>({
23
+ supportedCommands: ['open'],
24
+ });
25
+
17
26
  export default codegenNativeComponent<NativeMenuProps>('TinyuiMenuView', {
18
27
  excludedPlatforms: ['android'],
19
28
  });
@@ -1,17 +1,22 @@
1
- import { forwardRef, type ComponentRef } from 'react';
2
- import { View } from 'react-native';
1
+ import {
2
+ forwardRef,
3
+ useImperativeHandle,
4
+ useRef,
5
+ type ComponentRef,
6
+ } from 'react';
7
+ import { View, type HostInstance } from 'react-native';
3
8
 
4
9
  import { assertComponentEnabled } from '../utils';
5
- import type { MenuComponent, MenuProps } from './types';
6
- import NativeMenuView from './MenuNativeComponent';
10
+ import type { MenuComponent, MenuProps, MenuRef } from './types';
11
+ import NativeMenuView, { Commands } from './MenuNativeComponent';
7
12
  import { serializeMenuOptions } from './options';
8
13
 
9
- const MenuRoot = forwardRef<ComponentRef<typeof View>, MenuProps>(function Menu(
14
+ const MenuRoot = forwardRef<MenuRef, MenuProps>(function Menu(
10
15
  {
11
16
  accessibilityLabel,
12
17
  children,
13
18
  disabled,
14
- onPrimaryAction,
19
+ onActionPress,
15
20
  options,
16
21
  title,
17
22
  testID,
@@ -21,17 +26,32 @@ const MenuRoot = forwardRef<ComponentRef<typeof View>, MenuProps>(function Menu(
21
26
  ) {
22
27
  assertComponentEnabled('Menu');
23
28
 
24
- const { config, callbacks } = serializeMenuOptions(options);
29
+ const viewRef = useRef<HostInstance>(null);
30
+ const nativeRef = useRef<ComponentRef<typeof NativeMenuView>>(null);
31
+
32
+ useImperativeHandle(
33
+ ref,
34
+ () =>
35
+ Object.assign(viewRef.current!, {
36
+ open() {
37
+ if (!disabled && nativeRef.current) {
38
+ Commands.open(nativeRef.current);
39
+ }
40
+ },
41
+ }),
42
+ [disabled]
43
+ );
44
+
45
+ const menuConfig = serializeMenuOptions(options);
25
46
 
26
47
  return (
27
- <View {...viewProps} ref={ref} collapsable={false}>
48
+ <View {...viewProps} ref={viewRef} collapsable={false}>
28
49
  <NativeMenuView
50
+ ref={nativeRef}
29
51
  accessibilityLabel={accessibilityLabel}
30
52
  disabled={disabled}
31
- hasPrimaryAction={onPrimaryAction != null}
32
- menuConfig={config}
33
- onItemPress={(event) => callbacks.get(event.nativeEvent.id)?.()}
34
- onPrimaryAction={onPrimaryAction}
53
+ menuConfig={menuConfig}
54
+ onActionPress={onActionPress}
35
55
  testID={testID}
36
56
  title={title}
37
57
  >
@@ -45,10 +65,13 @@ export const Menu = MenuRoot as MenuComponent;
45
65
 
46
66
  export type {
47
67
  MenuActionOption,
68
+ MenuActionPressEvent,
69
+ MenuActionPressEventData,
48
70
  MenuDividerOption,
49
71
  MenuItemState,
50
72
  MenuOption,
51
73
  MenuProps,
74
+ MenuRef,
52
75
  MenuSectionOption,
53
76
  MenuSubmenuOption,
54
77
  } from './types';
@@ -52,30 +52,18 @@ interface NativeMenuConfiguration {
52
52
  items: NativeMenuElement[];
53
53
  }
54
54
 
55
- export interface SerializedMenuOptions {
56
- config: NativeMenuConfiguration;
57
- callbacks: Map<string, () => void>;
58
- }
59
-
60
55
  function serializeColor(color: ColorValue | undefined): NativeMenuColor {
61
56
  return color === undefined ? undefined : processColor(color);
62
57
  }
63
58
 
64
59
  export function serializeMenuOptions(
65
60
  options: readonly MenuOption[]
66
- ): SerializedMenuOptions {
67
- const callbacks = new Map<string, () => void>();
68
- const items = serializeOptions(options, callbacks, new Set(), 'root');
69
-
70
- return {
71
- callbacks,
72
- config: { items },
73
- };
61
+ ): NativeMenuConfiguration {
62
+ return { items: serializeOptions(options, new Set(), 'root') };
74
63
  }
75
64
 
76
65
  function serializeOptions(
77
66
  options: readonly MenuOption[],
78
- callbacks: Map<string, () => void>,
79
67
  usedIds: Set<string>,
80
68
  path: string
81
69
  ): NativeMenuElement[] {
@@ -101,7 +89,6 @@ function serializeOptions(
101
89
  displayInline: option.displayInline ?? false,
102
90
  children: serializeOptions(
103
91
  option.options,
104
- callbacks,
105
92
  usedIds,
106
93
  `${optionPath}.submenu`
107
94
  ),
@@ -114,7 +101,6 @@ function serializeOptions(
114
101
  title: option.title,
115
102
  children: serializeOptions(
116
103
  option.options,
117
- callbacks,
118
104
  usedIds,
119
105
  `${optionPath}.section`
120
106
  ),
@@ -127,10 +113,6 @@ function serializeOptions(
127
113
  }
128
114
  usedIds.add(id);
129
115
 
130
- if (option.onSelect) {
131
- callbacks.set(id, option.onSelect);
132
- }
133
-
134
116
  return {
135
117
  type: 'action',
136
118
  id,
package/src/Menu/types.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import type {
2
- ComponentRef,
3
2
  ForwardRefExoticComponent,
4
3
  ReactNode,
5
4
  RefAttributes,
6
5
  } from 'react';
7
- import type { ColorValue, View, ViewProps } from 'react-native';
6
+ import type { ColorValue, HostInstance, ViewProps } from 'react-native';
8
7
 
9
8
  export type MenuItemState = 'off' | 'on' | 'mixed';
10
9
 
@@ -17,7 +16,11 @@ interface MenuOptionLabel {
17
16
  icon?: string;
18
17
  /** Tint applied to `icon` or `systemImage`. */
19
18
  iconColor?: ColorValue;
20
- /** Foreground color applied to the option title. */
19
+ /**
20
+ * Retained for source compatibility. UIKit menu elements don't expose a
21
+ * public custom title-color API; use `destructive` for system red styling.
22
+ * @deprecated UIKit ignores custom menu title colors.
23
+ */
21
24
  titleColor?: ColorValue;
22
25
  }
23
26
 
@@ -32,7 +35,6 @@ export interface MenuActionOption extends MenuOptionLabel {
32
35
  hidden?: boolean;
33
36
  /** Keep the menu visible after selection on iOS 16 and newer. */
34
37
  keepOpen?: boolean;
35
- onSelect?: () => void;
36
38
  }
37
39
 
38
40
  export interface MenuSubmenuOption extends MenuOptionLabel {
@@ -61,6 +63,25 @@ export interface MenuDividerOption {
61
63
  export type MenuOption =
62
64
  MenuActionOption | MenuSubmenuOption | MenuSectionOption | MenuDividerOption;
63
65
 
66
+ export interface MenuActionPressEventData {
67
+ /** The selected action's explicit id, or its generated menu-path id. */
68
+ id: string;
69
+ /** The selected action's displayed title. */
70
+ title: string;
71
+ }
72
+
73
+ export type MenuActionPressEvent = Readonly<{
74
+ nativeEvent: Readonly<MenuActionPressEventData>;
75
+ }>;
76
+
77
+ export type MenuRef = HostInstance & {
78
+ /**
79
+ * Opens the menu at its mounted trigger on iOS 17.4 and newer.
80
+ * Does nothing on older iOS versions or while disabled or detached.
81
+ */
82
+ open(): void;
83
+ };
84
+
64
85
  export interface MenuProps extends Omit<ViewProps, 'children'> {
65
86
  /** The trigger element. */
66
87
  children: ReactNode;
@@ -70,10 +91,10 @@ export interface MenuProps extends Omit<ViewProps, 'children'> {
70
91
  options: readonly MenuOption[];
71
92
  /** Prevents the trigger from opening the menu. */
72
93
  disabled?: boolean;
73
- /** Called on a normal tap. When set, a long press opens the menu. */
74
- onPrimaryAction?: () => void;
94
+ /** Called whenever an enabled action is selected. */
95
+ onActionPress?: (event: MenuActionPressEvent) => void;
75
96
  }
76
97
 
77
98
  export interface MenuComponent extends ForwardRefExoticComponent<
78
- MenuProps & RefAttributes<ComponentRef<typeof View>>
99
+ MenuProps & RefAttributes<MenuRef>
79
100
  > {}
@@ -7,6 +7,8 @@ export interface Spec extends TurboModule {
7
7
  * based on the `react-native-tinyui.components` array in package.json.
8
8
  */
9
9
  getEnabledComponents(): ReadonlyArray<string>;
10
+ configureTips(displayFrequency: string): Promise<void>;
11
+ invalidateTip(tipId: string, reason: string): Promise<void>;
10
12
  }
11
13
 
12
14
  export default TurboModuleRegistry.get<Spec>('Tinyui');