diff --git a/package.json b/package.json
index 44c11d5..9ef18e6 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,8 @@
"url": "git://github.com/bigcommerce/stencil-utils.git"
},
"dependencies": {
+ "@types/eventemitter2": "^2.2.1",
+ "@types/jquery": "^3.3.29",
"eventemitter2": "^0.4.14",
"jquery": "^3.3.1",
"query-string": "^5.0.0"
diff --git a/src/api.d.ts b/src/api.d.ts
new file mode 100644
index 0000000..abe9c3a
--- /dev/null
+++ b/src/api.d.ts
@@ -0,0 +1,5 @@
+export * from './typings/api';
+import { Api } from './typings/api';
+
+declare const api: Api;
+export default api;
diff --git a/src/hooks.d.ts b/src/hooks.d.ts
new file mode 100644
index 0000000..d70529a
--- /dev/null
+++ b/src/hooks.d.ts
@@ -0,0 +1,5 @@
+export * from './typings/hooks';
+import { Hooks } from './typings/hooks';
+
+declare const hooks: Hooks;
+export default hooks;
diff --git a/src/main.d.ts b/src/main.d.ts
new file mode 100644
index 0000000..3f80fbc
--- /dev/null
+++ b/src/main.d.ts
@@ -0,0 +1 @@
+export * from './typings';
diff --git a/src/tools.d.ts b/src/tools.d.ts
new file mode 100644
index 0000000..41cf0c3
--- /dev/null
+++ b/src/tools.d.ts
@@ -0,0 +1,6 @@
+export * from './typings/tools';
+import { Tools } from './typings/tools';
+
+declare const tools: Tools;
+
+export default tools;
diff --git a/src/typings/api.d.ts b/src/typings/api.d.ts
new file mode 100644
index 0000000..3366947
--- /dev/null
+++ b/src/typings/api.d.ts
@@ -0,0 +1,426 @@
+///
+
+export declare namespace Api {
+ type StringObject = { [key: string]: string; };
+ type GenericObject = { [key: string]: any; };
+
+ type Template = string|string[]|StringObject;
+ type ValidMethods = 'GET'|'POST'|'PUT'|'DELETE';
+ type RequestTemplate = T extends keyof O ? O[T] : {} extends O ? string : never;
+ type TemplateResponse = T extends string[]|StringObject ? GenericObject : string;
+ type TemplateRequestCallback = (error: string, response: TemplateResponse) => void|any;
+ type JsonRequestCallback = (error: string, response: T) => void|any;
+ type QuantityRequestCallback = (error: string, response: number) => void|any;
+ type GetShippingQuoteRequestCallback = (error: string, response: GetShippingQuoteResponse) => void|any;
+
+ interface RequestOptions {
+ baseUrl?: string;
+ formData?: FormData;
+ params?: any;
+ config?: any;
+ template?: Template;
+ includeOptions?: boolean;
+ }
+
+ interface Cart {
+ baseAmount: number;
+ cartAmount: number;
+ coupons: any[];
+ createdTime: string;
+ currency: Currency;
+ customerId: number;
+ discountAmount: number;
+ discounts: Discount[];
+ email: string;
+ id: string;
+ isTaxIncluded: boolean;
+ lineItems: {
+ customItems: CustomProduct[];
+ digitalItems: DigitalProduct[];
+ giftCertificates: GiftCertificateProduct[];
+ physicalItems: PhysicalProduct[]
+ }
+ }
+
+ interface Currency {
+ code: string;
+ decimalPlaces: number;
+ name: string;
+ symbol: string;
+ }
+
+ interface Discount {
+ id: number;
+ discountedAmount: number;
+ }
+
+ interface BaseProduct {
+ id: string;
+ parentId: string;
+ variantId: string;
+ productId: number;
+ sku: string;
+ name: string;
+ url: string;
+ quantity: number;
+ isTaxable: boolean;
+ imageUrl: string;
+ discounts: Discount[];
+ discountAmount: number;
+ couponAmount: number;
+ listPrice: number;
+ salePrice: number;
+ extendedListPrice: number;
+ extendedSalePrice: number;
+ Options: ProductOption[];
+ brand: string;
+ }
+
+ interface PhysicalProduct extends BaseProduct {}
+
+ interface DigitalProduct extends BaseProduct {}
+
+ interface CustomProduct {
+ id: string;
+ sku: string;
+ name: string;
+ quantity: number;
+ listPrice: number;
+ extendedListPrice: number;
+ }
+
+ interface GiftCertificateProduct {
+ id: string;
+ name: string;
+ theme: string;
+ amount: number;
+ isTaxable: boolean;
+ sender: {
+ name: string;
+ email: string;
+ };
+ recipient: {
+ name: string;
+ email: string;
+ };
+ message: string;
+ }
+
+ interface ProductOption {
+ name: string;
+ nameId: number;
+ value: string;
+ valueId: number;
+ }
+
+ interface AddedCartItem {
+ hash: string;
+ id: string;
+ product_id: number;
+ thumbnail: string;
+ url: string;
+ }
+
+ interface CartUpdateItem {
+ id: string;
+ quantity: number;
+ }
+
+ interface ShippingMethod {
+ id: number;
+ type: string;
+ cost: {
+ formatted: string;
+ value: number;
+ };
+ provider_name: string;
+ }
+
+ interface UpsShippingMethod extends ShippingMethod {
+ logo_path?: string;
+ description: string;
+ }
+
+ interface GetShippingQuoteResponse {
+ content: TemplateResponse;
+ data: {
+ quotes: {
+ shipping_methods: ShippingMethod[];
+ ups_shipping_methods: UpsShippingMethod[];
+ };
+ };
+ }
+
+ interface ApiStatusResponse {
+ errors?: string[];
+ status: string;
+ }
+
+ class BaseApi {
+ constructor(version: string);
+ remoteVersion: string;
+ remoteBaseEndpoint: string;
+
+ makeRequest>(url: string, method: ValidMethods, options: RequestOptions & O, remote: boolean, callback: TemplateRequestCallback): void;
+ remoteRequest>(endpoint: string, method: ValidMethods, options: RequestOptions & O, callback: TemplateRequestCallback): void;
+ }
+
+ class CountryApi extends BaseApi {
+ endpoint: string;
+
+ /**
+ *
+ * Get country data by id wrapper
+ *
+ * @param {Number} id
+ * @param {Function} callback
+ */
+ getById(id: number, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get country data by country name
+ * @param {String} name
+ * @param callback
+ */
+ getByName(name: string, callback: TemplateRequestCallback): void;
+ }
+
+ class ProductAttributesApi extends BaseApi {
+ endpoint: string;
+ inCartEndpoint: string;
+
+ /**
+ * Get product attributes from selected options
+ *
+ * @param {Number} productId
+ * @param {Object} params
+ * @param callback
+ */
+ optionChange(productId: number, params: any, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get product attributes from selected options
+ *
+ * @param {Number} productId
+ * @param {Object} params
+ * @param {String|Array|Object}
+ * @param callback
+ */
+ optionChange(productId: number, params: any, template: Template & T, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get product attributes from selected options while editing in cart
+ * @param {Number} itemId
+ * @param {Object} params
+ * @param callback
+ */
+ configureInCart>(itemId: number, params: RequestOptions & O, callback: TemplateRequestCallback): void;
+ }
+
+ class ProductApi extends BaseApi {
+ endpoint: string;
+
+ /**
+ * Get product by ID
+ *
+ * @param {Number} productId
+ * @param {Function} callback
+ */
+ getById(productId: number, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get product by ID
+ *
+ * @param {Number} productId
+ * @param {Object} params
+ * @param {Function} callback
+ */
+ getById>(productId: number, params: RequestOptions & O, callback: TemplateRequestCallback): void;
+ }
+
+ class SearchApi extends BaseApi {
+ endpoint: string;
+
+ /**
+ * Get search results
+ * @param {String} query
+ * @param {Function} callback
+ */
+ search(query: string, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get search results
+ * @param {String} query
+ * @param {Object} params
+ * @param {Function} callback
+ */
+ search>(query: string, params: RequestOptions & O, callback: TemplateRequestCallback): void;
+ }
+
+ class CartApi extends BaseApi {
+ /**
+ * Get the current Cart's details, either with or without Product Option selections.
+ *
+ * @param options
+ * @param {Function} callback
+ */
+ getCart(options: RequestOptions, callback: JsonRequestCallback): void;
+
+ /**
+ * Get a sum of the cart line item quantities
+ *
+ * @param options
+ * @param {Function} callback
+ */
+ getCartQuantity(options: RequestOptions, callback: QuantityRequestCallback): void;
+
+ /**
+ * Add item to cart with options (variants)
+ *
+ * @param {FormData} formData
+ * @param {Function} callback
+ */
+ itemAdd(formData: FormData, callback: JsonRequestCallback<{ data: { cart_item: AddedCartItem; }; }>): void;
+
+ /**
+ * Update cart item quantity
+ *
+ * @param {String} itemId
+ * @param {Number} qty
+ * @param {Function} callback
+ */
+ itemUpdate(itemId: string, qty: number, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Update cart item quantity
+ *
+ * @param {Object} itemId
+ * @param {Function} callback
+ */
+ itemUpdate(itemId: CartUpdateItem[], callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Remove cart items
+ *
+ * Calls the internal update function with quantity: 0
+ *
+ * @param {String} itemId
+ * @param {Function} callback
+ */
+ itemRemove(itemId: string, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Get giftwrapping options
+ * @param {String} itemId
+ * @param {Function} callback
+ */
+ getItemGiftWrappingOptions(itemId: string, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get giftwrapping options
+ * @param {String} itemId
+ * @param {Object} options
+ * @param {Function} callback
+ */
+ getItemGiftWrappingOptions>(itemId: string, options: RequestOptions & O, callback: TemplateRequestCallback): void;
+
+ /**
+ * Submit giftwrapping options
+ *
+ * @param {String} itemId
+ * @param {Function} callback
+ */
+ submitItemGiftWrappingOption(itemId: string, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Submit giftwrapping options
+ *
+ * @param {String} itemId
+ * @param {Object} params
+ * @param {Function} callback
+ */
+ submitItemGiftWrappingOption>(itemId: string, params: RequestOptions & O, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Update cart items
+ *
+ * @param {Array} items
+ * @param {Function} callback
+ */
+ update(items: CartUpdateItem[], callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Get cart content
+ *
+ * @param {Function} callback
+ */
+ getContent(callback: TemplateRequestCallback): void;
+
+ /**
+ * Get cart content
+ *
+ * @param {Object} options
+ * @param {Function} callback
+ */
+ getContent>(options: RequestOptions & O, callback: TemplateRequestCallback): void;
+
+ /**
+ * Get cart shipping quote
+ *
+ * @param {Object} params
+ * @param {Function} callback
+ */
+ getShippingQuotes(params: any, callback: GetShippingQuoteRequestCallback): void;
+
+ /**
+ * Get cart shipping quote
+ *
+ * @param {Object} params
+ * @param {String|Array|Object} renderWith
+ * @param {Function} callback
+ */
+ getShippingQuotes(params: any, renderWith: Template & T, callback: GetShippingQuoteRequestCallback): void;
+
+ /**
+ * Submit shipping quote based on quoteId
+ *
+ * @param {Number} quoteId
+ * @param {Function} callback
+ */
+ submitShippingQuote(quoteId: number, callback: (error: string, response: JsonRequestCallback<{ data: ApiStatusResponse; }>) => void): void;
+
+ /**
+ * Apply a coupon code or gift certificate to the cart
+ *
+ * @param {String} code
+ * @param {Function} callback
+ */
+ applyCode(code: string, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+
+ /**
+ * Apply a coupon code or gift certificate to the cart
+ *
+ * @param {Number} code
+ * @param {Function} callback
+ */
+ applyGiftCertificate(code: string, callback: JsonRequestCallback<{ data: ApiStatusResponse; }>): void;
+ }
+
+ interface Internals {
+ /**
+ * Convenience function to request a page via ajax
+ */
+ getPage>(url: string, options: RequestOptions & O, callback: TemplateRequestCallback): void;
+ }
+}
+
+export interface Api {
+ country: Api.CountryApi;
+ productAttributes: Api.ProductAttributesApi;
+ product: Api.ProductApi;
+ search: Api.SearchApi;
+ cart: Api.CartApi;
+ getPage: Api.Internals['getPage'];
+}
+
+export default Api;
diff --git a/src/typings/hooks.d.ts b/src/typings/hooks.d.ts
new file mode 100644
index 0000000..05c8337
--- /dev/null
+++ b/src/typings/hooks.d.ts
@@ -0,0 +1,63 @@
+///
+///
+
+export declare namespace Hooks {
+ class BaseHooks extends EventEmitter2 {
+ $body: JQuery
+ }
+
+ class CartHooks extends BaseHooks {
+ itemAdd(): void;
+ }
+
+ class CookieHooks extends BaseHooks {}
+
+ class CurrencySelectorHooks extends BaseHooks {
+ currencySelector(): void;
+ }
+
+ class ProductHooks extends BaseHooks {
+ optionsChange(): void;
+ }
+
+ class SearchHooks extends BaseHooks {
+ quickSearch(): void;
+ }
+
+ class FacetedSearchHooks extends BaseHooks {
+ searchEvents(): void;
+ }
+
+ class SortByHooks extends BaseHooks {
+ sortByEvents(): void;
+ }
+
+
+ namespace Internals {
+ interface Classes {
+ cart: CartHooks;
+ cookie: CookieHooks;
+ currencySelector: CurrencySelectorHooks;
+ product: ProductHooks;
+ search: SearchHooks;
+ facetedSearch: FacetedSearchHooks;
+ sortBy: SortByHooks;
+ }
+
+ export const classes: Classes
+ }
+
+ interface Internals {
+ classes: Internals.Classes;
+ parseHooks(hookName: H): Internals.Classes[T];
+ }
+}
+
+
+export declare class Hooks {
+ on(hookname: H, callback: () => void|any): ReturnType;
+ off(hookname: H, callback: () => void|any): ReturnType;
+ emit(hookname: H, callback: () => void|any): ReturnType;
+}
+
+export default Hooks;
diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts
new file mode 100644
index 0000000..b359fe9
--- /dev/null
+++ b/src/typings/index.d.ts
@@ -0,0 +1,22 @@
+// Type definitions for Stencil Utils v4.1.0
+// Project: https://github.com/bigcommerce/stencil-utils
+// Definitions by: Arctic Leaf
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// Documentation: https://developer.bigcommerce.com/stencil-docs/adding-event-hooks-to-your-theme/stencil-utils-api-reference
+
+import Api from './api';
+import Hooks from './hooks';
+import Tools from './tools';
+
+interface StencilUtils {
+ api: Api;
+ hooks: Hooks;
+ tools: Tools;
+}
+
+declare const utils: StencilUtils;
+
+export const api: Api;
+export const hooks: Hooks;
+export const tools: Tools;
+export default utils;
diff --git a/src/typings/tools.d.ts b/src/typings/tools.d.ts
new file mode 100644
index 0000000..d0dc46a
--- /dev/null
+++ b/src/typings/tools.d.ts
@@ -0,0 +1,23 @@
+export declare namespace Tools {
+ class ImageTool {
+ getSrc(path: string, dimensions: string): string;
+ }
+
+ class StorageTools {
+ /**
+ * Check if a storage type (like localStorage or sessionStorage) is available for use
+ * https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Testing_for_availability
+ * @param type
+ * @returns boolean
+ */
+ storageAvailable(type: string): boolean;
+ localStorageAvailable(): boolean;
+ }
+}
+
+export interface Tools {
+ image: Tools.ImageTool;
+ storage: Tools.StorageTools;
+}
+
+export default Tools;