@mrmeg/expo-ui 0.4.2 → 0.5.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.
- package/LLM_USAGE.md +1 -1
- package/README.md +1 -1
- package/dist/components/Button.d.ts +13 -3
- package/dist/hooks/useTheme.js +16 -1
- package/dist/state/themeStore.d.ts +30 -0
- package/dist/state/themeStore.js +6 -0
- package/package.json +1 -1
package/LLM_USAGE.md
CHANGED
|
@@ -37,7 +37,7 @@ near the root when the app uses package feedback or overlay components.
|
|
|
37
37
|
`@rn-primitives` portal host.
|
|
38
38
|
|
|
39
39
|
```tsx
|
|
40
|
-
import { ThemeProvider } from "
|
|
40
|
+
import { ThemeProvider } from "expo-router";
|
|
41
41
|
import { UIProvider } from "@mrmeg/expo-ui/components";
|
|
42
42
|
import { colors } from "@mrmeg/expo-ui/constants";
|
|
43
43
|
import { useResources, useTheme } from "@mrmeg/expo-ui/hooks";
|
package/README.md
CHANGED
|
@@ -307,7 +307,7 @@ LLM rules:
|
|
|
307
307
|
Call `useResources()` once near the Expo app root before hiding the splash screen:
|
|
308
308
|
|
|
309
309
|
```tsx
|
|
310
|
-
import { ThemeProvider } from "
|
|
310
|
+
import { ThemeProvider } from "expo-router";
|
|
311
311
|
import { colors } from "@mrmeg/expo-ui/constants";
|
|
312
312
|
import { useResources, useTheme } from "@mrmeg/expo-ui/hooks";
|
|
313
313
|
import { UIProvider } from "@mrmeg/expo-ui/components";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { ComponentType } from "react";
|
|
2
|
-
import { PressableProps, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
import { PressableProps, PressableStateCallbackType, DimensionValue, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
3
3
|
import { TextProps } from "./StyledText";
|
|
4
4
|
/**
|
|
5
5
|
* Button variants
|
|
@@ -9,9 +9,19 @@ type Presets = "default" | "outline" | "ghost" | "link" | "destructive" | "secon
|
|
|
9
9
|
* Button size variants
|
|
10
10
|
*/
|
|
11
11
|
export type ButtonSize = "sm" | "md" | "lg";
|
|
12
|
-
export type ButtonAccessoryStyle =
|
|
12
|
+
export type ButtonAccessoryStyle = {
|
|
13
|
+
margin?: DimensionValue;
|
|
14
|
+
marginHorizontal?: DimensionValue;
|
|
15
|
+
marginVertical?: DimensionValue;
|
|
16
|
+
marginTop?: DimensionValue;
|
|
17
|
+
marginRight?: DimensionValue;
|
|
18
|
+
marginBottom?: DimensionValue;
|
|
19
|
+
marginLeft?: DimensionValue;
|
|
20
|
+
marginStart?: DimensionValue;
|
|
21
|
+
marginEnd?: DimensionValue;
|
|
22
|
+
};
|
|
13
23
|
export interface ButtonAccessoryProps {
|
|
14
|
-
style:
|
|
24
|
+
style: ButtonAccessoryStyle;
|
|
15
25
|
pressableState: PressableStateCallbackType;
|
|
16
26
|
disabled?: boolean;
|
|
17
27
|
}
|
package/dist/hooks/useTheme.js
CHANGED
|
@@ -47,9 +47,24 @@ export function useTheme() {
|
|
|
47
47
|
const userTheme = useThemeStore((s) => s.userTheme);
|
|
48
48
|
const systemTheme = useThemeStore((s) => s.systemTheme);
|
|
49
49
|
const setTheme = useThemeStore((s) => s.setTheme);
|
|
50
|
+
const colorOverrides = useThemeStore((s) => s.colorOverrides);
|
|
50
51
|
// Determine which theme to use (user preference or system)
|
|
51
52
|
const effectiveScheme = resolveThemePreference(userTheme, systemTheme);
|
|
52
|
-
const
|
|
53
|
+
const base = colors[effectiveScheme];
|
|
54
|
+
// Layer any app-injected palette over the package defaults for the active
|
|
55
|
+
// scheme. When no override is present we return the base theme *by reference*
|
|
56
|
+
// so memoization and identity checks downstream stay stable (and the package
|
|
57
|
+
// behaves exactly as it did before overrides existed).
|
|
58
|
+
const override = colorOverrides[effectiveScheme];
|
|
59
|
+
const theme = useMemo(() => {
|
|
60
|
+
if (!override || Object.keys(override).length === 0) {
|
|
61
|
+
return base;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
...base,
|
|
65
|
+
colors: { ...base.colors, ...override },
|
|
66
|
+
};
|
|
67
|
+
}, [base, override]);
|
|
53
68
|
// Sync theme to DOM so CSS in +html.tsx follows the app's runtime theme
|
|
54
69
|
useEffect(() => {
|
|
55
70
|
if (Platform.OS === "web" && typeof document !== "undefined") {
|
|
@@ -1,10 +1,40 @@
|
|
|
1
|
+
import type { ThemeColors } from "../constants/colors";
|
|
1
2
|
export type ThemePreference = "system" | "light" | "dark";
|
|
2
3
|
export type ResolvedTheme = "light" | "dark";
|
|
4
|
+
/**
|
|
5
|
+
* Per-scheme color overrides a host app can inject to brand the package.
|
|
6
|
+
*
|
|
7
|
+
* The package ships a neutral default palette (see `constants/colors.ts`).
|
|
8
|
+
* A consuming app almost always has its own brand palette; without a way to
|
|
9
|
+
* push it in, package components (Badge, Button, inputs, …) render with the
|
|
10
|
+
* package's colors while app-authored siblings render with the app's — the
|
|
11
|
+
* two disagree on what e.g. `primary` means, producing collisions such as
|
|
12
|
+
* white text on a white badge. `setColors` lets the app forward its palette
|
|
13
|
+
* once so every package component resolves against the same source of truth.
|
|
14
|
+
*
|
|
15
|
+
* Each scheme is `Partial<ThemeColors>`: only the keys provided are overridden,
|
|
16
|
+
* so an app can re-skin `primary`/`accent` while inheriting neutral defaults.
|
|
17
|
+
*/
|
|
18
|
+
export type ColorOverrides = {
|
|
19
|
+
light?: Partial<ThemeColors>;
|
|
20
|
+
dark?: Partial<ThemeColors>;
|
|
21
|
+
};
|
|
3
22
|
export type ThemeStore = {
|
|
4
23
|
userTheme: ThemePreference;
|
|
5
24
|
systemTheme: ResolvedTheme;
|
|
25
|
+
/**
|
|
26
|
+
* App-injected palette overrides, applied by `useTheme` on top of the
|
|
27
|
+
* package defaults. Empty by default — zero override means the package
|
|
28
|
+
* behaves exactly as before this field existed (fully backward compatible).
|
|
29
|
+
*/
|
|
30
|
+
colorOverrides: ColorOverrides;
|
|
6
31
|
setTheme: (theme: ThemePreference) => void;
|
|
7
32
|
setSystemTheme: (theme: ResolvedTheme) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Replace the active color overrides. Pass `{}` (or omit both schemes) to
|
|
35
|
+
* clear overrides and fall back to the package defaults.
|
|
36
|
+
*/
|
|
37
|
+
setColors: (overrides: ColorOverrides) => void;
|
|
8
38
|
loadTheme: () => void;
|
|
9
39
|
};
|
|
10
40
|
export declare function resolveThemePreference(userTheme: ThemePreference, systemTheme: ResolvedTheme): ResolvedTheme;
|
package/dist/state/themeStore.js
CHANGED
|
@@ -16,6 +16,12 @@ export const useThemeStore = create((set) => ({
|
|
|
16
16
|
// Always start with "light" so SSR and the first client render agree.
|
|
17
17
|
// Real values are populated by `syncThemeFromEnvironment()` after mount.
|
|
18
18
|
systemTheme: "light",
|
|
19
|
+
// No overrides by default: the package renders with its built-in palette
|
|
20
|
+
// until a host app calls `setColors`.
|
|
21
|
+
colorOverrides: {},
|
|
22
|
+
setColors: (overrides) => {
|
|
23
|
+
set({ colorOverrides: overrides ?? {} });
|
|
24
|
+
},
|
|
19
25
|
setTheme: (theme) => {
|
|
20
26
|
set({
|
|
21
27
|
userTheme: theme,
|