@webpros/tsxuserprofilevue 3.5.2 → 3.5.3

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/USAGE_GUIDE.md ADDED
@@ -0,0 +1,659 @@
1
+ # TSXUserProfile Component - Usage Guide
2
+
3
+ ## Overview
4
+
5
+ TSXUserProfile is a Vue 3 web component for managing user profiles and licenses. It can be embedded in any web application and communicates via events.
6
+
7
+ ## Installation
8
+
9
+ ### NPM
10
+ ```bash
11
+ npm install @webpros/tsxuserprofilevue
12
+ ```
13
+
14
+ ### CDN
15
+ ```html
16
+ <script type="module" crossorigin src="https://unpkg.com/@webpros/tsxuserprofilevue/dist/index.js"></script>
17
+ <link rel="stylesheet" href="https://unpkg.com/@webpros/tsxuserprofilevue/dist/tsxUserProfile.css">
18
+ ```
19
+
20
+ ## Basic Usage
21
+
22
+ ### HTML
23
+ ```html
24
+ <tsx-user-profile
25
+ base-api-url="https://api.example.com"
26
+ current-language="en"
27
+ user-data='{"email":"user@example.com","firstName":"John","familyName":"Doe","timezone":"America/New_York"}'
28
+ token="your-auth-token"
29
+ ></tsx-user-profile>
30
+ ```
31
+
32
+ ### Vue 3
33
+ ```vue
34
+ <script setup>
35
+ import '@webpros/tsxuserprofilevue'
36
+
37
+ const userData = {
38
+ email: 'user@example.com',
39
+ firstName: 'John',
40
+ familyName: 'Doe',
41
+ timezone: 'America/New_York',
42
+ gravatar: 'https://www.gravatar.com/avatar/...',
43
+ nixstatsId: '12345',
44
+ threeSixtyId: '67890'
45
+ }
46
+ </script>
47
+
48
+ <template>
49
+ <tsx-user-profile
50
+ base-api-url="https://api.example.com"
51
+ :user-data="JSON.stringify(userData)"
52
+ current-language="en"
53
+ token="your-auth-token"
54
+ />
55
+ </template>
56
+ ```
57
+
58
+ ### React
59
+ ```jsx
60
+ import '@webpros/tsxuserprofilevue'
61
+
62
+ function UserProfile() {
63
+ const userData = {
64
+ email: 'user@example.com',
65
+ firstName: 'John',
66
+ familyName: 'Doe',
67
+ timezone: 'America/New_York'
68
+ }
69
+
70
+ return (
71
+ <tsx-user-profile
72
+ base-api-url="https://api.example.com"
73
+ user-data={JSON.stringify(userData)}
74
+ current-language="en"
75
+ token="your-auth-token"
76
+ />
77
+ )
78
+ }
79
+ ```
80
+
81
+ ## Component Props
82
+
83
+ ### Required Props
84
+
85
+ | Prop | Type | Description |
86
+ |------|------|-------------|
87
+ | `base-api-url` | String | **Required**. Base URL for API calls |
88
+
89
+ ### Optional Props
90
+
91
+ | Prop | Type | Default | Description |
92
+ |------|------|---------|-------------|
93
+ | `current-language` | String | `'en'` | Language code: `'de'`, `'en'`, `'fr'`, `'es'`, `'it'`, `'ja'`, `'ru'`, `'pt'` |
94
+ | `user-data` | String (JSON) | `'{}'` | User information as JSON string (see User Data Structure) |
95
+ | `view` | String | `'profile'` | View type: `'profile'` or `'license'` |
96
+ | `token` | String | `''` | Authentication token for API requests |
97
+ | `read-only` | Boolean/String | `false` | Makes the component read-only (no editing) |
98
+ | `off-canvas` | Boolean | `false` | Display as off-canvas sidebar instead of inline |
99
+ | `open-canvas` | Boolean | `false` | Initial state of off-canvas (open/closed) |
100
+ | `partner-type` | String | `''` | Partner type: `'standaloneRetail'`, `'standalonePartner'`, `'whitelabel'`, `'platform'`, `'partner'` |
101
+ | `is-license-partner` | Boolean | `false` | Whether user is a license partner |
102
+ | `extra-inactive-fields` | String (JSON) | `'[]'` | Additional fields to hide (JSON array string) |
103
+ | `locale-saving-url` | String | `''` | URL endpoint for saving language preferences |
104
+ | `override-base-api-url` | String | `''` | Override the base API URL for specific requests |
105
+ | `complete-upsell-url` | String | `''` | URL for license upsell/purchase flow |
106
+
107
+ ## User Data Structure
108
+
109
+ The `user-data` prop accepts a JSON string with the following structure:
110
+
111
+ ```typescript
112
+ interface IProfileUser {
113
+ // Basic Information
114
+ email?: string // User's email address
115
+ firstName?: string // User's first name
116
+ familyName?: string // User's last name
117
+ name?: string // Full name (alternative to firstName/familyName)
118
+ nickname?: string // User's nickname
119
+
120
+ // Avatar
121
+ gravatar?: string // Gravatar URL or email hash
122
+
123
+ // System Information
124
+ timezone?: string | null // IANA timezone (e.g., 'America/New_York')
125
+ nixstatsId?: string // Nixstats user ID
126
+ threeSixtyId?: string // 360 Monitoring user ID
127
+
128
+ // Authentication
129
+ sessionToken?: string // Session token
130
+ isOauthUser?: boolean // Whether user authenticated via OAuth
131
+
132
+ // Permissions
133
+ isDeletable?: boolean // Whether account can be deleted
134
+ }
135
+ ```
136
+
137
+ ### Example User Data
138
+
139
+ ```javascript
140
+ const userData = {
141
+ email: 'john.doe@example.com',
142
+ firstName: 'John',
143
+ familyName: 'Doe',
144
+ nickname: 'johnd',
145
+ gravatar: 'https://www.gravatar.com/avatar/1e45f0572fb68149199a0acb56ccc3dc',
146
+ timezone: 'Europe/Berlin',
147
+ nixstatsId: '12345',
148
+ threeSixtyId: '67890',
149
+ isOauthUser: false,
150
+ isDeletable: true
151
+ }
152
+
153
+ // Pass as JSON string
154
+ <tsx-user-profile user-data={JSON.stringify(userData)} />
155
+ ```
156
+
157
+ ### Important Notes
158
+
159
+ - **All fields are optional**
160
+ - If `timezone` is not provided, the component will use the browser's timezone
161
+ - If `gravatar` is an email, it will be converted to a Gravatar URL automatically
162
+ - If `isDeletable` is `false`, the "Remove Account" option will be hidden
163
+
164
+ ## Inactive Fields Configuration
165
+
166
+ You can hide specific sections of the profile using the `extra-inactive-fields` prop and automatic hiding based on `partner-type`.
167
+
168
+ ### Available Fields to Hide
169
+
170
+ - `naming` - Name editing section
171
+ - `ids` - User IDs display (nixstatsId, threeSixtyId)
172
+ - `password` - Password change section
173
+ - `language` - Language selector
174
+ - `timezone` - Timezone selector
175
+ - `consent` - Consent/privacy settings
176
+ - `dnt` - Do Not Track settings
177
+ - `removeAccount` - Account deletion option
178
+ - `comparePlansLink` - Compare plans link (license view)
179
+
180
+ ### Automatic Hiding by Partner Type
181
+
182
+ Different partner types automatically hide certain fields:
183
+
184
+ ```typescript
185
+ // Partner Type Configurations
186
+ {
187
+ 'standaloneRetail': [], // No fields hidden
188
+ 'standalonePartner': ['consent', 'comparePlansLink'],
189
+ 'whitelabel': ['naming', 'password', 'consent'],
190
+ 'platform': ['naming', 'password', 'consent'],
191
+ 'partner': ['consent', 'comparePlansLink']
192
+ }
193
+ ```
194
+
195
+ ### Manual Configuration
196
+
197
+ Use `extra-inactive-fields` to hide additional fields:
198
+
199
+ ```html
200
+ <!-- Hide password and timezone fields -->
201
+ <tsx-user-profile
202
+ base-api-url="https://api.example.com"
203
+ user-data='{"email":"user@example.com"}'
204
+ extra-inactive-fields='["password", "timezone"]'
205
+ />
206
+ ```
207
+
208
+ ### Combined Example
209
+
210
+ ```html
211
+ <!-- Partner type hides some fields, extra-inactive-fields adds more -->
212
+ <tsx-user-profile
213
+ base-api-url="https://api.example.com"
214
+ partner-type="whitelabel"
215
+ extra-inactive-fields='["language", "ids"]'
216
+ />
217
+ <!-- This will hide: naming, password, consent (from whitelabel) + language, ids (from extra) -->
218
+ ```
219
+
220
+ ## Event Handling
221
+
222
+ The component uses [MITT](https://github.com/developit/mitt) for event communication. All user interactions emit events that you can listen to.
223
+
224
+ ### Setting Up Event Listeners
225
+
226
+ ```javascript
227
+ // Listen to all TSXUserProfile events
228
+ window.mitt.on('tsxUserProfile', (payload) => {
229
+ console.log('Event received:', payload)
230
+
231
+ switch(payload.action) {
232
+ case 'updateTimezone':
233
+ console.log('Timezone changed to:', payload.data)
234
+ // Save to your backend
235
+ break
236
+ case 'updateName':
237
+ console.log('Name changed:', payload.data)
238
+ break
239
+ case 'updatePassword':
240
+ console.log('Password change requested')
241
+ break
242
+ // ... handle other events
243
+ }
244
+ })
245
+ ```
246
+
247
+ ### Available Events
248
+
249
+ | Event Action | Payload Data | Description |
250
+ |-------------|--------------|-------------|
251
+ | `updateTimezone` | `string` | User changed timezone |
252
+ | `updateName` | `{firstName: string, familyName: string}` | User updated name |
253
+ | `updatePassword` | `{oldPassword: string, newPassword: string}` | Password change request |
254
+ | `updateLanguage` | `string` | Language changed |
255
+ | `deleteAccount` | `{}` | Account deletion requested |
256
+ | `updateConsent` | `boolean` | Consent settings changed |
257
+ | `updateDnt` | `boolean` | Do Not Track setting changed |
258
+
259
+ ### Event Example
260
+
261
+ ```javascript
262
+ // Initialize MITT if not already done
263
+ window.mitt = window.mitt || mitt()
264
+
265
+ // Listen for timezone changes
266
+ window.mitt.on('tsxUserProfile', (payload) => {
267
+ if (payload.action === 'updateTimezone') {
268
+ // Send to your API
269
+ fetch('/api/user/timezone', {
270
+ method: 'POST',
271
+ headers: { 'Content-Type': 'application/json' },
272
+ body: JSON.stringify({ timezone: payload.data })
273
+ })
274
+ }
275
+ })
276
+ ```
277
+
278
+ ## Styling and Theming
279
+
280
+ The component uses CSS custom properties (variables) for theming. Define these in your stylesheet:
281
+
282
+ ```css
283
+ :root {
284
+ /* Base Colors */
285
+ --tsxup-brightest: #ffffff;
286
+ --tsxup-brightest-darker: #e5e7eb;
287
+ --tsxup-darkest: #111827;
288
+ --tsxup-darkest-light: #4b5563;
289
+
290
+ /* Signal Colors */
291
+ --tsxup-signal-success: #4CA154;
292
+ --tsxup-signal-error: #b73737;
293
+
294
+ /* Brand Colors */
295
+ --tsxup-primary: #1E40AF;
296
+ --tsxup-primary-light: #668bca;
297
+
298
+ /* Text */
299
+ --tsxup-text: var(--tsxup-darkest);
300
+ --tsxup-text-lighter: var(--tsxup-darkest-light);
301
+ --tsxup-headline: var(--tsxup-darkest);
302
+
303
+ /* Buttons */
304
+ --tsxUp-button-color: var(--tsxup-brightest);
305
+ --tsxUp-button-bg: var(--tsxup-primary);
306
+ --tsxUp-button-color-hover: var(--tsxup-brightest);
307
+ --tsxUp-button-bg-hover: var(--tsxup-primary-light);
308
+
309
+ /* Select Fields */
310
+ --tsxUp-selectField-border: var(--tsxup-brightest-darker);
311
+ --tsxUp-selectField-background: var(--tsxup-brightest);
312
+ --tsxUp-selectField-backgroundHover: var(--tsxup-brightest);
313
+ --tsxUp-selectField-backgroundDisabled: var(--tsxup-brightest-darker);
314
+ --tsxUp-selectField-color: var(--tsxup-darkest);
315
+ --tsxUp-selectField-selectedBackground: var(--tsxup-primary-light);
316
+ --tsxUp-selectField-selectedColor: var(--tsxup-brightest);
317
+ }
318
+ ```
319
+
320
+ ### Dark Mode Example
321
+
322
+ ```css
323
+ @media (prefers-color-scheme: dark) {
324
+ :root {
325
+ --tsxup-brightest: #1f2937;
326
+ --tsxup-brightest-darker: #374151;
327
+ --tsxup-darkest: #f9fafb;
328
+ --tsxup-darkest-light: #d1d5db;
329
+ --tsxup-text: var(--tsxup-darkest);
330
+ --tsxup-headline: var(--tsxup-darkest);
331
+ }
332
+ }
333
+ ```
334
+
335
+ ## Advanced Usage Examples
336
+
337
+ ### Off-Canvas Sidebar Mode
338
+
339
+ Display the profile as a sliding sidebar panel:
340
+
341
+ ```html
342
+ <tsx-user-profile
343
+ base-api-url="https://api.example.com"
344
+ user-data='{"email":"user@example.com","firstName":"John"}'
345
+ off-canvas="true"
346
+ open-canvas="false"
347
+ view="profile"
348
+ token="your-token"
349
+ />
350
+ ```
351
+
352
+ Control the canvas programmatically:
353
+
354
+ ```javascript
355
+ // Open the canvas
356
+ window.mitt.emit('openCanvas', { view: 'profile' })
357
+
358
+ // Close the canvas
359
+ window.mitt.emit('closeCanvas')
360
+
361
+ // Switch to license view
362
+ window.mitt.emit('openCanvas', { view: 'license' })
363
+ ```
364
+
365
+ ### License Management View
366
+
367
+ Display license and subscription information:
368
+
369
+ ```html
370
+ <tsx-user-profile
371
+ base-api-url="https://api.example.com"
372
+ view="license"
373
+ read-only="false"
374
+ complete-upsell-url="https://example.com/upsell"
375
+ token="your-token"
376
+ />
377
+ ```
378
+
379
+ ### Read-Only Profile
380
+
381
+ Display user information without editing capabilities:
382
+
383
+ ```html
384
+ <tsx-user-profile
385
+ base-api-url="https://api.example.com"
386
+ user-data='{"email":"user@example.com","firstName":"John","familyName":"Doe"}'
387
+ read-only="true"
388
+ extra-inactive-fields='["password", "removeAccount"]'
389
+ />
390
+ ```
391
+
392
+ ### Multi-Language Support
393
+
394
+ ```html
395
+ <!-- German -->
396
+ <tsx-user-profile
397
+ base-api-url="https://api.example.com"
398
+ current-language="de"
399
+ user-data='{"email":"benutzer@beispiel.de"}'
400
+ />
401
+
402
+ <!-- French -->
403
+ <tsx-user-profile
404
+ base-api-url="https://api.example.com"
405
+ current-language="fr"
406
+ user-data='{"email":"utilisateur@exemple.fr"}'
407
+ />
408
+ ```
409
+
410
+ Supported languages: `de`, `en`, `fr`, `es`, `it`, `ja`, `ru`, `pt`
411
+
412
+ ### Complete Integration Example
413
+
414
+ ```html
415
+ <!DOCTYPE html>
416
+ <html lang="en">
417
+ <head>
418
+ <meta charset="UTF-8">
419
+ <title>User Profile</title>
420
+ <script type="module" src="https://unpkg.com/@webpros/tsxuserprofilevue/dist/index.js"></script>
421
+ <link rel="stylesheet" href="https://unpkg.com/@webpros/tsxuserprofilevue/dist/tsxUserProfile.css">
422
+ <style>
423
+ :root {
424
+ --tsxup-primary: #0066cc;
425
+ --tsxup-primary-light: #3399ff;
426
+ }
427
+ .profile-container {
428
+ max-width: 800px;
429
+ margin: 0 auto;
430
+ padding: 20px;
431
+ }
432
+ </style>
433
+ </head>
434
+ <body>
435
+ <div class="profile-container">
436
+ <h1>My Profile</h1>
437
+ <tsx-user-profile
438
+ id="userProfile"
439
+ base-api-url="https://api.example.com"
440
+ current-language="en"
441
+ token="your-auth-token"
442
+ />
443
+ </div>
444
+
445
+ <script type="module">
446
+ import mitt from 'https://unpkg.com/mitt/dist/mitt.mjs'
447
+
448
+ // Initialize MITT
449
+ window.mitt = window.mitt || mitt()
450
+
451
+ // Fetch user data from your API
452
+ async function loadUserData() {
453
+ const response = await fetch('https://api.example.com/user/profile', {
454
+ headers: { 'Authorization': 'Bearer your-auth-token' }
455
+ })
456
+ const userData = await response.json()
457
+
458
+ // Set user data on component
459
+ const profile = document.getElementById('userProfile')
460
+ profile.setAttribute('user-data', JSON.stringify(userData))
461
+ }
462
+
463
+ // Handle events
464
+ window.mitt.on('tsxUserProfile', async (payload) => {
465
+ console.log('Event:', payload)
466
+
467
+ // Save changes to your API
468
+ if (payload.action === 'updateTimezone') {
469
+ await fetch('https://api.example.com/user/timezone', {
470
+ method: 'POST',
471
+ headers: {
472
+ 'Authorization': 'Bearer your-auth-token',
473
+ 'Content-Type': 'application/json'
474
+ },
475
+ body: JSON.stringify({ timezone: payload.data })
476
+ })
477
+ }
478
+
479
+ if (payload.action === 'updateName') {
480
+ await fetch('https://api.example.com/user/name', {
481
+ method: 'POST',
482
+ headers: {
483
+ 'Authorization': 'Bearer your-auth-token',
484
+ 'Content-Type': 'application/json'
485
+ },
486
+ body: JSON.stringify(payload.data)
487
+ })
488
+ }
489
+ })
490
+
491
+ // Load user data on page load
492
+ loadUserData()
493
+ </script>
494
+ </body>
495
+ </html>
496
+ ```
497
+
498
+ ## Framework-Specific Integration
499
+
500
+ ### Vue 3 / Nuxt 3
501
+
502
+ ```vue
503
+ <script setup>
504
+ import { ref, onMounted } from 'vue'
505
+ import '@webpros/tsxuserprofilevue'
506
+ import mitt from 'mitt'
507
+
508
+ // Initialize MITT
509
+ if (!window.mitt) {
510
+ window.mitt = mitt()
511
+ }
512
+
513
+ const userData = ref({
514
+ email: 'user@example.com',
515
+ firstName: 'John',
516
+ familyName: 'Doe',
517
+ timezone: 'America/New_York'
518
+ })
519
+
520
+ onMounted(() => {
521
+ window.mitt.on('tsxUserProfile', (payload) => {
522
+ console.log('Profile event:', payload)
523
+ // Handle events
524
+ })
525
+ })
526
+ </script>
527
+
528
+ <template>
529
+ <div class="profile-wrapper">
530
+ <tsx-user-profile
531
+ base-api-url="https://api.example.com"
532
+ :user-data="JSON.stringify(userData)"
533
+ current-language="en"
534
+ token="your-token"
535
+ />
536
+ </div>
537
+ </template>
538
+ ```
539
+
540
+ ### React / Next.js
541
+
542
+ ```jsx
543
+ import { useEffect, useRef } from 'react'
544
+ import '@webpros/tsxuserprofilevue'
545
+ import mitt from 'mitt'
546
+
547
+ export default function UserProfile() {
548
+ const userData = {
549
+ email: 'user@example.com',
550
+ firstName: 'John',
551
+ familyName: 'Doe',
552
+ timezone: 'America/New_York'
553
+ }
554
+
555
+ useEffect(() => {
556
+ // Initialize MITT
557
+ if (!window.mitt) {
558
+ window.mitt = mitt()
559
+ }
560
+
561
+ // Event listener
562
+ const handleEvent = (payload) => {
563
+ console.log('Profile event:', payload)
564
+ // Handle events
565
+ }
566
+
567
+ window.mitt.on('tsxUserProfile', handleEvent)
568
+
569
+ return () => {
570
+ window.mitt.off('tsxUserProfile', handleEvent)
571
+ }
572
+ }, [])
573
+
574
+ return (
575
+ <div className="profile-wrapper">
576
+ <tsx-user-profile
577
+ base-api-url="https://api.example.com"
578
+ user-data={JSON.stringify(userData)}
579
+ current-language="en"
580
+ token="your-token"
581
+ />
582
+ </div>
583
+ )
584
+ }
585
+ ```
586
+
587
+ ## Troubleshooting
588
+
589
+ ### Component Not Rendering
590
+
591
+ 1. **Check if the script is loaded**: Verify the component script is included
592
+ 2. **Check user-data format**: Must be a valid JSON string
593
+ 3. **Check base-api-url**: This prop is required
594
+
595
+ ### Events Not Firing
596
+
597
+ 1. **Initialize MITT**: Ensure `window.mitt` is initialized before the component loads
598
+ 2. **Check event listener**: Make sure you're listening to `'tsxUserProfile'` events
599
+
600
+ ### Styling Issues
601
+
602
+ 1. **CSS Variables**: Ensure CSS variables are defined in your stylesheet
603
+ 2. **CSS Import**: Import the component's CSS file
604
+ 3. **Wrapper Styling**: Add custom styling via a wrapper div
605
+
606
+ ### TypeScript Support
607
+
608
+ ```typescript
609
+ // Type definitions for user data
610
+ interface IProfileUser {
611
+ email?: string
612
+ firstName?: string
613
+ familyName?: string
614
+ name?: string
615
+ nickname?: string
616
+ gravatar?: string
617
+ timezone?: string | null
618
+ nixstatsId?: string
619
+ threeSixtyId?: string
620
+ sessionToken?: string
621
+ isOauthUser?: boolean
622
+ isDeletable?: boolean
623
+ }
624
+
625
+ // Event payload type
626
+ interface TSXUserProfileEvent {
627
+ action: string
628
+ data: any
629
+ }
630
+
631
+ // Usage
632
+ const userData: IProfileUser = {
633
+ email: 'user@example.com',
634
+ firstName: 'John',
635
+ familyName: 'Doe'
636
+ }
637
+ ```
638
+
639
+ ## API Requirements
640
+
641
+ The component expects certain API endpoints to be available at the `base-api-url`:
642
+
643
+ - `GET /user/profile` - Fetch user profile data
644
+ - `POST /user/timezone` - Update timezone
645
+ - `POST /user/name` - Update name
646
+ - `POST /user/password` - Change password
647
+ - `GET /licenses` - Fetch license information (for license view)
648
+ - `GET /plans` - Fetch available subscription plans
649
+
650
+ Ensure your backend implements these endpoints or use the event system to handle data persistence.
651
+
652
+ ## License
653
+
654
+ MIT
655
+
656
+ ## Support
657
+
658
+ For issues and questions, please visit the [GitHub repository](https://github.com/leankoala-gmbh/tsxuserprofilevue).
659
+