Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 19 additions & 25 deletions apps/native-component-list/src/screens/SecureStoreScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,22 @@ function SecureStoreView() {
const [value, setValue] = React.useState<string | undefined>();
const [service, setService] = React.useState<string | undefined>();
const [requireAuth, setRequireAuth] = React.useState<boolean>(false);
const [requireConfirmation, setRequireConfirmation] = React.useState<boolean>(true);
const [byteSize, setByteSize] = React.useState<string>('4096');

const storeOptions = React.useMemo<SecureStore.SecureStoreOptions>(
() => ({
keychainService: service,
requireAuthentication: requireAuth,
authenticationPrompt: requireAuth ? 'Authenticate' : undefined,
...(Platform.OS === 'android' ? { requireConfirmation } : {}),
}),
[requireAuth, service]
[requireAuth, requireConfirmation, service]
);

async function storeValueAsync(value: string, key: string) {
try {
await SecureStore.setItemAsync(key, value, {
keychainService: service,
requireAuthentication: requireAuth,
authenticationPrompt: 'Authenticate',
});
await SecureStore.setItemAsync(key, value, storeOptions);
Alert.alert('Success!', 'Value: ' + value + ', stored successfully for key: ' + key, [
{ text: 'OK', onPress: () => {} },
]);
Expand All @@ -65,11 +63,7 @@ function SecureStoreView() {

function storeValue(value: string, key: string) {
try {
SecureStore.setItem(key, value, {
keychainService: service,
requireAuthentication: requireAuth,
authenticationPrompt: 'Authenticate',
});
SecureStore.setItem(key, value, storeOptions);
Alert.alert('Success!', 'Value: ' + value + ', stored successfully for key: ' + key, [
{ text: 'OK', onPress: () => {} },
]);
Expand All @@ -80,11 +74,7 @@ function SecureStoreView() {

async function getValueAsync(key: string) {
try {
const fetchedValue = await SecureStore.getItemAsync(key, {
keychainService: service,
requireAuthentication: requireAuth,
authenticationPrompt: 'Authenticate',
});
const fetchedValue = await SecureStore.getItemAsync(key, storeOptions);
Alert.alert('Success!', 'Fetched value: ' + fetchedValue, [
{ text: 'OK', onPress: () => {} },
]);
Expand All @@ -95,11 +85,7 @@ function SecureStoreView() {

function getValue(key: string) {
try {
const fetchedValue = SecureStore.getItem(key, {
keychainService: service,
requireAuthentication: requireAuth,
authenticationPrompt: 'Authenticate',
});
const fetchedValue = SecureStore.getItem(key, storeOptions);
Alert.alert('Success!', 'Fetched value: ' + fetchedValue, [
{ text: 'OK', onPress: () => {} },
]);
Expand Down Expand Up @@ -184,10 +170,18 @@ function SecureStoreView() {
Can use biometric authentication: {SecureStore.canUseBiometricAuthentication().toString()}
</BodyText>
{SecureStore.canUseBiometricAuthentication() && (
<View style={styles.authToggleContainer}>
<BodyText>Requires authentication:</BodyText>
<Switch value={requireAuth} onValueChange={setRequireAuth} />
</View>
<>
<View style={styles.authToggleContainer}>
<BodyText>Requires authentication:</BodyText>
<Switch value={requireAuth} onValueChange={setRequireAuth} />
</View>
{Platform.OS === 'android' && requireAuth && (
<View style={styles.authToggleContainer}>
<BodyText>Requires confirmation:</BodyText>
<Switch value={requireConfirmation} onValueChange={setRequireConfirmation} />
</View>
)}
</>
)}
{value && key && (
<ListButton onPress={() => storeValueAsync(value, key)} title="Store value with key" />
Expand Down
29 changes: 29 additions & 0 deletions apps/native-component-list/src/screens/UI/ModifiersScreen.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,35 @@ export default function ModifiersScreen() {
/>
</Section>

<Section title="Padding">
<Text
modifiers={[
padding(),
background('#E8F0FE'),
foregroundStyle({ type: 'color', color: '#1A1A1A' }),
]}>
System default padding on every edge
</Text>

<Text
modifiers={[
padding({ top: 'default', horizontal: 24 }),
background('#E8F0FE'),
foregroundStyle({ type: 'color', color: '#1A1A1A' }),
]}>
System default on top, 24 points on the sides, none at the bottom
</Text>

<Text
modifiers={[
padding({ all: 'default', leading: 0 }),
background('#E8F0FE'),
foregroundStyle({ type: 'color', color: '#1A1A1A' }),
]}>
System default on every edge except the leading one
</Text>
</Section>

{/* New Modifier System Demo Section */}
<Section title="SwiftUI Modifiers Demo">
{/* Basic Appearance Modifiers */}
Expand Down
30 changes: 30 additions & 0 deletions docs/pages/versions/unversioned/sdk/ui/universal/bottomsheet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ export default function BottomSheetNoIndicatorExample() {
}
```

### Content padding

The sheet insets its content by default. Pass [`contentPadding`](#contentpadding) to change that inset — `0` lets a row, image, or divider reach the sheet's edges.

```tsx BottomSheetContentPaddingExample.tsx
import { useState } from 'react';
import { Host, BottomSheet, Button, Column, Text } from '@expo/ui';

export default function BottomSheetContentPaddingExample() {
const [isPresented, setIsPresented] = useState(false);

return (
<Host style={{ flex: 1 }}>
<Button label="Open" onPress={() => setIsPresented(true)} />
<BottomSheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
contentPadding={0}>
<Column>
<Column style={{ backgroundColor: '#0a84ff', padding: 16 }}>
<Text>This banner reaches the sheet's edge.</Text>
</Column>
<Button label="Close" onPress={() => setIsPresented(false)} />
</Column>
</BottomSheet>
</Host>
);
}
```

### Snap points

Pass [`snapPoints`](#snappoints) to let the user drag the sheet between multiple resting heights. You can use the semantic values `'half'` and `'full'` for cross-platform parity. The `{ fraction }` and `{ height }` forms are honored precisely on iOS and web.
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"schemaVersion":"2.0","name":"expo-ui/universal/bottomsheet","variant":"project","kind":1,"children":[{"name":"BottomSheetProps","variant":"declaration","kind":256,"comment":{"summary":[{"kind":"text","text":"Props for the ["},{"kind":"code","text":"`BottomSheet`"},{"kind":"text","text":"](#bottomsheet) component, a modal sheet that slides up from the bottom of the screen."}]},"children":[{"name":"children","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Content to render inside the bottom sheet."}]},"type":{"type":"reference","target":{"packageName":"@types/react","packagePath":"index.d.ts","qualifiedName":"React.ReactNode"},"name":"ReactNode","package":"@types/react","qualifiedName":"React.ReactNode"}},{"name":"isPresented","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Whether the bottom sheet is currently visible."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"modifiers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Platform-specific modifier escape hatch. Pass an array of modifier configs\nfrom "},{"kind":"code","text":"`@expo/ui/swift-ui/modifiers`"},{"kind":"text","text":" or "},{"kind":"code","text":"`@expo/ui/jetpack-compose/modifiers`"},{"kind":"text","text":"."}]},"type":{"type":"array","elementType":{"type":"reference","target":{"packageName":"@expo/ui","packagePath":"src/types.ts","qualifiedName":"ModifierConfig"},"name":"ModifierConfig","package":"@expo/ui"}}},{"name":"onDismiss","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Called when the bottom sheet is dismissed by the user (e.g. swiping down or tapping the overlay)."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"showDragIndicator","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to show a drag indicator at the top of the sheet."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"true"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"snapPoints","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Heights the sheet can rest at.\nWhen omitted, the sheet auto-sizes to its content.\nSee ["},{"kind":"code","text":"`SnapPoint`"},{"kind":"text","text":"](#snappoint) for the supported values."}],"blockTags":[{"tag":"@example","name":"`['half', 'full']` — draggable between half and full","content":[]},{"tag":"@example","name":"`['full']` — always full height","content":[]}]},"type":{"type":"array","elementType":{"type":"reference","name":"SnapPoint","package":"@expo/ui"}}},{"name":"testID","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Identifier used to locate the component in end-to-end tests."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"SnapPoint","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"A snap point describing one of the heights a ["},{"kind":"code","text":"`BottomSheet`"},{"kind":"text","text":"](#bottomsheet) can rest at.\n\n- "},{"kind":"code","text":"`'half'`"},{"kind":"text","text":" — Approximately half-screen.\n- "},{"kind":"code","text":"`'full'`"},{"kind":"text","text":" — Fully expanded.\n- "},{"kind":"code","text":"`{ fraction }`"},{"kind":"text","text":" — A fraction of the screen height (0–1).\n iOS / web only.\n- "},{"kind":"code","text":"`{ height }`"},{"kind":"text","text":" — A fixed pixel height.\n iOS / web only.\n\nOn Android, "},{"kind":"code","text":"`{ fraction }`"},{"kind":"text","text":" and "},{"kind":"code","text":"`{ height }`"},{"kind":"text","text":" snap to the nearest of "},{"kind":"code","text":"`'half'`"},{"kind":"text","text":" / "},{"kind":"code","text":"`'full'`"},{"kind":"text","text":".\nSee the component docs for platform behavior notes."}]},"type":{"type":"union","types":[{"type":"literal","value":"half"},{"type":"literal","value":"full"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"fraction","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"number"}}]}},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"height","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"number"}}]}}]}},{"name":"BottomSheet","variant":"declaration","kind":64,"signatures":[{"name":"BottomSheet","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"A modal sheet that slides up from the bottom of the screen."}]},"parameters":[{"name":"__namedParameters","variant":"param","kind":32768,"type":{"type":"reference","name":"BottomSheetProps","package":"@expo/ui"}}],"type":{"type":"reference","target":{"packageName":"@types/react","packagePath":"jsx-runtime.d.ts","qualifiedName":"JSX.Element"},"name":"Element","package":"@types/react","qualifiedName":"JSX.Element"}}]}],"packageName":"@expo/ui"}
{"schemaVersion":"2.0","name":"expo-ui/universal/bottomsheet","variant":"project","kind":1,"children":[{"name":"BottomSheetProps","variant":"declaration","kind":256,"comment":{"summary":[{"kind":"text","text":"Props for the ["},{"kind":"code","text":"`BottomSheet`"},{"kind":"text","text":"](#bottomsheet) component, a modal sheet that slides up from the bottom of the screen."}]},"children":[{"name":"children","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Content to render inside the bottom sheet."}]},"type":{"type":"reference","target":{"packageName":"@types/react","packagePath":"index.d.ts","qualifiedName":"React.ReactNode"},"name":"ReactNode","package":"@types/react","qualifiedName":"React.ReactNode"}},{"name":"contentPadding","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Padding between the sheet and ["},{"kind":"code","text":"`children`"},{"kind":"text","text":"](#children), in dp on Android, points on iOS, and\nCSS pixels on web. Pass "},{"kind":"code","text":"`0`"},{"kind":"text","text":" for content that reaches the sheet's edges.\n\nWhen omitted, each platform keeps the inset it applies by default."}],"blockTags":[{"tag":"@example","name":"`contentPadding={0}` — full-bleed content","content":[]},{"tag":"@example","name":"`contentPadding={{ top: 8, bottom: 24 }}` — no horizontal inset","content":[]}]},"type":{"type":"reference","name":"BottomSheetContentPadding","package":"@expo/ui"}},{"name":"isPresented","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Whether the bottom sheet is currently visible."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"modifiers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Platform-specific modifier escape hatch. Pass an array of modifier configs\nfrom "},{"kind":"code","text":"`@expo/ui/swift-ui/modifiers`"},{"kind":"text","text":" or "},{"kind":"code","text":"`@expo/ui/jetpack-compose/modifiers`"},{"kind":"text","text":"."}]},"type":{"type":"array","elementType":{"type":"reference","target":{"packageName":"@expo/ui","packagePath":"src/types.ts","qualifiedName":"ModifierConfig"},"name":"ModifierConfig","package":"@expo/ui"}}},{"name":"onDismiss","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Called when the bottom sheet is dismissed by the user (e.g. swiping down or tapping the overlay)."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"showDragIndicator","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to show a drag indicator at the top of the sheet."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"true"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"snapPoints","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Heights the sheet can rest at.\nWhen omitted, the sheet auto-sizes to its content.\nSee ["},{"kind":"code","text":"`SnapPoint`"},{"kind":"text","text":"](#snappoint) for the supported values."}],"blockTags":[{"tag":"@example","name":"`['half', 'full']` — draggable between half and full","content":[]},{"tag":"@example","name":"`['full']` — always full height","content":[]}]},"type":{"type":"array","elementType":{"type":"reference","name":"SnapPoint","package":"@expo/ui"}}},{"name":"testID","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Identifier used to locate the component in end-to-end tests."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"BottomSheetContentPadding","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Padding between a ["},{"kind":"code","text":"`BottomSheet`"},{"kind":"text","text":"](#bottomsheet) and its content — a single value applied to every\nedge, or per-edge values where an edge that is left out is "},{"kind":"code","text":"`0`"},{"kind":"text","text":"."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"bottom","variant":"declaration","kind":1024,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"left","variant":"declaration","kind":1024,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"right","variant":"declaration","kind":1024,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"top","variant":"declaration","kind":1024,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}}]}}]}},{"name":"SnapPoint","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"A snap point describing one of the heights a ["},{"kind":"code","text":"`BottomSheet`"},{"kind":"text","text":"](#bottomsheet) can rest at.\n\n- "},{"kind":"code","text":"`'half'`"},{"kind":"text","text":" — Approximately half-screen.\n- "},{"kind":"code","text":"`'full'`"},{"kind":"text","text":" — Fully expanded.\n- "},{"kind":"code","text":"`{ fraction }`"},{"kind":"text","text":" — A fraction of the screen height (0–1).\n iOS / web only.\n- "},{"kind":"code","text":"`{ height }`"},{"kind":"text","text":" — A fixed pixel height.\n iOS / web only.\n\nOn Android, "},{"kind":"code","text":"`{ fraction }`"},{"kind":"text","text":" and "},{"kind":"code","text":"`{ height }`"},{"kind":"text","text":" snap to the nearest of "},{"kind":"code","text":"`'half'`"},{"kind":"text","text":" / "},{"kind":"code","text":"`'full'`"},{"kind":"text","text":".\nSee the component docs for platform behavior notes."}]},"type":{"type":"union","types":[{"type":"literal","value":"half"},{"type":"literal","value":"full"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"fraction","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"number"}}]}},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"height","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"number"}}]}}]}},{"name":"BottomSheet","variant":"declaration","kind":64,"signatures":[{"name":"BottomSheet","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"A modal sheet that slides up from the bottom of the screen."}]},"parameters":[{"name":"__namedParameters","variant":"param","kind":32768,"type":{"type":"reference","name":"BottomSheetProps","package":"@expo/ui"}}],"type":{"type":"reference","target":{"packageName":"@types/react","packagePath":"jsx-runtime.d.ts","qualifiedName":"JSX.Element"},"name":"Element","package":"@types/react","qualifiedName":"JSX.Element"}}]}],"packageName":"@expo/ui"}
2 changes: 2 additions & 0 deletions packages/@expo/fingerprint/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

### 🐛 Bug fixes

- Set development mode before loading Expo config and `.env` files. ([#48839](https://github.com/expo/expo/pull/48839) by [@ramonclaudio](https://github.com/ramonclaudio))

### 💡 Others

- Hoisted the ignore-path Minimatch build out of the per-module filter in `ExpoConfigLoader`, avoiding O(modules × patterns) Minimatch constructions during config load. Byte-identical fingerprint hash. ([#48367](https://github.com/expo/expo/pull/48367) by [@alfonsocj](https://github.com/alfonsocj))
Expand Down
Loading
Loading