@mrmeg/expo-ui 0.22.0 → 0.24.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/llms-full.md CHANGED
@@ -1,154 +1,172 @@
1
1
  # @mrmeg/expo-ui Full Contract
2
2
 
3
- `@mrmeg/expo-ui` packages reusable Expo and React Native UI primitives for
4
- MrMeg apps. It owns the shared design system, tokens, package theme store,
5
- resource hook, global notification store, overlay shell, and small interaction
6
- helpers. The consuming app owns routes, screens, feature state, auth, billing,
7
- media, monitoring, API calls, product copy, and app-specific layouts.
3
+ The package owns the shared design system, tokens, theme store, resource hook,
4
+ global notification store, overlay shell, and small interaction helpers. The
5
+ consuming app owns routes, screens, feature state, auth, billing, media,
6
+ monitoring, API calls, product copy, and app-specific layouts.
8
7
 
9
8
  ## Agent Rules
10
9
 
11
- Do not recreate primitives that this package already provides. Import from
10
+ Do not recreate primitives this package already provides. Import from
12
11
  `@mrmeg/expo-ui` and compose package components in the app.
13
12
 
14
- Use only exported package paths:
13
+ Importable paths, and nothing else:
15
14
 
16
15
  - `@mrmeg/expo-ui`
17
- - `@mrmeg/expo-ui/components`
18
- - `@mrmeg/expo-ui/components/*`
19
- - `@mrmeg/expo-ui/constants`
20
- - `@mrmeg/expo-ui/constants/*`
21
- - `@mrmeg/expo-ui/hooks`
22
- - `@mrmeg/expo-ui/hooks/*`
23
- - `@mrmeg/expo-ui/state`
16
+ - `@mrmeg/expo-ui/components`, `@mrmeg/expo-ui/components/*`
17
+ - `@mrmeg/expo-ui/constants`, `@mrmeg/expo-ui/constants/*`
18
+ - `@mrmeg/expo-ui/hooks`, `@mrmeg/expo-ui/hooks/*`
19
+ - `@mrmeg/expo-ui/state`, `@mrmeg/expo-ui/state/*`
24
20
  - `@mrmeg/expo-ui/lib`
25
21
 
26
- Do not import from `@mrmeg/expo-ui/dist/*`, `packages/ui/src/*`, or copied
22
+ Never import from `@mrmeg/expo-ui/dist/*`, `packages/ui/src/*`, or copied
27
23
  app-local component files.
28
24
 
25
+ ```tsx
26
+ import { Button, StyledText, UIProvider } from "@mrmeg/expo-ui/components";
27
+ import { Button as ButtonDirect } from "@mrmeg/expo-ui/components/Button";
28
+ import { colors, spacing, typography } from "@mrmeg/expo-ui/constants";
29
+ import { useResources, useStyles, useTheme } from "@mrmeg/expo-ui/hooks";
30
+ import { globalUIStore, notify, ThemeColorScope, useThemeStore } from "@mrmeg/expo-ui/state";
31
+ import { configureExpoUiI18n, hapticLight } from "@mrmeg/expo-ui/lib";
32
+ // The root barrel re-exports the whole public surface:
33
+ import { Button, colors, UIProvider, useTheme } from "@mrmeg/expo-ui";
34
+ ```
35
+
29
36
  ## App Setup
30
37
 
31
- Call `useResources()` once near the Expo app root. Mount `UIProvider` once near
32
- the root when the app uses package feedback or overlay components.
38
+ Call `useResources()` once near the Expo app root; it resolves `{ loaded, error }`
39
+ and loads the Feather icon font plus the four static Inter weights (web gets a
40
+ single Google Fonts Inter stylesheet).
33
41
 
34
- `UIProvider` owns the package `Notification`, `StatusBar`, default
35
- `@rn-primitives` portal host, and native keyboard-avoiding root. Mount it
36
- before using `Dialog`, `AlertDialog`, `BottomSheet`, `Drawer`, `DropdownMenu`,
37
- `Popover`, `SelectContent`, `Tooltip`, or `notify` / `globalUIStore`
38
- notifications. Pass `keyboardAvoiding={false}` to opt out of the native root
39
- keyboard avoidance, or use `KeyboardAvoidingView` directly for a subtree with
40
- custom behavior. Web skips the root keyboard wrapper unless `keyboardAvoiding`
41
- is explicitly enabled.
42
+ Mount `UIProvider` once near the root. It owns the package `Notification`,
43
+ `StatusBar`, default `@rn-primitives` portal host, and native keyboard-avoiding
44
+ root, and is required before `Dialog`, `AlertDialog`, `BottomSheet`, `Drawer`,
45
+ `DropdownMenu`, `Popover`, `SelectContent`, `Tooltip`, or `notify` /
46
+ `globalUIStore` notifications.
42
47
 
43
- On native, `BottomSheet.Content` composes its sheet transform with React Native
44
- keyboard event values. Pass `avoidKeyboard={false}` for sheets that should not
45
- move.
48
+ `UIProvider` props: `notification`, `portalHost`, `statusBar` (default `true`),
49
+ `keyboardAvoiding` (default `true` on native, `false` on web), and
50
+ `keyboardAvoidingProps` forwarded to the root wrapper. Native keyboard avoidance
51
+ uses `react-native-keyboard-controller`, so mount its `KeyboardProvider` above
52
+ `UIProvider`; use `KeyboardAvoidingView` directly for a subtree needing custom
53
+ behavior.
46
54
 
47
55
  i18n is optional. Plain children and `text` props work without `i18next` or
48
- `react-i18next`. Use `configureExpoUiI18n()` only when a consuming app wants
49
- package `tx` props translated by its app-owned i18n instance.
56
+ `react-i18next`. Use `configureExpoUiI18n()` only when the app wants package
57
+ `tx` props translated by its own i18n instance.
50
58
 
51
59
  ## Theme Rules
52
60
 
53
- Use `useTheme()` and `useStyles()` from `@mrmeg/expo-ui/hooks`. Use semantic
54
- tokens such as `surfaceSunken`, `background`, `foreground`, `card`, `popover`,
55
- `border`, `borderStrong`, `input`, `ring`, `primary`, `secondary`, `accent`,
56
- `mutedForeground`, `destructive`, `success`, and `warning`.
61
+ Use `useTheme()` and `useStyles()` from `@mrmeg/expo-ui/hooks`. Semantic tokens
62
+ on `theme.colors`: `surfaceSunken`, `background`, `foreground`, `card`,
63
+ `cardForeground`, `popover`, `popoverForeground`, `text`, `textDim`, `muted`,
64
+ `mutedForeground`, `border`, `borderStrong`, `input`, `ring`, `overlay`,
65
+ `primary`, `secondary`, `accent`, their `*Foreground` pairs, `destructive`,
66
+ `success`, `warning`.
57
67
 
58
68
  Surfaces form a tier ladder rather than a shadow scale: `surfaceSunken` (app
59
69
  chrome such as the Drawer rail) < `background` (content) < `card`/`popover`
60
- (raised) < `muted` (chips, insets). Use `borderStrong` for hairlines on filled
61
- or raised elements, where `border` would blend into the fill.
62
-
63
- Use `StyledText` and semantic text aliases instead of raw `Text` for app UI.
64
- Use package controls instead of hardcoded Pressable/View/Text combinations.
65
-
66
- When the saved theme preference is `system`, the package theme store owns OS
67
- color-scheme sync, including web `prefers-color-scheme`. Apps should not add
68
- their own `Appearance` or `matchMedia` listeners just to make package
69
- components follow system light/dark changes.
70
+ (raised) < `muted` (chips, insets). Use `borderStrong` for hairlines on filled or
71
+ raised elements, where `border` would blend into the fill.
70
72
 
71
- ## Import Examples
73
+ On web every theme color resolves to a CSS custom property (`var(--c-*)`) so the
74
+ app re-themes in CSS when `html[data-theme]` changes; native keeps literals.
75
+ Consequence: hex-suffix alpha (`theme.colors.x + "15"`) does not work — use
76
+ `withAlpha(color, alpha)`. `constants` also exports `rawThemeColors.light/.dark`
77
+ and `resolveRawColor(color, scheme)` for sinks that cannot take `var()`, and
78
+ `getThemeCssVariables(overrides?)` for an app's `+html.tsx`.
72
79
 
73
- ```tsx
74
- import { Button, StyledText, UIProvider } from "@mrmeg/expo-ui/components";
75
- import { Button as ButtonDirect } from "@mrmeg/expo-ui/components/Button";
76
- import { colors, spacing, typography } from "@mrmeg/expo-ui/constants";
77
- import { useResources, useTheme } from "@mrmeg/expo-ui/hooks";
78
- import { globalUIStore, notify, useThemeStore } from "@mrmeg/expo-ui/state";
79
- import { configureExpoUiI18n, hapticLight } from "@mrmeg/expo-ui/lib";
80
- ```
80
+ Color overrides resolve in three layers, last wins: package defaults → global
81
+ brand (`useThemeStore.getState().setColors({ light?, dark? })`) → subtree scope
82
+ (`<ThemeColorScope colors={{ light, dark }}>`). Each is a `Partial<ThemeColors>`.
83
+ `setFonts` and `setShape({ button: { borderRadius?, withShadow? } })` are the
84
+ font and geometry counterparts; per-instance props always win.
81
85
 
82
- The root barrel also exports the public surface:
86
+ Use `StyledText` and semantic text aliases instead of raw `Text`, and package
87
+ controls instead of hardcoded Pressable/View/Text combinations.
83
88
 
84
- ```tsx
85
- import { Button, UIProvider, colors, useTheme } from "@mrmeg/expo-ui";
86
- ```
89
+ When the saved theme preference is `system`, the package theme store owns OS
90
+ color-scheme sync, including web `prefers-color-scheme`. Apps must not add their
91
+ own `Appearance` or `matchMedia` listeners for package components.
87
92
 
88
93
  ## Component Catalog
89
94
 
90
- Use this catalog before creating a new app-local primitive.
91
-
92
- | Component | Import | Use When | Gotchas |
93
- |-----------|--------|----------|---------|
94
- | `Accordion` | `@mrmeg/expo-ui/components` | Multi-section disclosure such as FAQ or grouped settings | Use compound parts instead of custom expanders. |
95
- | `Alert` | `@mrmeg/expo-ui/components` | Cross-platform imperative alerts | Avoid direct `window.alert` and duplicated native/web branching. |
96
- | `AnimatedView` | `@mrmeg/expo-ui/components` | Entrance and visibility animation | Keep simple reveal effects in the package wrapper. |
97
- | `Badge` | `@mrmeg/expo-ui/components` | Short status labels | Prefer over custom pill views. |
98
- | `BottomSheet` | `@mrmeg/expo-ui/components` | Mobile-first modal sheets | Requires root `UIProvider`; text-input sheets can disable `avoidKeyboard`. |
99
- | `Button` | `@mrmeg/expo-ui/components` | Commands and CTAs | Use `preset`, not `variant`; visible heights are compact. |
100
- | `Card` | `@mrmeg/expo-ui/components` | Individual framed content groups | Do not wrap whole page sections in cards. |
101
- | `Checkbox` | `@mrmeg/expo-ui/components` | Boolean selection in forms or lists | Prefer over custom checkmark controls. |
102
- | `Collapsible` | `@mrmeg/expo-ui/components` | One-off disclosure | Use for advanced settings or helper sections. |
103
- | `Dialog`, `AlertDialog` | `@mrmeg/expo-ui/components` | Blocking modal content or decisions | Requires root `UIProvider` portal setup. |
104
- | `DismissKeyboard` | `@mrmeg/expo-ui/components` | Tap-away keyboard dismissal | Prefer over screen-level keyboard wrappers. |
105
- | `Drawer` | `@mrmeg/expo-ui/components` | Side panels and drawer navigation | `Drawer.Content` owns safe-area top/bottom padding; do not duplicate it in children. |
106
- | `DropdownMenu` | `@mrmeg/expo-ui/components` | Menus and command lists | Requires root `UIProvider` portal setup. |
107
- | `EmptyState` | `@mrmeg/expo-ui/components` | No-data or recoverable error regions | Prefer over one-off empty placeholders. |
108
- | `ErrorBoundary` | `@mrmeg/expo-ui/components` | React render error fallback | Use for route or feature boundaries. |
109
- | `Icon` | `@mrmeg/expo-ui/components` | Feather or custom icons with theme tokens | Avoid raw vector icons with hardcoded colors. |
110
- | `InputOTP` | `@mrmeg/expo-ui/components` | Verification code entry | Prefer over manually managed text input groups. |
111
- | `KeyboardAvoidingView` | `@mrmeg/expo-ui/components` | Native keyboard-aware layout roots, composer footers, and form-heavy subtrees | `UIProvider` already mounts one root by default; use this directly only for custom subtrees. |
112
- | `Label` | `@mrmeg/expo-ui/components` | Accessible form labels | Pair with two distinct ids: `nativeID` is the label's id, `htmlFor` is the input's `nativeID`. Never reuse one id for both. |
113
- | `MaxWidthContainer` | `@mrmeg/expo-ui/components` | Centered responsive width | Use for web and tablet constrained layouts. |
114
- | `Notification` | `@mrmeg/expo-ui/components` | Global toast surface | Trigger through `notify` (or `globalUIStore` for subscriptions/tests) with root `UIProvider`; optional actions dismiss after press. |
115
- | `Popover` | `@mrmeg/expo-ui/components` | Anchored contextual content | Requires root `UIProvider` portal setup. |
116
- | `Progress` | `@mrmeg/expo-ui/components` | Determinate or indeterminate progress | Prefer over layout-shifting spinners for progress regions. |
117
- | `RadioGroup` | `@mrmeg/expo-ui/components` | Small mutually exclusive choices | Use `Select` for longer option sets. |
118
- | `Select` | `@mrmeg/expo-ui/components` | Option menus | `SelectContent` requires root `UIProvider` portal setup. |
119
- | `Separator` | `@mrmeg/expo-ui/components` | Horizontal or vertical dividers | Prefer over border-only spacer views. |
120
- | `Skeleton` | `@mrmeg/expo-ui/components` | Loading placeholders | Use stable dimensions to avoid layout shift. |
121
- | `Slider` | `@mrmeg/expo-ui/components` | Numeric value selection | Prefer over custom pan gesture tracks. |
122
- | `StatusBar` | `@mrmeg/expo-ui/components` | Theme-aware native status bar | Usually mounted through `UIProvider`. |
123
- | `StyledText` | `@mrmeg/expo-ui/components` | Theme-aware typography | Prefer semantic aliases over raw `Text`. |
124
- | `Switch` | `@mrmeg/expo-ui/components` | Binary settings | Prefer over custom toggles for on/off state. |
125
- | `Tabs` | `@mrmeg/expo-ui/components` | In-page tabbed views | Use for profile sections, report views, and settings categories. |
126
- | `TextInput` | `@mrmeg/expo-ui/components` | Text entry | Use built-in label and error text support. |
127
- | `Toggle` | `@mrmeg/expo-ui/components` | One pressed/unpressed control | Use `Button` for commands and `Switch` for settings. |
128
- | `ToggleGroup` | `@mrmeg/expo-ui/components` | Related pressed states | Use for segmented controls, formatting, and filter chips. |
129
- | `Tooltip` | `@mrmeg/expo-ui/components` | Short hover/focus help | Requires root `UIProvider` portal setup. |
95
+ Every component is exported from `@mrmeg/expo-ui/components`, and from
96
+ `@mrmeg/expo-ui/components/<Name>` for a direct import. Check this catalog
97
+ before creating a new app-local primitive.
98
+
99
+ | Component | Use When | Gotchas |
100
+ |-----------|----------|---------|
101
+ | `Accordion` | Multi-section disclosure such as FAQ or grouped settings | Use the compound parts instead of custom expanders. |
102
+ | `Alert` | Cross-platform imperative alerts | Avoid `window.alert` and duplicated native/web branching. |
103
+ | `AnimatedView` | Entrance and visibility animation | Keep simple reveal effects in this wrapper. |
104
+ | `Avatar`, `AvatarGroup` | Profile images with initials/icon fallback | Pass both `source` and `name`; set `size`/`shape` on the group, not per child. |
105
+ | `Badge` | Short status labels | Prefer over custom pill views. |
106
+ | `BottomSheet` | Mobile-first modal sheets | Requires root `UIProvider`. Native sheet via `@expo/ui`; `swipeEnabled`, `avoidKeyboard`, `dismissKeyboardOnDrag` are accepted but ignored. |
107
+ | `Button` | Commands and CTAs | Use `preset`, not `variant`; heights are 28/32/40. |
108
+ | `Card` | Individual framed content groups | Do not wrap whole page sections in cards. |
109
+ | `Carousel` | Small known set of horizontally snapping slides | Renders every child (no virtualization); fractional `itemWidth` measures the viewport until first layout. |
110
+ | `Checkbox` | Boolean selection in forms or lists | Prefer over custom checkmark controls. |
111
+ | `Collapsible` | One-off disclosure | Use for advanced settings or helper sections. |
112
+ | `Dialog`, `AlertDialog` | Blocking modal content or decisions | Requires root `UIProvider` portal host. |
113
+ | `DismissKeyboard` | Tap-away keyboard dismissal | Prefer over screen-level keyboard wrappers. |
114
+ | `Drawer` | Side panels and drawer navigation | `Drawer.Content` owns safe-area top/bottom padding; do not duplicate it in children. |
115
+ | `DropdownMenu` | Menus and command lists | Requires root `UIProvider` portal host. |
116
+ | `EmptyState` | No-data or recoverable error regions | Props: `icon`, `title`, `description`, `actionLabel`, `onAction`, `actionPreset`. |
117
+ | `ErrorBoundary` | React render error fallback | Use for route or feature boundaries. |
118
+ | `Icon` | Feather or custom icons with theme tokens | `color` takes a theme color name; pass `decorative` to hide from a11y. |
119
+ | `InputOTP` | Verification code entry | Prefer over manually managed text input groups. |
120
+ | `Item` | List / settings rows | Applies the row density tokens and a 44px native hit area (40px on web). |
121
+ | `KeyboardAvoidingView` | Native keyboard-aware roots, composer footers, form-heavy subtrees | `UIProvider` already mounts one root; use directly only for custom subtrees. |
122
+ | `Label` | Accessible form labels | Two distinct ids: `nativeID` is the label's, `htmlFor` is the input's `nativeID`. Never reuse one id for both. |
123
+ | `MaxWidthContainer` | Centered responsive width | Use for web and tablet constrained layouts. |
124
+ | `Notification` | Global toast surface | Trigger through `notify` (or `globalUIStore` for subscriptions/tests) with root `UIProvider`; actions dismiss after press. |
125
+ | `Popover` | Anchored contextual content | Requires root `UIProvider` portal host. |
126
+ | `Progress` | Determinate or indeterminate progress | Omit `value` for indeterminate. Prefer over layout-shifting spinners. |
127
+ | `RadioGroup` | Small mutually exclusive choices | Use `Select` for longer option sets. |
128
+ | `SectionHeader` | Eyebrow / title / description section intro | Prefer over stacked ad hoc heading text. |
129
+ | `SegmentedControl` | Native segmented picker | Backed by `@expo/ui`; the platform owns its look. |
130
+ | `Select` | Option menus | `SelectContent` requires root `UIProvider` portal host; `label` drives default item text. |
131
+ | `Separator` | Horizontal or vertical dividers | Prefer over border-only spacer views. |
132
+ | `Skeleton` | Loading placeholders | Use stable dimensions to avoid layout shift. |
133
+ | `Slider` | Numeric value selection | Backed by `@expo/ui`; prefer over custom pan gesture tracks. |
134
+ | `StatCard` | Metric tile | Props: `label`, `value`, `unit`, `change` (`{ value, direction }`), `icon`, `onPress`. |
135
+ | `StatusBar` | Theme-aware native status bar | Usually mounted through `UIProvider`. |
136
+ | `StyledText` | Theme-aware typography | Prefer semantic aliases over raw `Text`. |
137
+ | `Switch` | Binary settings | Prefer over custom toggles for on/off state. |
138
+ | `Tabs` | In-page tabbed views | Sizes are `sm`/`md` only. |
139
+ | `TextInput` | Text entry | Owns label, helper/error text, clear button, password reveal, numeric filtering, left/right elements. |
140
+ | `Toggle` | One pressed/unpressed control | Sizes are `sm`/`default`/`lg`. Use `Button` for commands, `Switch` for settings. |
141
+ | `ToggleGroup` | Related pressed states | Use for segmented controls, formatting, and filter chips. |
142
+ | `Tooltip` | Short hover/focus help | Requires root `UIProvider` portal host. |
143
+
144
+ Every compound part has a named export (`CardHeader`, `AccordionItem`,
145
+ `SelectContent`, …). Dot notation exists only on `AlertDialog`, `BottomSheet`,
146
+ `Button`, `Dialog`, `Drawer`, `Popover`, `RadioGroup`, `Select`, `Tabs`, and
147
+ `Tooltip` — `Card`, `Accordion`, `Collapsible`, `DropdownMenu`, `Item`,
148
+ `Skeleton`, `Toggle`, and `ToggleGroup` are named exports only.
130
149
 
131
150
  ## Selection Rules
132
151
 
133
- Use `Button` for commands, `Toggle` for one pressed state, `ToggleGroup` for
134
- related pressed states, and `Switch` for binary settings.
135
-
136
- Use `RadioGroup` for small mutually exclusive choices and `Select` for longer
152
+ `Button` commands · `Toggle` one pressed state · `ToggleGroup` a related set ·
153
+ `Switch` binary settings · `RadioGroup` few exclusive choices · `Select` longer
137
154
  option sets.
138
155
 
139
- Use `Dialog` for blocking decisions, `Popover` for contextual controls,
140
- `Tooltip` for short explanations, and `DropdownMenu` for action lists.
156
+ `Dialog` blocking decisions · `Popover` contextual controls · `Tooltip` short
157
+ explanations · `DropdownMenu` action lists.
141
158
 
142
- Use `Card` for individual repeated or framed items, not as a wrapper around
143
- full page sections. Use `EmptyState` for no-data or recoverable error regions,
144
- `Skeleton` for loading content with stable layout, and `Progress` for real
145
- progress or indeterminate long-running work.
159
+ `Card` individual repeated or framed items, never a wrapper around full page
160
+ sections · `EmptyState` no-data or recoverable errors · `Skeleton` loading
161
+ content with stable layout · `Progress` real or indeterminate progress.
146
162
 
147
163
  ## Notifications
148
164
 
149
- `notify` is the primary imperative API for triggering the `Notification` component. Import from `@mrmeg/expo-ui/state` (also re-exported from the package root).
150
-
151
- Notifications auto-dismiss after 4s (`DEFAULT_NOTIFICATION_DURATION`) unless a `duration` is given; pass `duration: 0` to keep one up until dismissed. `notify.loading` never auto-dismisses.
165
+ `notify` (from `@mrmeg/expo-ui/state`, also on the root barrel) is the imperative
166
+ API for the `Notification` component. Notifications auto-dismiss after 4s
167
+ (`DEFAULT_NOTIFICATION_DURATION`) unless a `duration` is given; `duration: 0`
168
+ keeps one up until dismissed, and `notify.loading` never auto-dismisses.
169
+ `position` is `"top"` (default) or `"bottom"`.
152
170
 
153
171
  ```ts
154
172
  import { notify } from "@mrmeg/expo-ui/state";
@@ -158,7 +176,6 @@ notify.error("Upload failed");
158
176
  notify.warning("Connection slow");
159
177
  notify.info("Copied to clipboard");
160
178
 
161
- // Loading spinner — persists until replaced or hidden (no auto-dismiss)
162
179
  notify.loading("Uploading…");
163
180
  notify.hide();
164
181
 
@@ -173,19 +190,12 @@ await notify.promise(saveProfile(), {
173
190
  });
174
191
  ```
175
192
 
176
- `globalUIStore` (the underlying zustand store) remains available for reactive selectors and tests. Use `notify` for all imperative triggers in app code.
193
+ `globalUIStore` (the underlying zustand store) stays available for reactive
194
+ selectors and tests. Use `notify` for imperative triggers in app code.
177
195
 
178
196
  ## Validation
179
197
 
180
- Run the UI package gates when changing package code or shipped docs:
181
-
182
- ```sh
183
- bun run ui:typecheck
184
- bun run ui:test
185
- bun run ui:build
186
- bun run ui:pack
187
- bun run ui:consumer-smoke
188
- ```
189
-
190
- For documentation-only package surface changes, `bun run ui:pack` is the
191
- minimum check that proves the new docs are included in the npm tarball.
198
+ Changing package code or shipped docs? Run the gates from the monorepo root:
199
+ `ui:typecheck`, `ui:test`, `ui:build`, `ui:pack`, `ui:consumer-smoke`
200
+ (`bun run <gate>`). Docs-only changes need at least `ui:pack`, which proves the
201
+ new docs land in the npm tarball.
package/llms.txt CHANGED
@@ -1,36 +1,38 @@
1
1
  # @mrmeg/expo-ui
2
2
 
3
- Docs for agents:
3
+ Docs, in `node_modules/@mrmeg/expo-ui/`:
4
4
 
5
- - README.md: install, setup, imports, theme usage, components, publishing.
6
- - LLM_USAGE.md: concise component-selection and implementation rules.
7
- - llms-full.md: expanded package contract and component catalog.
5
+ - README.md — install, setup, theme, component guide, release.
6
+ - LLM_USAGE.md — concise component-selection and implementation rules.
7
+ - llms-full.md — expanded contract, component catalog, notifications.
8
8
 
9
- Public entrypoints:
9
+ Public entrypoints (nothing else is importable):
10
10
 
11
11
  - @mrmeg/expo-ui
12
- - @mrmeg/expo-ui/components
13
- - @mrmeg/expo-ui/components/*
14
- - @mrmeg/expo-ui/constants
15
- - @mrmeg/expo-ui/constants/*
16
- - @mrmeg/expo-ui/hooks
17
- - @mrmeg/expo-ui/hooks/*
18
- - @mrmeg/expo-ui/state
12
+ - @mrmeg/expo-ui/components, /components/*
13
+ - @mrmeg/expo-ui/constants, /constants/*
14
+ - @mrmeg/expo-ui/hooks, /hooks/*
15
+ - @mrmeg/expo-ui/state, /state/*
19
16
  - @mrmeg/expo-ui/lib
20
17
 
21
- Do not recreate primitives this package already provides. Import reusable UI
22
- from the package and compose it in the app.
18
+ Never import from /dist/*, a source checkout, or an app-local copy.
19
+
20
+ Do not recreate primitives this package provides; compose the exports.
23
21
 
24
22
  Call useResources() once near the Expo app root. Mount UIProvider once near the
25
- root before using package notifications or overlay primitives: Dialog,
26
- AlertDialog, BottomSheet, Drawer, DropdownMenu, Popover, SelectContent, or
27
- Tooltip.
28
- BottomSheet.Content uses React Native keyboard events for text inputs;
29
- avoidKeyboard defaults to true.
23
+ root: it owns Notification, StatusBar, the @rn-primitives portal host, and the
24
+ native keyboard-avoiding root. Required before Dialog, AlertDialog, BottomSheet,
25
+ Drawer, DropdownMenu, Popover, SelectContent, Tooltip, and notify. On native,
26
+ mount react-native-keyboard-controller's KeyboardProvider above UIProvider.
27
+
28
+ BottomSheet renders the platform's native sheet via @expo/ui, which owns
29
+ gestures and keyboard avoidance; swipeEnabled, avoidKeyboard, and
30
+ dismissKeyboardOnDrag are accepted but ignored.
30
31
 
31
32
  Use useTheme(), useStyles(), semantic tokens, StyledText, and package controls.
32
- Do not add app-local Appearance or matchMedia listeners for package theme sync.
33
- Do not import from dist, source checkout paths, or app-local copies.
33
+ Do not add app-local Appearance or matchMedia listeners for theme sync. On web
34
+ theme colors are CSS variables: use withAlpha(color, alpha), never hex-suffix
35
+ concatenation.
34
36
 
35
37
  i18n is optional. Plain children and text props work without app i18n. Use
36
- configureExpoUiI18n() only when the app wants package tx props translated.
38
+ configureExpoUiI18n() only to translate package tx props.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrmeg/expo-ui",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "private": false,
5
5
  "description": "Reusable Expo and React Native UI primitives for MrMeg projects.",
6
6
  "keywords": [
@@ -83,7 +83,7 @@
83
83
  "scripts": {
84
84
  "typecheck": "tsc --noEmit -p tsconfig.json",
85
85
  "test": "jest --config ../../jest.config.js packages/ui/src --runInBand --watchman=false && bun run check:forbidden-imports",
86
- "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/fix-ui-package-esm.mjs && bun run check:forbidden-imports",
86
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/fix-package-esm.mjs ui && bun run check:forbidden-imports",
87
87
  "check:forbidden-imports": "node ../../scripts/check-ui-forbidden-imports.mjs",
88
88
  "publish:dry-run": "bun pm pack --dry-run"
89
89
  },
@@ -98,7 +98,7 @@
98
98
  "@rn-primitives/dropdown-menu": "~1.5.2",
99
99
  "@rn-primitives/label": "~1.5.2",
100
100
  "@rn-primitives/popover": "~1.5.2",
101
- "@rn-primitives/portal": "~1.5.2",
101
+ "@rn-primitives/portal": "~1.5.3",
102
102
  "@rn-primitives/radio-group": "~1.5.2",
103
103
  "@rn-primitives/select": "~1.5.2",
104
104
  "@rn-primitives/separator": "~1.5.2",