@mrmeg/expo-ui 0.1.3 → 0.1.4
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 +13 -1
- package/README.md +27 -15
- package/dist/components/Button.js +2 -2
- package/dist/components/Notification.js +4 -5
- package/dist/components/StyledText.js +2 -3
- package/dist/lib/i18n.d.ts +3 -0
- package/dist/lib/i18n.js +11 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/package.json +1 -3
package/LLM_USAGE.md
CHANGED
|
@@ -16,7 +16,7 @@ import { Button as ButtonDirect } from "@mrmeg/expo-ui/components/Button";
|
|
|
16
16
|
import { colors, spacing, typography } from "@mrmeg/expo-ui/constants";
|
|
17
17
|
import { useResources, useTheme } from "@mrmeg/expo-ui/hooks";
|
|
18
18
|
import { globalUIStore, useThemeStore } from "@mrmeg/expo-ui/state";
|
|
19
|
-
import { hapticLight } from "@mrmeg/expo-ui/lib";
|
|
19
|
+
import { configureExpoUiI18n, hapticLight } from "@mrmeg/expo-ui/lib";
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
The root barrel also exports the public surface:
|
|
@@ -68,6 +68,18 @@ export function RootLayout() {
|
|
|
68
68
|
`AlertDialog`, `BottomSheet`, `Drawer`, `DropdownMenu`, `Popover`,
|
|
69
69
|
`SelectContent`, or `Tooltip`.
|
|
70
70
|
|
|
71
|
+
i18n is optional. Do not add app-level i18n setup just to use this package.
|
|
72
|
+
Plain children and `text` props work without `i18next` or `react-i18next`.
|
|
73
|
+
`tx` props render the key until the consumer opts in with a package-local
|
|
74
|
+
translator:
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { configureExpoUiI18n } from "@mrmeg/expo-ui/lib";
|
|
78
|
+
import { i18n } from "./i18n";
|
|
79
|
+
|
|
80
|
+
configureExpoUiI18n((key, options) => i18n.t(key, options));
|
|
81
|
+
```
|
|
82
|
+
|
|
71
83
|
## Theme And Text Rules
|
|
72
84
|
|
|
73
85
|
- Use `useTheme()` and semantic tokens instead of hardcoded colors.
|
package/README.md
CHANGED
|
@@ -28,11 +28,11 @@ Consumers must also install the peer dependencies listed in `package.json`.
|
|
|
28
28
|
The tested baseline is Expo SDK 55 with React 19.2, React Native 0.83,
|
|
29
29
|
React Native Web 0.21, Reanimated 4.2, Worklets 0.7, and
|
|
30
30
|
`@rn-primitives/*` 1.4. `@rn-primitives/portal` is package-managed because
|
|
31
|
-
`UIProvider` mounts the portal host used by package overlays.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
`UIProvider` mounts the portal host used by package overlays. i18n setup is
|
|
32
|
+
optional; plain text and children render without `i18next` or
|
|
33
|
+
`react-i18next`. Start consumer apps from the same Expo SDK family or update
|
|
34
|
+
the package and peer ranges deliberately. Keep npm auth tokens in developer or
|
|
35
|
+
CI configuration, not in this repository.
|
|
36
36
|
|
|
37
37
|
## Imports
|
|
38
38
|
|
|
@@ -44,7 +44,7 @@ import { colors as colorsDirect } from "@mrmeg/expo-ui/constants/colors";
|
|
|
44
44
|
import { useResources, useTheme } from "@mrmeg/expo-ui/hooks";
|
|
45
45
|
import { useTheme as useThemeDirect } from "@mrmeg/expo-ui/hooks/useTheme";
|
|
46
46
|
import { globalUIStore, useThemeStore } from "@mrmeg/expo-ui/state";
|
|
47
|
-
import { hapticLight } from "@mrmeg/expo-ui/lib";
|
|
47
|
+
import { configureExpoUiI18n, hapticLight } from "@mrmeg/expo-ui/lib";
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
The root barrel also exports the public surface:
|
|
@@ -116,6 +116,17 @@ Useful `StyledText` props:
|
|
|
116
116
|
- `variant`: `sansSerif`, `serif`
|
|
117
117
|
- `align`, `tx`, `txOptions`
|
|
118
118
|
|
|
119
|
+
`tx` support is opt-in. Without a configured translator, `tx` renders the key
|
|
120
|
+
and `text` renders as provided. Consumers that already use i18n can connect it
|
|
121
|
+
once near app startup:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { configureExpoUiI18n } from "@mrmeg/expo-ui/lib";
|
|
125
|
+
import { i18n } from "./i18n";
|
|
126
|
+
|
|
127
|
+
configureExpoUiI18n((key, options) => i18n.t(key, options));
|
|
128
|
+
```
|
|
129
|
+
|
|
119
130
|
## Component Guide
|
|
120
131
|
|
|
121
132
|
All components are exported from `@mrmeg/expo-ui/components`; direct imports such as `@mrmeg/expo-ui/components/Button` are supported. Use this table as the first stop before building a new primitive in a consumer app.
|
|
@@ -336,13 +347,14 @@ publishing instead:
|
|
|
336
347
|
1. In npm package settings for `@mrmeg/expo-ui`, add a trusted publisher:
|
|
337
348
|
GitHub Actions, owner `mrmeg`, repository `expo-template`, workflow
|
|
338
349
|
filename `publish-ui.yml`.
|
|
339
|
-
2.
|
|
340
|
-
and `ref=dev`.
|
|
350
|
+
2. Bump `packages/ui/package.json` in a commit and push it to `main`.
|
|
341
351
|
|
|
342
|
-
The workflow uses npm OIDC, not a checked-in token or local npm login.
|
|
343
|
-
the package version,
|
|
344
|
-
|
|
345
|
-
|
|
352
|
+
The workflow uses npm OIDC, not a checked-in token or local npm login. On push,
|
|
353
|
+
it reads the committed package version, skips cleanly if that version is already
|
|
354
|
+
published, otherwise runs the package gates and publishes from `packages/ui`.
|
|
355
|
+
The workflow can also be run manually with `version=patch` and `ref=main`; manual
|
|
356
|
+
runs bump the package version, update `bun.lock`, run the package gates, commit
|
|
357
|
+
the version bump, and publish.
|
|
346
358
|
|
|
347
359
|
Keep `repository.url` in `package.json` as
|
|
348
360
|
`git+https://github.com/mrmeg/expo-template.git`. npm trusted publishing checks
|
|
@@ -353,9 +365,9 @@ If npm trusted publishing is blocked by package settings, add an npm automation
|
|
|
353
365
|
or granular publish token to GitHub Actions secrets as `NPM_TOKEN` and rerun the
|
|
354
366
|
same workflow. The token is used only for the publish step.
|
|
355
367
|
|
|
356
|
-
If the workflow fails after the version is already bumped, rerun it with
|
|
357
|
-
exact current package version, for example `version=0.1.
|
|
358
|
-
do not bump again.
|
|
368
|
+
If the manual workflow fails after the version is already bumped, rerun it with
|
|
369
|
+
the exact current package version, for example `version=0.1.3`. Exact-version
|
|
370
|
+
reruns do not bump again.
|
|
359
371
|
|
|
360
372
|
Manual package checks:
|
|
361
373
|
|
|
@@ -147,13 +147,13 @@ export function Button(props) {
|
|
|
147
147
|
},
|
|
148
148
|
// Spread array styles from Slot to prevent nested arrays on web
|
|
149
149
|
...(Array.isArray(styleOverride) ? styleOverride : [styleOverride]),
|
|
150
|
-
], children: [!!LeftAccessory && !loading && (_jsx(LeftAccessory, { style: styles.leftAccessory, pressableState: state, disabled: isDisabled })), loading && (_jsx(ActivityIndicator, { size: "small", color: textColor, style: styles.loader })), (tx || text) ? (_jsx(StyledText, { style: [
|
|
150
|
+
], children: [!!LeftAccessory && !loading && (_jsx(LeftAccessory, { style: styles.leftAccessory, pressableState: state, disabled: isDisabled })), loading && (_jsx(ActivityIndicator, { size: "small", color: textColor, style: styles.loader })), (tx || text) ? (_jsx(StyledText, { tx: tx, text: text, txOptions: txOptions, style: [
|
|
151
151
|
styles.text,
|
|
152
152
|
state.pressed && styles.pressedText,
|
|
153
153
|
state.pressed && pressedTextStyleOverride,
|
|
154
154
|
isDisabled && disabledTextStyleOverride,
|
|
155
155
|
textStyleOverride,
|
|
156
|
-
]
|
|
156
|
+
] })) : !loading && children ? (
|
|
157
157
|
// Wrap string children in StyledText to apply TextColorContext
|
|
158
158
|
typeof children === "string" ? (_jsx(StyledText, { style: [
|
|
159
159
|
styles.text,
|
|
@@ -2,13 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useCallback, useContext, useEffect, useRef } from "react";
|
|
3
3
|
import { StyleSheet, View, ActivityIndicator, Pressable, Platform } from "react-native";
|
|
4
4
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, runOnJS, useReducedMotion, Easing, } from "react-native-reanimated";
|
|
5
|
-
import { useTranslation } from "react-i18next";
|
|
6
5
|
import { SafeAreaInsetsContext } from "react-native-safe-area-context";
|
|
7
6
|
import { fontFamilies } from "../constants/fonts.js";
|
|
8
7
|
import { Icon } from "./Icon.js";
|
|
9
8
|
import { useTheme } from "../hooks/useTheme.js";
|
|
10
9
|
import { spacing } from "../constants/spacing.js";
|
|
11
10
|
import { StyledText } from "./StyledText.js";
|
|
11
|
+
import { translateText } from "../lib/i18n.js";
|
|
12
12
|
import { globalUIStore } from "../state/globalUIStore.js";
|
|
13
13
|
/**
|
|
14
14
|
* Notification
|
|
@@ -36,7 +36,6 @@ import { globalUIStore } from "../state/globalUIStore.js";
|
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
38
|
export const Notification = () => {
|
|
39
|
-
const { t } = useTranslation();
|
|
40
39
|
const { theme, getShadowStyle } = useTheme();
|
|
41
40
|
const reduceMotion = useReducedMotion();
|
|
42
41
|
const insets = useContext(SafeAreaInsetsContext);
|
|
@@ -140,11 +139,11 @@ export const Notification = () => {
|
|
|
140
139
|
return alert.title;
|
|
141
140
|
switch (alert?.type) {
|
|
142
141
|
case "error":
|
|
143
|
-
return
|
|
142
|
+
return translateText("notification.error");
|
|
144
143
|
case "success":
|
|
145
|
-
return
|
|
144
|
+
return translateText("notification.success");
|
|
146
145
|
case "warning":
|
|
147
|
-
return
|
|
146
|
+
return translateText("notification.warning");
|
|
148
147
|
case "info":
|
|
149
148
|
return "";
|
|
150
149
|
default:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React, { forwardRef } from "react";
|
|
3
3
|
import { Text as RNText, StyleSheet } from "react-native";
|
|
4
|
-
import { useTranslation } from "react-i18next";
|
|
5
4
|
import { useTheme } from "../hooks/useTheme.js";
|
|
6
5
|
import { fontFamilies } from "../constants/fonts.js";
|
|
6
|
+
import { translateText } from "../lib/i18n.js";
|
|
7
7
|
/**
|
|
8
8
|
* TextClassContext provides className context for nested text components
|
|
9
9
|
* Used by @rn-primitives to apply consistent styling through the component tree
|
|
@@ -75,7 +75,6 @@ const getFontFamilyWeight = (weight) => {
|
|
|
75
75
|
export const StyledText = forwardRef((props, ref) => {
|
|
76
76
|
const { tx, text, txOptions, style, variant = "sansSerif", fontWeight, size, semantic, align, children, ...otherProps } = props;
|
|
77
77
|
const { theme } = useTheme();
|
|
78
|
-
const { t } = useTranslation();
|
|
79
78
|
// Check if there's a color override from parent context (e.g., Button)
|
|
80
79
|
const contextColor = React.useContext(TextColorContext);
|
|
81
80
|
// Use context color if provided, otherwise use theme default
|
|
@@ -100,7 +99,7 @@ export const StyledText = forwardRef((props, ref) => {
|
|
|
100
99
|
const styleHasFontSize = flatStyle && "fontSize" in flatStyle;
|
|
101
100
|
const styleHasLineHeight = flatStyle && "lineHeight" in flatStyle;
|
|
102
101
|
const resolvedLineHeight = styleHasFontSize && !styleHasLineHeight ? undefined : lineHeight;
|
|
103
|
-
const i18nText =
|
|
102
|
+
const i18nText = translateText(tx, text, txOptions);
|
|
104
103
|
const content = i18nText || children;
|
|
105
104
|
return (_jsx(RNText, { ref: ref, style: [
|
|
106
105
|
{
|
package/dist/lib/i18n.js
ADDED
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrmeg/expo-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Reusable Expo and React Native UI primitives for MrMeg projects.",
|
|
6
6
|
"keywords": [
|
|
@@ -105,9 +105,7 @@
|
|
|
105
105
|
"expo": "~55.0.0",
|
|
106
106
|
"expo-font": "~55.0.0",
|
|
107
107
|
"expo-haptics": "~55.0.0",
|
|
108
|
-
"i18next": ">=25.0.0 <27.0.0",
|
|
109
108
|
"react": ">=19.2.0 <20.0.0",
|
|
110
|
-
"react-i18next": ">=15.0.0 <18.0.0",
|
|
111
109
|
"react-native": ">=0.83.0 <0.84.0",
|
|
112
110
|
"react-native-gesture-handler": "~2.30.0",
|
|
113
111
|
"react-native-reanimated": "~4.2.0",
|