diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8631b58..f702703 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,28 +1,26 @@
{
- "editor.tabSize": 2,
- "editor.insertSpaces": true,
- "files.insertFinalNewline": true,
- "files.trimTrailingWhitespace": true,
- "editor.codeActionsOnSave": {
- "source.fixAll": "always"
- },
- "editor.defaultFormatter": "biomejs.biome",
- "editor.formatOnSave": true,
- "typescript.enablePromptUseWorkspaceTsdk": true,
- "typescript.tsdk": "node_modules/typescript/lib",
- "[typescriptreact]": {
- "editor.defaultFormatter": "vscode.typescript-language-features"
- },
- "[typescript]": {
- "editor.defaultFormatter": "biomejs.biome"
- },
- "[javascript]": {
- "editor.defaultFormatter": "biomejs.biome"
- },
- "css.customData": [
- ".vscode/css_custom_data.json"
- ],
- "files.associations": {
- "*.css": "tailwindcss"
- }
+ "editor.tabSize": 2,
+ "editor.insertSpaces": true,
+ "files.insertFinalNewline": true,
+ "files.trimTrailingWhitespace": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll": "always"
+ },
+ "editor.defaultFormatter": "biomejs.biome",
+ "editor.formatOnSave": true,
+ "typescript.enablePromptUseWorkspaceTsdk": true,
+ "typescript.tsdk": "node_modules/typescript/lib",
+ "[typescriptreact]": {
+ "editor.defaultFormatter": "vscode.typescript-language-features"
+ },
+ "[typescript]": {
+ "editor.defaultFormatter": "biomejs.biome"
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": "biomejs.biome"
+ },
+ "css.customData": [".vscode/css_custom_data.json"],
+ "files.associations": {
+ "*.css": "tailwindcss"
}
+}
diff --git a/app.config.ts b/app.config.ts
new file mode 100644
index 0000000..aa8e629
--- /dev/null
+++ b/app.config.ts
@@ -0,0 +1,56 @@
+import type { ConfigContext, ExpoConfig } from "@expo/config";
+
+export default ({ config }: ConfigContext): ExpoConfig => ({
+ ...config,
+ name: "Launchtrack Starter",
+ slug: "launchtrack-starter",
+ version: "1.0.0",
+ orientation: "portrait",
+ icon: "./assets/images/icon.png",
+ scheme: "ltstarter",
+ userInterfaceStyle: "dark",
+ runtimeVersion: {
+ policy: "appVersion"
+ },
+ splash: {
+ image: "./assets/images/splash.png",
+ resizeMode: "contain",
+ backgroundColor: "#ffffff"
+ },
+ assetBundlePatterns: [
+ "**/*"
+ ],
+ ios: {
+ supportsTablet: true,
+ bundleIdentifier: "dev.launchtrack.base"
+ },
+ android: {
+ adaptiveIcon: {
+ foregroundImage: "./assets/images/adaptive-icon.png",
+ backgroundColor: "#ffffff"
+ },
+ package: "dev.launchtrack.starterbase"
+ },
+ web: {
+ bundler: "metro",
+ output: "single",
+ favicon: "./assets/images/favicon.png"
+ },
+ plugins: [
+ [
+ "expo-router",
+ {
+ origin: process.env.NODE_ENV === "production" ? "https://launchtrack.github.io/expo-starter/": null
+ }
+ ]
+ ],
+ experiments: {
+ typedRoutes: true
+ },
+ extra: {
+ eas: {
+ projectId: ""
+ }
+ },
+ owner: "*"
+});
diff --git a/app.json b/app.json
deleted file mode 100644
index 6a9b107..0000000
--- a/app.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "expo": {
- "name": "Launchtrack Base",
- "slug": "launchtrack-base",
- "version": "1.0.0",
- "orientation": "portrait",
- "icon": "./assets/images/icon.png",
- "scheme": "myapp",
- "userInterfaceStyle": "dark",
- "runtimeVersion": {
- "policy": "appVersion"
- },
- "splash": {
- "image": "./assets/images/splash.png",
- "resizeMode": "contain",
- "backgroundColor": "#ffffff"
- },
- "assetBundlePatterns": [
- "**/*"
- ],
- "ios": {
- "supportsTablet": true,
- "bundleIdentifier": "dev.launchtrack.base"
- },
- "android": {
- "adaptiveIcon": {
- "foregroundImage": "./assets/images/adaptive-icon.png",
- "backgroundColor": "#ffffff"
- },
- "package": "dev.launchtrack.starterbase"
- },
- "web": {
- "bundler": "metro",
- "output": "single",
- "favicon": "./assets/images/favicon.png"
- },
- "plugins": [
- "expo-router"
- ],
- "experiments": {
- "typedRoutes": true
- },
- "extra": {
- "router": {
- "origin": "https://launchtrack.github.io/expo-starter/"
- },
- "eas": {
- "projectId": ""
- }
- },
- "owner": "*"
- }
-}
diff --git a/app/+not-found.tsx b/app/+not-found.tsx
index 08c97b6..41e3fad 100644
--- a/app/+not-found.tsx
+++ b/app/+not-found.tsx
@@ -1,15 +1,15 @@
-import { Link, Stack } from 'expo-router';
-import { View } from 'react-native';
-import { Text } from '~/components/ui/text';
+import { Link, Stack } from "expo-router";
+import { View } from "react-native";
+import { Text } from "~/components/ui/text";
export default function NotFoundScreen() {
return (
<>
-
+
This screen doesn't exist.
-
+
Go to home screen!
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 1258e31..c643cef 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -75,9 +75,7 @@ export default function RootLayout() {
-
+
diff --git a/app/habits/[id].tsx b/app/habits/[id].tsx
index 072cd7d..5886e85 100644
--- a/app/habits/[id].tsx
+++ b/app/habits/[id].tsx
@@ -30,9 +30,8 @@ import { Text } from "~/components/ui/text";
import { getHabits, setHabits } from "~/lib/storage";
import { cn } from "~/lib/utils";
-
const HabitCategories = [
- { value: "tom@cruise.com", label: "Health And Wellness", },
+ { value: "tom@cruise.com", label: "Health And Wellness" },
{ value: "napoleon@dynamite.com", label: "Personal Development" },
{ value: "kunfu@panda.com", label: "Social And Relationships" },
{ value: "bruce@lee.com", label: "Productivity" },
@@ -42,11 +41,11 @@ const HabitCategories = [
{ value: "lara@croft.com", label: "Leisure" },
];
-const HabitDurations = [
- {value: 5, label: "5 minutes"},
- {value: 10, label: "10 minutes"},
- {value: 15, label: "15 minutes"},
- {value: 30, label: "30 minutes"}
+const HabitDurations = [
+ { value: 5, label: "5 minutes" },
+ { value: 10, label: "10 minutes" },
+ { value: 15, label: "15 minutes" },
+ { value: 30, label: "30 minutes" },
];
const formSchema = z.object({
@@ -60,7 +59,7 @@ const formSchema = z.object({
{ value: z.string(), label: z.string() },
{
invalid_type_error: "Please select a favorite email.",
- }
+ },
),
duration: z.number().int().positive(),
enableNotifications: z.boolean(),
@@ -91,16 +90,16 @@ export default function FormScreen() {
};
async function onSubmit(values: z.infer) {
-
-
const oldHabits = await getHabits();
- setHabits([...oldHabits, {
- ...values,
- id: Math.random().toString(36).substring(7),
- category: values.category.value,
- }]);
- router.replace('/');
-
+ setHabits([
+ ...oldHabits,
+ {
+ ...values,
+ id: Math.random().toString(36).substring(7),
+ category: values.category.value,
+ },
+ ]);
+ router.replace("/");
}
return (
@@ -111,7 +110,7 @@ export default function FormScreen() {
automaticallyAdjustContentInsets={false}
contentInset={{ top: 12 }}
>
-
- (
@@ -162,7 +161,7 @@ export default function FormScreen() {
@@ -229,7 +228,6 @@ export default function FormScreen() {
}}
/>
-
)}
/>
-
+
@@ -260,4 +258,3 @@ export default function FormScreen() {
);
}
-
diff --git a/app/index.tsx b/app/index.tsx
index e2e5dee..f5d5abc 100644
--- a/app/index.tsx
+++ b/app/index.tsx
@@ -31,16 +31,20 @@ const HabitCard: React.FC = ({ habit, onDelete }) => {
return (
- {habit.name} Morning
+
+ {habit.name}
+
+ {" "}
+ Morning
+
+
{habit.description}
-
-
-
+
@@ -78,23 +82,21 @@ export default function Screen() {
(
-
- ),
+ headerRight: () => ,
}}
/>
}
+ ItemSeparatorComponent={() => }
data={habits}
renderItem={({ item }) => (
handleDeleteHabit(item.id)} />
)}
keyExtractor={(item) => item.id}
- ListFooterComponent={}
+ ListFooterComponent={}
/>
+ {["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][day]}
+
))}
-
- {initialHabit ? 'Update' : 'Create'}
-
+
+ {initialHabit ? "Update" : "Create"}
+
);
};
diff --git a/components/habit/index.ts b/components/habit/index.ts
index e236ba9..3177e56 100644
--- a/components/habit/index.ts
+++ b/components/habit/index.ts
@@ -1,3 +1,3 @@
-export * from "./card"
-export * from "./list"
-export * from "./form"
\ No newline at end of file
+export * from "./card";
+export * from "./list";
+export * from "./form";
diff --git a/components/header-avatar.tsx b/components/header-avatar.tsx
index c91ba6d..4ea00c9 100644
--- a/components/header-avatar.tsx
+++ b/components/header-avatar.tsx
@@ -1,8 +1,6 @@
-
-
-
-
-
- RS
-
-
\ No newline at end of file
+
+
+
+ RS
+
+;
diff --git a/components/primitives/avatar/index.tsx b/components/primitives/avatar/index.tsx
index 41a3892..a6238f6 100644
--- a/components/primitives/avatar/index.tsx
+++ b/components/primitives/avatar/index.tsx
@@ -1,16 +1,20 @@
-import * as React from 'react';
+import * as React from "react";
import {
+ Image as RNImage,
ImageErrorEventData,
ImageLoadEventData,
NativeSyntheticEvent,
- Image as RNImage,
View,
-} from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import { ComponentPropsWithAsChild, SlottableViewProps, ViewRef } from '~/components/primitives/types';
-import { AvatarImageProps, AvatarRootProps } from './types';
+} from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import {
+ ComponentPropsWithAsChild,
+ SlottableViewProps,
+ ViewRef,
+} from "~/components/primitives/types";
+import { AvatarImageProps, AvatarRootProps } from "./types";
-type AvatarState = 'loading' | 'error' | 'loaded';
+type AvatarState = "loading" | "error" | "loaded";
interface IRootContext extends AvatarRootProps {
status: AvatarState;
@@ -21,75 +25,93 @@ const RootContext = React.createContext(null);
const Root = React.forwardRef(
({ asChild, alt, ...viewProps }, ref) => {
- const [status, setStatus] = React.useState('loading');
+ const [status, setStatus] = React.useState("loading");
const Component = asChild ? Slot.View : View;
return (
);
- }
+ },
);
-Root.displayName = 'RootAvatar';
+Root.displayName = "RootAvatar";
function useRootContext() {
const context = React.useContext(RootContext);
if (!context) {
- throw new Error('Avatar compound components cannot be rendered outside the Avatar component');
+ throw new Error(
+ "Avatar compound components cannot be rendered outside the Avatar component",
+ );
}
return context;
}
const Image = React.forwardRef<
React.ElementRef,
- Omit, 'alt'> & AvatarImageProps
+ Omit, "alt"> & AvatarImageProps
>(
(
- { asChild, onLoad: onLoadProps, onError: onErrorProps, onLoadingStatusChange, ...props },
- ref
+ {
+ asChild,
+ onLoad: onLoadProps,
+ onError: onErrorProps,
+ onLoadingStatusChange,
+ ...props
+ },
+ ref,
) => {
const { alt, setStatus, status } = useRootContext();
const onLoad = React.useCallback(
(e: NativeSyntheticEvent) => {
- setStatus('loaded');
- onLoadingStatusChange?.('loaded');
+ setStatus("loaded");
+ onLoadingStatusChange?.("loaded");
onLoadProps?.(e);
},
- [onLoadProps]
+ [onLoadProps],
);
const onError = React.useCallback(
(e: NativeSyntheticEvent) => {
- setStatus('error');
- onLoadingStatusChange?.('error');
+ setStatus("error");
+ onLoadingStatusChange?.("error");
onErrorProps?.(e);
},
- [onErrorProps]
+ [onErrorProps],
);
- if (status === 'error') {
+ if (status === "error") {
return null;
}
const Component = asChild ? Slot.Image : RNImage;
- return ;
- }
+ return (
+
+ );
+ },
);
-Image.displayName = 'ImageAvatar';
+Image.displayName = "ImageAvatar";
-const Fallback = React.forwardRef(({ asChild, ...props }, ref) => {
- const { alt, status } = useRootContext();
+const Fallback = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const { alt, status } = useRootContext();
- if (status !== 'error') {
- return null;
- }
- const Component = asChild ? Slot.View : View;
- return ;
-});
+ if (status !== "error") {
+ return null;
+ }
+ const Component = asChild ? Slot.View : View;
+ return ;
+ },
+);
-Fallback.displayName = 'FallbackAvatar';
+Fallback.displayName = "FallbackAvatar";
export { Fallback, Image, Root };
diff --git a/components/primitives/avatar/types.ts b/components/primitives/avatar/types.ts
index 4d6d9c0..2a1c3b4 100644
--- a/components/primitives/avatar/types.ts
+++ b/components/primitives/avatar/types.ts
@@ -4,7 +4,7 @@ interface AvatarRootProps {
interface AvatarImageProps {
children?: React.ReactNode;
- onLoadingStatusChange?: (status: 'error' | 'loaded') => void;
+ onLoadingStatusChange?: (status: "error" | "loaded") => void;
}
export type { AvatarRootProps, AvatarImageProps };
diff --git a/components/primitives/checkbox/checkbox.tsx b/components/primitives/checkbox/checkbox.tsx
index 8240558..cb0fc9f 100644
--- a/components/primitives/checkbox/checkbox.tsx
+++ b/components/primitives/checkbox/checkbox.tsx
@@ -1,8 +1,12 @@
-import * as React from 'react';
-import { GestureResponderEvent, Pressable, View } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import type { ComponentPropsWithAsChild, PressableRef, SlottablePressableProps } from '~/components/primitives/types';
-import type { CheckboxIndicator, CheckboxRootProps } from './types';
+import * as React from "react";
+import { GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import type {
+ ComponentPropsWithAsChild,
+ PressableRef,
+ SlottablePressableProps,
+} from "~/components/primitives/types";
+import type { CheckboxIndicator, CheckboxRootProps } from "./types";
interface RootContext extends CheckboxRootProps {
nativeID?: string;
@@ -10,8 +14,14 @@ interface RootContext extends CheckboxRootProps {
const CheckboxContext = React.createContext(null);
-const Root = React.forwardRef(
- ({ asChild, disabled = false, checked, onCheckedChange, nativeID, ...props }, ref) => {
+const Root = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & CheckboxRootProps
+>(
+ (
+ { asChild, disabled = false, checked, onCheckedChange, nativeID, ...props },
+ ref,
+ ) => {
return (
);
- }
+ },
);
-Root.displayName = 'RootNativeCheckbox';
+Root.displayName = "RootNativeCheckbox";
function useCheckboxContext() {
const context = React.useContext(CheckboxContext);
if (!context) {
throw new Error(
- 'Checkbox compound components cannot be rendered outside the Checkbox component'
+ "Checkbox compound components cannot be rendered outside the Checkbox component",
);
}
return context;
@@ -41,7 +51,8 @@ function useCheckboxContext() {
const Trigger = React.forwardRef(
({ asChild, onPress: onPressProp, ...props }, ref) => {
- const { disabled, checked, onCheckedChange, nativeID } = useCheckboxContext();
+ const { disabled, checked, onCheckedChange, nativeID } =
+ useCheckboxContext();
function onPress(ev: GestureResponderEvent) {
if (disabled) return;
@@ -56,7 +67,7 @@ const Trigger = React.forwardRef(
ref={ref}
nativeID={nativeID}
aria-disabled={disabled}
- role='checkbox'
+ role="checkbox"
aria-checked={checked}
onPress={onPress}
accessibilityState={{
@@ -67,10 +78,10 @@ const Trigger = React.forwardRef(
{...props}
/>
);
- }
+ },
);
-Trigger.displayName = 'TriggerNativeCheckbox';
+Trigger.displayName = "TriggerNativeCheckbox";
const Indicator = React.forwardRef<
React.ElementRef,
@@ -90,12 +101,12 @@ const Indicator = React.forwardRef<
ref={ref}
aria-disabled={disabled}
aria-hidden={!(forceMount || checked)}
- role={'presentation'}
+ role={"presentation"}
{...props}
/>
);
});
-Indicator.displayName = 'IndicatorNativeCheckbox';
+Indicator.displayName = "IndicatorNativeCheckbox";
export { Indicator, Root };
diff --git a/components/primitives/checkbox/checkbox.web.tsx b/components/primitives/checkbox/checkbox.web.tsx
index 661ead3..088d2ed 100644
--- a/components/primitives/checkbox/checkbox.web.tsx
+++ b/components/primitives/checkbox/checkbox.web.tsx
@@ -1,17 +1,32 @@
-import * as Checkbox from '@radix-ui/react-checkbox';
-import * as React from 'react';
-import { GestureResponderEvent, Pressable, View } from 'react-native';
-import { useAugmentedRef } from '~/components/primitives/hooks';
-import * as Slot from '~/components/primitives/slot';
-import type { ComponentPropsWithAsChild, PressableRef, SlottablePressableProps } from '~/components/primitives/types';
-import type { CheckboxIndicator, CheckboxRootProps } from './types';
+import * as Checkbox from "@radix-ui/react-checkbox";
+import * as React from "react";
+import { GestureResponderEvent, Pressable, View } from "react-native";
+import { useAugmentedRef } from "~/components/primitives/hooks";
+import * as Slot from "~/components/primitives/slot";
+import type {
+ ComponentPropsWithAsChild,
+ PressableRef,
+ SlottablePressableProps,
+} from "~/components/primitives/types";
+import type { CheckboxIndicator, CheckboxRootProps } from "./types";
const CheckboxContext = React.createContext(null);
-const Root = React.forwardRef(
+const Root = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & CheckboxRootProps
+>(
(
- { asChild, disabled, checked, onCheckedChange, onPress: onPressProp, role: _role, ...props },
- ref
+ {
+ asChild,
+ disabled,
+ checked,
+ onCheckedChange,
+ onPress: onPressProp,
+ role: _role,
+ ...props
+ },
+ ref,
) => {
const augmentedRef = useAugmentedRef({ ref });
@@ -23,19 +38,19 @@ const Root = React.forwardRef {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
- augRef.dataset.state = checked ? 'checked' : 'unchecked';
- augRef.value = checked ? 'on' : 'off';
+ augRef.dataset.state = checked ? "checked" : "unchecked";
+ augRef.value = checked ? "on" : "off";
}
}, [checked]);
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
- augRef.type = 'button';
- augRef.role = 'checkbox';
+ augRef.type = "button";
+ augRef.role = "checkbox";
if (disabled) {
- augRef.dataset.disabled = 'true';
+ augRef.dataset.disabled = "true";
} else {
augRef.dataset.disabled = undefined;
}
@@ -53,7 +68,7 @@ const Root = React.forwardRef
);
- }
+ },
);
-Root.displayName = 'RootWebCheckbox';
+Root.displayName = "RootWebCheckbox";
function useCheckboxContext() {
const context = React.useContext(CheckboxContext);
if (context === null) {
throw new Error(
- 'Checkbox compound components cannot be rendered outside the Checkbox component'
+ "Checkbox compound components cannot be rendered outside the Checkbox component",
);
}
return context;
@@ -86,7 +101,7 @@ const Indicator = React.forwardRef<
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
- augRef.dataset.state = checked ? 'checked' : 'unchecked';
+ augRef.dataset.state = checked ? "checked" : "unchecked";
}
}, [checked]);
@@ -94,7 +109,7 @@ const Indicator = React.forwardRef<
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
if (disabled) {
- augRef.dataset.disabled = 'true';
+ augRef.dataset.disabled = "true";
} else {
augRef.dataset.disabled = undefined;
}
@@ -109,6 +124,6 @@ const Indicator = React.forwardRef<
);
});
-Indicator.displayName = 'IndicatorWebCheckbox';
+Indicator.displayName = "IndicatorWebCheckbox";
export { Indicator, Root };
diff --git a/components/primitives/checkbox/index.ts b/components/primitives/checkbox/index.ts
index 8d78b3e..057f167 100644
--- a/components/primitives/checkbox/index.ts
+++ b/components/primitives/checkbox/index.ts
@@ -1 +1 @@
-export * from './checkbox';
+export * from "./checkbox";
diff --git a/components/primitives/checkbox/types.ts b/components/primitives/checkbox/types.ts
index c3bf2bc..8dd5898 100644
--- a/components/primitives/checkbox/types.ts
+++ b/components/primitives/checkbox/types.ts
@@ -1,4 +1,4 @@
-import type { ForceMountable } from '~/components/primitives/types';
+import type { ForceMountable } from "~/components/primitives/types";
interface CheckboxRootProps {
checked: boolean;
diff --git a/components/primitives/dialog/dialog.tsx b/components/primitives/dialog/dialog.tsx
index f8e82ca..fd19176 100644
--- a/components/primitives/dialog/dialog.tsx
+++ b/components/primitives/dialog/dialog.tsx
@@ -1,6 +1,14 @@
-import { useControllableState } from '~/components/primitives/hooks';
-import { Portal as RNPPortal } from '~/components/primitives/portal';
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import {
+ BackHandler,
+ GestureResponderEvent,
+ Pressable,
+ Text,
+ View,
+} from "react-native";
+import { useControllableState } from "~/components/primitives/hooks";
+import { Portal as RNPPortal } from "~/components/primitives/portal";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
@@ -8,21 +16,30 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import { BackHandler, GestureResponderEvent, Pressable, Text, View } from 'react-native';
+} from "~/components/primitives/types";
import type {
DialogContentProps,
DialogOverlayProps,
DialogPortalProps,
DialogRootProps,
RootContext,
-} from './types';
+} from "./types";
-const DialogContext = React.createContext<(RootContext & { nativeID: string }) | null>(null);
+const DialogContext = React.createContext<
+ (RootContext & { nativeID: string }) | null
+>(null);
const Root = React.forwardRef(
- ({ asChild, open: openProp, defaultOpen, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
+ (
+ {
+ asChild,
+ open: openProp,
+ defaultOpen,
+ onOpenChange: onOpenChangeProp,
+ ...viewProps
+ },
+ ref,
+ ) => {
const nativeID = React.useId();
const [open = false, onOpenChange] = useControllableState({
prop: openProp,
@@ -42,15 +59,17 @@ const Root = React.forwardRef(
);
- }
+ },
);
-Root.displayName = 'RootNativeDialog';
+Root.displayName = "RootNativeDialog";
function useRootContext() {
const context = React.useContext(DialogContext);
if (!context) {
- throw new Error('Dialog compound components cannot be rendered outside the Dialog component');
+ throw new Error(
+ "Dialog compound components cannot be rendered outside the Dialog component",
+ );
}
return context;
}
@@ -71,16 +90,16 @@ const Trigger = React.forwardRef(
);
- }
+ },
);
-Trigger.displayName = 'TriggerNativeDialog';
+Trigger.displayName = "TriggerNativeDialog";
/**
* @warning when using a custom ``, you might have to adjust the Content's sideOffset to account for nav elements like headers.
@@ -101,8 +120,20 @@ function Portal({ forceMount, hostName, children }: DialogPortalProps) {
);
}
-const Overlay = React.forwardRef(
- ({ asChild, forceMount, closeOnPress = true, onPress: OnPressProp, ...props }, ref) => {
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DialogOverlayProps
+>(
+ (
+ {
+ asChild,
+ forceMount,
+ closeOnPress = true,
+ onPress: OnPressProp,
+ ...props
+ },
+ ref,
+ ) => {
const { open, onOpenChange } = useRootContext();
function onPress(ev: GestureResponderEvent) {
@@ -120,49 +151,53 @@ const Overlay = React.forwardRef;
- }
+ },
);
-Overlay.displayName = 'OverlayNativeDialog';
+Overlay.displayName = "OverlayNativeDialog";
-const Content = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const { open, nativeID, onOpenChange } = useRootContext();
-
- React.useEffect(() => {
- const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
+const Content = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DialogContentProps
+>(({ asChild, forceMount, ...props }, ref) => {
+ const { open, nativeID, onOpenChange } = useRootContext();
+
+ React.useEffect(() => {
+ const backHandler = BackHandler.addEventListener(
+ "hardwareBackPress",
+ () => {
onOpenChange(false);
return true;
- });
+ },
+ );
- return () => {
- backHandler.remove();
- };
- }, []);
+ return () => {
+ backHandler.remove();
+ };
+ }, []);
- if (!forceMount) {
- if (!open) {
- return null;
- }
+ if (!forceMount) {
+ if (!open) {
+ return null;
}
-
- const Component = asChild ? Slot.View : View;
- return (
-
- );
}
-);
-Content.displayName = 'ContentNativeDialog';
+ const Component = asChild ? Slot.View : View;
+ return (
+
+ );
+});
+
+Content.displayName = "ContentNativeDialog";
const Close = React.forwardRef(
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
@@ -179,32 +214,46 @@ const Close = React.forwardRef(
);
- }
+ },
);
-Close.displayName = 'CloseNativeDialog';
+Close.displayName = "CloseNativeDialog";
const Title = React.forwardRef((props, ref) => {
const { nativeID } = useRootContext();
- return ;
+ return (
+
+ );
});
-Title.displayName = 'TitleNativeDialog';
+Title.displayName = "TitleNativeDialog";
-const Description = React.forwardRef((props, ref) => {
- const { nativeID } = useRootContext();
- return ;
-});
-
-Description.displayName = 'DescriptionNativeDialog';
+const Description = React.forwardRef(
+ (props, ref) => {
+ const { nativeID } = useRootContext();
+ return ;
+ },
+);
-export { Close, Content, Description, Overlay, Portal, Root, Title, Trigger, useRootContext };
+Description.displayName = "DescriptionNativeDialog";
+
+export {
+ Close,
+ Content,
+ Description,
+ Overlay,
+ Portal,
+ Root,
+ Title,
+ Trigger,
+ useRootContext,
+};
function onStartShouldSetResponder() {
return true;
diff --git a/components/primitives/dialog/dialog.web.tsx b/components/primitives/dialog/dialog.web.tsx
index 6af6b33..9b64468 100644
--- a/components/primitives/dialog/dialog.web.tsx
+++ b/components/primitives/dialog/dialog.web.tsx
@@ -1,6 +1,12 @@
-import * as Dialog from '@radix-ui/react-dialog';
-import { useAugmentedRef, useControllableState } from '../hooks';
-import * as Slot from '~/components/primitives/slot';
+import * as Dialog from "@radix-ui/react-dialog";
+import * as React from "react";
+import {
+ type GestureResponderEvent,
+ Pressable,
+ Text,
+ View,
+} from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
@@ -8,21 +14,29 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import { Pressable, Text, View, type GestureResponderEvent } from 'react-native';
+} from "~/components/primitives/types";
+import { useAugmentedRef, useControllableState } from "../hooks";
import type {
DialogContentProps,
DialogOverlayProps,
DialogPortalProps,
DialogRootProps,
RootContext,
-} from './types';
+} from "./types";
const DialogContext = React.createContext(null);
const Root = React.forwardRef(
- ({ asChild, open: openProp, defaultOpen, onOpenChange: onOpenChangeProp, ...viewProps }, ref) => {
+ (
+ {
+ asChild,
+ open: openProp,
+ defaultOpen,
+ onOpenChange: onOpenChangeProp,
+ ...viewProps
+ },
+ ref,
+ ) => {
const [open = false, onOpenChange] = useControllableState({
prop: openProp,
defaultProp: defaultOpen,
@@ -31,20 +45,26 @@ const Root = React.forwardRef(
const Component = asChild ? Slot.View : View;
return (
-
+
);
- }
+ },
);
-Root.displayName = 'RootWebDialog';
+Root.displayName = "RootWebDialog";
function useRootContext() {
const context = React.useContext(DialogContext);
if (!context) {
- throw new Error('Dialog compound components cannot be rendered outside the Dialog component');
+ throw new Error(
+ "Dialog compound components cannot be rendered outside the Dialog component",
+ );
}
return context;
}
@@ -63,8 +83,8 @@ const Trigger = React.forwardRef(
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
- augRef.dataset.state = open ? 'open' : 'closed';
- augRef.type = 'button';
+ augRef.dataset.state = open ? "open" : "closed";
+ augRef.type = "button";
}
}, [open]);
@@ -74,35 +94,45 @@ const Trigger = React.forwardRef(
);
- }
+ },
);
-Trigger.displayName = 'TriggerWebDialog';
+Trigger.displayName = "TriggerWebDialog";
function Portal({ forceMount, container, children }: DialogPortalProps) {
- return ;
+ return (
+
+ );
}
-const Overlay = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.Pressable : Pressable;
- return (
-
-
-
- );
- }
-);
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DialogOverlayProps
+>(({ asChild, forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return (
+
+
+
+ );
+});
-Overlay.displayName = 'OverlayWebDialog';
+Overlay.displayName = "OverlayWebDialog";
-const Content = React.forwardRef(
+const Content = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DialogContentProps
+>(
(
{
asChild,
@@ -114,7 +144,7 @@ const Content = React.forwardRef {
const Component = asChild ? Slot.View : View;
return (
@@ -129,10 +159,10 @@ const Content = React.forwardRef
);
- }
+ },
);
-Content.displayName = 'ContentWebDialog';
+Content.displayName = "ContentWebDialog";
const Close = React.forwardRef(
({ asChild, onPress: onPressProp, disabled, ...props }, ref) => {
@@ -149,7 +179,7 @@ const Close = React.forwardRef(
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
- augRef.type = 'button';
+ augRef.type = "button";
}
}, []);
@@ -160,38 +190,52 @@ const Close = React.forwardRef(
>
);
- }
+ },
);
-Close.displayName = 'CloseWebDialog';
-
-const Title = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
- return (
-
-
-
- );
-});
+Close.displayName = "CloseWebDialog";
-Title.displayName = 'TitleWebDialog';
+const Title = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return (
+
+
+
+ );
+ },
+);
-const Description = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
- return (
-
-
-
- );
-});
+Title.displayName = "TitleWebDialog";
-Description.displayName = 'DescriptionWebDialog';
+const Description = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return (
+
+
+
+ );
+ },
+);
-export { Close, Content, Description, Overlay, Portal, Root, Title, Trigger, useRootContext };
+Description.displayName = "DescriptionWebDialog";
+
+export {
+ Close,
+ Content,
+ Description,
+ Overlay,
+ Portal,
+ Root,
+ Title,
+ Trigger,
+ useRootContext,
+};
diff --git a/components/primitives/dialog/index.ts b/components/primitives/dialog/index.ts
index 20da8e5..e5c2874 100644
--- a/components/primitives/dialog/index.ts
+++ b/components/primitives/dialog/index.ts
@@ -1 +1 @@
-export * from './dialog';
+export * from "./dialog";
diff --git a/components/primitives/dialog/types.ts b/components/primitives/dialog/types.ts
index 439a868..da599c8 100644
--- a/components/primitives/dialog/types.ts
+++ b/components/primitives/dialog/types.ts
@@ -1,4 +1,4 @@
-import type { ForceMountable } from '~/components/primitives/types';
+import type { ForceMountable } from "~/components/primitives/types";
type RootContext = {
open: boolean;
diff --git a/components/primitives/dropdown-menu/dropdown-menu.tsx b/components/primitives/dropdown-menu/dropdown-menu.tsx
index 279fbfb..dcacfa6 100644
--- a/components/primitives/dropdown-menu/dropdown-menu.tsx
+++ b/components/primitives/dropdown-menu/dropdown-menu.tsx
@@ -1,16 +1,19 @@
-import * as React from 'react';
+import * as React from "react";
import {
BackHandler,
- Pressable,
- Text,
- View,
type GestureResponderEvent,
type LayoutChangeEvent,
type LayoutRectangle,
-} from 'react-native';
-import { useRelativePosition, type LayoutPosition } from '~/components/primitives/hooks';
-import { Portal as RNPPortal } from '~/components/primitives/portal';
-import * as Slot from '~/components/primitives/slot';
+ Pressable,
+ Text,
+ View,
+} from "react-native";
+import {
+ type LayoutPosition,
+ useRelativePosition,
+} from "~/components/primitives/hooks";
+import { Portal as RNPPortal } from "~/components/primitives/portal";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PositionedContentProps,
@@ -20,7 +23,7 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
+} from "~/components/primitives/types";
import type {
DropdownMenuCheckboxItemProps,
DropdownMenuItemProps,
@@ -32,7 +35,7 @@ import type {
DropdownMenuSeparatorProps,
DropdownMenuSubProps,
DropdownMenuSubTriggerProps,
-} from './types';
+} from "./types";
interface IRootContext extends DropdownMenuRootProps {
triggerPosition: LayoutPosition | null;
@@ -44,38 +47,41 @@ interface IRootContext extends DropdownMenuRootProps {
const RootContext = React.createContext(null);
-const Root = React.forwardRef(
- ({ asChild, open, onOpenChange, ...viewProps }, ref) => {
- const nativeID = React.useId();
- const [triggerPosition, setTriggerPosition] = React.useState(null);
- const [contentLayout, setContentLayout] = React.useState(null);
+const Root = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuRootProps
+>(({ asChild, open, onOpenChange, ...viewProps }, ref) => {
+ const nativeID = React.useId();
+ const [triggerPosition, setTriggerPosition] =
+ React.useState(null);
+ const [contentLayout, setContentLayout] =
+ React.useState(null);
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-Root.displayName = 'RootNativeDropdownMenu';
+Root.displayName = "RootNativeDropdownMenu";
function useRootContext() {
const context = React.useContext(RootContext);
if (!context) {
throw new Error(
- 'DropdownMenu compound components cannot be rendered outside the DropdownMenu component'
+ "DropdownMenu compound components cannot be rendered outside the DropdownMenu component",
);
}
return context;
@@ -94,7 +100,7 @@ const Trigger = React.forwardRef(
}
return triggerRef.current;
},
- [triggerRef.current]
+ [triggerRef.current],
);
function onPress(ev: GestureResponderEvent) {
@@ -112,17 +118,17 @@ const Trigger = React.forwardRef(
);
- }
+ },
);
-Trigger.displayName = 'TriggerNativeDropdownMenu';
+Trigger.displayName = "TriggerNativeDropdownMenu";
/**
* @warning when using a custom ``, you might have to adjust the Content's sideOffset to account for nav elements like headers.
@@ -147,9 +153,22 @@ function Portal({ forceMount, hostName, children }: DropdownMenuPortalProps) {
);
}
-const Overlay = React.forwardRef(
- ({ asChild, forceMount, onPress: OnPressProp, closeOnPress = true, ...props }, ref) => {
- const { open, onOpenChange, setContentLayout, setTriggerPosition } = useRootContext();
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DropdownMenuOverlayProps
+>(
+ (
+ {
+ asChild,
+ forceMount,
+ onPress: OnPressProp,
+ closeOnPress = true,
+ ...props
+ },
+ ref,
+ ) => {
+ const { open, onOpenChange, setContentLayout, setTriggerPosition } =
+ useRootContext();
function onPress(ev: GestureResponderEvent) {
if (closeOnPress) {
@@ -168,21 +187,24 @@ const Overlay = React.forwardRef;
- }
+ },
);
-Overlay.displayName = 'OverlayNativeDropdownMenu';
+Overlay.displayName = "OverlayNativeDropdownMenu";
/**
* @info `position`, `top`, `left`, and `maxWidth` style properties are controlled internally. Opt out of this behavior by setting `disablePositioningStyle` to `true`.
*/
-const Content = React.forwardRef(
+const Content = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & PositionedContentProps
+>(
(
{
asChild = false,
forceMount,
- align = 'start',
- side = 'bottom',
+ align = "start",
+ side = "bottom",
sideOffset = 0,
alignOffset = 0,
avoidCollisions = true,
@@ -192,7 +214,7 @@ const Content = React.forwardRef {
const {
open,
@@ -205,12 +227,15 @@ const Content = React.forwardRef {
- const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
- setTriggerPosition(null);
- setContentLayout(null);
- onOpenChange(false);
- return true;
- });
+ const backHandler = BackHandler.addEventListener(
+ "hardwareBackPress",
+ () => {
+ setTriggerPosition(null);
+ setContentLayout(null);
+ onOpenChange(false);
+ return true;
+ },
+ );
return () => {
setContentLayout(null);
@@ -245,7 +270,7 @@ const Content = React.forwardRef
);
- }
+ },
);
-Content.displayName = 'ContentNativeDropdownMenu';
+Content.displayName = "ContentNativeDropdownMenu";
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DropdownMenuItemProps
+>(
(
- { asChild, textValue, onPress: onPressProp, disabled = false, closeOnPress = true, ...props },
- ref
+ {
+ asChild,
+ textValue,
+ onPress: onPressProp,
+ disabled = false,
+ closeOnPress = true,
+ ...props
+ },
+ ref,
) => {
- const { onOpenChange, setTriggerPosition, setContentLayout } = useRootContext();
+ const { onOpenChange, setTriggerPosition, setContentLayout } =
+ useRootContext();
function onPress(ev: GestureResponderEvent) {
if (closeOnPress) {
@@ -278,7 +314,7 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemNativeDropdownMenu';
+Item.displayName = "ItemNativeDropdownMenu";
-const Group = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return ;
-});
+const Group = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return ;
+ },
+);
-Group.displayName = 'GroupNativeDropdownMenu';
+Group.displayName = "GroupNativeDropdownMenu";
-const Label = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
- return ;
-});
+const Label = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return ;
+ },
+);
-Label.displayName = 'LabelNativeDropdownMenu';
+Label.displayName = "LabelNativeDropdownMenu";
type FormItemContext =
| { checked: boolean }
@@ -330,9 +370,10 @@ const CheckboxItem = React.forwardRef<
disabled = false,
...props
},
- ref
+ ref,
) => {
- const { onOpenChange, setContentLayout, setTriggerPosition, nativeID } = useRootContext();
+ const { onOpenChange, setContentLayout, setTriggerPosition, nativeID } =
+ useRootContext();
function onPress(ev: GestureResponderEvent) {
onCheckedChange(!checked);
@@ -350,7 +391,7 @@ const CheckboxItem = React.forwardRef<
);
- }
+ },
);
-CheckboxItem.displayName = 'CheckboxItemNativeDropdownMenu';
+CheckboxItem.displayName = "CheckboxItemNativeDropdownMenu";
function useFormItemContext() {
const context = React.useContext(FormItemContext);
if (!context) {
throw new Error(
- 'CheckboxItem or RadioItem compound components cannot be rendered outside of a CheckboxItem or RadioItem component'
+ "CheckboxItem or RadioItem compound components cannot be rendered outside of a CheckboxItem or RadioItem component",
);
}
return context;
}
-const RadioGroup = React.forwardRef(
- ({ asChild, value, onValueChange, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+const RadioGroup = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuRadioGroupProps
+>(({ asChild, value, onValueChange, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-RadioGroup.displayName = 'RadioGroupNativeDropdownMenu';
+RadioGroup.displayName = "RadioGroupNativeDropdownMenu";
type BothFormItemContext = Exclude & {
checked: boolean;
@@ -409,11 +451,13 @@ const RadioItem = React.forwardRef<
closeOnPress = true,
...props
},
- ref
+ ref,
) => {
- const { onOpenChange, setContentLayout, setTriggerPosition } = useRootContext();
+ const { onOpenChange, setContentLayout, setTriggerPosition } =
+ useRootContext();
- const { value, onValueChange } = useFormItemContext() as BothFormItemContext;
+ const { value, onValueChange } =
+ useFormItemContext() as BothFormItemContext;
function onPress(ev: GestureResponderEvent) {
onValueChange(itemValue);
if (closeOnPress) {
@@ -430,7 +474,7 @@ const RadioItem = React.forwardRef<
);
- }
+ },
);
-RadioItem.displayName = 'RadioItemNativeDropdownMenu';
+RadioItem.displayName = "RadioItemNativeDropdownMenu";
function useItemIndicatorContext() {
return React.useContext(RadioItemContext);
}
-const ItemIndicator = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const { itemValue } = useItemIndicatorContext();
- const { checked, value } = useFormItemContext() as BothFormItemContext;
+const ItemIndicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount, ...props }, ref) => {
+ const { itemValue } = useItemIndicatorContext();
+ const { checked, value } = useFormItemContext() as BothFormItemContext;
- if (!forceMount) {
- if (itemValue == null && !checked) {
- return null;
- }
- if (value !== itemValue) {
- return null;
- }
+ if (!forceMount) {
+ if (itemValue == null && !checked) {
+ return null;
+ }
+ if (value !== itemValue) {
+ return null;
}
- const Component = asChild ? Slot.View : View;
- return ;
}
-);
+ const Component = asChild ? Slot.View : View;
+ return ;
+});
-ItemIndicator.displayName = 'ItemIndicatorNativeDropdownMenu';
+ItemIndicator.displayName = "ItemIndicatorNativeDropdownMenu";
-const Separator = React.forwardRef(
- ({ asChild, decorative, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return ;
- }
-);
+const Separator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuSeparatorProps
+>(({ asChild, decorative, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+ );
+});
-Separator.displayName = 'SeparatorNativeDropdownMenu';
+Separator.displayName = "SeparatorNativeDropdownMenu";
const SubContext = React.createContext<{
nativeID: string;
@@ -486,31 +538,34 @@ const SubContext = React.createContext<{
onOpenChange: (value: boolean) => void;
} | null>(null);
-const Sub = React.forwardRef(
- ({ asChild, open, onOpenChange, ...props }, ref) => {
- const nativeID = React.useId();
+const Sub = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuSubProps
+>(({ asChild, open, onOpenChange, ...props }, ref) => {
+ const nativeID = React.useId();
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-Sub.displayName = 'SubNativeDropdownMenu';
+Sub.displayName = "SubNativeDropdownMenu";
function useSubContext() {
const context = React.useContext(SubContext);
if (!context) {
- throw new Error('Sub compound components cannot be rendered outside of a Sub component');
+ throw new Error(
+ "Sub compound components cannot be rendered outside of a Sub component",
+ );
}
return context;
}
@@ -518,49 +573,57 @@ function useSubContext() {
const SubTrigger = React.forwardRef<
PressableRef,
SlottablePressableProps & DropdownMenuSubTriggerProps
->(({ asChild, textValue, onPress: onPressProp, disabled = false, ...props }, ref) => {
- const { nativeID, open, onOpenChange } = useSubContext();
+>(
+ (
+ { asChild, textValue, onPress: onPressProp, disabled = false, ...props },
+ ref,
+ ) => {
+ const { nativeID, open, onOpenChange } = useSubContext();
- function onPress(ev: GestureResponderEvent) {
- onOpenChange(!open);
- onPressProp?.(ev);
- }
+ function onPress(ev: GestureResponderEvent) {
+ onOpenChange(!open);
+ onPressProp?.(ev);
+ }
- const Component = asChild ? Slot.Pressable : Pressable;
- return (
-
- );
-});
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return (
+
+ );
+ },
+);
-SubTrigger.displayName = 'SubTriggerNativeDropdownMenu';
+SubTrigger.displayName = "SubTriggerNativeDropdownMenu";
-const SubContent = React.forwardRef(
- ({ asChild = false, forceMount, ...props }, ref) => {
- const { open, nativeID } = useSubContext();
+const SubContent = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ForceMountable
+>(({ asChild = false, forceMount, ...props }, ref) => {
+ const { open, nativeID } = useSubContext();
- if (!forceMount) {
- if (!open) {
- return null;
- }
+ if (!forceMount) {
+ if (!open) {
+ return null;
}
-
- const Component = asChild ? Slot.Pressable : Pressable;
- return ;
}
-);
-Content.displayName = 'ContentNativeDropdownMenu';
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return (
+
+ );
+});
+
+Content.displayName = "ContentNativeDropdownMenu";
export {
CheckboxItem,
diff --git a/components/primitives/dropdown-menu/dropdown-menu.web.tsx b/components/primitives/dropdown-menu/dropdown-menu.web.tsx
index d168c24..3825a01 100644
--- a/components/primitives/dropdown-menu/dropdown-menu.web.tsx
+++ b/components/primitives/dropdown-menu/dropdown-menu.web.tsx
@@ -1,8 +1,8 @@
-import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
-import * as React from 'react';
-import { GestureResponderEvent, Pressable, Text, View } from 'react-native';
-import { useAugmentedRef } from '~/components/primitives/hooks';
-import * as Slot from '~/components/primitives/slot';
+import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
+import * as React from "react";
+import { GestureResponderEvent, Pressable, Text, View } from "react-native";
+import { useAugmentedRef } from "~/components/primitives/hooks";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PositionedContentProps,
@@ -12,8 +12,8 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
-import { EmptyGestureResponderEvent } from '~/components/primitives/utils';
+} from "~/components/primitives/types";
+import { EmptyGestureResponderEvent } from "~/components/primitives/utils";
import type {
DropdownMenuCheckboxItemProps,
DropdownMenuItemProps,
@@ -25,30 +25,33 @@ import type {
DropdownMenuSeparatorProps,
DropdownMenuSubProps,
DropdownMenuSubTriggerProps,
-} from './types';
+} from "./types";
-const DropdownMenuContext = React.createContext(null);
-
-const Root = React.forwardRef(
- ({ asChild, open, onOpenChange, ...viewProps }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
-
-
- );
- }
+const DropdownMenuContext = React.createContext(
+ null,
);
-Root.displayName = 'RootWebDropdownMenu';
+const Root = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuRootProps
+>(({ asChild, open, onOpenChange, ...viewProps }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+
+
+ );
+});
+
+Root.displayName = "RootWebDropdownMenu";
function useRootContext() {
const context = React.useContext(DropdownMenuContext);
if (!context) {
throw new Error(
- 'DropdownMenu compound components cannot be rendered outside the DropdownMenu component'
+ "DropdownMenu compound components cannot be rendered outside the DropdownMenu component",
);
}
return context;
@@ -62,7 +65,7 @@ const Trigger = React.forwardRef(
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
- augRef.dataset.state = open ? 'open' : 'closed';
+ augRef.dataset.state = open ? "open" : "closed";
}
}, [open]);
@@ -70,7 +73,7 @@ const Trigger = React.forwardRef(
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
if (disabled) {
- augRef.dataset.disabled = 'true';
+ augRef.dataset.disabled = "true";
} else {
augRef.dataset.disabled = undefined;
}
@@ -83,29 +86,39 @@ const Trigger = React.forwardRef(
);
- }
+ },
);
-Trigger.displayName = 'TriggerWebDropdownMenu';
+Trigger.displayName = "TriggerWebDropdownMenu";
function Portal({ forceMount, container, children }: DropdownMenuPortalProps) {
- return ;
+ return (
+
+ );
}
-const Overlay = React.forwardRef(
- ({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Pressable : Pressable;
- return ;
- }
-);
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DropdownMenuOverlayProps
+>(({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return ;
+});
-Overlay.displayName = 'OverlayWebDropdownMenu';
+Overlay.displayName = "OverlayWebDropdownMenu";
const DropdownMenuContentContext = React.createContext<{
close: () => void;
} | null>(null);
-const Content = React.forwardRef(
+const Content = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & PositionedContentProps
+>(
(
{
asChild = false,
@@ -127,7 +140,7 @@ const Content = React.forwardRef {
const itemRef = React.useRef(null);
@@ -159,7 +172,7 @@ const Content = React.forwardRef
);
- }
+ },
);
-Content.displayName = 'ContentWebDropdownMenu';
+Content.displayName = "ContentWebDropdownMenu";
function useDropdownMenuContentContext() {
const context = React.useContext(DropdownMenuContentContext);
if (!context) {
throw new Error(
- 'DropdownMenu compound components cannot be rendered outside the DropdownMenu component'
+ "DropdownMenu compound components cannot be rendered outside the DropdownMenu component",
);
}
return context;
}
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & DropdownMenuItemProps
+>(
(
{
asChild,
@@ -192,13 +208,13 @@ const Item = React.forwardRef {
const { close } = useDropdownMenuContentContext();
function onKeyDown(ev: React.KeyboardEvent) {
onKeyDownProp?.(ev);
- if (ev.key === 'Enter' || ev.key === ' ') {
+ if (ev.key === "Enter" || ev.key === " ") {
onPressProp?.(EmptyGestureResponderEvent);
if (closeOnPress) {
close();
@@ -230,32 +246,36 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemWebDropdownMenu';
+Item.displayName = "ItemWebDropdownMenu";
-const Group = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
-});
+const Group = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+ },
+);
-Group.displayName = 'GroupWebDropdownMenu';
+Group.displayName = "GroupWebDropdownMenu";
-const Label = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
- return (
-
-
-
- );
-});
+const Label = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return (
+
+
+
+ );
+ },
+);
-Label.displayName = 'LabelWebDropdownMenu';
+Label.displayName = "LabelWebDropdownMenu";
const CheckboxItem = React.forwardRef<
PressableRef,
@@ -273,13 +293,13 @@ const CheckboxItem = React.forwardRef<
onKeyDown: onKeyDownProp,
...props
},
- ref
+ ref,
) => {
const { close } = useDropdownMenuContentContext();
function onKeyDown(ev: React.KeyboardEvent) {
onKeyDownProp?.(ev);
- if (ev.key === 'Enter' || ev.key === ' ') {
+ if (ev.key === "Enter" || ev.key === " ") {
onPressProp?.(EmptyGestureResponderEvent);
onCheckedChange?.(!checked);
if (closeOnPress) {
@@ -310,41 +330,46 @@ const CheckboxItem = React.forwardRef<
// @ts-expect-error web only
onKeyDown={onKeyDown}
onPress={onPress}
- role='button'
+ role="button"
{...props}
/>
);
- }
+ },
);
-CheckboxItem.displayName = 'CheckboxItemWebDropdownMenu';
+CheckboxItem.displayName = "CheckboxItemWebDropdownMenu";
const DropdownMenuRadioGroupContext = React.createContext<{
value?: string;
onValueChange?: (value: string) => void;
} | null>(null);
-const RadioGroup = React.forwardRef(
- ({ asChild, value, onValueChange, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
-
-
- );
- }
-);
+const RadioGroup = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuRadioGroupProps
+>(({ asChild, value, onValueChange, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+
+
+ );
+});
-RadioGroup.displayName = 'RadioGroupWebDropdownMenu';
+RadioGroup.displayName = "RadioGroupWebDropdownMenu";
function useDropdownMenuRadioGroupContext() {
const context = React.useContext(DropdownMenuRadioGroupContext);
if (!context) {
throw new Error(
- 'DropdownMenuRadioGroup compound components cannot be rendered outside the DropdownMenuRadioGroup component'
+ "DropdownMenuRadioGroup compound components cannot be rendered outside the DropdownMenuRadioGroup component",
);
}
return context;
@@ -364,14 +389,14 @@ const RadioItem = React.forwardRef<
onKeyDown: onKeyDownProp,
...props
},
- ref
+ ref,
) => {
const { onValueChange } = useDropdownMenuRadioGroupContext();
const { close } = useDropdownMenuContentContext();
function onKeyDown(ev: React.KeyboardEvent) {
onKeyDownProp?.(ev);
- if (ev.key === 'Enter' || ev.key === ' ') {
+ if (ev.key === "Enter" || ev.key === " ") {
onValueChange?.(value);
onPressProp?.(EmptyGestureResponderEvent);
if (closeOnPress) {
@@ -405,62 +430,65 @@ const RadioItem = React.forwardRef<
/>
);
- }
+ },
);
-RadioItem.displayName = 'RadioItemWebDropdownMenu';
+RadioItem.displayName = "RadioItemWebDropdownMenu";
-const ItemIndicator = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+const ItemIndicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-ItemIndicator.displayName = 'ItemIndicatorWebDropdownMenu';
+ItemIndicator.displayName = "ItemIndicatorWebDropdownMenu";
-const Separator = React.forwardRef(
- ({ asChild, decorative, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+const Separator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuSeparatorProps
+>(({ asChild, decorative, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-Separator.displayName = 'SeparatorWebDropdownMenu';
+Separator.displayName = "SeparatorWebDropdownMenu";
const DropdownMenuSubContext = React.createContext<{
open: boolean;
onOpenChange: (open: boolean) => void;
} | null>(null);
-const Sub = React.forwardRef(
- ({ asChild, open, onOpenChange, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
-
-
- );
- }
-);
+const Sub = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & DropdownMenuSubProps
+>(({ asChild, open, onOpenChange, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+
+
+ );
+});
-Sub.displayName = 'SubWebDropdownMenu';
+Sub.displayName = "SubWebDropdownMenu";
function useSubContext() {
const context = React.useContext(DropdownMenuSubContext);
if (!context) {
throw new Error(
- 'DropdownMenu compound components cannot be rendered outside the DropdownMenu component'
+ "DropdownMenu compound components cannot be rendered outside the DropdownMenu component",
);
}
return context;
@@ -472,28 +500,33 @@ const SubTrigger = React.forwardRef<
>(({ asChild, textValue, disabled = false, ...props }, ref) => {
const Component = asChild ? Slot.Pressable : Pressable;
return (
-
+
);
});
-SubTrigger.displayName = 'SubTriggerWebDropdownMenu';
+SubTrigger.displayName = "SubTriggerWebDropdownMenu";
-const SubContent = React.forwardRef(
- ({ asChild = false, forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.Pressable : Pressable;
- return (
-
-
-
-
-
- );
- }
-);
+const SubContent = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ForceMountable
+>(({ asChild = false, forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return (
+
+
+
+
+
+ );
+});
-Content.displayName = 'ContentWebDropdownMenu';
+Content.displayName = "ContentWebDropdownMenu";
export {
CheckboxItem,
diff --git a/components/primitives/dropdown-menu/index.ts b/components/primitives/dropdown-menu/index.ts
index 2759d3c..10ff970 100644
--- a/components/primitives/dropdown-menu/index.ts
+++ b/components/primitives/dropdown-menu/index.ts
@@ -1 +1 @@
-export * from './dropdown-menu';
+export * from "./dropdown-menu";
diff --git a/components/primitives/dropdown-menu/types.ts b/components/primitives/dropdown-menu/types.ts
index d6cf9a1..1dcd971 100644
--- a/components/primitives/dropdown-menu/types.ts
+++ b/components/primitives/dropdown-menu/types.ts
@@ -1,4 +1,4 @@
-import type { ForceMountable } from '~/components/primitives/types';
+import type { ForceMountable } from "~/components/primitives/types";
interface DropdownMenuRootProps {
open: boolean;
diff --git a/components/primitives/hooks/index.ts b/components/primitives/hooks/index.ts
index 58c0d1b..4ebce6a 100644
--- a/components/primitives/hooks/index.ts
+++ b/components/primitives/hooks/index.ts
@@ -1,3 +1,6 @@
-export { useAugmentedRef } from './useAugmentedRef';
-export { useRelativePosition, type LayoutPosition } from './useRelativePosition';
-export { useControllableState } from './useControllableState';
+export { useAugmentedRef } from "./useAugmentedRef";
+export {
+ useRelativePosition,
+ type LayoutPosition,
+} from "./useRelativePosition";
+export { useControllableState } from "./useControllableState";
diff --git a/components/primitives/hooks/useAugmentedRef.tsx b/components/primitives/hooks/useAugmentedRef.tsx
index 13a5669..e375b18 100644
--- a/components/primitives/hooks/useAugmentedRef.tsx
+++ b/components/primitives/hooks/useAugmentedRef.tsx
@@ -1,4 +1,4 @@
-import * as React from 'react';
+import * as React from "react";
interface AugmentRefProps {
ref: React.Ref;
@@ -15,7 +15,7 @@ export function useAugmentedRef({
React.useImperativeHandle(
ref,
() => {
- if (typeof augmentedRef === 'function' || !augmentedRef?.current) {
+ if (typeof augmentedRef === "function" || !augmentedRef?.current) {
return {} as T;
}
return {
@@ -23,7 +23,7 @@ export function useAugmentedRef({
...methods,
};
},
- deps
+ deps,
);
return augmentedRef;
}
diff --git a/components/primitives/hooks/useControllableState.tsx b/components/primitives/hooks/useControllableState.tsx
index 3b42b53..b941545 100644
--- a/components/primitives/hooks/useControllableState.tsx
+++ b/components/primitives/hooks/useControllableState.tsx
@@ -2,7 +2,7 @@
// The code is licensed under the MIT License.
// https://github.com/radix-ui/primitives/tree/main
-import * as React from 'react';
+import * as React from "react";
type UseControllableStateParams = {
prop?: T | undefined;
@@ -17,23 +17,28 @@ function useControllableState({
defaultProp,
onChange = () => {},
}: UseControllableStateParams) {
- const [uncontrolledProp, setUncontrolledProp] = useUncontrolledState({ defaultProp, onChange });
+ const [uncontrolledProp, setUncontrolledProp] = useUncontrolledState({
+ defaultProp,
+ onChange,
+ });
const isControlled = prop !== undefined;
const value = isControlled ? prop : uncontrolledProp;
const handleChange = useCallbackRef(onChange);
- const setValue: React.Dispatch> = React.useCallback(
- (nextValue) => {
- if (isControlled) {
- const setter = nextValue as SetStateFn;
- const value = typeof nextValue === 'function' ? setter(prop) : nextValue;
- if (value !== prop) handleChange(value as T);
- } else {
- setUncontrolledProp(nextValue);
- }
- },
- [isControlled, prop, setUncontrolledProp, handleChange]
- );
+ const setValue: React.Dispatch> =
+ React.useCallback(
+ (nextValue) => {
+ if (isControlled) {
+ const setter = nextValue as SetStateFn;
+ const value =
+ typeof nextValue === "function" ? setter(prop) : nextValue;
+ if (value !== prop) handleChange(value as T);
+ } else {
+ setUncontrolledProp(nextValue);
+ }
+ },
+ [isControlled, prop, setUncontrolledProp, handleChange],
+ );
return [value, setValue] as const;
}
@@ -41,7 +46,7 @@ function useControllableState({
function useUncontrolledState({
defaultProp,
onChange,
-}: Omit, 'prop'>) {
+}: Omit, "prop">) {
const uncontrolledState = React.useState(defaultProp);
const [value] = uncontrolledState;
const prevValueRef = React.useRef(value);
@@ -61,7 +66,9 @@ function useUncontrolledState({
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
* prop or avoid re-executing effects when passed as a dependency
*/
-function useCallbackRef any>(callback: T | undefined): T {
+function useCallbackRef any>(
+ callback: T | undefined,
+): T {
const callbackRef = React.useRef(callback);
React.useEffect(() => {
@@ -69,7 +76,10 @@ function useCallbackRef any>(callback: T | undefin
});
// https://github.com/facebook/react/issues/19240
- return React.useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);
+ return React.useMemo(
+ () => ((...args) => callbackRef.current?.(...args)) as T,
+ [],
+ );
}
export { useControllableState };
diff --git a/components/primitives/hooks/useRelativePosition.tsx b/components/primitives/hooks/useRelativePosition.tsx
index f1544be..42ae081 100644
--- a/components/primitives/hooks/useRelativePosition.tsx
+++ b/components/primitives/hooks/useRelativePosition.tsx
@@ -1,25 +1,25 @@
-import * as React from 'react';
+import * as React from "react";
import {
- useWindowDimensions,
type LayoutRectangle,
type ScaledSize,
type ViewStyle,
-} from 'react-native';
-import type { Insets } from '~/components/primitives/types';
+ useWindowDimensions,
+} from "react-native";
+import type { Insets } from "~/components/primitives/types";
const POSITION_ABSOLUTE: ViewStyle = {
- position: 'absolute',
+ position: "absolute",
};
const HIDDEN_CONTENT: ViewStyle = {
- position: 'absolute',
+ position: "absolute",
opacity: 0,
zIndex: -9999999,
};
type UseRelativePositionArgs = Omit<
GetContentStyleArgs,
- 'triggerPosition' | 'contentLayout' | 'dimensions'
+ "triggerPosition" | "contentLayout" | "dimensions"
> & {
triggerPosition: LayoutPosition | null;
contentLayout: LayoutRectangle | null;
@@ -75,7 +75,7 @@ interface GetPositionArgs {
}
interface GetSidePositionArgs extends GetPositionArgs {
- side: 'top' | 'bottom';
+ side: "top" | "bottom";
sideOffset: number;
}
@@ -90,28 +90,33 @@ function getSidePosition({
}: GetSidePositionArgs) {
const insetTop = insets?.top ?? 0;
const insetBottom = insets?.bottom ?? 0;
- const positionTop = triggerPosition?.pageY - sideOffset - contentLayout.height;
- const positionBottom = triggerPosition.pageY + triggerPosition.height + sideOffset;
+ const positionTop =
+ triggerPosition?.pageY - sideOffset - contentLayout.height;
+ const positionBottom =
+ triggerPosition.pageY + triggerPosition.height + sideOffset;
if (!avoidCollisions) {
return {
- top: side === 'top' ? positionTop : positionBottom,
+ top: side === "top" ? positionTop : positionBottom,
};
}
- if (side === 'top') {
+ if (side === "top") {
return {
top: Math.max(insetTop, positionTop),
};
}
return {
- top: Math.min(dimensions.height - insetBottom - contentLayout.height, positionBottom),
+ top: Math.min(
+ dimensions.height - insetBottom - contentLayout.height,
+ positionBottom,
+ ),
};
}
interface GetAlignPositionArgs extends GetPositionArgs {
- align: 'start' | 'center' | 'end';
+ align: "start" | "center" | "end";
alignOffset: number;
}
@@ -138,11 +143,12 @@ function getAlignPosition({
alignOffset,
insetLeft,
insetRight,
- dimensions
+ dimensions,
);
if (avoidCollisions) {
- const doesCollide = left < insetLeft || left + contentWidth > dimensions.width - insetRight;
+ const doesCollide =
+ left < insetLeft || left + contentWidth > dimensions.width - insetRight;
if (doesCollide) {
const spaceLeft = left - insetLeft;
const spaceRight = dimensions.width - insetRight - (left + contentWidth);
@@ -154,7 +160,7 @@ function getAlignPosition({
} else {
const centeredPosition = Math.max(
insetLeft,
- (dimensions.width - contentWidth - insetRight) / 2
+ (dimensions.width - contentWidth - insetRight) / 2,
);
left = centeredPosition;
}
@@ -165,32 +171,34 @@ function getAlignPosition({
}
function getLeftPosition(
- align: 'start' | 'center' | 'end',
+ align: "start" | "center" | "end",
triggerPageX: number,
triggerWidth: number,
contentWidth: number,
alignOffset: number,
insetLeft: number,
insetRight: number,
- dimensions: ScaledSize
+ dimensions: ScaledSize,
) {
let left = 0;
- if (align === 'start') {
+ if (align === "start") {
left = triggerPageX;
}
- if (align === 'center') {
+ if (align === "center") {
left = triggerPageX + triggerWidth / 2 - contentWidth / 2;
}
- if (align === 'end') {
+ if (align === "end") {
left = triggerPageX + triggerWidth - contentWidth;
}
return Math.max(
insetLeft,
- Math.min(left + alignOffset, dimensions.width - contentWidth - insetRight)
+ Math.min(left + alignOffset, dimensions.width - contentWidth - insetRight),
);
}
-type GetContentStyleArgs = GetPositionArgs & GetSidePositionArgs & GetAlignPositionArgs;
+type GetContentStyleArgs = GetPositionArgs &
+ GetSidePositionArgs &
+ GetAlignPositionArgs;
function getContentStyle({
align,
@@ -222,6 +230,6 @@ function getContentStyle({
alignOffset,
insets,
dimensions,
- })
+ }),
);
}
diff --git a/components/primitives/label/index.ts b/components/primitives/label/index.ts
index 301fbde..c8a3baf 100644
--- a/components/primitives/label/index.ts
+++ b/components/primitives/label/index.ts
@@ -1 +1 @@
-export * from './label';
+export * from "./label";
diff --git a/components/primitives/label/label.tsx b/components/primitives/label/label.tsx
index 40b5f7b..429dcb4 100644
--- a/components/primitives/label/label.tsx
+++ b/components/primitives/label/label.tsx
@@ -1,31 +1,32 @@
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import { Pressable, Text as RNText } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableTextProps,
TextRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import { Pressable, Text as RNText } from 'react-native';
-import type { LabelRootProps, LabelTextProps } from './types';
+} from "~/components/primitives/types";
+import type { LabelRootProps, LabelTextProps } from "./types";
const Root = React.forwardRef<
PressableRef,
- Omit & LabelRootProps
+ Omit &
+ LabelRootProps
>(({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.Pressable : Pressable;
return ;
});
-Root.displayName = 'RootNativeLabel';
+Root.displayName = "RootNativeLabel";
const Text = React.forwardRef(
({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.Text : RNText;
return ;
- }
+ },
);
-Text.displayName = 'TextNativeLabel';
+Text.displayName = "TextNativeLabel";
export { Root, Text };
diff --git a/components/primitives/label/label.web.tsx b/components/primitives/label/label.web.tsx
index e17768f..f8f15c2 100644
--- a/components/primitives/label/label.web.tsx
+++ b/components/primitives/label/label.web.tsx
@@ -1,24 +1,25 @@
-import * as Label from '@radix-ui/react-label';
-import * as Slot from '~/components/primitives/slot';
+import * as Label from "@radix-ui/react-label";
+import * as React from "react";
+import { Text as RNText } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableTextProps,
TextRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import { Text as RNText } from 'react-native';
-import type { LabelRootProps, LabelTextProps } from './types';
+} from "~/components/primitives/types";
+import type { LabelRootProps, LabelTextProps } from "./types";
const Root = React.forwardRef<
PressableRef,
- Omit & LabelRootProps
+ Omit &
+ LabelRootProps
>(({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.View : Slot.View;
return ;
});
-Root.displayName = 'RootWebLabel';
+Root.displayName = "RootWebLabel";
const Text = React.forwardRef(
({ asChild, nativeID, ...props }, ref) => {
@@ -28,9 +29,9 @@ const Text = React.forwardRef(
);
- }
+ },
);
-Text.displayName = 'TextWebLabel';
+Text.displayName = "TextWebLabel";
export { Root, Text };
diff --git a/components/primitives/label/types.ts b/components/primitives/label/types.ts
index d3b273c..969cdfe 100644
--- a/components/primitives/label/types.ts
+++ b/components/primitives/label/types.ts
@@ -1,4 +1,4 @@
-import type { ViewStyle } from 'react-native';
+import type { ViewStyle } from "react-native";
interface LabelRootProps {
children: React.ReactNode;
diff --git a/components/primitives/portal.tsx b/components/primitives/portal.tsx
index bd3ede8..0743a5a 100644
--- a/components/primitives/portal.tsx
+++ b/components/primitives/portal.tsx
@@ -1,17 +1,24 @@
-import * as React from 'react';
-import { Platform, type View, type ViewStyle } from 'react-native';
-import { create } from 'zustand';
+import * as React from "react";
+import { Platform, type View, type ViewStyle } from "react-native";
+import { create } from "zustand";
-const DEFAULT_PORTAL_HOST = 'INTERNAL_PRIMITIVE_DEFAULT_HOST_NAME';
+const DEFAULT_PORTAL_HOST = "INTERNAL_PRIMITIVE_DEFAULT_HOST_NAME";
type PortalMap = Map;
type PortalHostMap = Map;
const usePortal = create<{ map: PortalHostMap }>(() => ({
- map: new Map().set(DEFAULT_PORTAL_HOST, new Map()),
+ map: new Map().set(
+ DEFAULT_PORTAL_HOST,
+ new Map(),
+ ),
}));
-const updatePortal = (hostName: string, name: string, children: React.ReactNode) => {
+const updatePortal = (
+ hostName: string,
+ name: string,
+ children: React.ReactNode,
+) => {
usePortal.setState((prev) => {
const next = new Map(prev.map);
const portal = next.get(hostName) ?? new Map();
@@ -31,7 +38,9 @@ const removePortal = (hostName: string, name: string) => {
};
export function PortalHost({ name = DEFAULT_PORTAL_HOST }: { name?: string }) {
- const portalMap = usePortal((state) => state.map).get(name) ?? new Map();
+ const portalMap =
+ usePortal((state) => state.map).get(name) ??
+ new Map();
if (portalMap.size === 0) return null;
return <>{Array.from(portalMap.values())}>;
}
@@ -67,7 +76,7 @@ export function useModalPortalRoot() {
const [sideOffset, setSideOffSet] = React.useState(0);
const onLayout = React.useCallback(() => {
- if (Platform.OS === 'web') return;
+ if (Platform.OS === "web") return;
ref.current?.measure((_x, _y, _width, _height, _pageX, pageY) => {
setSideOffSet(-pageY);
});
diff --git a/components/primitives/progress/index.ts b/components/primitives/progress/index.ts
index 2ee5781..148e959 100644
--- a/components/primitives/progress/index.ts
+++ b/components/primitives/progress/index.ts
@@ -1 +1 @@
-export * from './progress';
+export * from "./progress";
diff --git a/components/primitives/progress/progress.tsx b/components/primitives/progress/progress.tsx
index ff404f0..9cbf6b8 100644
--- a/components/primitives/progress/progress.tsx
+++ b/components/primitives/progress/progress.tsx
@@ -1,8 +1,8 @@
-import * as React from 'react';
-import { View } from 'react-native';
-import * as Slot from '../slot';
-import type { SlottableViewProps, ViewRef } from '../types';
-import type { ProgressRootProps } from './types';
+import * as React from "react";
+import { View } from "react-native";
+import * as Slot from "../slot";
+import type { SlottableViewProps, ViewRef } from "../types";
+import type { ProgressRootProps } from "./types";
// This project uses code from WorkOS/Radix Primitives.
// The code is licensed under the MIT License.
@@ -12,8 +12,14 @@ const DEFAULT_MAX = 100;
const Root = React.forwardRef(
(
- { asChild, value: valueProp, max: maxProp, getValueLabel = defaultGetValueLabel, ...props },
- ref
+ {
+ asChild,
+ value: valueProp,
+ max: maxProp,
+ getValueLabel = defaultGetValueLabel,
+ ...props
+ },
+ ref,
) => {
const max = maxProp ?? DEFAULT_MAX;
const value = isValidValueNumber(valueProp, max) ? valueProp : 0;
@@ -21,7 +27,7 @@ const Root = React.forwardRef(
const Component = asChild ? Slot.View : View;
return (
(
{...props}
/>
);
- }
+ },
);
-Root.displayName = 'RootProgress';
+Root.displayName = "RootProgress";
-const Indicator = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return ;
-});
+const Indicator = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return ;
+ },
+);
-Indicator.displayName = 'IndicatorProgress';
+Indicator.displayName = "IndicatorProgress";
export { Indicator, Root };
@@ -55,5 +63,7 @@ function defaultGetValueLabel(value: number, max: number) {
}
function isValidValueNumber(value: any, max: number): value is number {
- return typeof value === 'number' && !isNaN(value) && value <= max && value >= 0;
+ return (
+ typeof value === "number" && !isNaN(value) && value <= max && value >= 0
+ );
}
diff --git a/components/primitives/progress/progress.web.tsx b/components/primitives/progress/progress.web.tsx
index ca9fbd1..a96e5ee 100644
--- a/components/primitives/progress/progress.web.tsx
+++ b/components/primitives/progress/progress.web.tsx
@@ -1,9 +1,9 @@
-import * as Progress from '@radix-ui/react-progress';
-import * as React from 'react';
-import { View } from 'react-native';
-import * as Slot from '../slot';
-import type { SlottableViewProps, ViewRef } from '../types';
-import type { ProgressRootProps } from './types';
+import * as Progress from "@radix-ui/react-progress";
+import * as React from "react";
+import { View } from "react-native";
+import * as Slot from "../slot";
+import type { SlottableViewProps, ViewRef } from "../types";
+import type { ProgressRootProps } from "./types";
const ProgressContext = React.createContext(null);
@@ -12,25 +12,32 @@ const Root = React.forwardRef(
const Component = asChild ? Slot.View : View;
return (
-
+
);
- }
+ },
);
-Root.displayName = 'RootProgress';
+Root.displayName = "RootProgress";
-const Indicator = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
-});
+const Indicator = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+ },
+);
-Indicator.displayName = 'IndicatorProgress';
+Indicator.displayName = "IndicatorProgress";
export { Indicator, Root };
diff --git a/components/primitives/progress/types.ts b/components/primitives/progress/types.ts
index da3d070..9ff1c4f 100644
--- a/components/primitives/progress/types.ts
+++ b/components/primitives/progress/types.ts
@@ -1,7 +1,7 @@
interface ProgressRootProps {
- value?: number | null | undefined;
- max?: number;
- getValueLabel?(value: number, max: number): string;
- }
-
- export type { ProgressRootProps };
\ No newline at end of file
+ value?: number | null | undefined;
+ max?: number;
+ getValueLabel?(value: number, max: number): string;
+}
+
+export type { ProgressRootProps };
diff --git a/components/primitives/radio-group/index.ts b/components/primitives/radio-group/index.ts
index ed40543..ffd376c 100644
--- a/components/primitives/radio-group/index.ts
+++ b/components/primitives/radio-group/index.ts
@@ -1 +1 @@
-export * from './radio-group';
+export * from "./radio-group";
diff --git a/components/primitives/radio-group/radio-group.tsx b/components/primitives/radio-group/radio-group.tsx
index 62d6182..c6a6afd 100644
--- a/components/primitives/radio-group/radio-group.tsx
+++ b/components/primitives/radio-group/radio-group.tsx
@@ -1,41 +1,42 @@
-import * as React from 'react';
-import { Pressable, View, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import { type GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import type { RadioGroupItemProps, RadioGroupRootProps } from './types';
+} from "~/components/primitives/types";
+import type { RadioGroupItemProps, RadioGroupRootProps } from "./types";
const RadioGroupContext = React.createContext(null);
-const Root = React.forwardRef(
- ({ asChild, value, onValueChange, disabled = false, ...viewProps }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+const Root = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & RadioGroupRootProps
+>(({ asChild, value, onValueChange, disabled = false, ...viewProps }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-Root.displayName = 'RootRadioGroup';
+Root.displayName = "RootRadioGroup";
function useRadioGroupContext() {
const context = React.useContext(RadioGroupContext);
if (!context) {
throw new Error(
- 'RadioGroup compound components cannot be rendered outside the RadioGroup component'
+ "RadioGroup compound components cannot be rendered outside the RadioGroup component",
);
}
return context;
@@ -47,10 +48,19 @@ interface RadioItemContext {
const RadioItemContext = React.createContext(null);
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & RadioGroupItemProps
+>(
(
- { asChild, value: itemValue, disabled: disabledProp = false, onPress: onPressProp, ...props },
- ref
+ {
+ asChild,
+ value: itemValue,
+ disabled: disabledProp = false,
+ onPress: onPressProp,
+ ...props
+ },
+ ref,
) => {
const { disabled, value, onValueChange } = useRadioGroupContext();
@@ -69,7 +79,7 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemRadioGroup';
+Item.displayName = "ItemRadioGroup";
function useRadioItemContext() {
const context = React.useContext(RadioItemContext);
if (!context) {
throw new Error(
- 'RadioItem compound components cannot be rendered outside the RadioItem component'
+ "RadioItem compound components cannot be rendered outside the RadioItem component",
);
}
return context;
}
-const Indicator = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const { value } = useRadioGroupContext();
- const { itemValue } = useRadioItemContext();
+const Indicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount, ...props }, ref) => {
+ const { value } = useRadioGroupContext();
+ const { itemValue } = useRadioItemContext();
- if (!forceMount) {
- if (value !== itemValue) {
- return null;
- }
+ if (!forceMount) {
+ if (value !== itemValue) {
+ return null;
}
- const Component = asChild ? Slot.View : View;
- return ;
}
-);
+ const Component = asChild ? Slot.View : View;
+ return ;
+});
-Indicator.displayName = 'IndicatorRadioGroup';
+Indicator.displayName = "IndicatorRadioGroup";
export { Indicator, Item, Root };
diff --git a/components/primitives/radio-group/radio-group.web.tsx b/components/primitives/radio-group/radio-group.web.tsx
index 5710ae9..2dfecfa 100644
--- a/components/primitives/radio-group/radio-group.web.tsx
+++ b/components/primitives/radio-group/radio-group.web.tsx
@@ -1,78 +1,86 @@
-import * as RadioGroup from '@radix-ui/react-radio-group';
-import * as React from 'react';
-import { GestureResponderEvent, Pressable, View } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as RadioGroup from "@radix-ui/react-radio-group";
+import * as React from "react";
+import { GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import type { RadioGroupItemProps, RadioGroupRootProps } from './types';
+} from "~/components/primitives/types";
+import type { RadioGroupItemProps, RadioGroupRootProps } from "./types";
const RadioGroupContext = React.createContext(null);
-const Root = React.forwardRef(
- ({ asChild, value, onValueChange, disabled = false, ...viewProps }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
- (({ asChild, value, onValueChange, disabled = false, ...viewProps }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
-
-
-
-
- );
- }
-);
+
+
+
+ );
+});
-Root.displayName = 'RootRadioGroup';
+Root.displayName = "RootRadioGroup";
function useRadioGroupContext() {
const context = React.useContext(RadioGroupContext);
if (!context) {
throw new Error(
- 'RadioGroup compound components cannot be rendered outside the RadioGroup component'
+ "RadioGroup compound components cannot be rendered outside the RadioGroup component",
);
}
return context;
}
-const Item = React.forwardRef(
- ({ asChild, value, onPress: onPressProps, ...props }, ref) => {
- const { onValueChange } = useRadioGroupContext();
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & RadioGroupItemProps
+>(({ asChild, value, onPress: onPressProps, ...props }, ref) => {
+ const { onValueChange } = useRadioGroupContext();
- function onPress(ev: GestureResponderEvent) {
- if (onPressProps) {
- onPressProps(ev);
- }
- onValueChange(value);
+ function onPress(ev: GestureResponderEvent) {
+ if (onPressProps) {
+ onPressProps(ev);
}
-
- const Component = asChild ? Slot.Pressable : Pressable;
- return (
-
-
-
- );
+ onValueChange(value);
}
-);
-Item.displayName = 'ItemRadioGroup';
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return (
+
+
+
+ );
+});
-const Indicator = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
+Item.displayName = "ItemRadioGroup";
+
+const Indicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
-Indicator.displayName = 'IndicatorRadioGroup';
+Indicator.displayName = "IndicatorRadioGroup";
export { Indicator, Item, Root };
diff --git a/components/primitives/radio-group/types.ts b/components/primitives/radio-group/types.ts
index dd14ca3..0c39aea 100644
--- a/components/primitives/radio-group/types.ts
+++ b/components/primitives/radio-group/types.ts
@@ -9,7 +9,7 @@ interface RadioGroupItemProps {
/**
* nativeID of the label element that describes this radio group item
*/
- 'aria-labelledby': string;
+ "aria-labelledby": string;
}
export type { RadioGroupRootProps, RadioGroupItemProps };
diff --git a/components/primitives/select/index.ts b/components/primitives/select/index.ts
index c739673..e1856bb 100644
--- a/components/primitives/select/index.ts
+++ b/components/primitives/select/index.ts
@@ -1 +1 @@
-export * from './select';
+export * from "./select";
diff --git a/components/primitives/select/select.tsx b/components/primitives/select/select.tsx
index 92c1dd6..3f97d6f 100644
--- a/components/primitives/select/select.tsx
+++ b/components/primitives/select/select.tsx
@@ -1,6 +1,20 @@
-import { useControllableState, useRelativePosition, type LayoutPosition } from '~/components/primitives/hooks';
-import { Portal as RNPPortal } from '~/components/primitives/portal';
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import {
+ BackHandler,
+ type GestureResponderEvent,
+ type LayoutChangeEvent,
+ type LayoutRectangle,
+ Pressable,
+ Text,
+ View,
+} from "react-native";
+import {
+ type LayoutPosition,
+ useControllableState,
+ useRelativePosition,
+} from "~/components/primitives/hooks";
+import { Portal as RNPPortal } from "~/components/primitives/portal";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PositionedContentProps,
@@ -10,17 +24,7 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import {
- BackHandler,
- Pressable,
- Text,
- View,
- type GestureResponderEvent,
- type LayoutChangeEvent,
- type LayoutRectangle,
-} from 'react-native';
+} from "~/components/primitives/types";
import type {
RootContext,
SelectContentProps,
@@ -30,7 +34,7 @@ import type {
SelectRootProps,
SelectSeparatorProps,
SelectValueProps,
-} from './types';
+} from "./types";
interface IRootContext extends RootContext {
triggerPosition: LayoutPosition | null;
@@ -55,7 +59,7 @@ const Root = React.forwardRef(
disabled,
...viewProps
},
- ref
+ ref,
) => {
const nativeID = React.useId();
const [open = false, onOpenChange] = useControllableState({
@@ -68,8 +72,10 @@ const Root = React.forwardRef(
defaultProp: defaultValue,
onChange: onValueChangeProp,
});
- const [triggerPosition, setTriggerPosition] = React.useState(null);
- const [contentLayout, setContentLayout] = React.useState(null);
+ const [triggerPosition, setTriggerPosition] =
+ React.useState(null);
+ const [contentLayout, setContentLayout] =
+ React.useState(null);
const Component = asChild ? Slot.View : View;
return (
@@ -90,15 +96,17 @@ const Root = React.forwardRef(
);
- }
+ },
);
-Root.displayName = 'RootNativeSelect';
+Root.displayName = "RootNativeSelect";
function useRootContext() {
const context = React.useContext(RootContext);
if (!context) {
- throw new Error('Select compound components cannot be rendered outside the Select component');
+ throw new Error(
+ "Select compound components cannot be rendered outside the Select component",
+ );
}
return context;
}
@@ -106,7 +114,12 @@ function useRootContext() {
const Trigger = React.forwardRef(
({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
const triggerRef = React.useRef(null);
- const { open, onOpenChange, disabled: disabledRoot, setTriggerPosition } = useRootContext();
+ const {
+ open,
+ onOpenChange,
+ disabled: disabledRoot,
+ setTriggerPosition,
+ } = useRootContext();
React.useImperativeHandle(
ref,
@@ -116,7 +129,7 @@ const Trigger = React.forwardRef(
}
return triggerRef.current;
},
- [triggerRef.current]
+ [triggerRef.current],
);
function onPress(ev: GestureResponderEvent) {
@@ -133,17 +146,17 @@ const Trigger = React.forwardRef(
);
- }
+ },
);
-Trigger.displayName = 'TriggerNativeSelect';
+Trigger.displayName = "TriggerNativeSelect";
const Value = React.forwardRef(
({ asChild, placeholder, ...props }, ref) => {
@@ -154,10 +167,10 @@ const Value = React.forwardRef(
{value?.label ?? placeholder}
);
- }
+ },
);
-Value.displayName = 'ValueNativeSelect';
+Value.displayName = "ValueNativeSelect";
/**
* @warning when using a custom ``, you might have to adjust the Content's sideOffset.
@@ -182,9 +195,22 @@ function Portal({ forceMount, hostName, children }: SelectPortalProps) {
);
}
-const Overlay = React.forwardRef(
- ({ asChild, forceMount, onPress: OnPressProp, closeOnPress = true, ...props }, ref) => {
- const { open, onOpenChange, setTriggerPosition, setContentLayout } = useRootContext();
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & SelectOverlayProps
+>(
+ (
+ {
+ asChild,
+ forceMount,
+ onPress: OnPressProp,
+ closeOnPress = true,
+ ...props
+ },
+ ref,
+ ) => {
+ const { open, onOpenChange, setTriggerPosition, setContentLayout } =
+ useRootContext();
function onPress(ev: GestureResponderEvent) {
if (closeOnPress) {
@@ -203,10 +229,10 @@ const Overlay = React.forwardRef;
- }
+ },
);
-Overlay.displayName = 'OverlayNativeSelect';
+Overlay.displayName = "OverlayNativeSelect";
/**
* @info `position`, `top`, `left`, and `maxWidth` style properties are controlled internally. Opt out of this behavior by setting `disablePositioningStyle` to `true`.
@@ -219,8 +245,8 @@ const Content = React.forwardRef<
{
asChild = false,
forceMount,
- align = 'start',
- side = 'bottom',
+ align = "start",
+ side = "bottom",
sideOffset = 0,
alignOffset = 0,
avoidCollisions = true,
@@ -231,7 +257,7 @@ const Content = React.forwardRef<
position: _position,
...props
},
- ref
+ ref,
) => {
const {
open,
@@ -244,12 +270,15 @@ const Content = React.forwardRef<
} = useRootContext();
React.useEffect(() => {
- const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
- setTriggerPosition(null);
- setContentLayout(null);
- onOpenChange(false);
- return true;
- });
+ const backHandler = BackHandler.addEventListener(
+ "hardwareBackPress",
+ () => {
+ setTriggerPosition(null);
+ setContentLayout(null);
+ onOpenChange(false);
+ return true;
+ },
+ );
return () => {
setContentLayout(null);
@@ -284,7 +313,7 @@ const Content = React.forwardRef<
return (
);
- }
+ },
);
-Content.displayName = 'ContentNativeSelect';
+Content.displayName = "ContentNativeSelect";
const ItemContext = React.createContext<{
itemValue: string;
label: string;
} | null>(null);
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & SelectItemProps
+>(
(
{
asChild,
@@ -314,10 +346,15 @@ const Item = React.forwardRef {
- const { onOpenChange, value, onValueChange, setTriggerPosition, setContentLayout } =
- useRootContext();
+ const {
+ onOpenChange,
+ value,
+ onValueChange,
+ setTriggerPosition,
+ setContentLayout,
+ } = useRootContext();
function onPress(ev: GestureResponderEvent) {
if (closeOnPress) {
setTriggerPosition(null);
@@ -334,7 +371,7 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemNativeSelect';
+Item.displayName = "ItemNativeSelect";
function useItemContext() {
const context = React.useContext(ItemContext);
if (!context) {
- throw new Error('Item compound components cannot be rendered outside of an Item component');
+ throw new Error(
+ "Item compound components cannot be rendered outside of an Item component",
+ );
}
return context;
}
-const ItemText = React.forwardRef>(
- ({ asChild, ...props }, ref) => {
- const { label } = useItemContext();
+const ItemText = React.forwardRef<
+ TextRef,
+ Omit
+>(({ asChild, ...props }, ref) => {
+ const { label } = useItemContext();
- const Component = asChild ? Slot.Text : Text;
- return (
-
- {label}
-
- );
- }
-);
+ const Component = asChild ? Slot.Text : Text;
+ return (
+
+ {label}
+
+ );
+});
-ItemText.displayName = 'ItemTextNativeSelect';
+ItemText.displayName = "ItemTextNativeSelect";
-const ItemIndicator = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const { itemValue } = useItemContext();
- const { value } = useRootContext();
+const ItemIndicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount, ...props }, ref) => {
+ const { itemValue } = useItemContext();
+ const { value } = useRootContext();
- if (!forceMount) {
- if (value?.value !== itemValue) {
- return null;
- }
+ if (!forceMount) {
+ if (value?.value !== itemValue) {
+ return null;
}
- const Component = asChild ? Slot.View : View;
- return ;
}
-);
-
-ItemIndicator.displayName = 'ItemIndicatorNativeSelect';
-
-const Group = React.forwardRef(({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.View : View;
- return ;
+ return ;
});
-Group.displayName = 'GroupNativeSelect';
+ItemIndicator.displayName = "ItemIndicatorNativeSelect";
-const Label = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
- return ;
-});
+const Group = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return ;
+ },
+);
-Label.displayName = 'LabelNativeSelect';
+Group.displayName = "GroupNativeSelect";
-const Separator = React.forwardRef(
- ({ asChild, decorative, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return ;
- }
+const Label = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return ;
+ },
);
-Separator.displayName = 'SeparatorNativeSelect';
+Label.displayName = "LabelNativeSelect";
+
+const Separator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & SelectSeparatorProps
+>(({ asChild, decorative, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+ );
+});
+
+Separator.displayName = "SeparatorNativeSelect";
-const ScrollUpButton = ({ children }: { children?: React.ReactNode; className?: string }) => {
+const ScrollUpButton = ({
+ children,
+}: { children?: React.ReactNode; className?: string }) => {
return children;
};
-const ScrollDownButton = ({ children }: { children?: React.ReactNode; className?: string }) => {
+const ScrollDownButton = ({
+ children,
+}: { children?: React.ReactNode; className?: string }) => {
return children;
};
-const Viewport = ({ children }: { children?: React.ReactNode; className?: string }) => {
+const Viewport = ({
+ children,
+}: { children?: React.ReactNode; className?: string }) => {
return children;
};
@@ -448,7 +506,7 @@ export {
useRootContext,
};
-export type { Option } from './types';
+export type { Option } from "./types";
function onStartShouldSetResponder() {
return true;
diff --git a/components/primitives/select/select.web.tsx b/components/primitives/select/select.web.tsx
index 14454b3..a7f18ec 100644
--- a/components/primitives/select/select.web.tsx
+++ b/components/primitives/select/select.web.tsx
@@ -1,6 +1,11 @@
-import * as Select from '@radix-ui/react-select';
-import { useAugmentedRef, useControllableState } from '~/components/primitives/hooks';
-import * as Slot from '~/components/primitives/slot';
+import * as Select from "@radix-ui/react-select";
+import * as React from "react";
+import { Pressable, Text, View } from "react-native";
+import {
+ useAugmentedRef,
+ useControllableState,
+} from "~/components/primitives/hooks";
+import * as Slot from "~/components/primitives/slot";
import type {
ForceMountable,
PositionedContentProps,
@@ -10,9 +15,7 @@ import type {
SlottableViewProps,
TextRef,
ViewRef,
-} from '~/components/primitives/types';
-import * as React from 'react';
-import { Pressable, Text, View } from 'react-native';
+} from "~/components/primitives/types";
import type {
RootContext,
SelectContentProps,
@@ -22,7 +25,7 @@ import type {
SelectRootProps,
SelectSeparatorProps,
SelectValueProps,
-} from './types';
+} from "./types";
const SelectContext = React.createContext(null);
@@ -42,7 +45,7 @@ const Root = React.forwardRef(
onOpenChange: onOpenChangeProp,
...viewProps
},
- ref
+ ref,
) => {
const [open = false, onOpenChange] = useControllableState({
prop: openProp,
@@ -82,15 +85,17 @@ const Root = React.forwardRef(
);
- }
+ },
);
-Root.displayName = 'RootWebSelect';
+Root.displayName = "RootWebSelect";
function useRootContext() {
const context = React.useContext(SelectContext);
if (!context) {
- throw new Error('Select compound components cannot be rendered outside the Select component');
+ throw new Error(
+ "Select compound components cannot be rendered outside the Select component",
+ );
}
return context;
}
@@ -103,21 +108,26 @@ const Trigger = React.forwardRef(
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
- augRef.dataset.state = open ? 'open' : 'closed';
- augRef.type = 'button';
+ augRef.dataset.state = open ? "open" : "closed";
+ augRef.type = "button";
}
}, [open]);
const Component = asChild ? Slot.Pressable : Pressable;
return (
-
+
);
- }
+ },
);
-Trigger.displayName = 'TriggerWebSelect';
+Trigger.displayName = "TriggerWebSelect";
const Value = React.forwardRef(
({ asChild, placeholder, children, ...props }, ref) => {
@@ -126,23 +136,24 @@ const Value = React.forwardRef(
{children}
);
- }
+ },
);
-Value.displayName = 'ValueWebSelect';
+Value.displayName = "ValueWebSelect";
function Portal({ container, children }: SelectPortalProps) {
return ;
}
-const Overlay = React.forwardRef(
- ({ asChild, forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.Pressable : Pressable;
- return ;
- }
-);
+const Overlay = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & SelectOverlayProps
+>(({ asChild, forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.Pressable : Pressable;
+ return ;
+});
-Overlay.displayName = 'OverlayWebSelect';
+Overlay.displayName = "OverlayWebSelect";
const Content = React.forwardRef<
ViewRef,
@@ -152,9 +163,9 @@ const Content = React.forwardRef<
{
asChild = false,
forceMount: _forceMount,
- align = 'start',
- side = 'bottom',
- position = 'popper',
+ align = "start",
+ side = "bottom",
+ position = "popper",
sideOffset = 0,
alignOffset = 0,
avoidCollisions = true,
@@ -165,7 +176,7 @@ const Content = React.forwardRef<
onPointerDownOutside,
...props
},
- ref
+ ref,
) => {
const Component = asChild ? Slot.View : View;
return (
@@ -183,116 +194,134 @@ const Content = React.forwardRef<
);
- }
+ },
);
-Content.displayName = 'ContentWebSelect';
+Content.displayName = "ContentWebSelect";
const ItemContext = React.createContext<{
itemValue: string;
label: string;
} | null>(null);
-const Item = React.forwardRef(
- ({ asChild, closeOnPress = true, label, value, children, ...props }, ref) => {
- return (
-
-
-
- <>{children}>
-
-
-
- );
- }
-);
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & SelectItemProps
+>(({ asChild, closeOnPress = true, label, value, children, ...props }, ref) => {
+ return (
+
+
+
+ <>{children}>
+
+
+
+ );
+});
-Item.displayName = 'ItemWebSelect';
+Item.displayName = "ItemWebSelect";
function useItemContext() {
const context = React.useContext(ItemContext);
if (!context) {
- throw new Error('Item compound components cannot be rendered outside of an Item component');
+ throw new Error(
+ "Item compound components cannot be rendered outside of an Item component",
+ );
}
return context;
}
-const ItemText = React.forwardRef>(
- ({ asChild, ...props }, ref) => {
- const { label } = useItemContext();
-
- const Component = asChild ? Slot.Text : Text;
- return (
-
-
- {label}
-
-
- );
- }
-);
-
-ItemText.displayName = 'ItemTextWebSelect';
-
-const ItemIndicator = React.forwardRef(
- ({ asChild, forceMount: _forceMount, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
- }
-);
-
-ItemIndicator.displayName = 'ItemIndicatorWebSelect';
+const ItemText = React.forwardRef<
+ TextRef,
+ Omit
+>(({ asChild, ...props }, ref) => {
+ const { label } = useItemContext();
-const Group = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
+ const Component = asChild ? Slot.Text : Text;
return (
-
-
-
+
+
+ {label}
+
+
);
});
-Group.displayName = 'GroupWebSelect';
+ItemText.displayName = "ItemTextWebSelect";
-const Label = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.Text : Text;
+const ItemIndicator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ForceMountable
+>(({ asChild, forceMount: _forceMount, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
return (
-
+
-
+
);
});
-Label.displayName = 'LabelWebSelect';
+ItemIndicator.displayName = "ItemIndicatorWebSelect";
-const Separator = React.forwardRef(
- ({ asChild, decorative, ...props }, ref) => {
+const Group = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.View : View;
return (
-
+
-
+
);
- }
+ },
);
-Separator.displayName = 'SeparatorWebSelect';
+Group.displayName = "GroupWebSelect";
-const ScrollUpButton = (props: React.ComponentPropsWithoutRef) => {
+const Label = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.Text : Text;
+ return (
+
+
+
+ );
+ },
+);
+
+Label.displayName = "LabelWebSelect";
+
+const Separator = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & SelectSeparatorProps
+>(({ asChild, decorative, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+});
+
+Separator.displayName = "SeparatorWebSelect";
+
+const ScrollUpButton = (
+ props: React.ComponentPropsWithoutRef,
+) => {
return ;
};
const ScrollDownButton = (
- props: React.ComponentPropsWithoutRef
+ props: React.ComponentPropsWithoutRef,
) => {
return ;
};
-const Viewport = (props: React.ComponentPropsWithoutRef) => {
+const Viewport = (
+ props: React.ComponentPropsWithoutRef,
+) => {
return ;
};
@@ -316,4 +345,4 @@ export {
useRootContext,
};
-export type { Option } from './types';
+export type { Option } from "./types";
diff --git a/components/primitives/select/types.ts b/components/primitives/select/types.ts
index 2787f96..b5a299a 100644
--- a/components/primitives/select/types.ts
+++ b/components/primitives/select/types.ts
@@ -1,4 +1,4 @@
-import type { ForceMountable } from '~/components/primitives/types';
+import type { ForceMountable } from "~/components/primitives/types";
type Option =
| {
@@ -26,7 +26,7 @@ interface SelectRootProps {
/**
* Platform: WEB ONLY
*/
- dir?: 'ltr' | 'rtl';
+ dir?: "ltr" | "rtl";
/**
* Platform: WEB ONLY
*/
@@ -61,7 +61,7 @@ interface SelectContentProps {
/**
* Platform: WEB ONLY
*/
- position?: 'popper' | 'item-aligned' | undefined;
+ position?: "popper" | "item-aligned" | undefined;
}
interface SelectItemProps {
diff --git a/components/primitives/separator/index.tsx b/components/primitives/separator/index.tsx
index f21c733..9063d44 100644
--- a/components/primitives/separator/index.tsx
+++ b/components/primitives/separator/index.tsx
@@ -1,23 +1,26 @@
-import * as React from 'react';
-import { View } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import type { SlottableViewProps, ViewRef } from '~/components/primitives/types';
-import type { SeparatorRootProps } from './types';
+import * as React from "react";
+import { View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import type {
+ SlottableViewProps,
+ ViewRef,
+} from "~/components/primitives/types";
+import type { SeparatorRootProps } from "./types";
const Root = React.forwardRef(
- ({ asChild, decorative, orientation = 'horizontal', ...props }, ref) => {
+ ({ asChild, decorative, orientation = "horizontal", ...props }, ref) => {
const Component = asChild ? Slot.View : View;
return (
);
- }
+ },
);
-Root.displayName = 'RootSeparator';
+Root.displayName = "RootSeparator";
export { Root };
diff --git a/components/primitives/separator/types.ts b/components/primitives/separator/types.ts
index fd6434a..b8040c3 100644
--- a/components/primitives/separator/types.ts
+++ b/components/primitives/separator/types.ts
@@ -1,5 +1,5 @@
interface SeparatorRootProps {
- orientation?: 'horizontal' | 'vertical';
+ orientation?: "horizontal" | "vertical";
decorative?: boolean;
}
diff --git a/components/primitives/slot.tsx b/components/primitives/slot.tsx
index 403b91e..bad7783 100644
--- a/components/primitives/slot.tsx
+++ b/components/primitives/slot.tsx
@@ -1,46 +1,49 @@
-import * as React from 'react';
+import * as React from "react";
import {
Image as RNImage,
- Pressable as RNPressable,
- Text as RNText,
- View as RNView,
- StyleSheet,
- type PressableStateCallbackType,
type ImageProps as RNImageProps,
type ImageStyle as RNImageStyle,
+ Pressable as RNPressable,
type PressableProps as RNPressableProps,
+ type PressableStateCallbackType,
+ type StyleProp,
+ StyleSheet,
+ Text as RNText,
type TextProps as RNTextProps,
+ View as RNView,
type ViewProps as RNViewProps,
- type StyleProp,
-} from 'react-native';
-
-const Pressable = React.forwardRef, RNPressableProps>(
- (props, forwardedRef) => {
- const { children, ...pressableSlotProps } = props;
+} from "react-native";
- if (!React.isValidElement(children)) {
- console.log('Slot.Pressable - Invalid asChild element', children);
- return null;
- }
+const Pressable = React.forwardRef<
+ React.ElementRef,
+ RNPressableProps
+>((props, forwardedRef) => {
+ const { children, ...pressableSlotProps } = props;
- return React.cloneElement<
- React.ComponentPropsWithoutRef,
- React.ElementRef
- >(isTextChildren(children) ? <>> : children, {
- ...mergeProps(pressableSlotProps, children.props),
- ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
- });
+ if (!React.isValidElement(children)) {
+ console.log("Slot.Pressable - Invalid asChild element", children);
+ return null;
}
-);
-Pressable.displayName = 'SlotPressable';
+ return React.cloneElement<
+ React.ComponentPropsWithoutRef,
+ React.ElementRef
+ >(isTextChildren(children) ? <>> : children, {
+ ...mergeProps(pressableSlotProps, children.props),
+ ref: forwardedRef
+ ? composeRefs(forwardedRef, (children as any).ref)
+ : (children as any).ref,
+ });
+});
+
+Pressable.displayName = "SlotPressable";
const View = React.forwardRef, RNViewProps>(
(props, forwardedRef) => {
const { children, ...viewSlotProps } = props;
if (!React.isValidElement(children)) {
- console.log('Slot.View - Invalid asChild element', children);
+ console.log("Slot.View - Invalid asChild element", children);
return null;
}
@@ -49,19 +52,21 @@ const View = React.forwardRef, RNViewProps>(
React.ElementRef
>(isTextChildren(children) ? <>> : children, {
...mergeProps(viewSlotProps, children.props),
- ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
+ ref: forwardedRef
+ ? composeRefs(forwardedRef, (children as any).ref)
+ : (children as any).ref,
});
- }
+ },
);
-View.displayName = 'SlotView';
+View.displayName = "SlotView";
const Text = React.forwardRef, RNTextProps>(
(props, forwardedRef) => {
const { children, ...textSlotProps } = props;
if (!React.isValidElement(children)) {
- console.log('Slot.Text - Invalid asChild element', children);
+ console.log("Slot.Text - Invalid asChild element", children);
return null;
}
@@ -70,37 +75,42 @@ const Text = React.forwardRef, RNTextProps>(
React.ElementRef
>(isTextChildren(children) ? <>> : children, {
...mergeProps(textSlotProps, children.props),
- ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
+ ref: forwardedRef
+ ? composeRefs(forwardedRef, (children as any).ref)
+ : (children as any).ref,
});
- }
+ },
);
-Text.displayName = 'SlotText';
+Text.displayName = "SlotText";
type ImageSlotProps = RNImageProps & {
children?: React.ReactNode;
};
-const Image = React.forwardRef, ImageSlotProps>(
- (props, forwardedRef) => {
- const { children, ...imageSlotProps } = props;
+const Image = React.forwardRef<
+ React.ElementRef,
+ ImageSlotProps
+>((props, forwardedRef) => {
+ const { children, ...imageSlotProps } = props;
- if (!React.isValidElement(children)) {
- console.log('Slot.Image - Invalid asChild element', children);
- return null;
- }
-
- return React.cloneElement<
- React.ComponentPropsWithoutRef,
- React.ElementRef
- >(isTextChildren(children) ? <>> : children, {
- ...mergeProps(imageSlotProps, children.props),
- ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
- });
+ if (!React.isValidElement(children)) {
+ console.log("Slot.Image - Invalid asChild element", children);
+ return null;
}
-);
-Image.displayName = 'SlotImage';
+ return React.cloneElement<
+ React.ComponentPropsWithoutRef,
+ React.ElementRef
+ >(isTextChildren(children) ? <>> : children, {
+ ...mergeProps(imageSlotProps, children.props),
+ ref: forwardedRef
+ ? composeRefs(forwardedRef, (children as any).ref)
+ : (children as any).ref,
+ });
+});
+
+Image.displayName = "SlotImage";
export { Image, Pressable, Text, View };
@@ -111,7 +121,7 @@ export { Image, Pressable, Text, View };
function composeRefs(...refs: (React.Ref | undefined)[]) {
return (node: T) =>
refs.forEach((ref) => {
- if (typeof ref === 'function') {
+ if (typeof ref === "function") {
ref(node);
} else if (ref != null) {
(ref as React.MutableRefObject).current = node;
@@ -144,34 +154,40 @@ function mergeProps(slotProps: AnyProps, childProps: AnyProps) {
}
}
// if it's `style`, we merge them
- else if (propName === 'style') {
+ else if (propName === "style") {
overrideProps[propName] = combineStyles(slotPropValue, childPropValue);
- } else if (propName === 'className') {
- overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');
+ } else if (propName === "className") {
+ overrideProps[propName] = [slotPropValue, childPropValue]
+ .filter(Boolean)
+ .join(" ");
}
}
return { ...slotProps, ...overrideProps };
}
-type PressableStyle = RNPressableProps['style'];
+type PressableStyle = RNPressableProps["style"];
type ImageStyle = StyleProp;
type Style = PressableStyle | ImageStyle;
function combineStyles(slotStyle?: Style, childValue?: Style) {
- if (typeof slotStyle === 'function' && typeof childValue === 'function') {
+ if (typeof slotStyle === "function" && typeof childValue === "function") {
return (state: PressableStateCallbackType) => {
return StyleSheet.flatten([slotStyle(state), childValue(state)]);
};
}
- if (typeof slotStyle === 'function') {
+ if (typeof slotStyle === "function") {
return (state: PressableStateCallbackType) => {
- return childValue ? StyleSheet.flatten([slotStyle(state), childValue]) : slotStyle(state);
+ return childValue
+ ? StyleSheet.flatten([slotStyle(state), childValue])
+ : slotStyle(state);
};
}
- if (typeof childValue === 'function') {
+ if (typeof childValue === "function") {
return (state: PressableStateCallbackType) => {
- return slotStyle ? StyleSheet.flatten([slotStyle, childValue(state)]) : childValue(state);
+ return slotStyle
+ ? StyleSheet.flatten([slotStyle, childValue(state)])
+ : childValue(state);
};
}
@@ -179,9 +195,11 @@ function combineStyles(slotStyle?: Style, childValue?: Style) {
}
export function isTextChildren(
- children: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode)
+ children:
+ | React.ReactNode
+ | ((state: PressableStateCallbackType) => React.ReactNode),
) {
return Array.isArray(children)
- ? children.every((child) => typeof child === 'string')
- : typeof children === 'string';
+ ? children.every((child) => typeof child === "string")
+ : typeof children === "string";
}
diff --git a/components/primitives/switch/index.ts b/components/primitives/switch/index.ts
index 4dd2256..7c69fd9 100644
--- a/components/primitives/switch/index.ts
+++ b/components/primitives/switch/index.ts
@@ -1 +1 @@
-export * from './switch';
+export * from "./switch";
diff --git a/components/primitives/switch/switch.tsx b/components/primitives/switch/switch.tsx
index ceebe36..7072f4d 100644
--- a/components/primitives/switch/switch.tsx
+++ b/components/primitives/switch/switch.tsx
@@ -1,13 +1,13 @@
-import * as React from 'react';
-import { Pressable, View, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import { type GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import type { SwitchRootProps } from './types';
+} from "~/components/primitives/types";
+import type { SwitchRootProps } from "./types";
const Root = React.forwardRef<
PressableRef,
@@ -20,10 +20,10 @@ const Root = React.forwardRef<
onCheckedChange,
disabled,
onPress: onPressProp,
- 'aria-valuetext': ariaValueText,
+ "aria-valuetext": ariaValueText,
...props
},
- ref
+ ref,
) => {
function onPress(ev: GestureResponderEvent) {
if (disabled) return;
@@ -36,9 +36,9 @@ const Root = React.forwardRef<
);
- }
+ },
);
-Root.displayName = 'RootNativeSwitch';
+Root.displayName = "RootNativeSwitch";
const Thumb = React.forwardRef(
({ asChild, ...props }, ref) => {
const Component = asChild ? Slot.View : View;
- return ;
- }
+ return ;
+ },
);
-Thumb.displayName = 'ThumbNativeSwitch';
+Thumb.displayName = "ThumbNativeSwitch";
export { Root, Thumb };
diff --git a/components/primitives/switch/switch.web.tsx b/components/primitives/switch/switch.web.tsx
index 5628746..ff42eeb 100644
--- a/components/primitives/switch/switch.web.tsx
+++ b/components/primitives/switch/switch.web.tsx
@@ -1,16 +1,19 @@
-import * as Switch from '@radix-ui/react-switch';
-import * as React from 'react';
-import { Pressable, View, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as Switch from "@radix-ui/react-switch";
+import * as React from "react";
+import { type GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import type { SwitchRootProps } from './types';
+} from "~/components/primitives/types";
+import type { SwitchRootProps } from "./types";
-const Root = React.forwardRef(
+const Root = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & SwitchRootProps
+>(
(
{
asChild,
@@ -21,7 +24,7 @@ const Root = React.forwardRef {
function onPress(ev: GestureResponderEvent) {
onCheckedChange(!checked);
@@ -30,14 +33,19 @@ const Root = React.forwardRef
+
);
- }
+ },
);
-Root.displayName = 'RootWebSwitch';
+Root.displayName = "RootWebSwitch";
-const Thumb = React.forwardRef(({ asChild, ...props }, ref) => {
- const Component = asChild ? Slot.View : View;
- return (
-
-
-
- );
-});
+const Thumb = React.forwardRef(
+ ({ asChild, ...props }, ref) => {
+ const Component = asChild ? Slot.View : View;
+ return (
+
+
+
+ );
+ },
+);
-Thumb.displayName = 'ThumbWebSwitch';
+Thumb.displayName = "ThumbWebSwitch";
export { Root, Thumb };
diff --git a/components/primitives/toggle-group/index.ts b/components/primitives/toggle-group/index.ts
index 9ebe798..1112dbb 100644
--- a/components/primitives/toggle-group/index.ts
+++ b/components/primitives/toggle-group/index.ts
@@ -1 +1 @@
-export * from './toggle-group';
+export * from "./toggle-group";
diff --git a/components/primitives/toggle-group/toggle-group.tsx b/components/primitives/toggle-group/toggle-group.tsx
index d799fc0..9ff2036 100644
--- a/components/primitives/toggle-group/toggle-group.tsx
+++ b/components/primitives/toggle-group/toggle-group.tsx
@@ -1,18 +1,23 @@
-import * as React from 'react';
-import { Pressable, View, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as React from "react";
+import { type GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import { ToggleGroupUtils } from '~/components/primitives/utils';
-import type { ToggleGroupItemProps, ToggleGroupRootProps } from './types';
+} from "~/components/primitives/types";
+import { ToggleGroupUtils } from "~/components/primitives/utils";
+import type { ToggleGroupItemProps, ToggleGroupRootProps } from "./types";
-const ToggleGroupContext = React.createContext(null);
+const ToggleGroupContext = React.createContext(
+ null,
+);
-const Root = React.forwardRef(
+const Root = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ToggleGroupRootProps
+>(
(
{
asChild,
@@ -26,7 +31,7 @@ const Root = React.forwardRef {
const Component = asChild ? Slot.View : View;
return (
@@ -40,19 +45,19 @@ const Root = React.forwardRef
-
+
);
- }
+ },
);
-Root.displayName = 'RootToggleGroup';
+Root.displayName = "RootToggleGroup";
function useRootContext() {
const context = React.useContext(ToggleGroupContext);
if (!context) {
throw new Error(
- 'ToggleGroup compound components cannot be rendered outside the ToggleGroup component'
+ "ToggleGroup compound components cannot be rendered outside the ToggleGroup component",
);
}
return context;
@@ -60,29 +65,42 @@ function useRootContext() {
const ItemContext = React.createContext(null);
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ToggleGroupItemProps
+>(
(
- { asChild, value: itemValue, disabled: disabledProp = false, onPress: onPressProp, ...props },
- ref
+ {
+ asChild,
+ value: itemValue,
+ disabled: disabledProp = false,
+ onPress: onPressProp,
+ ...props
+ },
+ ref,
) => {
const id = React.useId();
const { type, disabled, value, onValueChange } = useRootContext();
function onPress(ev: GestureResponderEvent) {
if (disabled || disabledProp) return;
- if (type === 'single') {
+ if (type === "single") {
onValueChange(ToggleGroupUtils.getNewSingleValue(value, itemValue));
}
- if (type === 'multiple') {
+ if (type === "multiple") {
onValueChange(ToggleGroupUtils.getNewMultipleValue(value, itemValue));
}
onPressProp?.(ev);
}
const isChecked =
- type === 'single' ? ToggleGroupUtils.getIsSelected(value, itemValue) : undefined;
+ type === "single"
+ ? ToggleGroupUtils.getIsSelected(value, itemValue)
+ : undefined;
const isSelected =
- type === 'multiple' ? ToggleGroupUtils.getIsSelected(value, itemValue) : undefined;
+ type === "multiple"
+ ? ToggleGroupUtils.getIsSelected(value, itemValue)
+ : undefined;
const Component = asChild ? Slot.Pressable : Pressable;
return (
@@ -91,7 +109,7 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemToggleGroup';
+Item.displayName = "ItemToggleGroup";
function useItemContext() {
const context = React.useContext(ItemContext);
if (!context) {
throw new Error(
- 'ToggleGroupItem compound components cannot be rendered outside the ToggleGroupItem component'
+ "ToggleGroupItem compound components cannot be rendered outside the ToggleGroupItem component",
);
}
return context;
diff --git a/components/primitives/toggle-group/toggle-group.web.tsx b/components/primitives/toggle-group/toggle-group.web.tsx
index 848e4db..436d5da 100644
--- a/components/primitives/toggle-group/toggle-group.web.tsx
+++ b/components/primitives/toggle-group/toggle-group.web.tsx
@@ -1,19 +1,24 @@
-import * as ToggleGroup from '@radix-ui/react-toggle-group';
-import * as React from 'react';
-import { Pressable, View, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
+import * as ToggleGroup from "@radix-ui/react-toggle-group";
+import * as React from "react";
+import { type GestureResponderEvent, Pressable, View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
import type {
PressableRef,
SlottablePressableProps,
SlottableViewProps,
ViewRef,
-} from '~/components/primitives/types';
-import { ToggleGroupUtils } from '~/components/primitives/utils';
-import type { ToggleGroupItemProps, ToggleGroupRootProps } from './types';
+} from "~/components/primitives/types";
+import { ToggleGroupUtils } from "~/components/primitives/utils";
+import type { ToggleGroupItemProps, ToggleGroupRootProps } from "./types";
-const ToggleGroupContext = React.createContext(null);
+const ToggleGroupContext = React.createContext(
+ null,
+);
-const Root = React.forwardRef(
+const Root = React.forwardRef<
+ ViewRef,
+ SlottableViewProps & ToggleGroupRootProps
+>(
(
{
asChild,
@@ -27,7 +32,7 @@ const Root = React.forwardRef {
const Component = asChild ? Slot.View : View;
return (
@@ -56,16 +61,16 @@ const Root = React.forwardRef
);
- }
+ },
);
-Root.displayName = 'RootToggleGroup';
+Root.displayName = "RootToggleGroup";
function useRootContext() {
const context = React.useContext(ToggleGroupContext);
if (!context) {
throw new Error(
- 'ToggleGroup compound components cannot be rendered outside the ToggleGroup component'
+ "ToggleGroup compound components cannot be rendered outside the ToggleGroup component",
);
}
return context;
@@ -73,19 +78,28 @@ function useRootContext() {
const ItemContext = React.createContext(null);
-const Item = React.forwardRef(
+const Item = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ToggleGroupItemProps
+>(
(
- { asChild, value: itemValue, disabled: disabledProp = false, onPress: onPressProp, ...props },
- ref
+ {
+ asChild,
+ value: itemValue,
+ disabled: disabledProp = false,
+ onPress: onPressProp,
+ ...props
+ },
+ ref,
) => {
const { type, disabled, value, onValueChange } = useRootContext();
function onPress(ev: GestureResponderEvent) {
onPressProp?.(ev);
- if (type === 'single') {
+ if (type === "single") {
onValueChange(ToggleGroupUtils.getNewSingleValue(value, itemValue));
}
- if (type === 'multiple') {
+ if (type === "multiple") {
onValueChange(ToggleGroupUtils.getNewMultipleValue(value, itemValue));
}
}
@@ -98,22 +112,22 @@ const Item = React.forwardRef
);
- }
+ },
);
-Item.displayName = 'ItemToggleGroup';
+Item.displayName = "ItemToggleGroup";
function useItemContext() {
const context = React.useContext(ItemContext);
if (!context) {
throw new Error(
- 'ToggleGroupItem compound components cannot be rendered outside the ToggleGroupItem component'
+ "ToggleGroupItem compound components cannot be rendered outside the ToggleGroupItem component",
);
}
return context;
diff --git a/components/primitives/toggle-group/types.ts b/components/primitives/toggle-group/types.ts
index da7e64e..a77fc3f 100644
--- a/components/primitives/toggle-group/types.ts
+++ b/components/primitives/toggle-group/types.ts
@@ -1,11 +1,11 @@
type SingleRootProps = {
- type: 'single';
+ type: "single";
value: string | undefined;
onValueChange: (val: string | undefined) => void;
};
type MultipleRootProps = {
- type: 'multiple';
+ type: "multiple";
value: string[];
onValueChange: (val: string[]) => void;
};
@@ -19,11 +19,11 @@ type ToggleGroupRootProps = (SingleRootProps | MultipleRootProps) & {
/**
* Platform: WEB ONLY
*/
- orientation?: 'horizontal' | 'vertical';
+ orientation?: "horizontal" | "vertical";
/**
* Platform: WEB ONLY
*/
- dir?: 'ltr' | 'rtl';
+ dir?: "ltr" | "rtl";
/**
* Platform: WEB ONLY
*/
diff --git a/components/primitives/toggle/index.ts b/components/primitives/toggle/index.ts
index 4af0cec..934fd73 100644
--- a/components/primitives/toggle/index.ts
+++ b/components/primitives/toggle/index.ts
@@ -1 +1 @@
-export * from './toggle';
+export * from "./toggle";
diff --git a/components/primitives/toggle/toggle.tsx b/components/primitives/toggle/toggle.tsx
index d124ba3..62b1819 100644
--- a/components/primitives/toggle/toggle.tsx
+++ b/components/primitives/toggle/toggle.tsx
@@ -1,11 +1,27 @@
-import * as React from 'react';
-import { Pressable, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import type { PressableRef, SlottablePressableProps } from '~/components/primitives/types';
-import type { ToggleRootProps } from './types';
+import * as React from "react";
+import { type GestureResponderEvent, Pressable } from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import type {
+ PressableRef,
+ SlottablePressableProps,
+} from "~/components/primitives/types";
+import type { ToggleRootProps } from "./types";
-const Root = React.forwardRef(
- ({ asChild, pressed, onPressedChange, disabled, onPress: onPressProp, ...props }, ref) => {
+const Root = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ToggleRootProps
+>(
+ (
+ {
+ asChild,
+ pressed,
+ onPressedChange,
+ disabled,
+ onPress: onPressProp,
+ ...props
+ },
+ ref,
+ ) => {
function onPress(ev: GestureResponderEvent) {
if (disabled) return;
const newValue = !pressed;
@@ -18,7 +34,7 @@ const Root = React.forwardRef
);
- }
+ },
);
-Root.displayName = 'RootNativeToggle';
+Root.displayName = "RootNativeToggle";
export { Root };
diff --git a/components/primitives/toggle/toggle.web.tsx b/components/primitives/toggle/toggle.web.tsx
index 3678708..d341919 100644
--- a/components/primitives/toggle/toggle.web.tsx
+++ b/components/primitives/toggle/toggle.web.tsx
@@ -1,12 +1,28 @@
-import * as Toggle from '@radix-ui/react-toggle';
-import * as React from 'react';
-import { Pressable, type GestureResponderEvent } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import type { PressableRef, SlottablePressableProps } from '~/components/primitives/types';
-import type { ToggleRootProps } from './types';
+import * as Toggle from "@radix-ui/react-toggle";
+import * as React from "react";
+import { type GestureResponderEvent, Pressable } from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import type {
+ PressableRef,
+ SlottablePressableProps,
+} from "~/components/primitives/types";
+import type { ToggleRootProps } from "./types";
-const Root = React.forwardRef(
- ({ asChild, pressed, onPressedChange, disabled, onPress: onPressProp, ...props }, ref) => {
+const Root = React.forwardRef<
+ PressableRef,
+ SlottablePressableProps & ToggleRootProps
+>(
+ (
+ {
+ asChild,
+ pressed,
+ onPressedChange,
+ disabled,
+ onPress: onPressProp,
+ ...props
+ },
+ ref,
+ ) => {
function onPress(ev: GestureResponderEvent) {
onPressProp?.(ev);
onPressedChange(!pressed);
@@ -14,13 +30,24 @@ const Root = React.forwardRef
-
+
+
);
- }
+ },
);
-Root.displayName = 'RootWebToggle';
+Root.displayName = "RootWebToggle";
export { Root };
diff --git a/components/primitives/types.ts b/components/primitives/types.ts
index 40f26e2..4afe20d 100644
--- a/components/primitives/types.ts
+++ b/components/primitives/types.ts
@@ -1,4 +1,4 @@
-import type { Pressable, Text, View, ViewStyle } from 'react-native';
+import type { Pressable, Text, View, ViewStyle } from "react-native";
type ComponentPropsWithAsChild> =
React.ComponentPropsWithoutRef & { asChild?: boolean };
@@ -40,8 +40,8 @@ interface PositionedContentProps {
alignOffset?: number;
insets?: Insets;
avoidCollisions?: boolean;
- align?: 'start' | 'center' | 'end';
- side?: 'top' | 'bottom';
+ align?: "start" | "center" | "end";
+ side?: "top" | "bottom";
sideOffset?: number;
/**
* Platform: NATIVE ONLY
@@ -71,7 +71,7 @@ interface PositionedContentProps {
* Platform: WEB ONLY
*/
onInteractOutside?: (
- event: PointerDownOutsideEvent | FocusOutsideEvent
+ event: PointerDownOutsideEvent | FocusOutsideEvent,
) => void;
/**
* Platform: WEB ONLY
@@ -80,7 +80,7 @@ interface PositionedContentProps {
/**
* Platform: WEB ONLY
*/
- sticky?: 'partial' | 'always';
+ sticky?: "partial" | "always";
/**
* Platform: WEB ONLY
*/
diff --git a/components/primitives/utils.ts b/components/primitives/utils.ts
index 8453d37..6f23f20 100644
--- a/components/primitives/utils.ts
+++ b/components/primitives/utils.ts
@@ -1,26 +1,32 @@
-import type { GestureResponderEvent } from 'react-native';
+import type { GestureResponderEvent } from "react-native";
const ToggleGroupUtils = {
getIsSelected(value: string | string[] | undefined, itemValue: string) {
if (value === undefined) {
return false;
}
- if (typeof value === 'string') {
+ if (typeof value === "string") {
return value === itemValue;
}
return value.includes(itemValue);
},
- getNewSingleValue(originalValue: string | string[] | undefined, itemValue: string) {
+ getNewSingleValue(
+ originalValue: string | string[] | undefined,
+ itemValue: string,
+ ) {
if (originalValue === itemValue) {
return undefined;
}
return itemValue;
},
- getNewMultipleValue(originalValue: string | string[] | undefined, itemValue: string) {
+ getNewMultipleValue(
+ originalValue: string | string[] | undefined,
+ itemValue: string,
+ ) {
if (originalValue === undefined) {
return [itemValue];
}
- if (typeof originalValue === 'string') {
+ if (typeof originalValue === "string") {
return originalValue === itemValue ? [] : [originalValue, itemValue];
}
if (originalValue.includes(itemValue)) {
@@ -33,12 +39,12 @@ const ToggleGroupUtils = {
const EmptyGestureResponderEvent: GestureResponderEvent = {
nativeEvent: {
changedTouches: [],
- identifier: '0',
+ identifier: "0",
locationX: 0,
locationY: 0,
pageX: 0,
pageY: 0,
- target: '0',
+ target: "0",
timestamp: 0,
touches: [],
},
@@ -55,7 +61,7 @@ const EmptyGestureResponderEvent: GestureResponderEvent = {
stopPropagation: () => {},
target: {} as any,
timeStamp: 0,
- type: '',
+ type: "",
};
export { ToggleGroupUtils, EmptyGestureResponderEvent };
diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx
index d8704c6..c9e1c18 100644
--- a/components/ui/avatar.tsx
+++ b/components/ui/avatar.tsx
@@ -1,6 +1,6 @@
-import * as React from 'react';
-import * as AvatarPrimitive from '~/components/primitives/avatar';
-import { cn } from '~/lib/utils';
+import * as React from "react";
+import * as AvatarPrimitive from "~/components/primitives/avatar";
+import { cn } from "~/lib/utils";
const Avatar = React.forwardRef<
React.ElementRef,
@@ -8,7 +8,10 @@ const Avatar = React.forwardRef<
>(({ className, ...props }, ref) => (
));
@@ -20,7 +23,7 @@ const AvatarImage = React.forwardRef<
>(({ className, ...props }, ref) => (
));
@@ -33,8 +36,8 @@ const AvatarFallback = React.forwardRef<
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
index 07663af..dd2cf45 100644
--- a/components/ui/badge.tsx
+++ b/components/ui/badge.tsx
@@ -1,38 +1,41 @@
-import { cva, type VariantProps } from 'class-variance-authority';
-import { View } from 'react-native';
-import * as Slot from '~/components/primitives/slot';
-import type { SlottableViewProps } from '~/components/primitives/types';
-import { cn } from '~/lib/utils';
-import { TextClassContext } from '~/components/ui/text';
+import { type VariantProps, cva } from "class-variance-authority";
+import { View } from "react-native";
+import * as Slot from "~/components/primitives/slot";
+import type { SlottableViewProps } from "~/components/primitives/types";
+import { TextClassContext } from "~/components/ui/text";
+import { cn } from "~/lib/utils";
const badgeVariants = cva(
- 'web:inline-flex items-center rounded-full border border-border px-2.5 py-0.5 web:transition-colors web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2',
+ "web:inline-flex items-center rounded-full border border-border px-2.5 py-0.5 web:transition-colors web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2",
{
variants: {
variant: {
- default: 'border-transparent bg-primary web:hover:opacity-80 active:opacity-80',
- secondary: 'border-transparent bg-secondary web:hover:opacity-80 active:opacity-80',
- destructive: 'border-transparent bg-destructive web:hover:opacity-80 active:opacity-80',
- outline: 'text-foreground',
+ default:
+ "border-transparent bg-primary web:hover:opacity-80 active:opacity-80",
+ secondary:
+ "border-transparent bg-secondary web:hover:opacity-80 active:opacity-80",
+ destructive:
+ "border-transparent bg-destructive web:hover:opacity-80 active:opacity-80",
+ outline: "text-foreground",
},
},
defaultVariants: {
- variant: 'default',
+ variant: "default",
},
- }
+ },
);
-const badgeTextVariants = cva('text-xs font-semibold ', {
+const badgeTextVariants = cva("text-xs font-semibold ", {
variants: {
variant: {
- default: 'text-primary-foreground',
- secondary: 'text-secondary-foreground',
- destructive: 'text-destructive-foreground',
- outline: 'text-foreground',
+ default: "text-primary-foreground",
+ secondary: "text-secondary-foreground",
+ destructive: "text-destructive-foreground",
+ outline: "text-foreground",
},
},
defaultVariants: {
- variant: 'default',
+ variant: "default",
},
});
@@ -42,7 +45,10 @@ function Badge({ className, variant, asChild, ...props }: BadgeProps) {
const Component = asChild ? Slot.View : View;
return (
-
+
);
}
diff --git a/components/ui/bottom-sheet.native.tsx b/components/ui/bottom-sheet.native.tsx
index b093fb2..8205e95 100644
--- a/components/ui/bottom-sheet.native.tsx
+++ b/components/ui/bottom-sheet.native.tsx
@@ -1,332 +1,357 @@
import type {
- BottomSheetBackdropProps,
- BottomSheetFooterProps as GBottomSheetFooterProps,
- } from '@gorhom/bottom-sheet';
- import {
- BottomSheetBackdrop,
- BottomSheetModal,
- BottomSheetFlatList as GBottomSheetFlatList,
- BottomSheetFooter as GBottomSheetFooter,
- BottomSheetTextInput as GBottomSheetTextInput,
- BottomSheetView as GBottomSheetView,
- useBottomSheetModal,
- } from '@gorhom/bottom-sheet';
- import type { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
- import { useTheme } from '@react-navigation/native';
- import * as React from 'react';
- import { GestureResponderEvent, Keyboard, Pressable, View, ViewStyle } from 'react-native';
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
- import { X } from '../../components/Icons';
- import { Button } from './button';
- import * as Slot from '../primitives/slot';
- import { useColorScheme } from '../../lib/useColorScheme';
- import { cn } from '../../lib/utils';
-
- // TODO: refactor and move to UI
- // TODO: create web component, use https://ui.shadcn.com/docs/components/drawer
-
- type BottomSheetRef = React.ElementRef;
- type BottomSheetProps = React.ComponentPropsWithoutRef;
-
- interface BottomSheetContext {
- sheetRef: React.RefObject;
- }
-
- const BottomSheetContext = React.createContext({} as BottomSheetContext);
-
- const BottomSheet = React.forwardRef(({ ...props }, ref) => {
+ BottomSheetBackdropProps,
+ BottomSheetFooterProps as GBottomSheetFooterProps,
+} from "@gorhom/bottom-sheet";
+import {
+ BottomSheetBackdrop,
+ BottomSheetFlatList as GBottomSheetFlatList,
+ BottomSheetFooter as GBottomSheetFooter,
+ BottomSheetModal,
+ BottomSheetTextInput as GBottomSheetTextInput,
+ BottomSheetView as GBottomSheetView,
+ useBottomSheetModal,
+} from "@gorhom/bottom-sheet";
+import type { BottomSheetModalMethods } from "@gorhom/bottom-sheet/lib/typescript/types";
+import { useTheme } from "@react-navigation/native";
+import * as React from "react";
+import {
+ GestureResponderEvent,
+ Keyboard,
+ Pressable,
+ View,
+ ViewStyle,
+} from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { X } from "../../components/Icons";
+import { useColorScheme } from "../../lib/useColorScheme";
+import { cn } from "../../lib/utils";
+import * as Slot from "../primitives/slot";
+import { Button } from "./button";
+
+// TODO: refactor and move to UI
+// TODO: create web component, use https://ui.shadcn.com/docs/components/drawer
+
+type BottomSheetRef = React.ElementRef;
+type BottomSheetProps = React.ComponentPropsWithoutRef;
+
+interface BottomSheetContext {
+ sheetRef: React.RefObject;
+}
+
+const BottomSheetContext = React.createContext({} as BottomSheetContext);
+
+const BottomSheet = React.forwardRef(
+ ({ ...props }, ref) => {
const sheetRef = React.useRef(null);
-
+
return (
);
- });
-
- function useBottomSheetContext() {
- const context = React.useContext(BottomSheetContext);
- if (!context) {
- throw new Error(
- 'BottomSheet compound components cannot be rendered outside the BottomSheet component'
- );
- }
- return context;
+ },
+);
+
+function useBottomSheetContext() {
+ const context = React.useContext(BottomSheetContext);
+ if (!context) {
+ throw new Error(
+ "BottomSheet compound components cannot be rendered outside the BottomSheet component",
+ );
}
-
- const CLOSED_INDEX = -1;
-
- type BottomSheetContentRef = React.ElementRef;
-
- type BottomSheetContentProps = Omit<
- React.ComponentPropsWithoutRef,
- 'backdropComponent'
- > & {
- backdropProps?: Partial>;
- };
-
- const BottomSheetContent = React.forwardRef(
- (
- {
- enablePanDownToClose = true,
- enableDynamicSizing = true,
- index = 0,
- backdropProps,
- backgroundStyle,
- android_keyboardInputMode = 'adjustResize',
- ...props
- },
- ref
- ) => {
- const insets = useSafeAreaInsets();
- const { isDarkColorScheme } = useColorScheme();
- const { colors } = useTheme();
- const { sheetRef } = useBottomSheetContext();
-
- React.useImperativeHandle(
- ref,
- () => {
- if (!sheetRef.current) {
- return {} as BottomSheetModalMethods;
- }
- return sheetRef.current;
- },
- [sheetRef.current]
- );
-
- const renderBackdrop = React.useCallback(
- (props: BottomSheetBackdropProps) => {
- const {
- pressBehavior = 'close',
- opacity = isDarkColorScheme ? 0.3 : 0.7,
- disappearsOnIndex = CLOSED_INDEX,
- style,
- onPress,
- ...rest
- } = {
- ...props,
- ...backdropProps,
- };
- return (
- {
- if (Keyboard.isVisible()) {
- Keyboard.dismiss();
- }
- onPress?.();
- }}
- {...rest}
- />
- );
- },
- [backdropProps, colors]
- );
-
- return (
-
- );
- }
- );
-
- const BottomSheetOpenTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef & {
- asChild?: boolean;
- }
- >(({ onPress, asChild = false, ...props }, ref) => {
- const { sheetRef } = useBottomSheetContext();
- function handleOnPress(ev: GestureResponderEvent) {
- sheetRef.current?.present();
- onPress?.(ev);
- }
- const Trigger = asChild ? Slot.Pressable : Pressable;
- return ;
- });
-
- const BottomSheetCloseTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef & {
- asChild?: boolean;
- }
- >(({ onPress, asChild = false, ...props }, ref) => {
- const { dismiss } = useBottomSheetModal();
- function handleOnPress(ev: GestureResponderEvent) {
- dismiss();
- if (Keyboard.isVisible()) {
- Keyboard.dismiss();
- }
- onPress?.(ev);
- }
- const Trigger = asChild ? Slot.Pressable : Pressable;
- return ;
- });
-
- const BOTTOM_SHEET_HEADER_HEIGHT = 60; // BottomSheetHeader height
-
- type BottomSheetViewProps = Omit<
- React.ComponentPropsWithoutRef,
- 'style'
- > & {
- hadHeader?: boolean;
- style?: ViewStyle;
- };
-
- function BottomSheetView({
- className,
- children,
- hadHeader = true,
- style,
- ...props
- }: BottomSheetViewProps) {
+ return context;
+}
+
+const CLOSED_INDEX = -1;
+
+type BottomSheetContentRef = React.ElementRef;
+
+type BottomSheetContentProps = Omit<
+ React.ComponentPropsWithoutRef,
+ "backdropComponent"
+> & {
+ backdropProps?: Partial<
+ React.ComponentPropsWithoutRef
+ >;
+};
+
+const BottomSheetContent = React.forwardRef<
+ BottomSheetContentRef,
+ BottomSheetContentProps
+>(
+ (
+ {
+ enablePanDownToClose = true,
+ enableDynamicSizing = true,
+ index = 0,
+ backdropProps,
+ backgroundStyle,
+ android_keyboardInputMode = "adjustResize",
+ ...props
+ },
+ ref,
+ ) => {
const insets = useSafeAreaInsets();
- return (
- {
+ if (!sheetRef.current) {
+ return {} as BottomSheetModalMethods;
+ }
+ return sheetRef.current;
+ },
+ [sheetRef.current],
+ );
+
+ const renderBackdrop = React.useCallback(
+ (props: BottomSheetBackdropProps) => {
+ const {
+ pressBehavior = "close",
+ opacity = isDarkColorScheme ? 0.3 : 0.7,
+ disappearsOnIndex = CLOSED_INDEX,
style,
- ]}
- className={cn(`px-4`, className)}
+ onPress,
+ ...rest
+ } = {
+ ...props,
+ ...backdropProps,
+ };
+ return (
+ {
+ if (Keyboard.isVisible()) {
+ Keyboard.dismiss();
+ }
+ onPress?.();
+ }}
+ {...rest}
+ />
+ );
+ },
+ [backdropProps, colors],
+ );
+
+ return (
+
- {children}
-
+ />
);
+ },
+);
+
+const BottomSheetOpenTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ asChild?: boolean;
}
-
- type BottomSheetTextInputRef = React.ElementRef;
- type BottomSheetTextInputProps = React.ComponentPropsWithoutRef;
- const BottomSheetTextInput = React.forwardRef(
- ({ className, placeholderClassName, ...props }, ref) => {
- return (
-
- );
+>(({ onPress, asChild = false, ...props }, ref) => {
+ const { sheetRef } = useBottomSheetContext();
+ function handleOnPress(ev: GestureResponderEvent) {
+ sheetRef.current?.present();
+ onPress?.(ev);
+ }
+ const Trigger = asChild ? Slot.Pressable : Pressable;
+ return ;
+});
+
+const BottomSheetCloseTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ asChild?: boolean;
+ }
+>(({ onPress, asChild = false, ...props }, ref) => {
+ const { dismiss } = useBottomSheetModal();
+ function handleOnPress(ev: GestureResponderEvent) {
+ dismiss();
+ if (Keyboard.isVisible()) {
+ Keyboard.dismiss();
}
+ onPress?.(ev);
+ }
+ const Trigger = asChild ? Slot.Pressable : Pressable;
+ return ;
+});
+
+const BOTTOM_SHEET_HEADER_HEIGHT = 60; // BottomSheetHeader height
+
+type BottomSheetViewProps = Omit<
+ React.ComponentPropsWithoutRef,
+ "style"
+> & {
+ hadHeader?: boolean;
+ style?: ViewStyle;
+};
+
+function BottomSheetView({
+ className,
+ children,
+ hadHeader = true,
+ style,
+ ...props
+}: BottomSheetViewProps) {
+ const insets = useSafeAreaInsets();
+ return (
+
+ {children}
+
);
-
- type BottomSheetFlatListRef = React.ElementRef;
- type BottomSheetFlatListProps = React.ComponentPropsWithoutRef;
- const BottomSheetFlatList = React.forwardRef