@pixeasy/customizer 0.0.9-beta.0 → 0.0.10-beta.0
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 +395 -44
- package/index.d.ts +21 -17
- package/package.json +1 -1
- package/pixeasy-customizer.css +1 -1
- package/pixeasy-customizer.min.js +354 -265
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Framework-agnostic SDK to embed the Pixeasy customizer in Angular, React, Vue, or any ESM app.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @pixeasy/customizer
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Quick
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
import { createPixeasyBuilder } from '@pixeasy/customizer';
|
|
@@ -23,60 +23,160 @@ builder.open({
|
|
|
23
23
|
});
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`container` can be
|
|
26
|
+
**Note:** `container` can be a CSS selector string (element id) or an `HTMLElement` reference.
|
|
27
27
|
|
|
28
|
-
## API
|
|
28
|
+
## API Reference
|
|
29
29
|
|
|
30
30
|
### `createPixeasyBuilder()`
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Creates and returns a new `PixeasyBuilder` instance. You can create multiple builder instances if needed.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const builder = createPixeasyBuilder();
|
|
36
|
+
```
|
|
33
37
|
|
|
34
38
|
### `PixeasyBuilder.open(options)`
|
|
35
39
|
|
|
40
|
+
Opens the customizer with the specified configuration.
|
|
41
|
+
|
|
42
|
+
#### Options
|
|
43
|
+
|
|
36
44
|
```ts
|
|
37
45
|
type PixeasyOpenOptions = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
// Required
|
|
47
|
+
container: string | HTMLElement; // CSS selector or DOM element to mount the customizer
|
|
48
|
+
apiKey: string; // Your API key (format: dk_xxx_yyy)
|
|
49
|
+
productId: string; // Product ID (UUID format)
|
|
50
|
+
|
|
51
|
+
// Optional
|
|
52
|
+
predesignId?: string; // Load a pre-designed template
|
|
53
|
+
submissionNumber?: string; // Load an existing submission for editing
|
|
54
|
+
locale?: string; // Language/locale code (e.g., 'en', 'fr', 'de')
|
|
55
|
+
theme?: string; // Theme name or color scheme
|
|
56
|
+
readonly?: boolean; // Set to true to disable editing (view-only mode)
|
|
44
57
|
};
|
|
45
58
|
```
|
|
46
59
|
|
|
47
|
-
|
|
60
|
+
#### Option Details
|
|
61
|
+
|
|
62
|
+
| Option | Type | Required | Description |
|
|
63
|
+
| ------------------ | ----------------------- | -------- | ------------------------------------------------------------------------------------- |
|
|
64
|
+
| `container` | `string \| HTMLElement` | Yes | Target container to mount the customizer. If string, treated as element ID. |
|
|
65
|
+
| `apiKey` | `string` | Yes | Your Pixeasy API key for authentication. |
|
|
66
|
+
| `productId` | `string` | Yes | UUID of the product to customize. |
|
|
67
|
+
| `predesignId` | `string` | No | Load a pre-designed template/predesign. Useful for template-based workflows. |
|
|
68
|
+
| `submissionNumber` | `string` | No | Load an existing submission for editing or review. Use with `readonly` for view-only. |
|
|
69
|
+
| `locale` | `string` | No | Set the UI language. Examples: `'en'`, `'fr'`, `'de'`, `'es'`. |
|
|
70
|
+
| `theme` | `string` | No | Apply a theme or color scheme to the customizer UI. |
|
|
71
|
+
| `readonly` | `boolean` | No | Enable view-only mode. Prevents editing and submission. Perfect for order review. |
|
|
48
72
|
|
|
49
|
-
|
|
73
|
+
### Events
|
|
50
74
|
|
|
51
|
-
|
|
52
|
-
| --- | --- | --- |
|
|
53
|
-
| `manifest-loaded` | After the customizer manifest is loaded successfully for the current `productId`. | `ManifestLoadedEventDetail` |
|
|
54
|
-
| `sdk-ready` | After the customizer finishes its initial load and is ready for interaction. | `SdkReadyEventDetail` |
|
|
55
|
-
| `submission:success` | Fires when a submission request succeeds. | `SubmissionSuccessEventDetail` |
|
|
56
|
-
| `submission:failed` | Fires when a submission request fails (API error or network/exception). | `SubmissionFailedEventDetail` |
|
|
57
|
-
| `error` | When the runtime reports an error (invalid config, manifest load failure, asset load failure, or unexpected runtime error). | `ErrorEventDetail` |
|
|
58
|
-
| `closed` | When you call `builder.close()` (the element is removed and listeners are detached). | `undefined` |
|
|
75
|
+
All events can be subscribed using `builder.on(eventName, handler)`.
|
|
59
76
|
|
|
60
|
-
|
|
77
|
+
| Event | When it fires | Payload |
|
|
78
|
+
| -------------------- | -------------------------------------------------------------------------------------------- | ------------------------------ |
|
|
79
|
+
| `manifest-loaded` | After the product manifest loads successfully. | `ManifestLoadedEventDetail` |
|
|
80
|
+
| `sdk-ready` | After the customizer initializes and is ready for interaction. | `SdkReadyEventDetail` |
|
|
81
|
+
| `submission:success` | After a successful submission. | `SubmissionSuccessEventDetail` |
|
|
82
|
+
| `submission:failed` | When submission fails (API error, network issue, or validation error). | `SubmissionFailedEventDetail` |
|
|
83
|
+
| `error` | When a runtime error occurs (invalid config, manifest load failed, asset load failed, etc.). | `ErrorEventDetail` |
|
|
84
|
+
| `closed` | When the customizer is closed via `builder.close()`. | `undefined` |
|
|
61
85
|
|
|
62
|
-
|
|
86
|
+
#### Event Payload Types
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// Fires after manifest is loaded
|
|
90
|
+
interface ManifestLoadedEventDetail {
|
|
91
|
+
productId: string;
|
|
92
|
+
manifestMeta?: {
|
|
93
|
+
version?: string;
|
|
94
|
+
} | null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Fires when SDK is ready for use
|
|
98
|
+
interface SdkReadyEventDetail {
|
|
99
|
+
productId: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Fires on successful submission
|
|
103
|
+
interface SubmissionSuccessEventDetail {
|
|
104
|
+
productId?: string;
|
|
105
|
+
views?: string[]; // Generated views/angles
|
|
106
|
+
submissionNumber: string; // Unique submission identifier
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Fires when submission fails
|
|
110
|
+
interface SubmissionFailedEventDetail {
|
|
111
|
+
productId?: string;
|
|
112
|
+
views?: string[];
|
|
113
|
+
message: string; // Error message
|
|
114
|
+
errors?: string[]; // Detailed error list
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Fires on SDK errors
|
|
118
|
+
interface ErrorEventDetail {
|
|
119
|
+
code: 'INVALID_CONFIG' | 'MANIFEST_LOAD_FAILED' | 'ASSET_LOAD_FAILED' | 'RUNTIME_ERROR';
|
|
120
|
+
message: string;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Event Subscription Example
|
|
63
125
|
|
|
64
126
|
```ts
|
|
65
127
|
import { SDK_EVENTS } from '@pixeasy/customizer';
|
|
66
128
|
|
|
129
|
+
const builder = createPixeasyBuilder();
|
|
130
|
+
|
|
131
|
+
builder.open({
|
|
132
|
+
container: 'pixeasyBuilder',
|
|
133
|
+
apiKey: 'dk_xxx_yyy',
|
|
134
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Subscribe to events
|
|
67
138
|
builder
|
|
68
|
-
.on(SDK_EVENTS.MANIFEST_LOADED, (event) =>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.on(SDK_EVENTS.
|
|
72
|
-
|
|
73
|
-
|
|
139
|
+
.on(SDK_EVENTS.MANIFEST_LOADED, (event) => {
|
|
140
|
+
console.log('Manifest loaded for product:', event.productId);
|
|
141
|
+
})
|
|
142
|
+
.on(SDK_EVENTS.SDK_READY, (event) => {
|
|
143
|
+
console.log('Customizer is ready!', event.productId);
|
|
144
|
+
})
|
|
145
|
+
.on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
|
|
146
|
+
console.log('Submission successful:', event.submissionNumber);
|
|
147
|
+
console.log('Generated views:', event.views);
|
|
148
|
+
})
|
|
149
|
+
.on(SDK_EVENTS.SUBMISSION_FAILED, (event) => {
|
|
150
|
+
console.error('Submission failed:', event.message);
|
|
151
|
+
if (event.errors) {
|
|
152
|
+
console.error('Errors:', event.errors);
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
.on(SDK_EVENTS.ERROR, (event) => {
|
|
156
|
+
console.error(`Error [${event.code}]:`, event.message);
|
|
157
|
+
})
|
|
158
|
+
.on(SDK_EVENTS.CLOSED, () => {
|
|
159
|
+
console.log('Customizer closed');
|
|
160
|
+
});
|
|
74
161
|
```
|
|
75
162
|
|
|
76
|
-
|
|
163
|
+
#### Unsubscribing from Events
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
const handleSuccess = (event) => console.log('Success:', event.submissionNumber);
|
|
167
|
+
|
|
168
|
+
builder.on(SDK_EVENTS.SUBMISSION_SUCCESS, handleSuccess);
|
|
169
|
+
|
|
170
|
+
// Later, remove the listener
|
|
171
|
+
builder.off(SDK_EVENTS.SUBMISSION_SUCCESS, handleSuccess);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Framework Examples
|
|
77
175
|
|
|
78
176
|
### React
|
|
79
177
|
|
|
178
|
+
#### Basic Usage
|
|
179
|
+
|
|
80
180
|
```tsx
|
|
81
181
|
import { useEffect } from 'react';
|
|
82
182
|
import { createPixeasyBuilder } from '@pixeasy/customizer';
|
|
@@ -85,42 +185,293 @@ import '@pixeasy/customizer/styles.css';
|
|
|
85
185
|
export function CustomizerHost() {
|
|
86
186
|
useEffect(() => {
|
|
87
187
|
const builder = createPixeasyBuilder();
|
|
188
|
+
|
|
88
189
|
builder.open({
|
|
89
190
|
container: 'pixeasyBuilder',
|
|
90
191
|
apiKey: 'dk_xxx_yyy',
|
|
91
192
|
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
92
193
|
});
|
|
194
|
+
|
|
195
|
+
return () => builder.close();
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
return <div id="pixeasyBuilder" />;
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### Advanced Usage with Events
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import { useEffect } from 'react';
|
|
206
|
+
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
|
|
207
|
+
import '@pixeasy/customizer/styles.css';
|
|
208
|
+
|
|
209
|
+
export function CustomizerWithEvents() {
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
const builder = createPixeasyBuilder();
|
|
212
|
+
|
|
213
|
+
builder
|
|
214
|
+
.on(SDK_EVENTS.SDK_READY, () => {
|
|
215
|
+
console.log('Customizer ready');
|
|
216
|
+
})
|
|
217
|
+
.on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
|
|
218
|
+
console.log('Submission successful:', event.submissionNumber);
|
|
219
|
+
// Handle success - e.g., show confirmation, redirect, etc.
|
|
220
|
+
})
|
|
221
|
+
.on(SDK_EVENTS.ERROR, (event) => {
|
|
222
|
+
console.error('Error occurred:', event.message);
|
|
223
|
+
})
|
|
224
|
+
.open({
|
|
225
|
+
container: 'pixeasyBuilder',
|
|
226
|
+
apiKey: 'dk_xxx_yyy',
|
|
227
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
228
|
+
locale: 'en',
|
|
229
|
+
theme: 'dark',
|
|
230
|
+
});
|
|
231
|
+
|
|
93
232
|
return () => builder.close();
|
|
94
233
|
}, []);
|
|
95
234
|
|
|
235
|
+
return <div id="pixeasyBuilder" style={{ width: '100%', height: '100vh' }} />;
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Load Existing Submission
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { useEffect } from 'react';
|
|
243
|
+
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
|
|
244
|
+
import '@pixeasy/customizer/styles.css';
|
|
245
|
+
|
|
246
|
+
export function EditSubmission({ submissionNumber }: { submissionNumber: string }) {
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
const builder = createPixeasyBuilder();
|
|
249
|
+
|
|
250
|
+
builder
|
|
251
|
+
.on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
|
|
252
|
+
console.log('Updated submission:', event.submissionNumber);
|
|
253
|
+
})
|
|
254
|
+
.open({
|
|
255
|
+
container: 'pixeasyBuilder',
|
|
256
|
+
apiKey: 'dk_xxx_yyy',
|
|
257
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
258
|
+
submissionNumber: submissionNumber, // Load for editing
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
return () => builder.close();
|
|
262
|
+
}, [submissionNumber]);
|
|
263
|
+
|
|
264
|
+
return <div id="pixeasyBuilder" />;
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### View-Only Mode
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
import { useEffect } from 'react';
|
|
272
|
+
import { createPixeasyBuilder } from '@pixeasy/customizer';
|
|
273
|
+
import '@pixeasy/customizer/styles.css';
|
|
274
|
+
|
|
275
|
+
export function ViewSubmission({ submissionNumber }: { submissionNumber: string }) {
|
|
276
|
+
useEffect(() => {
|
|
277
|
+
const builder = createPixeasyBuilder();
|
|
278
|
+
|
|
279
|
+
builder.open({
|
|
280
|
+
container: 'pixeasyBuilder',
|
|
281
|
+
apiKey: 'dk_xxx_yyy',
|
|
282
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
283
|
+
submissionNumber: submissionNumber,
|
|
284
|
+
readonly: true, // Enable view-only mode
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
return () => builder.close();
|
|
288
|
+
}, [submissionNumber]);
|
|
289
|
+
|
|
96
290
|
return <div id="pixeasyBuilder" />;
|
|
97
291
|
}
|
|
98
292
|
```
|
|
99
293
|
|
|
100
294
|
### Vue
|
|
101
295
|
|
|
296
|
+
#### Basic Usage
|
|
297
|
+
|
|
102
298
|
```ts
|
|
103
299
|
import { onMounted, onBeforeUnmount } from 'vue';
|
|
104
300
|
import { createPixeasyBuilder } from '@pixeasy/customizer';
|
|
105
301
|
import '@pixeasy/customizer/styles.css';
|
|
106
302
|
|
|
107
|
-
|
|
303
|
+
export default {
|
|
304
|
+
setup() {
|
|
305
|
+
const builder = createPixeasyBuilder();
|
|
108
306
|
|
|
109
|
-
onMounted(() => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
307
|
+
onMounted(() => {
|
|
308
|
+
builder.open({
|
|
309
|
+
container: 'pixeasyBuilder',
|
|
310
|
+
apiKey: 'dk_xxx_yyy',
|
|
311
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
onBeforeUnmount(() => builder.close());
|
|
116
316
|
|
|
117
|
-
|
|
317
|
+
return {};
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### With Events and Options
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
import { onMounted, onBeforeUnmount } from 'vue';
|
|
326
|
+
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
|
|
327
|
+
import '@pixeasy/customizer/styles.css';
|
|
328
|
+
|
|
329
|
+
export default {
|
|
330
|
+
props: {
|
|
331
|
+
submissionNumber: [String, null],
|
|
332
|
+
},
|
|
333
|
+
setup(props) {
|
|
334
|
+
const builder = createPixeasyBuilder();
|
|
335
|
+
|
|
336
|
+
onMounted(() => {
|
|
337
|
+
builder
|
|
338
|
+
.on(SDK_EVENTS.SDK_READY, () => {
|
|
339
|
+
console.log('Customizer initialized');
|
|
340
|
+
})
|
|
341
|
+
.on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
|
|
342
|
+
console.log('Saved:', event.submissionNumber);
|
|
343
|
+
})
|
|
344
|
+
.open({
|
|
345
|
+
container: 'pixeasyBuilder',
|
|
346
|
+
apiKey: 'dk_xxx_yyy',
|
|
347
|
+
productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
348
|
+
submissionNumber: props.submissionNumber || undefined,
|
|
349
|
+
locale: 'en',
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
onBeforeUnmount(() => builder.close());
|
|
354
|
+
|
|
355
|
+
return {};
|
|
356
|
+
},
|
|
357
|
+
};
|
|
118
358
|
```
|
|
119
359
|
|
|
120
360
|
## Exports
|
|
121
361
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
362
|
+
The package exports the following:
|
|
363
|
+
|
|
364
|
+
### Classes & Functions
|
|
365
|
+
|
|
366
|
+
- **`createPixeasyBuilder()`** - Factory function to create a new `PixeasyBuilder` instance
|
|
367
|
+
- **`PixeasyBuilder`** - Main class for managing the customizer lifecycle
|
|
368
|
+
- **`definePixeasyCustomizerElement()`** - Registers the `<pixeasy-customizer>` custom element (auto-called internally)
|
|
369
|
+
- **`generateThumbnails()`** - Utility function to generate product thumbnails from SVG and 3D models
|
|
370
|
+
|
|
371
|
+
### Types
|
|
372
|
+
|
|
373
|
+
- **`PixeasyOpenOptions`** - Configuration object for `builder.open()`
|
|
374
|
+
- **`SdkElementConfig`** - Base configuration interface
|
|
375
|
+
- **`ManifestLoadedEventDetail`** - Payload for manifest-loaded event
|
|
376
|
+
- **`SdkReadyEventDetail`** - Payload for sdk-ready event
|
|
377
|
+
- **`SubmissionSuccessEventDetail`** - Payload for submission:success event
|
|
378
|
+
- **`SubmissionFailedEventDetail`** - Payload for submission:failed event
|
|
379
|
+
- **`ErrorEventDetail`** - Payload for error event
|
|
380
|
+
- **`SDK_EVENTS`** - Enum of all available event names
|
|
381
|
+
- **`BuilderEventName`** - Type-safe event name type
|
|
382
|
+
- **`ThumbnailView`** - View types for thumbnail generation ('front' | 'right' | 'back' | 'left')
|
|
383
|
+
- **`GeneratedThumbnail`** - Thumbnail generation result
|
|
384
|
+
|
|
385
|
+
### Stylesheets
|
|
386
|
+
|
|
387
|
+
- **`@pixeasy/customizer/styles.css`** - Required stylesheet (import once in your app)
|
|
388
|
+
|
|
389
|
+
## Common Use Cases
|
|
390
|
+
|
|
391
|
+
### Create a New Design from Scratch
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
builder.open({
|
|
395
|
+
container: 'pixeasyBuilder',
|
|
396
|
+
apiKey: 'dk_xxx_yyy',
|
|
397
|
+
productId: 'product-uuid',
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Use a Template/Predesign
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
builder.open({
|
|
405
|
+
container: 'pixeasyBuilder',
|
|
406
|
+
apiKey: 'dk_xxx_yyy',
|
|
407
|
+
productId: 'product-uuid',
|
|
408
|
+
predesignId: 'predesign-uuid', // Start with a pre-designed template
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Edit an Existing Submission
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
builder.open({
|
|
416
|
+
container: 'pixeasyBuilder',
|
|
417
|
+
apiKey: 'dk_xxx_yyy',
|
|
418
|
+
productId: 'product-uuid',
|
|
419
|
+
submissionNumber: 'SUB-12345', // Load existing submission
|
|
420
|
+
});
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Review Order (Read-Only)
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
builder.open({
|
|
427
|
+
container: 'pixeasyBuilder',
|
|
428
|
+
apiKey: 'dk_xxx_yyy',
|
|
429
|
+
productId: 'product-uuid',
|
|
430
|
+
submissionNumber: 'SUB-12345',
|
|
431
|
+
readonly: true, // Disable editing
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Multi-Language Support
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
builder.open({
|
|
439
|
+
container: 'pixeasyBuilder',
|
|
440
|
+
apiKey: 'dk_xxx_yyy',
|
|
441
|
+
productId: 'product-uuid',
|
|
442
|
+
locale: 'de', // German, or 'fr', 'es', etc.
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Best Practices
|
|
447
|
+
|
|
448
|
+
1. **Always import styles** - Include the CSS stylesheet once in your app:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
import '@pixeasy/customizer/styles.css';
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
2. **Handle errors gracefully** - Always subscribe to the `error` event:
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
builder.on(SDK_EVENTS.ERROR, (event) => {
|
|
458
|
+
console.error(`Error [${event.code}]: ${event.message}`);
|
|
459
|
+
// Show user-friendly error message
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
3. **Validate API key and Product ID** - These are required for the customizer to function:
|
|
464
|
+
|
|
465
|
+
```ts
|
|
466
|
+
if (!apiKey || !productId) {
|
|
467
|
+
throw new Error('Missing required configuration');
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
4. **Clean up on unmount** - Always call `builder.close()` when the component unmounts to prevent memory leaks
|
|
472
|
+
|
|
473
|
+
5. **Use events for flow control** - Subscribe to `submission:success` to handle post-submission actions
|
|
474
|
+
|
|
475
|
+
6. **Handle locale properly** - Set the locale to match user preferences before opening
|
|
476
|
+
|
|
477
|
+
7. **Use readonly mode for reviews** - Enable `readonly: true` when showing past submissions or previews
|
package/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface SdkElementConfig {
|
|
|
2
2
|
apiKey: string;
|
|
3
3
|
productId: string;
|
|
4
4
|
predesignId?: string;
|
|
5
|
+
submissionNumber?: string;
|
|
5
6
|
locale?: string;
|
|
6
7
|
theme?: string;
|
|
7
8
|
readonly?: boolean;
|
|
@@ -52,30 +53,33 @@ export const SDK_EVENTS: {
|
|
|
52
53
|
export type BuilderEventName = (typeof SDK_EVENTS)[keyof typeof SDK_EVENTS];
|
|
53
54
|
export type UrlOrText = { type: 'url'; value: string } | { type: 'text'; value: string };
|
|
54
55
|
|
|
55
|
-
|
|
56
56
|
export class PixeasyBuilder {
|
|
57
57
|
open(options: PixeasyOpenOptions): this;
|
|
58
58
|
on<K extends BuilderEventName>(
|
|
59
59
|
name: K,
|
|
60
|
-
handler: (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
handler: (
|
|
61
|
+
payload: {
|
|
62
|
+
[typeof SDK_EVENTS.MANIFEST_LOADED]: ManifestLoadedEventDetail;
|
|
63
|
+
[typeof SDK_EVENTS.SDK_READY]: SdkReadyEventDetail;
|
|
64
|
+
[typeof SDK_EVENTS.SUBMISSION_SUCCESS]: SubmissionSuccessEventDetail;
|
|
65
|
+
[typeof SDK_EVENTS.SUBMISSION_FAILED]: SubmissionFailedEventDetail;
|
|
66
|
+
[typeof SDK_EVENTS.ERROR]: ErrorEventDetail;
|
|
67
|
+
[typeof SDK_EVENTS.CLOSED]: undefined;
|
|
68
|
+
}[K],
|
|
69
|
+
) => void,
|
|
68
70
|
): this;
|
|
69
71
|
off<K extends BuilderEventName>(
|
|
70
72
|
name: K,
|
|
71
|
-
handler: (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
handler: (
|
|
74
|
+
payload: {
|
|
75
|
+
[typeof SDK_EVENTS.MANIFEST_LOADED]: ManifestLoadedEventDetail;
|
|
76
|
+
[typeof SDK_EVENTS.SDK_READY]: SdkReadyEventDetail;
|
|
77
|
+
[typeof SDK_EVENTS.SUBMISSION_SUCCESS]: SubmissionSuccessEventDetail;
|
|
78
|
+
[typeof SDK_EVENTS.SUBMISSION_FAILED]: SubmissionFailedEventDetail;
|
|
79
|
+
[typeof SDK_EVENTS.ERROR]: ErrorEventDetail;
|
|
80
|
+
[typeof SDK_EVENTS.CLOSED]: undefined;
|
|
81
|
+
}[K],
|
|
82
|
+
) => void,
|
|
79
83
|
): this;
|
|
80
84
|
close(): this;
|
|
81
85
|
}
|