{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "native-date-select",
  "title": "Native Date Select",
  "description": "A native date/time selection input built on Expo UI DatePicker (iOS) and DateTimePicker (Android). Always compose with Content; optionally add Trigger and Input for a form-styled field or custom trigger. Content opens a wheel bottom sheet on iOS and Material dialogs on Android.",
  "dependencies": [
    "@expo/ui",
    "react-native-reanimated"
  ],
  "registryDependencies": [
    "@tetra-ui/action-input",
    "@tetra-ui/bottom-sheet",
    "@tetra-ui/icons",
    "@tetra-ui/input",
    "@tetra-ui/slot"
  ],
  "files": [
    {
      "path": "ui/native-date-select/index.ts",
      "content": "export * from \"./native-date-select\";\nexport type {\n  NativeDateSelectDisplay,\n  NativeDateSelectMode,\n  NativeDateSelectPickerProps,\n  NativeDateSelectPresentation,\n  NativeDateSelectVariant,\n} from \"./native-date-select-picker\";\n",
      "type": "registry:ui"
    },
    {
      "path": "ui/native-date-select/native-date-select.tsx",
      "content": "import {\n  Children,\n  createContext,\n  isValidElement,\n  useCallback,\n  useContext,\n  useEffect,\n  useLayoutEffect,\n  useMemo,\n  useState,\n} from \"react\";\nimport {\n  type GestureResponderEvent,\n  Platform,\n  Pressable,\n  type PressableProps,\n  View,\n} from \"react-native\";\nimport Animated, {\n  Easing,\n  interpolate,\n  useAnimatedStyle,\n  useSharedValue,\n  withTiming,\n} from \"react-native-reanimated\";\nimport { cn } from \"@/lib/utils\";\nimport { ActionInput } from \"../action-input\";\nimport {\n  BottomSheet,\n  BottomSheetBody,\n  BottomSheetContent,\n  BottomSheetFooter,\n  BottomSheetHeader,\n  BottomSheetTitle,\n} from \"../bottom-sheet\";\nimport { ChevronDownIcon } from \"../icons\";\nimport {\n  InputAddon,\n  type InputAddonChild,\n  type InputAddonChildren,\n  InputAddonIcon,\n  useInputAddons,\n} from \"../input\";\nimport { Slot } from \"../slot\";\nimport {\n  type NativeDateSelectMode,\n  NativeDateSelectPicker,\n  type NativeDateSelectVariant,\n} from \"./native-date-select-picker\";\n\n// Constants\nconst ANIMATION_DURATION = 280;\nconst ANIMATION_EASING = Easing.out(Easing.cubic);\nconst NATIVE_DATE_SELECT_INPUT_NAME = \"NativeDateSelectInput\";\nconst NATIVE_DATE_SELECT_TRIGGER_NAME = \"NativeDateSelectTrigger\";\nconst NATIVE_DATE_SELECT_CONTENT_NAME = \"NativeDateSelectContent\";\nconst NATIVE_DATE_SELECT_SHEET_FOOTER_NAME = \"NativeDateSelectSheetFooter\";\nconst WHEEL_PICKER_HEIGHT = 216;\nconst DEFAULT_PLACEHOLDER = \"Pick a date\";\n\n// Types\ntype NativeDateSelectContextProps = {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  value?: Date;\n  onValueChange: (value: Date) => void;\n  selectedValue?: Date;\n  setSelectedValue: (value: Date) => void;\n  onConfirm: (value?: Date) => void;\n  onCancel: () => void;\n  disabled?: boolean;\n  mode: NativeDateSelectMode;\n  variant: NativeDateSelectVariant;\n  setVariant: (variant: NativeDateSelectVariant) => void;\n  minimumDate?: Date;\n  maximumDate?: Date;\n  is24Hour?: boolean;\n  placeholder: string;\n  setPlaceholder: (placeholder: string) => void;\n  hasTrigger: boolean;\n  hasInput: boolean;\n  className?: string;\n  testID?: string;\n};\n\ntype NativeDateSelectProps = {\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  value?: Date;\n  onValueChange?: (value: Date) => void;\n  mode?: NativeDateSelectMode;\n  variant?: NativeDateSelectVariant;\n  minimumDate?: Date;\n  maximumDate?: Date;\n  disabled?: boolean;\n  is24Hour?: boolean;\n  className?: string;\n  testID?: string;\n  children?: React.ReactNode;\n};\n\ntype NativeDateSelectInputProps = Partial<\n  React.ComponentProps<typeof ActionInput>\n> & {\n  variant?: NativeDateSelectVariant;\n  placeholder?: string;\n  formatValue?: (date: Date) => string;\n  children?: React.ReactNode;\n};\n\ntype NativeDateSelectTriggerProps = PressableProps & {\n  asChild?: boolean;\n};\n\ntype NativeDateSelectContentProps = {\n  children?: React.ReactNode;\n};\n\ntype NativeDateSelectSheetConfirmProps = PressableProps & {\n  asChild?: boolean;\n};\n\n// Context\nconst NativeDateSelectContext =\n  createContext<NativeDateSelectContextProps | null>(null);\n\nconst useNativeDateSelect = () => {\n  const context = useContext(NativeDateSelectContext);\n  if (!context) {\n    throw new Error(\n      \"useNativeDateSelect must be used within a NativeDateSelect\"\n    );\n  }\n  return context;\n};\n\n// Helpers\nconst getDisplayName = (type: React.ReactElement[\"type\"]) => {\n  if (typeof type === \"string\" || !(\"displayName\" in type)) {\n    return;\n  }\n  return type.displayName;\n};\n\nconst formatDateByMode = (date: Date, mode: NativeDateSelectMode) => {\n  switch (mode) {\n    case \"time\":\n      return new Intl.DateTimeFormat(undefined, {\n        hour: \"numeric\",\n        minute: \"2-digit\",\n      }).format(date);\n    case \"datetime\":\n      return new Intl.DateTimeFormat(undefined, {\n        day: \"numeric\",\n        hour: \"numeric\",\n        minute: \"2-digit\",\n        month: \"short\",\n        year: \"numeric\",\n      }).format(date);\n    default:\n      return new Intl.DateTimeFormat(undefined, {\n        day: \"numeric\",\n        month: \"short\",\n        year: \"numeric\",\n      }).format(date);\n  }\n};\n\nconst findNativeDateSelectSheetFooter = (children: React.ReactNode) => {\n  for (const child of Children.toArray(children)) {\n    if (\n      isValidElement(child) &&\n      (child.type === NativeDateSelectSheetFooter ||\n        getDisplayName(child.type) === NATIVE_DATE_SELECT_SHEET_FOOTER_NAME)\n    ) {\n      return child;\n    }\n  }\n};\n\nconst getNativeDateSelectFormFlags = (children: React.ReactNode) => {\n  let hasTrigger = false;\n  let hasInput = false;\n  let inputVariant: NativeDateSelectVariant | undefined;\n\n  const visit = (node: React.ReactNode) => {\n    for (const child of Children.toArray(node)) {\n      if (!isValidElement(child)) {\n        continue;\n      }\n\n      const name = getDisplayName(child.type);\n      if (name === NATIVE_DATE_SELECT_TRIGGER_NAME) {\n        hasTrigger = true;\n      }\n      if (name === NATIVE_DATE_SELECT_INPUT_NAME) {\n        hasInput = true;\n        const props = child.props as { variant?: NativeDateSelectVariant };\n        inputVariant = props.variant;\n      }\n\n      if (\n        child.props &&\n        typeof child.props === \"object\" &&\n        \"children\" in child.props\n      ) {\n        visit((child.props as { children?: React.ReactNode }).children);\n      }\n    }\n  };\n\n  visit(children);\n\n  return { hasInput, hasTrigger, inputVariant };\n};\n\n// Components\n/**\n * Native date/time select built on Expo UI DatePicker (iOS) and DateTimePicker (Android).\n * Always compose with NativeDateSelectContent. Optionally add Trigger and Input.\n */\nexport const NativeDateSelect = ({\n  open: openProp,\n  onOpenChange: onOpenChangeProp,\n  value: valueProp,\n  onValueChange: onValueChangeProp,\n  mode = \"date\",\n  variant: variantProp = \"default\",\n  minimumDate,\n  maximumDate,\n  disabled,\n  is24Hour,\n  className,\n  testID,\n  children,\n}: NativeDateSelectProps) => {\n  const [internalOpen, setInternalOpen] = useState(openProp ?? false);\n  const [internalValue, setInternalValue] = useState<Date>();\n  const [selectedValue, setSelectedValue] = useState<Date>();\n  const [placeholder, setPlaceholder] = useState(DEFAULT_PLACEHOLDER);\n\n  const { hasTrigger, hasInput, inputVariant } = useMemo(\n    () => getNativeDateSelectFormFlags(children),\n    [children]\n  );\n  // Seeded from Input override, else root. Do not re-sync from root props or\n  // an Input override will be overwritten.\n  const [variant, setVariant] = useState<NativeDateSelectVariant>(\n    () => inputVariant ?? variantProp\n  );\n\n  const isOpenControlled = openProp !== undefined;\n  const open = isOpenControlled ? openProp : internalOpen;\n\n  const isValueControlled = valueProp !== undefined;\n  const value = isValueControlled ? valueProp : internalValue;\n\n  useEffect(() => {\n    if (value !== undefined) {\n      setSelectedValue(value);\n    }\n  }, [value]);\n\n  const onOpenChange = useCallback(\n    (nextOpen: boolean) => {\n      if (!isOpenControlled) {\n        setInternalOpen(nextOpen);\n      }\n      onOpenChangeProp?.(nextOpen);\n    },\n    [isOpenControlled, onOpenChangeProp]\n  );\n\n  const onValueChange = useCallback(\n    (nextValue: Date) => {\n      if (!isValueControlled) {\n        setInternalValue(nextValue);\n      }\n      onValueChangeProp?.(nextValue);\n    },\n    [isValueControlled, onValueChangeProp]\n  );\n\n  const onConfirm = useCallback(\n    (nextValue?: Date) => {\n      const finalValue = nextValue ?? selectedValue;\n\n      if (finalValue !== undefined) {\n        onValueChange(finalValue);\n      }\n\n      onOpenChange(false);\n    },\n    [onOpenChange, onValueChange, selectedValue]\n  );\n\n  const onCancel = useCallback(() => {\n    if (value !== undefined) {\n      setSelectedValue(value);\n    }\n    onOpenChange(false);\n  }, [onOpenChange, value]);\n\n  const ctx = useMemo(\n    () => ({\n      className,\n      disabled,\n      hasInput,\n      hasTrigger,\n      is24Hour,\n      maximumDate,\n      minimumDate,\n      mode,\n      onCancel,\n      onConfirm,\n      onOpenChange,\n      onValueChange,\n      open,\n      placeholder,\n      selectedValue,\n      setPlaceholder,\n      setSelectedValue,\n      setVariant,\n      testID,\n      value,\n      variant,\n    }),\n    [\n      className,\n      disabled,\n      hasInput,\n      hasTrigger,\n      is24Hour,\n      maximumDate,\n      minimumDate,\n      mode,\n      onCancel,\n      onConfirm,\n      onOpenChange,\n      onValueChange,\n      open,\n      placeholder,\n      selectedValue,\n      testID,\n      value,\n      variant,\n    ]\n  );\n\n  return (\n    <NativeDateSelectContext.Provider value={ctx}>\n      {children}\n    </NativeDateSelectContext.Provider>\n  );\n};\n\nexport const NativeDateSelectTrigger = ({\n  asChild,\n  onPress: onPressProp,\n  ...props\n}: NativeDateSelectTriggerProps) => {\n  const { disabled, onOpenChange, value, selectedValue, setSelectedValue } =\n    useNativeDateSelect();\n\n  const handlePress = useCallback(\n    (event: GestureResponderEvent) => {\n      onPressProp?.(event);\n\n      if (disabled) {\n        return;\n      }\n\n      const seedValue = selectedValue ?? value ?? new Date();\n      setSelectedValue(seedValue);\n      onOpenChange(true);\n    },\n    [\n      disabled,\n      onOpenChange,\n      onPressProp,\n      selectedValue,\n      setSelectedValue,\n      value,\n    ]\n  );\n\n  const Comp = asChild ? Slot.Pressable : Pressable;\n\n  return <Comp {...props} disabled={disabled} onPress={handlePress} />;\n};\n\nNativeDateSelectTrigger.displayName = NATIVE_DATE_SELECT_TRIGGER_NAME;\n\n/**\n * Form-styled native date select input.\n * - Default / wheel: display-only ActionInput (open via NativeDateSelectTrigger)\n * - iOS `compact`: non-pressable input shell; only the native compact DatePicker is interactive\n */\nexport const NativeDateSelectInput = ({\n  variant: variantProp,\n  placeholder = DEFAULT_PLACEHOLDER,\n  formatValue,\n  className,\n  testID,\n  children,\n  ...props\n}: NativeDateSelectInputProps) => {\n  const {\n    open,\n    value,\n    onValueChange,\n    selectedValue,\n    disabled,\n    mode,\n    variant: variantFromRoot,\n    minimumDate,\n    maximumDate,\n    is24Hour,\n    setPlaceholder,\n    setVariant,\n  } = useNativeDateSelect();\n\n  const variant = variantProp ?? variantFromRoot;\n\n  const addonElements = useMemo(() => {\n    const addons: InputAddonChild[] = [];\n    for (const child of Children.toArray(children)) {\n      if (isValidElement(child) && child.type === InputAddon) {\n        addons.push(child as InputAddonChild);\n      }\n    }\n    return addons;\n  }, [children]);\n\n  const { startAddons, endAddons, pressableClassName } = useInputAddons(\n    addonElements as InputAddonChildren\n  );\n\n  useLayoutEffect(() => {\n    setPlaceholder(placeholder);\n  }, [placeholder, setPlaceholder]);\n\n  useLayoutEffect(() => {\n    if (variantProp !== undefined) {\n      setVariant(variantProp);\n    }\n  }, [variantProp, setVariant]);\n\n  const committedValue = value;\n  const pickerValue = selectedValue ?? committedValue ?? new Date();\n\n  const valueLabel = useMemo(() => {\n    if (committedValue === undefined) {\n      return;\n    }\n    return formatValue\n      ? formatValue(committedValue)\n      : formatDateByMode(committedValue, mode);\n  }, [committedValue, formatValue, mode]);\n\n  const openSharedValue = useSharedValue(open ? 1 : 0);\n\n  useEffect(() => {\n    openSharedValue.value = withTiming(open ? 1 : 0, {\n      duration: ANIMATION_DURATION,\n      easing: ANIMATION_EASING,\n    });\n  }, [open, openSharedValue]);\n\n  const animatedStyle = useAnimatedStyle(() => {\n    const rotate = interpolate(openSharedValue.value, [0, 1], [0, 180]);\n    return {\n      transform: [{ rotate: `${rotate}deg` }],\n    };\n  });\n\n  if (Platform.OS === \"ios\" && variant === \"compact\") {\n    return (\n      <View\n        className={cn(\n          \"flex min-h-12 w-full flex-row items-center gap-2 rounded-lg border border-input bg-background py-2 pr-0 pl-3\",\n          disabled && \"opacity-50\",\n          pressableClassName,\n          className\n        )}\n      >\n        {startAddons}\n\n        <View className=\"min-w-0 grow\" />\n\n        <InputAddon align=\"inline-end\" className=\"shrink-0\">\n          <NativeDateSelectPicker\n            disabled={disabled}\n            is24Hour={is24Hour}\n            maximumDate={maximumDate}\n            minimumDate={minimumDate}\n            mode={mode}\n            onValueChange={onValueChange}\n            testID={testID}\n            value={pickerValue}\n            variant=\"compact\"\n          />\n        </InputAddon>\n\n        {endAddons}\n      </View>\n    );\n  }\n\n  const sheetInputAddons = [\n    ...startAddons,\n    <InputAddon align=\"inline-end\" key=\"native-date-select-chevron\">\n      <Animated.View style={animatedStyle}>\n        <InputAddonIcon>\n          <ChevronDownIcon />\n        </InputAddonIcon>\n      </Animated.View>\n    </InputAddon>,\n    ...endAddons,\n  ] as InputAddonChildren;\n\n  return (\n    <ActionInput\n      {...props}\n      className={cn(pressableClassName, className)}\n      disabled={disabled}\n      focused={open}\n      placeholder={placeholder}\n      testID={testID}\n      value={valueLabel}\n    >\n      {sheetInputAddons}\n    </ActionInput>\n  );\n};\n\nNativeDateSelectInput.displayName = NATIVE_DATE_SELECT_INPUT_NAME;\n\n/**\n * Presentation surface for the native date select. Always required.\n * - Content-only: inline native picker (variant from root)\n * - iOS wheel/default + form UI: bottom sheet with wheel DatePicker\n * - iOS compact + Input: no sheet (picker lives in NativeDateSelectInput)\n * - Android + form UI: Material date/time dialog when open\n */\nexport const NativeDateSelectContent = ({\n  children,\n}: NativeDateSelectContentProps) => {\n  const {\n    open,\n    onOpenChange,\n    value,\n    onValueChange,\n    selectedValue,\n    setSelectedValue,\n    onCancel,\n    disabled,\n    mode,\n    variant,\n    minimumDate,\n    maximumDate,\n    is24Hour,\n    placeholder,\n    hasTrigger,\n    hasInput,\n    className,\n    testID,\n  } = useNativeDateSelect();\n\n  const hasFormUi = hasTrigger || hasInput;\n\n  const sheetFooter = useMemo(\n    () => findNativeDateSelectSheetFooter(children),\n    [children]\n  );\n\n  const requiresConfirm =\n    Platform.OS === \"ios\" && hasFormUi && Boolean(sheetFooter);\n  const committedValue = value;\n  const draftValue = selectedValue ?? committedValue ?? new Date();\n  const pickerValue = requiresConfirm\n    ? draftValue\n    : (committedValue ?? draftValue);\n\n  const handlePickerValueChange = useCallback(\n    (nextValue: Date) => {\n      if (requiresConfirm) {\n        setSelectedValue(nextValue);\n        return;\n      }\n      onValueChange(nextValue);\n    },\n    [onValueChange, requiresConfirm, setSelectedValue]\n  );\n\n  if (!hasFormUi) {\n    return (\n      <NativeDateSelectPicker\n        className={className}\n        disabled={disabled}\n        is24Hour={is24Hour}\n        maximumDate={maximumDate}\n        minimumDate={minimumDate}\n        mode={mode}\n        onValueChange={onValueChange}\n        presentation=\"inline\"\n        testID={testID}\n        value={committedValue ?? new Date()}\n        variant={variant}\n      />\n    );\n  }\n\n  if (Platform.OS === \"ios\" && variant === \"compact\" && hasInput) {\n    return null;\n  }\n\n  if (Platform.OS === \"ios\") {\n    return (\n      <BottomSheet\n        onOpenChange={requiresConfirm ? onCancel : onOpenChange}\n        open={open}\n      >\n        <BottomSheetContent>\n          <BottomSheetHeader>\n            <BottomSheetTitle>{placeholder}</BottomSheetTitle>\n          </BottomSheetHeader>\n          <BottomSheetBody className={sheetFooter ? undefined : \"pb-4\"}>\n            <NativeDateSelectPicker\n              disabled={disabled}\n              is24Hour={is24Hour}\n              matchContents={false}\n              maximumDate={maximumDate}\n              minimumDate={minimumDate}\n              mode={mode}\n              onValueChange={handlePickerValueChange}\n              style={{ height: WHEEL_PICKER_HEIGHT, width: \"100%\" }}\n              testID={testID}\n              value={pickerValue}\n              variant=\"wheel\"\n            />\n          </BottomSheetBody>\n          {sheetFooter}\n        </BottomSheetContent>\n      </BottomSheet>\n    );\n  }\n\n  if (!open) {\n    return null;\n  }\n\n  return (\n    <NativeDateSelectPicker\n      disabled={disabled}\n      is24Hour={is24Hour}\n      maximumDate={maximumDate}\n      minimumDate={minimumDate}\n      mode={mode}\n      onDismiss={onCancel}\n      onValueChange={(nextValue) => {\n        onValueChange(nextValue);\n        onOpenChange(false);\n      }}\n      presentation=\"dialog\"\n      testID={testID}\n      value={pickerValue}\n      variant={variant}\n    />\n  );\n};\n\nNativeDateSelectContent.displayName = NATIVE_DATE_SELECT_CONTENT_NAME;\n\nexport const NativeDateSelectSheetFooter = (\n  props: React.ComponentProps<typeof BottomSheetFooter>\n) => {\n  return <BottomSheetFooter {...props} />;\n};\n\nNativeDateSelectSheetFooter.displayName = NATIVE_DATE_SELECT_SHEET_FOOTER_NAME;\n\nexport const NativeDateSelectSheetConfirm = ({\n  asChild,\n  onPress: onPressProp,\n  ...props\n}: NativeDateSelectSheetConfirmProps) => {\n  const { onConfirm } = useNativeDateSelect();\n\n  const onPress = useCallback(\n    (event: GestureResponderEvent) => {\n      onPressProp?.(event);\n      onConfirm();\n    },\n    [onConfirm, onPressProp]\n  );\n\n  const Comp = asChild ? Slot.Pressable : Pressable;\n\n  return <Comp {...props} onPress={onPress} />;\n};\n",
      "type": "registry:ui"
    },
    {
      "path": "ui/native-date-select/native-date-select-picker.tsx",
      "content": "import {\n  DatePickerDialog,\n  DateTimePicker,\n  Host as HostPrimitive,\n  TimePickerDialog,\n} from \"@expo/ui/jetpack-compose\";\nimport { useState } from \"react\";\nimport type { StyleProp, ViewStyle } from \"react-native\";\nimport { useCSSVariable, withUniwind } from \"uniwind\";\nimport { cn } from \"@/lib/utils\";\n\nconst StyledHost = withUniwind(HostPrimitive);\n\nexport type NativeDateSelectMode = \"date\" | \"time\" | \"datetime\";\nexport type NativeDateSelectVariant =\n  | \"default\"\n  | \"wheel\"\n  | \"compact\"\n  | \"graphical\";\n/** @deprecated Use NativeDateSelectVariant */\nexport type NativeDateSelectDisplay = NativeDateSelectVariant;\nexport type NativeDateSelectPresentation = \"inline\" | \"dialog\";\n\nexport type NativeDateSelectPickerProps = {\n  value: Date;\n  onValueChange: (value: Date) => void;\n  mode?: NativeDateSelectMode;\n  variant?: NativeDateSelectVariant;\n  minimumDate?: Date;\n  maximumDate?: Date;\n  disabled?: boolean;\n  is24Hour?: boolean;\n  presentation?: NativeDateSelectPresentation;\n  onDismiss?: () => void;\n  className?: string;\n  style?: StyleProp<ViewStyle>;\n  testID?: string;\n  matchContents?: boolean;\n};\n\nconst modeToDisplayedComponents = (\n  mode: NativeDateSelectMode\n): \"date\" | \"hourAndMinute\" => {\n  if (mode === \"time\") {\n    return \"hourAndMinute\";\n  }\n  return \"date\";\n};\n\nconst variantToAndroidPickerVariant = (\n  variant: NativeDateSelectVariant\n): \"picker\" | \"input\" => {\n  if (variant === \"wheel\") {\n    return \"input\";\n  }\n  return \"picker\";\n};\n\nconst mergeDateAndTime = (datePart: Date, timePart: Date) => {\n  const next = new Date(datePart);\n  next.setHours(\n    timePart.getHours(),\n    timePart.getMinutes(),\n    timePart.getSeconds(),\n    timePart.getMilliseconds()\n  );\n  return next;\n};\n\n/**\n * Android native date/time picker.\n * - `presentation=\"inline\"`: Compose DateTimePicker (date or time; datetime falls back to date)\n * - `presentation=\"dialog\"`: Material dialogs; datetime shows date then time sequentially\n */\nexport const NativeDateSelectPicker = ({\n  value,\n  onValueChange,\n  mode = \"date\",\n  variant = \"default\",\n  minimumDate,\n  maximumDate,\n  is24Hour,\n  presentation = \"inline\",\n  onDismiss,\n  className,\n  style,\n}: NativeDateSelectPickerProps) => {\n  const primaryColor = useCSSVariable(\"--color-primary\") as string;\n  const [dialogStep, setDialogStep] = useState<\"date\" | \"time\">(\n    mode === \"time\" ? \"time\" : \"date\"\n  );\n  const [pendingDate, setPendingDate] = useState(value);\n\n  const selectableDates =\n    minimumDate || maximumDate\n      ? { end: maximumDate, start: minimumDate }\n      : undefined;\n\n  if (presentation === \"dialog\") {\n    const handleDismiss = () => {\n      setDialogStep(mode === \"time\" ? \"time\" : \"date\");\n      onDismiss?.();\n    };\n\n    if (mode === \"time\" || dialogStep === \"time\") {\n      return (\n        <HostPrimitive style={style}>\n          <TimePickerDialog\n            color={primaryColor}\n            initialDate={(mode === \"datetime\"\n              ? pendingDate\n              : value\n            ).toISOString()}\n            is24Hour={is24Hour}\n            onDateSelected={(date) => {\n              const next =\n                mode === \"datetime\"\n                  ? mergeDateAndTime(pendingDate, date)\n                  : date;\n              setDialogStep(mode === \"time\" ? \"time\" : \"date\");\n              onValueChange(next);\n            }}\n            onDismissRequest={handleDismiss}\n          />\n        </HostPrimitive>\n      );\n    }\n\n    return (\n      <HostPrimitive style={style}>\n        <DatePickerDialog\n          color={primaryColor}\n          initialDate={value.toISOString()}\n          onDateSelected={(date) => {\n            if (mode === \"datetime\") {\n              setPendingDate(date);\n              setDialogStep(\"time\");\n              return;\n            }\n            onValueChange(date);\n          }}\n          onDismissRequest={handleDismiss}\n          selectableDates={selectableDates}\n          variant={variantToAndroidPickerVariant(variant)}\n        />\n      </HostPrimitive>\n    );\n  }\n\n  return (\n    <StyledHost\n      className={cn(\"w-full\", className)}\n      matchContents={{ vertical: true }}\n      style={[{ width: \"100%\" }, style]}\n    >\n      <DateTimePicker\n        color={primaryColor}\n        displayedComponents={modeToDisplayedComponents(mode)}\n        initialDate={value.toISOString()}\n        is24Hour={is24Hour}\n        onDateSelected={onValueChange}\n        selectableDates={selectableDates}\n        showVariantToggle={false}\n        variant={variantToAndroidPickerVariant(variant)}\n      />\n    </StyledHost>\n  );\n};\n",
      "type": "registry:ui"
    },
    {
      "path": "ui/native-date-select/native-date-select-picker.ios.tsx",
      "content": "import { DatePicker, Host as HostPrimitive } from \"@expo/ui/swift-ui\";\nimport {\n  datePickerStyle,\n  disabled as disabledModifier,\n  labelsHidden,\n  type ModifierConfig,\n  tint,\n} from \"@expo/ui/swift-ui/modifiers\";\nimport type { StyleProp, ViewStyle } from \"react-native\";\nimport { useCSSVariable, withUniwind } from \"uniwind\";\nimport { cn } from \"@/lib/utils\";\n\nconst StyledHost = withUniwind(HostPrimitive);\n\nexport type NativeDateSelectMode = \"date\" | \"time\" | \"datetime\";\nexport type NativeDateSelectVariant =\n  | \"default\"\n  | \"wheel\"\n  | \"compact\"\n  | \"graphical\";\n/** @deprecated Use NativeDateSelectVariant */\nexport type NativeDateSelectDisplay = NativeDateSelectVariant;\nexport type NativeDateSelectPresentation = \"inline\" | \"dialog\";\n\nexport type NativeDateSelectPickerProps = {\n  value: Date;\n  onValueChange: (value: Date) => void;\n  mode?: NativeDateSelectMode;\n  variant?: NativeDateSelectVariant;\n  minimumDate?: Date;\n  maximumDate?: Date;\n  disabled?: boolean;\n  is24Hour?: boolean;\n  presentation?: NativeDateSelectPresentation;\n  onDismiss?: () => void;\n  className?: string;\n  style?: StyleProp<ViewStyle>;\n  testID?: string;\n  matchContents?: boolean;\n};\n\nconst modeToDisplayedComponents = (\n  mode: NativeDateSelectMode\n): (\"date\" | \"hourAndMinute\")[] => {\n  switch (mode) {\n    case \"time\":\n      return [\"hourAndMinute\"];\n    case \"datetime\":\n      return [\"date\", \"hourAndMinute\"];\n    default:\n      return [\"date\"];\n  }\n};\n\nconst variantToDatePickerStyle = (\n  variant: NativeDateSelectVariant\n): \"automatic\" | \"compact\" | \"graphical\" | \"wheel\" => {\n  switch (variant) {\n    case \"wheel\":\n      return \"wheel\";\n    case \"compact\":\n      return \"compact\";\n    case \"graphical\":\n      return \"graphical\";\n    default:\n      return \"automatic\";\n  }\n};\n\n/**\n * iOS native date/time picker via SwiftUI DatePicker.\n * `presentation` is ignored (always inline).\n */\nexport const NativeDateSelectPicker = ({\n  value,\n  onValueChange,\n  mode = \"date\",\n  variant = \"default\",\n  minimumDate,\n  maximumDate,\n  disabled,\n  className,\n  style,\n  testID,\n  matchContents = true,\n}: NativeDateSelectPickerProps) => {\n  const primaryColor = useCSSVariable(\"--color-primary\") as string;\n\n  const modifiers: ModifierConfig[] = [\n    datePickerStyle(variantToDatePickerStyle(variant)),\n    tint(primaryColor),\n  ];\n\n  if (variant === \"compact\") {\n    modifiers.push(labelsHidden());\n  }\n\n  if (disabled) {\n    modifiers.push(disabledModifier(true));\n  }\n\n  return (\n    <StyledHost\n      className={cn(className)}\n      matchContents={matchContents}\n      style={style}\n    >\n      <DatePicker\n        displayedComponents={modeToDisplayedComponents(mode)}\n        modifiers={modifiers}\n        onDateChange={onValueChange}\n        range={\n          minimumDate || maximumDate\n            ? { end: maximumDate, start: minimumDate }\n            : undefined\n        }\n        selection={value}\n        testID={testID}\n      />\n    </StyledHost>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}
