@metrifox/angular-sdk 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Metrifox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,487 @@
1
+ # @metrifox/angular-sdk
2
+
3
+ A fully-configurable **Angular SDK** providing ready-to-use components for SaaS and billing platforms including customer portals, pricing tables, and more.
4
+
5
+ This is the official Angular version of the Metrifox SDK, mirroring the functionality of [@metrifox/react-sdk](https://www.npmjs.com/package/@metrifox/react-sdk).
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@metrifox/angular-sdk.svg)](https://www.npmjs.com/package/@metrifox/angular-sdk)
8
+ [![license](https://img.shields.io/npm/l/@metrifox/angular-sdk.svg)](https://github.com/metrifox/metrifox-angular-sdk/blob/main/LICENSE)
9
+
10
+ ## Features
11
+
12
+ - 🎨 **Fully Customizable** - Extensive theming support to match your brand
13
+ - 📦 **Standalone Components** - Modern Angular standalone components (no NgModule required)
14
+ - 🔥 **TypeScript** - Full type safety with comprehensive TypeScript definitions
15
+ - 🚀 **Easy Integration** - Simple setup with minimal configuration
16
+ - 📱 **Responsive** - Mobile-friendly components out of the box
17
+ - ♿ **Accessible** - WCAG compliant components
18
+ - 🌙 **Dark Mode** - Built-in dark mode support
19
+ - ⚡ **Tree-shakeable** - Only import what you need
20
+
21
+ ## Requirements
22
+
23
+ - Angular 17.0.0 or higher (compatible with Angular 17, 18, and 19)
24
+ - RxJS 7.0.0 or higher
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ # Using pnpm (recommended)
30
+ pnpm add @metrifox/angular-sdk
31
+
32
+ # Using npm
33
+ npm install @metrifox/angular-sdk
34
+
35
+ # Using yarn
36
+ yarn add @metrifox/angular-sdk
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ### 1. Provide the SDK (required for components)
42
+
43
+ For standalone apps that use `<metrifox-customer-portal>` or `<metrifox-pricing-table>`, register the SDK in your app config so the components can inject `MetrifoxService`:
44
+
45
+ ```typescript
46
+ // app.config.ts (Standalone)
47
+ import { ApplicationConfig } from "@angular/core";
48
+ import { provideMetrifox } from "@metrifox/angular-sdk";
49
+
50
+ export const appConfig: ApplicationConfig = {
51
+ providers: [
52
+ provideMetrifox(), // provides HttpClient + MetrifoxService
53
+ ],
54
+ };
55
+ ```
56
+
57
+ ### 2. Initialize the SDK
58
+
59
+ Initialize Metrifox before using any components (e.g. in your root component’s `ngOnInit` or in a guard):
60
+
61
+ ```typescript
62
+ import { MetrifoxService } from "@metrifox/angular-sdk";
63
+
64
+ MetrifoxService.initialize({
65
+ clientKey: "your-metrifox-client-key",
66
+ });
67
+ ```
68
+
69
+ Or using the module approach:
70
+
71
+ ```typescript
72
+ // app.module.ts
73
+ import { MetrifoxModule } from "@metrifox/angular-sdk";
74
+
75
+ @NgModule({
76
+ imports: [
77
+ MetrifoxModule.forRoot({
78
+ clientKey: "your-metrifox-client-key",
79
+ }),
80
+ ],
81
+ })
82
+ export class AppModule {}
83
+ ```
84
+
85
+ ### 3. Import Styles
86
+
87
+ Add the SDK styles to your `angular.json`:
88
+
89
+ ```json
90
+ {
91
+ "styles": ["src/styles.css", "node_modules/@metrifox/angular-sdk/styles.css"]
92
+ }
93
+ ```
94
+
95
+ Or import in your global `styles.css`:
96
+
97
+ ```css
98
+ @import "@metrifox/angular-sdk/styles.css";
99
+ ```
100
+
101
+ ### 4. Use Components
102
+
103
+ ```typescript
104
+ import { Component } from "@angular/core";
105
+ import { CustomerPortalComponent } from "@metrifox/angular-sdk";
106
+
107
+ @Component({
108
+ selector: "app-billing",
109
+ standalone: true,
110
+ imports: [CustomerPortalComponent],
111
+ template: ` <metrifox-customer-portal [customerKey]="'cust_123'" /> `,
112
+ })
113
+ export class BillingComponent {}
114
+ ```
115
+
116
+ ## Components
117
+
118
+ ### CustomerPortal
119
+
120
+ Displays a customizable customer dashboard with plans, subscriptions, billing, and more.
121
+
122
+ ```typescript
123
+ import { CustomerPortalComponent, SectionConfig } from "@metrifox/angular-sdk";
124
+
125
+ @Component({
126
+ standalone: true,
127
+ imports: [CustomerPortalComponent],
128
+ template: `
129
+ <metrifox-customer-portal
130
+ [customerKey]="customerKey"
131
+ [sectionsConfig]="sections"
132
+ (dataLoaded)="onDataLoaded($event)"
133
+ (error)="onError($event)"
134
+ >
135
+ </metrifox-customer-portal>
136
+ `,
137
+ })
138
+ export class MyComponent {
139
+ customerKey = "cust_123";
140
+
141
+ sections: SectionConfig[] = [
142
+ { key: "subscription" },
143
+ { key: "plan" },
144
+ { key: "upcomingInvoice" },
145
+ { key: "billingHistory" },
146
+ { key: "paymentOverview" },
147
+ { key: "entitlementUsage" },
148
+ { key: "walletBalance" },
149
+ ];
150
+
151
+ onDataLoaded(data: CustomerData) {
152
+ console.log("Customer data loaded:", data);
153
+ }
154
+
155
+ onError(error: MetrifoxErrorEvent) {
156
+ console.error("Error:", error);
157
+ }
158
+ }
159
+ ```
160
+
161
+ #### CustomerPortal Inputs
162
+
163
+ | Property | Type | Required | Description |
164
+ | ---------------- | ----------------- | -------- | ---------------------------------- |
165
+ | `customerKey` | `string` | Yes | Unique identifier for the customer |
166
+ | `sectionsConfig` | `SectionConfig[]` | No | Configuration for portal sections |
167
+
168
+ #### CustomerPortal Outputs
169
+
170
+ | Event | Type | Description |
171
+ | ------------ | -------------------- | ------------------------------------ |
172
+ | `dataLoaded` | `CustomerData` | Emitted when customer data is loaded |
173
+ | `error` | `MetrifoxErrorEvent` | Emitted when an error occurs |
174
+
175
+ #### Available Sections
176
+
177
+ - `subscription` - Active subscription overview
178
+ - `plan` - Current plan details
179
+ - `upcomingInvoice` - Next invoice details
180
+ - `billingHistory` - List of past transactions
181
+ - `paymentOverview` - Payment methods
182
+ - `entitlementUsage` - Feature/resource usage
183
+ - `walletBalance` - Credit/wallet balance
184
+
185
+ ### PricingTable
186
+
187
+ Displays subscription plans and one-time purchases.
188
+
189
+ ```typescript
190
+ import { PricingTableComponent, PlanSelectEvent } from "@metrifox/angular-sdk";
191
+
192
+ @Component({
193
+ standalone: true,
194
+ imports: [PricingTableComponent],
195
+ template: `
196
+ <metrifox-pricing-table
197
+ [checkoutUsername]="username"
198
+ [productKey]="productKey"
199
+ [plansOnly]="false"
200
+ [showTabHeader]="true"
201
+ (planSelected)="onPlanSelect($event)"
202
+ (purchaseSelected)="onPurchaseSelect($event)"
203
+ >
204
+ </metrifox-pricing-table>
205
+ `,
206
+ })
207
+ export class PricingComponent {
208
+ username = "your-checkout-username";
209
+ productKey = "your-product-key";
210
+
211
+ onPlanSelect(event: PlanSelectEvent) {
212
+ console.log("Plan selected:", event.plan);
213
+ console.log("Action:", event.action); // 'upgrade' | 'downgrade' | 'new' | 'current'
214
+ }
215
+
216
+ onPurchaseSelect(event: PurchaseSelectEvent) {
217
+ console.log("Purchase selected:", event.purchase);
218
+ }
219
+ }
220
+ ```
221
+
222
+ #### PricingTable Inputs
223
+
224
+ | Property | Type | Required | Default | Description |
225
+ | --------------------- | --------- | -------- | ------- | -------------------------------------------- |
226
+ | `checkoutUsername` | `string` | Yes | - | Username for checkout |
227
+ | `productKey` | `string` | Yes | - | Product identifier |
228
+ | `plansOnly` | `boolean` | No | `false` | Show only subscription plans |
229
+ | `singlePurchasesOnly` | `boolean` | No | `false` | Show only one-time purchases |
230
+ | `showTabHeader` | `boolean` | No | `true` | Show tab header for switching |
231
+ | `customerKey` | `string` | No | - | Current customer (to highlight current plan) |
232
+
233
+ #### PricingTable Outputs
234
+
235
+ | Event | Type | Description |
236
+ | ------------------ | --------------------- | ----------------------------------- |
237
+ | `planSelected` | `PlanSelectEvent` | Emitted when a plan is selected |
238
+ | `purchaseSelected` | `PurchaseSelectEvent` | Emitted when a purchase is selected |
239
+ | `dataLoaded` | `PricingData` | Emitted when pricing data is loaded |
240
+ | `error` | `MetrifoxErrorEvent` | Emitted when an error occurs |
241
+
242
+ ## Theming
243
+
244
+ Configure themes during initialization:
245
+
246
+ ```typescript
247
+ import { MetrifoxService, MetrifoxTheme } from "@metrifox/angular-sdk";
248
+
249
+ const theme: MetrifoxTheme = {
250
+ customerPortal: {
251
+ tabs: {
252
+ background: "#111827",
253
+ borderColor: "#243044",
254
+ activeBackground: "#1f2937",
255
+ activeTextColor: "#3b82f6",
256
+ inactiveTextColor: "#9ca3af",
257
+ },
258
+ card: {
259
+ titleBackground: "#1f2937",
260
+ contentBackground: "#111827",
261
+ titleColor: "#f9fafb",
262
+ details: {
263
+ labelColor: "#cbd5e1",
264
+ valueColor: "#ffffff",
265
+ },
266
+ },
267
+ button: {
268
+ background: "#3b82f6",
269
+ textColor: "#ffffff",
270
+ },
271
+ },
272
+ pricingTable: {
273
+ card: {
274
+ background: "#ffffff",
275
+ borderColor: "#e5e7eb",
276
+ header: {
277
+ textColor: "#111827",
278
+ },
279
+ price: {
280
+ amountColor: "#111827",
281
+ },
282
+ },
283
+ button: {
284
+ background: "#2563eb",
285
+ textColor: "#ffffff",
286
+ },
287
+ },
288
+ };
289
+
290
+ MetrifoxService.initialize({
291
+ clientKey: "your-client-key",
292
+ theme,
293
+ });
294
+ ```
295
+
296
+ ### Dark Mode
297
+
298
+ The SDK supports dark mode out of the box:
299
+
300
+ 1. **Automatic** - Follows system preference (`prefers-color-scheme: dark`)
301
+ 2. **Manual** - Add `metrifox-dark` class or `data-theme="dark"` attribute
302
+
303
+ ```html
304
+ <!-- Manual dark mode -->
305
+ <div class="metrifox-dark">
306
+ <metrifox-customer-portal [customerKey]="key" />
307
+ </div>
308
+ ```
309
+
310
+ ## Using the Service Directly
311
+
312
+ Access Metrifox APIs programmatically:
313
+
314
+ ```typescript
315
+ import { Component, inject } from '@angular/core';
316
+ import { MetrifoxService } from '@metrifox/angular-sdk';
317
+
318
+ @Component({ ... })
319
+ export class MyComponent {
320
+ private metrifoxService = inject(MetrifoxService);
321
+
322
+ loadCustomer() {
323
+ this.metrifoxService.getCustomerData('cust_123').subscribe({
324
+ next: (data) => console.log('Customer:', data),
325
+ error: (err) => console.error('Error:', err)
326
+ });
327
+ }
328
+
329
+ updateSubscription() {
330
+ this.metrifoxService.updateSubscription('cust_123', {
331
+ planId: 'plan_pro',
332
+ proration: 'create_prorations'
333
+ }).subscribe({
334
+ next: (result) => {
335
+ if (result.checkoutUrl) {
336
+ window.location.href = result.checkoutUrl;
337
+ }
338
+ }
339
+ });
340
+ }
341
+
342
+ checkFeatureAccess() {
343
+ this.metrifoxService.checkAccess('cust_123', 'api_calls').subscribe({
344
+ next: ({ hasAccess, remaining, limit }) => {
345
+ console.log(`Access: ${hasAccess}, Remaining: ${remaining}/${limit}`);
346
+ }
347
+ });
348
+ }
349
+
350
+ recordUsage() {
351
+ this.metrifoxService.recordUsage('cust_123', 'api_calls', 1).subscribe({
352
+ next: () => console.log('Usage recorded')
353
+ });
354
+ }
355
+ }
356
+ ```
357
+
358
+ ## Custom Components
359
+
360
+ Replace any section with your own component:
361
+
362
+ ```typescript
363
+ // my-custom-plan.component.ts
364
+ import { Component, Input } from "@angular/core";
365
+ import {
366
+ CustomSectionComponentBase,
367
+ CustomerData,
368
+ } from "@metrifox/angular-sdk";
369
+
370
+ @Component({
371
+ selector: "app-custom-plan",
372
+ standalone: true,
373
+ template: `
374
+ <div class="custom-plan">
375
+ <h3>{{ customerData?.plan?.name }}</h3>
376
+ <p>Custom property: {{ customProp }}</p>
377
+ </div>
378
+ `,
379
+ })
380
+ export class MyCustomPlanComponent implements CustomSectionComponentBase {
381
+ @Input() customerData?: CustomerData;
382
+ @Input() customerKey?: string;
383
+ @Input() customProp?: string;
384
+ }
385
+
386
+ // Usage
387
+ @Component({
388
+ template: `
389
+ <metrifox-customer-portal
390
+ [customerKey]="'cust_123'"
391
+ [sectionsConfig]="sections"
392
+ >
393
+ </metrifox-customer-portal>
394
+ `,
395
+ })
396
+ export class BillingComponent {
397
+ sections: SectionConfig[] = [
398
+ { key: "subscription" },
399
+ {
400
+ key: "plan",
401
+ component: MyCustomPlanComponent,
402
+ props: { customProp: "Hello!" },
403
+ },
404
+ ];
405
+ }
406
+ ```
407
+
408
+ ## TypeScript Support
409
+
410
+ The SDK is fully typed. Import types as needed:
411
+
412
+ ```typescript
413
+ import type {
414
+ // Configuration
415
+ MetrifoxConfig,
416
+ MetrifoxTheme,
417
+
418
+ // Customer Portal
419
+ CustomerPortalTheme,
420
+ SectionConfig,
421
+ SectionKey,
422
+
423
+ // Pricing Table
424
+ PricingTableTheme,
425
+ PlanSelectEvent,
426
+ PurchaseSelectEvent,
427
+
428
+ // Data Models
429
+ CustomerData,
430
+ SubscriptionData,
431
+ PricingData,
432
+ PricingPlan,
433
+
434
+ // Events
435
+ MetrifoxErrorEvent,
436
+ } from "@metrifox/angular-sdk";
437
+ ```
438
+
439
+ ## Migration from React SDK
440
+
441
+ | React | Angular |
442
+ | ----------------------- | ------------------------------ |
443
+ | `metrifoxInit()` | `MetrifoxService.initialize()` |
444
+ | `<CustomerPortal />` | `<metrifox-customer-portal>` |
445
+ | `<PricingTable />` | `<metrifox-pricing-table>` |
446
+ | `customerKey` prop | `[customerKey]` input |
447
+ | `onPlanSelect` callback | `(planSelected)` output |
448
+
449
+ ## Testing with the demo playground
450
+
451
+ The [metrifox-sdk-demo](https://github.com/metrifox/metrifox-sdk-demo) repo includes an **Angular SDK demo playground** that works like the React SDK demo: sidebar (Customer Portal / Pricing Table), config panel (API keys + Theme options), and live preview.
452
+
453
+ To run the package against the demo playground:
454
+
455
+ 1. **Build the Angular SDK** (this repo):
456
+
457
+ ```bash
458
+ pnpm install
459
+ pnpm run build
460
+ ```
461
+
462
+ 2. **Run the demo** (in [metrifox-sdk-demo/angular-sdk](https://github.com/metrifox/metrifox-sdk-demo/tree/main/angular-sdk)):
463
+
464
+ ```bash
465
+ cd path/to/metrifox-sdk-demo/angular-sdk
466
+ npm install
467
+ npm run dev
468
+ ```
469
+
470
+ The demo’s `package.json` points to `file:../../metrifox-angular-sdk/dist`, so it uses your local build. Open `http://localhost:4200` and use the config panel to set Client Key, Customer Key (for the portal), and Theme options.
471
+
472
+ ## Browser Support
473
+
474
+ - Chrome (latest)
475
+ - Firefox (latest)
476
+ - Safari (latest)
477
+ - Edge (latest)
478
+
479
+ ## Support
480
+
481
+ - 📧 Email: support@metrifox.com
482
+ - 📚 Documentation: https://docs.metrifox.com
483
+ - 🐛 Issues: https://github.com/metrifox/metrifox-angular-sdk/issues
484
+
485
+ ## License
486
+
487
+ MIT © [Metrifox](https://metrifox.com)