@liquidcommerce/elements-sdk 2.7.0 → 2.7.2
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.
- package/README.md +83 -2750
- package/dist/index.checkout.esm.js +6898 -6837
- package/dist/index.esm.js +11463 -10993
- package/dist/types/auto-initialize/shared-utils.d.ts +5 -0
- package/dist/types/constants/core.constant.d.ts +0 -4
- package/dist/types/core/base-component.service.d.ts +2 -1
- package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +1 -0
- package/dist/types/enums/core.enum.d.ts +11 -0
- package/dist/types/interfaces/configs/product-list.interface.d.ts +2 -2
- package/dist/types/interfaces/core.interface.d.ts +5 -4
- package/dist/types/modules/address/address-input.component.d.ts +11 -0
- package/dist/types/modules/checkout/components/checkout-stripe-form.component.d.ts +2 -1
- package/dist/types/modules/product-list/components/card-components/index.d.ts +3 -0
- package/dist/types/modules/product-list/components/card-components/product-badge.d.ts +8 -0
- package/dist/types/modules/product-list/components/card-components/product-fulfillments.d.ts +2 -0
- package/dist/types/modules/product-list/components/card-components/product-price-and-personalization.d.ts +13 -0
- package/dist/types/modules/product-list/components/card-components/product-title.d.ts +6 -0
- package/dist/types/modules/product-list/components/index.d.ts +1 -0
- package/dist/types/modules/product-list/components/product-list-engraving.component.d.ts +5 -1
- package/dist/types/modules/product-list/components/product-list-product-pre-cart.component.d.ts +28 -0
- package/dist/types/modules/product-list/components/product-list-retailers.component.d.ts +10 -2
- package/dist/types/modules/product-list/product-list-card.component.d.ts +0 -5
- package/dist/types/modules/product-list/product-list.commands.d.ts +11 -2
- package/dist/types/modules/product-list/product-list.interface.d.ts +1 -0
- package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +11 -2
- package/dist/types/modules/ui-components/lce-element/lce-element.component.d.ts +2 -1
- package/dist/types/utils/dom-compat.d.ts +2 -0
- package/docs/gitbook/actions.md +964 -0
- package/docs/gitbook/address.md +48 -0
- package/docs/gitbook/cart.md +65 -0
- package/docs/gitbook/checkout.md +131 -0
- package/docs/gitbook/events.md +1765 -0
- package/docs/gitbook/overview.md +166 -0
- package/docs/gitbook/product.md +64 -0
- package/docs/gitbook/quick-start-guide.md +393 -0
- package/docs/v1/README.md +210 -0
- package/docs/v1/api/actions/address-actions.md +281 -0
- package/docs/v1/api/actions/cart-actions.md +337 -0
- package/docs/v1/api/actions/checkout-actions.md +387 -0
- package/docs/v1/api/actions/product-actions.md +115 -0
- package/docs/v1/api/client.md +482 -0
- package/docs/v1/api/configuration.md +1 -0
- package/docs/v1/api/injection-methods.md +247 -0
- package/docs/v1/api/typescript-types.md +1 -0
- package/docs/v1/api/ui-helpers.md +200 -0
- package/docs/v1/examples/advanced-patterns.md +96 -0
- package/docs/v1/examples/checkout-flow.md +91 -0
- package/docs/v1/examples/custom-theming.md +63 -0
- package/docs/v1/examples/multi-product-page.md +90 -0
- package/docs/v1/examples/simple-product-page.md +89 -0
- package/docs/v1/getting-started/concepts.md +507 -0
- package/docs/v1/getting-started/installation.md +328 -0
- package/docs/v1/getting-started/quick-start.md +405 -0
- package/docs/v1/guides/address-component.md +431 -0
- package/docs/v1/guides/best-practices.md +324 -0
- package/docs/v1/guides/cart-component.md +737 -0
- package/docs/v1/guides/checkout-component.md +672 -0
- package/docs/v1/guides/events.md +926 -0
- package/docs/v1/guides/product-component.md +686 -0
- package/docs/v1/guides/product-list-component.md +598 -0
- package/docs/v1/guides/theming.md +216 -0
- package/docs/v1/integration/angular.md +39 -0
- package/docs/v1/integration/laravel.md +41 -0
- package/docs/v1/integration/nextjs.md +60 -0
- package/docs/v1/integration/proxy-setup.md +89 -0
- package/docs/v1/integration/react.md +64 -0
- package/docs/v1/integration/vanilla-js.md +84 -0
- package/docs/v1/integration/vue.md +34 -0
- package/docs/v1/reference/browser-support.md +44 -0
- package/docs/v1/reference/error-handling.md +70 -0
- package/docs/v1/reference/performance.md +54 -0
- package/docs/v1/reference/troubleshooting.md +64 -0
- package/package.json +1 -1
- package/docs/ACTIONS.md +0 -1301
- package/docs/BROWSER_SUPPORT.md +0 -279
- package/docs/CONFIGURATION.md +0 -997
- package/docs/DOCUMENTATION_INDEX.md +0 -319
- package/docs/EVENTS.md +0 -798
- package/docs/PROXY.md +0 -228
- package/docs/THEMING.md +0 -681
- package/docs/TROUBLESHOOTING.md +0 -793
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# Best Practices
|
|
2
|
+
|
|
3
|
+
Recommended patterns and practices for working with the Elements SDK.
|
|
4
|
+
|
|
5
|
+
## Initialization
|
|
6
|
+
|
|
7
|
+
### Initialize Once
|
|
8
|
+
|
|
9
|
+
Create a single client instance and reuse it:
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// Good
|
|
13
|
+
const client = await Elements('KEY', { env: 'production' });
|
|
14
|
+
await client.injectProductElement([...]);
|
|
15
|
+
await client.injectCartElement('cart');
|
|
16
|
+
|
|
17
|
+
// Bad - creates multiple instances
|
|
18
|
+
await Elements('KEY', { env: 'production' });
|
|
19
|
+
await Elements('KEY', { env: 'production' });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Use Global Access
|
|
23
|
+
|
|
24
|
+
After initialization, use `window.elements`:
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// Initialize once
|
|
28
|
+
await Elements('KEY', { env: 'production' });
|
|
29
|
+
|
|
30
|
+
// Use globally throughout your app
|
|
31
|
+
window.elements.actions.cart.openCart();
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Wait for Client Ready
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
if (window.elements) {
|
|
38
|
+
// Client already ready
|
|
39
|
+
window.elements.actions.cart.openCart();
|
|
40
|
+
} else {
|
|
41
|
+
// Wait for initialization
|
|
42
|
+
window.addEventListener('lce:actions.client_ready', () => {
|
|
43
|
+
window.elements.actions.cart.openCart();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Component Injection
|
|
49
|
+
|
|
50
|
+
### Verify Container Exists
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// Check container before injection
|
|
54
|
+
if (document.getElementById('product')) {
|
|
55
|
+
await client.injectProductElement([
|
|
56
|
+
{ containerId: 'product', identifier: '123' }
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Provide Adequate Space
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
#product-container {
|
|
65
|
+
min-height: 600px; /* Prevent layout shift */
|
|
66
|
+
max-width: 1200px;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Handle Loading States
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
showLoader('product-container');
|
|
74
|
+
|
|
75
|
+
await client.injectProductElement([...]);
|
|
76
|
+
|
|
77
|
+
// Loader automatically replaced when product loads
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Error Handling
|
|
81
|
+
|
|
82
|
+
### Catch Errors Appropriately
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
try {
|
|
86
|
+
await window.elements.actions.cart.addProduct([...]);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (error.name === 'SDKError') {
|
|
89
|
+
console.error('SDK Error:', error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Provide Fallbacks
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
const client = await Elements('KEY', { env: 'production' });
|
|
98
|
+
|
|
99
|
+
if (!client) {
|
|
100
|
+
// Initialization failed
|
|
101
|
+
showFallbackUI();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Performance
|
|
107
|
+
|
|
108
|
+
### Lazy Load Products
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const observer = new IntersectionObserver(async (entries) => {
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
if (entry.isIntersecting) {
|
|
114
|
+
const container = entry.target;
|
|
115
|
+
await client.injectProductElement([
|
|
116
|
+
{ containerId: container.id, identifier: container.dataset.productId }
|
|
117
|
+
]);
|
|
118
|
+
observer.unobserve(container);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
document.querySelectorAll('.product-placeholder').forEach(el => {
|
|
124
|
+
observer.observe(el);
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Use Checkout-Only Build
|
|
129
|
+
|
|
130
|
+
For checkout pages:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import { ElementsCheckout } from '@liquidcommerce/elements-sdk/checkout';
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Reduces bundle size by ~60%.
|
|
137
|
+
|
|
138
|
+
### Defer Non-Critical Operations
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
// Load visible products first
|
|
142
|
+
await client.injectProductElement([
|
|
143
|
+
{ containerId: 'hero-product', identifier: '001' }
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
// Load others after delay
|
|
147
|
+
setTimeout(async () => {
|
|
148
|
+
await client.injectProductElement([
|
|
149
|
+
{ containerId: 'related-1', identifier: '002' }
|
|
150
|
+
]);
|
|
151
|
+
}, 1000);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## State Management
|
|
155
|
+
|
|
156
|
+
### Pre-fill Known Data
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
// Set address if known
|
|
160
|
+
if (userSavedAddress) {
|
|
161
|
+
await window.elements.actions.address.setAddressManually(
|
|
162
|
+
userSavedAddress,
|
|
163
|
+
userCoordinates
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Pre-fill checkout info
|
|
168
|
+
window.addEventListener('lce:actions.checkout_opened', () => {
|
|
169
|
+
if (userIsLoggedIn) {
|
|
170
|
+
window.elements.actions.checkout.updateCustomerInfo({
|
|
171
|
+
firstName: user.firstName,
|
|
172
|
+
email: user.email
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Don't Clear Cart Unnecessarily
|
|
179
|
+
|
|
180
|
+
Cart persists across sessions - avoid clearing unless intentional:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
// Only clear when user explicitly requests
|
|
184
|
+
document.getElementById('clear-cart-btn').addEventListener('click', async () => {
|
|
185
|
+
if (confirm('Clear cart?')) {
|
|
186
|
+
await window.elements.actions.cart.resetCart();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Events
|
|
192
|
+
|
|
193
|
+
### Use Events for Reactive Updates
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
// Update UI when cart changes
|
|
197
|
+
window.addEventListener('lce:actions.cart_updated', () => {
|
|
198
|
+
const cart = window.elements.actions.cart.getDetails();
|
|
199
|
+
updateHeaderCartCount(cart.itemsCount);
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Track Important Events
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
window.addEventListener('lce:actions.checkout_submit_completed', (event) => {
|
|
207
|
+
const { orderId, total } = event.detail.data;
|
|
208
|
+
|
|
209
|
+
// Analytics
|
|
210
|
+
gtag('event', 'purchase', {
|
|
211
|
+
transaction_id: orderId,
|
|
212
|
+
value: total / 100
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Backend tracking
|
|
216
|
+
fetch('/api/track-order', {
|
|
217
|
+
method: 'POST',
|
|
218
|
+
body: JSON.stringify({ orderId, total })
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Security
|
|
224
|
+
|
|
225
|
+
### Use Proxy in Production
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const client = await Elements('YOUR_API_KEY', {
|
|
229
|
+
env: 'production',
|
|
230
|
+
proxy: {
|
|
231
|
+
baseUrl: 'https://yoursite.com/api/elements-proxy'
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Prevents ad blockers and protects API keys.
|
|
237
|
+
|
|
238
|
+
### Separate API Keys by Environment
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const apiKey = process.env.NODE_ENV === 'production'
|
|
242
|
+
? 'prod_key_xyz'
|
|
243
|
+
: 'dev_key_abc';
|
|
244
|
+
|
|
245
|
+
const client = await Elements(apiKey, {
|
|
246
|
+
env: process.env.NODE_ENV === 'production' ? 'production' : 'development'
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Testing
|
|
251
|
+
|
|
252
|
+
### Use Development Mode
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
const client = await Elements('YOUR_API_KEY', {
|
|
256
|
+
env: 'development',
|
|
257
|
+
debugMode: 'console', // or 'panel'
|
|
258
|
+
development: {
|
|
259
|
+
openShadowDom: true, // Makes debugging easier
|
|
260
|
+
paymentMethodId: 'pm_test_123' // Bypass Stripe for tests
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Handle Test Scenarios
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// Test empty cart
|
|
269
|
+
if (isDevelopment) {
|
|
270
|
+
await window.elements.actions.cart.resetCart();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Test with specific product
|
|
274
|
+
await window.elements.actions.cart.addProduct([
|
|
275
|
+
{ identifier: testProductId, fulfillmentType: 'shipping', quantity: 1 }
|
|
276
|
+
]);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Accessibility
|
|
280
|
+
|
|
281
|
+
### Provide Labels
|
|
282
|
+
|
|
283
|
+
```html
|
|
284
|
+
<label for="cart-toggle">Shopping Cart</label>
|
|
285
|
+
<button id="cart-toggle" data-lce-cart-toggle-button>
|
|
286
|
+
Cart (<span data-lce-cart-items-count></span>)
|
|
287
|
+
</button>
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Use Semantic HTML
|
|
291
|
+
|
|
292
|
+
```html
|
|
293
|
+
<nav aria-label="Main navigation">
|
|
294
|
+
<div id="cart-button"></div>
|
|
295
|
+
</nav>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Mobile Optimization
|
|
299
|
+
|
|
300
|
+
### Responsive Containers
|
|
301
|
+
|
|
302
|
+
```css
|
|
303
|
+
@media (max-width: 768px) {
|
|
304
|
+
#product-container {
|
|
305
|
+
padding: 10px;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Mobile-Specific Cart Button
|
|
311
|
+
|
|
312
|
+
```javascript
|
|
313
|
+
if (window.innerWidth < 768) {
|
|
314
|
+
window.elements.ui.floatingCartButton(true);
|
|
315
|
+
} else {
|
|
316
|
+
window.elements.ui.cartButton('header-cart', true);
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## See Also
|
|
321
|
+
|
|
322
|
+
- [Performance Guide](../reference/performance.md)
|
|
323
|
+
- [Troubleshooting](../reference/troubleshooting.md)
|
|
324
|
+
- [Component Guides](../guides/)
|