@sudobility/components-rn 1.0.21 → 1.0.23

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 (42) hide show
  1. package/dist/index.cjs.js.map +1 -1
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/lib/utils.d.ts +7 -2
  6. package/dist/lib/utils.d.ts.map +1 -1
  7. package/dist/ui/Alert/Alert.d.ts +8 -0
  8. package/dist/ui/Alert/Alert.d.ts.map +1 -1
  9. package/dist/ui/Button/Button.shared.d.ts +18 -3
  10. package/dist/ui/Button/Button.shared.d.ts.map +1 -1
  11. package/dist/ui/Card/Card.d.ts +32 -0
  12. package/dist/ui/Card/Card.d.ts.map +1 -1
  13. package/dist/ui/{ChainBadge.d.ts → ChainBadge/ChainBadge.d.ts} +1 -0
  14. package/dist/ui/ChainBadge/ChainBadge.d.ts.map +1 -0
  15. package/dist/ui/ChainBadge/index.d.ts +2 -0
  16. package/dist/ui/ChainBadge/index.d.ts.map +1 -0
  17. package/dist/ui/Spinner/Spinner.d.ts +8 -0
  18. package/dist/ui/Spinner/Spinner.d.ts.map +1 -1
  19. package/dist/ui/Toast/Toast.d.ts +11 -0
  20. package/dist/ui/Toast/Toast.d.ts.map +1 -1
  21. package/package.json +23 -12
  22. package/src/__tests__/alert.test.tsx +95 -0
  23. package/src/__tests__/badge.test.tsx +121 -0
  24. package/src/__tests__/button.test.tsx +107 -0
  25. package/src/__tests__/card.test.tsx +149 -0
  26. package/src/__tests__/dialog.test.tsx +76 -0
  27. package/src/__tests__/input.test.tsx +80 -0
  28. package/src/__tests__/modal.test.tsx +125 -0
  29. package/src/__tests__/sheet.test.tsx +113 -0
  30. package/src/__tests__/tabs.test.tsx +213 -0
  31. package/src/__tests__/toast.test.tsx +181 -0
  32. package/src/__tests__/utils.test.ts +47 -0
  33. package/src/index.ts +4 -1
  34. package/src/lib/utils.ts +7 -2
  35. package/src/ui/Alert/Alert.tsx +8 -0
  36. package/src/ui/Button/Button.shared.ts +18 -3
  37. package/src/ui/Card/Card.tsx +32 -0
  38. package/src/ui/{ChainBadge.tsx → ChainBadge/ChainBadge.tsx} +2 -1
  39. package/src/ui/ChainBadge/index.ts +1 -0
  40. package/src/ui/Spinner/Spinner.tsx +8 -0
  41. package/src/ui/Toast/Toast.tsx +11 -0
  42. package/dist/ui/ChainBadge.d.ts.map +0 -1
@@ -1,8 +1,13 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  /**
3
3
  * Merges class names for React Native with NativeWind.
4
- * Unlike web version, we don't need tailwind-merge since NativeWind
5
- * processes Tailwind classes at build time.
4
+ *
5
+ * Unlike the web version (`@sudobility/components`), this does NOT use
6
+ * `tailwind-merge` since NativeWind processes Tailwind classes at build
7
+ * time and handles conflict resolution internally.
8
+ *
9
+ * @param inputs - Class values to merge (strings, arrays, objects, etc.)
10
+ * @returns A single merged class name string
6
11
  */
7
12
  export declare function cn(...inputs: ClassValue[]): string;
8
13
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAE7C;;;;;;;;;GASG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
@@ -1,5 +1,11 @@
1
1
  import { default as React } from 'react';
2
2
  import { ViewProps } from 'react-native';
3
+ /**
4
+ * Props for the Alert component.
5
+ *
6
+ * Supports semantic variants (info, success, warning, attention, error)
7
+ * with design system styling, optional custom icons, and compound content.
8
+ */
3
9
  export interface AlertProps extends ViewProps {
4
10
  variant?: 'info' | 'success' | 'warning' | 'attention' | 'error';
5
11
  title?: string;
@@ -7,10 +13,12 @@ export interface AlertProps extends ViewProps {
7
13
  icon?: React.ReactNode;
8
14
  children?: React.ReactNode;
9
15
  }
16
+ /** Alert title sub-component with bold font styling. */
10
17
  export declare const AlertTitle: React.FC<{
11
18
  children: React.ReactNode;
12
19
  className?: string;
13
20
  }>;
21
+ /** Alert description sub-component with smaller text styling. */
14
22
  export declare const AlertDescription: React.FC<{
15
23
  children: React.ReactNode;
16
24
  className?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/ui/Alert/Alert.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAI1D,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAWD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAEA,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAEA,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA8BtC,CAAC"}
1
+ {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/ui/Alert/Alert.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAWD,wDAAwD;AACxD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAEA,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAEA,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA8BtC,CAAC"}
@@ -11,15 +11,30 @@ export interface ButtonBaseProps {
11
11
  children: ReactNode;
12
12
  }
13
13
  /**
14
- * Map size abbreviations to design system variant keys
14
+ * Map size abbreviations to design system variant keys.
15
+ *
16
+ * @param size - The abbreviated size key ('sm', 'lg', or 'default')
17
+ * @returns The full design system variant key ('small', 'large', or 'default')
15
18
  */
16
19
  export declare const mapSizeToVariantKey: (size: string | undefined) => string;
17
20
  /**
18
- * Get button variant class from design system
21
+ * Get button variant class string from the design system.
22
+ *
23
+ * Handles gradient variants, web3 variants (wallet/connect/disconnect),
24
+ * and standard variants with size modifiers.
25
+ *
26
+ * @param variantName - The button variant name (e.g., 'primary', 'gradient', 'wallet')
27
+ * @param sizeName - Optional size abbreviation ('sm' or 'lg')
28
+ * @param v - The design system variants object
29
+ * @returns A Tailwind class string from the design system
19
30
  */
20
31
  export declare const getButtonVariantClass: (variantName: string, sizeName: string | undefined, v: any) => string;
21
32
  /**
22
- * Shared button state logic
33
+ * Shared button state logic for determining disabled and spinner visibility.
34
+ *
35
+ * @param loading - Whether the button is in a loading state
36
+ * @param disabled - Whether the button is explicitly disabled
37
+ * @returns An object with `isDisabled` and `showSpinner` booleans
23
38
  */
24
39
  export declare const useButtonState: (loading: boolean | undefined, disabled: boolean | undefined) => {
25
40
  isDisabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Button.shared.d.ts","sourceRoot":"","sources":["../../../src/ui/Button/Button.shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EACJ,SAAS,GACT,SAAS,GACT,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,qBAAqB,GACrB,SAAS,GACT,MAAM,GACN,UAAU,GACV,oBAAoB,GACpB,kBAAkB,GAClB,QAAQ,GACR,SAAS,GACT,YAAY,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IACxC,SAAS,CAAC,EACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,KAAK,GACL,SAAS,GACT,aAAa,GACb,YAAY,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,MAQ9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,EACnB,UAAU,MAAM,GAAG,SAAS,EAC5B,GAAG,GAAG,KACL,MAYF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,SAAS,OAAO,GAAG,SAAS,EAC5B,UAAU,OAAO,GAAG,SAAS;;;CAI7B,CAAC"}
1
+ {"version":3,"file":"Button.shared.d.ts","sourceRoot":"","sources":["../../../src/ui/Button/Button.shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EACJ,SAAS,GACT,SAAS,GACT,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,qBAAqB,GACrB,SAAS,GACT,MAAM,GACN,UAAU,GACV,oBAAoB,GACpB,kBAAkB,GAClB,QAAQ,GACR,SAAS,GACT,YAAY,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IACxC,SAAS,CAAC,EACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,KAAK,GACL,SAAS,GACT,aAAa,GACb,YAAY,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,MAQ9D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,EACnB,UAAU,MAAM,GAAG,SAAS,EAC5B,GAAG,GAAG,KACL,MAYF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GACzB,SAAS,OAAO,GAAG,SAAS,EAC5B,UAAU,OAAO,GAAG,SAAS;;;CAI7B,CAAC"}
@@ -1,5 +1,12 @@
1
1
  import { default as React } from 'react';
2
2
  import { ViewProps } from 'react-native';
3
+ /**
4
+ * Props for the Card component.
5
+ *
6
+ * Supports multiple visual variants (bordered, elevated, info, success, etc.),
7
+ * configurable padding, optional icon display, and a close button for
8
+ * info-type variants.
9
+ */
3
10
  export interface CardProps extends ViewProps {
4
11
  variant?: 'default' | 'bordered' | 'elevated' | 'info' | 'success' | 'warning' | 'error' | 'callout';
5
12
  padding?: 'none' | 'sm' | 'md' | 'lg';
@@ -10,13 +17,38 @@ export interface CardProps extends ViewProps {
10
17
  /** For info variants: show close button */
11
18
  onClose?: () => void;
12
19
  }
20
+ /**
21
+ * Card component for React Native.
22
+ *
23
+ * A versatile container with variant-based styling from the design system.
24
+ * Info-type variants (info, success, warning, error) support an optional
25
+ * icon and close button.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Card variant="elevated" padding="md">
30
+ * <CardHeader title="Title" description="Subtitle" />
31
+ * <CardContent><Text>Body</Text></CardContent>
32
+ * <CardFooter><Button>Action</Button></CardFooter>
33
+ * </Card>
34
+ * ```
35
+ */
13
36
  export declare const Card: React.FC<CardProps>;
37
+ /** Props for the CardHeader sub-component. */
14
38
  interface CardHeaderProps extends ViewProps {
39
+ /** Card title rendered as a heading. */
15
40
  title?: string;
41
+ /** Card description rendered below the title. */
16
42
  description?: string;
17
43
  }
44
+ /**
45
+ * Card header sub-component with optional title and description.
46
+ * Uses design system text variants for consistent typography.
47
+ */
18
48
  export declare const CardHeader: React.FC<CardHeaderProps>;
49
+ /** Card body content area. */
19
50
  export declare const CardContent: React.FC<ViewProps>;
51
+ /** Card footer area, rendered as a horizontal row with top padding. */
20
52
  export declare const CardFooter: React.FC<ViewProps>;
21
53
  export {};
22
54
  //# sourceMappingURL=Card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/ui/Card/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAIrE,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,OAAO,CAAC,EACJ,SAAS,GACT,UAAU,GACV,UAAU,GACV,MAAM,GACN,SAAS,GACT,SAAS,GACT,OAAO,GACP,SAAS,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAYD,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAmDpC,CAAC;AAEF,UAAU,eAAgB,SAAQ,SAAS;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgBhD,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAU3C,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAU1C,CAAC"}
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/ui/Card/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAIrE;;;;;;GAMG;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,OAAO,CAAC,EACJ,SAAS,GACT,UAAU,GACV,UAAU,GACV,MAAM,GACN,SAAS,GACT,SAAS,GACT,OAAO,GACP,SAAS,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAYD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAmDpC,CAAC;AAEF,8CAA8C;AAC9C,UAAU,eAAgB,SAAQ,SAAS;IACzC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgBhD,CAAC;AAEF,8BAA8B;AAC9B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAU3C,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAU1C,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { ViewProps } from 'react-native';
3
3
  export type ChainType = 'evm' | 'solana' | 'bitcoin' | 'cosmos';
4
+ /** Badge displaying a blockchain network identifier with chain-specific color and icon */
4
5
  export interface ChainBadgeProps extends ViewProps {
5
6
  chainType: ChainType;
6
7
  size?: 'sm' | 'md' | 'lg';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChainBadge.d.ts","sourceRoot":"","sources":["../../../src/ui/ChainBadge/ChainBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhE,0FAA0F;AAC1F,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA0CD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAgChD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ChainBadge, type ChainBadgeProps, type ChainType } from './ChainBadge';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/ChainBadge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC"}
@@ -1,10 +1,18 @@
1
1
  import { default as React } from 'react';
2
2
  import { ViewProps } from 'react-native';
3
+ /**
4
+ * Props for the Spinner loading indicator component.
5
+ */
3
6
  export interface SpinnerProps extends ViewProps {
7
+ /** Size of the activity indicator. */
4
8
  size?: 'small' | 'default' | 'large' | 'extraLarge';
9
+ /** Color variant for the spinner. */
5
10
  variant?: 'default' | 'white' | 'success' | 'warning' | 'error';
11
+ /** Accessibility label for screen readers. */
6
12
  accessibilityLabel?: string;
13
+ /** Text shown below the spinner when showText is true. */
7
14
  loadingText?: string;
15
+ /** Whether to display loading text below the spinner. */
8
16
  showText?: boolean;
9
17
  }
10
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../../src/ui/Spinner/Spinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAG7E,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;IACpD,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiBD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA2B1C,CAAC"}
1
+ {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../../src/ui/Spinner/Spinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAG7E;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,sCAAsC;IACtC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;IACpD,qCAAqC;IACrC,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAChE,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiBD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA2B1C,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ /** Data structure representing a single toast notification. */
2
3
  export interface ToastMessage {
3
4
  id: string;
4
5
  title?: string;
@@ -16,11 +17,21 @@ export interface ToastProps {
16
17
  /** Remove toast handler */
17
18
  onRemove: (id: string) => void;
18
19
  }
20
+ /** Context value provided by ToastProvider for managing toast notifications. */
19
21
  export interface ToastContextValue {
20
22
  toasts: ToastMessage[];
21
23
  addToast: (toast: Omit<ToastMessage, 'id'>) => void;
22
24
  removeToast: (id: string) => void;
23
25
  }
26
+ /**
27
+ * Hook to access the toast notification system.
28
+ *
29
+ * Must be used within a ToastProvider. Returns functions to add and remove
30
+ * toast notifications, plus the current list of active toasts.
31
+ *
32
+ * @returns The toast context value with addToast, removeToast, and toasts
33
+ * @throws Error if used outside of a ToastProvider
34
+ */
24
35
  export declare const useToast: () => ToastContextValue;
25
36
  /**
26
37
  * Toast Component
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/ui/Toast/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,oBAAoB;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,2BAA2B;IAC3B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;IACpD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAID,eAAO,MAAM,QAAQ,yBAMpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAoFtC,CAAC;AAwBF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CA+BjE,CAAC"}
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/ui/Toast/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAIf,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,oBAAoB;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,2BAA2B;IAC3B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,gFAAgF;AAChF,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;IACpD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,yBAMpB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAoFtC,CAAC;AAwBF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CA+BjE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/components-rn",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "React Native UI components and design system - Ported from @sudobility/components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -48,8 +48,8 @@
48
48
  ],
49
49
  "author": "Sudobility",
50
50
  "peerDependencies": {
51
- "@sudobility/design": "^1.1.19",
52
- "@sudobility/types": "^1.9.53",
51
+ "@sudobility/design": "^1.1.20",
52
+ "@sudobility/types": "^1.9.54",
53
53
  "nativewind": ">=4.0.0",
54
54
  "react": "^18.0.0 || ^19.0.0",
55
55
  "react-native": ">=0.72.0",
@@ -61,9 +61,18 @@
61
61
  "clsx": "^2.0.0"
62
62
  },
63
63
  "devDependencies": {
64
+ "@babel/core": "^7.29.0",
65
+ "@babel/preset-env": "^7.29.0",
66
+ "@babel/preset-flow": "^7.27.1",
67
+ "@babel/preset-react": "^7.28.5",
68
+ "@babel/preset-typescript": "^7.28.5",
69
+ "@babel/runtime": "^7.28.6",
64
70
  "@eslint/js": "^9.15.0",
65
- "@sudobility/design": "^1.1.19",
66
- "@sudobility/types": "^1.9.53",
71
+ "@react-native/babel-preset": "^0.84.0",
72
+ "@react-native/js-polyfills": "^0.84.0",
73
+ "@react-native/normalize-colors": "^0.84.0",
74
+ "@sudobility/design": "^1.1.20",
75
+ "@sudobility/types": "^1.9.54",
67
76
  "@testing-library/jest-native": "^5.4.3",
68
77
  "@testing-library/react-native": "^13.3.3",
69
78
  "@types/jest": "^29.5.0",
@@ -72,22 +81,24 @@
72
81
  "@typescript-eslint/eslint-plugin": "^8.15.0",
73
82
  "@typescript-eslint/parser": "^8.15.0",
74
83
  "ajv": "^8.17.1",
84
+ "babel-jest": "^30.2.0",
75
85
  "class-variance-authority": "^0.7.1",
76
86
  "clsx": "^2.1.1",
77
- "eslint": "^9.15.0",
78
- "eslint-config-prettier": "^9.1.0",
79
- "eslint-plugin-prettier": "^5.2.1",
87
+ "eslint": "^9.38.0",
88
+ "eslint-config-prettier": "^10.1.8",
89
+ "eslint-plugin-prettier": "^5.5.4",
80
90
  "eslint-plugin-react-hooks": "^5.0.0",
81
91
  "eslint-plugin-react-refresh": "^0.4.14",
82
92
  "jest": "^29.7.0",
83
93
  "jest-environment-jsdom": "^30.2.0",
84
94
  "nativewind": "^4.1.0",
85
- "prettier": "^3.4.0",
95
+ "prettier": "^3.6.2",
86
96
  "react": "^18.3.0",
87
97
  "react-native": "^0.76.0",
88
- "typescript": "^5.6.0",
98
+ "react-test-renderer": "18.3.1",
99
+ "typescript": "^5.9.3",
89
100
  "vite": "^6.0.0",
90
- "vite-plugin-dts": "^4.3.0"
101
+ "vite-plugin-dts": "^4.5.4"
91
102
  },
92
103
  "repository": {
93
104
  "type": "git",
@@ -98,7 +109,7 @@
98
109
  },
99
110
  "homepage": "https://github.com/sudobility/components-rn#readme",
100
111
  "publishConfig": {
101
- "access": "restricted"
112
+ "access": "public"
102
113
  },
103
114
  "engines": {
104
115
  "node": ">=18.0.0"
@@ -0,0 +1,95 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react-native';
3
+ import { Text } from 'react-native';
4
+ import { Alert, AlertTitle, AlertDescription } from '../ui/Alert';
5
+
6
+ // Mock @sudobility/design
7
+ jest.mock('@sudobility/design', () => ({
8
+ variants: {
9
+ alert: {
10
+ info: () => 'mocked-alert-info',
11
+ success: () => 'mocked-alert-success',
12
+ warning: () => 'mocked-alert-warning',
13
+ attention: () => 'mocked-alert-attention',
14
+ error: () => 'mocked-alert-error',
15
+ },
16
+ },
17
+ }));
18
+
19
+ describe('Alert', () => {
20
+ it('renders with title', () => {
21
+ render(<Alert title='Alert Title' />);
22
+ expect(screen.getByText('Alert Title')).toBeTruthy();
23
+ });
24
+
25
+ it('renders with description', () => {
26
+ render(<Alert description='Alert description' />);
27
+ expect(screen.getByText('Alert description')).toBeTruthy();
28
+ });
29
+
30
+ it('renders with both title and description', () => {
31
+ render(
32
+ <Alert title='Important' description='This is an important message' />
33
+ );
34
+ expect(screen.getByText('Important')).toBeTruthy();
35
+ expect(screen.getByText('This is an important message')).toBeTruthy();
36
+ });
37
+
38
+ it('has alert accessibility role', () => {
39
+ render(<Alert title='Alert' testID='alert-el' />);
40
+ const alert = screen.getByTestId('alert-el');
41
+ expect(alert.props.accessibilityRole).toBe('alert');
42
+ });
43
+
44
+ it('renders with different variants without crashing', () => {
45
+ const variants = [
46
+ 'info',
47
+ 'success',
48
+ 'warning',
49
+ 'attention',
50
+ 'error',
51
+ ] as const;
52
+
53
+ variants.forEach(variant => {
54
+ const { unmount } = render(<Alert variant={variant} title={variant} />);
55
+ expect(screen.getByText(variant)).toBeTruthy();
56
+ unmount();
57
+ });
58
+ });
59
+
60
+ it('renders default icons for each variant', () => {
61
+ render(<Alert variant='success' title='Success' testID='alert-icon' />);
62
+ const alert = screen.getByTestId('alert-icon');
63
+ expect(alert.props.accessibilityRole).toBe('alert');
64
+ });
65
+
66
+ it('renders custom icon when provided', () => {
67
+ render(
68
+ <Alert icon={<Text testID='custom-icon'>*</Text>} title='Custom Icon' />
69
+ );
70
+ expect(screen.getByTestId('custom-icon')).toBeTruthy();
71
+ });
72
+
73
+ it('renders children content', () => {
74
+ render(
75
+ <Alert>
76
+ <Text>Custom child content</Text>
77
+ </Alert>
78
+ );
79
+ expect(screen.getByText('Custom child content')).toBeTruthy();
80
+ });
81
+ });
82
+
83
+ describe('AlertTitle', () => {
84
+ it('renders text content', () => {
85
+ render(<AlertTitle>Title Text</AlertTitle>);
86
+ expect(screen.getByText('Title Text')).toBeTruthy();
87
+ });
88
+ });
89
+
90
+ describe('AlertDescription', () => {
91
+ it('renders text content', () => {
92
+ render(<AlertDescription>Description text</AlertDescription>);
93
+ expect(screen.getByText('Description text')).toBeTruthy();
94
+ });
95
+ });
@@ -0,0 +1,121 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react-native';
3
+ import { Text } from 'react-native';
4
+ import { Badge } from '../ui/Badge';
5
+
6
+ describe('Badge', () => {
7
+ it('renders children text', () => {
8
+ render(<Badge>Active</Badge>);
9
+ expect(screen.getByText('Active')).toBeTruthy();
10
+ });
11
+
12
+ it('renders with different variants without crashing', () => {
13
+ const variants = [
14
+ 'default',
15
+ 'primary',
16
+ 'success',
17
+ 'warning',
18
+ 'danger',
19
+ 'info',
20
+ 'purple',
21
+ ] as const;
22
+
23
+ variants.forEach(variant => {
24
+ const { unmount } = render(<Badge variant={variant}>{variant}</Badge>);
25
+ expect(screen.getByText(variant)).toBeTruthy();
26
+ unmount();
27
+ });
28
+ });
29
+
30
+ it('renders with different sizes without crashing', () => {
31
+ const sizes = ['sm', 'md', 'lg'] as const;
32
+
33
+ sizes.forEach(size => {
34
+ const { unmount } = render(<Badge size={size}>Size {size}</Badge>);
35
+ expect(screen.getByText(`Size ${size}`)).toBeTruthy();
36
+ unmount();
37
+ });
38
+ });
39
+
40
+ it('renders an icon when provided', () => {
41
+ render(
42
+ <Badge icon={<Text testID='badge-icon'>Star</Text>}>Featured</Badge>
43
+ );
44
+ expect(screen.getByTestId('badge-icon')).toBeTruthy();
45
+ expect(screen.getByText('Featured')).toBeTruthy();
46
+ });
47
+
48
+ it('renders a dot indicator when dot is true', () => {
49
+ const { toJSON } = render(<Badge dot>Pending</Badge>);
50
+ expect(screen.getByText('Pending')).toBeTruthy();
51
+ // The dot is a View element that gets rendered in the tree
52
+ expect(toJSON()).toBeTruthy();
53
+ });
54
+
55
+ it('renders as a pressable when onPress is provided', () => {
56
+ const onPress = jest.fn();
57
+ render(<Badge onPress={onPress}>Clickable</Badge>);
58
+ fireEvent.press(screen.getByRole('button'));
59
+ expect(onPress).toHaveBeenCalledTimes(1);
60
+ });
61
+
62
+ it('does not have button role when onPress is not provided', () => {
63
+ render(<Badge>Static</Badge>);
64
+ expect(screen.queryByRole('button')).toBeNull();
65
+ });
66
+
67
+ it('renders dismiss button when dismissible', () => {
68
+ const onDismiss = jest.fn();
69
+ render(
70
+ <Badge dismissible onDismiss={onDismiss}>
71
+ Dismissable
72
+ </Badge>
73
+ );
74
+ const dismissButton = screen.getByLabelText('Dismiss');
75
+ expect(dismissButton).toBeTruthy();
76
+ fireEvent.press(dismissButton);
77
+ expect(onDismiss).toHaveBeenCalledTimes(1);
78
+ });
79
+
80
+ it('does not render dismiss button when not dismissible', () => {
81
+ render(<Badge>Not dismissable</Badge>);
82
+ expect(screen.queryByLabelText('Dismiss')).toBeNull();
83
+ });
84
+
85
+ it('displays count', () => {
86
+ render(<Badge count={5}>Items</Badge>);
87
+ expect(screen.getByText('5')).toBeTruthy();
88
+ });
89
+
90
+ it('displays maxCount with + when count exceeds it', () => {
91
+ render(
92
+ <Badge count={150} maxCount={99}>
93
+ Items
94
+ </Badge>
95
+ );
96
+ expect(screen.getByText('99+')).toBeTruthy();
97
+ });
98
+
99
+ it('displays exact count when within maxCount', () => {
100
+ render(
101
+ <Badge count={50} maxCount={99}>
102
+ Items
103
+ </Badge>
104
+ );
105
+ expect(screen.getByText('50')).toBeTruthy();
106
+ });
107
+
108
+ it('renders with outline style without crashing', () => {
109
+ render(
110
+ <Badge variant='primary' outline>
111
+ Outlined
112
+ </Badge>
113
+ );
114
+ expect(screen.getByText('Outlined')).toBeTruthy();
115
+ });
116
+
117
+ it('renders with pill shape without crashing', () => {
118
+ render(<Badge pill>Pill</Badge>);
119
+ expect(screen.getByText('Pill')).toBeTruthy();
120
+ });
121
+ });
@@ -0,0 +1,107 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react-native';
3
+ import { Text } from 'react-native';
4
+ import { Button } from '../ui/Button';
5
+
6
+ // Mock @sudobility/design
7
+ jest.mock('@sudobility/design', () => ({
8
+ variants: {
9
+ button: new Proxy(
10
+ {},
11
+ {
12
+ get: () =>
13
+ new Proxy(() => 'mocked-class', {
14
+ get: () => () => 'mocked-class',
15
+ }),
16
+ }
17
+ ),
18
+ },
19
+ }));
20
+
21
+ describe('Button', () => {
22
+ it('renders with string children', () => {
23
+ render(<Button>Press me</Button>);
24
+ expect(screen.getByText('Press me')).toBeTruthy();
25
+ });
26
+
27
+ it('renders with custom children (non-string)', () => {
28
+ render(
29
+ <Button>
30
+ <Text testID='custom-child'>Custom</Text>
31
+ </Button>
32
+ );
33
+ expect(screen.getByTestId('custom-child')).toBeTruthy();
34
+ });
35
+
36
+ it('has button accessibility role', () => {
37
+ render(<Button>Click</Button>);
38
+ expect(screen.getByRole('button')).toBeTruthy();
39
+ });
40
+
41
+ it('calls onPress when pressed', () => {
42
+ const onPress = jest.fn();
43
+ render(<Button onPress={onPress}>Click</Button>);
44
+ fireEvent.press(screen.getByRole('button'));
45
+ expect(onPress).toHaveBeenCalledTimes(1);
46
+ });
47
+
48
+ it('does not call onPress when disabled', () => {
49
+ const onPress = jest.fn();
50
+ render(
51
+ <Button onPress={onPress} disabled>
52
+ Click
53
+ </Button>
54
+ );
55
+ fireEvent.press(screen.getByRole('button'));
56
+ expect(onPress).not.toHaveBeenCalled();
57
+ });
58
+
59
+ it('shows spinner when loading', () => {
60
+ render(<Button loading>Loading</Button>);
61
+ // ActivityIndicator is rendered when loading is true
62
+ // The button should also be disabled
63
+ const button = screen.getByRole('button');
64
+ expect(button.props.accessibilityState).toEqual({ disabled: true });
65
+ });
66
+
67
+ it('applies accessibility label', () => {
68
+ render(<Button accessibilityLabel='Submit form'>Submit</Button>);
69
+ const button = screen.getByRole('button');
70
+ expect(button.props.accessibilityLabel).toBe('Submit form');
71
+ });
72
+
73
+ it('sets disabled accessibility state when disabled', () => {
74
+ render(<Button disabled>Disabled</Button>);
75
+ const button = screen.getByRole('button');
76
+ expect(button.props.accessibilityState).toEqual({ disabled: true });
77
+ });
78
+
79
+ it('renders with different variants without crashing', () => {
80
+ const variants = [
81
+ 'default',
82
+ 'primary',
83
+ 'secondary',
84
+ 'outline',
85
+ 'ghost',
86
+ 'destructive',
87
+ 'success',
88
+ 'link',
89
+ ] as const;
90
+
91
+ variants.forEach(variant => {
92
+ const { unmount } = render(<Button variant={variant}>{variant}</Button>);
93
+ expect(screen.getByText(variant)).toBeTruthy();
94
+ unmount();
95
+ });
96
+ });
97
+
98
+ it('renders with different sizes without crashing', () => {
99
+ const sizes = ['default', 'sm', 'lg', 'icon'] as const;
100
+
101
+ sizes.forEach(size => {
102
+ const { unmount } = render(<Button size={size}>{`Size ${size}`}</Button>);
103
+ expect(screen.getByText(`Size ${size}`)).toBeTruthy();
104
+ unmount();
105
+ });
106
+ });
107
+ });