diff --git a/.babelrc b/.babelrc
index d2ad76e..13306a8 100644
--- a/.babelrc
+++ b/.babelrc
@@ -10,9 +10,12 @@
]
],
"plugins": [
- ["@babel/plugin-proposal-private-methods", {
- "loose": true
- }],
+ [
+ "@babel/plugin-proposal-private-methods",
+ {
+ "loose": true
+ }
+ ],
["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/plugin-transform-classes"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 21c330c..03bf1a3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node: ['16']
+ node: ['20', '22']
name: Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..c43d1fd
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,2 @@
+__tests__
+dist
diff --git a/README.md b/README.md
index 5e21d62..efaed1b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,14 @@
# Hellotext.js
-Track the events happening on your site to [Hellotext](https://www.hellotext.com) in real-time with this library.
+Official [Hellotext](https://www.hellotext.com) (client-side) JavaScript library.
-## Installation
+This library allows you the following,
+
+- Track events happening on your site to [Hellotext](https://www.hellotext.com) in real-time.
+- Use Hellotext Forms to dynamically collect data from your customers based on your specific business requirements.
+
+
+## Installation
### Using NPM
@@ -21,7 +27,7 @@ yarn add @hellotext/hellotext
Import the library into your app.
```javascript
-import Hellotext from "@hellotext/hellotext";
+import Hellotext from '@hellotext/hellotext'
```
Initialize the library passing the public `HELLOTEXT_BUSINESS_ID` identifier that represents the business.
@@ -29,165 +35,17 @@ Initialize the library passing the public `HELLOTEXT_BUSINESS_ID` identifier tha
You can find it from the business's settings page.
```javascript
-Hellotext.initialize("HELLOTEXT_BUSINESS_ID");
+Hellotext.initialize('HELLOTEXT_BUSINESS_ID')
```
Failing to initialize the class before calling any other method will throw a `NotInitializedError`.
-## Usage
-
-Tracking events is straightforward and perhaps the simplest example is tracking a page view:
-
-```javascript
-Hellotext.track("page.viewed");
-```
-
-In the example above only the name of the action is required.
-
-### Handling Responses
-
-The `track` method returns a Promise that can be `await`ed using the async/await syntax. Or using `.then` on the returned Promise.
-
-```javascript
-const response = await Hellotext.track("page.viewed");
-```
-
-The return of the `Hellotext.track` method is an instance of a `Response` object that ships with the package. You can check the status of the response via methods, like:
-
-```javascript
-if(response.failed) {
- console.log("failed because", response.data)
-}
-
-if(response.succeeded) {
- console.log("success")
- console.log(response.data) // { status: "received" }
-}
-```
-
-### Parameters
-
-The parameters passed to the action must be a valid set of parameters as described in
-[Tracking Actions](https://www.hellotext.com/api#tracking).
-
-#### URL Parameter
-
-The library takes care of handling the `url` parameter with the current URL automatically and is not required to specify it explicitly.
-If you want to provide another url, you can pass a `url` key in the params object when tracking an event.
-
-```javascript
-Hellotext.track("page.viewed", {
- url: "www.example.org"
-});
-```
-
-### Errors
-
-Failing to provide valid set of parameters will result in an error object being returned, describing the parameters that did not satisfy the rules.
-
-```javascript
-const response = await Hellotext.track("app.installed", { app_parameters: { name: "My App" }})
-
-console.log(response.data)
-```
-
-yields
-
-```javascript
-{
- errors: [
- {
- type: 'parameter_not_unique',
- parameter: 'name',
- description: 'The value must be unique and it is already present in another object of the same type.'
- },
- ]
-}
-```
-
-For a complete list of errors types. See [Error Types](https://www.hellotext.com/api#errors)
-
-### Associated objects
-
-Generally, most actions also require an associated object. These can be of type [`app`](https://www.hellotext.com/api#apps), [`coupon`](https://www.hellotext.com/api#coupons), [`form`](https://www.hellotext.com/api#forms), [`order`](https://www.hellotext.com/api#orders), [`product`](https://www.hellotext.com/api#products) and [`refund`](https://www.hellotext.com/api#refunds).
-Aside from [Custom Actions](https://www.hellotext.com/api#create_an_action), which don't require the trackable to be present.
-
-
-You can create the associated object directly by defining its parameters in a hash:
-
-```javascript
-Hellotext.track("order.placed", {
- amount: 395.00,
- currency: "USD",
- order_parameters: {
- "amount": "395.00",
- "reference": "654321",
- }
-});
-```
-
-If you want to reuse existing objects, you must pass the identifier of an existing associated object. For example, to track a product purchase the identifier of a previously created product object as the `product`.
-For more information about identifiers, view the [Tracking API](https://www.hellotext.com/api#tracking)
-
-```javascript
-Hellotext.track("product.purchased", {
- amount: 395.00,
- currency: "USD",
- product: "erA2RAXE"
-});
-```
-
-## List of actions
-
-The following is a complete list of built-in actions and their required associated objects.
-
-| Action | Description | Required Parameter |
-|-----------------------|----------------------------------------------------------| --- |
-| **app.installed** | An app was installed. | `app` or [app_parameters](https://www.hellotext.com/api#app)
-| **app.removed** | An app was removed. | `app` or [app_parameters](https://www.hellotext.com/api#app)
-| **app.spent** | A customer spent on an app. | `app` or [app_parameters](https://www.hellotext.com/api#app)
-| **cart.abandoned** | A cart was abandoned. | `product` or [product_parameters](https://www.hellotext.com/api#products)
-| **cart.added** | Added an item to the cart. | `product` or [product_parameters](https://www.hellotext.com/api#products)
-| **cart.removed** | Removed an item from the cart. | `product` or [product_parameters](https://www.hellotext.com/api#products)
-| **coupon.redeemed** | A coupon was redeem by a customer. | `coupon` or [coupon_parameters](https://www.hellotext.com/api#coupons)
-| **form.completed** | A form was completed by the customer. | `form` or [form_parameters](https://www.hellotext.com/api#forms)
-| **order.placed** | Order has been placed. | `order` or [order_parameters](https://www.hellotext.com/api#orders)
-| **order.confirmed** | Order has been confirmed by you. | `order` or [order_parameters](https://www.hellotext.com/api#orders)
-| **order.cancelled** | Order has been cancelled either by you or your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders)
-| **order.shipped** | Order has been shipped to your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders)
-| **order.delivered** | Order has been delivered to your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders)
-| **page.viewed** | A page was viewed by a customer. | `url`
-| **product.purchased** | A product has been purchased. | `product` or [product_parameters](https://www.hellotext.com/api#products)
-| **product.viewed** | A product page has been viewed. | `product` or [product_parameters](https://www.hellotext.com/api#products)
-| **refund.requested** | A customer requested a refund. | `refund` or [refund_parameters](https://www.hellotext.com/api#refunds)
-| **refund.received** | A refund was issued by you to your customer. | `refund` or [refund_parameters](https://www.hellotext.com/api#refunds)
-
-You can also create your **[own defined actions](https://www.hellotext.com/api#actions)**.
-
-## Additional Properties
-
-You can include additional attributes to the tracked event, additional properties must be included inside the `metadata` object:
-
-```javascript
-Hellotext.track("product.purchased", {
- amount: 0.20,
- currency: "USD",
- metadata: {
- myProperty: "custom"
- },
- tracked_at: 1665684173
-});
-```
-
-### List of additional attributes
+## Documentation
-| Property | Description | Type | Default |
-| --- | --- | --- | --- |
-| **amount** | Monetary amount that represents the revenue associated to this tracked event. | float | `0`
-| **currency** | Currency for the `amount` given in ISO 4217 format. | currency | `USD`
-| **metadata** | Set of key-value pairs that you can attach to an event. This can be useful for storing additional information about the object in a structured format. | hash | `{}`
-| **tracked_at** | Original date when the event happened. This is useful if you want to record an event that happened in the past. If no value is provided its value will be the same from `created_at`. | epoch | `null`
+Learn how to leverage the library to track events and collect forms.
+- [Tracking Events](/docs/tracking.md)
+- [Forms](/docs/forms.md)
## Events
@@ -209,54 +67,56 @@ Hellotext.removeEventListener(eventName, callback)
### List of events
- `session-set`: This event is fired when the session value for `Hellotext.session` is set. Either through an API request, or if the session was found in the cookie.
+- `forms:collected` This event is fired when forms are collected. The callback will receive the array of forms collected.
+- `form:completed` This event is fired when a form has been completed. A form is completed when the user fills all required inputs and verifies their OTP(One-Time Password). The callback will receive the form object that was completed, alongside the data the user filled in the form.
## Understanding Sessions
-The library looks for a session identifier present on the `hellotext_session` query parameter. If the session is not present as a cookie neither it will create a new random session identifier, you can disable this default behaviour via the configuration, see [Configuration Options](#configuration-options) for more information.
-The session is automatically sent to Hellotext any time the `Hellotext.track` method is called.
+The library looks for a session identifier present on the `hellotext_session` query parameter. If the session is not present as a cookie neither it will create a new random session identifier, you can disable this default behaviour via the configuration, see [Configuration Options](#configuration-options) for more information.
+The session is automatically sent to Hellotext any time the `Hellotext.track` method is called.
Short links redirections attaches a session identifier to the destination url as `hellotext_session` query parameter. This will identify all the events back to the customer who opened the link.
### Get session
-It is possible to obtain the current session by simply calling `Hellotext.session`.
+It is possible to obtain the current session by simply calling `Hellotext.session`.
```javascript
await Hellotext.session
// Returns bBJn9vR15yPaYkWmR2QK0jopMeNxrA6l
```
-If the session has not been set yet, the result returned will be `undefined`.
+If the session has not been set yet, the result returned will be `undefined`.
You can check whether the session has been set or not by calling `Hellotext.isInitialized`.
```javascript
-if(Hellotext.isInitialized) {
- console.log("session is present")
+if (Hellotext.isInitialized) {
+ console.log('session is present')
} else {
- console.log("session has not been set")
+ console.log('session has not been set')
}
```
Moreover, you can hook in and listen for the session being set, such that when it's set, you're notified about the change, like so
```javascript
-Hellotext.on("session-set", (session) => {
- console.log("session is: ", session)
+Hellotext.on('session-set', session => {
+ console.log('session is: ', session)
})
```
You may want to store the session on your backend when customers are unidentified so you can later [attach it to a profile](https://www.hellotext.com/api#attach_session) when it becomes known.
-### Configuration
+### Configuration
-When initializing the library, you may pass an optional configuration object as the second argument.
+When initializing the library, you may pass an optional configuration object as the second argument.
```javascript
-Hellotext.initialize("HELLOTEXT_BUSINESS_ID", configurationOptions);
+Hellotext.initialize('HELLOTEXT_BUSINESS_ID', configurationOptions)
```
#### Configuration Options
| Property | Description | Type | Default |
-|---------------------|------------------------------------------------------------------------------------------------------------------|---------| --- |
-| autogenerateSession | Whether the library should automatically generate a session when no session is found in the query or the cookies | Boolean | true
+| ------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | ------- |
+| autogenerateSession | Whether the library should automatically generate a session when no session is found in the query or the cookies | Boolean | true |
diff --git a/__tests__/api/sessions_test.js b/__tests__/api/sessions_test.js
new file mode 100644
index 0000000..f170eae
--- /dev/null
+++ b/__tests__/api/sessions_test.js
@@ -0,0 +1,12 @@
+import API from '../../src/api/sessions'
+
+beforeEach(() => {
+ global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({ id: 1 }) })
+})
+
+describe('create', () => {
+ it('creates a session object', async () => {
+ const response = await new API('M01az53K').create()
+ expect(response.id).toEqual(1)
+ })
+})
diff --git a/__tests__/builders/input_builder_test.js b/__tests__/builders/input_builder_test.js
new file mode 100644
index 0000000..3d75742
--- /dev/null
+++ b/__tests__/builders/input_builder_test.js
@@ -0,0 +1,117 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import Hellotext from '../../src/hellotext'
+import { InputBuilder } from '../../src/builders/input_builder'
+
+describe('when the input is first_name', () => {
+ const data = {
+ label: 'First Name',
+ type: 'text',
+ required: true,
+ placeholder: 'Enter your first name',
+ kind: 'first_name',
+ }
+
+ it('builds an article element that contains a label and input elements', () => {
+ const article = InputBuilder.build(data)
+ const label = article.querySelector('label')
+ const input = article.querySelector('input')
+
+ expect(label.innerText).toEqual('First Name')
+ expect(label.getAttribute('for')).toEqual('first_name')
+
+ expect(input.id).toEqual('first_name')
+ expect(input.type).toEqual('text')
+ expect(input.required).toEqual(true)
+ expect(input.placeholder).toEqual('Enter your first name')
+ expect(input.name).toEqual('first_name')
+ })
+})
+
+describe('when the input is last_name', () => {
+ const data = {
+ label: 'Last Name',
+ type: 'text',
+ required: false,
+ placeholder: 'Enter your last name',
+ kind: 'last_name',
+ }
+
+ it('builds an article element that contains a label and input elements', () => {
+ const article = InputBuilder.build(data)
+ const label = article.querySelector('label')
+ const input = article.querySelector('input')
+
+ expect(label.innerText).toEqual('Last Name')
+ expect(label.getAttribute('for')).toEqual('last_name')
+
+ expect(input.id).toEqual('last_name')
+ expect(input.type).toEqual('text')
+ expect(input.required).toEqual(false)
+ expect(input.placeholder).toEqual('Enter your last name')
+ expect(input.name).toEqual('last_name')
+ })
+})
+
+describe('when the input belongs to a property', () => {
+ const data = {
+ label: 'Email',
+ type: 'email',
+ required: true,
+ placeholder: 'Enter your email',
+ kind: 'email',
+ property: 'xybz',
+ }
+
+ it('builds an article element that contains a label and input elements', () => {
+ const article = InputBuilder.build(data)
+ const label = article.querySelector('label')
+ const input = article.querySelector('input')
+
+ expect(label.innerText).toEqual('Email')
+ expect(label.getAttribute('for')).toEqual('email')
+
+ expect(input.id).toEqual('email')
+ expect(input.type).toEqual('email')
+ expect(input.required).toEqual(true)
+ expect(input.placeholder).toEqual('Enter your email')
+ expect(input.name).toEqual('email')
+ })
+})
+
+describe('when the input is a phone number', () => {
+ const data = {
+ label: 'Phone',
+ type: 'tel',
+ required: true,
+ placeholder: 'Enter your phone number',
+ kind: 'phone',
+ }
+
+ beforeEach(() => {
+ Hellotext.business = {
+ country: {
+ prefix: '598',
+ code: 'UY',
+ }
+ }
+ })
+
+ it('builds an article element that contains a label and input elements', () => {
+ const article = InputBuilder.build(data)
+ const label = article.querySelector('label')
+ const input = article.querySelector('input')
+
+ expect(label.innerText).toEqual('Phone')
+ expect(label.getAttribute('for')).toEqual('phone')
+
+ expect(input.id).toEqual('phone')
+ expect(input.type).toEqual('tel')
+ expect(input.required).toEqual(true)
+ expect(input.placeholder).toEqual('Enter your phone number')
+ expect(input.name).toEqual('phone')
+ expect(input.value).toEqual('+598')
+ })
+})
diff --git a/__tests__/event_emitter_test.js b/__tests__/core/event_test.js
similarity index 51%
rename from __tests__/event_emitter_test.js
rename to __tests__/core/event_test.js
index 3634b3d..2b6d0ad 100644
--- a/__tests__/event_emitter_test.js
+++ b/__tests__/core/event_test.js
@@ -1,7 +1,27 @@
-import EventEmitter from "../src/eventEmitter"
+import Event from "../../src/core/event"
+
+describe(".valid", function () {
+ it("is true when event name is a valid defined name", () => {
+ expect(Event.valid("session-set")).toEqual(true)
+ });
+
+ it("is false when event name is not defined", () => {
+ expect(Event.valid("undefined-event")).toEqual(false)
+ });
+});
+
+describe(".invalid", () => {
+ it("is true when event name is not defined", () => {
+ expect(Event.invalid("undefined-event")).toEqual(true)
+ });
+
+ it("is false when event name is a valid defined name", () => {
+ expect(Event.invalid("session-set")).toEqual(false)
+ });
+});
describe("#addSubscriber", function () {
- const instance = new EventEmitter()
+ const instance = new Event()
it("adds the callback to the list of subscribers for an event", () => {
const callback = (session) => {}
@@ -11,7 +31,7 @@ describe("#addSubscriber", function () {
});
describe("#removeSubscriber", function () {
- const instance = new EventEmitter()
+ const instance = new Event()
it("removes the callback from the list of subscribers for an event", () => {
const callback = (session) => {}
@@ -22,14 +42,14 @@ describe("#removeSubscriber", function () {
});
});
-describe("#emit", () => {
- const instance = new EventEmitter()
+describe("#dispatch", () => {
+ const instance = new Event()
it("notifies the listeners for an event", () => {
const callback = jest.fn()
instance.addSubscriber("session-set", callback)
- instance.emit("session-set", "session_payload")
+ instance.dispatch("session-set", "session_payload")
expect(callback).toHaveBeenCalledTimes(1)
});
diff --git a/__tests__/event_test.js b/__tests__/event_test.js
deleted file mode 100644
index 6e45b13..0000000
--- a/__tests__/event_test.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import Event from "../src/event"
-
-describe(".valid", function () {
- it("is true when event name is a valid defined name", () => {
- expect(Event.valid("session-set")).toEqual(true)
- });
-
- it("is false when event name is not defined", () => {
- expect(Event.valid("undefined-event")).toEqual(false)
- });
-});
-
-describe(".invalid", () => {
- it("is true when event name is not defined", () => {
- expect(Event.invalid("undefined-event")).toEqual(true)
- });
-
- it("is false when event name is a valid defined name", () => {
- expect(Event.invalid("session-set")).toEqual(false)
- });
-});
diff --git a/__tests__/hellotext_test.js b/__tests__/hellotext_test.js
index 3fd9aaa..1f79f0d 100644
--- a/__tests__/hellotext_test.js
+++ b/__tests__/hellotext_test.js
@@ -3,6 +3,7 @@
*/
import Hellotext from "../src/hellotext";
+import { Business } from "../src/models"
const getCookieValue = name => document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop()
@@ -10,6 +11,10 @@ const expireSession = () => {
document.cookie = "hello_session=;expires=Thu, 01 Jan 1970 00:00:00 GMT"
}
+beforeEach(() => {
+ Business.prototype.fetchPublicData = jest.fn().mockResolvedValue({ whitelist: 'disabled' })
+})
+
afterEach(() => {
jest.clearAllMocks();
});
@@ -204,3 +209,10 @@ describe("when hello_preview query parameter is present", () => {
});
})
})
+
+describe('setSession', () => {
+ it('sets the session', () => {
+ Hellotext.setSession("12345")
+ expect(Hellotext.session).toEqual("12345")
+ })
+})
diff --git a/__tests__/models/business_test.js b/__tests__/models/business_test.js
new file mode 100644
index 0000000..9b2a8c1
--- /dev/null
+++ b/__tests__/models/business_test.js
@@ -0,0 +1,26 @@
+/**
+ * @jest-environment jsdom
+ */
+
+
+import { Business } from '../../src/models'
+
+describe('enabledWhitelist', () => {
+ beforeEach(() => {
+ global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({}) })
+ })
+
+ it('is true when the whitelist is an array', () => {
+ const business = new Business('123')
+ business.data = { whitelist: ['www.example.com'] }
+
+ expect(business.enabledWhitelist).toEqual(true)
+ })
+
+ it('is false when the whitelist is a string', () => {
+ const business = new Business('123')
+ business.data = { whitelist: 'disabled' }
+
+ expect(business.enabledWhitelist).toEqual(false)
+ })
+})
diff --git a/__tests__/models/cookies_test.js b/__tests__/models/cookies_test.js
new file mode 100644
index 0000000..04c2652
--- /dev/null
+++ b/__tests__/models/cookies_test.js
@@ -0,0 +1,25 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { Cookies } from '../../src/models'
+
+beforeEach(() => {
+ document.cookie = ''
+})
+
+describe('set', () => {
+ it('sets the value of a cookie', () => {
+ expect(Cookies.get('hello_session')).toEqual(undefined)
+
+ Cookies.set('hello_session', 'session')
+ expect(Cookies.get('hello_session')).toEqual('session')
+ })
+})
+
+describe('get', () => {
+ it('gets the value of a cookie', () => {
+ document.cookie = 'hello_session=session'
+ expect(Cookies.get('hello_session')).toEqual('session')
+ })
+})
diff --git a/__tests__/models/form_collection_test.js b/__tests__/models/form_collection_test.js
new file mode 100644
index 0000000..1ebb471
--- /dev/null
+++ b/__tests__/models/form_collection_test.js
@@ -0,0 +1,100 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { Business, FormCollection } from '../../src/models'
+import Hellotext from '../../src/hellotext'
+
+beforeEach(() => {
+ Business.prototype.fetchPublicData = jest.fn().mockResolvedValue({ whitelist: 'disabled' })
+
+ Hellotext.initialize('M01az53K', {
+ autogenerateSession: false
+ })
+})
+
+describe('collect', () => {
+ it('does not fetch forms when there are no forms to fetch', async () => {
+ const fetch = jest.fn()
+ global.fetch = fetch
+
+ await Hellotext.forms.collect()
+
+ expect(fetch).not.toHaveBeenCalled()
+ })
+
+ it('fetches forms when there are forms to fetch', async () => {
+ global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({ id: 1 }) })
+
+ document.body.innerHTML = `
+
+ `
+
+ await Hellotext.forms.collect()
+
+ expect(fetch).toHaveBeenCalledTimes(1)
+ })
+})
+
+describe('add', () => {
+ const forms = new FormCollection()
+ const form = { id: 1, name: 'Form 1' }
+
+ it('adds a form to the forms array', () => {
+ forms.add(form)
+ expect(forms.length).toEqual(1)
+ })
+
+ it('does not add a form that is already in the forms array', () => {
+ forms.add(form)
+ forms.add(form)
+
+ expect(forms.length).toEqual(1)
+ })
+})
+
+describe('getting elements', () => {
+ const forms = new FormCollection()
+ forms.add({ id: 1, name: 'Form 1' })
+ forms.add({ id: 2, name: 'Form 1' })
+
+ describe('getById', () => {
+ it('returns the form with the given id', () => {
+ expect(forms.getById(1).id).toEqual(1)
+ })
+ })
+
+ describe('getByIndex', () => {
+ it('returns the form at the given index', () => {
+ expect(forms.getByIndex(1).id).toEqual(2)
+ })
+ })
+})
+
+describe('includes', () => {
+ const forms = new FormCollection()
+ const form = { id: 1, name: 'Form 1' }
+
+ it('is true when the form is in the forms array', () => {
+ forms.add(form)
+ expect(forms.includes(1)).toEqual(true)
+ })
+
+ it('is false when the form is not in the forms array', () => {
+ expect(forms.includes(2)).toEqual(false)
+ })
+})
+
+describe('excludes', () => {
+ const forms = new FormCollection()
+ const form = { id: 1, name: 'Form 1' }
+
+ it('is true when the form is not in the forms array', () => {
+ expect(forms.excludes(2)).toEqual(true)
+ })
+
+ it('is false when the form is in the forms array', () => {
+ forms.add(form)
+ expect(forms.excludes(1)).toEqual(false)
+ })
+})
diff --git a/__tests__/models/form_test.js b/__tests__/models/form_test.js
new file mode 100644
index 0000000..f40a73e
--- /dev/null
+++ b/__tests__/models/form_test.js
@@ -0,0 +1,29 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import Hellotext from '../../src/hellotext'
+import { Form } from '../../src/models'
+
+describe('id', () => {
+ it('is the form id', () => {
+ const form = new Form({ id: 1 })
+ expect(form.id).toEqual(1)
+ })
+})
+
+describe('markAsCompleted', () => {
+ it('saves the form as completed in localStorage', () => {
+ const form = new Form({ id: 1 })
+ form.markAsCompleted()
+ expect(localStorage.getItem('hello-form-1')).toEqual('completed')
+ })
+
+ it('emits a form:completed event', () => {
+ const form = new Form({ id: 1 })
+ const emit = jest.spyOn(Hellotext.eventEmitter, 'dispatch')
+
+ form.markAsCompleted()
+ expect(emit).toHaveBeenCalledWith('form:completed', { id: 1 })
+ })
+})
diff --git a/__tests__/models/query_test.js b/__tests__/models/query_test.js
new file mode 100644
index 0000000..08b07a3
--- /dev/null
+++ b/__tests__/models/query_test.js
@@ -0,0 +1,97 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { Query } from '../../src/models'
+
+describe('get', () => {
+ beforeEach(() => {
+ const windowMock = {
+ location: { search: "?hello_session=session&hello_preview=1" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+ })
+
+ it('gets the value of a query parameter', () => {
+ const query = new Query()
+
+ expect(query.get("session")).toEqual("session")
+ expect(query.get("preview")).toEqual("1")
+ })
+})
+
+describe('has', () => {
+ beforeEach(() => {
+ const windowMock = {
+ location: { search: "?hello_session=session" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+ })
+
+ it('is true when the query parameter is present', () => {
+ const query = new Query()
+ expect(query.has("session")).toEqual(true)
+ })
+
+ it('is false when the query parameter is not present', () => {
+ const query = new Query()
+ expect(query.has("preview")).toEqual(false)
+ })
+})
+
+describe('inPreviewMode', () => {
+ it('is true when the preview query parameter is present', () => {
+ const windowMock = {
+ location: { search: "?hello_preview" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+
+ expect(Query.inPreviewMode).toEqual(true)
+ })
+
+ it('is false when the preview query parameter is not present', () => {
+ const windowMock = {
+ location: { search: "" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+
+ expect(Query.inPreviewMode).toEqual(false)
+ })
+})
+
+describe('session', () => {
+ it('gets the session from the query parameter when present in query', () => {
+ const windowMock = {
+ location: { search: "?hello_session=session" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+
+ const query = new Query()
+ expect(query.session).toEqual("session")
+ })
+
+ it('gets the session from the cookie when not present in query', () => {
+ const windowMock = {
+ location: { search: "" },
+ }
+
+ jest.spyOn(global, 'window', 'get').mockImplementation(() => windowMock)
+
+ document.cookie = "hello_session=session"
+
+ const query = new Query()
+ expect(query.session).toEqual("session")
+ })
+})
+
+describe("#toHellotextParameter", () => {
+ it("prefixes the argument with hello_", () => {
+ const query = new Query()
+ expect(query.toHellotextParam("preview")).toEqual("hello_preview")
+ });
+})
diff --git a/__tests__/query_test.js b/__tests__/query_test.js
deleted file mode 100644
index 679d200..0000000
--- a/__tests__/query_test.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * @jest-environment jsdom
- */
-
-import Query from "../src/query";
-
-describe("#toHellotextParameter", () => {
- it("prefixes the argument with hello_", () => {
- const query = new Query()
-
- expect(query.toHellotextParam("preview")).toEqual("hello_preview")
- });
-})
diff --git a/dist/hellotext.js b/dist/hellotext.js
index 3e71025..1286af5 100644
--- a/dist/hellotext.js
+++ b/dist/hellotext.js
@@ -1 +1 @@
-(()=>{"use strict";var e={413:(e,t)=>{function r(e){var t="function"==typeof Map?new Map:void 0;return r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,o)}function o(){return n(e,arguments,a(this).constructor)}return o.prototype=Object.create(e.prototype,{constructor:{value:o,enumerable:!1,writable:!0,configurable:!0}}),i(o,e)},r(e)}function n(e,t,r){return n=o()?Reflect.construct.bind():function(e,t,r){var n=[null];n.push.apply(n,t);var o=new(Function.bind.apply(e,n));return r&&i(o,r.prototype),o},n.apply(null,arguments)}function o(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}function a(e){return a=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},a(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.InvalidEvent=void 0;var s=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&i(e,t)}(u,e);var t,r,n,s=(r=u,n=o(),function(){var e,t=a(r);if(n){var o=a(this).constructor;e=Reflect.construct(t,arguments,o)}else e=t.apply(this,arguments);return function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,e)});function u(e){var t;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,u),(t=s.call(this,"".concat(e," is not valid. Please provide a valid event name"))).name="InvalidEvent",t}return t=u,Object.defineProperty(t,"prototype",{writable:!1}),t}(r(Error));t.InvalidEvent=s},215:(e,t)=>{function r(e){var t="function"==typeof Map?new Map:void 0;return r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,o)}function o(){return n(e,arguments,a(this).constructor)}return o.prototype=Object.create(e.prototype,{constructor:{value:o,enumerable:!1,writable:!0,configurable:!0}}),i(o,e)},r(e)}function n(e,t,r){return n=o()?Reflect.construct.bind():function(e,t,r){var n=[null];n.push.apply(n,t);var o=new(Function.bind.apply(e,n));return r&&i(o,r.prototype),o},n.apply(null,arguments)}function o(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function i(e,t){return i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},i(e,t)}function a(e){return a=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},a(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.NotInitializedError=void 0;var s=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&i(e,t)}(u,e);var t,r,n,s=(r=u,n=o(),function(){var e,t=a(r);if(n){var o=a(this).constructor;e=Reflect.construct(t,arguments,o)}else e=t.apply(this,arguments);return function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,e)});function u(){var e;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,u),(e=s.call(this,"You need to initialize before tracking events. Call Hellotext.initialize and pass your public business id")).name="NotInitializedError",e}return t=u,Object.defineProperty(t,"prototype",{writable:!1}),t}(r(Error));t.NotInitializedError=s},372:(e,t)=>{function r(e,t){for(var r=0;rt===e))}}],null&&r(t.prototype,null),n&&r(t,n),Object.defineProperty(t,"prototype",{writable:!1}),e}();t.default=n,n.events=["session-set"]},179:(e,t)=>{function r(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function n(e){for(var t=1;te!==t)))}},{key:"emit",value:function(e,t){this.subscribers[e].forEach((e=>{e(t)}))}},{key:"listeners",get:function(){return 0!==Object.keys(this.subscribers).length}}])&&i(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();t.default=s},474:(e,t)=>{function r(e,t){for(var r=0;r{function r(e,t){for(var r=0;r{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof self&&self||void 0!==e&&e,t={searchParams:"URLSearchParams"in e,iterable:"Symbol"in e&&"iterator"in Symbol,blob:"FileReader"in e&&"Blob"in e&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in e,arrayBuffer:"ArrayBuffer"in e};if(t.arrayBuffer)var r=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],n=ArrayBuffer.isView||function(e){return e&&r.indexOf(Object.prototype.toString.call(e))>-1};function o(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||""===e)throw new TypeError('Invalid character in header field name: "'+e+'"');return e.toLowerCase()}function i(e){return"string"!=typeof e&&(e=String(e)),e}function a(e){var r={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return t.iterable&&(r[Symbol.iterator]=function(){return r}),r}function s(e){this.map={},e instanceof s?e.forEach((function(e,t){this.append(t,e)}),this):Array.isArray(e)?e.forEach((function(e){this.append(e[0],e[1])}),this):e&&Object.getOwnPropertyNames(e).forEach((function(t){this.append(t,e[t])}),this)}function u(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function c(e){return new Promise((function(t,r){e.onload=function(){t(e.result)},e.onerror=function(){r(e.error)}}))}function f(e){var t=new FileReader,r=c(t);return t.readAsArrayBuffer(e),r}function l(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function p(){return this.bodyUsed=!1,this._initBody=function(e){var r;this.bodyUsed=this.bodyUsed,this._bodyInit=e,e?"string"==typeof e?this._bodyText=e:t.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:t.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:t.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():t.arrayBuffer&&t.blob&&(r=e)&&DataView.prototype.isPrototypeOf(r)?(this._bodyArrayBuffer=l(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):t.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||n(e))?this._bodyArrayBuffer=l(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):t.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},t.blob&&(this.blob=function(){var e=u(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?u(this)||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer)):this.blob().then(f)}),this.text=function(){var e,t,r,n=u(this);if(n)return n;if(this._bodyBlob)return e=this._bodyBlob,r=c(t=new FileReader),t.readAsText(e),r;if(this._bodyArrayBuffer)return Promise.resolve(function(e){for(var t=new Uint8Array(e),r=new Array(t.length),n=0;n-1?n:r),this.mode=t.mode||this.mode||null,this.signal=t.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&o)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(o),!("GET"!==this.method&&"HEAD"!==this.method||"no-store"!==t.cache&&"no-cache"!==t.cache)){var i=/([?&])_=[^&]*/;i.test(this.url)?this.url=this.url.replace(i,"$1_="+(new Date).getTime()):this.url+=(/\?/.test(this.url)?"&":"?")+"_="+(new Date).getTime()}}function d(e){var t=new FormData;return e.trim().split("&").forEach((function(e){if(e){var r=e.split("="),n=r.shift().replace(/\+/g," "),o=r.join("=").replace(/\+/g," ");t.append(decodeURIComponent(n),decodeURIComponent(o))}})),t}function b(e,t){if(!(this instanceof b))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');t||(t={}),this.type="default",this.status=void 0===t.status?200:t.status,this.ok=this.status>=200&&this.status<300,this.statusText=void 0===t.statusText?"":""+t.statusText,this.headers=new s(t.headers),this.url=t.url||"",this._initBody(e)}y.prototype.clone=function(){return new y(this,{body:this._bodyInit})},p.call(y.prototype),p.call(b.prototype),b.prototype.clone=function(){return new b(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new s(this.headers),url:this.url})},b.error=function(){var e=new b(null,{status:0,statusText:""});return e.type="error",e};var v=[301,302,303,307,308];b.redirect=function(e,t){if(-1===v.indexOf(t))throw new RangeError("Invalid status code");return new b(null,{status:t,headers:{location:e}})};var w=e.DOMException;try{new w}catch(e){(w=function(e,t){this.message=e,this.name=t;var r=Error(e);this.stack=r.stack}).prototype=Object.create(Error.prototype),w.prototype.constructor=w}function m(r,n){return new Promise((function(o,a){var u=new y(r,n);if(u.signal&&u.signal.aborted)return a(new w("Aborted","AbortError"));var c=new XMLHttpRequest;function f(){c.abort()}c.onload=function(){var e,t,r={status:c.status,statusText:c.statusText,headers:(e=c.getAllResponseHeaders()||"",t=new s,e.replace(/\r?\n[\t ]+/g," ").split("\r").map((function(e){return 0===e.indexOf("\n")?e.substr(1,e.length):e})).forEach((function(e){var r=e.split(":"),n=r.shift().trim();if(n){var o=r.join(":").trim();t.append(n,o)}})),t)};r.url="responseURL"in c?c.responseURL:r.headers.get("X-Request-URL");var n="response"in c?c.response:c.responseText;setTimeout((function(){o(new b(n,r))}),0)},c.onerror=function(){setTimeout((function(){a(new TypeError("Network request failed"))}),0)},c.ontimeout=function(){setTimeout((function(){a(new TypeError("Network request failed"))}),0)},c.onabort=function(){setTimeout((function(){a(new w("Aborted","AbortError"))}),0)},c.open(u.method,function(t){try{return""===t&&e.location.href?e.location.href:t}catch(e){return t}}(u.url),!0),"include"===u.credentials?c.withCredentials=!0:"omit"===u.credentials&&(c.withCredentials=!1),"responseType"in c&&(t.blob?c.responseType="blob":t.arrayBuffer&&u.headers.get("Content-Type")&&-1!==u.headers.get("Content-Type").indexOf("application/octet-stream")&&(c.responseType="arraybuffer")),!n||"object"!=typeof n.headers||n.headers instanceof s?u.headers.forEach((function(e,t){c.setRequestHeader(t,e)})):Object.getOwnPropertyNames(n.headers).forEach((function(e){c.setRequestHeader(e,i(n.headers[e]))})),u.signal&&(u.signal.addEventListener("abort",f),c.onreadystatechange=function(){4===c.readyState&&u.signal.removeEventListener("abort",f)}),c.send(void 0===u._bodyInit?null:u._bodyInit)}))}m.polyfill=!0,e.fetch||(e.fetch=m,e.Headers=s,e.Request=y,e.Response=b)})(),(()=>{var e=s(r(372)),t=s(r(179)),n=s(r(310)),o=s(r(474)),i=r(215),a=r(413);function s(e){return e&&e.__esModule?e:{default:e}}function u(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{autogenerateSession:!0};if(d(this,m)[m]=e,d(this,O)[O]=t,d(this,P)[P]=new o.default(window.location.search),!d(this,P)[P].has("preview")){var r=d(this,P)[P].get("session")||d(this,S)[S];r&&"undefined"!==r&&"null"!==r?(d(this,w)[w]=r,d(this,T)[T]()):t.autogenerateSession&&d(this,_)[_]().then((e=>{d(this,w)[w]=e.id,d(this,T)[T]()}))}}},{key:"track",value:(u=p((function*(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(d(this,j)[j])throw new i.NotInitializedError;if(d(this,P)[P].has("preview"))return new n.default(!0,{received:!0});var r=yield fetch(this.__apiURL+"track/events",{headers:d(this,E)[E],method:"post",body:JSON.stringify(c(c({session:this.session,action:e},t),{},{url:t&&t.url||window.location.href}))});return new n.default(200===r.status,yield r.json())})),function(e){return u.apply(this,arguments)})},{key:"on",value:function(t,r){if(e.default.invalid(t))throw new a.InvalidEvent(t);d(this,g)[g].addSubscriber(t,r)}},{key:"removeEventListener",value:function(t,r){if(e.default.invalid(t))throw new a.InvalidEvent(t);d(this,g)[g].removeSubscriber(t,r)}},{key:"session",get:function(){if(d(this,j)[j])throw new i.NotInitializedError;return d(this,w)[w]}},{key:"isInitialized",get:function(){return void 0!==d(this,w)[w]}}],s&&h(r,s),Object.defineProperty(r,"prototype",{writable:!1}),t}();function x(){return(x=p((function*(){if(d(this,j)[j])throw new i.NotInitializedError;var e=this.__apiURL+"track/sessions";return this.mintingPromise=yield fetch(e,{method:"post",headers:{Authorization:"Bearer ".concat(d(this,m)[m])}}),this.mintingPromise.json()}))).apply(this,arguments)}Object.defineProperty(A,S,{get:function(){var e;return null===(e=document.cookie.match("(^|;)\\s*hello_session\\s*=\\s*([^;]+)"))||void 0===e?void 0:e.pop()},set:void 0}),Object.defineProperty(A,T,{value:function(){if(d(this,j)[j])throw new i.NotInitializedError;d(this,g)[g].listeners&&d(this,g)[g].emit("session-set",d(this,w)[w]),document.cookie="hello_session=".concat(d(this,w)[w])}}),Object.defineProperty(A,E,{get:function(){if(d(this,j)[j])throw new i.NotInitializedError;return{Authorization:"Bearer ".concat(d(this,m)[m]),Accept:"application.json","Content-Type":"application/json"}},set:void 0}),Object.defineProperty(A,_,{value:function(){return x.apply(this,arguments)}}),Object.defineProperty(A,j,{get:function(){return void 0===d(this,m)[m]},set:void 0}),A.__apiURL="https://api.hellotext.com/v1/",Object.defineProperty(A,w,{writable:!0,value:void 0}),Object.defineProperty(A,m,{writable:!0,value:void 0}),Object.defineProperty(A,O,{writable:!0,value:void 0}),Object.defineProperty(A,g,{writable:!0,value:new t.default}),Object.defineProperty(A,P,{writable:!0,value:void 0})})()})();
\ No newline at end of file
+(()=>{"use strict";var e={599:(e,t,r)=>{r.r(t),r.d(t,{Application:()=>X,AttributeObserver:()=>w,Context:()=>I,Controller:()=>ue,ElementObserver:()=>g,IndexedMultimap:()=>A,Multimap:()=>k,SelectorObserver:()=>C,StringMapObserver:()=>T,TokenListObserver:()=>M,ValueListObserver:()=>_,add:()=>O,defaultSchema:()=>J,del:()=>E,fetch:()=>P,prune:()=>j});class n{constructor(e,t,r){this.eventTarget=e,this.eventName=t,this.eventOptions=r,this.unorderedBindings=new Set}connect(){this.eventTarget.addEventListener(this.eventName,this,this.eventOptions)}disconnect(){this.eventTarget.removeEventListener(this.eventName,this,this.eventOptions)}bindingConnected(e){this.unorderedBindings.add(e)}bindingDisconnected(e){this.unorderedBindings.delete(e)}handleEvent(e){const t=function(e){if("immediatePropagationStopped"in e)return e;{const{stopImmediatePropagation:t}=e;return Object.assign(e,{immediatePropagationStopped:!1,stopImmediatePropagation(){this.immediatePropagationStopped=!0,t.call(this)}})}}(e);for(const e of this.bindings){if(t.immediatePropagationStopped)break;e.handleEvent(t)}}hasBindings(){return this.unorderedBindings.size>0}get bindings(){return Array.from(this.unorderedBindings).sort(((e,t)=>{const r=e.index,n=t.index;return rn?1:0}))}}class i{constructor(e){this.application=e,this.eventListenerMaps=new Map,this.started=!1}start(){this.started||(this.started=!0,this.eventListeners.forEach((e=>e.connect())))}stop(){this.started&&(this.started=!1,this.eventListeners.forEach((e=>e.disconnect())))}get eventListeners(){return Array.from(this.eventListenerMaps.values()).reduce(((e,t)=>e.concat(Array.from(t.values()))),[])}bindingConnected(e){this.fetchEventListenerForBinding(e).bindingConnected(e)}bindingDisconnected(e,t=!1){this.fetchEventListenerForBinding(e).bindingDisconnected(e),t&&this.clearEventListenersForBinding(e)}handleError(e,t,r={}){this.application.handleError(e,`Error ${t}`,r)}clearEventListenersForBinding(e){const t=this.fetchEventListenerForBinding(e);t.hasBindings()||(t.disconnect(),this.removeMappedEventListenerFor(e))}removeMappedEventListenerFor(e){const{eventTarget:t,eventName:r,eventOptions:n}=e,i=this.fetchEventListenerMapForEventTarget(t),o=this.cacheKey(r,n);i.delete(o),0==i.size&&this.eventListenerMaps.delete(t)}fetchEventListenerForBinding(e){const{eventTarget:t,eventName:r,eventOptions:n}=e;return this.fetchEventListener(t,r,n)}fetchEventListener(e,t,r){const n=this.fetchEventListenerMapForEventTarget(e),i=this.cacheKey(t,r);let o=n.get(i);return o||(o=this.createEventListener(e,t,r),n.set(i,o)),o}createEventListener(e,t,r){const i=new n(e,t,r);return this.started&&i.connect(),i}fetchEventListenerMapForEventTarget(e){let t=this.eventListenerMaps.get(e);return t||(t=new Map,this.eventListenerMaps.set(e,t)),t}cacheKey(e,t){const r=[e];return Object.keys(t).sort().forEach((e=>{r.push(`${t[e]?"":"!"}${e}`)})),r.join(":")}}const o={stop:({event:e,value:t})=>(t&&e.stopPropagation(),!0),prevent:({event:e,value:t})=>(t&&e.preventDefault(),!0),self:({event:e,value:t,element:r})=>!t||r===e.target},s=/^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/;function a(e){return e.replace(/(?:[_-])([a-z0-9])/g,((e,t)=>t.toUpperCase()))}function u(e){return a(e.replace(/--/g,"-").replace(/__/g,"_"))}function c(e){return e.charAt(0).toUpperCase()+e.slice(1)}function l(e){return e.replace(/([A-Z])/g,((e,t)=>`-${t.toLowerCase()}`))}function h(e){return null!=e}function d(e,t){return Object.prototype.hasOwnProperty.call(e,t)}const f=["meta","ctrl","alt","shift"];class p{constructor(e,t,r,n){this.element=e,this.index=t,this.eventTarget=r.eventTarget||e,this.eventName=r.eventName||function(e){const t=e.tagName.toLowerCase();if(t in m)return m[t](e)}(e)||y("missing event name"),this.eventOptions=r.eventOptions||{},this.identifier=r.identifier||y("missing identifier"),this.methodName=r.methodName||y("missing method name"),this.keyFilter=r.keyFilter||"",this.schema=n}static forToken(e,t){return new this(e.element,e.index,function(e){const t=e.trim().match(s)||[];let r=t[2],n=t[3];return n&&!["keydown","keyup","keypress"].includes(r)&&(r+=`.${n}`,n=""),{eventTarget:(i=t[4],"window"==i?window:"document"==i?document:void 0),eventName:r,eventOptions:t[7]?(o=t[7],o.split(":").reduce(((e,t)=>Object.assign(e,{[t.replace(/^!/,"")]:!/^!/.test(t)})),{})):{},identifier:t[5],methodName:t[6],keyFilter:t[1]||n};var i,o}(e.content),t)}toString(){const e=this.keyFilter?`.${this.keyFilter}`:"",t=this.eventTargetName?`@${this.eventTargetName}`:"";return`${this.eventName}${e}${t}->${this.identifier}#${this.methodName}`}shouldIgnoreKeyboardEvent(e){if(!this.keyFilter)return!1;const t=this.keyFilter.split("+");if(this.keyFilterDissatisfied(e,t))return!0;const r=t.filter((e=>!f.includes(e)))[0];return!!r&&(d(this.keyMappings,r)||y(`contains unknown key filter: ${this.keyFilter}`),this.keyMappings[r].toLowerCase()!==e.key.toLowerCase())}shouldIgnoreMouseEvent(e){if(!this.keyFilter)return!1;const t=[this.keyFilter];return!!this.keyFilterDissatisfied(e,t)}get params(){const e={},t=new RegExp(`^data-${this.identifier}-(.+)-param$`,"i");for(const{name:r,value:n}of Array.from(this.element.attributes)){const i=r.match(t),o=i&&i[1];o&&(e[a(o)]=v(n))}return e}get eventTargetName(){return(e=this.eventTarget)==window?"window":e==document?"document":void 0;var e}get keyMappings(){return this.schema.keyMappings}keyFilterDissatisfied(e,t){const[r,n,i,o]=f.map((e=>t.includes(e)));return e.metaKey!==r||e.ctrlKey!==n||e.altKey!==i||e.shiftKey!==o}}const m={a:()=>"click",button:()=>"click",form:()=>"submit",details:()=>"toggle",input:e=>"submit"==e.getAttribute("type")?"click":"input",select:()=>"change",textarea:()=>"input"};function y(e){throw new Error(e)}function v(e){try{return JSON.parse(e)}catch(t){return e}}class b{constructor(e,t){this.context=e,this.action=t}get index(){return this.action.index}get eventTarget(){return this.action.eventTarget}get eventOptions(){return this.action.eventOptions}get identifier(){return this.context.identifier}handleEvent(e){const t=this.prepareActionEvent(e);this.willBeInvokedByEvent(e)&&this.applyEventModifiers(t)&&this.invokeWithEvent(t)}get eventName(){return this.action.eventName}get method(){const e=this.controller[this.methodName];if("function"==typeof e)return e;throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`)}applyEventModifiers(e){const{element:t}=this.action,{actionDescriptorFilters:r}=this.context.application,{controller:n}=this.context;let i=!0;for(const[o,s]of Object.entries(this.eventOptions))if(o in r){const a=r[o];i=i&&a({name:o,value:s,event:e,element:t,controller:n})}return i}prepareActionEvent(e){return Object.assign(e,{params:this.action.params})}invokeWithEvent(e){const{target:t,currentTarget:r}=e;try{this.method.call(this.controller,e),this.context.logDebugActivity(this.methodName,{event:e,target:t,currentTarget:r,action:this.methodName})}catch(t){const{identifier:r,controller:n,element:i,index:o}=this,s={identifier:r,controller:n,element:i,index:o,event:e};this.context.handleError(t,`invoking action "${this.action}"`,s)}}willBeInvokedByEvent(e){const t=e.target;return!(e instanceof KeyboardEvent&&this.action.shouldIgnoreKeyboardEvent(e))&&!(e instanceof MouseEvent&&this.action.shouldIgnoreMouseEvent(e))&&(this.element===t||(t instanceof Element&&this.element.contains(t)?this.scope.containsElement(t):this.scope.containsElement(this.action.element)))}get controller(){return this.context.controller}get methodName(){return this.action.methodName}get element(){return this.scope.element}get scope(){return this.context.scope}}class g{constructor(e,t){this.mutationObserverInit={attributes:!0,childList:!0,subtree:!0},this.element=e,this.started=!1,this.delegate=t,this.elements=new Set,this.mutationObserver=new MutationObserver((e=>this.processMutations(e)))}start(){this.started||(this.started=!0,this.mutationObserver.observe(this.element,this.mutationObserverInit),this.refresh())}pause(e){this.started&&(this.mutationObserver.disconnect(),this.started=!1),e(),this.started||(this.mutationObserver.observe(this.element,this.mutationObserverInit),this.started=!0)}stop(){this.started&&(this.mutationObserver.takeRecords(),this.mutationObserver.disconnect(),this.started=!1)}refresh(){if(this.started){const e=new Set(this.matchElementsInTree());for(const t of Array.from(this.elements))e.has(t)||this.removeElement(t);for(const t of Array.from(e))this.addElement(t)}}processMutations(e){if(this.started)for(const t of e)this.processMutation(t)}processMutation(e){"attributes"==e.type?this.processAttributeChange(e.target,e.attributeName):"childList"==e.type&&(this.processRemovedNodes(e.removedNodes),this.processAddedNodes(e.addedNodes))}processAttributeChange(e,t){this.elements.has(e)?this.delegate.elementAttributeChanged&&this.matchElement(e)?this.delegate.elementAttributeChanged(e,t):this.removeElement(e):this.matchElement(e)&&this.addElement(e)}processRemovedNodes(e){for(const t of Array.from(e)){const e=this.elementFromNode(t);e&&this.processTree(e,this.removeElement)}}processAddedNodes(e){for(const t of Array.from(e)){const e=this.elementFromNode(t);e&&this.elementIsActive(e)&&this.processTree(e,this.addElement)}}matchElement(e){return this.delegate.matchElement(e)}matchElementsInTree(e=this.element){return this.delegate.matchElementsInTree(e)}processTree(e,t){for(const r of this.matchElementsInTree(e))t.call(this,r)}elementFromNode(e){if(e.nodeType==Node.ELEMENT_NODE)return e}elementIsActive(e){return e.isConnected==this.element.isConnected&&this.element.contains(e)}addElement(e){this.elements.has(e)||this.elementIsActive(e)&&(this.elements.add(e),this.delegate.elementMatched&&this.delegate.elementMatched(e))}removeElement(e){this.elements.has(e)&&(this.elements.delete(e),this.delegate.elementUnmatched&&this.delegate.elementUnmatched(e))}}class w{constructor(e,t,r){this.attributeName=t,this.delegate=r,this.elementObserver=new g(e,this)}get element(){return this.elementObserver.element}get selector(){return`[${this.attributeName}]`}start(){this.elementObserver.start()}pause(e){this.elementObserver.pause(e)}stop(){this.elementObserver.stop()}refresh(){this.elementObserver.refresh()}get started(){return this.elementObserver.started}matchElement(e){return e.hasAttribute(this.attributeName)}matchElementsInTree(e){const t=this.matchElement(e)?[e]:[],r=Array.from(e.querySelectorAll(this.selector));return t.concat(r)}elementMatched(e){this.delegate.elementMatchedAttribute&&this.delegate.elementMatchedAttribute(e,this.attributeName)}elementUnmatched(e){this.delegate.elementUnmatchedAttribute&&this.delegate.elementUnmatchedAttribute(e,this.attributeName)}elementAttributeChanged(e,t){this.delegate.elementAttributeValueChanged&&this.attributeName==t&&this.delegate.elementAttributeValueChanged(e,t)}}function O(e,t,r){P(e,t).add(r)}function E(e,t,r){P(e,t).delete(r),j(e,t)}function P(e,t){let r=e.get(t);return r||(r=new Set,e.set(t,r)),r}function j(e,t){const r=e.get(t);null!=r&&0==r.size&&e.delete(t)}class k{constructor(){this.valuesByKey=new Map}get keys(){return Array.from(this.valuesByKey.keys())}get values(){return Array.from(this.valuesByKey.values()).reduce(((e,t)=>e.concat(Array.from(t))),[])}get size(){return Array.from(this.valuesByKey.values()).reduce(((e,t)=>e+t.size),0)}add(e,t){O(this.valuesByKey,e,t)}delete(e,t){E(this.valuesByKey,e,t)}has(e,t){const r=this.valuesByKey.get(e);return null!=r&&r.has(t)}hasKey(e){return this.valuesByKey.has(e)}hasValue(e){return Array.from(this.valuesByKey.values()).some((t=>t.has(e)))}getValuesForKey(e){const t=this.valuesByKey.get(e);return t?Array.from(t):[]}getKeysForValue(e){return Array.from(this.valuesByKey).filter((([t,r])=>r.has(e))).map((([e,t])=>e))}}class A extends k{constructor(){super(),this.keysByValue=new Map}get values(){return Array.from(this.keysByValue.keys())}add(e,t){super.add(e,t),O(this.keysByValue,t,e)}delete(e,t){super.delete(e,t),E(this.keysByValue,t,e)}hasValue(e){return this.keysByValue.has(e)}getKeysForValue(e){const t=this.keysByValue.get(e);return t?Array.from(t):[]}}class C{constructor(e,t,r,n){this._selector=t,this.details=n,this.elementObserver=new g(e,this),this.delegate=r,this.matchesByElement=new k}get started(){return this.elementObserver.started}get selector(){return this._selector}set selector(e){this._selector=e,this.refresh()}start(){this.elementObserver.start()}pause(e){this.elementObserver.pause(e)}stop(){this.elementObserver.stop()}refresh(){this.elementObserver.refresh()}get element(){return this.elementObserver.element}matchElement(e){const{selector:t}=this;if(t){const r=e.matches(t);return this.delegate.selectorMatchElement?r&&this.delegate.selectorMatchElement(e,this.details):r}return!1}matchElementsInTree(e){const{selector:t}=this;if(t){const r=this.matchElement(e)?[e]:[],n=Array.from(e.querySelectorAll(t)).filter((e=>this.matchElement(e)));return r.concat(n)}return[]}elementMatched(e){const{selector:t}=this;t&&this.selectorMatched(e,t)}elementUnmatched(e){const t=this.matchesByElement.getKeysForValue(e);for(const r of t)this.selectorUnmatched(e,r)}elementAttributeChanged(e,t){const{selector:r}=this;if(r){const t=this.matchElement(e),n=this.matchesByElement.has(r,e);t&&!n?this.selectorMatched(e,r):!t&&n&&this.selectorUnmatched(e,r)}}selectorMatched(e,t){this.delegate.selectorMatched(e,t,this.details),this.matchesByElement.add(t,e)}selectorUnmatched(e,t){this.delegate.selectorUnmatched(e,t,this.details),this.matchesByElement.delete(t,e)}}class T{constructor(e,t){this.element=e,this.delegate=t,this.started=!1,this.stringMap=new Map,this.mutationObserver=new MutationObserver((e=>this.processMutations(e)))}start(){this.started||(this.started=!0,this.mutationObserver.observe(this.element,{attributes:!0,attributeOldValue:!0}),this.refresh())}stop(){this.started&&(this.mutationObserver.takeRecords(),this.mutationObserver.disconnect(),this.started=!1)}refresh(){if(this.started)for(const e of this.knownAttributeNames)this.refreshAttribute(e,null)}processMutations(e){if(this.started)for(const t of e)this.processMutation(t)}processMutation(e){const t=e.attributeName;t&&this.refreshAttribute(t,e.oldValue)}refreshAttribute(e,t){const r=this.delegate.getStringMapKeyForAttribute(e);if(null!=r){this.stringMap.has(e)||this.stringMapKeyAdded(r,e);const n=this.element.getAttribute(e);if(this.stringMap.get(e)!=n&&this.stringMapValueChanged(n,r,t),null==n){const t=this.stringMap.get(e);this.stringMap.delete(e),t&&this.stringMapKeyRemoved(r,e,t)}else this.stringMap.set(e,n)}}stringMapKeyAdded(e,t){this.delegate.stringMapKeyAdded&&this.delegate.stringMapKeyAdded(e,t)}stringMapValueChanged(e,t,r){this.delegate.stringMapValueChanged&&this.delegate.stringMapValueChanged(e,t,r)}stringMapKeyRemoved(e,t,r){this.delegate.stringMapKeyRemoved&&this.delegate.stringMapKeyRemoved(e,t,r)}get knownAttributeNames(){return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames)))}get currentAttributeNames(){return Array.from(this.element.attributes).map((e=>e.name))}get recordedAttributeNames(){return Array.from(this.stringMap.keys())}}class M{constructor(e,t,r){this.attributeObserver=new w(e,t,this),this.delegate=r,this.tokensByElement=new k}get started(){return this.attributeObserver.started}start(){this.attributeObserver.start()}pause(e){this.attributeObserver.pause(e)}stop(){this.attributeObserver.stop()}refresh(){this.attributeObserver.refresh()}get element(){return this.attributeObserver.element}get attributeName(){return this.attributeObserver.attributeName}elementMatchedAttribute(e){this.tokensMatched(this.readTokensForElement(e))}elementAttributeValueChanged(e){const[t,r]=this.refreshTokensForElement(e);this.tokensUnmatched(t),this.tokensMatched(r)}elementUnmatchedAttribute(e){this.tokensUnmatched(this.tokensByElement.getValuesForKey(e))}tokensMatched(e){e.forEach((e=>this.tokenMatched(e)))}tokensUnmatched(e){e.forEach((e=>this.tokenUnmatched(e)))}tokenMatched(e){this.delegate.tokenMatched(e),this.tokensByElement.add(e.element,e)}tokenUnmatched(e){this.delegate.tokenUnmatched(e),this.tokensByElement.delete(e.element,e)}refreshTokensForElement(e){const t=this.tokensByElement.getValuesForKey(e),r=this.readTokensForElement(e),n=function(e,t){const r=Math.max(e.length,t.length);return Array.from({length:r},((r,n)=>[e[n],t[n]]))}(t,r).findIndex((([e,t])=>{return n=t,!((r=e)&&n&&r.index==n.index&&r.content==n.content);var r,n}));return-1==n?[[],[]]:[t.slice(n),r.slice(n)]}readTokensForElement(e){const t=this.attributeName;return function(e,t,r){return e.trim().split(/\s+/).filter((e=>e.length)).map(((e,n)=>({element:t,attributeName:r,content:e,index:n})))}(e.getAttribute(t)||"",e,t)}}class _{constructor(e,t,r){this.tokenListObserver=new M(e,t,this),this.delegate=r,this.parseResultsByToken=new WeakMap,this.valuesByTokenByElement=new WeakMap}get started(){return this.tokenListObserver.started}start(){this.tokenListObserver.start()}stop(){this.tokenListObserver.stop()}refresh(){this.tokenListObserver.refresh()}get element(){return this.tokenListObserver.element}get attributeName(){return this.tokenListObserver.attributeName}tokenMatched(e){const{element:t}=e,{value:r}=this.fetchParseResultForToken(e);r&&(this.fetchValuesByTokenForElement(t).set(e,r),this.delegate.elementMatchedValue(t,r))}tokenUnmatched(e){const{element:t}=e,{value:r}=this.fetchParseResultForToken(e);r&&(this.fetchValuesByTokenForElement(t).delete(e),this.delegate.elementUnmatchedValue(t,r))}fetchParseResultForToken(e){let t=this.parseResultsByToken.get(e);return t||(t=this.parseToken(e),this.parseResultsByToken.set(e,t)),t}fetchValuesByTokenForElement(e){let t=this.valuesByTokenByElement.get(e);return t||(t=new Map,this.valuesByTokenByElement.set(e,t)),t}parseToken(e){try{return{value:this.delegate.parseValueForToken(e)}}catch(e){return{error:e}}}}class S{constructor(e,t){this.context=e,this.delegate=t,this.bindingsByAction=new Map}start(){this.valueListObserver||(this.valueListObserver=new _(this.element,this.actionAttribute,this),this.valueListObserver.start())}stop(){this.valueListObserver&&(this.valueListObserver.stop(),delete this.valueListObserver,this.disconnectAllActions())}get element(){return this.context.element}get identifier(){return this.context.identifier}get actionAttribute(){return this.schema.actionAttribute}get schema(){return this.context.schema}get bindings(){return Array.from(this.bindingsByAction.values())}connectAction(e){const t=new b(this.context,e);this.bindingsByAction.set(e,t),this.delegate.bindingConnected(t)}disconnectAction(e){const t=this.bindingsByAction.get(e);t&&(this.bindingsByAction.delete(e),this.delegate.bindingDisconnected(t))}disconnectAllActions(){this.bindings.forEach((e=>this.delegate.bindingDisconnected(e,!0))),this.bindingsByAction.clear()}parseValueForToken(e){const t=p.forToken(e,this.schema);if(t.identifier==this.identifier)return t}elementMatchedValue(e,t){this.connectAction(t)}elementUnmatchedValue(e,t){this.disconnectAction(t)}}class x{constructor(e,t){this.context=e,this.receiver=t,this.stringMapObserver=new T(this.element,this),this.valueDescriptorMap=this.controller.valueDescriptorMap}start(){this.stringMapObserver.start(),this.invokeChangedCallbacksForDefaultValues()}stop(){this.stringMapObserver.stop()}get element(){return this.context.element}get controller(){return this.context.controller}getStringMapKeyForAttribute(e){if(e in this.valueDescriptorMap)return this.valueDescriptorMap[e].name}stringMapKeyAdded(e,t){const r=this.valueDescriptorMap[t];this.hasValue(e)||this.invokeChangedCallback(e,r.writer(this.receiver[e]),r.writer(r.defaultValue))}stringMapValueChanged(e,t,r){const n=this.valueDescriptorNameMap[t];null!==e&&(null===r&&(r=n.writer(n.defaultValue)),this.invokeChangedCallback(t,e,r))}stringMapKeyRemoved(e,t,r){const n=this.valueDescriptorNameMap[e];this.hasValue(e)?this.invokeChangedCallback(e,n.writer(this.receiver[e]),r):this.invokeChangedCallback(e,n.writer(n.defaultValue),r)}invokeChangedCallbacksForDefaultValues(){for(const{key:e,name:t,defaultValue:r,writer:n}of this.valueDescriptors)null==r||this.controller.data.has(e)||this.invokeChangedCallback(t,n(r),void 0)}invokeChangedCallback(e,t,r){const n=`${e}Changed`,i=this.receiver[n];if("function"==typeof i){const n=this.valueDescriptorNameMap[e];try{const e=n.reader(t);let o=r;r&&(o=n.reader(r)),i.call(this.receiver,e,o)}catch(e){throw e instanceof TypeError&&(e.message=`Stimulus Value "${this.context.identifier}.${n.name}" - ${e.message}`),e}}}get valueDescriptors(){const{valueDescriptorMap:e}=this;return Object.keys(e).map((t=>e[t]))}get valueDescriptorNameMap(){const e={};return Object.keys(this.valueDescriptorMap).forEach((t=>{const r=this.valueDescriptorMap[t];e[r.name]=r})),e}hasValue(e){const t=`has${c(this.valueDescriptorNameMap[e].name)}`;return this.receiver[t]}}class B{constructor(e,t){this.context=e,this.delegate=t,this.targetsByName=new k}start(){this.tokenListObserver||(this.tokenListObserver=new M(this.element,this.attributeName,this),this.tokenListObserver.start())}stop(){this.tokenListObserver&&(this.disconnectAllTargets(),this.tokenListObserver.stop(),delete this.tokenListObserver)}tokenMatched({element:e,content:t}){this.scope.containsElement(e)&&this.connectTarget(e,t)}tokenUnmatched({element:e,content:t}){this.disconnectTarget(e,t)}connectTarget(e,t){var r;this.targetsByName.has(t,e)||(this.targetsByName.add(t,e),null===(r=this.tokenListObserver)||void 0===r||r.pause((()=>this.delegate.targetConnected(e,t))))}disconnectTarget(e,t){var r;this.targetsByName.has(t,e)&&(this.targetsByName.delete(t,e),null===(r=this.tokenListObserver)||void 0===r||r.pause((()=>this.delegate.targetDisconnected(e,t))))}disconnectAllTargets(){for(const e of this.targetsByName.keys)for(const t of this.targetsByName.getValuesForKey(e))this.disconnectTarget(t,e)}get attributeName(){return`data-${this.context.identifier}-target`}get element(){return this.context.element}get scope(){return this.context.scope}}function F(e,t){const r=L(e);return Array.from(r.reduce(((e,r)=>(function(e,t){const r=e[t];return Array.isArray(r)?r:[]}(r,t).forEach((t=>e.add(t))),e)),new Set))}function L(e){const t=[];for(;e;)t.push(e),e=Object.getPrototypeOf(e);return t.reverse()}class N{constructor(e,t){this.started=!1,this.context=e,this.delegate=t,this.outletsByName=new k,this.outletElementsByName=new k,this.selectorObserverMap=new Map,this.attributeObserverMap=new Map}start(){this.started||(this.outletDefinitions.forEach((e=>{this.setupSelectorObserverForOutlet(e),this.setupAttributeObserverForOutlet(e)})),this.started=!0,this.dependentContexts.forEach((e=>e.refresh())))}refresh(){this.selectorObserverMap.forEach((e=>e.refresh())),this.attributeObserverMap.forEach((e=>e.refresh()))}stop(){this.started&&(this.started=!1,this.disconnectAllOutlets(),this.stopSelectorObservers(),this.stopAttributeObservers())}stopSelectorObservers(){this.selectorObserverMap.size>0&&(this.selectorObserverMap.forEach((e=>e.stop())),this.selectorObserverMap.clear())}stopAttributeObservers(){this.attributeObserverMap.size>0&&(this.attributeObserverMap.forEach((e=>e.stop())),this.attributeObserverMap.clear())}selectorMatched(e,t,{outletName:r}){const n=this.getOutlet(e,r);n&&this.connectOutlet(n,e,r)}selectorUnmatched(e,t,{outletName:r}){const n=this.getOutletFromMap(e,r);n&&this.disconnectOutlet(n,e,r)}selectorMatchElement(e,{outletName:t}){const r=this.selector(t),n=this.hasOutlet(e,t),i=e.matches(`[${this.schema.controllerAttribute}~=${t}]`);return!!r&&n&&i&&e.matches(r)}elementMatchedAttribute(e,t){const r=this.getOutletNameFromOutletAttributeName(t);r&&this.updateSelectorObserverForOutlet(r)}elementAttributeValueChanged(e,t){const r=this.getOutletNameFromOutletAttributeName(t);r&&this.updateSelectorObserverForOutlet(r)}elementUnmatchedAttribute(e,t){const r=this.getOutletNameFromOutletAttributeName(t);r&&this.updateSelectorObserverForOutlet(r)}connectOutlet(e,t,r){var n;this.outletElementsByName.has(r,t)||(this.outletsByName.add(r,e),this.outletElementsByName.add(r,t),null===(n=this.selectorObserverMap.get(r))||void 0===n||n.pause((()=>this.delegate.outletConnected(e,t,r))))}disconnectOutlet(e,t,r){var n;this.outletElementsByName.has(r,t)&&(this.outletsByName.delete(r,e),this.outletElementsByName.delete(r,t),null===(n=this.selectorObserverMap.get(r))||void 0===n||n.pause((()=>this.delegate.outletDisconnected(e,t,r))))}disconnectAllOutlets(){for(const e of this.outletElementsByName.keys)for(const t of this.outletElementsByName.getValuesForKey(e))for(const r of this.outletsByName.getValuesForKey(e))this.disconnectOutlet(r,t,e)}updateSelectorObserverForOutlet(e){const t=this.selectorObserverMap.get(e);t&&(t.selector=this.selector(e))}setupSelectorObserverForOutlet(e){const t=this.selector(e),r=new C(document.body,t,this,{outletName:e});this.selectorObserverMap.set(e,r),r.start()}setupAttributeObserverForOutlet(e){const t=this.attributeNameForOutletName(e),r=new w(this.scope.element,t,this);this.attributeObserverMap.set(e,r),r.start()}selector(e){return this.scope.outlets.getSelectorForOutletName(e)}attributeNameForOutletName(e){return this.scope.schema.outletAttributeForScope(this.identifier,e)}getOutletNameFromOutletAttributeName(e){return this.outletDefinitions.find((t=>this.attributeNameForOutletName(t)===e))}get outletDependencies(){const e=new k;return this.router.modules.forEach((t=>{F(t.definition.controllerConstructor,"outlets").forEach((r=>e.add(r,t.identifier)))})),e}get outletDefinitions(){return this.outletDependencies.getKeysForValue(this.identifier)}get dependentControllerIdentifiers(){return this.outletDependencies.getValuesForKey(this.identifier)}get dependentContexts(){const e=this.dependentControllerIdentifiers;return this.router.contexts.filter((t=>e.includes(t.identifier)))}hasOutlet(e,t){return!!this.getOutlet(e,t)||!!this.getOutletFromMap(e,t)}getOutlet(e,t){return this.application.getControllerForElementAndIdentifier(e,t)}getOutletFromMap(e,t){return this.outletsByName.getValuesForKey(t).find((t=>t.element===e))}get scope(){return this.context.scope}get schema(){return this.context.schema}get identifier(){return this.context.identifier}get application(){return this.context.application}get router(){return this.application.router}}class I{constructor(e,t){this.logDebugActivity=(e,t={})=>{const{identifier:r,controller:n,element:i}=this;t=Object.assign({identifier:r,controller:n,element:i},t),this.application.logDebugActivity(this.identifier,e,t)},this.module=e,this.scope=t,this.controller=new e.controllerConstructor(this),this.bindingObserver=new S(this,this.dispatcher),this.valueObserver=new x(this,this.controller),this.targetObserver=new B(this,this),this.outletObserver=new N(this,this);try{this.controller.initialize(),this.logDebugActivity("initialize")}catch(e){this.handleError(e,"initializing controller")}}connect(){this.bindingObserver.start(),this.valueObserver.start(),this.targetObserver.start(),this.outletObserver.start();try{this.controller.connect(),this.logDebugActivity("connect")}catch(e){this.handleError(e,"connecting controller")}}refresh(){this.outletObserver.refresh()}disconnect(){try{this.controller.disconnect(),this.logDebugActivity("disconnect")}catch(e){this.handleError(e,"disconnecting controller")}this.outletObserver.stop(),this.targetObserver.stop(),this.valueObserver.stop(),this.bindingObserver.stop()}get application(){return this.module.application}get identifier(){return this.module.identifier}get schema(){return this.application.schema}get dispatcher(){return this.application.dispatcher}get element(){return this.scope.element}get parentElement(){return this.element.parentElement}handleError(e,t,r={}){const{identifier:n,controller:i,element:o}=this;r=Object.assign({identifier:n,controller:i,element:o},r),this.application.handleError(e,`Error ${t}`,r)}targetConnected(e,t){this.invokeControllerMethod(`${t}TargetConnected`,e)}targetDisconnected(e,t){this.invokeControllerMethod(`${t}TargetDisconnected`,e)}outletConnected(e,t,r){this.invokeControllerMethod(`${u(r)}OutletConnected`,e,t)}outletDisconnected(e,t,r){this.invokeControllerMethod(`${u(r)}OutletDisconnected`,e,t)}invokeControllerMethod(e,...t){const r=this.controller;"function"==typeof r[e]&&r[e](...t)}}const D="function"==typeof Object.getOwnPropertySymbols?e=>[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)]:Object.getOwnPropertyNames,$=(()=>{function e(e){function t(){return Reflect.construct(e,arguments,new.target)}return t.prototype=Object.create(e.prototype,{constructor:{value:t}}),Reflect.setPrototypeOf(t,e),t}try{return function(){const t=e((function(){this.a.call(this)}));t.prototype.a=function(){},new t}(),e}catch(e){return e=>class extends e{}}})();class R{constructor(e,t){this.application=e,this.definition=function(e){return{identifier:e.identifier,controllerConstructor:(t=e.controllerConstructor,function(e,t){const r=$(e),n=function(e,t){return D(t).reduce(((r,n)=>{const i=function(e,t,r){const n=Object.getOwnPropertyDescriptor(e,r);if(!n||!("value"in n)){const e=Object.getOwnPropertyDescriptor(t,r).value;return n&&(e.get=n.get||e.get,e.set=n.set||e.set),e}}(e,t,n);return i&&Object.assign(r,{[n]:i}),r}),{})}(e.prototype,t);return Object.defineProperties(r.prototype,n),r}(t,function(e){return F(e,"blessings").reduce(((t,r)=>{const n=r(e);for(const e in n){const r=t[e]||{};t[e]=Object.assign(r,n[e])}return t}),{})}(t)))};var t}(t),this.contextsByScope=new WeakMap,this.connectedContexts=new Set}get identifier(){return this.definition.identifier}get controllerConstructor(){return this.definition.controllerConstructor}get contexts(){return Array.from(this.connectedContexts)}connectContextForScope(e){const t=this.fetchContextForScope(e);this.connectedContexts.add(t),t.connect()}disconnectContextForScope(e){const t=this.contextsByScope.get(e);t&&(this.connectedContexts.delete(t),t.disconnect())}fetchContextForScope(e){let t=this.contextsByScope.get(e);return t||(t=new I(this,e),this.contextsByScope.set(e,t)),t}}class V{constructor(e){this.scope=e}has(e){return this.data.has(this.getDataKey(e))}get(e){return this.getAll(e)[0]}getAll(e){return(this.data.get(this.getDataKey(e))||"").match(/[^\s]+/g)||[]}getAttributeName(e){return this.data.getAttributeNameForKey(this.getDataKey(e))}getDataKey(e){return`${e}-class`}get data(){return this.scope.data}}class K{constructor(e){this.scope=e}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get(e){const t=this.getAttributeNameForKey(e);return this.element.getAttribute(t)}set(e,t){const r=this.getAttributeNameForKey(e);return this.element.setAttribute(r,t),this.get(e)}has(e){const t=this.getAttributeNameForKey(e);return this.element.hasAttribute(t)}delete(e){if(this.has(e)){const t=this.getAttributeNameForKey(e);return this.element.removeAttribute(t),!0}return!1}getAttributeNameForKey(e){return`data-${this.identifier}-${l(e)}`}}class U{constructor(e){this.warnedKeysByObject=new WeakMap,this.logger=e}warn(e,t,r){let n=this.warnedKeysByObject.get(e);n||(n=new Set,this.warnedKeysByObject.set(e,n)),n.has(t)||(n.add(t),this.logger.warn(r,e))}}function q(e,t){return`[${e}~="${t}"]`}class z{constructor(e){this.scope=e}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get schema(){return this.scope.schema}has(e){return null!=this.find(e)}find(...e){return e.reduce(((e,t)=>e||this.findTarget(t)||this.findLegacyTarget(t)),void 0)}findAll(...e){return e.reduce(((e,t)=>[...e,...this.findAllTargets(t),...this.findAllLegacyTargets(t)]),[])}findTarget(e){const t=this.getSelectorForTargetName(e);return this.scope.findElement(t)}findAllTargets(e){const t=this.getSelectorForTargetName(e);return this.scope.findAllElements(t)}getSelectorForTargetName(e){return q(this.schema.targetAttributeForScope(this.identifier),e)}findLegacyTarget(e){const t=this.getLegacySelectorForTargetName(e);return this.deprecate(this.scope.findElement(t),e)}findAllLegacyTargets(e){const t=this.getLegacySelectorForTargetName(e);return this.scope.findAllElements(t).map((t=>this.deprecate(t,e)))}getLegacySelectorForTargetName(e){const t=`${this.identifier}.${e}`;return q(this.schema.targetAttribute,t)}deprecate(e,t){if(e){const{identifier:r}=this,n=this.schema.targetAttribute,i=this.schema.targetAttributeForScope(r);this.guide.warn(e,`target:${t}`,`Please replace ${n}="${r}.${t}" with ${i}="${t}". The ${n} attribute is deprecated and will be removed in a future version of Stimulus.`)}return e}get guide(){return this.scope.guide}}class H{constructor(e,t){this.scope=e,this.controllerElement=t}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get schema(){return this.scope.schema}has(e){return null!=this.find(e)}find(...e){return e.reduce(((e,t)=>e||this.findOutlet(t)),void 0)}findAll(...e){return e.reduce(((e,t)=>[...e,...this.findAllOutlets(t)]),[])}getSelectorForOutletName(e){const t=this.schema.outletAttributeForScope(this.identifier,e);return this.controllerElement.getAttribute(t)}findOutlet(e){const t=this.getSelectorForOutletName(e);if(t)return this.findElement(t,e)}findAllOutlets(e){const t=this.getSelectorForOutletName(e);return t?this.findAllElements(t,e):[]}findElement(e,t){return this.scope.queryElements(e).filter((r=>this.matchesElement(r,e,t)))[0]}findAllElements(e,t){return this.scope.queryElements(e).filter((r=>this.matchesElement(r,e,t)))}matchesElement(e,t,r){const n=e.getAttribute(this.scope.schema.controllerAttribute)||"";return e.matches(t)&&n.split(" ").includes(r)}}class Z{constructor(e,t,r,n){this.targets=new z(this),this.classes=new V(this),this.data=new K(this),this.containsElement=e=>e.closest(this.controllerSelector)===this.element,this.schema=e,this.element=t,this.identifier=r,this.guide=new U(n),this.outlets=new H(this.documentScope,t)}findElement(e){return this.element.matches(e)?this.element:this.queryElements(e).find(this.containsElement)}findAllElements(e){return[...this.element.matches(e)?[this.element]:[],...this.queryElements(e).filter(this.containsElement)]}queryElements(e){return Array.from(this.element.querySelectorAll(e))}get controllerSelector(){return q(this.schema.controllerAttribute,this.identifier)}get isDocumentScope(){return this.element===document.documentElement}get documentScope(){return this.isDocumentScope?this:new Z(this.schema,document.documentElement,this.identifier,this.guide.logger)}}class W{constructor(e,t,r){this.element=e,this.schema=t,this.delegate=r,this.valueListObserver=new _(this.element,this.controllerAttribute,this),this.scopesByIdentifierByElement=new WeakMap,this.scopeReferenceCounts=new WeakMap}start(){this.valueListObserver.start()}stop(){this.valueListObserver.stop()}get controllerAttribute(){return this.schema.controllerAttribute}parseValueForToken(e){const{element:t,content:r}=e;return this.parseValueForElementAndIdentifier(t,r)}parseValueForElementAndIdentifier(e,t){const r=this.fetchScopesByIdentifierForElement(e);let n=r.get(t);return n||(n=this.delegate.createScopeForElementAndIdentifier(e,t),r.set(t,n)),n}elementMatchedValue(e,t){const r=(this.scopeReferenceCounts.get(t)||0)+1;this.scopeReferenceCounts.set(t,r),1==r&&this.delegate.scopeConnected(t)}elementUnmatchedValue(e,t){const r=this.scopeReferenceCounts.get(t);r&&(this.scopeReferenceCounts.set(t,r-1),1==r&&this.delegate.scopeDisconnected(t))}fetchScopesByIdentifierForElement(e){let t=this.scopesByIdentifierByElement.get(e);return t||(t=new Map,this.scopesByIdentifierByElement.set(e,t)),t}}class G{constructor(e){this.application=e,this.scopeObserver=new W(this.element,this.schema,this),this.scopesByIdentifier=new k,this.modulesByIdentifier=new Map}get element(){return this.application.element}get schema(){return this.application.schema}get logger(){return this.application.logger}get controllerAttribute(){return this.schema.controllerAttribute}get modules(){return Array.from(this.modulesByIdentifier.values())}get contexts(){return this.modules.reduce(((e,t)=>e.concat(t.contexts)),[])}start(){this.scopeObserver.start()}stop(){this.scopeObserver.stop()}loadDefinition(e){this.unloadIdentifier(e.identifier);const t=new R(this.application,e);this.connectModule(t);const r=e.controllerConstructor.afterLoad;r&&r.call(e.controllerConstructor,e.identifier,this.application)}unloadIdentifier(e){const t=this.modulesByIdentifier.get(e);t&&this.disconnectModule(t)}getContextForElementAndIdentifier(e,t){const r=this.modulesByIdentifier.get(t);if(r)return r.contexts.find((t=>t.element==e))}proposeToConnectScopeForElementAndIdentifier(e,t){const r=this.scopeObserver.parseValueForElementAndIdentifier(e,t);r?this.scopeObserver.elementMatchedValue(r.element,r):console.error(`Couldn't find or create scope for identifier: "${t}" and element:`,e)}handleError(e,t,r){this.application.handleError(e,t,r)}createScopeForElementAndIdentifier(e,t){return new Z(this.schema,e,t,this.logger)}scopeConnected(e){this.scopesByIdentifier.add(e.identifier,e);const t=this.modulesByIdentifier.get(e.identifier);t&&t.connectContextForScope(e)}scopeDisconnected(e){this.scopesByIdentifier.delete(e.identifier,e);const t=this.modulesByIdentifier.get(e.identifier);t&&t.disconnectContextForScope(e)}connectModule(e){this.modulesByIdentifier.set(e.identifier,e),this.scopesByIdentifier.getValuesForKey(e.identifier).forEach((t=>e.connectContextForScope(t)))}disconnectModule(e){this.modulesByIdentifier.delete(e.identifier),this.scopesByIdentifier.getValuesForKey(e.identifier).forEach((t=>e.disconnectContextForScope(t)))}}const J={controllerAttribute:"data-controller",actionAttribute:"data-action",targetAttribute:"data-target",targetAttributeForScope:e=>`data-${e}-target`,outletAttributeForScope:(e,t)=>`data-${e}-${t}-outlet`,keyMappings:Object.assign(Object.assign({enter:"Enter",tab:"Tab",esc:"Escape",space:" ",up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight",home:"Home",end:"End",page_up:"PageUp",page_down:"PageDown"},Q("abcdefghijklmnopqrstuvwxyz".split("").map((e=>[e,e])))),Q("0123456789".split("").map((e=>[e,e]))))};function Q(e){return e.reduce(((e,[t,r])=>Object.assign(Object.assign({},e),{[t]:r})),{})}class X{constructor(e=document.documentElement,t=J){this.logger=console,this.debug=!1,this.logDebugActivity=(e,t,r={})=>{this.debug&&this.logFormattedMessage(e,t,r)},this.element=e,this.schema=t,this.dispatcher=new i(this),this.router=new G(this),this.actionDescriptorFilters=Object.assign({},o)}static start(e,t){const r=new this(e,t);return r.start(),r}async start(){await new Promise((e=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",(()=>e())):e()})),this.logDebugActivity("application","starting"),this.dispatcher.start(),this.router.start(),this.logDebugActivity("application","start")}stop(){this.logDebugActivity("application","stopping"),this.dispatcher.stop(),this.router.stop(),this.logDebugActivity("application","stop")}register(e,t){this.load({identifier:e,controllerConstructor:t})}registerActionOption(e,t){this.actionDescriptorFilters[e]=t}load(e,...t){(Array.isArray(e)?e:[e,...t]).forEach((e=>{e.controllerConstructor.shouldLoad&&this.router.loadDefinition(e)}))}unload(e,...t){(Array.isArray(e)?e:[e,...t]).forEach((e=>this.router.unloadIdentifier(e)))}get controllers(){return this.router.contexts.map((e=>e.controller))}getControllerForElementAndIdentifier(e,t){const r=this.router.getContextForElementAndIdentifier(e,t);return r?r.controller:null}handleError(e,t,r){var n;this.logger.error("%s\n\n%o\n\n%o",t,e,r),null===(n=window.onerror)||void 0===n||n.call(window,t,"",0,0,e)}logFormattedMessage(e,t,r={}){r=Object.assign({application:this},r),this.logger.groupCollapsed(`${e} #${t}`),this.logger.log("details:",Object.assign({},r)),this.logger.groupEnd()}}function Y(e,t,r){return e.application.getControllerForElementAndIdentifier(t,r)}function ee(e,t,r){let n=Y(e,t,r);return n||(e.application.router.proposeToConnectScopeForElementAndIdentifier(t,r),n=Y(e,t,r),n||void 0)}function te([e,t],r){return function(e){const{token:t,typeDefinition:r}=e,n=`${l(t)}-value`,i=function(e){const{controller:t,token:r,typeDefinition:n}=e,i=function(e){const{controller:t,token:r,typeObject:n}=e,i=h(n.type),o=h(n.default),s=i&&o,a=i&&!o,u=!i&&o,c=re(n.type),l=ne(e.typeObject.default);if(a)return c;if(u)return l;if(c!==l)throw new Error(`The specified default value for the Stimulus Value "${t?`${t}.${r}`:r}" must match the defined type "${c}". The provided default value of "${n.default}" is of type "${l}".`);return s?c:void 0}({controller:t,token:r,typeObject:n}),o=ne(n),s=re(n),a=i||o||s;if(a)return a;throw new Error(`Unknown value type "${t?`${t}.${n}`:r}" for "${r}" value`)}(e);return{type:i,key:n,name:a(n),get defaultValue(){return function(e){const t=re(e);if(t)return ie[t];const r=d(e,"default"),n=d(e,"type"),i=e;if(r)return i.default;if(n){const{type:e}=i,t=re(e);if(t)return ie[t]}return e}(r)},get hasCustomDefaultValue(){return void 0!==ne(r)},reader:oe[i],writer:se[i]||se.default}}({controller:r,token:e,typeDefinition:t})}function re(e){switch(e){case Array:return"array";case Boolean:return"boolean";case Number:return"number";case Object:return"object";case String:return"string"}}function ne(e){switch(typeof e){case"boolean":return"boolean";case"number":return"number";case"string":return"string"}return Array.isArray(e)?"array":"[object Object]"===Object.prototype.toString.call(e)?"object":void 0}const ie={get array(){return[]},boolean:!1,number:0,get object(){return{}},string:""},oe={array(e){const t=JSON.parse(e);if(!Array.isArray(t))throw new TypeError(`expected value of type "array" but instead got value "${e}" of type "${ne(t)}"`);return t},boolean:e=>!("0"==e||"false"==String(e).toLowerCase()),number:e=>Number(e.replace(/_/g,"")),object(e){const t=JSON.parse(e);if(null===t||"object"!=typeof t||Array.isArray(t))throw new TypeError(`expected value of type "object" but instead got value "${e}" of type "${ne(t)}"`);return t},string:e=>e},se={default:function(e){return`${e}`},array:ae,object:ae};function ae(e){return JSON.stringify(e)}class ue{constructor(e){this.context=e}static get shouldLoad(){return!0}static afterLoad(e,t){}get application(){return this.context.application}get scope(){return this.context.scope}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get targets(){return this.scope.targets}get outlets(){return this.scope.outlets}get classes(){return this.scope.classes}get data(){return this.scope.data}initialize(){}connect(){}disconnect(){}dispatch(e,{target:t=this.element,detail:r={},prefix:n=this.identifier,bubbles:i=!0,cancelable:o=!0}={}){const s=new CustomEvent(n?`${n}:${e}`:e,{detail:r,bubbles:i,cancelable:o});return t.dispatchEvent(s),s}}ue.blessings=[function(e){return F(e,"classes").reduce(((e,t)=>{return Object.assign(e,{[`${r=t}Class`]:{get(){const{classes:e}=this;if(e.has(r))return e.get(r);{const t=e.getAttributeName(r);throw new Error(`Missing attribute "${t}"`)}}},[`${r}Classes`]:{get(){return this.classes.getAll(r)}},[`has${c(r)}Class`]:{get(){return this.classes.has(r)}}});var r}),{})},function(e){return F(e,"targets").reduce(((e,t)=>{return Object.assign(e,{[`${r=t}Target`]:{get(){const e=this.targets.find(r);if(e)return e;throw new Error(`Missing target element "${r}" for "${this.identifier}" controller`)}},[`${r}Targets`]:{get(){return this.targets.findAll(r)}},[`has${c(r)}Target`]:{get(){return this.targets.has(r)}}});var r}),{})},function(e){const t=function(e,t){return L(e).reduce(((e,r)=>(e.push(...function(e,t){const r=e[t];return r?Object.keys(r).map((e=>[e,r[e]])):[]}(r,t)),e)),[])}(e,"values"),r={valueDescriptorMap:{get(){return t.reduce(((e,t)=>{const r=te(t,this.identifier),n=this.data.getAttributeNameForKey(r.key);return Object.assign(e,{[n]:r})}),{})}}};return t.reduce(((e,t)=>Object.assign(e,function(e,t){const r=te(e,void 0),{key:n,name:i,reader:o,writer:s}=r;return{[i]:{get(){const e=this.data.get(n);return null!==e?o(e):r.defaultValue},set(e){void 0===e?this.data.delete(n):this.data.set(n,s(e))}},[`has${c(i)}`]:{get(){return this.data.has(n)||r.hasCustomDefaultValue}}}}(t))),r)},function(e){return F(e,"outlets").reduce(((e,t)=>Object.assign(e,function(e){const t=u(e);return{[`${t}Outlet`]:{get(){const t=this.outlets.find(e),r=this.outlets.getSelectorForOutletName(e);if(t){const r=ee(this,t,e);if(r)return r;throw new Error(`The provided outlet element is missing an outlet controller "${e}" instance for host controller "${this.identifier}"`)}throw new Error(`Missing outlet element "${e}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${r}".`)}},[`${t}Outlets`]:{get(){const t=this.outlets.findAll(e);return t.length>0?t.map((t=>{const r=ee(this,t,e);if(r)return r;console.warn(`The provided outlet element is missing an outlet controller "${e}" instance for host controller "${this.identifier}"`,t)})).filter((e=>e)):[]}},[`${t}OutletElement`]:{get(){const t=this.outlets.find(e),r=this.outlets.getSelectorForOutletName(e);if(t)return t;throw new Error(`Missing outlet element "${e}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${r}".`)}},[`${t}OutletElements`]:{get(){return this.outlets.findAll(e)}},[`has${c(t)}Outlet`]:{get(){return this.outlets.has(e)}}}}(t))),{})}],ue.targets=[],ue.outlets=[],ue.values={}},697:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=s(r(231)),i=s(r(830)),o=s(r(911));function s(e){return e&&e.__esModule?e:{default:e}}function a(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(613);function i(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function o(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(613),i=r(541),o=r(874);function s(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function a(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n},o=r(613),s=r(874);function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e){for(var t=1;t{function r(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function n(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(613);function i(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function o(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n},o=r(613),s=r(874);function a(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function u(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var o=e.apply(t,r);function s(e){a(o,n,i,s,u,"next",e)}function u(e){a(o,n,i,s,u,"throw",e)}s(void 0)}))}}function c(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.InputBuilder=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n};function o(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.LogoBuilder=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n};function o(e,t){for(var r=0;r\n ".concat(i.default.business.locale.white_label.powered_by,'\n \n \n \n ')}})},761:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.OTPBuilder=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n};function o(e,t){for(var r=0;r\n \n
').concat(t,'
\n \n \n \n \n \n ")}})},425:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(599),i=u(r(688)),o=r(541),s=u(r(495)),a=r(761);function u(e){return e&&e.__esModule?e:{default:e}}function c(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function l(e,t){for(var r=0;re.disabled=!0));var r=yield t.json();r.identified?this.completed():(i.default.setSession(r.session),this.revealOTPContainer(r.id))}},u=function(){var e=this,t=arguments;return new Promise((function(r,i){var o=n.apply(e,t);function s(e){c(o,r,i,s,a,"next",e)}function a(e){c(o,r,i,s,a,"throw",e)}s(void 0)}))},function(e){return u.apply(this,arguments)})},{key:"revealOTPContainer",value:function(e){var t=this.requiredInputs.find((e=>"email"===e.name))?i.default.business.locale.otp.sent_to_email:i.default.business.locale.otp.sent_to_phone;this.element.appendChild(a.OTPBuilder.build(e,t))}},{key:"completed",value:function(){this.form.markAsCompleted(this.formData),this.element.remove()}},{key:"showErrorMessages",value:function(){this.element.querySelectorAll("input:invalid").forEach((e=>{e.closest("article").querySelector("[data-error-container]").innerText=e.validationMessage}))}},{key:"clearErrorMessages",value:function(){this.element.querySelectorAll("input").forEach((e=>{e.closest("article").querySelector("[data-error-container]").innerText=""}))}},{key:"inputTargetConnected",value:function(e){e.getAttribute("data-default-value")&&(e.value=e.getAttribute("data-default-value"))}},{key:"requiredInputs",get:function(){return this.inputTargets.filter((e=>e.required))}},{key:"invalid",get:function(){return!this.element.checkValidity()}}],r&&l(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),v}(n.Controller);t.default=p,p.values={data:Object,step:{type:Number,default:1}},p.targets=["inputContainer","input","button","otpContainer"]},454:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(599),i=s(r(688)),o=s(r(230));function s(e){return e&&e.__esModule?e:{default:e}}function a(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function u(e){return function(){var t=this,r=arguments;return new Promise((function(n,i){var o=e.apply(t,r);function s(e){a(o,n,i,s,u,"next",e)}function u(e){a(o,n,i,s,u,"throw",e)}s(void 0)}))}}function c(e,t){for(var r=0;r{this.attempts=0}),6e4)}},{key:"connect",value:function(){l(d(m.prototype),"connect",this).call(this),this.inputTarget.addEventListener("input",this.onInputChange)}},{key:"disconnect",value:function(){clearInterval(this.throttleInterval),this.inputTarget.removeEventListener("input",this.onInputChange),l(d(m.prototype),"disconnect",this).call(this)}},{key:"resend",value:(s=u((function*(){if(this.throttled)return alert(i.default.business.locale.otp.throttled);this.resendButtonTarget.disabled=!0,(yield o.default.resendOTP(this.submissionIdValue)).succeeded&&(this.resendButtonTarget.disabled=!1),alert(i.default.business.locale.otp.resend_successful),this.attempts+=1})),function(){return s.apply(this,arguments)})},{key:"onInputChange",value:(n=u((function*(){6===this.inputTarget.value.length&&(this.inputTarget.disabled=!0,this.resendButtonTarget.disabled=!0,(yield o.default.verifyOTP(this.submissionIdValue,this.inputTarget.value)).succeeded?this.dispatch("verified",{detail:{submissionId:this.submissionIdValue}}):alert(i.default.business.locale.otp.invalid),this.inputTarget.disabled=!1,this.resendButtonTarget.disabled=!1)})),function(){return n.apply(this,arguments)})},{key:"throttled",get:function(){return this.attempts>=3}}],r&&c(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),m}(n.Controller);t.default=f,f.values={submissionId:String},f.targets=["input","resendButton"]},660:(e,t)=>{function r(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=r(160);function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;tt===e))}}],(r=[{key:"addSubscriber",value:function(t,r){if(e.invalid(t))throw new n.InvalidEvent(t);this.subscribers=o(o({},this.subscribers),{},{[t]:this.subscribers[t]?[...this.subscribers[t],r]:[r]})}},{key:"removeSubscriber",value:function(t,r){if(e.invalid(t))throw new n.InvalidEvent(t);this.subscribers[t]&&(this.subscribers[t]=this.subscribers[t].filter((e=>e!==r)))}},{key:"dispatch",value:function(e,t){var r;null===(r=this.subscribers[e])||void 0===r||r.forEach((e=>{e(t)}))}},{key:"listeners",get:function(){return 0!==Object.keys(this.subscribers).length}}])&&a(t.prototype,r),i&&a(t,i),Object.defineProperty(t,"prototype",{writable:!1}),e}();t.default=c,c.events=["session-set","forms:collected","form:completed"]},613:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"Configuration",{enumerable:!0,get:function(){return o.Configuration}}),Object.defineProperty(t,"Event",{enumerable:!0,get:function(){return i.default}});var n,i=(n=r(51))&&n.__esModule?n:{default:n},o=r(660)},160:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"InvalidEvent",{enumerable:!0,get:function(){return n.InvalidEvent}}),Object.defineProperty(t,"NotInitializedError",{enumerable:!0,get:function(){return i.NotInitializedError}});var n=r(547),i=r(735)},547:(e,t)=>{function r(e){var t="function"==typeof Map?new Map:void 0;return r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,i)}function i(){return n(e,arguments,s(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),o(i,e)},r(e)}function n(e,t,r){return n=i()?Reflect.construct.bind():function(e,t,r){var n=[null];n.push.apply(n,t);var i=new(Function.bind.apply(e,n));return r&&o(i,r.prototype),i},n.apply(null,arguments)}function i(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function o(e,t){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},o(e,t)}function s(e){return s=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},s(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.InvalidEvent=void 0;var a=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&o(e,t)}(u,e);var t,r,n,a=(r=u,n=i(),function(){var e,t=s(r);if(n){var i=s(this).constructor;e=Reflect.construct(t,arguments,i)}else e=t.apply(this,arguments);return function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,e)});function u(e){var t;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,u),(t=a.call(this,"".concat(e," is not valid. Please provide a valid event name"))).name="InvalidEvent",t}return t=u,Object.defineProperty(t,"prototype",{writable:!1}),t}(r(Error));t.InvalidEvent=a},735:(e,t)=>{function r(e){var t="function"==typeof Map?new Map:void 0;return r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,i)}function i(){return n(e,arguments,s(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),o(i,e)},r(e)}function n(e,t,r){return n=i()?Reflect.construct.bind():function(e,t,r){var n=[null];n.push.apply(n,t);var i=new(Function.bind.apply(e,n));return r&&o(i,r.prototype),i},n.apply(null,arguments)}function i(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function o(e,t){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},o(e,t)}function s(e){return s=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},s(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.NotInitializedError=void 0;var a=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&o(e,t)}(u,e);var t,r,n,a=(r=u,n=i(),function(){var e,t=s(r);if(n){var i=s(this).constructor;e=Reflect.construct(t,arguments,i)}else e=t.apply(this,arguments);return function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,e)});function u(){var e;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,u),(e=a.call(this,"You need to initialize before tracking events. Call Hellotext.initialize and pass your public business id")).name="NotInitializedError",e}return t=u,Object.defineProperty(t,"prototype",{writable:!1}),t}(r(Error));t.NotInitializedError=a},688:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=r(613),o=(n=r(697))&&n.__esModule?n:{default:n},s=r(541),a=r(160);function u(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{autogenerateSession:!0};this.business=new s.Business(e),this.forms=new s.FormCollection,m(this,g)[g]=i.Configuration.assign(t),m(this,w)[w]=new s.Query,addEventListener("load",(()=>{this.forms.collect()})),m(this,w)[w].inPreviewMode||(m(this,w)[w].session?m(this,b)[b]=s.Cookies.set("hello_session",m(this,w)[w].session):t.autogenerateSession&&m(this,O)[O]().then((e=>{m(this,b)[b]=s.Cookies.set("hello_session",e.id)})))}},{key:"setSession",value:function(e){m(this,b)[b]=s.Cookies.set("hello_session",e)}},{key:"track",value:(n=d((function*(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(this.notInitialized)throw new a.NotInitializedError;return yield o.default.events.create({headers:this.headers,body:c(c({session:this.session,action:e},t),{},{url:t&&t.url||window.location.href})})})),function(e){return n.apply(this,arguments)})},{key:"on",value:function(e,t){this.eventEmitter.addSubscriber(e,t)}},{key:"removeEventListener",value:function(e,t){this.eventEmitter.removeSubscriber(e,t)}},{key:"session",get:function(){if(this.notInitialized)throw new a.NotInitializedError;return m(this,b)[b]}},{key:"isInitialized",get:function(){return void 0!==m(this,b)[b]}},{key:"notInitialized",get:function(){return void 0===this.business.id}},{key:"headers",get:function(){if(this.notInitialized)throw new a.NotInitializedError;return{Authorization:"Bearer ".concat(this.business.id),Accept:"application.json","Content-Type":"application/json"}}}],r&&f(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function P(){return(P=d((function*(){if(this.notInitialized)throw new a.NotInitializedError;return o.default.sessions(this.business.id).create()}))).apply(this,arguments)}Object.defineProperty(E,O,{value:function(){return P.apply(this,arguments)}}),Object.defineProperty(E,b,{writable:!0,value:void 0}),Object.defineProperty(E,g,{writable:!0,value:void 0}),Object.defineProperty(E,w,{writable:!0,value:void 0}),E.eventEmitter=new i.Event,E.forms=void 0,E.business=void 0;var j=E;t.default=j},989:(e,t,r)=>{var n=r(599),i=a(r(688)),o=a(r(425)),s=a(r(454));function a(e){return e&&e.__esModule?e:{default:e}}r(689);var u=n.Application.start();u.register("hellotext--form",o.default),u.register("hellotext--otp",s.default),i.default},485:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,t.default={otp:{sent_to_email:"A One-Time Password has been sent to your email address",sent_to_phone:"An One-Time Password has been sent to your phone number",resend_successful:"The One-Time Password has been resent successfully",invalid:"Invalid One-Time Password",resend:"Resend OTP",throttled:"You have reached the maximum number of attempts. Please try again in 1 minute."},white_label:{powered_by:"Powered by"}}},594:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,t.default={otp:{sent_to_email:"Un código de un solo uso ha sido enviado a tu correo electrónico",sent_to_phone:"Un código de un solo uso ha sido enviado a tu número de teléfono",resend_successful:"El código de un solo uso ha sido reenviado exitosamente",invalid:"Código de un solo uso inválido",resend:"Reenviar OTP",throttled:"Has alcanzado el número máximo de intentos. Por favor intenta de nuevo en 1 minuto."},white_label:{powered_by:"Desarrollado por"}}},779:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=o(r(485)),i=o(r(594));function o(e){return e&&e.__esModule?e:{default:e}}var s={en:n.default,es:i.default};t.default=s},926:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Business=void 0;var n=o(r(830)),i=o(r(779));function o(e){return e&&e.__esModule?e:{default:e}}function s(e,t){for(var r=0;re.json())).then((e=>this.data=e))}}])&&s(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();t.Business=a},524:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Cookies=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n};function o(e,t){for(var r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.Form=void 0;var n,i=(n=r(688))&&n.__esModule?n:{default:n},o=r(219),s=r(846);function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e,t,r){return(t=h(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t,r,n,i,o,s){try{var a=e[o](s),u=a.value}catch(e){return void r(e)}a.done?t(u):Promise.resolve(u).then(n,i)}function l(e,t){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:null;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),Object.defineProperty(this,m,{value:v}),this.data=t,this.element=r||document.querySelector('[data-hello-form="'.concat(this.id,'"]'))||document.createElement("form")}var t,r,n,h;return t=e,r=[{key:"mount",value:(n=function*(){var e=this.data.steps[0];this.buildHeader(e.header),this.buildInputs(e.inputs),this.buildButton(e.button),this.buildFooter(e.footer),this.elementAttributes.forEach((e=>{this.element.setAttribute(e.name,e.value)})),document.contains(this.element)||document.body.appendChild(this.element),i.default.business.features.white_label||this.element.prepend(s.LogoBuilder.build())},h=function(){var e=this,t=arguments;return new Promise((function(r,i){var o=n.apply(e,t);function s(e){c(o,r,i,s,a,"next",e)}function a(e){c(o,r,i,s,a,"throw",e)}s(void 0)}))},function(){return h.apply(this,arguments)})},{key:"buildHeader",value:function(e){var t=d(this,m)[m]("[data-form-header]","header");t.innerHTML=e.content,this.element.querySelector("[data-form-header]")?this.element.querySelector("[data-form-header]").replaceWith(t):this.element.prepend(t)}},{key:"buildInputs",value:function(e){var t=d(this,m)[m]("[data-form-inputs]","main");e.map((e=>o.InputBuilder.build(e))).forEach((e=>t.appendChild(e))),this.element.querySelector("[data-form-inputs]")?this.element.querySelector("[data-form-inputs]").replaceWith(t):this.element.querySelector("[data-form-header]").insertAdjacentHTML("afterend",t.outerHTML)}},{key:"buildButton",value:function(e){var t=d(this,m)[m]("[data-form-button]","button");t.innerText=e.text,t.setAttribute("data-action","click->hellotext--form#submit"),t.setAttribute("data-hellotext--form-target","button"),this.element.querySelector("[data-form-button]")?this.element.querySelector("[data-form-button]").replaceWith(t):this.element.querySelector("[data-form-inputs]").insertAdjacentHTML("afterend",t.outerHTML)}},{key:"buildFooter",value:function(e){var t=d(this,m)[m]("[data-form-footer]","footer");t.innerHTML=e.content,this.element.querySelector("[data-form-footer]")?this.element.querySelector("[data-form-footer]").replaceWith(t):this.element.appendChild(t)}},{key:"markAsCompleted",value:function(e){localStorage.setItem("hello-form-".concat(this.id),"completed"),i.default.eventEmitter.dispatch("form:completed",function(e){for(var t=1;thellotext--form#completed"}]}}],r&&l(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function v(e,t){var r=this.element.querySelector(e);if(r)return r.cloneNode(!0);var n=document.createElement(t);return n.setAttribute(e.replace("[","").replace("]",""),""),n}t.Form=y},187:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.FormCollection=void 0;var n=a(r(688)),i=a(r(697)),o=r(860),s=r(160);function a(e){return e&&e.__esModule?e:{default:e}}function u(e,t){for(var r=0;ri.default.forms.get(e).then((e=>e.json()))));n.default.business.enabledWhitelist||console.warn("No whitelist has been configured. It is advised to whitelist the domain to avoid bots from submitting forms."),Promise.all(t).then((e=>e.forEach(this.add))).then((()=>n.default.eventEmitter.dispatch("forms:collected",this)))}}},{key:"forEach",value:function(e){this.forms.forEach(e)}},{key:"map",value:function(e){return this.forms.map(e)}},{key:"add",value:function(e){this.includes(e.id)||this.forms.push(new o.Form(e))}},{key:"getById",value:function(e){return this.forms.find((t=>t.id===e))}},{key:"getByIndex",value:function(e){return this.forms[e]}},{key:"includes",value:function(e){return this.forms.some((t=>t.id===e))}},{key:"excludes",value:function(e){return!this.includes(e)}},{key:"length",get:function(){return this.forms.length}}],r&&u(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function f(){return Array.from(document.querySelectorAll("[data-hello-form]")).map((e=>e.dataset.helloForm)).filter(this.excludes)}t.FormCollection=d},541:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"Business",{enumerable:!0,get:function(){return n.Business}}),Object.defineProperty(t,"Cookies",{enumerable:!0,get:function(){return s.Cookies}}),Object.defineProperty(t,"Form",{enumerable:!0,get:function(){return i.Form}}),Object.defineProperty(t,"FormCollection",{enumerable:!0,get:function(){return a.FormCollection}}),Object.defineProperty(t,"Query",{enumerable:!0,get:function(){return o.Query}});var n=r(926),i=r(860),o=r(992),s=r(524),a=r(187)},992:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Query=void 0;var n=r(524);function i(e,t){for(var r=0;r{r.d(t,{Z:()=>a});var n=r(81),i=r.n(n),o=r(645),s=r.n(o)()(i());s.push([e.id,"form[data-hello-form] {\n position: relative;\n\n article {\n [data-error-container] {\n display: none;\n }\n\n &:has(input:invalid) {\n [data-error-container] {\n display: block;\n }\n }\n }\n\n [data-logo-container] {\n display: flex;\n justify-content: center;\n align-items: flex-end;\n position: absolute;\n right: 1rem;\n bottom: 1rem;\n\n small {\n margin: 0 .3rem;\n }\n\n [data-hello-brand] {\n width: 4rem;\n }\n }\n}\n",""]);const a=s},645:e=>{e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r="",n=void 0!==t[5];return t[4]&&(r+="@supports (".concat(t[4],") {")),t[2]&&(r+="@media ".concat(t[2]," {")),n&&(r+="@layer".concat(t[5].length>0?" ".concat(t[5]):""," {")),r+=e(t),n&&(r+="}"),t[2]&&(r+="}"),t[4]&&(r+="}"),r})).join("")},t.i=function(e,r,n,i,o){"string"==typeof e&&(e=[[null,e,void 0]]);var s={};if(n)for(var a=0;a0?" ".concat(l[5]):""," {").concat(l[1],"}")),l[5]=o),r&&(l[2]?(l[1]="@media ".concat(l[2]," {").concat(l[1],"}"),l[2]=r):l[2]=r),i&&(l[4]?(l[1]="@supports (".concat(l[4],") {").concat(l[1],"}"),l[4]=i):l[4]="".concat(i)),t.push(l))}},t}},81:e=>{e.exports=function(e){return e[1]}},689:(e,t,r)=>{r.r(t),r.d(t,{default:()=>v});var n=r(379),i=r.n(n),o=r(795),s=r.n(o),a=r(569),u=r.n(a),c=r(565),l=r.n(c),h=r(216),d=r.n(h),f=r(589),p=r.n(f),m=r(601),y={};y.styleTagTransform=p(),y.setAttributes=l(),y.insert=u().bind(null,"head"),y.domAPI=s(),y.insertStyleElement=d(),i()(m.Z,y);const v=m.Z&&m.Z.locals?m.Z.locals:void 0},379:e=>{var t=[];function r(e){for(var r=-1,n=0;n{var t={};e.exports=function(e,r){var n=function(e){if(void 0===t[e]){var r=document.querySelector(e);if(window.HTMLIFrameElement&&r instanceof window.HTMLIFrameElement)try{r=r.contentDocument.head}catch(e){r=null}t[e]=r}return t[e]}(e);if(!n)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");n.appendChild(r)}},216:e=>{e.exports=function(e){var t=document.createElement("style");return e.setAttributes(t,e.attributes),e.insert(t,e.options),t}},565:(e,t,r)=>{e.exports=function(e){var t=r.nc;t&&e.setAttribute("nonce",t)}},795:e=>{e.exports=function(e){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var t=e.insertStyleElement(e);return{update:function(r){!function(e,t,r){var n="";r.supports&&(n+="@supports (".concat(r.supports,") {")),r.media&&(n+="@media ".concat(r.media," {"));var i=void 0!==r.layer;i&&(n+="@layer".concat(r.layer.length>0?" ".concat(r.layer):""," {")),n+=r.css,i&&(n+="}"),r.media&&(n+="}"),r.supports&&(n+="}");var o=r.sourceMap;o&&"undefined"!=typeof btoa&&(n+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(o))))," */")),t.styleTagTransform(n,e,t.options)}(t,e,r)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(t)}}}},589:e=>{e.exports=function(e,t){if(t.styleSheet)t.styleSheet.cssText=e;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}}},147:(e,t,r)=>{var n="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof self&&self||void 0!==n&&n,i={searchParams:"URLSearchParams"in n,iterable:"Symbol"in n&&"iterator"in Symbol,blob:"FileReader"in n&&"Blob"in n&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in n,arrayBuffer:"ArrayBuffer"in n};if(i.arrayBuffer)var o=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],s=ArrayBuffer.isView||function(e){return e&&o.indexOf(Object.prototype.toString.call(e))>-1};function a(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||""===e)throw new TypeError('Invalid character in header field name: "'+e+'"');return e.toLowerCase()}function u(e){return"string"!=typeof e&&(e=String(e)),e}function c(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return i.iterable&&(t[Symbol.iterator]=function(){return t}),t}function l(e){this.map={},e instanceof l?e.forEach((function(e,t){this.append(t,e)}),this):Array.isArray(e)?e.forEach((function(e){this.append(e[0],e[1])}),this):e&&Object.getOwnPropertyNames(e).forEach((function(t){this.append(t,e[t])}),this)}function h(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function d(e){return new Promise((function(t,r){e.onload=function(){t(e.result)},e.onerror=function(){r(e.error)}}))}function f(e){var t=new FileReader,r=d(t);return t.readAsArrayBuffer(e),r}function p(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function m(){return this.bodyUsed=!1,this._initBody=function(e){var t;this.bodyUsed=this.bodyUsed,this._bodyInit=e,e?"string"==typeof e?this._bodyText=e:i.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:i.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:i.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():i.arrayBuffer&&i.blob&&(t=e)&&DataView.prototype.isPrototypeOf(t)?(this._bodyArrayBuffer=p(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):i.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||s(e))?this._bodyArrayBuffer=p(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):i.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},i.blob&&(this.blob=function(){var e=h(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?h(this)||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer)):this.blob().then(f)}),this.text=function(){var e,t,r,n=h(this);if(n)return n;if(this._bodyBlob)return e=this._bodyBlob,r=d(t=new FileReader),t.readAsText(e),r;if(this._bodyArrayBuffer)return Promise.resolve(function(e){for(var t=new Uint8Array(e),r=new Array(t.length),n=0;n-1?n:r),this.mode=t.mode||this.mode||null,this.signal=t.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&i)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(i),!("GET"!==this.method&&"HEAD"!==this.method||"no-store"!==t.cache&&"no-cache"!==t.cache)){var o=/([?&])_=[^&]*/;o.test(this.url)?this.url=this.url.replace(o,"$1_="+(new Date).getTime()):this.url+=(/\?/.test(this.url)?"&":"?")+"_="+(new Date).getTime()}}function b(e){var t=new FormData;return e.trim().split("&").forEach((function(e){if(e){var r=e.split("="),n=r.shift().replace(/\+/g," "),i=r.join("=").replace(/\+/g," ");t.append(decodeURIComponent(n),decodeURIComponent(i))}})),t}function g(e,t){if(!(this instanceof g))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');t||(t={}),this.type="default",this.status=void 0===t.status?200:t.status,this.ok=this.status>=200&&this.status<300,this.statusText=void 0===t.statusText?"":""+t.statusText,this.headers=new l(t.headers),this.url=t.url||"",this._initBody(e)}v.prototype.clone=function(){return new v(this,{body:this._bodyInit})},m.call(v.prototype),m.call(g.prototype),g.prototype.clone=function(){return new g(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new l(this.headers),url:this.url})},g.error=function(){var e=new g(null,{status:0,statusText:""});return e.type="error",e};var w=[301,302,303,307,308];g.redirect=function(e,t){if(-1===w.indexOf(t))throw new RangeError("Invalid status code");return new g(null,{status:t,headers:{location:e}})};var O=n.DOMException;try{new O}catch(e){(O=function(e,t){this.message=e,this.name=t;var r=Error(e);this.stack=r.stack}).prototype=Object.create(Error.prototype),O.prototype.constructor=O}function E(e,t){return new Promise((function(r,o){var s=new v(e,t);if(s.signal&&s.signal.aborted)return o(new O("Aborted","AbortError"));var a=new XMLHttpRequest;function c(){a.abort()}a.onload=function(){var e,t,n={status:a.status,statusText:a.statusText,headers:(e=a.getAllResponseHeaders()||"",t=new l,e.replace(/\r?\n[\t ]+/g," ").split("\r").map((function(e){return 0===e.indexOf("\n")?e.substr(1,e.length):e})).forEach((function(e){var r=e.split(":"),n=r.shift().trim();if(n){var i=r.join(":").trim();t.append(n,i)}})),t)};n.url="responseURL"in a?a.responseURL:n.headers.get("X-Request-URL");var i="response"in a?a.response:a.responseText;setTimeout((function(){r(new g(i,n))}),0)},a.onerror=function(){setTimeout((function(){o(new TypeError("Network request failed"))}),0)},a.ontimeout=function(){setTimeout((function(){o(new TypeError("Network request failed"))}),0)},a.onabort=function(){setTimeout((function(){o(new O("Aborted","AbortError"))}),0)},a.open(s.method,function(e){try{return""===e&&n.location.href?n.location.href:e}catch(t){return e}}(s.url),!0),"include"===s.credentials?a.withCredentials=!0:"omit"===s.credentials&&(a.withCredentials=!1),"responseType"in a&&(i.blob?a.responseType="blob":i.arrayBuffer&&s.headers.get("Content-Type")&&-1!==s.headers.get("Content-Type").indexOf("application/octet-stream")&&(a.responseType="arraybuffer")),!t||"object"!=typeof t.headers||t.headers instanceof l?s.headers.forEach((function(e,t){a.setRequestHeader(t,e)})):Object.getOwnPropertyNames(t.headers).forEach((function(e){a.setRequestHeader(e,u(t.headers[e]))})),s.signal&&(s.signal.addEventListener("abort",c),a.onreadystatechange=function(){4===a.readyState&&s.signal.removeEventListener("abort",c)}),a.send(void 0===s._bodyInit?null:s._bodyInit)}))}E.polyfill=!0,n.fetch||(n.fetch=E,n.Headers=l,n.Request=v,n.Response=g)}},t={};function r(n){var i=t[n];if(void 0!==i)return i.exports;var o=t[n]={id:n,exports:{}};return e[n](o,o.exports,r),o.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nc=void 0,r(147),r(599),r(989)})();
\ No newline at end of file
diff --git a/docs/forms.md b/docs/forms.md
new file mode 100644
index 0000000..c2ea77a
--- /dev/null
+++ b/docs/forms.md
@@ -0,0 +1,127 @@
+## Forms
+
+Create dynamic forms based on built-in subscriber attributes such as name, email, phone or other custom properties unique to your business.
+Then let Hellotext handle building the form, collecting, validating and authenticating the data users submit.
+
+For more information on how to create a form from the dashboard, view this [guide](https://help.hellotext.com/forms).
+
+### Collection Phase
+
+After initializing the `Hellotext` class, it attaches a `load` event listener and once the page is loaded,
+it looks for any HTML element that is on the page that has a `data-hello-form` attribute.
+
+You can access the forms object to also trigger the form collection phase manually.
+This is useful if you have a Single Page Application(SPA) and cannot hardcode the `data-hello-form` element on the rendered page.
+
+To manually collect forms, do the following.
+
+```javascript
+Hellotext.initialize('HELLOTEXT_BUSINESS_ID')
+Hellotext.forms.collect()
+```
+
+Once loaded, you can access the `FormCollection` object by calling `Hellotext.forms`.
+
+Make sure you have initialized with `Hellotext.initialize` otherwise an error is reported.
+
+Form collection finishes once Hellotext has fetched the data for the form elements present on the page from the Hellotext API.
+Afterwards, it dispatches a `forms:collected` event that you can subscribe to.
+
+```javascript
+Hellotext.on('forms:collected', (forms) => {
+ console.log(forms) // Instance of FormCollection
+})
+```
+
+The `FormCollection` class is a wrapper around the forms, which providers other useful methods.
+
+- `getById(id: string): Form` - Get a form by it's id
+- `getByIndex(index: number): Form` - Get a form by it's index
+- `includes(id: string): boolean` - Check if a form is included in the collection
+- `excludes(id: string): boolean` - Check if a form is not included in the collection
+- `length` - Get the number of forms in the collection
+- `forEach`, `map` are also supported.
+
+### Mounting forms
+
+After the collection phase, form elements would be available to be mounted. Hellotext does not automatically mount form elements,
+you have total control on when and where to mount the form elements. To mount a form object, you call the `mount` method on the form object.
+
+```javascript
+Hellotext.on('forms:collected', (forms) => {
+ forms.getByIndex(0).mount()
+})
+```
+
+Mounting a form creates the form and it's components that are associated to it, and attaches it to the DOM.
+Hellotext looks for a `form` element with the `data-hello-form` attribute and mounts the form inside it.
+If this condition is not met, Hellotext creates the form manually and appends it to the body of the document.
+We recommend to make the criteria met to ensure the form is loaded into an expected place in your page.
+
+### Validation
+
+Hellotext automatically validates the form inputs based on how they were configured on the dashboard
+using browser's native [checkValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/checkValidity).
+Once the user tries to submit the form and there are missing required fields,
+the submission is halted and we display default browser's error message using [HTMLObjectElement.validationMessage](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage) property.
+
+### Authentication
+
+Hellotext protects you from bot submissions and protects your customers from identity theft and impersonation.
+When a subscriber fills the form, Hellotext sends a One Time Password (OTP) code to the subscriber. If they have an email,
+an email is sent to them, otherwise an SMS is sent to their phone number.
+Until a valid OTP has been entered, data will not show up on the dashboard and will not contribute to attribution marketing.
+
+### Form Completion
+
+Once the user enters the OTP they received. The form is considered to be complete and will be sent to the Hellotext API to create(or update) a profile from the submission information.
+The library also dispatches a `form:completed` event that you can subscribe to. In addition, a Session object is set and stored on the browser's cookies.
+Additionally, the `Hellotext.session` is also set if no session was present already, you can listen for the session events by subscribing to `session-set` event.
+
+```javascript
+Hellotext.on('form:completed', (form) => {
+ console.log(form) // An object from FormData
+})
+
+{
+ id: "xxxxx", // Id of the form that has been completed
+ first_name: "Billy",
+ last_name: "Butcher",
+ email: "theboys@hellotext.com",
+ phone: "+1234567890",
+ property_by_id[xxxxx]: "value"
+}
+```
+
+The data in the from will differ based on the inputs you have configured on the dashboard.
+
+### Understanding form's layout
+
+Hellotext assumes a fixed layout for forms, which are in order of Header, Inputs, Button and Notice.
+
+But you can override this layout if you want. Overriding a form's layout can be achieved
+by moving the placement of the form's components. For example, if you want to display the Button component after the Footer, here's how you can do that
+
+```html
+
+```
+
+Hellotext would simply load the contents inside the respective elements without creating the default layout.
+If these elements were not defined, Hellotext would render the button then the notice component.
+
+### Customizing the Form's styles
+
+Generated form elements have minimum styles to make them display correctly. No colors, borders or padding are applied.
+You can style the form elements to match your brand guidelines. Hellotext.js ships with a few lines of CSS to apply layout on the components.
+See `styles/index.css` for the default styles applied to the form elements.
+
+### White Labels
+
+As a subscriber to Hellotext, if your package does not support white labels, a `powered by Hellotext` logo is displayed at the bottom-right of the form.
+You are free to move the position of this element if you want, but it should be visible to your subscribers.
diff --git a/docs/tracking.md b/docs/tracking.md
new file mode 100644
index 0000000..dd0c9a3
--- /dev/null
+++ b/docs/tracking.md
@@ -0,0 +1,155 @@
+## Tracking Events
+
+Track subscriber events as they happen on your website and let Hellotext report them back to your business.
+
+Tracking events is straightforward and perhaps the simplest example is tracking a page view:
+
+```javascript
+Hellotext.track('page.viewed')
+```
+
+In the example above only the name of the action is required.
+
+### Handling Responses
+
+The `track` method returns a Promise that can be `await`ed using the async/await syntax. Or using `.then` on the returned Promise.
+
+```javascript
+const response = await Hellotext.track('page.viewed')
+```
+
+The return of the `Hellotext.track` method is an instance of a `Response` object that ships with the package. You can check the status of the response via methods, like:
+
+```javascript
+if (response.failed) {
+ console.log('failed because', response.data)
+}
+
+if (response.succeeded) {
+ console.log('success')
+ console.log(response.data) // { status: "received" }
+}
+```
+
+### Parameters
+
+The parameters passed to the action must be a valid set of parameters as described in
+[Tracking Actions](https://www.hellotext.com/api#tracking).
+
+#### URL Parameter
+
+The library takes care of handling the `url` parameter with the current URL automatically and is not required to specify it explicitly.
+If you want to provide another url, you can pass a `url` key in the params object when tracking an event.
+
+```javascript
+Hellotext.track('page.viewed', {
+ url: 'www.example.org',
+})
+```
+
+### Errors
+
+Failing to provide valid set of parameters will result in an error object being returned, describing the parameters that did not satisfy the rules.
+
+```javascript
+const response = await Hellotext.track('app.installed', { app_parameters: { name: 'My App' } })
+
+console.log(response.data)
+```
+
+yields
+
+```javascript
+{
+ errors: [
+ {
+ type: 'parameter_not_unique',
+ parameter: 'name',
+ description:
+ 'The value must be unique and it is already present in another object of the same type.',
+ },
+ ]
+}
+```
+
+For a complete list of errors types. See [Error Types](https://www.hellotext.com/api#errors)
+
+### Associated objects
+
+Generally, most actions also require an associated object. These can be of type [`app`](https://www.hellotext.com/api#apps), [`coupon`](https://www.hellotext.com/api#coupons), [`form`](https://www.hellotext.com/api#forms), [`order`](https://www.hellotext.com/api#orders), [`product`](https://www.hellotext.com/api#products) and [`refund`](https://www.hellotext.com/api#refunds).
+Aside from [Custom Actions](https://www.hellotext.com/api#create_an_action), which don't require the trackable to be present.
+
+You can create the associated object directly by defining its parameters in a hash:
+
+```javascript
+Hellotext.track('order.placed', {
+ amount: 395.0,
+ currency: 'USD',
+ order_parameters: {
+ amount: '395.00',
+ reference: '654321',
+ },
+})
+```
+
+If you want to reuse existing objects, you must pass the identifier of an existing associated object. For example, to track a product purchase the identifier of a previously created product object as the `product`.
+For more information about identifiers, view the [Tracking API](https://www.hellotext.com/api#tracking)
+
+```javascript
+Hellotext.track('product.purchased', {
+ amount: 395.0,
+ currency: 'USD',
+ product: 'erA2RAXE',
+})
+```
+
+## List of actions
+
+The following is a complete list of built-in actions and their required associated objects.
+
+| Action | Description | Required Parameter |
+| --------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------- |
+| **app.installed** | An app was installed. | `app` or [app_parameters](https://www.hellotext.com/api#app) |
+| **app.removed** | An app was removed. | `app` or [app_parameters](https://www.hellotext.com/api#app) |
+| **app.spent** | A customer spent on an app. | `app` or [app_parameters](https://www.hellotext.com/api#app) |
+| **cart.abandoned** | A cart was abandoned. | `product` or [product_parameters](https://www.hellotext.com/api#products) |
+| **cart.added** | Added an item to the cart. | `product` or [product_parameters](https://www.hellotext.com/api#products) |
+| **cart.removed** | Removed an item from the cart. | `product` or [product_parameters](https://www.hellotext.com/api#products) |
+| **coupon.redeemed** | A coupon was redeem by a customer. | `coupon` or [coupon_parameters](https://www.hellotext.com/api#coupons) |
+| **form.completed** | A form was completed by the customer. | `form` or [form_parameters](https://www.hellotext.com/api#forms) |
+| **order.placed** | Order has been placed. | `order` or [order_parameters](https://www.hellotext.com/api#orders) |
+| **order.confirmed** | Order has been confirmed by you. | `order` or [order_parameters](https://www.hellotext.com/api#orders) |
+| **order.cancelled** | Order has been cancelled either by you or your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders) |
+| **order.shipped** | Order has been shipped to your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders) |
+| **order.delivered** | Order has been delivered to your customer. | `order` or [order_parameters](https://www.hellotext.com/api#orders) |
+| **page.viewed** | A page was viewed by a customer. | `url` |
+| **product.purchased** | A product has been purchased. | `product` or [product_parameters](https://www.hellotext.com/api#products) |
+| **product.viewed** | A product page has been viewed. | `product` or [product_parameters](https://www.hellotext.com/api#products) |
+| **refund.requested** | A customer requested a refund. | `refund` or [refund_parameters](https://www.hellotext.com/api#refunds) |
+| **refund.received** | A refund was issued by you to your customer. | `refund` or [refund_parameters](https://www.hellotext.com/api#refunds) |
+
+You can also create your **[own defined actions](https://www.hellotext.com/api#actions)**.
+
+## Additional Properties
+
+You can include additional attributes to the tracked event, additional properties must be included inside the `metadata` object:
+
+```javascript
+Hellotext.track('product.purchased', {
+ amount: 0.2,
+ currency: 'USD',
+ metadata: {
+ myProperty: 'custom',
+ },
+ tracked_at: 1665684173,
+})
+```
+
+### List of additional attributes
+
+| Property | Description | Type | Default |
+| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- |
+| **amount** | Monetary amount that represents the revenue associated to this tracked event. | float | `0` |
+| **currency** | Currency for the `amount` given in ISO 4217 format. | currency | `USD` |
+| **metadata** | Set of key-value pairs that you can attach to an event. This can be useful for storing additional information about the object in a structured format. | hash | `{}` |
+| **tracked_at** | Original date when the event happened. This is useful if you want to record an event that happened in the past. If no value is provided its value will be the same from `created_at`. | epoch | `null` |
diff --git a/lib/api.js b/lib/api.js
new file mode 100644
index 0000000..3c743d7
--- /dev/null
+++ b/lib/api.js
@@ -0,0 +1,73 @@
+'use strict'
+
+Object.defineProperty(exports, '__esModule', {
+ value: true,
+})
+exports.default = void 0
+var _sessions = _interopRequireDefault(require('./api/sessions'))
+var _businesses = _interopRequireDefault(require('./api/businesses'))
+var _events = _interopRequireDefault(require('./api/events'))
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : { default: obj }
+}
+function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError('Cannot call a class as a function')
+ }
+}
+function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i]
+ descriptor.enumerable = descriptor.enumerable || false
+ descriptor.configurable = true
+ if ('value' in descriptor) descriptor.writable = true
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor)
+ }
+}
+function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps)
+ if (staticProps) _defineProperties(Constructor, staticProps)
+ Object.defineProperty(Constructor, 'prototype', { writable: false })
+ return Constructor
+}
+function _toPropertyKey(arg) {
+ var key = _toPrimitive(arg, 'string')
+ return typeof key === 'symbol' ? key : String(key)
+}
+function _toPrimitive(input, hint) {
+ if (typeof input !== 'object' || input === null) return input
+ var prim = input[Symbol.toPrimitive]
+ if (prim !== undefined) {
+ var res = prim.call(input, hint || 'default')
+ if (typeof res !== 'object') return res
+ throw new TypeError('@@toPrimitive must return a primitive value.')
+ }
+ return (hint === 'string' ? String : Number)(input)
+}
+var API = /*#__PURE__*/ (function () {
+ function API() {
+ _classCallCheck(this, API)
+ }
+ _createClass(API, null, [
+ {
+ key: 'sessions',
+ value: function sessions(businessId) {
+ return new _sessions.default(businessId)
+ },
+ },
+ {
+ key: 'businesses',
+ get: function get() {
+ return _businesses.default
+ },
+ },
+ {
+ key: 'events',
+ get: function get() {
+ return _events.default
+ },
+ },
+ ])
+ return API
+})()
+exports.default = API
diff --git a/lib/api/businesses.js b/lib/api/businesses.js
new file mode 100644
index 0000000..537e074
--- /dev/null
+++ b/lib/api/businesses.js
@@ -0,0 +1,45 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+var _core = require("../core");
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var _default = /*#__PURE__*/function () {
+ function _default() {
+ _classCallCheck(this, _default);
+ }
+ _createClass(_default, null, [{
+ key: "endpoint",
+ get: function get() {
+ return _core.Configuration.endpoint('public/businesses');
+ }
+ }, {
+ key: "get",
+ value: function () {
+ var _get = _asyncToGenerator(function* (id) {
+ return fetch("".concat(this.endpoint, "/").concat(id), {
+ method: 'GET',
+ headers: {
+ Authorization: "Bearer ".concat(id),
+ Accept: 'application.json',
+ 'Content-Type': 'application/json'
+ }
+ });
+ });
+ function get(_x) {
+ return _get.apply(this, arguments);
+ }
+ return get;
+ }()
+ }]);
+ return _default;
+}();
+exports.default = _default;
\ No newline at end of file
diff --git a/lib/api/events.js b/lib/api/events.js
new file mode 100644
index 0000000..dfc46db
--- /dev/null
+++ b/lib/api/events.js
@@ -0,0 +1,54 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+var _core = require("../core");
+var _models = require("../models");
+var _response = require("./response");
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var EventsAPI = /*#__PURE__*/function () {
+ function EventsAPI() {
+ _classCallCheck(this, EventsAPI);
+ }
+ _createClass(EventsAPI, null, [{
+ key: "endpoint",
+ get: function get() {
+ return _core.Configuration.endpoint('track/events');
+ }
+ }, {
+ key: "create",
+ value: function () {
+ var _create = _asyncToGenerator(function* (_ref) {
+ var {
+ headers,
+ body
+ } = _ref;
+ if (_models.Query.inPreviewMode) {
+ return new _response.Response(true, {
+ received: true
+ });
+ }
+ var response = yield fetch(this.endpoint, {
+ method: 'POST',
+ headers,
+ body: JSON.stringify(body)
+ });
+ return new _response.Response(response.status === 200, yield response.json());
+ });
+ function create(_x) {
+ return _create.apply(this, arguments);
+ }
+ return create;
+ }()
+ }]);
+ return EventsAPI;
+}();
+exports.default = EventsAPI;
\ No newline at end of file
diff --git a/lib/api/forms.js b/lib/api/forms.js
new file mode 100644
index 0000000..aa026d1
--- /dev/null
+++ b/lib/api/forms.js
@@ -0,0 +1,65 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+var _hellotext = _interopRequireDefault(require("../hellotext"));
+var _core = require("../core");
+var _response = require("./response");
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
+function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
+function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var FormsAPI = /*#__PURE__*/function () {
+ function FormsAPI() {
+ _classCallCheck(this, FormsAPI);
+ }
+ _createClass(FormsAPI, null, [{
+ key: "endpoint",
+ get: function get() {
+ return _core.Configuration.endpoint('public/forms');
+ }
+ }, {
+ key: "get",
+ value: function () {
+ var _get = _asyncToGenerator(function* (id) {
+ return fetch("".concat(this.endpoint, "/").concat(id), {
+ method: 'GET',
+ headers: _hellotext.default.headers
+ });
+ });
+ function get(_x) {
+ return _get.apply(this, arguments);
+ }
+ return get;
+ }()
+ }, {
+ key: "submit",
+ value: function () {
+ var _submit = _asyncToGenerator(function* (id, data) {
+ var response = yield fetch("".concat(this.endpoint, "/").concat(id, "/submissions"), {
+ method: 'POST',
+ headers: _hellotext.default.headers,
+ body: JSON.stringify(_objectSpread({
+ session: _hellotext.default.session
+ }, data))
+ });
+ return new _response.Response(response.ok, response);
+ });
+ function submit(_x2, _x3) {
+ return _submit.apply(this, arguments);
+ }
+ return submit;
+ }()
+ }]);
+ return FormsAPI;
+}();
+exports.default = FormsAPI;
\ No newline at end of file
diff --git a/lib/api/index.js b/lib/api/index.js
new file mode 100644
index 0000000..4c9891f
--- /dev/null
+++ b/lib/api/index.js
@@ -0,0 +1,51 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+Object.defineProperty(exports, "Response", {
+ enumerable: true,
+ get: function get() {
+ return _response.Response;
+ }
+});
+exports.default = void 0;
+var _sessions = _interopRequireDefault(require("./sessions"));
+var _businesses = _interopRequireDefault(require("./businesses"));
+var _events = _interopRequireDefault(require("./events"));
+var _forms = _interopRequireDefault(require("./forms"));
+var _response = require("./response");
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var API = /*#__PURE__*/function () {
+ function API() {
+ _classCallCheck(this, API);
+ }
+ _createClass(API, null, [{
+ key: "sessions",
+ value: function sessions(businessId) {
+ return new _sessions.default(businessId);
+ }
+ }, {
+ key: "businesses",
+ get: function get() {
+ return _businesses.default;
+ }
+ }, {
+ key: "events",
+ get: function get() {
+ return _events.default;
+ }
+ }, {
+ key: "forms",
+ get: function get() {
+ return _forms.default;
+ }
+ }]);
+ return API;
+}();
+exports.default = API;
\ No newline at end of file
diff --git a/lib/api/response.js b/lib/api/response.js
new file mode 100644
index 0000000..c54d517
--- /dev/null
+++ b/lib/api/response.js
@@ -0,0 +1,57 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.Response = void 0;
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
+var id = 0;
+function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
+var _success = /*#__PURE__*/_classPrivateFieldLooseKey("success");
+var Response = /*#__PURE__*/function () {
+ function Response(success, response) {
+ _classCallCheck(this, Response);
+ Object.defineProperty(this, _success, {
+ writable: true,
+ value: void 0
+ });
+ this.response = response;
+ _classPrivateFieldLooseBase(this, _success)[_success] = success;
+ }
+ _createClass(Response, [{
+ key: "data",
+ get: function get() {
+ return this.response;
+ }
+ }, {
+ key: "json",
+ value: function () {
+ var _json = _asyncToGenerator(function* () {
+ return yield this.response.json();
+ });
+ function json() {
+ return _json.apply(this, arguments);
+ }
+ return json;
+ }()
+ }, {
+ key: "failed",
+ get: function get() {
+ return _classPrivateFieldLooseBase(this, _success)[_success] === false;
+ }
+ }, {
+ key: "succeeded",
+ get: function get() {
+ return _classPrivateFieldLooseBase(this, _success)[_success] === true;
+ }
+ }]);
+ return Response;
+}();
+exports.Response = Response;
\ No newline at end of file
diff --git a/lib/api/sessions.js b/lib/api/sessions.js
new file mode 100644
index 0000000..70b22aa
--- /dev/null
+++ b/lib/api/sessions.js
@@ -0,0 +1,46 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+var _core = require("../core");
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var SessionsAPI = /*#__PURE__*/function () {
+ function SessionsAPI(businessId) {
+ _classCallCheck(this, SessionsAPI);
+ this.businessId = businessId;
+ }
+ _createClass(SessionsAPI, [{
+ key: "create",
+ value: function () {
+ var _create = _asyncToGenerator(function* () {
+ var response = yield fetch(SessionsAPI.endpoint, {
+ method: 'POST',
+ headers: {
+ Authorization: "Bearer ".concat(this.businessId),
+ Accept: 'application/json'
+ }
+ });
+ return response.json();
+ });
+ function create() {
+ return _create.apply(this, arguments);
+ }
+ return create;
+ }()
+ }], [{
+ key: "endpoint",
+ get: function get() {
+ return _core.Configuration.endpoint('track/sessions');
+ }
+ }]);
+ return SessionsAPI;
+}();
+exports.default = SessionsAPI;
\ No newline at end of file
diff --git a/lib/api/submissions.js b/lib/api/submissions.js
new file mode 100644
index 0000000..00976ee
--- /dev/null
+++ b/lib/api/submissions.js
@@ -0,0 +1,61 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+var _hellotext = _interopRequireDefault(require("../hellotext"));
+var _core = require("../core");
+var _response = require("./response");
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var SubmissionsAPI = /*#__PURE__*/function () {
+ function SubmissionsAPI() {
+ _classCallCheck(this, SubmissionsAPI);
+ }
+ _createClass(SubmissionsAPI, null, [{
+ key: "endpoint",
+ get: function get() {
+ return _core.Configuration.endpoint('public/submissions');
+ }
+ }, {
+ key: "resendOTP",
+ value: function () {
+ var _resendOTP = _asyncToGenerator(function* (id) {
+ var response = yield fetch("".concat(this.endpoint, "/").concat(id, "/otps"), {
+ method: 'POST',
+ headers: _hellotext.default.headers
+ });
+ return new _response.Response(response.ok, response);
+ });
+ function resendOTP(_x) {
+ return _resendOTP.apply(this, arguments);
+ }
+ return resendOTP;
+ }()
+ }, {
+ key: "verifyOTP",
+ value: function () {
+ var _verifyOTP = _asyncToGenerator(function* (id, otp) {
+ var response = yield fetch("".concat(this.endpoint, "/").concat(id, "/otps/").concat(otp, "/verify"), {
+ method: 'POST',
+ headers: _hellotext.default.headers
+ });
+ return new _response.Response(response.ok, response);
+ });
+ function verifyOTP(_x2, _x3) {
+ return _verifyOTP.apply(this, arguments);
+ }
+ return verifyOTP;
+ }()
+ }]);
+ return SubmissionsAPI;
+}();
+var _default = SubmissionsAPI;
+exports.default = _default;
\ No newline at end of file
diff --git a/lib/builders/inputBuilder.js b/lib/builders/inputBuilder.js
new file mode 100644
index 0000000..6e7bade
--- /dev/null
+++ b/lib/builders/inputBuilder.js
@@ -0,0 +1,97 @@
+'use strict'
+
+Object.defineProperty(exports, '__esModule', {
+ value: true,
+})
+exports.InputBuilder = void 0
+var _hellotext = _interopRequireDefault(require('../hellotext'))
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : { default: obj }
+}
+function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError('Cannot call a class as a function')
+ }
+}
+function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i]
+ descriptor.enumerable = descriptor.enumerable || false
+ descriptor.configurable = true
+ if ('value' in descriptor) descriptor.writable = true
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor)
+ }
+}
+function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps)
+ if (staticProps) _defineProperties(Constructor, staticProps)
+ Object.defineProperty(Constructor, 'prototype', { writable: false })
+ return Constructor
+}
+function _toPropertyKey(arg) {
+ var key = _toPrimitive(arg, 'string')
+ return typeof key === 'symbol' ? key : String(key)
+}
+function _toPrimitive(input, hint) {
+ if (typeof input !== 'object' || input === null) return input
+ var prim = input[Symbol.toPrimitive]
+ if (prim !== undefined) {
+ var res = prim.call(input, hint || 'default')
+ if (typeof res !== 'object') return res
+ throw new TypeError('@@toPrimitive must return a primitive value.')
+ }
+ return (hint === 'string' ? String : Number)(input)
+}
+var InputBuilder = /*#__PURE__*/ (function () {
+ function InputBuilder() {
+ _classCallCheck(this, InputBuilder)
+ }
+ _createClass(InputBuilder, null, [
+ {
+ key: 'build',
+ value: function build(data) {
+ var article = document.createElement('article')
+ var label = document.createElement('label')
+ var input = document.createElement('input')
+ label.innerText = data.label
+ input.type = data.type
+ input.required = data.required
+ input.placeholder = data.placeholder
+ if (['first_name', 'last_name'].includes(data.kind)) {
+ input.type = 'text'
+ input.id = input.name = data.kind
+ label.setAttribute('for', data.kind)
+ } else {
+ input.type = data.type
+ if (data.type === 'email') {
+ input.id = input.name = 'email'
+ label.setAttribute('for', 'email')
+ } else if (input.type === 'tel') {
+ input.id = input.name = 'phone'
+ label.setAttribute('for', 'phone')
+ input.value = '+'.concat(_hellotext.default.business.country.prefix)
+ input.setAttribute(
+ 'data-default-value',
+ '+'.concat(_hellotext.default.business.country.prefix),
+ )
+ } else {
+ input.name = input.id = 'property_by_id['.concat(data.property, ']')
+ label.setAttribute('for', 'property_by_id['.concat(data.property, ']'))
+ }
+ }
+ var main = document.createElement('main')
+ main.appendChild(label)
+ main.appendChild(input)
+ article.appendChild(main)
+ article.setAttribute('data-hellotext--form-target', 'inputContainer')
+ input.setAttribute('data-hellotext--form-target', 'input')
+ var errorContainer = document.createElement('div')
+ errorContainer.setAttribute('data-error-container', '')
+ article.appendChild(errorContainer)
+ return article
+ },
+ },
+ ])
+ return InputBuilder
+})()
+exports.InputBuilder = InputBuilder
diff --git a/lib/builders/input_builder.js b/lib/builders/input_builder.js
new file mode 100644
index 0000000..d103561
--- /dev/null
+++ b/lib/builders/input_builder.js
@@ -0,0 +1,61 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.InputBuilder = void 0;
+var _hellotext = _interopRequireDefault(require("../hellotext"));
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+var InputBuilder = /*#__PURE__*/function () {
+ function InputBuilder() {
+ _classCallCheck(this, InputBuilder);
+ }
+ _createClass(InputBuilder, null, [{
+ key: "build",
+ value: function build(data) {
+ var article = document.createElement('article');
+ var label = document.createElement('label');
+ var input = document.createElement('input');
+ label.innerText = data.label;
+ input.type = data.type;
+ input.required = data.required;
+ input.placeholder = data.placeholder;
+ if (['first_name', 'last_name'].includes(data.kind)) {
+ input.type = 'text';
+ input.id = input.name = data.kind;
+ label.setAttribute('for', data.kind);
+ } else {
+ input.type = data.type;
+ if (data.type === 'email') {
+ input.id = input.name = 'email';
+ label.setAttribute('for', 'email');
+ } else if (input.type === 'tel') {
+ input.id = input.name = 'phone';
+ label.setAttribute('for', 'phone');
+ input.value = "+".concat(_hellotext.default.business.country.prefix);
+ input.setAttribute('data-default-value', "+".concat(_hellotext.default.business.country.prefix));
+ } else {
+ input.name = input.id = "property_by_id[".concat(data.property, "]");
+ label.setAttribute('for', "property_by_id[".concat(data.property, "]"));
+ }
+ }
+ var main = document.createElement('main');
+ main.appendChild(label);
+ main.appendChild(input);
+ article.appendChild(main);
+ article.setAttribute('data-hellotext--form-target', 'inputContainer');
+ input.setAttribute('data-hellotext--form-target', 'input');
+ var errorContainer = document.createElement('div');
+ errorContainer.setAttribute('data-error-container', '');
+ article.appendChild(errorContainer);
+ return article;
+ }
+ }]);
+ return InputBuilder;
+}();
+exports.InputBuilder = InputBuilder;
\ No newline at end of file
diff --git a/lib/builders/logo_builder.js b/lib/builders/logo_builder.js
new file mode 100644
index 0000000..85c4619
--- /dev/null
+++ b/lib/builders/logo_builder.js
@@ -0,0 +1,38 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.LogoBuilder = void 0;
+var _hellotext = _interopRequireDefault(require("../hellotext"));
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
+function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
+function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
+function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
+var id = 0;
+function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
+var _template = /*#__PURE__*/_classPrivateFieldLooseKey("template");
+var LogoBuilder = /*#__PURE__*/function () {
+ function LogoBuilder() {
+ _classCallCheck(this, LogoBuilder);
+ }
+ _createClass(LogoBuilder, null, [{
+ key: "build",
+ value: function build() {
+ var container = document.createElement('div');
+ container.innerHTML = _classPrivateFieldLooseBase(this, _template)[_template]();
+ return container.firstElementChild;
+ }
+ }]);
+ return LogoBuilder;
+}();
+exports.LogoBuilder = LogoBuilder;
+function _template2() {
+ return "\n