@liquidcommerce/elements-sdk 2.6.0-beta.37 → 2.6.0-beta.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,320 @@
1
+ # Actions
2
+
3
+ Actions let you control the SDK with JavaScript instead of (or in addition to) user interactions. Open the cart when a user clicks your custom button, pre-fill checkout forms for returning customers, or add products to cart from anywhere in your app.
4
+
5
+ ## Accessing Actions
6
+
7
+ ```javascript
8
+ // Global access
9
+ const { actions } = window.elements;
10
+
11
+ // Or from client instance
12
+ const client = await Elements('YOUR_API_KEY', config);
13
+ // Access via client.actions
14
+ ```
15
+
16
+ ## How Actions Work
17
+
18
+ Actions are fire-and-forget methods that return `void` or `Promise<void>`. All feedback comes through [events](./events.md) - this is by design for security.
19
+
20
+ ```javascript
21
+ // 1. Listen for feedback
22
+ window.addEventListener('lce:actions.cart_promo_code_applied', (event) => {
23
+ const { discount, newSubtotal } = event.detail.data;
24
+ showSuccess(`Saved $${discount}!`);
25
+ });
26
+
27
+ // 2. Fire the action
28
+ await actions.cart.applyPromoCode('SUMMER20');
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Address Actions
34
+
35
+ Manage the customer's delivery location.
36
+
37
+ | Method | Returns | Description |
38
+ |--------|---------|-------------|
39
+ | `setAddressByPlacesId(placesId)` | `Promise<void>` | Set location via Google Places ID |
40
+ | `setAddressManually(address, coords)` | `Promise<void>` | Set location with address and coordinates |
41
+ | `getDetails()` | `IAddressData \| null` | Get current address |
42
+ | `clear()` | `Promise<void>` | Clear address (also resets cart) |
43
+
44
+ ### setAddressByPlacesId
45
+
46
+ ```javascript
47
+ await actions.address.setAddressByPlacesId('ChIJN1t_tDeuEmsRUsoyG83frY4');
48
+ ```
49
+
50
+ ### setAddressManually
51
+
52
+ ```javascript
53
+ await actions.address.setAddressManually(
54
+ {
55
+ one: '123 Main St',
56
+ two: 'Apt 4B', // optional
57
+ city: 'New York',
58
+ state: 'NY',
59
+ zip: '10001',
60
+ country: 'US' // optional
61
+ },
62
+ {
63
+ lat: 40.7128,
64
+ long: -74.0060
65
+ }
66
+ );
67
+ ```
68
+
69
+ ### getDetails
70
+
71
+ ```javascript
72
+ const address = actions.address.getDetails();
73
+ if (address) {
74
+ console.log(address.formattedAddress);
75
+ console.log(address.coordinates);
76
+ }
77
+ ```
78
+
79
+ ### clear
80
+
81
+ ```javascript
82
+ await actions.address.clear();
83
+ // Note: This also clears the cart
84
+ ```
85
+
86
+ **Feedback Events:** `address_updated`, `address_cleared`, `address_failed`
87
+
88
+ ---
89
+
90
+ ## Product Actions
91
+
92
+ Query product information.
93
+
94
+ | Method | Returns | Description |
95
+ |--------|---------|-------------|
96
+ | `getDetails(identifier)` | `IBaseProductEventData` | Get product state |
97
+
98
+ ### getDetails
99
+
100
+ ```javascript
101
+ const product = actions.product.getDetails('00619947000020');
102
+
103
+ console.log(product.name);
104
+ console.log(product.selectedSizeId);
105
+ console.log(product.selectedFulfillmentType);
106
+ console.log(product.priceInfo);
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Cart Actions
112
+
113
+ Control the shopping cart.
114
+
115
+ | Method | Returns | Description |
116
+ |--------|---------|---------------------|
117
+ | `openCart()` | `void` | Show cart drawer |
118
+ | `closeCart()` | `void` | Hide cart drawer |
119
+ | `toggleCart()` | `void` | Toggle cart drawer |
120
+ | `addProduct(items[], openCart?)` | `Promise<void>` | Add items to cart |
121
+ | `applyPromoCode(code)` | `Promise<void>` | Apply discount code |
122
+ | `removePromoCode()` | `Promise<void>` | Remove discount |
123
+ | `resetCart()` | `Promise<void>` | Clear all items |
124
+ | `getDetails()` | `IBaseCartEventData` | Get cart state |
125
+
126
+ ### openCart / closeCart / toggleCart
127
+
128
+ ```javascript
129
+ actions.cart.openCart();
130
+ actions.cart.closeCart();
131
+ actions.cart.toggleCart();
132
+ ```
133
+
134
+ ### addProduct
135
+
136
+ ```javascript
137
+ await actions.cart.addProduct(
138
+ [
139
+ {
140
+ identifier: '00619947000020',
141
+ fulfillmentType: 'shipping', // 'shipping' or 'onDemand'
142
+ quantity: 2
143
+ }
144
+ ],
145
+ true // Open cart after adding (optional)
146
+ );
147
+ ```
148
+
149
+ ### applyPromoCode / removePromoCode
150
+
151
+ ```javascript
152
+ await actions.cart.applyPromoCode('SUMMER20');
153
+ await actions.cart.removePromoCode();
154
+ ```
155
+
156
+ ### resetCart
157
+
158
+ ```javascript
159
+ await actions.cart.resetCart();
160
+ ```
161
+
162
+ ### getDetails
163
+
164
+ ```javascript
165
+ const cart = actions.cart.getDetails();
166
+
167
+ console.log(cart.itemCount);
168
+ console.log(cart.subtotal);
169
+ console.log(cart.items);
170
+ ```
171
+
172
+ **Feedback Events:** `cart_opened`, `cart_closed`, `cart_product_add_success`, `cart_product_add_failed`, `cart_promo_code_applied`, `cart_promo_code_removed`, `cart_promo_code_failed`, `cart_reset`
173
+
174
+ ---
175
+
176
+ ## Checkout Actions
177
+
178
+ Control the checkout flow.
179
+
180
+ | Method | Returns | Description |
181
+ |--------|---------|-------------|
182
+ | `openCheckout()` | `void` | Show checkout drawer |
183
+ | `closeCheckout()` | `void` | Hide checkout drawer |
184
+ | `toggleCheckout()` | `void` | Toggle checkout drawer |
185
+ | `exitCheckout()` | `void` | Navigate to exit URL |
186
+ | `addProduct(items[], open?)` | `Promise<void>` | Add to checkout directly |
187
+ | `applyPromoCode(code)` | `Promise<void>` | Apply discount |
188
+ | `removePromoCode()` | `Promise<void>` | Remove discount |
189
+ | `applyGiftCard(code)` | `Promise<void>` | Apply gift card |
190
+ | `removeGiftCard(code)` | `Promise<void>` | Remove gift card |
191
+ | `toggleIsGift(active?)` | `Promise<void>` | Enable/disable gift mode |
192
+ | `toggleBillingSameAsShipping(active?)` | `Promise<void>` | Use same address |
193
+ | `toggleMarketingPreferences(field, active)` | `Promise<void>` | Set opt-in |
194
+ | `updateCustomerInfo(params)` | `void` | Pre-fill customer form |
195
+ | `updateBillingInfo(params)` | `void` | Pre-fill billing form |
196
+ | `updateGiftInfo(params)` | `void` | Pre-fill gift form |
197
+ | `getDetails()` | `ICheckoutDetailsEventData` | Get checkout state |
198
+
199
+ ### openCheckout / closeCheckout / toggleCheckout / exitCheckout
200
+
201
+ ```javascript
202
+ actions.checkout.openCheckout();
203
+ actions.checkout.closeCheckout();
204
+ actions.checkout.toggleCheckout();
205
+ actions.checkout.exitCheckout(); // Navigates to configured exit URL
206
+ ```
207
+
208
+ ### addProduct
209
+
210
+ ```javascript
211
+ // Add products directly to checkout (skip cart)
212
+ await actions.checkout.addProduct(
213
+ [{ identifier: '00619947000020', fulfillmentType: 'shipping', quantity: 1 }],
214
+ true // Open checkout (optional)
215
+ );
216
+ ```
217
+
218
+ ### applyPromoCode / removePromoCode
219
+
220
+ ```javascript
221
+ await actions.checkout.applyPromoCode('SAVE10');
222
+ await actions.checkout.removePromoCode();
223
+ ```
224
+
225
+ ### applyGiftCard / removeGiftCard
226
+
227
+ ```javascript
228
+ await actions.checkout.applyGiftCard('GIFT-XXXX-XXXX');
229
+ await actions.checkout.removeGiftCard('GIFT-XXXX-XXXX');
230
+ ```
231
+
232
+ ### toggleIsGift / toggleBillingSameAsShipping / toggleMarketingPreferences
233
+
234
+ ```javascript
235
+ await actions.checkout.toggleIsGift(true);
236
+ await actions.checkout.toggleBillingSameAsShipping(true);
237
+ await actions.checkout.toggleMarketingPreferences('canEmail', true);
238
+ await actions.checkout.toggleMarketingPreferences('canSms', false);
239
+ ```
240
+
241
+ ### updateCustomerInfo
242
+
243
+ ```javascript
244
+ actions.checkout.updateCustomerInfo({
245
+ firstName: 'John',
246
+ lastName: 'Doe',
247
+ email: 'john@example.com',
248
+ phone: '555-123-4567'
249
+ });
250
+ ```
251
+
252
+ ### updateBillingInfo
253
+
254
+ ```javascript
255
+ actions.checkout.updateBillingInfo({
256
+ firstName: 'John',
257
+ lastName: 'Doe',
258
+ street1: '123 Billing St',
259
+ street2: 'Suite 100', // optional
260
+ city: 'New York',
261
+ state: 'NY',
262
+ zipCode: '10001'
263
+ });
264
+ ```
265
+
266
+ ### updateGiftInfo
267
+
268
+ ```javascript
269
+ actions.checkout.updateGiftInfo({
270
+ recipientName: 'Jane Smith',
271
+ senderName: 'John Doe',
272
+ giftMessage: 'Happy Birthday!'
273
+ });
274
+ ```
275
+
276
+ ### getDetails
277
+
278
+ ```javascript
279
+ const checkout = actions.checkout.getDetails();
280
+
281
+ console.log(checkout.subtotal);
282
+ console.log(checkout.total);
283
+ console.log(checkout.items);
284
+ console.log(checkout.isGift);
285
+ ```
286
+
287
+ **Feedback Events:** `checkout_opened`, `checkout_closed`, `checkout_product_add_success`, `checkout_product_add_failed`, `checkout_promo_code_applied`, `checkout_promo_code_removed`, `checkout_promo_code_failed`, `checkout_gift_card_applied`, `checkout_gift_card_removed`, `checkout_gift_card_failed`
288
+
289
+ ---
290
+
291
+ ## Product List Actions
292
+
293
+ Coming soon.
294
+
295
+ ---
296
+
297
+ ## Security Notes
298
+
299
+ Events never expose sensitive information:
300
+
301
+ **Safe in events:**
302
+ - Success/failure status
303
+ - Discount amounts
304
+ - Total amounts
305
+ - Item counts and identifiers
306
+
307
+ **Never exposed:**
308
+ - Promo codes or gift card codes
309
+ - Gift card balances
310
+ - Sensitive financial details
311
+
312
+ ---
313
+
314
+ ## See Also
315
+
316
+ - [Events Reference](./events.md) - Event feedback for actions
317
+ - [Product](./product.md) - Product component
318
+ - [Cart](./cart.md) - Cart component
319
+ - [Checkout](./checkout.md) - Checkout component
320
+ - [Address](./address.md) - Address component
@@ -0,0 +1,242 @@
1
+ # Address
2
+
3
+ The address component manages the customer's delivery location. This determines which products are available, their pricing, and fulfillment options. Most implementations don't need to interact with this directly - it's built into the product component.
4
+
5
+ ## Overview
6
+
7
+ The address element powers location-aware shopping:
8
+ - Customers enter their delivery address
9
+ - The SDK fetches location-specific inventory and pricing
10
+ - Fulfillment options update based on what's available in that area
11
+ - The address persists across sessions for returning customers
12
+
13
+ **Important:** You typically don't need to inject this component separately. The address input is embedded within the product component by default. Use standalone injection only for dedicated "enter your address" landing pages.
14
+
15
+ ---
16
+
17
+ ## Declarative Setup (HTML Attributes)
18
+
19
+ In most cases, the address component is automatically managed within the product element. No separate configuration is required.
20
+
21
+ When you inject a product element, customers can:
22
+ 1. Click to enter their delivery address
23
+ 2. See real-time availability and pricing for their location
24
+ 3. Have their address remembered for future visits
25
+
26
+ The address UI appears as part of the product component's fulfillment section.
27
+
28
+ ---
29
+
30
+ ## Programmatic Setup (JavaScript API)
31
+
32
+ For standalone address collection (e.g., a "Check Availability" page), inject the address element directly.
33
+
34
+ ### Basic Injection
35
+
36
+ ```javascript
37
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
38
+
39
+ const component = await client.injectAddressElement('address-container');
40
+ ```
41
+
42
+ ### Return Value
43
+
44
+ Returns `IInjectedComponent | null`:
45
+
46
+ ```javascript
47
+ if (component) {
48
+ // Get the container element
49
+ const element = component.getElement();
50
+
51
+ // Get the component type
52
+ const type = component.getType(); // 'address'
53
+
54
+ // Force a re-render
55
+ component.rerender();
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Actions
62
+
63
+ Control address state programmatically. Useful for:
64
+ - Pre-filling addresses for logged-in customers
65
+ - Custom address form integrations
66
+ - Single-click address selection
67
+
68
+ ### Set Address by Google Places ID
69
+
70
+ Set the delivery location using a Google Places ID:
71
+
72
+ ```javascript
73
+ await window.elements.actions.address.setAddressByPlacesId('ChIJN1t_tDeuEmsRUsoyG83frY4');
74
+ ```
75
+
76
+ ### Set Address Manually
77
+
78
+ Set the delivery location with explicit address data and coordinates:
79
+
80
+ ```javascript
81
+ await window.elements.actions.address.setAddressManually(
82
+ {
83
+ one: '123 Main St', // Street address line 1
84
+ two: 'Apt 4B', // Street address line 2 (optional)
85
+ city: 'New York',
86
+ state: 'NY',
87
+ zip: '10001',
88
+ country: 'US' // Optional, defaults to US
89
+ },
90
+ {
91
+ lat: 40.7128, // Latitude
92
+ long: -74.0060 // Longitude
93
+ }
94
+ );
95
+ ```
96
+
97
+ ### Get Address Details
98
+
99
+ Retrieve the currently saved address:
100
+
101
+ ```javascript
102
+ const address = window.elements.actions.address.getDetails();
103
+
104
+ if (address) {
105
+ console.log(address.formattedAddress);
106
+ console.log(address.coordinates);
107
+ }
108
+ ```
109
+
110
+ Returns `IAddressData | null`.
111
+
112
+ ### Clear Address
113
+
114
+ Remove the saved address. **Note:** This also clears the cart since pricing and availability are location-dependent.
115
+
116
+ ```javascript
117
+ await window.elements.actions.address.clear();
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Events
123
+
124
+ Listen to address changes for analytics or custom UI updates.
125
+
126
+ ### Subscribing to Events
127
+
128
+ ```javascript
129
+ window.addEventListener('lce:actions.address_updated', (event) => {
130
+ const { formattedAddress, coordinates } = event.detail.data;
131
+ console.log('Address set to:', formattedAddress);
132
+ });
133
+ ```
134
+
135
+ ### Available Events
136
+
137
+ | Event | Description | Key Data |
138
+ |-------|-------------|----------|
139
+ | `address_updated` | Location set or changed | googlePlacesId, formattedAddress, address, coordinates |
140
+ | `address_cleared` | Location removed | boolean (true) |
141
+ | `address_failed` | Location operation failed | error message, googlePlacesId (if applicable) |
142
+
143
+ ### Example: Update Custom UI
144
+
145
+ ```javascript
146
+ // Update your own UI when address changes
147
+ window.addEventListener('lce:actions.address_updated', (event) => {
148
+ const { formattedAddress } = event.detail.data;
149
+ document.querySelector('.delivery-location').textContent = formattedAddress;
150
+ });
151
+
152
+ // Handle address being cleared
153
+ window.addEventListener('lce:actions.address_cleared', () => {
154
+ document.querySelector('.delivery-location').textContent = 'Enter your address';
155
+ });
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Clear Address Behavior
161
+
162
+ When an address is cleared (either by the customer or programmatically), several things happen:
163
+
164
+ 1. **Cart is reset** - Items are removed because pricing and availability are location-specific
165
+ 2. **Local storage is cleared** - The saved address is removed
166
+ 3. **Product displays update** - Products show "Enter address" prompts again
167
+
168
+ This ensures customers never see stale pricing or unavailable items.
169
+
170
+ ---
171
+
172
+ ## Use Cases
173
+
174
+ ### Pre-fill for Logged-in Customers
175
+
176
+ ```javascript
177
+ // When user logs in, set their saved address
178
+ if (user.savedAddress) {
179
+ await window.elements.actions.address.setAddressManually(
180
+ {
181
+ one: user.savedAddress.street,
182
+ city: user.savedAddress.city,
183
+ state: user.savedAddress.state,
184
+ zip: user.savedAddress.zip
185
+ },
186
+ {
187
+ lat: user.savedAddress.latitude,
188
+ long: user.savedAddress.longitude
189
+ }
190
+ );
191
+ }
192
+ ```
193
+
194
+ ### Custom Address Form
195
+
196
+ ```javascript
197
+ // Connect your own address form to the SDK
198
+ document.querySelector('#address-form').addEventListener('submit', async (e) => {
199
+ e.preventDefault();
200
+ const formData = new FormData(e.target);
201
+
202
+ // Use your geocoding service to get coordinates
203
+ const coords = await geocode(formData.get('address'));
204
+
205
+ await window.elements.actions.address.setAddressManually(
206
+ {
207
+ one: formData.get('street'),
208
+ city: formData.get('city'),
209
+ state: formData.get('state'),
210
+ zip: formData.get('zip')
211
+ },
212
+ coords
213
+ );
214
+ });
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Customization
220
+
221
+ Style the address component through theme configuration.
222
+
223
+ ```javascript
224
+ const client = await Elements('YOUR_API_KEY', {
225
+ customTheme: {
226
+ address: {
227
+ // Address-specific theme options
228
+ }
229
+ }
230
+ });
231
+ ```
232
+
233
+ See [theming.md](./theming.md) for available address theme options.
234
+
235
+ ---
236
+
237
+ ## See Also
238
+
239
+ - [Product](./product.md) - The product element (includes embedded address)
240
+ - [Actions Reference](./actions.md) - All available actions
241
+ - [Events Reference](./events.md) - All available events
242
+ - [Theming Guide](./theming.md) - Customization options