ngx-kit 7.1.0 → 7.3.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.
Files changed (73) hide show
  1. package/angle-selector/README.md +34 -34
  2. package/box-shadow/README.md +33 -33
  3. package/color-picker/README.md +52 -52
  4. package/{shared → core}/README.md +117 -117
  5. package/data-table/README.md +120 -120
  6. package/date-picker/README.md +74 -74
  7. package/dialog/README.md +122 -92
  8. package/drag-resize/README.md +53 -55
  9. package/fesm2022/ngx-kit-angle-selector.mjs +9 -26
  10. package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
  11. package/fesm2022/ngx-kit-box-shadow.mjs +330 -356
  12. package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
  13. package/fesm2022/ngx-kit-color-picker.mjs +132 -272
  14. package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
  15. package/fesm2022/{ngx-kit-shared.mjs → ngx-kit-core.mjs} +908 -277
  16. package/fesm2022/ngx-kit-core.mjs.map +1 -0
  17. package/fesm2022/ngx-kit-data-table.mjs +1 -1
  18. package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
  19. package/fesm2022/ngx-kit-date-picker.mjs +34 -22
  20. package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
  21. package/fesm2022/ngx-kit-dialog.mjs +430 -331
  22. package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
  23. package/fesm2022/ngx-kit-drag-resize.mjs +193 -140
  24. package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
  25. package/fesm2022/ngx-kit-drawer-menu.mjs +3 -3
  26. package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -1
  27. package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
  28. package/fesm2022/ngx-kit-form-field.mjs +9 -3
  29. package/fesm2022/ngx-kit-form-field.mjs.map +1 -1
  30. package/fesm2022/ngx-kit-gallery.mjs +3 -3
  31. package/fesm2022/ngx-kit-gallery.mjs.map +1 -1
  32. package/fesm2022/ngx-kit-gradient-picker.mjs +20 -38
  33. package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
  34. package/fesm2022/ngx-kit-grid-layout.mjs +32 -30
  35. package/fesm2022/ngx-kit-grid-layout.mjs.map +1 -1
  36. package/fesm2022/ngx-kit-image-editor.mjs +3 -3
  37. package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
  38. package/fesm2022/ngx-kit-menu.mjs +1 -1
  39. package/fesm2022/ngx-kit-menu.mjs.map +1 -1
  40. package/fesm2022/ngx-kit-message.mjs +2 -2
  41. package/fesm2022/ngx-kit-message.mjs.map +1 -1
  42. package/fesm2022/ngx-kit-notify.mjs +1 -1
  43. package/fesm2022/ngx-kit-notify.mjs.map +1 -1
  44. package/fesm2022/ngx-kit-time-picker.mjs +1 -1
  45. package/fesm2022/ngx-kit-time-picker.mjs.map +1 -1
  46. package/fesm2022/ngx-kit-virtual-scroll.mjs +2 -2
  47. package/fesm2022/ngx-kit-virtual-scroll.mjs.map +1 -1
  48. package/gallery/README.md +71 -71
  49. package/gradient-picker/README.md +41 -41
  50. package/grid-layout/README.md +64 -64
  51. package/image-editor/README.md +44 -44
  52. package/menu/README.md +85 -85
  53. package/message/README.md +70 -70
  54. package/notify/README.md +56 -56
  55. package/package.json +5 -9
  56. package/time-picker/README.md +89 -89
  57. package/types/ngx-kit-angle-selector.d.ts +13 -16
  58. package/types/ngx-kit-box-shadow.d.ts +37 -95
  59. package/types/ngx-kit-color-picker.d.ts +61 -58
  60. package/types/{ngx-kit-shared.d.ts → ngx-kit-core.d.ts} +194 -34
  61. package/types/ngx-kit-data-table.d.ts +2 -2
  62. package/types/ngx-kit-date-picker.d.ts +15 -12
  63. package/types/ngx-kit-dialog.d.ts +208 -107
  64. package/types/ngx-kit-drag-resize.d.ts +74 -47
  65. package/types/ngx-kit-form-field.d.ts +26 -23
  66. package/types/ngx-kit-gradient-picker.d.ts +4 -7
  67. package/types/ngx-kit-menu.d.ts +1 -1
  68. package/types/ngx-kit-time-picker.d.ts +1 -1
  69. package/virtual-scroll/README.md +199 -199
  70. package/fesm2022/ngx-kit-shared.mjs.map +0 -1
  71. package/fesm2022/ngx-kit-webflow.mjs +0 -709
  72. package/fesm2022/ngx-kit-webflow.mjs.map +0 -1
  73. package/types/ngx-kit-webflow.d.ts +0 -286
@@ -1,120 +1,120 @@
1
- # ngx-kit/data-table
2
-
3
- A signal-based data table with full type-safety: column and custom renderer definitions are typed so TypeScript itself catches invalid columns or a wrong `rendererInputs`. Single/multi-column sorting, pagination, lazy (server-side) mode, and column resizing via Pointer Capture.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Registering renderers (optional, but recommended)
12
-
13
- ```ts
14
- // app.config.ts
15
- import { provideTable, defineRenderers } from 'ngx-kit/data-table';
16
- import { AvatarCellRenderer, BooleanCellRenderer } from './cell-renderers';
17
-
18
- export const appConfig: ApplicationConfig = {
19
- providers: [
20
- provideTable({
21
- renderers: defineRenderers({ avatar: AvatarCellRenderer, boolean: BooleanCellRenderer }),
22
- column: { minWidth: 80, maxWidth: 480, defaultWidth: 160 },
23
- }),
24
- ],
25
- };
26
- ```
27
-
28
- ## Type-safe column definitions
29
-
30
- ```ts
31
- interface Tenant {
32
- avatarUrl: string;
33
- name: string;
34
- isActive: boolean;
35
- }
36
-
37
- const renderers = defineRenderers({ avatar: AvatarCellRenderer, boolean: BooleanCellRenderer });
38
-
39
- const fields = defineFields<Tenant, typeof renderers>(renderers, [
40
- { column: 'avatarUrl', title: 'User', renderer: 'avatar', rendererInputs: { showName: true } }, // ✅ type-checked
41
- { column: 'name', title: 'Name', sortable: true },
42
- { column: 'isActive', title: 'Active', renderer: 'boolean', align: 'center' },
43
- ]);
44
- ```
45
-
46
- If `column` isn't a real field of `Tenant`, or `renderer` isn't a real key of the registry, or `rendererInputs` doesn't match that renderer's actual inputs — it's a compile error, not a runtime one.
47
-
48
- ## Usage in a template
49
-
50
- ```html
51
- <ngx-table
52
- [fields]="fields"
53
- [data]="tenants"
54
- [totalRecords]="tenants.length"
55
- [pageSize]="20"
56
- (sortChange)="onSortChange($event)"></ngx-table>
57
- ```
58
-
59
- ### Lazy mode (server-side pagination/sorting)
60
-
61
- ```html
62
- <ngx-table
63
- [fields]="fields"
64
- [data]="page"
65
- [totalRecords]="total"
66
- [lazy]="true"
67
- (lazyLoad)="fetchPage($event)"></ngx-table>
68
- ```
69
-
70
- ```ts
71
- fetchPage(ev: LazyLoadEvent<Tenant>) {
72
- // ev.pageIndex, ev.pageSize, ev.first, ev.sorts
73
- this.api.getTenants(ev).subscribe((res) => { this.page = res.data; this.total = res.total; });
74
- }
75
- ```
76
-
77
- ## API
78
-
79
- ### `<ngx-table>` inputs
80
-
81
- | Input | Type | Description |
82
- | ------------------ | ----------------------------------- | -------------------------------------------------------------- |
83
- | `fields` | `TableField<T, R>[]` **(required)** | Column definitions (from `defineFields`) |
84
- | `data` | `readonly T[]` **(required)** | Current page's data |
85
- | `totalRecords` | `number` **(required)** | Total row count (for pagination) |
86
- | `pageSize` | `number` | Defaults from `provideTable` |
87
- | `lazy` | `boolean` | If `true`, your app manages sorting/pagination (not the table) |
88
- | `loading` | `boolean` | Shows a loading state |
89
- | `showRecordNumber` | `boolean` | Shows a row-number column |
90
-
91
- ### Outputs
92
-
93
- | Output | Type | Description |
94
- | -------------- | ---------------------------------- | ------------------------------------------------------------------------------ |
95
- | `sortChange` | `SortMeta<T>[]` | Sort change (non-lazy mode) |
96
- | `lazyLoad` | `LazyLoadEvent<T>` | New page/sort (lazy mode) — includes `pageIndex`, `pageSize`, `first`, `sorts` |
97
- | `columnResize` | `{ field: string; width: number }` | A column's width changed |
98
-
99
- ### Defining a custom renderer
100
-
101
- ```ts
102
- @Component({
103
- standalone: true,
104
- selector: 'app-avatar-cell',
105
- template: `
106
- <img [src]="value()" />
107
- <span *ngIf="showName()">{{ row().name }}</span>
108
- `,
109
- })
110
- export class AvatarCellRenderer implements CellRendererComponent<string, Tenant> {
111
- value = input.required<string>();
112
- row = input.required<Tenant>();
113
- field = input.required<TableFieldBase<Tenant>>();
114
- showName = input(false); // automatically usable in rendererInputs for this column
115
- }
116
- ```
117
-
118
- ## Dark mode and RTL
119
-
120
- Supported automatically.
1
+ # ngx-kit/data-table
2
+
3
+ A signal-based data table with full type-safety: column and custom renderer definitions are typed so TypeScript itself catches invalid columns or a wrong `rendererInputs`. Single/multi-column sorting, pagination, lazy (server-side) mode, and column resizing via Pointer Capture.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install ngx-kit
9
+ ```
10
+
11
+ ## Registering renderers (optional, but recommended)
12
+
13
+ ```ts
14
+ // app.config.ts
15
+ import { provideTable, defineRenderers } from 'ngx-kit/data-table';
16
+ import { AvatarCellRenderer, BooleanCellRenderer } from './cell-renderers';
17
+
18
+ export const appConfig: ApplicationConfig = {
19
+ providers: [
20
+ provideTable({
21
+ renderers: defineRenderers({ avatar: AvatarCellRenderer, boolean: BooleanCellRenderer }),
22
+ column: { minWidth: 80, maxWidth: 480, defaultWidth: 160 },
23
+ }),
24
+ ],
25
+ };
26
+ ```
27
+
28
+ ## Type-safe column definitions
29
+
30
+ ```ts
31
+ interface Tenant {
32
+ avatarUrl: string;
33
+ name: string;
34
+ isActive: boolean;
35
+ }
36
+
37
+ const renderers = defineRenderers({ avatar: AvatarCellRenderer, boolean: BooleanCellRenderer });
38
+
39
+ const fields = defineFields<Tenant, typeof renderers>(renderers, [
40
+ { column: 'avatarUrl', title: 'User', renderer: 'avatar', rendererInputs: { showName: true } }, // ✅ type-checked
41
+ { column: 'name', title: 'Name', sortable: true },
42
+ { column: 'isActive', title: 'Active', renderer: 'boolean', align: 'center' },
43
+ ]);
44
+ ```
45
+
46
+ If `column` isn't a real field of `Tenant`, or `renderer` isn't a real key of the registry, or `rendererInputs` doesn't match that renderer's actual inputs — it's a compile error, not a runtime one.
47
+
48
+ ## Usage in a template
49
+
50
+ ```html
51
+ <ngx-table
52
+ [fields]="fields"
53
+ [data]="tenants"
54
+ [totalRecords]="tenants.length"
55
+ [pageSize]="20"
56
+ (sortChange)="onSortChange($event)"></ngx-table>
57
+ ```
58
+
59
+ ### Lazy mode (server-side pagination/sorting)
60
+
61
+ ```html
62
+ <ngx-table
63
+ [fields]="fields"
64
+ [data]="page"
65
+ [totalRecords]="total"
66
+ [lazy]="true"
67
+ (lazyLoad)="fetchPage($event)"></ngx-table>
68
+ ```
69
+
70
+ ```ts
71
+ fetchPage(ev: LazyLoadEvent<Tenant>) {
72
+ // ev.pageIndex, ev.pageSize, ev.first, ev.sorts
73
+ this.api.getTenants(ev).subscribe((res) => { this.page = res.data; this.total = res.total; });
74
+ }
75
+ ```
76
+
77
+ ## API
78
+
79
+ ### `<ngx-table>` inputs
80
+
81
+ | Input | Type | Description |
82
+ | ------------------ | ----------------------------------- | -------------------------------------------------------------- |
83
+ | `fields` | `TableField<T, R>[]` **(required)** | Column definitions (from `defineFields`) |
84
+ | `data` | `readonly T[]` **(required)** | Current page's data |
85
+ | `totalRecords` | `number` **(required)** | Total row count (for pagination) |
86
+ | `pageSize` | `number` | Defaults from `provideTable` |
87
+ | `lazy` | `boolean` | If `true`, your app manages sorting/pagination (not the table) |
88
+ | `loading` | `boolean` | Shows a loading state |
89
+ | `showRecordNumber` | `boolean` | Shows a row-number column |
90
+
91
+ ### Outputs
92
+
93
+ | Output | Type | Description |
94
+ | -------------- | ---------------------------------- | ------------------------------------------------------------------------------ |
95
+ | `sortChange` | `SortMeta<T>[]` | Sort change (non-lazy mode) |
96
+ | `lazyLoad` | `LazyLoadEvent<T>` | New page/sort (lazy mode) — includes `pageIndex`, `pageSize`, `first`, `sorts` |
97
+ | `columnResize` | `{ field: string; width: number }` | A column's width changed |
98
+
99
+ ### Defining a custom renderer
100
+
101
+ ```ts
102
+ @Component({
103
+ standalone: true,
104
+ selector: 'app-avatar-cell',
105
+ template: `
106
+ <img [src]="value()" />
107
+ <span *ngIf="showName()">{{ row().name }}</span>
108
+ `,
109
+ })
110
+ export class AvatarCellRenderer implements CellRendererComponent<string, Tenant> {
111
+ value = input.required<string>();
112
+ row = input.required<Tenant>();
113
+ field = input.required<TableFieldBase<Tenant>>();
114
+ showName = input(false); // automatically usable in rendererInputs for this column
115
+ }
116
+ ```
117
+
118
+ ## Dark mode and RTL
119
+
120
+ Supported automatically.
@@ -1,74 +1,74 @@
1
- # ngx-kit/date-picker
2
-
3
- A date picker supporting four calendar systems: Gregorian, Jalali (Persian), Hijri (Islamic), and Chinese — built on an adapter-based architecture that also makes it possible to add other calendars. It also ships a standalone calendar component (`ngx-calendar`) usable without any inputs.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Setup
12
-
13
- Calendar adapters need to be provided (the default provides all four; if you only need some of them, the bundle stays smaller since each is lazily imported):
14
-
15
- ```ts
16
- // app.config.ts
17
- import { provideDateAdapters } from 'ngx-kit/date-picker';
18
-
19
- export const appConfig: ApplicationConfig = {
20
- providers: [provideDateAdapters()],
21
- };
22
- ```
23
-
24
- ## Usage
25
-
26
- ```html
27
- <input
28
- type="text"
29
- [ngxInputDatePicker]="date"
30
- (change)="date = $event"
31
- [locale]="'fa'"
32
- [displayFormat]="'yyyy/MM/dd'" />
33
- ```
34
-
35
- ```html
36
- <ngx-calendar [locale]="'fa'" [theme]="'auto'"></ngx-calendar>
37
- ```
38
-
39
- ## API
40
-
41
- ### `[ngxInputDatePicker]`
42
-
43
- | Input | Type | Default | Description |
44
- | ------------------- | -------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------------- |
45
- | `locale` | `string` (`'en'`, `'fa'`, `'hi'`, `'zh'`, or any custom registered locale) | `'en'` | Which calendar to use |
46
- | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | |
47
- | `displayFormat` | `string` | `'yyyy/MM/dd'` | Text display format for the date |
48
- | `min` / `max` | `Date` | | Allowed range |
49
- | `config` | `NgxDatePickerConfig` | | Show/hide and text for the "today"/"clear" buttons, custom icon templates |
50
- | `change` _(output)_ | `EventEmitter<Date>` | | The selected date (always a standard JavaScript `Date`, regardless of the displayed calendar) |
51
-
52
- ### `getLocals()`
53
-
54
- Returns the list of currently registered locales (e.g. to populate a language `<select>`):
55
-
56
- ```ts
57
- availableLocals = getLocals(); // ['en', 'fa', 'hi', 'zh']
58
- ```
59
-
60
- ### Adding a custom calendar
61
-
62
- ```ts
63
- provideDateAdapters({ locale: 'ja', useClass: MyJapaneseAdapter });
64
- ```
65
-
66
- `MyJapaneseAdapter` must implement the `IDateAdapter` interface.
67
-
68
- ## Performance note
69
-
70
- The Hijri and Chinese calendars (which are table/astronomical-based, unlike the formulaic Gregorian/Jalali ones) cache their computation results internally — since rendering a calendar month calls the date computation separately for every day cell, without caching this could take several hundred milliseconds for years far from today.
71
-
72
- ## Dark mode and RTL
73
-
74
- Supported automatically (the Jalali/Hijri calendars are naturally RTL too).
1
+ # ngx-kit/date-picker
2
+
3
+ A date picker supporting four calendar systems: Gregorian, Jalali (Persian), Hijri (Islamic), and Chinese — built on an adapter-based architecture that also makes it possible to add other calendars. It also ships a standalone calendar component (`ngx-calendar`) usable without any inputs.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install ngx-kit
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ Calendar adapters need to be provided (the default provides all four; if you only need some of them, the bundle stays smaller since each is lazily imported):
14
+
15
+ ```ts
16
+ // app.config.ts
17
+ import { provideDateAdapters } from 'ngx-kit/date-picker';
18
+
19
+ export const appConfig: ApplicationConfig = {
20
+ providers: [provideDateAdapters()],
21
+ };
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```html
27
+ <input
28
+ type="text"
29
+ [ngxInputDatePicker]="date"
30
+ (change)="date = $event"
31
+ [locale]="'fa'"
32
+ [displayFormat]="'yyyy/MM/dd'" />
33
+ ```
34
+
35
+ ```html
36
+ <ngx-calendar [locale]="'fa'" [theme]="'auto'"></ngx-calendar>
37
+ ```
38
+
39
+ ## API
40
+
41
+ ### `[ngxInputDatePicker]`
42
+
43
+ | Input | Type | Default | Description |
44
+ | ------------------- | -------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------------- |
45
+ | `locale` | `string` (`'en'`, `'fa'`, `'hi'`, `'zh'`, or any custom registered locale) | `'en'` | Which calendar to use |
46
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | |
47
+ | `displayFormat` | `string` | `'yyyy/MM/dd'` | Text display format for the date |
48
+ | `min` / `max` | `Date` | | Allowed range |
49
+ | `config` | `NgxDatePickerConfig` | | Show/hide and text for the "today"/"clear" buttons, custom icon templates |
50
+ | `change` _(output)_ | `EventEmitter<Date>` | | The selected date (always a standard JavaScript `Date`, regardless of the displayed calendar) |
51
+
52
+ ### `getLocals()`
53
+
54
+ Returns the list of currently registered locales (e.g. to populate a language `<select>`):
55
+
56
+ ```ts
57
+ availableLocals = getLocals(); // ['en', 'fa', 'hi', 'zh']
58
+ ```
59
+
60
+ ### Adding a custom calendar
61
+
62
+ ```ts
63
+ provideDateAdapters({ locale: 'ja', useClass: MyJapaneseAdapter });
64
+ ```
65
+
66
+ `MyJapaneseAdapter` must implement the `IDateAdapter` interface.
67
+
68
+ ## Performance note
69
+
70
+ The Hijri and Chinese calendars (which are table/astronomical-based, unlike the formulaic Gregorian/Jalali ones) cache their computation results internally — since rendering a calendar month calls the date computation separately for every day cell, without caching this could take several hundred milliseconds for years far from today.
71
+
72
+ ## Dark mode and RTL
73
+
74
+ Supported automatically (the Jalali/Hijri calendars are naturally RTL too).
package/dialog/README.md CHANGED
@@ -1,92 +1,122 @@
1
- # ngx-kit/dialog
2
-
3
- Modal/dialog built on the browser's native `<dialog>` — no manual overlay, no third-party library.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Setup
12
-
13
- ```ts
14
- // app.config.ts
15
- import { ApplicationConfig, importProvidersFrom } from '@angular/core';
16
- import { NgxDialogModule } from 'ngx-kit/dialog';
17
-
18
- export const appConfig: ApplicationConfig = {
19
- providers: [importProvidersFrom(NgxDialogModule)],
20
- };
21
- ```
22
-
23
- ## Opening a dialog
24
-
25
- With the static API (no manual service injection needed):
26
-
27
- ```ts
28
- import { Dialog } from 'ngx-kit/dialog';
29
-
30
- const ref = Dialog.open(MyDialogComponent, {
31
- data: { userId: 42 },
32
- width: '480px',
33
- allowCloseOnOutsideClick: true,
34
- header: { enable: true, title: 'Edit user', showCloseButton: true },
35
- });
36
-
37
- ref.afterClosed.subscribe((result) => console.log('Result:', result));
38
- ```
39
-
40
- Inside the dialog's component:
41
-
42
- ```ts
43
- @Component({ ... })
44
- export class MyDialogComponent {
45
- private ref = inject(NgxDialogRef);
46
- data = inject(NGX_DIALOG_DATA); // the data passed via config.data
47
-
48
- save() {
49
- this.ref.close({ saved: true });
50
- }
51
- }
52
- ```
53
-
54
- ### Layout directives inside a dialog
55
-
56
- ```html
57
- <div *ngxDialogHeader>Custom title</div>
58
- <div *ngxDialogBody>Main content</div>
59
- <div *ngxDialogFooter>
60
- <button (click)="save()">Save</button>
61
- </div>
62
- ```
63
-
64
- ## API
65
-
66
- ### `Dialog.open<T>(component, config?)`
67
-
68
- | `config` field | Type | Default | Description |
69
- | ----------------------------------------------------------- | ---------- | ----------- | ---------------------------------------------- |
70
- | `data` | `T` | `{}` | Data passed to the component inside the dialog |
71
- | `allowCloseOnOutsideClick` | `boolean` | `false` | Close when clicking the backdrop |
72
- | `containerClass` | `string` | `'ngx-kit'` | Extra class on the container |
73
- | `header.enable` / `header.title` / `header.showCloseButton` | | | Default header settings |
74
- | `footer.enable` | `boolean` | | Show the default footer |
75
- | `width` / `minWidth` / `maxWidth` | `string` | | Horizontal sizing |
76
- | `height` / `minHeight` / `maxHeight` | `string` | | Vertical sizing |
77
- | `injector` | `Injector` | | Custom injector for the inner component |
78
-
79
- ### `NgxDialogRef`
80
-
81
- | Member | Description |
82
- | ------------------------------ | --------------------------------------------------- |
83
- | `close(result?)` | Closes the dialog, optionally passing back a result |
84
- | `afterClosed: Observable<any>` | Emits `result` after the dialog closes |
85
-
86
- ## SSR note
87
-
88
- `Dialog.open(...)` is a static/global API that's perfectly safe for a typical browser app. If you're using Angular SSR, this static instance is shared across concurrent server requests — instead of the static API, inject `NgxOverlayService` directly (which is per-injector/per-request safe).
89
-
90
- ## Dark mode and RTL
91
-
92
- Supported automatically (`light-dark()` + CSS logical properties).
1
+ # ngx-kit/dialog
2
+
3
+ مودال/دیالوگ که کاملاً روی `ngx-kit/overlay` سوار شده - نه `<dialog>` بومی (پشتیبانی مرورگرها)، نه یک استک DOM جدا برای هر دیالوگ. تمام رفتار مشترک (بک‌دراپ، وسط‌چین کردن، فوکوس‌تِرپ، بستن با Escape/کلیک بیرون، قفل اسکرول صفحه، رندر در top layer با Popover API) از `OverlayService` می‌آید؛ این ماژول فقط لایه‌ی «دیالوگ» رو روش اضافه می‌کنه: کانفیگ، تزریق داده، هدر/بادی/فوتر، و یک دیالوگ تایید/اعلان آماده.
4
+
5
+ هر بیلدینگ‌بلاک (پنل، دایرکتیوهای هدر/فوتر/بادی، دیالوگ تایید) کاملاً **standalone** و **signal-based** است - بدون NgModule، بدون `ChangeDetectorRef.detectChanges()` دستی، سازگار با zoneless.
6
+
7
+ ## نصب و راه‌اندازی
8
+
9
+ ```bash
10
+ npm install ngx-kit
11
+ ```
12
+
13
+ ```ts
14
+ // app.config.ts
15
+ import { ApplicationConfig } from '@angular/core';
16
+ import { provideNgxDialog } from 'ngx-kit/dialog';
17
+
18
+ export const appConfig: ApplicationConfig = {
19
+ providers: [provideNgxDialog()],
20
+ };
21
+ ```
22
+
23
+ ## باز کردن یک دیالوگ
24
+
25
+ با API استاتیک (بدون نیاز به inject دستی):
26
+
27
+ ```ts
28
+ import { Dialog } from 'ngx-kit/dialog';
29
+
30
+ const ref = Dialog.open<{ saved: boolean }>(EditUserComponent, {
31
+ data: { userId: 42 },
32
+ size: 'md',
33
+ header: { enable: true, title: 'ویرایش کاربر' },
34
+ });
35
+
36
+ ref.afterClosed.subscribe((result) => console.log('نتیجه:', result));
37
+ ```
38
+
39
+ یا با تزریق مستقیم سرویس (توصیه‌شده برای SSR - پایین‌تر ببینید):
40
+
41
+ ```ts
42
+ private dialog = inject(NgxDialogService);
43
+ this.dialog.open(EditUserComponent, { data: { userId: 42 } });
44
+ ```
45
+
46
+ داخل کامپوننت محتوای دیالوگ:
47
+
48
+ ```ts
49
+ @Component({ standalone: true, ... })
50
+ export class EditUserComponent {
51
+ private ref = inject<NgxDialogRef<{ saved: boolean }>>(DIALOG_REF);
52
+ data = inject<{ userId: number }>(DIALOG_DATA);
53
+
54
+ save() {
55
+ this.ref.close({ saved: true });
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### دایرکتیوهای layout داخل کامپوننت محتوا
61
+
62
+ ```html
63
+ <div *ngxDialogHeader>عنوان سفارشی</div>
64
+ <div *ngxDialogBody>محتوای اصلی، اسکرول‌پذیر</div>
65
+ <div *ngxDialogFooter align="end">
66
+ <button (click)="save()">ذخیره</button>
67
+ </div>
68
+ ```
69
+
70
+ یا به‌جای نوشتن این‌ها دستی، از هدر/فوتر خودکار استفاده کنید (بخش API رو ببینید) - اما هر دو رو با هم استفاده نکنید.
71
+
72
+ ## API
73
+
74
+ ### `NgxDialogService.open<R, DataType>(component, config?)` / `Dialog.open(...)`
75
+
76
+ | فیلد `config` | نوع | پیش‌فرض | توضیح |
77
+ | -------------------------------------------------- | ------------------------------------------ | ------------------------------------- | --------------------------------------------------------------------------------- |
78
+ | `data` | `DataType` | `{}` | از طریق `DIALOG_DATA` به کامپوننت محتوا می‌رسه |
79
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | - | یک پریست عرض/ماکس-عرض |
80
+ | `width` / `minWidth` / `maxWidth` | `string` | - | اندازه‌ی دستی (روی پریست `size` اولویت داره) |
81
+ | `height` / `minHeight` / `maxHeight` | `string` | - | |
82
+ | `panelClass` / `backdropClass` | `string \| string[]` | `'ngx-kit'` / `'ngx-dialog-backdrop'` | کلاس اضافه روی پنل/بک‌دراپ |
83
+ | `header.enable` / `.title` / `.showCloseButton` | - | `false` | هدر خودکار (اگه خودتون `*ngxDialogHeader` بذارید، این رو فعال نکنید) |
84
+ | `footer.enable` / `.closeText` / `.align` | - | `false` | فوتر خودکار با یک دکمه‌ی بستن |
85
+ | `closeOnOutsideClick` | `boolean` | `false` | کلیک بیرون از پنل ببندتش |
86
+ | `closeOnEscape` | `boolean` | `true` | Escape ببندتش |
87
+ | `disableClose` | `boolean` | `false` | معادل ست کردن هر دوی بالا روی `false` - فقط با کد قابل بسته‌شدنه |
88
+ | `beforeClose` | `() => boolean` | - | گارد سینک قبل از بسته‌شدن با Escape/کلیک بیرون (نه برای `dialogRef.close()` دستی) |
89
+ | `lockBodyScroll` | `boolean` | `true` | جلوگیری از اسکرول صفحه‌ی پشت دیالوگ |
90
+ | `autoFocus` / `restoreFocus` | `boolean` | `true` | |
91
+ | `usePopover` | `boolean` | `true` | رندر با Popover API (fallback خودکار در مرورگرهای قدیمی) |
92
+ | `role` | `'dialog' \| 'alertdialog'` | `'dialog'` | |
93
+ | `ariaLabel` / `ariaLabelledby` / `ariaDescribedby` | `string` | - | |
94
+ | `animation` | `'zoom' \| 'fade' \| 'slide-up' \| 'none'` | `'zoom'` | |
95
+ | `injector` | `Injector` | - | Injector والد برای کامپوننت محتوا |
96
+
97
+ ### `NgxDialogRef<R>`
98
+
99
+ | عضو | توضیح |
100
+ | -------------------- | -------------------------------------------------------------------- |
101
+ | `close(result?)` | دیالوگ رو می‌بنده؛ ایمن در برابر فراخوانی تکراری |
102
+ | `afterClosed` | `Observable<R \| undefined>` - دقیقاً یک‌بار، بعد از حذف کامل از DOM |
103
+ | `closing` / `closed` | سیگنال‌های `boolean` برای وضعیت لحظه‌ای |
104
+ | `beforeClose` | همون گارد بالا؛ می‌تونید بعد از باز شدن هم عوضش کنید |
105
+
106
+ ### `NgxDialogService`
107
+
108
+ | عضو | توضیح |
109
+ | --------------------------- | ------------------------------------------------ |
110
+ | `open(component, config?)` | دیالوگ رو باز می‌کنه، `NgxDialogRef` برمی‌گردونه |
111
+ | `confirm(options)` | `Observable<boolean>` |
112
+ | `alert(options)` | `Observable<void>` |
113
+ | `closeAll()` | همه‌ی دیالوگ‌های باز رو می‌بنده |
114
+ | `openDialogs` / `openCount` | سیگنال‌های ریدانلی برای دیالوگ‌های باز فعلی |
115
+
116
+ ## نکته‌ی SSR
117
+
118
+ `Dialog.open(...)` یک نمونه‌ی استاتیک/global نگه می‌داره که برای یک اپ مرورکری معمولی کاملاً امنه. اگه از Angular SSR استفاده می‌کنید، این نمونه‌ی استاتیک بین درخواست‌های هم‌زمان سرور مشترکه - به‌جای API استاتیک، مستقیماً `NgxDialogService` رو inject کنید (که per-injector/per-request امنه). `provideNgxDialog()` عمداً روی سرور این نمونه‌ی استاتیک رو ست نمی‌کنه تا این باگ به‌جای رخ‌دادن خاموش، فوراً با خطای «service not initialized» مشخص بشه.
119
+
120
+ ## دارک‌مود و RTL
121
+
122
+ خودکار پشتیبانی می‌شه (`light-dark()` + جهت از طریق `DirectionService` که `ngx-kit/overlay` براش استفاده می‌کنه).