react-native-tinyui 3.0.0 → 3.2.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 (69) hide show
  1. package/README.md +136 -6
  2. package/ios/Core/Tinyui.mm +3 -0
  3. package/ios/Core/TinyuiComponentClasses.mm +11 -0
  4. package/ios/SwipeActions/TinyuiSwipeActionsView.h +12 -0
  5. package/ios/SwipeActions/TinyuiSwipeActionsView.mm +289 -0
  6. package/ios/TipKit/TinyuiTipPopoverProvider.swift +29 -2
  7. package/ios/TipKit/TinyuiTipPopoverView.mm +10 -0
  8. package/ios/TipKit/TinyuiTipView.mm +9 -0
  9. package/ios/TipKit/TinyuiTipViewProvider.swift +8 -2
  10. package/ios/TipKit/TinyuiTipsRuntime.swift +12 -0
  11. package/lib/module/SwipeActions/SwipeActionsNativeComponent.ts +19 -0
  12. package/lib/module/SwipeActions/actions.js +21 -0
  13. package/lib/module/SwipeActions/actions.js.map +1 -0
  14. package/lib/module/SwipeActions/index.js +43 -0
  15. package/lib/module/SwipeActions/index.js.map +1 -0
  16. package/lib/module/SwipeActions/types.js +4 -0
  17. package/lib/module/SwipeActions/types.js.map +1 -0
  18. package/lib/module/TipKit/Group.js +52 -0
  19. package/lib/module/TipKit/Group.js.map +1 -0
  20. package/lib/module/TipKit/Popover.js +15 -1
  21. package/lib/module/TipKit/Popover.js.map +1 -1
  22. package/lib/module/TipKit/TipPopoverNativeComponent.ts +7 -0
  23. package/lib/module/TipKit/TipViewNativeComponent.ts +6 -0
  24. package/lib/module/TipKit/View.js +13 -1
  25. package/lib/module/TipKit/View.js.map +1 -1
  26. package/lib/module/TipKit/index.js +2 -0
  27. package/lib/module/TipKit/index.js.map +1 -1
  28. package/lib/module/index.js +1 -0
  29. package/lib/module/index.js.map +1 -1
  30. package/lib/module/utils/getNativeTinyui.js.map +1 -1
  31. package/lib/typescript/src/SwipeActions/SwipeActionsNativeComponent.d.ts +15 -0
  32. package/lib/typescript/src/SwipeActions/SwipeActionsNativeComponent.d.ts.map +1 -0
  33. package/lib/typescript/src/SwipeActions/actions.d.ts +9 -0
  34. package/lib/typescript/src/SwipeActions/actions.d.ts.map +1 -0
  35. package/lib/typescript/src/SwipeActions/index.d.ts +4 -0
  36. package/lib/typescript/src/SwipeActions/index.d.ts.map +1 -0
  37. package/lib/typescript/src/SwipeActions/types.d.ts +37 -0
  38. package/lib/typescript/src/SwipeActions/types.d.ts.map +1 -0
  39. package/lib/typescript/src/TipKit/Group.d.ts +13 -0
  40. package/lib/typescript/src/TipKit/Group.d.ts.map +1 -0
  41. package/lib/typescript/src/TipKit/Popover.d.ts.map +1 -1
  42. package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts +5 -0
  43. package/lib/typescript/src/TipKit/TipPopoverNativeComponent.d.ts.map +1 -1
  44. package/lib/typescript/src/TipKit/TipViewNativeComponent.d.ts +4 -0
  45. package/lib/typescript/src/TipKit/TipViewNativeComponent.d.ts.map +1 -1
  46. package/lib/typescript/src/TipKit/View.d.ts.map +1 -1
  47. package/lib/typescript/src/TipKit/index.d.ts +3 -1
  48. package/lib/typescript/src/TipKit/index.d.ts.map +1 -1
  49. package/lib/typescript/src/TipKit/types.d.ts +18 -0
  50. package/lib/typescript/src/TipKit/types.d.ts.map +1 -1
  51. package/lib/typescript/src/index.d.ts +3 -1
  52. package/lib/typescript/src/index.d.ts.map +1 -1
  53. package/lib/typescript/src/utils/getNativeTinyui.d.ts +1 -1
  54. package/lib/typescript/src/utils/getNativeTinyui.d.ts.map +1 -1
  55. package/package.json +10 -2
  56. package/react-native-tinyui.podspec +6 -1
  57. package/src/SwipeActions/SwipeActionsNativeComponent.ts +19 -0
  58. package/src/SwipeActions/actions.ts +26 -0
  59. package/src/SwipeActions/index.tsx +54 -0
  60. package/src/SwipeActions/types.ts +37 -0
  61. package/src/TipKit/Group.tsx +76 -0
  62. package/src/TipKit/Popover.tsx +16 -2
  63. package/src/TipKit/TipPopoverNativeComponent.ts +7 -0
  64. package/src/TipKit/TipViewNativeComponent.ts +6 -0
  65. package/src/TipKit/View.tsx +14 -2
  66. package/src/TipKit/index.ts +4 -0
  67. package/src/TipKit/types.ts +24 -0
  68. package/src/index.tsx +9 -0
  69. package/src/utils/getNativeTinyui.ts +1 -0
@@ -6,6 +6,20 @@ export interface TipKitConfiguration {
6
6
  displayFrequency?: TipDisplayFrequency;
7
7
  }
8
8
  export type TipInvalidationReason = 'actionPerformed' | 'tipClosed';
9
+ export interface TipInvalidationEvent {
10
+ reason: TipInvalidationReason | 'displayCountExceeded' | 'displayDurationExceeded' | 'unknown';
11
+ }
12
+ export interface TipGroupProps {
13
+ /** Stable tip IDs in presentation order, independent of the layout tree. */
14
+ tipIds: readonly string[];
15
+ /** Currently only ordered presentation is supported. Defaults to ordered. */
16
+ priority?: 'ordered';
17
+ /** Pause all tips in this group without completing them. Defaults to true. */
18
+ enabled?: boolean;
19
+ /** Treat tapping outside a popover as completion. Defaults to false. */
20
+ invalidateOnOutsideDismiss?: boolean;
21
+ children: ReactNode;
22
+ }
9
23
  export interface TipAction {
10
24
  /** Unique nonempty identity within this tip, returned by `onActionPress`. */
11
25
  id: string;
@@ -31,9 +45,13 @@ export interface TipContentProps extends Omit<ViewProps, 'children'> {
31
45
  ignoresDisplayFrequency?: boolean;
32
46
  /** Receives the tapped button's id and title; does not automatically invalidate the tip. */
33
47
  onActionPress?: (action: TipAction) => void;
48
+ /** Called for native invalidation, including persisted invalidation on mount. */
49
+ onInvalidated?: (event: TipInvalidationEvent) => void;
34
50
  onError?: (error: TipError) => void;
35
51
  }
36
52
  export interface TipPopoverProps extends TipContentProps {
53
+ /** Invalidate on outside dismissal. Inherits from Group; otherwise false. */
54
+ invalidateOnOutsideDismiss?: boolean;
37
55
  /** Anchor content. Its existing touch handlers are preserved. */
38
56
  children: ReactNode;
39
57
  /** Preferred arrow edge on the bubble; UIKit may adapt to available space. */
@@ -1 +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,WAAW,SAAS;IACxB,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,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,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,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,4FAA4F;IAC5F,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CAChE;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,yEAAyE;IACzE,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CAChE"}
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,WAAW,oBAAoB;IACnC,MAAM,EACF,qBAAqB,GACrB,sBAAsB,GACtB,yBAAyB,GACzB,SAAS,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,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,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,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,4FAA4F;IAC5F,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5C,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,6EAA6E;IAC7E,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CAChE;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,yEAAyE;IACzE,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;CAChE"}
@@ -1,6 +1,8 @@
1
1
  export { Menu } from './Menu/index.js';
2
+ export { SwipeActions } from './SwipeActions/index.js';
3
+ export type { SwipeAction, SwipeActionPressEvent, SwipeActionsEdge, SwipeActionsProps, } from './SwipeActions/index.js';
2
4
  export { TipKit } from './TipKit/index.js';
3
- export type { TipAction, TipDisplayFrequency, TipError, TipInvalidationReason, TipPopoverProps, TipViewProps, TipKitConfiguration, } from './TipKit/index.js';
5
+ export type { TipAction, TipDisplayFrequency, TipError, TipInvalidationReason, TipInvalidationEvent, TipGroupProps, TipPopoverProps, TipViewProps, TipKitConfiguration, } from './TipKit/index.js';
4
6
  export type { MenuActionOption, MenuActionPressEvent, MenuActionPressEventData, MenuDividerOption, MenuItemState, MenuOption, MenuProps, MenuRef, MenuSectionOption, MenuSubmenuOption, } from './Menu/index.js';
5
7
  export { Stepper } from './Stepper/index.js';
6
8
  export type { StepperProps } from './Stepper/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,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAU,CAAC;AAClC,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,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,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
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAQ,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAgB,CAAC;AAC9C,YAAY,EACV,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAU,CAAC;AAClC,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,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,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' | 'Stepper' | 'ConcentricView' | 'SFSymbol' | 'TipKit';
2
+ export type TinyuiComponent = 'Menu' | 'SwipeActions' | '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,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"}
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,cAAc,GACd,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": "3.0.0",
4
- "description": "Dependency-free native iOS Menu, Popover, TipKit, Stepper, ConcentricView, SFSymbol and LiquidGlassText components for React Native",
3
+ "version": "3.2.0",
4
+ "description": "Dependency-free native iOS Menu, SwipeActions, 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,11 @@
20
20
  "types": "./lib/typescript/src/Popover/index.d.ts",
21
21
  "default": "./lib/module/Popover/index.js"
22
22
  },
23
+ "./swipe-actions": {
24
+ "react-native-tinyui-source": "./src/SwipeActions/index.tsx",
25
+ "types": "./lib/typescript/src/SwipeActions/index.d.ts",
26
+ "default": "./lib/module/SwipeActions/index.js"
27
+ },
23
28
  "./stepper": {
24
29
  "react-native-tinyui-source": "./src/Stepper/index.tsx",
25
30
  "types": "./lib/typescript/src/Stepper/index.d.ts",
@@ -152,6 +157,9 @@
152
157
  }
153
158
  },
154
159
  "components": {
160
+ "TinyuiSwipeActionsView": {
161
+ "className": "TinyuiSwipeActionsView"
162
+ },
155
163
  "TinyuiMenuView": {
156
164
  "className": "TinyuiMenuView"
157
165
  },
@@ -4,6 +4,11 @@ require "pathname"
4
4
  package = JSON.parse(File.read(File.join(__dir__, "package.json")))
5
5
 
6
6
  components = {
7
+ "SwipeActions" => {
8
+ :source_files => "ios/SwipeActions/**/*.{h,m,mm,swift,cpp}",
9
+ :definition => "TINYUI_FEATURE_SWIPE_ACTIONS=1",
10
+ :frameworks => ["UIKit"],
11
+ },
7
12
  "Menu" => {
8
13
  :source_files => "ios/Menu/**/*.{h,m,mm,swift,cpp}",
9
14
  :definition => "TINYUI_FEATURE_MENU=1",
@@ -100,7 +105,7 @@ Pod::Spec.new do |s|
100
105
  s.source = { :git => "https://github.com/luoxuhai/react-native-tinyui.git", :tag => "#{s.version}" }
101
106
 
102
107
  s.source_files = source_files
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"]
108
+ s.private_header_files = ["ios/Core/**/*.h", "ios/Menu/**/*.h", "ios/SwipeActions/**/*.h", "ios/Popover/**/*.h", "ios/LiquidGlassText/**/*.h", "ios/Stepper/**/*.h", "ios/ConcentricView/**/*.h", "ios/SFSymbol/**/*.h", "ios/TipKit/**/*.h"]
104
109
  s.preserve_paths = "ios/LiquidGlassText/GlassText-LICENSE"
105
110
  s.swift_version = "5.0"
106
111
  s.frameworks = frameworks unless frameworks.empty?
@@ -0,0 +1,19 @@
1
+ import {
2
+ codegenNativeComponent,
3
+ type CodegenTypes,
4
+ type ViewProps,
5
+ } from 'react-native';
6
+ import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
7
+
8
+ export interface NativeSwipeActionsProps extends ViewProps {
9
+ actionsConfig: CodegenTypes.UnsafeMixed;
10
+ edge?: CodegenTypes.WithDefault<'leading' | 'trailing', 'trailing'>;
11
+ allowsFullSwipe?: CodegenTypes.WithDefault<boolean, true>;
12
+ disabled?: boolean;
13
+ onActionPress?: DirectEventHandler<Readonly<{ id: string; title: string }>>;
14
+ }
15
+
16
+ export default codegenNativeComponent<NativeSwipeActionsProps>(
17
+ 'TinyuiSwipeActionsView',
18
+ { excludedPlatforms: ['android'] }
19
+ );
@@ -0,0 +1,26 @@
1
+ import { processColor } from 'react-native';
2
+
3
+ import type { SwipeAction } from './types';
4
+
5
+ export function serializeSwipeActions(actions: readonly SwipeAction[]) {
6
+ const ids = new Set<string>();
7
+
8
+ return actions.map((action, index) => {
9
+ const id = action.id ?? `item.${index}`;
10
+ if (ids.has(id)) {
11
+ throw new Error(`SwipeActions action id "${id}" must be unique.`);
12
+ }
13
+ ids.add(id);
14
+
15
+ return {
16
+ id,
17
+ title: action.title,
18
+ systemImage: action.systemImage,
19
+ tintColor:
20
+ action.tintColor === undefined
21
+ ? undefined
22
+ : processColor(action.tintColor),
23
+ destructive: action.destructive ?? false,
24
+ };
25
+ });
26
+ }
@@ -0,0 +1,54 @@
1
+ import { forwardRef, type ComponentRef } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+
4
+ import { assertComponentEnabled } from '../utils';
5
+ import { serializeSwipeActions } from './actions';
6
+ import NativeSwipeActionsView from './SwipeActionsNativeComponent';
7
+ import type { SwipeActionsProps } from './types';
8
+
9
+ export const SwipeActions = forwardRef<
10
+ ComponentRef<typeof View>,
11
+ SwipeActionsProps
12
+ >(function SwipeActionsRoot(
13
+ {
14
+ actions,
15
+ children,
16
+ contentContainerStyle,
17
+ edge = 'trailing',
18
+ allowsFullSwipe = true,
19
+ disabled = false,
20
+ style,
21
+ ...viewProps
22
+ },
23
+ ref
24
+ ) {
25
+ assertComponentEnabled('SwipeActions');
26
+
27
+ return (
28
+ <NativeSwipeActionsView
29
+ {...viewProps}
30
+ ref={ref}
31
+ actionsConfig={serializeSwipeActions(actions)}
32
+ edge={edge}
33
+ allowsFullSwipe={allowsFullSwipe}
34
+ disabled={disabled}
35
+ style={[styles.container, style]}
36
+ >
37
+ <View collapsable={false} style={[styles.content, contentContainerStyle]}>
38
+ {children}
39
+ </View>
40
+ </NativeSwipeActionsView>
41
+ );
42
+ });
43
+
44
+ const styles = StyleSheet.create({
45
+ container: { overflow: 'hidden' },
46
+ content: { flexGrow: 1 },
47
+ });
48
+
49
+ export type {
50
+ SwipeAction,
51
+ SwipeActionPressEvent,
52
+ SwipeActionsEdge,
53
+ SwipeActionsProps,
54
+ } from './types';
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ColorValue, StyleProp, ViewProps, ViewStyle } from 'react-native';
3
+
4
+ export type SwipeActionsEdge = 'leading' | 'trailing';
5
+
6
+ export interface SwipeAction {
7
+ /** Stable identifier. Defaults to `item.<index>` when omitted. */
8
+ id?: string;
9
+ /** Button title and accessible action name. */
10
+ title: string;
11
+ /** SF Symbol name. */
12
+ systemImage?: string;
13
+ /** Native action background color, including semantic and dynamic colors. */
14
+ tintColor?: ColorValue;
15
+ /** Uses the system destructive appearance. Does not remove the React row. */
16
+ destructive?: boolean;
17
+ }
18
+
19
+ export type SwipeActionPressEvent = Readonly<{
20
+ nativeEvent: Readonly<{ id: string; title: string }>;
21
+ }>;
22
+
23
+ export interface SwipeActionsProps extends Omit<ViewProps, 'children'> {
24
+ /** The React Native row content. */
25
+ children: ReactNode;
26
+ /** Styles the moving row, including its background, corners and padding. */
27
+ contentContainerStyle?: StyleProp<ViewStyle>;
28
+ /** Actions ordered from the selected edge inward. */
29
+ actions: readonly SwipeAction[];
30
+ /** Logical edge; respects layout direction. Defaults to `trailing`. */
31
+ edge?: SwipeActionsEdge;
32
+ /** A full swipe performs the first action. Defaults to `true`. */
33
+ allowsFullSwipe?: boolean;
34
+ /** Disables swipe actions without disabling the row's children. */
35
+ disabled?: boolean;
36
+ onActionPress?: (event: SwipeActionPressEvent) => void;
37
+ }
@@ -0,0 +1,76 @@
1
+ import {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useMemo,
6
+ useState,
7
+ } from 'react';
8
+
9
+ import { assertComponentEnabled } from '../utils';
10
+ import type { TipGroupProps } from './types';
11
+ import { validateTipId } from './validation';
12
+
13
+ interface GroupContextValue {
14
+ tipIds: ReadonlySet<string>;
15
+ currentTipId: string | undefined;
16
+ enabled: boolean;
17
+ invalidateOnOutsideDismiss: boolean;
18
+ complete: (tipId: string) => void;
19
+ }
20
+
21
+ const GroupContext = createContext<GroupContextValue | null>(null);
22
+
23
+ /** Orders tips by ID while native TipKit owns eligibility and persisted history. */
24
+ export function Group({
25
+ tipIds,
26
+ priority = 'ordered',
27
+ enabled = true,
28
+ invalidateOnOutsideDismiss = false,
29
+ children,
30
+ }: TipGroupProps) {
31
+ assertComponentEnabled('TipKit');
32
+ if (priority !== 'ordered') {
33
+ throw new Error('[TinyUI] TipKit.Group only supports ordered priority.');
34
+ }
35
+ const ids = new Set<string>();
36
+ for (const tipId of tipIds) {
37
+ validateTipId(tipId);
38
+ if (ids.has(tipId)) {
39
+ throw new Error('[TinyUI] TipKit.Group tipIds must be unique.');
40
+ }
41
+ ids.add(tipId);
42
+ }
43
+
44
+ const [completed, setCompleted] = useState<ReadonlySet<string>>(
45
+ () => new Set()
46
+ );
47
+ const complete = useCallback((tipId: string) => {
48
+ setCompleted((previous) =>
49
+ previous.has(tipId) ? previous : new Set([...previous, tipId])
50
+ );
51
+ }, []);
52
+ const value = useMemo(
53
+ () => ({
54
+ tipIds: new Set(tipIds),
55
+ currentTipId: tipIds.find((id) => !completed.has(id)),
56
+ enabled,
57
+ invalidateOnOutsideDismiss,
58
+ complete,
59
+ }),
60
+ [tipIds, completed, enabled, invalidateOnOutsideDismiss, complete]
61
+ );
62
+
63
+ return (
64
+ <GroupContext.Provider value={value}>{children}</GroupContext.Provider>
65
+ );
66
+ }
67
+
68
+ export function useTipGroup(tipId: string) {
69
+ const group = useContext(GroupContext);
70
+ if (group && !group.tipIds.has(tipId)) {
71
+ throw new Error(
72
+ `[TinyUI] TipKit tipId "${tipId}" is missing from its Group's tipIds.`
73
+ );
74
+ }
75
+ return group;
76
+ }
@@ -3,13 +3,15 @@ import { View } from 'react-native';
3
3
 
4
4
  import { assertComponentEnabled } from '../utils';
5
5
  import NativeTipPopoverView from './TipPopoverNativeComponent';
6
- import type { TipPopoverProps } from './types';
6
+ import type { TipPopoverProps, TipInvalidationEvent } from './types';
7
7
  import { validateTip } from './validation';
8
+ import { useTipGroup } from './Group';
8
9
 
9
10
  export const Popover = forwardRef<ComponentRef<typeof View>, TipPopoverProps>(
10
11
  function TipPopoverRoot(props, ref) {
11
12
  assertComponentEnabled('TipKit');
12
13
  validateTip(props);
14
+ const group = useTipGroup(props.tipId);
13
15
  const {
14
16
  children,
15
17
  tipId,
@@ -22,6 +24,8 @@ export const Popover = forwardRef<ComponentRef<typeof View>, TipPopoverProps>(
22
24
  ignoresDisplayFrequency = false,
23
25
  arrowEdge = 'auto',
24
26
  onActionPress,
27
+ onInvalidated,
28
+ invalidateOnOutsideDismiss = group?.invalidateOnOutsideDismiss ?? false,
25
29
  onError,
26
30
  ...viewProps
27
31
  } = props;
@@ -36,7 +40,10 @@ export const Popover = forwardRef<ComponentRef<typeof View>, TipPopoverProps>(
36
40
  message={message}
37
41
  systemImage={systemImage}
38
42
  actions={actions}
39
- enabled={enabled}
43
+ enabled={
44
+ enabled && (!group || (group.enabled && group.currentTipId === tipId))
45
+ }
46
+ invalidateOnOutsideDismiss={invalidateOnOutsideDismiss}
40
47
  maxDisplayCount={maxDisplayCount ?? 0}
41
48
  ignoresDisplayFrequency={ignoresDisplayFrequency}
42
49
  arrowEdge={arrowEdge}
@@ -45,6 +52,13 @@ export const Popover = forwardRef<ComponentRef<typeof View>, TipPopoverProps>(
45
52
  onActionPress?.({ id: nativeEvent.id, title: nativeEvent.title });
46
53
  }
47
54
  }}
55
+ onTipInvalidated={({ nativeEvent }) => {
56
+ if (nativeEvent.tipId !== tipId) return;
57
+ group?.complete(tipId);
58
+ onInvalidated?.({
59
+ reason: nativeEvent.reason as TipInvalidationEvent['reason'],
60
+ });
61
+ }}
48
62
  onTipError={({ nativeEvent }) => {
49
63
  if (nativeEvent.tipId !== tipId) return;
50
64
  const error = {
@@ -12,6 +12,7 @@ export interface NativeTipPopoverProps extends ViewProps {
12
12
  systemImage?: string;
13
13
  actions?: ReadonlyArray<Readonly<{ id: string; title: string }>>;
14
14
  enabled?: boolean;
15
+ invalidateOnOutsideDismiss?: boolean;
15
16
  maxDisplayCount?: CodegenTypes.Int32;
16
17
  ignoresDisplayFrequency?: boolean;
17
18
  arrowEdge?: string;
@@ -21,6 +22,12 @@ export interface NativeTipPopoverProps extends ViewProps {
21
22
  onTipError?: DirectEventHandler<
22
23
  Readonly<{ tipId: string; code: string; message: string }>
23
24
  >;
25
+ onTipInvalidated?: DirectEventHandler<
26
+ Readonly<{
27
+ tipId: string;
28
+ reason: string;
29
+ }>
30
+ >;
24
31
  }
25
32
 
26
33
  export default codegenNativeComponent<NativeTipPopoverProps>(
@@ -21,6 +21,12 @@ export interface NativeTipViewProps extends ViewProps {
21
21
  onTipError?: DirectEventHandler<
22
22
  Readonly<{ tipId: string; code: string; message: string }>
23
23
  >;
24
+ onTipInvalidated?: DirectEventHandler<
25
+ Readonly<{
26
+ tipId: string;
27
+ reason: string;
28
+ }>
29
+ >;
24
30
  }
25
31
 
26
32
  export default codegenNativeComponent<NativeTipViewProps>('TinyuiTipView', {
@@ -3,8 +3,9 @@ import type { View as ReactNativeView } from 'react-native';
3
3
 
4
4
  import { assertComponentEnabled } from '../utils';
5
5
  import NativeTipView from './TipViewNativeComponent';
6
- import type { TipViewProps } from './types';
6
+ import type { TipViewProps, TipInvalidationEvent } from './types';
7
7
  import { validateTip } from './validation';
8
+ import { useTipGroup } from './Group';
8
9
 
9
10
  export const View = forwardRef<
10
11
  ComponentRef<typeof ReactNativeView>,
@@ -12,6 +13,7 @@ export const View = forwardRef<
12
13
  >(function TipViewRoot(props, ref) {
13
14
  assertComponentEnabled('TipKit');
14
15
  validateTip(props, 'TipKit.View');
16
+ const group = useTipGroup(props.tipId);
15
17
  const {
16
18
  tipId,
17
19
  title,
@@ -23,6 +25,7 @@ export const View = forwardRef<
23
25
  ignoresDisplayFrequency = false,
24
26
  arrowEdge = 'none',
25
27
  onActionPress,
28
+ onInvalidated,
26
29
  onError,
27
30
  ...viewProps
28
31
  } = props;
@@ -38,7 +41,9 @@ export const View = forwardRef<
38
41
  message={message}
39
42
  systemImage={systemImage}
40
43
  actions={actions}
41
- enabled={enabled}
44
+ enabled={
45
+ enabled && (!group || (group.enabled && group.currentTipId === tipId))
46
+ }
42
47
  maxDisplayCount={maxDisplayCount ?? 0}
43
48
  ignoresDisplayFrequency={ignoresDisplayFrequency}
44
49
  arrowEdge={arrowEdge}
@@ -47,6 +52,13 @@ export const View = forwardRef<
47
52
  onActionPress?.({ id: nativeEvent.id, title: nativeEvent.title });
48
53
  }
49
54
  }}
55
+ onTipInvalidated={({ nativeEvent }) => {
56
+ if (nativeEvent.tipId !== tipId) return;
57
+ group?.complete(tipId);
58
+ onInvalidated?.({
59
+ reason: nativeEvent.reason as TipInvalidationEvent['reason'],
60
+ });
61
+ }}
50
62
  onTipError={({ nativeEvent }) => {
51
63
  if (nativeEvent.tipId !== tipId) return;
52
64
  const error = {
@@ -3,8 +3,10 @@ import type { TipInvalidationReason, TipKitConfiguration } from './types';
3
3
  import { validateTipId } from './validation';
4
4
  import { Popover } from './Popover';
5
5
  import { View } from './View';
6
+ import { Group } from './Group';
6
7
 
7
8
  export const TipKit = {
9
+ Group,
8
10
  Popover,
9
11
  View,
10
12
  /**
@@ -53,6 +55,8 @@ export type {
53
55
  TipDisplayFrequency,
54
56
  TipError,
55
57
  TipInvalidationReason,
58
+ TipInvalidationEvent,
59
+ TipGroupProps,
56
60
  TipKitConfiguration,
57
61
  TipPopoverProps,
58
62
  TipViewProps,
@@ -11,6 +11,26 @@ export interface TipKitConfiguration {
11
11
 
12
12
  export type TipInvalidationReason = 'actionPerformed' | 'tipClosed';
13
13
 
14
+ export interface TipInvalidationEvent {
15
+ reason:
16
+ | TipInvalidationReason
17
+ | 'displayCountExceeded'
18
+ | 'displayDurationExceeded'
19
+ | 'unknown';
20
+ }
21
+
22
+ export interface TipGroupProps {
23
+ /** Stable tip IDs in presentation order, independent of the layout tree. */
24
+ tipIds: readonly string[];
25
+ /** Currently only ordered presentation is supported. Defaults to ordered. */
26
+ priority?: 'ordered';
27
+ /** Pause all tips in this group without completing them. Defaults to true. */
28
+ enabled?: boolean;
29
+ /** Treat tapping outside a popover as completion. Defaults to false. */
30
+ invalidateOnOutsideDismiss?: boolean;
31
+ children: ReactNode;
32
+ }
33
+
14
34
  export interface TipAction {
15
35
  /** Unique nonempty identity within this tip, returned by `onActionPress`. */
16
36
  id: string;
@@ -38,10 +58,14 @@ export interface TipContentProps extends Omit<ViewProps, 'children'> {
38
58
  ignoresDisplayFrequency?: boolean;
39
59
  /** Receives the tapped button's id and title; does not automatically invalidate the tip. */
40
60
  onActionPress?: (action: TipAction) => void;
61
+ /** Called for native invalidation, including persisted invalidation on mount. */
62
+ onInvalidated?: (event: TipInvalidationEvent) => void;
41
63
  onError?: (error: TipError) => void;
42
64
  }
43
65
 
44
66
  export interface TipPopoverProps extends TipContentProps {
67
+ /** Invalidate on outside dismissal. Inherits from Group; otherwise false. */
68
+ invalidateOnOutsideDismiss?: boolean;
45
69
  /** Anchor content. Its existing touch handlers are preserved. */
46
70
  children: ReactNode;
47
71
  /** Preferred arrow edge on the bubble; UIKit may adapt to available space. */
package/src/index.tsx CHANGED
@@ -1,10 +1,19 @@
1
1
  export { Menu } from './Menu';
2
+ export { SwipeActions } from './SwipeActions';
3
+ export type {
4
+ SwipeAction,
5
+ SwipeActionPressEvent,
6
+ SwipeActionsEdge,
7
+ SwipeActionsProps,
8
+ } from './SwipeActions';
2
9
  export { TipKit } from './TipKit';
3
10
  export type {
4
11
  TipAction,
5
12
  TipDisplayFrequency,
6
13
  TipError,
7
14
  TipInvalidationReason,
15
+ TipInvalidationEvent,
16
+ TipGroupProps,
8
17
  TipPopoverProps,
9
18
  TipViewProps,
10
19
  TipKitConfiguration,
@@ -2,6 +2,7 @@ import NativeTinyui, { type Spec } from '../NativeTinyui';
2
2
 
3
3
  export type TinyuiComponent =
4
4
  | 'Menu'
5
+ | 'SwipeActions'
5
6
  | 'Popover'
6
7
  | 'LiquidGlassText'
7
8
  | 'Stepper'