panelui-native 0.1.0 → 0.4.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 (124) hide show
  1. package/README.md +251 -0
  2. package/lib/module/components/alert/index.js +107 -24
  3. package/lib/module/components/alert/index.js.map +1 -1
  4. package/lib/module/components/avatar/index.js +1 -1
  5. package/lib/module/components/avatar/index.js.map +1 -1
  6. package/lib/module/components/badge/index.js +3 -3
  7. package/lib/module/components/badge/index.js.map +1 -1
  8. package/lib/module/components/bottom-sheet/index.js +35 -31
  9. package/lib/module/components/bottom-sheet/index.js.map +1 -1
  10. package/lib/module/components/button/index.js +44 -15
  11. package/lib/module/components/button/index.js.map +1 -1
  12. package/lib/module/components/card/index.js +5 -5
  13. package/lib/module/components/card/index.js.map +1 -1
  14. package/lib/module/components/checkbox/index.js +21 -8
  15. package/lib/module/components/checkbox/index.js.map +1 -1
  16. package/lib/module/components/dialog/index.js +21 -17
  17. package/lib/module/components/dialog/index.js.map +1 -1
  18. package/lib/module/components/empty-state/index.js +178 -0
  19. package/lib/module/components/empty-state/index.js.map +1 -0
  20. package/lib/module/components/frame/index.js +100 -0
  21. package/lib/module/components/frame/index.js.map +1 -0
  22. package/lib/module/components/inline-select/index.js +159 -0
  23. package/lib/module/components/inline-select/index.js.map +1 -0
  24. package/lib/module/components/input/index.js +1 -1
  25. package/lib/module/components/input/index.js.map +1 -1
  26. package/lib/module/components/input-group/index.js +132 -0
  27. package/lib/module/components/input-group/index.js.map +1 -0
  28. package/lib/module/components/label/index.js +117 -0
  29. package/lib/module/components/label/index.js.map +1 -0
  30. package/lib/module/components/progress/index.js +138 -0
  31. package/lib/module/components/progress/index.js.map +1 -0
  32. package/lib/module/components/select/index.js +35 -28
  33. package/lib/module/components/select/index.js.map +1 -1
  34. package/lib/module/components/skeleton/index.js +1 -1
  35. package/lib/module/components/skeleton/index.js.map +1 -1
  36. package/lib/module/components/spinner/index.js +1 -1
  37. package/lib/module/components/spinner/index.js.map +1 -1
  38. package/lib/module/components/steps/index.js +354 -0
  39. package/lib/module/components/steps/index.js.map +1 -0
  40. package/lib/module/components/tabs/index.js +9 -3
  41. package/lib/module/components/tabs/index.js.map +1 -1
  42. package/lib/module/components/toast/index.js +479 -0
  43. package/lib/module/components/toast/index.js.map +1 -0
  44. package/lib/module/components/toast/toast-store.js +81 -0
  45. package/lib/module/components/toast/toast-store.js.map +1 -0
  46. package/lib/module/components/typography/index.js +126 -0
  47. package/lib/module/components/typography/index.js.map +1 -0
  48. package/lib/module/icons/index.js +223 -2
  49. package/lib/module/icons/index.js.map +1 -1
  50. package/lib/module/index.js +11 -2
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/providers/panel-ui-provider.js +20 -8
  53. package/lib/module/providers/panel-ui-provider.js.map +1 -1
  54. package/lib/module/theme/use-theme.js +90 -3
  55. package/lib/module/theme/use-theme.js.map +1 -1
  56. package/lib/typescript/src/components/alert/index.d.ts +41 -19
  57. package/lib/typescript/src/components/alert/index.d.ts.map +1 -1
  58. package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
  59. package/lib/typescript/src/components/button/index.d.ts +39 -0
  60. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  61. package/lib/typescript/src/components/checkbox/index.d.ts +8 -0
  62. package/lib/typescript/src/components/checkbox/index.d.ts.map +1 -1
  63. package/lib/typescript/src/components/dialog/index.d.ts.map +1 -1
  64. package/lib/typescript/src/components/empty-state/index.d.ts +73 -0
  65. package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -0
  66. package/lib/typescript/src/components/frame/index.d.ts +21 -0
  67. package/lib/typescript/src/components/frame/index.d.ts.map +1 -0
  68. package/lib/typescript/src/components/inline-select/index.d.ts +25 -0
  69. package/lib/typescript/src/components/inline-select/index.d.ts.map +1 -0
  70. package/lib/typescript/src/components/input-group/index.d.ts +34 -0
  71. package/lib/typescript/src/components/input-group/index.d.ts.map +1 -0
  72. package/lib/typescript/src/components/label/index.d.ts +28 -0
  73. package/lib/typescript/src/components/label/index.d.ts.map +1 -0
  74. package/lib/typescript/src/components/progress/index.d.ts +132 -0
  75. package/lib/typescript/src/components/progress/index.d.ts.map +1 -0
  76. package/lib/typescript/src/components/select/index.d.ts.map +1 -1
  77. package/lib/typescript/src/components/spinner/index.d.ts +2 -2
  78. package/lib/typescript/src/components/spinner/index.d.ts.map +1 -1
  79. package/lib/typescript/src/components/steps/index.d.ts +62 -0
  80. package/lib/typescript/src/components/steps/index.d.ts.map +1 -0
  81. package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
  82. package/lib/typescript/src/components/toast/index.d.ts +176 -0
  83. package/lib/typescript/src/components/toast/index.d.ts.map +1 -0
  84. package/lib/typescript/src/components/toast/toast-store.d.ts +65 -0
  85. package/lib/typescript/src/components/toast/toast-store.d.ts.map +1 -0
  86. package/lib/typescript/src/components/typography/index.d.ts +77 -0
  87. package/lib/typescript/src/components/typography/index.d.ts.map +1 -0
  88. package/lib/typescript/src/icons/index.d.ts +25 -0
  89. package/lib/typescript/src/icons/index.d.ts.map +1 -1
  90. package/lib/typescript/src/index.d.ts +12 -3
  91. package/lib/typescript/src/index.d.ts.map +1 -1
  92. package/lib/typescript/src/providers/panel-ui-provider.d.ts +20 -5
  93. package/lib/typescript/src/providers/panel-ui-provider.d.ts.map +1 -1
  94. package/lib/typescript/src/theme/use-theme.d.ts +64 -4
  95. package/lib/typescript/src/theme/use-theme.d.ts.map +1 -1
  96. package/package.json +28 -5
  97. package/src/components/alert/index.tsx +104 -28
  98. package/src/components/avatar/index.tsx +1 -1
  99. package/src/components/badge/index.tsx +3 -3
  100. package/src/components/bottom-sheet/index.tsx +8 -3
  101. package/src/components/button/index.tsx +47 -7
  102. package/src/components/card/index.tsx +5 -5
  103. package/src/components/checkbox/index.tsx +18 -4
  104. package/src/components/dialog/index.tsx +10 -5
  105. package/src/components/empty-state/index.tsx +136 -0
  106. package/src/components/frame/index.tsx +104 -0
  107. package/src/components/inline-select/index.tsx +185 -0
  108. package/src/components/input/index.tsx +1 -1
  109. package/src/components/input-group/index.tsx +164 -0
  110. package/src/components/label/index.tsx +128 -0
  111. package/src/components/progress/index.tsx +147 -0
  112. package/src/components/select/index.tsx +30 -23
  113. package/src/components/skeleton/index.tsx +1 -1
  114. package/src/components/spinner/index.tsx +1 -1
  115. package/src/components/steps/index.tsx +343 -0
  116. package/src/components/tabs/index.tsx +10 -2
  117. package/src/components/toast/index.tsx +447 -0
  118. package/src/components/toast/toast-store.ts +120 -0
  119. package/src/components/typography/index.tsx +121 -0
  120. package/src/icons/index.tsx +152 -1
  121. package/src/index.ts +82 -3
  122. package/src/providers/panel-ui-provider.tsx +35 -10
  123. package/src/theme/use-theme.ts +119 -4
  124. package/theme.css +446 -108
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,kCAA+B,CAAC;AAG3F,OAAO,EAAE,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAmB,CAAC;AAG7D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAqB,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAmB,CAAC;AACzD,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,oCAAiC,CAAC;AAGzC,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,6BAAoB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,8BAAqB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,6BAAoB,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,oCAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,8BAAqB,CAAC;AAC/D,OAAO,EACL,MAAM,EACN,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,8BAAqB,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,8BAAqB,CAAC;AACrF,OAAO,EACL,IAAI,EACJ,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,4BAAmB,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,4BAAmB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gCAAuB,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,6BAAoB,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,mBAAmB,GACzB,MAAM,mCAA0B,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gCAAuB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,+BAAsB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,8BAAqB,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAS,CAAC;AAG5E,OAAO,EAAE,EAAE,EAAE,MAAM,eAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,28 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export interface PanelUIProviderProps {
3
3
  children: ReactNode;
4
+ /**
5
+ * Classes for the themed page surface. Defaults to `bg-background`, which
6
+ * follows the active theme. Pass your own to change the page colour.
7
+ */
8
+ className?: string;
9
+ /**
10
+ * Set to false to render without the themed page background — do this only
11
+ * if you paint the app background yourself.
12
+ */
13
+ background?: boolean;
4
14
  }
5
15
  /**
6
- * Root provider for PanelUI. Wraps the app with the gesture handler root and
7
- * the portal host used by overlay components (Dialog, BottomSheet, Select).
16
+ * Root provider for PanelUI. Owns three things:
17
+ * the gesture handler root, the themed page background, and the portal host
18
+ * used by overlay components (Dialog, BottomSheet, Select).
8
19
  *
9
- * Theme switching is handled natively by Uniwind — use `Uniwind.setTheme()`
10
- * or the `useTheme()` hook exported from panelui-native.
20
+ * The background lives here because native wrappers like SafeAreaView do not
21
+ * accept `className` — putting `bg-background` on one silently does nothing,
22
+ * leaving the page unthemed while its children follow the theme.
23
+ *
24
+ * Theme switching is handled natively by Uniwind — use the `useTheme()` hook
25
+ * exported from panelui-native.
11
26
  */
12
- export declare function PanelUIProvider({ children }: PanelUIProviderProps): import("react").JSX.Element;
27
+ export declare function PanelUIProvider({ children, className, background, }: PanelUIProviderProps): import("react").JSX.Element;
13
28
  //# sourceMappingURL=panel-ui-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panel-ui-provider.d.ts","sourceRoot":"","sources":["../../../../src/providers/panel-ui-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,oBAAoB,+BASjE"}
1
+ {"version":3,"file":"panel-ui-provider.d.ts","sourceRoot":"","sources":["../../../../src/providers/panel-ui-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,UAAiB,GAClB,EAAE,oBAAoB,+BAatB"}
@@ -1,12 +1,72 @@
1
- export type ThemeName = 'light' | 'dark' | 'system';
1
+ /** Themes shipped in `panelui-native/theme.css`. */
2
+ export type PanelTheme = 'light' | 'dark' | 'moon' | 'moon-dark' | 'grass' | 'grass-dark';
3
+ export type ThemeName = PanelTheme | 'system';
4
+ /** Light/dark mode within a theme family. */
5
+ export type ThemeMode = 'light' | 'dark';
6
+ /** A theme family — one look, in its light and dark form. */
7
+ export interface PanelThemeFamily {
8
+ /** Stable id, e.g. `'moon'`. */
9
+ id: string;
10
+ /** Short display name, for a theme picker. */
11
+ name: string;
12
+ light: PanelTheme;
13
+ dark: PanelTheme;
14
+ /** Representative colour for a swatch, as `[light, dark]`. */
15
+ swatch: [string, string];
16
+ }
17
+ /**
18
+ * The theme families PanelUI ships. Each sets its own palette *and* its own
19
+ * radius scale, so switching family changes the shape of the UI as well as
20
+ * its colour — Panel is the Coss default, Moon is sharp and monochrome,
21
+ * Grass is soft and green.
22
+ *
23
+ * Everything beyond `panel` must be registered in your metro config, or
24
+ * `setTheme` throws "it was not registered":
25
+ *
26
+ * ```js
27
+ * withUniwindConfig(config, {
28
+ * cssEntryFile: './global.css',
29
+ * extraThemes: ['moon', 'moon-dark', 'grass', 'grass-dark'],
30
+ * });
31
+ * ```
32
+ */
33
+ export declare const PANEL_THEMES: readonly PanelThemeFamily[];
34
+ /** Every concrete theme name, in registration order. */
35
+ export declare const PANEL_THEME_NAMES: readonly PanelTheme[];
36
+ /** The names to pass as `extraThemes` in your metro config. */
37
+ export declare const PANEL_EXTRA_THEMES: readonly string[];
2
38
  /**
3
39
  * Reactive access to the current Uniwind theme plus a setter.
4
40
  * Theme changes are applied natively by Uniwind without re-rendering the tree.
5
41
  */
6
42
  export declare function useTheme(): {
7
- /** Currently resolved theme ('light' or 'dark'). */
8
- theme: string;
9
- /** Switch theme: 'light', 'dark', or 'system' (follows device). */
43
+ /** The active theme name, e.g. `'dark'` or `'moon-dark'`. */
44
+ theme: PanelTheme;
45
+ /** Switch theme by name, or `'system'` to follow the device. */
10
46
  setTheme: (name: ThemeName) => void;
11
47
  };
48
+ /**
49
+ * Theme family and light/dark mode as two separate axes — what a picker like
50
+ * "choose a brand, then toggle the sun" actually needs.
51
+ *
52
+ * Named themes are not adaptive in Uniwind, so each brand ships as a
53
+ * light/dark pair. Toggling the mode keeps the current family, so a user in
54
+ * Moon dark lands in Moon light rather than the default theme.
55
+ *
56
+ * ```tsx
57
+ * const { family, mode, setFamily, toggleMode } = useThemeMode();
58
+ * ```
59
+ */
60
+ export declare function useThemeMode(): {
61
+ /** The active theme family. */
62
+ family: PanelThemeFamily;
63
+ /** `'light'` or `'dark'` within that family. */
64
+ mode: ThemeMode;
65
+ /** Switch brand, staying in the current light/dark mode. */
66
+ setFamily: (id: string) => void;
67
+ /** Set the mode, staying in the current family. */
68
+ setMode: (next: ThemeMode) => void;
69
+ /** Flip light ↔ dark within the current family. */
70
+ toggleMode: () => void;
71
+ };
12
72
  //# sourceMappingURL=use-theme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-theme.d.ts","sourceRoot":"","sources":["../../../../src/theme/use-theme.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,QAAQ;IAIpB,oDAAoD;;IAEpD,mEAAmE;qBAClD,SAAS;EAE7B"}
1
+ {"version":3,"file":"use-theme.d.ts","sourceRoot":"","sources":["../../../../src/theme/use-theme.ts"],"names":[],"mappings":"AAEA,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,MAAM,GACN,MAAM,GACN,WAAW,GACX,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE9C,6CAA6C;AAC7C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEzC,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,gBAAgB,EAsBnD,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,SAAS,UAAU,EAElD,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAE/C,CAAC;AASF;;;GAGG;AACH,wBAAgB,QAAQ;IAIpB,6DAA6D;WAC7C,UAAU;IAC1B,gEAAgE;qBAC/C,SAAS;EAE7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY;IAMxB,+BAA+B;;IAE/B,gDAAgD;;IAEhD,4DAA4D;oBAC5C,MAAM;IAItB,mDAAmD;oBACnC,SAAS;IACzB,mDAAmD;;EAGtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panelui-native",
3
- "version": "0.1.0",
3
+ "version": "0.4.0",
4
4
  "description": "High-performance React Native UI components for Expo. Coss UI design language, powered by Uniwind (Tailwind v4) and Reanimated.",
5
5
  "main": "./lib/module/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -19,6 +19,7 @@
19
19
  "src",
20
20
  "lib",
21
21
  "theme.css",
22
+ "README.md",
22
23
  "!**/__tests__",
23
24
  "!**/*.tsbuildinfo"
24
25
  ],
@@ -32,19 +33,36 @@
32
33
  "react-native",
33
34
  "expo",
34
35
  "ui",
36
+ "ui-library",
37
+ "ui-components",
35
38
  "components",
39
+ "component-library",
36
40
  "tailwind",
41
+ "tailwindcss",
37
42
  "uniwind",
43
+ "nativewind",
44
+ "reanimated",
38
45
  "design-system",
39
- "shadcn"
46
+ "shadcn",
47
+ "dark-mode",
48
+ "theming",
49
+ "accessibility",
50
+ "typescript",
51
+ "ios",
52
+ "android",
53
+ "mobile"
40
54
  ],
41
55
  "repository": {
42
56
  "type": "git",
43
- "url": "git+https://github.com/Khalidabdi1/PanelUI.git"
57
+ "url": "git+https://github.com/panel-ui/PanelUI.git",
58
+ "directory": "packages/panelui"
59
+ },
60
+ "bugs": {
61
+ "url": "https://github.com/panel-ui/PanelUI/issues"
44
62
  },
45
63
  "author": "Khalid Abdi",
46
64
  "license": "MIT",
47
- "homepage": "https://github.com/Khalidabdi1/PanelUI#readme",
65
+ "homepage": "https://github.com/panel-ui/PanelUI#readme",
48
66
  "peerDependencies": {
49
67
  "react": "*",
50
68
  "react-native": "*",
@@ -66,7 +84,12 @@
66
84
  "source": "src",
67
85
  "output": "lib",
68
86
  "targets": [
69
- ["module", { "esm": true }],
87
+ [
88
+ "module",
89
+ {
90
+ "esm": true
91
+ }
92
+ ],
70
93
  "typescript"
71
94
  ]
72
95
  }
@@ -1,41 +1,50 @@
1
+ /**
2
+ * Alert — a status message with an optional leading status icon.
3
+ *
4
+ * Adapted from: heroui-inc/heroui-native src/components/alert/alert.tsx
5
+ * (Indicator / Content / Title / Description anatomy, status-driven icon and
6
+ * title colour), restyled with Coss UI tokens.
7
+ *
8
+ * The `variant` prop name is kept from PanelUI v0.2 rather than renamed to
9
+ * HeroUI's `status`, so existing code keeps working.
10
+ */
1
11
  import { createContext, forwardRef, useContext, type ReactNode } from 'react';
2
- import { View, type ViewProps } from 'react-native';
12
+ import { View, type Text as RNText, type ViewProps } from 'react-native';
3
13
  import { tv, type VariantProps } from 'tailwind-variants';
14
+ import { useCSSVariable } from 'uniwind';
4
15
  import { cn } from '../../utils/cn';
5
16
  import { Text, type TextProps } from '../../primitives/text';
17
+ import { AlertTriangleIcon, CheckCircleIcon, InfoIcon } from '../../icons';
6
18
 
7
19
  const alertVariants = tv({
8
20
  slots: {
9
- root: 'w-full gap-1 rounded-xl border p-4',
10
- title: 'font-semibold',
11
- description: 'text-sm',
21
+ root: 'w-full flex-row gap-3 rounded-xl border px-3.5 py-3',
22
+ indicator: 'pt-px',
23
+ content: 'flex-1 gap-0.5',
24
+ title: 'text-sm font-medium',
25
+ description: 'text-sm text-muted-foreground',
12
26
  },
13
27
  variants: {
14
28
  variant: {
15
29
  default: {
16
- root: 'border-border bg-card',
17
- title: 'text-foreground',
18
- description: 'text-muted-foreground',
30
+ root: 'border-border bg-surface',
31
+ title: 'text-card-foreground',
19
32
  },
20
33
  info: {
21
- root: 'border-info/32 bg-info/4',
22
- title: 'text-foreground',
23
- description: 'text-muted-foreground',
34
+ root: 'border-info/32 bg-info-soft',
35
+ title: 'text-info-foreground',
24
36
  },
25
37
  success: {
26
- root: 'border-success/32 bg-success/4',
27
- title: 'text-foreground',
28
- description: 'text-muted-foreground',
38
+ root: 'border-success/32 bg-success-soft',
39
+ title: 'text-success-foreground',
29
40
  },
30
41
  warning: {
31
- root: 'border-warning/32 bg-warning/4',
32
- title: 'text-foreground',
33
- description: 'text-muted-foreground',
42
+ root: 'border-warning/32 bg-warning-soft',
43
+ title: 'text-warning-foreground',
34
44
  },
35
45
  destructive: {
36
- root: 'border-destructive/32 bg-destructive/4',
37
- title: 'text-foreground',
38
- description: 'text-muted-foreground',
46
+ root: 'border-destructive/32 bg-destructive-soft',
47
+ title: 'text-destructive-foreground',
39
48
  },
40
49
  },
41
50
  },
@@ -44,20 +53,42 @@ const alertVariants = tv({
44
53
  },
45
54
  });
46
55
 
47
- type AlertVariant = VariantProps<typeof alertVariants>['variant'];
56
+ type AlertVariant = NonNullable<VariantProps<typeof alertVariants>['variant']>;
48
57
 
49
58
  const AlertContext = createContext<AlertVariant>('default');
50
59
 
60
+ /** CSS variable each variant's indicator icon takes its colour from. */
61
+ const INDICATOR_COLOR_VAR: Record<AlertVariant, string> = {
62
+ default: '--color-muted-foreground',
63
+ info: '--color-info-foreground',
64
+ success: '--color-success-foreground',
65
+ warning: '--color-warning-foreground',
66
+ destructive: '--color-destructive-foreground',
67
+ };
68
+
69
+ const INDICATOR_ICON: Record<AlertVariant, typeof InfoIcon> = {
70
+ default: InfoIcon,
71
+ info: InfoIcon,
72
+ success: CheckCircleIcon,
73
+ warning: AlertTriangleIcon,
74
+ destructive: AlertTriangleIcon,
75
+ };
76
+
51
77
  export interface AlertProps extends ViewProps, VariantProps<typeof alertVariants> {
52
78
  className?: string;
53
- /** Optional leading icon rendered before the content. */
79
+ /**
80
+ * Leading element rendered before the content.
81
+ *
82
+ * @deprecated Prefer `<Alert.Indicator>`, which picks a status icon for you.
83
+ * Still honoured so v0.2 call sites keep rendering.
84
+ */
54
85
  icon?: ReactNode;
55
86
  children?: ReactNode;
56
87
  }
57
88
 
58
89
  const AlertRoot = forwardRef<View, AlertProps>(
59
90
  ({ className, variant = 'default', icon, children, ...props }, ref) => {
60
- const { root } = alertVariants({ variant });
91
+ const { root, indicator, content } = alertVariants({ variant });
61
92
 
62
93
  return (
63
94
  <AlertContext.Provider value={variant}>
@@ -68,10 +99,10 @@ const AlertRoot = forwardRef<View, AlertProps>(
68
99
  {...props}
69
100
  >
70
101
  {icon ? (
71
- <View className="flex-row items-start gap-3">
72
- <View className="mt-0.5">{icon}</View>
73
- <View className="flex-1 gap-1">{children}</View>
74
- </View>
102
+ <>
103
+ <View className={indicator()}>{icon}</View>
104
+ <View className={content()}>{children}</View>
105
+ </>
75
106
  ) : (
76
107
  children
77
108
  )}
@@ -82,7 +113,48 @@ const AlertRoot = forwardRef<View, AlertProps>(
82
113
  );
83
114
  AlertRoot.displayName = 'Alert';
84
115
 
85
- const AlertTitle = forwardRef<React.ElementRef<typeof Text>, TextProps>(
116
+ export interface AlertIndicatorProps extends ViewProps {
117
+ className?: string;
118
+ /** Overrides the size/colour of the default status icon. */
119
+ iconProps?: { size?: number; color?: string };
120
+ /** Replaces the default status icon entirely. */
121
+ children?: ReactNode;
122
+ }
123
+
124
+ /**
125
+ * Leading status icon. Resolves both the icon and its colour from the parent
126
+ * Alert's variant, so it follows the active theme.
127
+ */
128
+ const AlertIndicator = forwardRef<View, AlertIndicatorProps>(
129
+ ({ className, iconProps, children, ...props }, ref) => {
130
+ const variant = useContext(AlertContext);
131
+ const { indicator } = alertVariants({ variant });
132
+ const themeColor = useCSSVariable(INDICATOR_COLOR_VAR[variant]);
133
+ const Icon = INDICATOR_ICON[variant];
134
+
135
+ const color =
136
+ iconProps?.color ?? (typeof themeColor === 'string' ? themeColor : undefined);
137
+
138
+ return (
139
+ <View ref={ref} className={indicator({ className })} {...props}>
140
+ {children ?? <Icon size={iconProps?.size ?? 18} color={color} />}
141
+ </View>
142
+ );
143
+ }
144
+ );
145
+ AlertIndicator.displayName = 'Alert.Indicator';
146
+
147
+ /** Flex-1 wrapper for Alert.Title and Alert.Description. */
148
+ const AlertContent = forwardRef<View, ViewProps & { className?: string }>(
149
+ ({ className, ...props }, ref) => {
150
+ const variant = useContext(AlertContext);
151
+ const { content } = alertVariants({ variant });
152
+ return <View ref={ref} className={content({ className })} {...props} />;
153
+ }
154
+ );
155
+ AlertContent.displayName = 'Alert.Content';
156
+
157
+ const AlertTitle = forwardRef<RNText, TextProps>(
86
158
  ({ className, ...props }, ref) => {
87
159
  const variant = useContext(AlertContext);
88
160
  const { title } = alertVariants({ variant });
@@ -91,7 +163,7 @@ const AlertTitle = forwardRef<React.ElementRef<typeof Text>, TextProps>(
91
163
  );
92
164
  AlertTitle.displayName = 'Alert.Title';
93
165
 
94
- const AlertDescription = forwardRef<React.ElementRef<typeof Text>, TextProps>(
166
+ const AlertDescription = forwardRef<RNText, TextProps>(
95
167
  ({ className, ...props }, ref) => {
96
168
  const variant = useContext(AlertContext);
97
169
  const { description } = alertVariants({ variant });
@@ -101,6 +173,10 @@ const AlertDescription = forwardRef<React.ElementRef<typeof Text>, TextProps>(
101
173
  AlertDescription.displayName = 'Alert.Description';
102
174
 
103
175
  export const Alert = Object.assign(AlertRoot, {
176
+ /** @optional Status icon rendered as the leading visual element. */
177
+ Indicator: AlertIndicator,
178
+ /** @optional Wrapper for title and description. */
179
+ Content: AlertContent,
104
180
  Title: AlertTitle,
105
181
  Description: AlertDescription,
106
182
  });
@@ -12,7 +12,7 @@ import { Text } from '../../primitives/text';
12
12
  const avatarVariants = tv({
13
13
  slots: {
14
14
  root: 'items-center justify-center overflow-hidden rounded-full border border-border bg-muted',
15
- image: 'h-full w-full',
15
+ image: 'absolute inset-0 h-full w-full',
16
16
  fallback: 'font-medium text-muted-foreground',
17
17
  },
18
18
  variants: {
@@ -14,9 +14,9 @@ const badgeVariants = tv({
14
14
  secondary: { root: 'bg-secondary', label: 'text-secondary-foreground' },
15
15
  outline: { root: 'border-border bg-transparent', label: 'text-foreground' },
16
16
  destructive: { root: 'bg-destructive', label: 'text-white' },
17
- success: { root: 'bg-success/8 dark:bg-success/16', label: 'text-success-foreground' },
18
- warning: { root: 'bg-warning/8 dark:bg-warning/16', label: 'text-warning-foreground' },
19
- info: { root: 'bg-info/8 dark:bg-info/16', label: 'text-info-foreground' },
17
+ success: { root: 'bg-success-subtle', label: 'text-success-foreground' },
18
+ warning: { root: 'bg-warning-subtle', label: 'text-warning-foreground' },
19
+ info: { root: 'bg-info-subtle', label: 'text-info-foreground' },
20
20
  },
21
21
  },
22
22
  defaultVariants: {
@@ -111,7 +111,8 @@ function BottomSheetContent({
111
111
  children,
112
112
  ...props
113
113
  }: BottomSheetContentProps) {
114
- const { open, setOpen } = useBottomSheet('BottomSheet.Content');
114
+ const context = useBottomSheet('BottomSheet.Content');
115
+ const { open, setOpen } = context;
115
116
  const { height: screenHeight } = useWindowDimensions();
116
117
  const insets = useSafeAreaInsets();
117
118
  const translateY = useSharedValue(0);
@@ -145,7 +146,10 @@ function BottomSheetContent({
145
146
 
146
147
  return (
147
148
  <Portal>
148
- <View className="absolute inset-0 justify-end">
149
+ {/* Portal content mounts under PortalHost, outside this provider's
150
+ subtree — re-provide the context so nested consumers keep working. */}
151
+ <BottomSheetContext.Provider value={context}>
152
+ <View className="absolute inset-0 justify-end">
149
153
  <Animated.View
150
154
  entering={FadeIn.duration(180)}
151
155
  exiting={FadeOut.duration(180)}
@@ -175,7 +179,8 @@ function BottomSheetContent({
175
179
  {children}
176
180
  </Animated.View>
177
181
  </GestureDetector>
178
- </View>
182
+ </View>
183
+ </BottomSheetContext.Provider>
179
184
  </Portal>
180
185
  );
181
186
  }
@@ -1,4 +1,4 @@
1
- import { forwardRef, isValidElement, type ReactNode } from 'react';
1
+ import { forwardRef, type ReactNode } from 'react';
2
2
  import type { View } from 'react-native';
3
3
  import { tv, type VariantProps } from 'tailwind-variants';
4
4
  import {
@@ -6,33 +6,40 @@ import {
6
6
  type AnimatedPressableProps,
7
7
  } from '../../primitives/animated-pressable';
8
8
  import { Text } from '../../primitives/text';
9
+ import { Spinner } from '../spinner';
9
10
 
10
11
  const buttonVariants = tv({
11
12
  slots: {
12
13
  root: 'flex-row items-center justify-center gap-2 rounded-lg border border-transparent',
13
14
  label: 'font-medium',
15
+ spinner: '',
14
16
  },
15
17
  variants: {
16
18
  variant: {
17
19
  primary: {
18
20
  root: 'border-primary bg-primary shadow-sm',
19
21
  label: 'text-primary-foreground',
22
+ spinner: 'border-primary-foreground/32 border-t-primary-foreground',
20
23
  },
21
24
  secondary: {
22
25
  root: 'bg-secondary',
23
26
  label: 'text-secondary-foreground',
27
+ spinner: 'border-secondary-foreground/24 border-t-secondary-foreground',
24
28
  },
25
29
  outline: {
26
30
  root: 'border-input bg-popover shadow-sm',
27
31
  label: 'text-foreground',
32
+ spinner: 'border-muted border-t-foreground',
28
33
  },
29
34
  ghost: {
30
35
  root: 'bg-transparent',
31
36
  label: 'text-foreground',
37
+ spinner: 'border-muted border-t-foreground',
32
38
  },
33
39
  destructive: {
34
40
  root: 'border-destructive bg-destructive shadow-sm',
35
41
  label: 'text-white',
42
+ spinner: 'border-white/32 border-t-white',
36
43
  },
37
44
  },
38
45
  size: {
@@ -41,6 +48,9 @@ const buttonVariants = tv({
41
48
  lg: { root: 'h-12 px-6', label: 'text-lg' },
42
49
  icon: { root: 'h-11 w-11 px-0' },
43
50
  },
51
+ fullWidth: {
52
+ true: { root: 'w-full' },
53
+ },
44
54
  disabled: {
45
55
  true: { root: 'opacity-[0.64]' },
46
56
  },
@@ -53,38 +63,68 @@ const buttonVariants = tv({
53
63
 
54
64
  type ButtonVariantProps = VariantProps<typeof buttonVariants>;
55
65
 
66
+ const SPINNER_SIZE = { sm: 'sm', md: 'sm', lg: 'md', icon: 'sm' } as const;
67
+
56
68
  export interface ButtonProps
57
69
  extends Omit<AnimatedPressableProps, 'children' | 'disabled'>,
58
70
  Omit<ButtonVariantProps, 'disabled'> {
59
71
  children?: ReactNode;
60
72
  disabled?: boolean;
73
+ /** Show a spinner and block presses while an action is in flight. */
74
+ loading?: boolean;
75
+ /** Content rendered before the label (replaced by the spinner while loading). */
76
+ startContent?: ReactNode;
77
+ /** Content rendered after the label. */
78
+ endContent?: ReactNode;
61
79
  /** Extra classes for the label when children is a string. */
62
80
  labelClassName?: string;
63
81
  }
64
82
 
65
83
  export const Button = forwardRef<View, ButtonProps>(
66
84
  (
67
- { children, className, labelClassName, variant, size, disabled, ...props },
85
+ {
86
+ children,
87
+ className,
88
+ labelClassName,
89
+ variant,
90
+ size,
91
+ fullWidth,
92
+ disabled,
93
+ loading = false,
94
+ startContent,
95
+ endContent,
96
+ ...props
97
+ },
68
98
  ref
69
99
  ) => {
70
- const { root, label } = buttonVariants({ variant, size, disabled: !!disabled });
100
+ const isDisabled = disabled || loading;
101
+ const { root, label, spinner } = buttonVariants({
102
+ variant,
103
+ size,
104
+ fullWidth,
105
+ disabled: isDisabled,
106
+ });
71
107
 
72
108
  return (
73
109
  <AnimatedPressable
74
110
  ref={ref}
75
111
  accessibilityRole="button"
76
- accessibilityState={{ disabled: !!disabled }}
77
- disabled={disabled}
112
+ accessibilityState={{ disabled: isDisabled, busy: loading }}
113
+ disabled={isDisabled}
78
114
  className={root({ className })}
79
115
  {...props}
80
116
  >
117
+ {loading ? (
118
+ <Spinner size={SPINNER_SIZE[size ?? 'md']} className={spinner()} />
119
+ ) : (
120
+ startContent
121
+ )}
81
122
  {typeof children === 'string' ? (
82
123
  <Text className={label({ className: labelClassName })}>{children}</Text>
83
- ) : isValidElement(children) ? (
84
- children
85
124
  ) : (
86
125
  children
87
126
  )}
127
+ {endContent}
88
128
  </AnimatedPressable>
89
129
  );
90
130
  }
@@ -10,14 +10,14 @@ export interface CardProps extends ViewProps {
10
10
  const CardRoot = forwardRef<View, CardProps>(({ className, ...props }, ref) => (
11
11
  <View
12
12
  ref={ref}
13
- className={cn('rounded-xl border border-border bg-card shadow-sm', className)}
13
+ className={cn('rounded-2xl border border-border bg-card shadow-sm', className)}
14
14
  {...props}
15
15
  />
16
16
  ));
17
17
  CardRoot.displayName = 'Card';
18
18
 
19
19
  const CardHeader = forwardRef<View, CardProps>(({ className, ...props }, ref) => (
20
- <View ref={ref} className={cn('gap-1.5 p-4', className)} {...props} />
20
+ <View ref={ref} className={cn('gap-1.5 p-6', className)} {...props} />
21
21
  ));
22
22
  CardHeader.displayName = 'Card.Header';
23
23
 
@@ -27,7 +27,7 @@ const CardTitle = forwardRef<React.ElementRef<typeof Text>, TextProps>(
27
27
  ref={ref}
28
28
  size="lg"
29
29
  weight="semibold"
30
- className={cn('text-card-foreground', className)}
30
+ className={cn('leading-none text-card-foreground', className)}
31
31
  {...props}
32
32
  />
33
33
  )
@@ -42,14 +42,14 @@ const CardDescription = forwardRef<React.ElementRef<typeof Text>, TextProps>(
42
42
  CardDescription.displayName = 'Card.Description';
43
43
 
44
44
  const CardContent = forwardRef<View, CardProps>(({ className, ...props }, ref) => (
45
- <View ref={ref} className={cn('p-4 pt-0', className)} {...props} />
45
+ <View ref={ref} className={cn('p-6 pt-0', className)} {...props} />
46
46
  ));
47
47
  CardContent.displayName = 'Card.Content';
48
48
 
49
49
  const CardFooter = forwardRef<View, CardProps>(({ className, ...props }, ref) => (
50
50
  <View
51
51
  ref={ref}
52
- className={cn('flex-row items-center gap-2 p-4 pt-0', className)}
52
+ className={cn('flex-row items-center gap-2 p-6 pt-0', className)}
53
53
  {...props}
54
54
  />
55
55
  ));