diff --git a/commerce_pos.libraries.yml b/commerce_pos.libraries.yml
index 64d7f4e..b1b189e 100644
--- a/commerce_pos.libraries.yml
+++ b/commerce_pos.libraries.yml
@@ -4,4 +4,10 @@ form:
     layout:
       css/commerce_pos_style.css: {}
   js:
-    js/commerce_pos.js: {}
\ No newline at end of file
+    js/commerce_pos.js: {}
+
+commerce-pos-widget:
+  js:
+    js/commerce_pos_widget.js: {}
+  dependencies:
+    - core/jquery
\ No newline at end of file
diff --git a/commerce_pos.routing.yml b/commerce_pos.routing.yml
index 8ea2023..4546615 100644
--- a/commerce_pos.routing.yml
+++ b/commerce_pos.routing.yml
@@ -38,3 +38,33 @@ commerce_pos.main:
     _title: 'Point of Sale'
   requirements:
     _permission: 'access commerce pos pages'
+
+commerce_pos.pos_order_item_widget_autocomplete:
+  path: '/commerce_pos/orderItemAutoCompleteHandler/{entity_type}/{view_mode}/{count}'
+  defaults:
+    _controller: '\Drupal\commerce_pos\Controller\PosOrderItemAutoComplete::orderItemAutoCompleteHandler'
+    _format: json
+    _title: 'Pos Order Item Autocomplete'
+  requirements:
+    _permission: 'access content'
+
+
+commerce_pos.auto_complete_add_order_addToOrder:
+  path: '/commerce_pos/addToOrder/{product_var_id}/{quantity}'
+  defaults:
+    _controller: '\Drupal\commerce_pos\Controller\UpdateOrder::addToOrder'
+    _title: 'Add to order'
+  requirements:
+    _permission: 'access content'
+    product_var_id: \d+
+    quantity: \d+
+
+commerce_pos.update_order:
+  path: '/commerce_pos/update_order'
+  defaults:
+    _controller: '\Drupal\commerce_pos\Controller\UpdateOrder::updateOrderForm'
+    _title: 'Update order'
+  options:
+    no_cache: TRUE
+  requirements:
+    _permission: 'access content'
diff --git a/config/install/core.entity_form_display.commerce_order.pos.default.yml b/config/install/core.entity_form_display.commerce_order.pos.default.yml
index 982c0a7..853ea08 100644
--- a/config/install/core.entity_form_display.commerce_order.pos.default.yml
+++ b/config/install/core.entity_form_display.commerce_order.pos.default.yml
@@ -2,33 +2,27 @@ langcode: en
 status: true
 dependencies:
   config:
-    - commerce_order.commerce_order_type.default
-    - field.field.commerce_order.pos.field_order_items
+    - commerce_order.commerce_order_type.pos
+    - field.field.commerce_order.pos.field_cashier
+    - field.field.commerce_order.pos.field_register
+    - field.field.commerce_order.pos.order_items
   module:
     - commerce_order
     - commerce_pos
+    - inline_entity_form
+_core:
+  default_config_hash: HhZKA_IA19mJACTv88yTh3eJ7gPY3sMapJ1qYbed0zs
 id: commerce_order.pos.default
 targetEntityType: commerce_order
 bundle: pos
 mode: default
 content:
-  order_items:
-    type: inline_entity_form_complex
-    weight: 0
-    settings:
-      override_labels: true
-      label_singular: 'order item'
-      label_plural: 'order items'
-      allow_new: true
-      match_operator: CONTAINS
-      allow_existing: false
-      form_mode: default
-    third_party_settings: {  }
   adjustments:
     type: commerce_adjustment_default
     weight: 1
     settings: {  }
     third_party_settings: {  }
+    region: content
   mail:
     type: email_default
     weight: 2
@@ -37,6 +31,16 @@ content:
       size: 60
       placeholder: ''
     third_party_settings: {  }
+  order_items:
+    type: pos_order_item_widget
+    weight: 0
+    settings:
+      size: 60
+      placeholder: ''
+      num_results: 10
+      purchasable_entity_view_mode: commerce_pos_product_select
+    third_party_settings: {  }
+    region: content
   uid:
     type: inline_entity_form_complex
     weight: 0
@@ -53,6 +57,8 @@ content:
 hidden:
   billing_profile: true
   created: true
+  field_cashier: true
+  field_register: true
   ip_address: true
   order_number: true
   state: true
diff --git a/config/install/core.entity_view_display.commerce_order_item.default.commerce_pos_order_item.yml b/config/install/core.entity_view_display.commerce_order_item.default.commerce_pos_order_item.yml
new file mode 100644
index 0000000..27dfbf3
--- /dev/null
+++ b/config/install/core.entity_view_display.commerce_order_item.default.commerce_pos_order_item.yml
@@ -0,0 +1,51 @@
+uuid: 95eceb82-b5e8-4f1e-9010-02fab6f8c08f
+langcode: en
+status: true
+dependencies:
+  config:
+    - commerce_order.commerce_order_item_type.default
+    - core.entity_view_mode.commerce_order_item.commerce_pos_order_item
+  enforced:
+    module:
+      - commerce_product
+  module:
+    - commerce_price
+_core:
+  default_config_hash: YvPk7-s7bZEOuxWBbu1G5wo4qc-OOnZpmCwPUdhp40o
+id: commerce_order_item.default.commerce_pos_order_item
+targetEntityType: commerce_order_item
+bundle: default
+mode: commerce_pos_order_item
+content:
+  purchased_entity:
+    type: entity_reference_entity_view
+    weight: 0
+    settings:
+      view_mode: commerce_pos_product_select
+      link: false
+    third_party_settings: {  }
+    label: hidden
+    region: content
+  quantity:
+    type: number_decimal
+    weight: 1
+    settings:
+      thousand_separator: ''
+      decimal_separator: .
+      scale: 2
+      prefix_suffix: true
+    third_party_settings: {  }
+    label: inline
+    region: content
+  total_price:
+    type: commerce_price_default
+    weight: 2
+    settings:
+      strip_trailing_zeroes: false
+      display_currency_code: false
+    third_party_settings: {  }
+    label: inline
+    region: content
+hidden:
+  adjustments: true
+  unit_price: true
diff --git a/config/install/core.entity_view_display.commerce_product_variation.default.commerce_pos_product_select.yml b/config/install/core.entity_view_display.commerce_product_variation.default.commerce_pos_product_select.yml
new file mode 100644
index 0000000..028bd98
--- /dev/null
+++ b/config/install/core.entity_view_display.commerce_product_variation.default.commerce_pos_product_select.yml
@@ -0,0 +1,43 @@
+uuid: 99fc632a-7961-49a5-8265-1ba38655c484
+langcode: en
+status: true
+dependencies:
+  config:
+    - commerce_product.commerce_product_variation_type.default
+    - core.entity_view_mode.commerce_product_variation.commerce_pos_product_select
+    - field.field.commerce_product_variation.pos.field_upc
+  module:
+    - commerce_price
+id: commerce_product_variation.default.commerce_pos_product_select
+targetEntityType: commerce_product_variation
+bundle: default
+mode: commerce_pos_product_select
+content:
+  price:
+    label: inline
+    type: commerce_price_default
+    weight: 1
+    region: content
+    settings:
+      strip_trailing_zeroes: false
+      display_currency_code: false
+    third_party_settings: {  }
+  sku:
+    type: string
+    weight: 2
+    region: content
+    label: inline
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+  title:
+    type: string
+    weight: 0
+    region: content
+    label: hidden
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+hidden:
+  field_upc: true
+  product_id: true
diff --git a/config/install/core.entity_view_mode.commerce_order_item.commerce_pos_order_item.yml b/config/install/core.entity_view_mode.commerce_order_item.commerce_pos_order_item.yml
new file mode 100644
index 0000000..430b9b0
--- /dev/null
+++ b/config/install/core.entity_view_mode.commerce_order_item.commerce_pos_order_item.yml
@@ -0,0 +1,9 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - commerce_order
+id: commerce_order_item.commerce_pos_order_item
+label: 'Commerce POS order item'
+targetEntityType: commerce_order_item
+cache: true
diff --git a/config/install/core.entity_view_mode.commerce_product_variation.commerce_pos_product_select.yml b/config/install/core.entity_view_mode.commerce_product_variation.commerce_pos_product_select.yml
new file mode 100644
index 0000000..961084b
--- /dev/null
+++ b/config/install/core.entity_view_mode.commerce_product_variation.commerce_pos_product_select.yml
@@ -0,0 +1,9 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - commerce_product
+id: commerce_product_variation.commerce_pos_product_select
+label: 'Commerce POS product select'
+targetEntityType: commerce_product_variation
+cache: true
diff --git a/config/install/field.field.commerce_order.pos.field_order_items.yml b/config/install/field.field.commerce_order.pos.order_items.yml
similarity index 100%
rename from config/install/field.field.commerce_order.pos.field_order_items.yml
rename to config/install/field.field.commerce_order.pos.order_items.yml
diff --git a/js/commerce_pos_widget.js b/js/commerce_pos_widget.js
new file mode 100644
index 0000000..cc4d852
--- /dev/null
+++ b/js/commerce_pos_widget.js
@@ -0,0 +1,15 @@
+(function ($) {
+    Drupal.behaviors.pos_autocomplete_widget = {
+        attach: function (context, settings) {
+            $('[data-drupal-selector="edit-order-items-target-id-product-selector"]').on('autocompleteclose', function() {
+                var field = $(this);
+                var product_id = field.val();
+                var updateOrderAjax = Drupal.ajax({
+                    url: "/commerce_pos/addToOrder/" + product_id + "/1",
+                    progress: { type: 'throbber' }
+                });
+                updateOrderAjax.execute();
+            });
+        }
+    };
+}(jQuery));
diff --git a/src/Controller/PosOrderItemAutoComplete.php b/src/Controller/PosOrderItemAutoComplete.php
new file mode 100644
index 0000000..58744c4
--- /dev/null
+++ b/src/Controller/PosOrderItemAutoComplete.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Drupal\commerce_pos\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\user\PrivateTempStoreFactory;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\commerce_product\Entity\ProductVariation;
+
+/**
+ * Class PosOrderItemAutoComplete.
+ *
+ * @package Drupal\commerce_pos\Controller
+ */
+class PosOrderItemAutoComplete extends ControllerBase {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
+   */
+  protected $entityDisplayRepository;
+
+  /**
+   * The tempstore object.
+   *
+   * @var \Drupal\user\SharedTempStore
+   */
+  protected $tempStore;
+
+  /**
+   * The renderer.
+   *
+   * @var \Drupal\Core\Render\RendererInterface
+   */
+  protected $renderer;
+
+  /**
+   * Constructs a new POS object.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, RendererInterface $renderer) {
+    $this->entityTypeManager = $entity_type_manager;
+    $this->tempStore = $temp_store_factory->get('commerce_pos');
+    $this->renderer = $renderer;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager'),
+      $container->get('user.private_tempstore'),
+      $container->get('renderer')
+    );
+  }
+
+  /**
+   * Order item auto complete handler.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object.
+   * @param $entity_type
+   * @param $view_mode
+   * @param $count
+   *
+   * @return object
+   *   The Json object for auto complete suggestions.
+   */
+  public function orderItemAutoCompleteHandler(Request $request, $entity_type, $view_mode, $count) {
+
+    $results = [];
+    if ($input = $request->query->get('q')) {
+      $suggestions = $this->searchQueryString($input);
+      $view_builder = $this->entityTypeManager->getViewBuilder($entity_type);
+      foreach ($suggestions as $key) {
+        $product_variation = ProductVariation::load($key->variation_id);
+        $results[] = [
+          'value' => $product_variation->id(),
+          'label' => $this->renderer->renderPlain($view_builder->view($product_variation, $view_mode, $product_variation->language()->getId())),
+        ];
+      }
+    }
+
+    return new JsonResponse($results);
+  }
+
+  /**
+   * Helper function for searching the product.
+   *
+   * @param string $string
+   *   The Query string.
+   *
+   * @return mixed
+   *   The query search result.
+   */
+  public function searchQueryString($string) {
+    // Getting the Store ID.
+    $register = $this->tempStore->get('register');
+    if (!empty($register)) {
+      $register = \Drupal::entityTypeManager()->getStorage('commerce_pos_register')->load($register);
+      $store_id = $register->getStoreId();
+    }
+    else {
+      $store_storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
+      $store_id = $store_storage->loadDefault()->id();
+    }
+
+    // @todo convert to entity query? This might be tricky... need to load all
+    // the products for a store and then all their variations?
+    $connection = \Drupal::service('database');
+    $query = $connection->select('commerce_product_variation_field_data', 'cpvd')
+      ->fields('cpvd', ['variation_id', 'product_id', 'title'])
+      ->range(0, 10);
+    $query->join('commerce_product__stores', 'cps', 'cps.entity_id = cpvd.product_id AND cps.stores_target_id = :store_id
+    AND cpvd.title LIKE :string', [':store_id' => $store_id, ':string' => '%' . $string . '%']);
+
+    $result = $query->execute()->fetchAll();
+
+    return $result;
+  }
+
+}
diff --git a/src/Controller/UpdateOrder.php b/src/Controller/UpdateOrder.php
new file mode 100644
index 0000000..21dcc58
--- /dev/null
+++ b/src/Controller/UpdateOrder.php
@@ -0,0 +1,154 @@
+<?php
+
+namespace Drupal\commerce_pos\Controller;
+
+use Drupal\commerce_order\Entity\OrderItem;
+use Drupal\commerce_pos\CurrentOrder;
+use Drupal\commerce_pos\Form\POSForm;
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Form\FormState;
+use Drupal\user\PrivateTempStoreFactory;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\commerce_product\Entity\ProductVariation;
+
+/**
+ * Class UpdateOrder.
+ *
+ * @package Drupal\commerce_pos\Controller
+ */
+class UpdateOrder extends ControllerBase {
+
+  /**
+   * The currentOrder object.
+   *
+   * @var \Drupal\commerce_pos\CurrentOrder
+   */
+  protected $currentOrder;
+
+  /**
+   * The tempstore object.
+   *
+   * @var \Drupal\user\SharedTempStore
+   */
+  protected $tempStore;
+
+  /**
+   * Constructs a new CartController object.
+   *
+   * @param \Drupal\commerce_pos\CurrentOrder $currentOrder
+   *   The current Order.
+   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
+   *   The temporary storage.
+   */
+  public function __construct(CurrentOrder $currentOrder, PrivateTempStoreFactory $temp_store_factory) {
+    $this->currentOrder = $currentOrder;
+    $this->tempStore = $temp_store_factory->get('commerce_pos');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('commerce_pos.current_order'),
+      $container->get('user.private_tempstore')
+    );
+  }
+
+  /**
+   * Add a product variation to the order.
+   *
+   * @param int $product_var_id
+   *   The product variation id to add to the order.
+   * @param $quantity
+   *   The quantity to add.
+   *
+   * @return \Drupal\Core\Ajax\AjaxResponse
+   *   An Ajax response to update the entire order form.
+   */
+  public function addToOrder($product_var_id, $quantity) {
+    $order = $this->getOrder();
+    // Loading the product variation object.
+    $pro_variation_obj = ProductVariation::load($product_var_id);
+
+    // Create new order Item for adding into existing order.
+    $order_item = OrderItem::create([
+      'type' => 'default',
+      'purchased_entity' => $pro_variation_obj,
+      'quantity' => $quantity,
+      'unit_price' => $pro_variation_obj->getPrice(),
+    ]);
+    $order_item->save();
+
+    // Adding the item into the Order.
+    $order->addItem($order_item)->save();
+
+    return $this->updateOrderForm();
+  }
+
+  /**
+   * Returns an updated order form.
+   *
+   * @return \Drupal\Core\Ajax\AjaxResponse
+   *   An Ajax response to update the entire order form.
+   */
+  public function updateOrderForm() {
+    $order = $this->getOrder();
+    $form_object = POSForm::create(\Drupal::getContainer());
+    $form_object->setEntity($order);
+
+    $form_object
+      ->setModuleHandler(\Drupal::moduleHandler())
+      ->setEntityTypeManager(\Drupal::entityTypeManager())
+      ->setOperation('pos')
+      ->setEntityManager(\Drupal::entityManager());
+
+    $form_state = (new FormState())->setFormState([]);
+
+    $form = \Drupal::formBuilder()->buildForm($form_object, $form_state);
+    $response = new AjaxResponse();
+    $response->addCommand(new ReplaceCommand('form.commerce-pos', $form));
+    return $response;
+  }
+
+  /**
+   * Gets the order from the tempstore or creates a new order.
+   *
+   * @todo
+   *   I think the order creation stuff is risky. The order should be created
+   *   by the PosForm and we should never have to dynamically create one.
+   *
+   * @return \Drupal\commerce_order\Entity\Order
+   */
+  protected function getOrder() {
+    // Getting the Store .
+    $register = $this->tempStore->get('register');
+    if (!empty($register)) {
+      $register = \Drupal::entityTypeManager()->getStorage('commerce_pos_register')->load($register);
+      $store_id = $register->getStoreId();
+    }
+    else {
+      $store_storage = \Drupal::entityTypeManager()->getStorage('commerce_store');
+      $store_id = $store_storage->loadDefault()->id();
+    }
+
+    $order = $this->currentOrder->get();
+
+    if (!$order) {
+      $order = Order::create([
+        'type' => 'pos',
+        'field_cashier' => \Drupal::currentUser()->id(),
+      ]);
+
+      $order->setStoreId($store_id);
+
+      $order->save();
+
+      $this->currentOrder->set($order);
+    }
+    return $order;
+  }
+
+}
diff --git a/src/Form/POSForm.php b/src/Form/POSForm.php
index 6fc5ff7..4ac0f28 100644
--- a/src/Form/POSForm.php
+++ b/src/Form/POSForm.php
@@ -3,7 +3,11 @@
 namespace Drupal\commerce_pos\Form;
 
 use Drupal\commerce_price\Price;
+use Drupal\Component\Datetime\TimeInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\ContentEntityForm;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\commerce_price\Entity\Currency;
@@ -14,6 +18,24 @@ use Drupal\commerce_order\Entity\Order;
  */
 class POSForm extends ContentEntityForm {
 
+  /**
+   * Constructs a ContentEntityForm object.
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
+   *   The entity type bundle service.
+   * @param \Drupal\Component\Datetime\TimeInterface $time
+   *   The time service.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory service.
+   */
+  public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, ConfigFactoryInterface $config_factory) {
+    parent::__construct($entity_manager, $entity_type_bundle_info, $time);
+
+    $this->setConfigFactory($config_factory);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -22,7 +44,7 @@ class POSForm extends ContentEntityForm {
       $container->get('entity.manager'),
       $container->get('entity_type.bundle.info'),
       $container->get('datetime.time'),
-      $container->get('current_user')
+      $container->get('config.factory')
     );
   }
 
diff --git a/src/Plugin/Field/FieldWidget/PosOrderItemWidget.php b/src/Plugin/Field/FieldWidget/PosOrderItemWidget.php
new file mode 100644
index 0000000..8dc705a
--- /dev/null
+++ b/src/Plugin/Field/FieldWidget/PosOrderItemWidget.php
@@ -0,0 +1,234 @@
+<?php
+
+namespace Drupal\commerce_pos\Plugin\Field\FieldWidget;
+
+use Drupal\commerce_product\Entity\ProductVariation;
+use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldFilteredMarkup;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Field\WidgetInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+
+/**
+ * Plugin implementation of the 'pos_order_item_widget' widget.
+ *
+ * @FieldWidget(
+ *   id = "pos_order_item_widget",
+ *   label = @Translation("Pos order item widget"),
+ *   field_types = {
+ *     "entity_reference"
+ *   },
+ *   multiple_values = true
+ * )
+ */
+class PosOrderItemWidget extends WidgetBase implements WidgetInterface, ContainerFactoryPluginInterface  {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
+   */
+  protected $entityDisplayRepository;
+
+  /**
+   * Constructs a EntityReferenceEntityFormatter instance.
+   *
+   * @param string $plugin_id
+   *   The plugin_id for the formatter.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the formatter is associated.
+   * @param array $settings
+   *   The formatter settings.
+   * @param array $third_party_settings
+   *   Any third party settings settings.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
+   *   The entity display repository.
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings,  EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+
+    $this->entityTypeManager = $entity_type_manager;
+    $this->entityDisplayRepository = $entity_display_repository;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['third_party_settings'],
+      $container->get('entity_type.manager'),
+      $container->get('entity_display.repository')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return [
+      'size' => 60,
+      'placeholder' => '',
+      'num_results' => 10,
+      'purchasable_entity_view_mode' => 'commerce_pos_product_select',
+      'order_item_view_mode' => 'commerce_pos_order_item',
+    ] + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = [];
+
+    $elements['size'] = [
+      '#type' => 'number',
+      '#title' => t('Size of textfield'),
+      '#default_value' => $this->getSetting('size'),
+      '#required' => TRUE,
+      '#min' => 1,
+    ];
+    $elements['placeholder'] = [
+      '#type' => 'textfield',
+      '#title' => t('Placeholder'),
+      '#default_value' => $this->getSetting('placeholder'),
+      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
+    ];
+    $elements['num_results'] = [
+      '#type' => 'number',
+      '#title' => t('Number of search results'),
+      '#default_value' => $this->getSetting('num_results'),
+      '#required' => TRUE,
+      '#min' => 1,
+      '#max' => 50,
+    ];
+    $elements['purchasable_entity_view_mode'] = [
+      '#type' => 'select',
+      '#title' => t('Purchasable entity view mode'),
+      '#default_value' => $this->getSetting('purchasable_entity_view_mode'),
+      '#required' => TRUE,
+      // @todo use the "Purchasable entity type" from the order type.
+      '#options' => $this->entityDisplayRepository->getViewModeOptions('commerce_product_variation'),
+      '#description' => 'This view mode is used for the list of product variations to select from.'
+    ];
+    $elements['order_item_view_mode'] = [
+      '#type' => 'select',
+      '#title' => t('Order item view mode'),
+      '#default_value' => $this->getSetting('order_item_view_mode'),
+      '#required' => TRUE,
+      // @todo use the .
+      '#options' => $this->entityDisplayRepository->getViewModeOptions('commerce_order_item'),
+      '#description' => 'This view mode is used list the order items on the form.'
+    ];
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = [];
+
+    $summary[] = t('Textfield size: @size', ['@size' => $this->getSetting('size')]);
+    if (!empty($this->getSetting('placeholder'))) {
+      $summary[] = t('Placeholder: @placeholder', ['@placeholder' => $this->getSetting('placeholder')]);
+    }
+
+    $summary[] = t('Number of results: @num_results', ['@num_results' => $this->getSetting('num_results')]);
+    $summary[] = t('Purchasable entity view mode: @view_mode', ['@view_mode' => $this->getSetting('purchasable_entity_view_mode')]);
+    $summary[] = t('Order item view mode: @view_mode', ['@view_mode' => $this->getSetting('order_item_view_mode')]);
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
+    $new_form = parent::form($items, $form, $form_state, $get_delta);
+
+    return $new_form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
+    foreach ($values as $key => $value) {
+      // The entity_autocomplete form element returns an array when an entity
+      // was "autocreated", so we need to move it up a level.
+      if (is_array($value['target_id'])) {
+        unset($values[$key]['target_id']);
+        $values[$key] += $value['target_id'];
+      }
+    }
+
+    return $values;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $element = [
+      '#type' => 'fieldset',
+      '#tree' => TRUE,
+      '#description' => $this->fieldDefinition->getDescription(),
+      '#field_title' => $this->fieldDefinition->getLabel(),
+    ] + $element;
+
+    $element['product_selector'] = [
+      '#type' => 'textfield',
+      '#size' => $this->getSetting('size'),
+      '#placeholder' => $this->getSetting('placeholder'),
+      '#maxlength' => $this->getFieldSetting('max_length'),
+      '#default_value' => NULL,
+      '#autocomplete_route_name' => 'commerce_pos.pos_order_item_widget_autocomplete',
+      '#autocomplete_route_parameters' => [
+        // @todo use the "Purchasable entity type" from the order type.
+        'entity_type' => 'commerce_product_variation',
+        'view_mode' => $this->getSetting('purchasable_entity_view_mode'),
+        'count' => $this->getSetting('num_results'),
+      ],
+    ];
+
+    // Render a list of products that have been added to the order.
+    $referenced_entities = $items->referencedEntities();
+    $element['products'] = [];
+    /** @var \Drupal\commerce_order\Entity\OrderItem $entity */
+    foreach($referenced_entities as $entity) {
+      $product = $entity->getPurchasedEntity();
+      $view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
+      $element['products'][] = $view_builder->view($entity, $this->getSetting('order_item_view_mode'), $entity->language()->getId());
+    }
+
+    $element['#attached']['library'][] = 'commerce_pos/commerce-pos-widget';
+
+    $element['#default_value'] = $items->referencedEntities();
+    return ['target_id' => $element];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {
+    return isset($element['target_id']) ? $element['target_id'] : FALSE;
+  }
+
+}
diff --git a/tests/fixtures/setup_test_pos.php b/tests/fixtures/setup_test_pos.php
new file mode 100644
index 0000000..91c83f4
--- /dev/null
+++ b/tests/fixtures/setup_test_pos.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * Script to set up configure a test POS set up to make testing and development
+ * simple.
+ */
+
+include_once \Drupal::root() . '/core/tests/Drupal/Tests/RandomGeneratorTrait.php';
+# Create a store.
+class storeCreator {
+  /** @todo  */
+  use \Drupal\Tests\RandomGeneratorTrait;
+  use \Drupal\commerce_store\StoreCreationTrait { createStore as public; }
+
+  public function createProductionVariation(array $values = []) {
+    $variation = \Drupal\commerce_product\Entity\ProductVariation::create($values + [
+      'type' => 'default',
+      'sku' => strtolower($this->randomMachineName()),
+      'title' => $this->randomMachineName(),
+      'status' => 1,
+      'price' => new \Drupal\commerce_price\Price(mt_rand(10,100), 'USD'),
+    ]);
+    $variation->save();
+    return $variation;
+  }
+
+  public function createProduct(array $values = []) {
+    $product = \Drupal\commerce_product\Entity\Product::create($values + [
+      'type' => 'default',
+      'title' => $this->randomMachineName(),
+    ]);
+    $product->save();
+    return $product;
+  }
+}
+
+$storeCreator = new storeCreator();
+$test_store = $storeCreator->createStore('POS test store', 'pos_test_store@example.com', 'physical');
+
+$register = \Drupal\commerce_pos\Entity\Register::create([
+  'store_id' => $test_store->id(),
+  'name' => 'Test register',
+  'cash' => new \Drupal\commerce_price\Price('1000.00', 'USD'),
+]);
+$register->save();
+
+$variations = [
+  $storeCreator->createProductionVariation(['title' => 'T-shirt XL']),
+  $storeCreator->createProductionVariation(['title' => 'T-shirt L']),
+  $storeCreator->createProductionVariation(['title' => 'T-shirt M']),
+];
+
+$storeCreator->createProduct(['variations' => $variations, 'title' => 'T-shirt', 'stores' => [$test_store]]);
+
+$variations = [
+  $storeCreator->createProductionVariation(['title' => 'Jumper XL']),
+  $storeCreator->createProductionVariation(['title' => 'Jumper L']),
+  $storeCreator->createProductionVariation(['title' => 'Jumper M']),
+];
+
+$storeCreator->createProduct(['variations' => $variations, 'title' => 'Jumper', 'stores' => [$test_store]]);
