{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "manual-address-inputs",
  "title": "Manual Address Inputs",
  "description": "Manual address form primitives.",
  "dependencies": [
    "mapbox-gl"
  ],
  "registryDependencies": [
    "@circle-ui/textbox"
  ],
  "files": [
    {
      "path": "registry/berlin/blocks/address.tsx",
      "content": "// Generated from packages/ui/src/components/address.tsx\n\"use client\";\n\nimport * as React from \"react\";\nimport type { Map as MapboxMap } from \"mapbox-gl\";\n\nimport { TextBox } from \"@/registry/berlin/circle-ui/textbox\";\n\nexport type SupportedLocale = \"en\" | \"de\";\n\nexport interface Address {\n  address?: string;\n  address2?: string;\n  city?: string;\n  postal_code?: string;\n  country?: string;\n  country_code?: string;\n  province?: string;\n}\n\ntype AddressAutofillResult = {\n  features?: Array<{\n    properties?: {\n      address_line1?: string;\n      postcode?: string;\n      place?: string;\n      country?: string;\n    };\n  }>;\n};\n\ntype AddressAutofillInputProps = {\n  label: string;\n  name: string;\n  onChange?: React.ChangeEventHandler<HTMLInputElement>;\n  onBlur: React.FocusEventHandler<HTMLInputElement>;\n  value?: string;\n  className?: string;\n  required?: boolean;\n  placeholder?: string;\n  accessToken?: string;\n  onAddressSelect?: (address: AddressAutofillResult) => void;\n};\n\nconst labels = {\n  en: {\n    address: \"Address\",\n    enterManually: \"Enter manually\",\n    form: {\n      address: \"Address\",\n      address2: \"Address 2\",\n      postalCode: \"Postal Code\",\n      city: \"City\",\n      country: \"Country\"\n    }\n  },\n  de: {\n    address: \"Adresse\",\n    enterManually: \"Manuell eingeben\",\n    form: {\n      address: \"Adresse\",\n      address2: \"Adresse 2\",\n      postalCode: \"Postleitzahl\",\n      city: \"Stadt\",\n      country: \"Land\"\n    }\n  }\n} satisfies Record<\n  SupportedLocale,\n  {\n    address: string;\n    enterManually: string;\n    form: {\n      address: string;\n      address2: string;\n      postalCode: string;\n      city: string;\n      country: string;\n    };\n  }\n>;\n\nconst styles = {\n  formWrapper: {\n    display: \"flex\",\n    flexDirection: \"column\",\n    gap: \"1rem\",\n  } satisfies React.CSSProperties,\n  formRow: {\n    display: \"flex\",\n    flexDirection: \"row\",\n    gap: \"1rem\",\n    width: \"100%\",\n  } satisfies React.CSSProperties,\n  manualAddressButton: {\n    color: \"var(--Black, #000)\",\n    fontFamily: \"\\\"Be Vietnam Pro\\\"\",\n    cursor: \"pointer\",\n    textDecoration: \"underline\",\n    textAlign: \"left\",\n    fontSize: \"14px\",\n    marginTop: \"8px\",\n    background: \"transparent\",\n    border: \"0\",\n    padding: \"0\",\n  } satisfies React.CSSProperties,\n  autofillInput: {\n    padding: \"12px\",\n    borderRadius: \"8px\",\n    border: \"1px solid rgba(0, 0, 0, 0.10)\",\n    background: \"var(--White, #FFF)\",\n    fontSize: \"16px\",\n    lineHeight: \"24px\",\n    width: \"100%\",\n  } satisfies React.CSSProperties,\n  autofillWrapper: {\n    display: \"flex\",\n    flexDirection: \"column\",\n    gap: \"1rem\",\n    width: \"100%\",\n  } satisfies React.CSSProperties,\n};\n\nfunction extractAddressFromMapboxFeatureCollection(\n  featureCollection: AddressAutofillResult,\n) {\n  const features = featureCollection.features;\n  if (!features || features.length === 0) {\n    return null;\n  }\n\n  const feature = features[0];\n  if (!feature?.properties) {\n    return null;\n  }\n\n  const address = feature.properties.address_line1;\n  const postalCode = feature.properties.postcode;\n  const city = feature.properties.place;\n  const country = feature.properties.country;\n  return { address, postal_code: postalCode, city, country } satisfies Address;\n}\n\nfunction getMapboxToken(accessToken?: string) {\n  const runtime = globalThis as typeof globalThis & {\n    process?: {\n      env?: {\n        NEXT_PUBLIC_MAPBOX_TOKEN?: string;\n      };\n    };\n  };\n\n  return accessToken || runtime.process?.env?.NEXT_PUBLIC_MAPBOX_TOKEN || \"\";\n}\n\nfunction AddressAutofillInput({\n  name,\n  onChange,\n  onBlur,\n  value,\n  className = \"\",\n  required = false,\n  placeholder = \"\",\n  accessToken,\n  onAddressSelect,\n}: AddressAutofillInputProps) {\n  const mapboxToken = getMapboxToken(accessToken);\n  const [MapboxAddressAutofill, setMapboxAddressAutofill] =\n    React.useState<React.ComponentType<any> | null>(null);\n\n  React.useEffect(() => {\n    let isMounted = true;\n\n    void import(\"@mapbox/search-js-react\")\n      .then((module) => {\n        if (isMounted) {\n          setMapboxAddressAutofill(\n            () => module.AddressAutofill as React.ComponentType<any>,\n          );\n        }\n      })\n      .catch(() => {\n        if (isMounted) {\n          setMapboxAddressAutofill(null);\n        }\n      });\n\n    return () => {\n      isMounted = false;\n    };\n  }, []);\n\n  const handleRetrieve = (result: AddressAutofillResult) => {\n    onAddressSelect?.(result);\n  };\n\n  const input = (\n    <input\n      type=\"text\"\n      id={name}\n      name={name}\n      onChange={onChange}\n      onBlur={onBlur}\n      value={value}\n      className={className}\n      required={required}\n      autoComplete=\"shipping address-line1\"\n      placeholder={placeholder}\n      style={styles.autofillInput}\n    />\n  );\n\n  if (!MapboxAddressAutofill || !mapboxToken) {\n    return <div style={styles.autofillWrapper}>{input}</div>;\n  }\n\n  return (\n    <div style={styles.autofillWrapper}>\n      <div>\n        <MapboxAddressAutofill\n          accessToken={mapboxToken}\n          onRetrieve={handleRetrieve}\n          options={{\n            language: \"de\",\n          }}\n        >\n          {input}\n        </MapboxAddressAutofill>\n      </div>\n    </div>\n  );\n}\n\nexport interface AutoAddressInputsProps {\n  locale?: SupportedLocale;\n  accessToken?: string;\n  onSelectAddress?: (address: Address) => void;\n}\n\nexport function AutoAddressInputs({\n  locale = \"en\",\n  accessToken,\n  onSelectAddress\n}: AutoAddressInputsProps) {\n  const handleSelection = (value: AddressAutofillResult) => {\n    const address = extractAddressFromMapboxFeatureCollection(value);\n    if (address) {\n      onSelectAddress?.(address);\n    }\n  };\n\n  return (\n    <AddressAutofillInput\n      accessToken={accessToken}\n      label={labels[locale].address}\n      name=\"address\"\n      className=\"border border-gray-300 rounded-lg px-3 py-2 w-full\"\n      onBlur={() => {}}\n      onAddressSelect={handleSelection}\n      required\n    />\n  );\n}\n\nexport interface ManualAddressInputsProps {\n  value?: Address;\n  locale?: SupportedLocale;\n  onChange?: (address: Address) => void;\n}\n\nexport function ManualAddressInputs({\n  value,\n  locale = \"en\",\n  onChange\n}: ManualAddressInputsProps) {\n  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    const { name } = event.target;\n    onChange?.({ ...(value ?? {}), [name]: event.target.value });\n  };\n\n  return (\n    <>\n      <TextBox\n        name=\"address\"\n        label={labels[locale].form.address}\n        value={value?.address}\n        onChange={handleChange}\n      />\n      <TextBox\n        name=\"co\"\n        label={labels[locale].form.address2}\n        value={value?.address2}\n        onChange={handleChange}\n      />\n      <div style={styles.formRow}>\n        <TextBox\n          name=\"city\"\n          label={labels[locale].form.city}\n          value={value?.city}\n          onChange={handleChange}\n          required\n        />\n        <TextBox\n          name=\"postal_code\"\n          label={labels[locale].form.postalCode}\n          value={value?.postal_code}\n          onChange={handleChange}\n          required\n        />\n      </div>\n      <TextBox\n        name=\"country\"\n        label={labels[locale].form.country}\n        value={value?.country}\n        onChange={handleChange}\n        required\n      />\n    </>\n  );\n}\n\nexport interface AddressInputProps extends ManualAddressInputsProps {\n  accessToken?: string;\n}\n\nexport function AddressInput({\n  value,\n  onChange,\n  locale = \"de\",\n  accessToken\n}: AddressInputProps) {\n  const [showManualFields, setShowManualFields] = React.useState(false);\n\n  React.useEffect(() => {\n    if (value?.postal_code) {\n      setShowManualFields(true);\n    }\n  }, [value]);\n\n  return (\n    <div style={styles.formWrapper}>\n      {showManualFields ? (\n        <ManualAddressInputs locale={locale} value={value} onChange={onChange} />\n      ) : (\n        <div className=\"flex flex-col gap-0\">\n          <AutoAddressInputs\n            accessToken={accessToken}\n            locale={locale}\n            onSelectAddress={onChange}\n          />\n          <button\n            type=\"button\"\n            style={styles.manualAddressButton}\n            onClick={() => setShowManualFields(true)}\n          >\n            {labels[locale].enterManually}\n          </button>\n        </div>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "src/components/ui/address.tsx"
    }
  ],
  "type": "registry:ui"
}