@mrmeg/expo-ui 0.27.1 → 0.28.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/CHANGELOG.md +598 -0
- package/LLM_USAGE.md +233 -35
- package/README.md +504 -103
- package/dist/components/Accordion.js +12 -6
- package/dist/components/AnimatedView.d.ts +1 -1
- package/dist/components/AnimatedView.js +5 -2
- package/dist/components/Avatar.d.ts +1 -1
- package/dist/components/Avatar.js +2 -2
- package/dist/components/Badge.js +5 -1
- package/dist/components/BottomSheet.d.ts +29 -1
- package/dist/components/BottomSheet.js +107 -30
- package/dist/components/Button.d.ts +20 -4
- package/dist/components/Button.js +60 -43
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/Card.js +24 -4
- package/dist/components/Carousel.js +2 -2
- package/dist/components/Checkbox.js +51 -44
- package/dist/components/Collapsible.js +7 -3
- package/dist/components/Dialog.js +87 -16
- package/dist/components/Drawer.d.ts +1 -1
- package/dist/components/Drawer.js +65 -55
- package/dist/components/DropdownMenu.js +11 -7
- package/dist/components/EmptyState.d.ts +2 -2
- package/dist/components/EmptyState.js +5 -2
- package/dist/components/Hydrated.d.ts +31 -0
- package/dist/components/Hydrated.js +30 -0
- package/dist/components/Icon.d.ts +17 -5
- package/dist/components/Icon.js +31 -10
- package/dist/components/InputOTP.js +5 -2
- package/dist/components/Item.d.ts +103 -4
- package/dist/components/Item.js +168 -15
- package/dist/components/KeyboardAvoidingView.d.ts +1 -1
- package/dist/components/KeyboardAvoidingView.js +4 -1
- package/dist/components/Label.js +3 -2
- package/dist/components/MaxWidthContainer.js +1 -1
- package/dist/components/Notification.js +45 -27
- package/dist/components/Popover.d.ts +18 -5
- package/dist/components/Popover.js +72 -8
- package/dist/components/Progress.js +8 -6
- package/dist/components/RadioGroup.js +52 -49
- package/dist/components/Screen.d.ts +61 -0
- package/dist/components/Screen.js +62 -0
- package/dist/components/SectionHeader.d.ts +1 -1
- package/dist/components/SegmentedControl.d.ts +12 -4
- package/dist/components/SegmentedControl.js +94 -4
- package/dist/components/Select.js +21 -26
- package/dist/components/Skeleton.js +24 -10
- package/dist/components/Slider.d.ts +11 -3
- package/dist/components/Slider.js +73 -6
- package/dist/components/StatCard.d.ts +4 -2
- package/dist/components/StatCard.js +3 -1
- package/dist/components/StyledText.d.ts +7 -1
- package/dist/components/StyledText.js +5 -3
- package/dist/components/Switch.d.ts +1 -1
- package/dist/components/Switch.js +20 -30
- package/dist/components/Tabs.d.ts +2 -2
- package/dist/components/Tabs.js +13 -24
- package/dist/components/TextInput.d.ts +1 -1
- package/dist/components/TextInput.js +71 -26
- package/dist/components/Toggle.d.ts +2 -42
- package/dist/components/Toggle.js +38 -27
- package/dist/components/ToggleGroup.d.ts +1 -1
- package/dist/components/ToggleGroup.js +37 -32
- package/dist/components/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip.js +9 -3
- package/dist/components/UIProvider.d.ts +22 -2
- package/dist/components/UIProvider.js +15 -3
- package/dist/components/bottomSheetDismiss.d.ts +19 -0
- package/dist/components/bottomSheetDismiss.js +44 -0
- package/dist/components/index.d.ts +46 -44
- package/dist/components/index.js +2 -0
- package/dist/components/keyboardDismiss.js +12 -4
- package/dist/components/nativeTextField.android.js +13 -9
- package/dist/constants/colors.d.ts +40 -5
- package/dist/constants/colors.js +26 -8
- package/dist/constants/fonts.d.ts +41 -2
- package/dist/constants/fonts.js +46 -7
- package/dist/constants/index.d.ts +5 -4
- package/dist/constants/index.js +1 -0
- package/dist/constants/interaction.d.ts +18 -0
- package/dist/constants/interaction.js +18 -0
- package/dist/constants/spacing.d.ts +2 -1
- package/dist/constants/spacing.js +2 -1
- package/dist/design-system.json +154 -2
- package/dist/hooks/index.d.ts +12 -7
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/useDimensions.d.ts +13 -8
- package/dist/hooks/useDimensions.js +123 -48
- package/dist/hooks/useFocusVisible.d.ts +30 -0
- package/dist/hooks/useFocusVisible.js +45 -0
- package/dist/hooks/useFontStyle.d.ts +2 -2
- package/dist/hooks/useFontStyle.js +3 -2
- package/dist/hooks/useHydrated.d.ts +13 -0
- package/dist/hooks/useHydrated.js +19 -0
- package/dist/hooks/useNotificationOffset.d.ts +20 -0
- package/dist/hooks/useNotificationOffset.js +34 -0
- package/dist/hooks/useResources.d.ts +21 -20
- package/dist/hooks/useResources.js +72 -68
- package/dist/hooks/useScalePress.d.ts +8 -5
- package/dist/hooks/useScalePress.js +16 -9
- package/dist/hooks/useShape.d.ts +24 -0
- package/dist/hooks/useShape.js +24 -0
- package/dist/hooks/useStaggeredEntrance.js +9 -7
- package/dist/hooks/useTheme.d.ts +3 -3
- package/dist/hooks/useTheme.js +177 -66
- package/dist/hooks/useWindowInsets.d.ts +13 -0
- package/dist/hooks/useWindowInsets.js +23 -0
- package/dist/index.d.ts +5 -5
- package/dist/lib/composeRefs.d.ts +8 -0
- package/dist/lib/composeRefs.js +20 -0
- package/dist/lib/haptics.d.ts +12 -0
- package/dist/lib/haptics.js +21 -0
- package/dist/lib/index.d.ts +6 -5
- package/dist/lib/index.js +1 -0
- package/dist/lib/interFonts.d.ts +15 -0
- package/dist/lib/interFonts.js +1 -0
- package/dist/lib/interFonts.native.d.ts +3 -0
- package/dist/lib/interFonts.native.js +20 -0
- package/dist/lib/popoverPlacement.d.ts +36 -0
- package/dist/lib/popoverPlacement.js +29 -0
- package/dist/lib/themedStyles.d.ts +1 -1
- package/dist/lib/useAnimatedValue.d.ts +15 -0
- package/dist/lib/useAnimatedValue.js +19 -0
- package/dist/lib/webHitTarget.d.ts +40 -0
- package/dist/lib/webHitTarget.js +37 -0
- package/dist/state/feedbackStore.d.ts +24 -0
- package/dist/state/feedbackStore.js +16 -0
- package/dist/state/globalUIStore.d.ts +27 -0
- package/dist/state/globalUIStore.js +23 -0
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +2 -0
- package/dist/state/initialScheme.d.ts +27 -0
- package/dist/state/initialScheme.js +29 -0
- package/dist/state/notify.d.ts +1 -1
- package/dist/state/themeColorScope.d.ts +1 -1
- package/dist/state/themeStore.d.ts +69 -16
- package/dist/state/themeStore.js +65 -38
- package/llms-full.md +56 -8
- package/llms.txt +10 -1
- package/package.json +69 -2
package/dist/state/themeStore.js
CHANGED
|
@@ -38,6 +38,10 @@ export const useThemeStore = create((set) => ({
|
|
|
38
38
|
fontOverrides: {},
|
|
39
39
|
// And again for shape: package geometry until a host app calls `setShape`.
|
|
40
40
|
shapeOverrides: {},
|
|
41
|
+
serifPreset: "georgia",
|
|
42
|
+
setSerifPreset: (preset) => {
|
|
43
|
+
set({ serifPreset: preset ?? "georgia" });
|
|
44
|
+
},
|
|
41
45
|
setColors: (overrides) => {
|
|
42
46
|
set({ colorOverrides: overrides ?? {} });
|
|
43
47
|
},
|
|
@@ -89,15 +93,15 @@ export const useThemeStore = create((set) => ({
|
|
|
89
93
|
set({ hasLoadedTheme: true });
|
|
90
94
|
}
|
|
91
95
|
}));
|
|
92
|
-
|
|
96
|
+
// The OS color-scheme listener is shared: one subscription however many
|
|
97
|
+
// callers hold it, removed when the last holder releases. Each
|
|
98
|
+
// `startSystemThemeListener()` call takes a hold and gets its own release.
|
|
99
|
+
let systemThemeSubscription = null;
|
|
100
|
+
let systemThemeHolds = 0;
|
|
93
101
|
export function syncSystemTheme() {
|
|
94
102
|
useThemeStore.getState().setSystemTheme(getSystemTheme());
|
|
95
103
|
}
|
|
96
|
-
|
|
97
|
-
if (stopSystemThemeListener) {
|
|
98
|
-
return stopSystemThemeListener;
|
|
99
|
-
}
|
|
100
|
-
syncSystemTheme();
|
|
104
|
+
function subscribeToSystemTheme() {
|
|
101
105
|
if (Platform.OS === "web" && typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
102
106
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
103
107
|
const onChange = () => {
|
|
@@ -105,48 +109,71 @@ export function startSystemThemeListener() {
|
|
|
105
109
|
};
|
|
106
110
|
if (typeof mediaQuery.addEventListener === "function") {
|
|
107
111
|
mediaQuery.addEventListener("change", onChange);
|
|
108
|
-
|
|
109
|
-
mediaQuery.removeEventListener("change", onChange);
|
|
110
|
-
stopSystemThemeListener = null;
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
mediaQuery.addListener(onChange);
|
|
115
|
-
stopSystemThemeListener = () => {
|
|
116
|
-
mediaQuery.removeListener(onChange);
|
|
117
|
-
stopSystemThemeListener = null;
|
|
118
|
-
};
|
|
112
|
+
return { remove: () => mediaQuery.removeEventListener("change", onChange) };
|
|
119
113
|
}
|
|
120
|
-
|
|
114
|
+
mediaQuery.addListener(onChange);
|
|
115
|
+
return { remove: () => mediaQuery.removeListener(onChange) };
|
|
121
116
|
}
|
|
122
|
-
|
|
117
|
+
return Appearance.addChangeListener(({ colorScheme }) => {
|
|
123
118
|
useThemeStore.getState().setSystemTheme(colorScheme === "dark" ? "dark" : "light");
|
|
124
119
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Keep `systemTheme` following the OS color scheme (`prefers-color-scheme` on
|
|
123
|
+
* web, `Appearance` on native). The first holder reads the current scheme and
|
|
124
|
+
* attaches the one listener; later calls share it.
|
|
125
|
+
*
|
|
126
|
+
* Returns this caller's release: once every holder has released, the
|
|
127
|
+
* listener is removed. Calling a release again is a no-op, so an effect
|
|
128
|
+
* cleanup that runs twice can't drop another caller's hold. On native the
|
|
129
|
+
* package holds the listener for the app's lifetime (see the module-load
|
|
130
|
+
* init below), so an app's release never stops OS tracking there.
|
|
131
|
+
*/
|
|
132
|
+
export function startSystemThemeListener() {
|
|
133
|
+
systemThemeHolds += 1;
|
|
134
|
+
if (systemThemeHolds === 1) {
|
|
135
|
+
syncSystemTheme();
|
|
136
|
+
systemThemeSubscription = subscribeToSystemTheme();
|
|
137
|
+
}
|
|
138
|
+
let released = false;
|
|
139
|
+
return () => {
|
|
140
|
+
if (released)
|
|
141
|
+
return;
|
|
142
|
+
released = true;
|
|
143
|
+
systemThemeHolds -= 1;
|
|
144
|
+
if (systemThemeHolds === 0) {
|
|
145
|
+
systemThemeSubscription?.remove();
|
|
146
|
+
systemThemeSubscription = null;
|
|
147
|
+
}
|
|
128
148
|
};
|
|
129
|
-
return stopSystemThemeListener;
|
|
130
149
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Single entry point for host apps to populate the store from the
|
|
152
|
+
* environment: the OS color-scheme listener plus the persisted preference.
|
|
153
|
+
*
|
|
154
|
+
* Web apps call it once, from a top-level `useEffect` (never during render or
|
|
155
|
+
* at module scope — see below), and return its result as the cleanup:
|
|
156
|
+
* `useEffect(() => syncThemeFromEnvironment(), [])`. Safe to call more than
|
|
157
|
+
* once (StrictMode's double effects, two roots): every call shares the one
|
|
158
|
+
* OS listener, re-reads the persisted preference, and returns its own
|
|
159
|
+
* cleanup, which releases only that call's hold on the listener.
|
|
160
|
+
*
|
|
161
|
+
* The listener starts BEFORE `loadTheme()` on purpose: reading the real OS
|
|
162
|
+
* scheme first means a `system` user resolves straight from the boot-default
|
|
163
|
+
* "light" to their actual scheme in one commit.
|
|
164
|
+
*/
|
|
139
165
|
export function syncThemeFromEnvironment() {
|
|
140
|
-
const
|
|
166
|
+
const release = startSystemThemeListener();
|
|
141
167
|
useThemeStore.getState().loadTheme();
|
|
142
|
-
return
|
|
168
|
+
return release;
|
|
143
169
|
}
|
|
144
170
|
// Native can read persistence at module load, so keep the historical
|
|
145
|
-
// auto-init behavior there
|
|
146
|
-
// `syncThemeFromEnvironment()` from a
|
|
147
|
-
// also evaluated in Node when
|
|
148
|
-
// `
|
|
149
|
-
//
|
|
171
|
+
// auto-init behavior there, with a hold on the OS listener that is never
|
|
172
|
+
// released. On web the host app must call `syncThemeFromEnvironment()` from a
|
|
173
|
+
// top-level `useEffect`: web bundles are also evaluated in Node when
|
|
174
|
+
// `expo export` renders the HTML shell, where `window`/`localStorage` don't
|
|
175
|
+
// exist, and reading them during the browser's first render would disagree
|
|
176
|
+
// with the markup being hydrated.
|
|
150
177
|
if (Platform.OS !== "web") {
|
|
151
178
|
useThemeStore.getState().loadTheme();
|
|
152
179
|
startSystemThemeListener();
|
package/llms-full.md
CHANGED
|
@@ -90,6 +90,52 @@ When the saved theme preference is `system`, the package theme store owns OS
|
|
|
90
90
|
color-scheme sync, including web `prefers-color-scheme`. Apps must not add their
|
|
91
91
|
own `Appearance` or `matchMedia` listeners for package components.
|
|
92
92
|
|
|
93
|
+
## Screen Layout
|
|
94
|
+
|
|
95
|
+
Screens are flat. On a 390 pt phone each nested inset comes out of the content:
|
|
96
|
+
rows boxed in a bordered group inside a padded screen start 33 pt from each edge
|
|
97
|
+
(16 + 1 + 16) with 324 pt left for them; the same rows in an `ItemGroup` start
|
|
98
|
+
16 pt in with 358 pt.
|
|
99
|
+
|
|
100
|
+
- One horizontal inset per screen: `spacing.screenPadding` (16). Either a
|
|
101
|
+
container pads or its children do, never both. `Item` rows and `ItemGroup`
|
|
102
|
+
titles and footers carry the 16 themselves, so a scroll view of groups gets
|
|
103
|
+
no horizontal padding; text, forms, and buttons between them pad their own
|
|
104
|
+
wrapper.
|
|
105
|
+
- No boxes as layout: no bordered, shadowed, or tinted rounded panel (or `Card`)
|
|
106
|
+
around a section, a form, or a group of rows. Separate sections with a header,
|
|
107
|
+
`spacing.sectionSpacing` (24), or a hairline (`Separator`).
|
|
108
|
+
- Lists and settings are `ItemGroup` + `Item`: full-width rows and touch
|
|
109
|
+
targets, hairlines inset under the title, no card per row, no border around
|
|
110
|
+
the group. Rows are direct children; the group separates them.
|
|
111
|
+
- Forms: fields span the column, grouped under section headers, not cards.
|
|
112
|
+
- Primary content (photos, video, maps, QR codes, charts) sizes to the column
|
|
113
|
+
width, never a fixed size floating in whitespace.
|
|
114
|
+
- Wide screens cap and centre the column (`width: "100%", maxWidth: 640,
|
|
115
|
+
alignSelf: "center"` on the scroll content; 960 for dense grids) instead of
|
|
116
|
+
boxing it.
|
|
117
|
+
- `Card` is for one item in a collection (feed entry, grid tile, carousel slide)
|
|
118
|
+
or a single tappable object; `StatCard` likewise (a scrolling metrics rail, a
|
|
119
|
+
tappable metric). Never nest them.
|
|
120
|
+
- Dialog, sheet, and popover chrome keep their surfaces.
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<ScrollView contentContainerStyle={{ width: "100%", maxWidth: 640, alignSelf: "center", paddingVertical: spacing.md, gap: spacing.sectionSpacing }}>
|
|
124
|
+
<ItemGroup title="Account" footer="Signed in as jane@example.com">
|
|
125
|
+
<Item onPress={openProfile}>
|
|
126
|
+
<ItemMedia icon="user" />
|
|
127
|
+
<ItemContent><ItemTitle>Edit profile</ItemTitle></ItemContent>
|
|
128
|
+
<ItemActions><Icon name="chevron-right" size={18} color="mutedForeground" /></ItemActions>
|
|
129
|
+
</Item>
|
|
130
|
+
<Item>
|
|
131
|
+
<ItemMedia icon="bell" />
|
|
132
|
+
<ItemContent><ItemTitle>Notifications</ItemTitle></ItemContent>
|
|
133
|
+
<ItemActions><Switch checked={enabled} onCheckedChange={setEnabled} /></ItemActions>
|
|
134
|
+
</Item>
|
|
135
|
+
</ItemGroup>
|
|
136
|
+
</ScrollView>
|
|
137
|
+
```
|
|
138
|
+
|
|
93
139
|
## Component Catalog
|
|
94
140
|
|
|
95
141
|
Every component is exported from `@mrmeg/expo-ui/components`, and from
|
|
@@ -105,7 +151,7 @@ before creating a new app-local primitive.
|
|
|
105
151
|
| `Badge` | Short status labels | Prefer over custom pill views. |
|
|
106
152
|
| `BottomSheet` | Mobile-first modal sheets | Requires root `UIProvider`. Native sheet via `@expo/ui`; `swipeEnabled`, `avoidKeyboard`, `dismissKeyboardOnDrag` are accepted but ignored (the iOS sheet presentation and Android Material3 keep content above the keyboard; never nest a `KeyboardAvoidingView` in a sheet). |
|
|
107
153
|
| `Button` | Commands and CTAs | Use `preset`, not `variant`; heights are 28/32/40. |
|
|
108
|
-
| `Card` |
|
|
154
|
+
| `Card` | One item in a collection (feed entry, grid tile, carousel slide) or a single tappable object | Not a layout box: never around a section, form, or row group; never nested. Parts pad `spacing.cardPadding`. |
|
|
109
155
|
| `Carousel` | Small known set of horizontally snapping slides | Renders every child (no virtualization); fractional `itemWidth` measures the viewport until first layout. |
|
|
110
156
|
| `Checkbox` | Boolean selection in forms or lists | Prefer over custom checkmark controls. |
|
|
111
157
|
| `Collapsible` | One-off disclosure | Use for advanced settings or helper sections. |
|
|
@@ -118,6 +164,7 @@ before creating a new app-local primitive.
|
|
|
118
164
|
| `Icon` | Lucide or custom icons with theme tokens | `color` takes a theme color name; pass `decorative` to hide from a11y. |
|
|
119
165
|
| `InputOTP` | Verification code entry | Prefer over manually managed text input groups. |
|
|
120
166
|
| `Item` | List / settings rows | Applies the row density tokens and a 44px native hit area (40px on web). |
|
|
167
|
+
| `ItemGroup` | A titled group of full-width `Item` rows | Props: `title`, `description`, `footer`, `style`, `testID`. Draws inset hairlines between rows; no border, fill, or horizontal padding, so the parent must not pad either. |
|
|
121
168
|
| `KeyboardAvoidingView` | Native keyboard-aware roots, composer footers, form-heavy subtrees | `UIProvider` already mounts one root; use directly only for custom subtrees. |
|
|
122
169
|
| `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
170
|
| `MaxWidthContainer` | Centered responsive width | Use for web and tablet constrained layouts. |
|
|
@@ -131,7 +178,7 @@ before creating a new app-local primitive.
|
|
|
131
178
|
| `Separator` | Horizontal or vertical dividers | Prefer over border-only spacer views. |
|
|
132
179
|
| `Skeleton` | Loading placeholders | Use stable dimensions to avoid layout shift. |
|
|
133
180
|
| `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`. |
|
|
181
|
+
| `StatCard` | Metric tile in a collection, or one tappable metric | Props: `label`, `value`, `unit`, `change` (`{ value, direction }`), `icon`, `onPress`. A Card, so the same rule applies. |
|
|
135
182
|
| `StatusBar` | Theme-aware native status bar | Usually mounted through `UIProvider`. |
|
|
136
183
|
| `StyledText` | Theme-aware typography | Prefer semantic aliases over raw `Text`. |
|
|
137
184
|
| `Switch` | Binary settings | Prefer over custom toggles for on/off state. |
|
|
@@ -156,9 +203,10 @@ option sets.
|
|
|
156
203
|
`Dialog` blocking decisions · `Popover` contextual controls · `Tooltip` short
|
|
157
204
|
explanations · `DropdownMenu` action lists.
|
|
158
205
|
|
|
159
|
-
`
|
|
160
|
-
|
|
161
|
-
|
|
206
|
+
`ItemGroup` + `Item` lists and settings · `Card` one item in a collection or one
|
|
207
|
+
tappable object, never a wrapper around a section, form, or row group, never
|
|
208
|
+
nested · `EmptyState` no-data or recoverable errors · `Skeleton` loading content
|
|
209
|
+
with stable layout · `Progress` real or indeterminate progress.
|
|
162
210
|
|
|
163
211
|
## Notifications
|
|
164
212
|
|
|
@@ -196,6 +244,6 @@ selectors and tests. Use `notify` for imperative triggers in app code.
|
|
|
196
244
|
## Validation
|
|
197
245
|
|
|
198
246
|
Changing package code or shipped docs? Run the gates from the monorepo root:
|
|
199
|
-
`
|
|
200
|
-
|
|
201
|
-
|
|
247
|
+
`typecheck`, `test`, `build`, `pack`, `consumer-smoke` (`bun run pkg ui <gate>`).
|
|
248
|
+
Docs-only changes need at least `bun run pkg ui pack`, which proves the new docs
|
|
249
|
+
land in the npm tarball.
|
package/llms.txt
CHANGED
|
@@ -30,7 +30,16 @@ gestures and keyboard avoidance; swipeEnabled, avoidKeyboard, and
|
|
|
30
30
|
dismissKeyboardOnDrag are accepted but ignored. On iOS the sheet presentation
|
|
31
31
|
lifts or shrinks the hosted content so Footer and Body end at the keyboard's
|
|
32
32
|
top (device-verified); Android avoidance is Material3's. Do not nest a
|
|
33
|
-
KeyboardAvoidingView inside a sheet.
|
|
33
|
+
KeyboardAvoidingView inside a sheet. Open the next modal from the sheet's
|
|
34
|
+
onDismissed callback (fires once the sheet is fully gone), not from
|
|
35
|
+
onOpenChange(false).
|
|
36
|
+
|
|
37
|
+
Screens are flat: one 16 pt horizontal inset (spacing.screenPadding), either
|
|
38
|
+
on the container or on its children, never both. Lists and settings are
|
|
39
|
+
ItemGroup + Item (full-width rows, inset hairlines), never rows inside a
|
|
40
|
+
bordered, shadowed, or tinted panel. Card is for one item in a collection or one
|
|
41
|
+
tappable object; never nest Cards. Media and charts fill the column width; wide
|
|
42
|
+
screens cap and centre the column. LLM_USAGE.md "Screen Layout" has the rules.
|
|
34
43
|
|
|
35
44
|
Use useTheme(), useStyles(), semantic tokens, StyledText, and package controls.
|
|
36
45
|
Do not add app-local Appearance or matchMedia listeners for theme sync. On web
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrmeg/expo-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Reusable Expo and React Native UI primitives for MrMeg projects.",
|
|
6
6
|
"keywords": [
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
},
|
|
30
30
|
"main": "./dist/index.js",
|
|
31
31
|
"types": "./dist/index.d.ts",
|
|
32
|
+
"sideEffects": [
|
|
33
|
+
"./src/state/themeStore.ts",
|
|
34
|
+
"./dist/state/themeStore.js"
|
|
35
|
+
],
|
|
32
36
|
"files": [
|
|
33
37
|
"dist",
|
|
34
38
|
"package.json",
|
|
@@ -40,42 +44,105 @@
|
|
|
40
44
|
],
|
|
41
45
|
"exports": {
|
|
42
46
|
".": {
|
|
47
|
+
"@mrmeg/source": "./src/index.ts",
|
|
43
48
|
"types": "./dist/index.d.ts",
|
|
44
49
|
"default": "./dist/index.js"
|
|
45
50
|
},
|
|
46
51
|
"./components": {
|
|
52
|
+
"@mrmeg/source": "./src/components/index.ts",
|
|
53
|
+
"types": "./dist/components/index.d.ts",
|
|
54
|
+
"default": "./dist/components/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./components/bottomSheetDismiss": {
|
|
57
|
+
"@mrmeg/source": "./src/components/bottomSheetDismiss.ts",
|
|
58
|
+
"types": "./dist/components/bottomSheetDismiss.d.ts",
|
|
59
|
+
"default": "./dist/components/bottomSheetDismiss.js"
|
|
60
|
+
},
|
|
61
|
+
"./components/bottomSheetHostSupport": {
|
|
62
|
+
"@mrmeg/source": "./src/components/bottomSheetHostSupport.ts",
|
|
63
|
+
"types": "./dist/components/bottomSheetHostSupport.d.ts",
|
|
64
|
+
"default": "./dist/components/bottomSheetHostSupport.js"
|
|
65
|
+
},
|
|
66
|
+
"./components/iconRegistry.generated": {
|
|
67
|
+
"@mrmeg/source": "./src/components/iconRegistry.generated.ts",
|
|
68
|
+
"types": "./dist/components/iconRegistry.generated.d.ts",
|
|
69
|
+
"default": "./dist/components/iconRegistry.generated.js"
|
|
70
|
+
},
|
|
71
|
+
"./components/index": {
|
|
72
|
+
"@mrmeg/source": "./src/components/index.ts",
|
|
47
73
|
"types": "./dist/components/index.d.ts",
|
|
48
74
|
"default": "./dist/components/index.js"
|
|
49
75
|
},
|
|
76
|
+
"./components/keyboardController": {
|
|
77
|
+
"@mrmeg/source": {
|
|
78
|
+
"react-native": "./src/components/keyboardController.native.ts",
|
|
79
|
+
"default": "./src/components/keyboardController.ts"
|
|
80
|
+
},
|
|
81
|
+
"types": "./dist/components/keyboardController.d.ts",
|
|
82
|
+
"default": "./dist/components/keyboardController.js"
|
|
83
|
+
},
|
|
84
|
+
"./components/keyboardDismiss": {
|
|
85
|
+
"@mrmeg/source": "./src/components/keyboardDismiss.ts",
|
|
86
|
+
"types": "./dist/components/keyboardDismiss.d.ts",
|
|
87
|
+
"default": "./dist/components/keyboardDismiss.js"
|
|
88
|
+
},
|
|
89
|
+
"./components/keyboardFocusRegistry": {
|
|
90
|
+
"@mrmeg/source": "./src/components/keyboardFocusRegistry.ts",
|
|
91
|
+
"types": "./dist/components/keyboardFocusRegistry.d.ts",
|
|
92
|
+
"default": "./dist/components/keyboardFocusRegistry.js"
|
|
93
|
+
},
|
|
94
|
+
"./components/StyledText.context": {
|
|
95
|
+
"@mrmeg/source": "./src/components/StyledText.context.ts",
|
|
96
|
+
"types": "./dist/components/StyledText.context.d.ts",
|
|
97
|
+
"default": "./dist/components/StyledText.context.js"
|
|
98
|
+
},
|
|
50
99
|
"./components/*": {
|
|
100
|
+
"@mrmeg/source": "./src/components/*.tsx",
|
|
51
101
|
"types": "./dist/components/*.d.ts",
|
|
52
102
|
"default": "./dist/components/*.js"
|
|
53
103
|
},
|
|
54
104
|
"./constants": {
|
|
105
|
+
"@mrmeg/source": "./src/constants/index.ts",
|
|
55
106
|
"types": "./dist/constants/index.d.ts",
|
|
56
107
|
"default": "./dist/constants/index.js"
|
|
57
108
|
},
|
|
58
109
|
"./constants/*": {
|
|
110
|
+
"@mrmeg/source": "./src/constants/*.ts",
|
|
59
111
|
"types": "./dist/constants/*.d.ts",
|
|
60
112
|
"default": "./dist/constants/*.js"
|
|
61
113
|
},
|
|
62
114
|
"./hooks": {
|
|
115
|
+
"@mrmeg/source": "./src/hooks/index.ts",
|
|
63
116
|
"types": "./dist/hooks/index.d.ts",
|
|
64
117
|
"default": "./dist/hooks/index.js"
|
|
65
118
|
},
|
|
119
|
+
"./hooks/useReduceMotion": {
|
|
120
|
+
"@mrmeg/source": "./src/hooks/useReduceMotion.tsx",
|
|
121
|
+
"types": "./dist/hooks/useReduceMotion.d.ts",
|
|
122
|
+
"default": "./dist/hooks/useReduceMotion.js"
|
|
123
|
+
},
|
|
66
124
|
"./hooks/*": {
|
|
125
|
+
"@mrmeg/source": "./src/hooks/*.ts",
|
|
67
126
|
"types": "./dist/hooks/*.d.ts",
|
|
68
127
|
"default": "./dist/hooks/*.js"
|
|
69
128
|
},
|
|
70
129
|
"./state": {
|
|
130
|
+
"@mrmeg/source": "./src/state/index.ts",
|
|
71
131
|
"types": "./dist/state/index.d.ts",
|
|
72
132
|
"default": "./dist/state/index.js"
|
|
73
133
|
},
|
|
134
|
+
"./state/themeColorScope": {
|
|
135
|
+
"@mrmeg/source": "./src/state/themeColorScope.tsx",
|
|
136
|
+
"types": "./dist/state/themeColorScope.d.ts",
|
|
137
|
+
"default": "./dist/state/themeColorScope.js"
|
|
138
|
+
},
|
|
74
139
|
"./state/*": {
|
|
140
|
+
"@mrmeg/source": "./src/state/*.ts",
|
|
75
141
|
"types": "./dist/state/*.d.ts",
|
|
76
142
|
"default": "./dist/state/*.js"
|
|
77
143
|
},
|
|
78
144
|
"./lib": {
|
|
145
|
+
"@mrmeg/source": "./src/lib/index.ts",
|
|
79
146
|
"types": "./dist/lib/index.d.ts",
|
|
80
147
|
"default": "./dist/lib/index.js"
|
|
81
148
|
},
|
|
@@ -129,7 +196,7 @@
|
|
|
129
196
|
"zustand": ">=5.0.0 <6.0.0"
|
|
130
197
|
},
|
|
131
198
|
"devDependencies": {
|
|
132
|
-
"@types/react": "~19.
|
|
199
|
+
"@types/react": "~19.3.0",
|
|
133
200
|
"typescript": "~6.0.3"
|
|
134
201
|
}
|
|
135
202
|
}
|