rn-feav-ui 1.0.7 → 1.0.8

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.
@@ -1,9 +1,25 @@
1
1
  import * as React from "react";
2
- import { darkTheme, lightTheme } from './colors';
3
- export declare const ThemeFEAVUiProvider: ({ children }: {
2
+ import { type ThemeFEA } from "./colors";
3
+ type DeepPartial<T> = {
4
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
5
+ };
6
+ export type ThemeOverridesFEA = {
7
+ light?: DeepPartial<ThemeFEA>;
8
+ dark?: DeepPartial<ThemeFEA>;
9
+ };
10
+ export type ThemeFEAVUiProviderProps = {
4
11
  children: React.ReactNode;
5
- }) => React.JSX.Element;
12
+ /** Default mode for first render (default: `light`). */
13
+ defaultMode?: "light" | "dark";
14
+ /**
15
+ * Override tokens from the app.
16
+ * Example: `{ dark: { colors: { background: "#000" } } }`
17
+ */
18
+ themeOverrides?: ThemeOverridesFEA;
19
+ };
20
+ export declare const ThemeFEAVUiProvider: ({ children, defaultMode, themeOverrides, }: ThemeFEAVUiProviderProps) => React.JSX.Element;
6
21
  export declare const useTheme: () => {
7
- theme: typeof lightTheme | typeof darkTheme;
22
+ theme: ThemeFEA;
8
23
  toggleTheme: () => void;
9
24
  } | null;
25
+ export {};
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
14
  if (k2 === undefined) k2 = k;
4
15
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -37,14 +48,43 @@ exports.useTheme = exports.ThemeFEAVUiProvider = void 0;
37
48
  var React = __importStar(require("react"));
38
49
  var react_1 = require("react");
39
50
  var colors_1 = require("./colors");
51
+ function isPlainObject(value) {
52
+ return typeof value === "object" && value !== null && !Array.isArray(value);
53
+ }
54
+ function deepMergeFEA(base, override) {
55
+ if (!override)
56
+ return base;
57
+ var out = isPlainObject(base) ? __assign({}, base) : base;
58
+ for (var _i = 0, _a = Object.keys(override); _i < _a.length; _i++) {
59
+ var key = _a[_i];
60
+ var overrideValue = override[key];
61
+ if (overrideValue === undefined)
62
+ continue;
63
+ var baseValue = base[key];
64
+ if (isPlainObject(baseValue) && isPlainObject(overrideValue)) {
65
+ out[key] = deepMergeFEA(baseValue, overrideValue);
66
+ }
67
+ else {
68
+ out[key] = overrideValue;
69
+ }
70
+ }
71
+ return out;
72
+ }
40
73
  var ThemeContext = (0, react_1.createContext)(null);
41
74
  var ThemeFEAVUiProvider = function (_a) {
42
- var children = _a.children;
43
- var _b = (0, react_1.useState)(colors_1.lightTheme), theme = _b[0], setTheme = _b[1];
75
+ var children = _a.children, _b = _a.defaultMode, defaultMode = _b === void 0 ? "light" : _b, themeOverrides = _a.themeOverrides;
76
+ var _c = (0, react_1.useState)(defaultMode), mode = _c[0], setMode = _c[1];
77
+ var baseTheme = mode === "light" ? colors_1.lightTheme : colors_1.darkTheme;
78
+ var mergedTheme = (0, react_1.useMemo)(function () {
79
+ var sideOverride = mode === "light" ? themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.light : themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.dark;
80
+ var theme = deepMergeFEA(baseTheme, sideOverride);
81
+ // Ensure mode matches the current mode even if override tries to change it.
82
+ return __assign(__assign({}, theme), { mode: mode });
83
+ }, [baseTheme, mode, themeOverrides]);
44
84
  var toggleTheme = function () {
45
- setTheme(theme.mode === 'light' ? colors_1.darkTheme : colors_1.lightTheme);
85
+ setMode(function (prev) { return (prev === "light" ? "dark" : "light"); });
46
86
  };
47
- return (React.createElement(ThemeContext.Provider, { value: { theme: theme, toggleTheme: toggleTheme } }, children));
87
+ return React.createElement(ThemeContext.Provider, { value: { theme: mergedTheme, toggleTheme: toggleTheme } }, children);
48
88
  };
49
89
  exports.ThemeFEAVUiProvider = ThemeFEAVUiProvider;
50
90
  var useTheme = function () { return (0, react_1.useContext)(ThemeContext); };
@@ -1,5 +1,76 @@
1
1
  export declare const lightTheme: {
2
2
  mode: string;
3
+ fontSizes: {
4
+ xs: number;
5
+ sm: number;
6
+ md: number;
7
+ lg: number;
8
+ xl: number;
9
+ "2xl": number;
10
+ "3xl": number;
11
+ "4xl": number;
12
+ "5xl": number;
13
+ };
14
+ lineHeights: {
15
+ xs: number;
16
+ sm: number;
17
+ md: number;
18
+ lg: number;
19
+ xl: number;
20
+ "2xl": number;
21
+ "3xl": number;
22
+ "4xl": number;
23
+ "5xl": number;
24
+ };
25
+ spacing: {
26
+ xs: number;
27
+ sm: number;
28
+ md: number;
29
+ lg: number;
30
+ xl: number;
31
+ "2xl": number;
32
+ "3xl": number;
33
+ };
34
+ radii: {
35
+ sm: number;
36
+ md: number;
37
+ lg: number;
38
+ xl: number;
39
+ full: number;
40
+ };
41
+ fontWeights: {
42
+ normal: number;
43
+ medium: number;
44
+ semibold: number;
45
+ bold: number;
46
+ extrabold: number;
47
+ };
48
+ borderWidths: {
49
+ thin: number;
50
+ thick: number;
51
+ };
52
+ shadows: {
53
+ sm: {
54
+ shadowColor: string;
55
+ shadowOpacity: number;
56
+ shadowRadius: number;
57
+ shadowOffset: {
58
+ width: number;
59
+ height: number;
60
+ };
61
+ elevation: number;
62
+ };
63
+ md: {
64
+ shadowColor: string;
65
+ shadowOpacity: number;
66
+ shadowRadius: number;
67
+ shadowOffset: {
68
+ width: number;
69
+ height: number;
70
+ };
71
+ elevation: number;
72
+ };
73
+ };
3
74
  colors: {
4
75
  background: string;
5
76
  foreground: string;
@@ -21,10 +92,89 @@ export declare const lightTheme: {
21
92
  bg: string;
22
93
  text: string;
23
94
  glass: string;
95
+ accent: string;
96
+ accentForeground: string;
97
+ success: string;
98
+ successForeground: string;
99
+ warning: string;
100
+ warningForeground: string;
101
+ info: string;
102
+ infoForeground: string;
24
103
  };
25
104
  };
26
105
  export declare const darkTheme: {
27
106
  mode: string;
107
+ fontSizes: {
108
+ xs: number;
109
+ sm: number;
110
+ md: number;
111
+ lg: number;
112
+ xl: number;
113
+ "2xl": number;
114
+ "3xl": number;
115
+ "4xl": number;
116
+ "5xl": number;
117
+ };
118
+ lineHeights: {
119
+ xs: number;
120
+ sm: number;
121
+ md: number;
122
+ lg: number;
123
+ xl: number;
124
+ "2xl": number;
125
+ "3xl": number;
126
+ "4xl": number;
127
+ "5xl": number;
128
+ };
129
+ spacing: {
130
+ xs: number;
131
+ sm: number;
132
+ md: number;
133
+ lg: number;
134
+ xl: number;
135
+ "2xl": number;
136
+ "3xl": number;
137
+ };
138
+ radii: {
139
+ sm: number;
140
+ md: number;
141
+ lg: number;
142
+ xl: number;
143
+ full: number;
144
+ };
145
+ fontWeights: {
146
+ normal: number;
147
+ medium: number;
148
+ semibold: number;
149
+ bold: number;
150
+ extrabold: number;
151
+ };
152
+ borderWidths: {
153
+ thin: number;
154
+ thick: number;
155
+ };
156
+ shadows: {
157
+ sm: {
158
+ shadowColor: string;
159
+ shadowOpacity: number;
160
+ shadowRadius: number;
161
+ shadowOffset: {
162
+ width: number;
163
+ height: number;
164
+ };
165
+ elevation: number;
166
+ };
167
+ md: {
168
+ shadowColor: string;
169
+ shadowOpacity: number;
170
+ shadowRadius: number;
171
+ shadowOffset: {
172
+ width: number;
173
+ height: number;
174
+ };
175
+ elevation: number;
176
+ };
177
+ };
28
178
  colors: {
29
179
  background: string;
30
180
  foreground: string;
@@ -46,5 +196,14 @@ export declare const darkTheme: {
46
196
  bg: string;
47
197
  text: string;
48
198
  glass: string;
199
+ accent: string;
200
+ accentForeground: string;
201
+ success: string;
202
+ successForeground: string;
203
+ warning: string;
204
+ warningForeground: string;
205
+ info: string;
206
+ infoForeground: string;
49
207
  };
50
208
  };
209
+ export type ThemeFEA = typeof lightTheme;
@@ -6,6 +6,71 @@ exports.darkTheme = exports.lightTheme = void 0;
6
6
  // ========================================
7
7
  exports.lightTheme = {
8
8
  mode: 'light',
9
+ fontSizes: {
10
+ xs: 12,
11
+ sm: 14,
12
+ md: 16,
13
+ lg: 18,
14
+ xl: 20,
15
+ "2xl": 24,
16
+ "3xl": 30,
17
+ "4xl": 36,
18
+ "5xl": 48,
19
+ },
20
+ lineHeights: {
21
+ xs: 16,
22
+ sm: 20,
23
+ md: 24,
24
+ lg: 28,
25
+ xl: 30,
26
+ "2xl": 32,
27
+ "3xl": 36,
28
+ "4xl": 40,
29
+ "5xl": 52,
30
+ },
31
+ spacing: {
32
+ xs: 2,
33
+ sm: 4,
34
+ md: 8,
35
+ lg: 12,
36
+ xl: 16,
37
+ "2xl": 24,
38
+ "3xl": 32,
39
+ },
40
+ radii: {
41
+ sm: 8,
42
+ md: 12,
43
+ lg: 14,
44
+ xl: 16,
45
+ full: 999,
46
+ },
47
+ fontWeights: {
48
+ normal: 400,
49
+ medium: 500,
50
+ semibold: 600,
51
+ bold: 700,
52
+ extrabold: 800,
53
+ },
54
+ borderWidths: {
55
+ thin: 1,
56
+ thick: 2,
57
+ },
58
+ shadows: {
59
+ sm: {
60
+ shadowColor: "#0f172a",
61
+ shadowOpacity: 0.08,
62
+ shadowRadius: 6,
63
+ shadowOffset: { width: 0, height: 2 },
64
+ elevation: 2,
65
+ },
66
+ md: {
67
+ shadowColor: "#0f172a",
68
+ shadowOpacity: 0.12,
69
+ shadowRadius: 10,
70
+ shadowOffset: { width: 0, height: 6 },
71
+ elevation: 4,
72
+ },
73
+ },
9
74
  colors: {
10
75
  // shadcn-like semantic tokens (neutral base + clear primary)
11
76
  background: "#ffffff",
@@ -29,10 +94,84 @@ exports.lightTheme = {
29
94
  bg: "#ffffff",
30
95
  text: "#0f172a",
31
96
  glass: "rgba(255,255,255,0.55)",
97
+ // extra semantic colors (useful for alerts/status)
98
+ accent: "#7c3aed",
99
+ accentForeground: "#ffffff",
100
+ success: "#16a34a",
101
+ successForeground: "#ffffff",
102
+ warning: "#f59e0b",
103
+ warningForeground: "#1f2937",
104
+ info: "#0ea5e9",
105
+ infoForeground: "#ffffff",
32
106
  }
33
107
  };
34
108
  exports.darkTheme = {
35
109
  mode: 'dark',
110
+ fontSizes: {
111
+ xs: 12,
112
+ sm: 14,
113
+ md: 16,
114
+ lg: 18,
115
+ xl: 20,
116
+ "2xl": 24,
117
+ "3xl": 30,
118
+ "4xl": 36,
119
+ "5xl": 48,
120
+ },
121
+ lineHeights: {
122
+ xs: 16,
123
+ sm: 20,
124
+ md: 24,
125
+ lg: 28,
126
+ xl: 30,
127
+ "2xl": 32,
128
+ "3xl": 36,
129
+ "4xl": 40,
130
+ "5xl": 52,
131
+ },
132
+ spacing: {
133
+ xs: 2,
134
+ sm: 4,
135
+ md: 8,
136
+ lg: 12,
137
+ xl: 16,
138
+ "2xl": 24,
139
+ "3xl": 32,
140
+ },
141
+ radii: {
142
+ sm: 8,
143
+ md: 12,
144
+ lg: 14,
145
+ xl: 16,
146
+ full: 999,
147
+ },
148
+ fontWeights: {
149
+ normal: 400,
150
+ medium: 500,
151
+ semibold: 600,
152
+ bold: 700,
153
+ extrabold: 800,
154
+ },
155
+ borderWidths: {
156
+ thin: 1,
157
+ thick: 2,
158
+ },
159
+ shadows: {
160
+ sm: {
161
+ shadowColor: "#000000",
162
+ shadowOpacity: 0.35,
163
+ shadowRadius: 8,
164
+ shadowOffset: { width: 0, height: 3 },
165
+ elevation: 3,
166
+ },
167
+ md: {
168
+ shadowColor: "#000000",
169
+ shadowOpacity: 0.45,
170
+ shadowRadius: 14,
171
+ shadowOffset: { width: 0, height: 8 },
172
+ elevation: 6,
173
+ },
174
+ },
36
175
  colors: {
37
176
  background: "#020617",
38
177
  foreground: "#f8fafc",
@@ -55,5 +194,14 @@ exports.darkTheme = {
55
194
  bg: "#020617",
56
195
  text: "#f8fafc",
57
196
  glass: "rgba(2,6,23,0.6)",
197
+ // extra semantic colors (useful for alerts/status)
198
+ accent: "#a78bfa",
199
+ accentForeground: "#0b1220",
200
+ success: "#22c55e",
201
+ successForeground: "#04110b",
202
+ warning: "#fbbf24",
203
+ warningForeground: "#0b1220",
204
+ info: "#38bdf8",
205
+ infoForeground: "#041018",
58
206
  }
59
207
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-feav-ui",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Shadcn-style React Native UI kit with theme support.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/readme.md CHANGED
@@ -86,7 +86,7 @@ Imports from package root:
86
86
 
87
87
  - `ShowcaseFEA` (recommended): full demo with internal `ThemeFEAVUiProvider` + `SonnerFEA`.
88
88
  - `ShowcaseWithProviderFEA`: same as `ShowcaseFEA` (explicit naming).
89
- - `ShowcaseScreenFEA`: screen only, for apps that already wrap provider + toast host.
89
+ - `ShowcaseScreenFEA`: screen only, for apps that already wrap provider + toast host. Props: `contentContainerStyle?: ViewStyle`.
90
90
  - `Showcase`: backward-compatible alias of `ShowcaseFEA`.
91
91
 
92
92
  Example (standalone):
@@ -110,7 +110,7 @@ export default function Screen() {
110
110
  return (
111
111
  <ThemeFEAVUiProvider>
112
112
  <SonnerFEA>
113
- <ShowcaseScreenFEA />
113
+ <ShowcaseScreenFEA contentContainerStyle={{ padding: 24, gap: 20 }} />
114
114
  </SonnerFEA>
115
115
  </ThemeFEAVUiProvider>
116
116
  );
@@ -125,11 +125,31 @@ export default function Screen() {
125
125
 
126
126
  | Export | Description |
127
127
  | --- | --- |
128
- | `ThemeFEAVUiProvider` | Wraps the app; provides `theme` and `toggleTheme`. Props: `children: React.ReactNode`. |
128
+ | `ThemeFEAVUiProvider` | Wraps the app; provides `theme` and `toggleTheme`. Props: `children`, `defaultMode?`, `themeOverrides?`. |
129
129
  | `useTheme()` | Returns `{ theme, toggleTheme } \| null`. `theme` is `lightTheme \| darkTheme`. |
130
130
  | `lightTheme` / `darkTheme` | Exported from the package root for typing or static access: `import { lightTheme, darkTheme } from "rn-feav-ui"`. Prefer `useTheme()` at runtime inside components. |
131
131
 
132
- **`theme.colors` (semantic tokens)** include: `background`, `foreground`, `card`, `cardForeground`, `muted`, `mutedForeground`, `border`, `input`, `ring`, `primary`, `primaryForeground`, `secondary`, `secondaryForeground`, `destructive`, `destructiveForeground`, plus aliases `bg`, `text`, `glass`. See `src/theme/colors.ts`.
132
+ **`theme.colors` (semantic tokens)** include: `background`, `foreground`, `card`, `cardForeground`, `muted`, `mutedForeground`, `border`, `input`, `ring`, `primary`, `primaryForeground`, `secondary`, `secondaryForeground`, `destructive`, `destructiveForeground`, plus aliases `bg`, `text`, `glass`, and extra status tokens `accent`, `success`, `warning`, `info` (with `*Foreground`). See `src/theme/colors.ts`.
133
+
134
+ **Other theme tokens**: `fontSizes`, `lineHeights`, `spacing`, `radii`, `fontWeights`, `borderWidths`, `shadows`.
135
+
136
+ You can override tokens from your app:
137
+
138
+ ```tsx
139
+ import { ThemeFEAVUiProvider } from "rn-feav-ui";
140
+
141
+ <ThemeFEAVUiProvider
142
+ defaultMode="dark"
143
+ themeOverrides={{
144
+ dark: {
145
+ colors: { background: "#000000", card: "#111827" },
146
+ fontSizes: { md: 17 },
147
+ },
148
+ }}
149
+ >
150
+ {/* app */}
151
+ </ThemeFEAVUiProvider>;
152
+ ```
133
153
 
134
154
  | Export | Description |
135
155
  | --- | --- |