@m1z23r/ngx-ui 0.0.1 → 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/README.md +257 -0
- package/fesm2022/m1z23r-ngx-ui.mjs +470 -11
- package/fesm2022/m1z23r-ngx-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/m1z23r-ngx-ui.d.ts +279 -4
package/README.md
CHANGED
|
@@ -338,6 +338,263 @@ export class MyComponent {
|
|
|
338
338
|
|
|
339
339
|
---
|
|
340
340
|
|
|
341
|
+
## Loading System
|
|
342
|
+
|
|
343
|
+
A centralized loading state management system with a service and directive for easy integration.
|
|
344
|
+
|
|
345
|
+
### LoadingService
|
|
346
|
+
|
|
347
|
+
Injectable service to manage loading states by identifier.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { LoadingService } from '@m1z23r/ngx-ui';
|
|
351
|
+
|
|
352
|
+
@Component({...})
|
|
353
|
+
export class MyComponent {
|
|
354
|
+
private loadingService = inject(LoadingService);
|
|
355
|
+
|
|
356
|
+
async login() {
|
|
357
|
+
this.loadingService.start('login');
|
|
358
|
+
try {
|
|
359
|
+
await this.authService.login();
|
|
360
|
+
} finally {
|
|
361
|
+
this.loadingService.stop('login');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async submitForm() {
|
|
366
|
+
this.loadingService.start('submit');
|
|
367
|
+
try {
|
|
368
|
+
await this.formService.submit();
|
|
369
|
+
} finally {
|
|
370
|
+
this.loadingService.stop('submit');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Methods
|
|
377
|
+
|
|
378
|
+
| Method | Parameters | Description |
|
|
379
|
+
|--------|------------|-------------|
|
|
380
|
+
| `start(id)` | `id: string` | Start loading for identifier |
|
|
381
|
+
| `stop(id)` | `id: string` | Stop loading for identifier |
|
|
382
|
+
| `set(id, loading)` | `id: string, loading: boolean` | Set loading state |
|
|
383
|
+
| `toggle(id)` | `id: string` | Toggle loading state |
|
|
384
|
+
| `isLoading(id)` | `id: string` | Returns `Signal<boolean>` for the identifier |
|
|
385
|
+
| `isAnyLoading()` | - | Returns `Signal<boolean>` true if any loading is active |
|
|
386
|
+
| `clear(id)` | `id: string` | Remove loading state for identifier |
|
|
387
|
+
| `clearAll()` | - | Remove all loading states |
|
|
388
|
+
|
|
389
|
+
### LoadingDirective
|
|
390
|
+
|
|
391
|
+
Directive that automatically connects a component's loading state to the LoadingService.
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
import { ButtonComponent, LoadingDirective, LoadingService } from '@m1z23r/ngx-ui';
|
|
395
|
+
|
|
396
|
+
@Component({
|
|
397
|
+
imports: [ButtonComponent, LoadingDirective],
|
|
398
|
+
template: `
|
|
399
|
+
<!-- These buttons automatically show loading when their identifier is active -->
|
|
400
|
+
<ui-button uiLoading="login" (clicked)="login()">Login</ui-button>
|
|
401
|
+
<ui-button uiLoading="submit" (clicked)="submit()">Submit</ui-button>
|
|
402
|
+
<ui-button uiLoading="delete" variant="outline">Delete</ui-button>
|
|
403
|
+
`
|
|
404
|
+
})
|
|
405
|
+
export class MyComponent {
|
|
406
|
+
private loadingService = inject(LoadingService);
|
|
407
|
+
|
|
408
|
+
async login() {
|
|
409
|
+
this.loadingService.start('login'); // Button with uiLoading="login" shows spinner
|
|
410
|
+
try {
|
|
411
|
+
await this.authService.login();
|
|
412
|
+
} finally {
|
|
413
|
+
this.loadingService.stop('login'); // Spinner stops
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Making Custom Components Loadable
|
|
420
|
+
|
|
421
|
+
Any component can support the `uiLoading` directive by implementing the `Loadable` interface:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
import { Loadable, LOADABLE } from '@m1z23r/ngx-ui';
|
|
425
|
+
|
|
426
|
+
@Component({
|
|
427
|
+
selector: 'my-custom-button',
|
|
428
|
+
providers: [{ provide: LOADABLE, useExisting: MyCustomButtonComponent }],
|
|
429
|
+
template: `
|
|
430
|
+
<button [disabled]="loading()">
|
|
431
|
+
@if (loading()) {
|
|
432
|
+
<span class="spinner"></span>
|
|
433
|
+
}
|
|
434
|
+
<ng-content />
|
|
435
|
+
</button>
|
|
436
|
+
`
|
|
437
|
+
})
|
|
438
|
+
export class MyCustomButtonComponent implements Loadable {
|
|
439
|
+
private readonly loading = signal(false);
|
|
440
|
+
|
|
441
|
+
// Required by Loadable interface
|
|
442
|
+
setLoading(loading: boolean): void {
|
|
443
|
+
this.loading.set(loading);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Now the directive works with your custom component:
|
|
449
|
+
|
|
450
|
+
```html
|
|
451
|
+
<my-custom-button uiLoading="save">Save</my-custom-button>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Combining with Direct Loading Input
|
|
455
|
+
|
|
456
|
+
The `ui-button` component supports both the directive and direct `loading` input. The button shows loading if either is true:
|
|
457
|
+
|
|
458
|
+
```html
|
|
459
|
+
<!-- Via directive (controlled by LoadingService) -->
|
|
460
|
+
<ui-button uiLoading="login">Login</ui-button>
|
|
461
|
+
|
|
462
|
+
<!-- Via direct input -->
|
|
463
|
+
<ui-button [loading]="isSubmitting()">Submit</ui-button>
|
|
464
|
+
|
|
465
|
+
<!-- Both work together - loading shows if either is true -->
|
|
466
|
+
<ui-button uiLoading="save" [loading]="manualLoading()">Save</ui-button>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Dialog System
|
|
472
|
+
|
|
473
|
+
A simple, Promise-based dialog system for opening modal dialogs programmatically. No RxJS required.
|
|
474
|
+
|
|
475
|
+
### DialogService
|
|
476
|
+
|
|
477
|
+
Injectable service to open dialogs programmatically.
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
import { DialogService, DIALOG_DATA, DIALOG_REF, DialogRef, ModalComponent, ButtonComponent } from '@m1z23r/ngx-ui';
|
|
481
|
+
|
|
482
|
+
// 1. Create a dialog component
|
|
483
|
+
@Component({
|
|
484
|
+
imports: [ModalComponent, ButtonComponent],
|
|
485
|
+
template: `
|
|
486
|
+
<ui-modal [title]="data.title" size="sm">
|
|
487
|
+
<p>{{ data.message }}</p>
|
|
488
|
+
|
|
489
|
+
<ng-container footer>
|
|
490
|
+
<ui-button variant="outline" (clicked)="dialogRef.close(false)">Cancel</ui-button>
|
|
491
|
+
<ui-button (clicked)="dialogRef.close(true)">Confirm</ui-button>
|
|
492
|
+
</ng-container>
|
|
493
|
+
</ui-modal>
|
|
494
|
+
`
|
|
495
|
+
})
|
|
496
|
+
export class ConfirmDialog {
|
|
497
|
+
dialogRef = inject(DIALOG_REF) as DialogRef<boolean>;
|
|
498
|
+
data = inject(DIALOG_DATA) as { title: string; message: string };
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// 2. Open the dialog
|
|
502
|
+
@Component({...})
|
|
503
|
+
export class MyComponent {
|
|
504
|
+
private dialogService = inject(DialogService);
|
|
505
|
+
|
|
506
|
+
async confirmAction() {
|
|
507
|
+
const dialogRef = this.dialogService.open(ConfirmDialog, {
|
|
508
|
+
data: { title: 'Confirm', message: 'Are you sure?' }
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
const confirmed = await dialogRef.afterClosed();
|
|
512
|
+
if (confirmed) {
|
|
513
|
+
// User confirmed
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### ModalComponent
|
|
520
|
+
|
|
521
|
+
A wrapper component that provides the modal UI with backdrop, header, body, and footer. Uses content projection.
|
|
522
|
+
|
|
523
|
+
```html
|
|
524
|
+
<ui-modal [title]="'My Dialog'" [size]="'md'" [closeOnEscape]="true" [closeOnBackdropClick]="true">
|
|
525
|
+
<!-- Body content (default slot) -->
|
|
526
|
+
<p>This is the modal body content.</p>
|
|
527
|
+
|
|
528
|
+
<!-- Footer content (named slot) -->
|
|
529
|
+
<ng-container footer>
|
|
530
|
+
<ui-button variant="outline" (clicked)="cancel()">Cancel</ui-button>
|
|
531
|
+
<ui-button (clicked)="save()">Save</ui-button>
|
|
532
|
+
</ng-container>
|
|
533
|
+
</ui-modal>
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
#### Modal Inputs
|
|
537
|
+
|
|
538
|
+
| Input | Type | Default | Description |
|
|
539
|
+
|-------|------|---------|-------------|
|
|
540
|
+
| `title` | `string` | - | Title displayed in the modal header |
|
|
541
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'md'` | Modal size preset |
|
|
542
|
+
| `width` | `string` | - | Custom width (overrides size) |
|
|
543
|
+
| `maxWidth` | `string` | - | Custom max-width (overrides size) |
|
|
544
|
+
| `closeOnBackdropClick` | `boolean` | `true` | Close when clicking backdrop |
|
|
545
|
+
| `closeOnEscape` | `boolean` | `true` | Close when pressing Escape |
|
|
546
|
+
| `showCloseButton` | `boolean` | `true` | Show close button in header |
|
|
547
|
+
| `panelClass` | `string` | - | Custom CSS class for container |
|
|
548
|
+
|
|
549
|
+
#### Modal Size Reference
|
|
550
|
+
|
|
551
|
+
| Size | Max Width |
|
|
552
|
+
|------|-----------|
|
|
553
|
+
| `sm` | 400px |
|
|
554
|
+
| `md` | 560px |
|
|
555
|
+
| `lg` | 800px |
|
|
556
|
+
| `xl` | 1140px |
|
|
557
|
+
| `full` | 100vw - padding |
|
|
558
|
+
|
|
559
|
+
### DialogConfig
|
|
560
|
+
|
|
561
|
+
Configuration options when opening a dialog.
|
|
562
|
+
|
|
563
|
+
```typescript
|
|
564
|
+
interface DialogConfig<TData = unknown> {
|
|
565
|
+
data?: TData; // Data passed via DIALOG_DATA
|
|
566
|
+
width?: string; // CSS width value
|
|
567
|
+
maxWidth?: string; // CSS max-width value
|
|
568
|
+
size?: ModalSize; // Size preset
|
|
569
|
+
closeOnBackdropClick?: boolean; // Default: true
|
|
570
|
+
closeOnEscape?: boolean; // Default: true
|
|
571
|
+
panelClass?: string; // Custom CSS class
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### DialogRef
|
|
576
|
+
|
|
577
|
+
Reference to an opened dialog, used to close it and get results.
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
class DialogRef<TResult> {
|
|
581
|
+
// Close the dialog with an optional result
|
|
582
|
+
close(result?: TResult): void;
|
|
583
|
+
|
|
584
|
+
// Get a promise that resolves when the dialog closes
|
|
585
|
+
afterClosed(): Promise<TResult | undefined>;
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Injection Tokens
|
|
590
|
+
|
|
591
|
+
| Token | Type | Description |
|
|
592
|
+
|-------|------|-------------|
|
|
593
|
+
| `DIALOG_DATA` | `unknown` | Data passed to the dialog via config |
|
|
594
|
+
| `DIALOG_REF` | `DialogRef` | Reference to close the dialog |
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
341
598
|
## Theming
|
|
342
599
|
|
|
343
600
|
All components use CSS custom properties for styling. Override these in your global stylesheet:
|