npm package: @omnic/widget-locations
Description: Simple map widget for Omnic Delivery applications
Author: David Arutiunian
Latest version: 1.1.86

<h1 align="center">Omnic Widget Locations</h1>

## USAGE

### Integration in `standalone` mode

When build in `standalone` mode the widget exposes `window.OMNIC_WIDGET_LOCATIONS_CONFIG` config object.
Add script tag to your page and pass the config object to the widget like this:

```html
<script>
  window.OMNIC_WIDGET_LOCATIONS_CONFIG = {
    INN: "INN",
    locale: "en",
    map: {
      provider: "google",
      center: [55.75, 37.57],
    },
    onPointClick: (point: CallbackPoint) => {
      // TODO: process point click
    },
  };
</script>
```

The `onPointClick` callback will be called when user clicks on a point on the map. The `point` object has the following structure:

```typescript
type Coordinates = [number, number];

interface Country {
  uid: string;
  name: string;
  abbreviation: string;
}

interface Region {
  uid: string;
  name: string;
  national_id: string;
}

interface City {
  uid: string;
  name: string;
  region: Region;
  latitude: number;
  country: Country;
  longitude: number;
  national_id: string;
}

interface Location {
  city: City;
  house: string;
  block: string;
  street: string;
  office: string;
  region: Region;
  floor: unknown;
  latitude: number;
  country: Country;
  longitude: number;
  postal_index: string;
  full_address: string;
}

interface Timetable {
  1: string[];
  2: string[];
  3: string[];
  4: string[];
  5: string[];
  6: string[];
  7: string[];
}

interface LocationPoint {
  uid: string;
  name: string;
  code: string;
  type: number;
  brand: string;
  status: number;
  images: string[];
  schedule: string[];
  max_length: number;
  max_weight: number;
  is_pickup: boolean;
  location: Location;
  description: string;
  is_favorite: boolean;
  pay_by_cash: boolean;
  pay_by_card: boolean;
  is_delivery: boolean;
  near_station?: string;
  location_name?: string;
  is_check_order: boolean;
  round_the_clock: boolean;
  is_dressing_room: boolean;
  near_metro_station?: string;
  timetable: Timetable;
}

interface NormalizeAddressResponseData {
  country_name: string;
  country_code: string;
  region: string;
  city: string;
  latitude: number;
  longitude: number;
  street: string;
  house: string;
  block: string;
  office: string;
  postal_index: string;
  address: string;
  address_full: string;
  city_place_id: string;
  region_place_id: string;
  place_id: string;
}

export interface DeliveryPoint {
  coords: Coordinates;
  address: Nullable<string>;
}

export interface DeliveryPointWithFullAddress extends Omit<DeliveryPoint, "address"> {
  comment: string;
  address: Nullable<NormalizeAddressResponseData>;
  delivery_time: string;
  apartment_number: string;
  // pay_by_cash: boolean;
  // pay_by_card: boolean;
}

// THIS IS THE TYPE OF THE CALLBACK POINT
type CallbackPoint = LocationPoint | CourierDeliveryPoint;
```

Then `OMNIC_WIDGET_LOCATIONS_CONFIG` has the following structure:

| Property                        | Type                             | Description                                                                                                                      |
| ------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| INN                             | string                           | INN of the company that uses the widget                                                                                          |
| font                            | string                           | Font family to use                                                                                                               |
| radius                          | number                           | Border radius of buttons                                                                                                         |
| locale                          | string                           | Locale of the widget. Currently supported: `en`, `ru`                                                                            |
| country                         | string                           | Country code in ISO 3166-1 Alpha-2 format. Used to restrict address autocomplete to this country (unless `globalSearch` is true) |
| palette                         | object                           | Palette config object                                                                                                            |
| palette.primary                 | string                           | Primary color of the widget. Example: `#ff0000`                                                                                  |
| palette.primary-dark            | string                           | Darker version of the primary color. Example: `#cc0000`                                                                          |
| map                             | object                           | Map config object. See below for details                                                                                         |
| logo                            | string                           | Logo type. Accepts `default` or `llama`                                                                                          |
| map.provider                    | string                           | Map provider. Currently supported: `google`                                                                                      |
| map.center                      | number[]                         | Coordinates of the map center. Example: `[55.75, 37.57]`                                                                         |
| map.initialZoom                 | number                           | Initial zoom level of the map. Example: `10`                                                                                     |
| hideLogo                        | boolean                          | Whether to hide the logo                                                                                                         |
| startScreen                     | string                           | Start screen of the widget. Currently supported: `map`, `selector`                                                               |
| disableDelivery                 | boolean                          | Whether to disable delivery option                                                                                               |
| inputs                          | WidgetInputs                     | Control over widget inputs                                                                                                       |
| handlers                        | WidgetHandlers                   | Handlers config object                                                                                                           |
| hideHeader                      | boolean                          | Whether to hide header                                                                                                           |
| hideFilters                     | boolean                          | Whether to hide filters                                                                                                          |
| hideDetails                     | boolean                          | Whether to hide details                                                                                                          |
| hideSearchInput                 | boolean                          | Whether to hide search input                                                                                                     |
| hideMapControls                 | boolean                          | Whether to hide map controls                                                                                                     |
| hideDeliveryTime                | boolean                          | Whether to hide delivery time                                                                                                    |
| hideCloseButtonOnLocationScreen | boolean                          | Whether to hide close button on location screen                                                                                  |
| disableGeolocation              | boolean                          | Whether to disable geolocation                                                                                                   |
| globalSearch                    | boolean                          | If true, address autocomplete searches worldwide instead of restricting to `country`                                           |
| skipPointInfo                   | boolean                          | if true - open parcel-locker details window immediately                                                                          |
| cornersVariant                  | 'sharp', 'rounded'               | components corners variant                                                                                                       |
| mapTheme                        | 'omnic', 'llama', 'chip'         | Change map color scheme                                                                                                          |
| iconType                        | 'omnic', 'omni-llama', 'we-chip' | Change icon type                                                                                                                 |
| onPointClick                    | function                         | Callback that will be called when user clicks on a point on the map.                                                             |
| onLocationSelect                | function                         | Callback that will be called when user selects a location Callback will be called with `google.maps.places.PlaceResult` argument |
| onCloseLocationSelector         | function                         | Callback that will be called when user closes location selector                                                                  |
| gMapKey                         | string                           | Google Maps API key                                                                                                              |
| gMapId                          | string                           | Google Map ID (for map styling)                                                                                                  |
| countryAbbreviation             | string                           | used for points loading                                                                                                          |
| regionName                      | string                           | used for points loading                                                                                                          |
| cityName                        | string                           | used for points loading                                                                                                          |
| warehouseSelection              | boolean                          | enable/disable select a warehouse on the map                                                                                     |
| onWarehouseSelect               | function                         | Callback that will be called when user select on a warehouse on the map.                                                         |
| onSamePointsClusterClick        | function                         | Callback that will be called when user clicks on a cluster of same-location points. Receives `LocationPoint[]`                   |

`WidgetInputs` type has the following structure:

```typescript
interface ForwardedInputElement extends Pick<HTMLInputElement, "focus" | "blur"> {
  setValue: (value: string) => void;
}

interface InputConfig {
  name: string;
  ref: RefObject<ForwardedInputElement>;
  onClick?: (name: string) => void;
}

interface WidgetInputs {
  /**
    Widget Map address input
   */
  address: InputConfig;
  /**
   * Widget city input
   */
  city: InputConfig;
  /**
   * Delivery apartment input
   */
  apartment: InputConfig;
  /**
   * Delivery comment input
   */
  comment: InputConfig;
}
```

`WidgetHandlers` type has the following structure:

```typescript
interface LocationSelectorElement {
  open: () => void;
  close: () => void;
}

interface WidgetHandlers {
  locationSelector: RefObject<LocationSelectorElement>;
}
```

**NOTE:** when using screen keyboard do not forget to call `focus()` method for `address` and `city` inputs, so that autocomplete will appear.

Include `styles.css` and `widget.umd.js` in your page:

```html
<link rel="stylesheet" href="styles.css" />
<script src="widget.umd.js"></script>
```

After that you can create a div block with id `@omnic/widget-locations` and widget will be rendered there:

```html
<div id="@omnic/widget-locations"></div>
```

### Integration in `React` mode

When build in `React` mode the widget exposes `Widget` component. First install a package:

```bash
npm install @omnic/widget-locations
```

Then import it and use like this:

```tsx
import React from "react";

import { Widget } from "@omnic/widget-locations";
import type { LocationPoint, DeliveryPoint } from "@omnic/widget-locations";

import "@omnic/widget-locations/dist/lib/style.css";

const App = () => {
  const onPointClick = (point: LocationPoint | DeliveryPoint) => {
    // TODO: process point click
  };

  return (
    <Widget /> {/* 👈 don't forget to provide `config` props */}
  );
};
```

`Widget` component has the following props:

| Property        | Type   | Description                                                    |
| --------------- | ------ | -------------------------------------------------------------- |
| config          | object | Config object. See above for details                           |
| options         | object | Options object                                                 |
| options.baseURL | string | Base URL of the widget API. Example: `https://widget.omnic.sh` |

DON'T FORGET to wrap the widget in a div with id `@omnic/widget-locations`, so that all css styles will be applied correctly.

## DEVELOPMENT

### Project setup

Install all dependencies:

```bash
$ npm install
```

Then build it in `lib` mode:

```bash
$ npm run build:lib
```

or `standalone` mode:

```bash
$ npm run build:app
```

Use `npm run dev` to start local development server.

## API

All API and components are exposed in `src/index.ts` file.

`src/main.tsx` file is responsible for rendering the widget in `standalone` mode or in development mode.