prettier-modals-angular 0.1.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 +21 -0
- package/README.md +152 -0
- package/fesm2022/prettier-modals-angular.mjs +235 -0
- package/fesm2022/prettier-modals-angular.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/pretty-modal-close.directive.d.ts +19 -0
- package/lib/pretty-modal-trigger.directive.d.ts +21 -0
- package/lib/pretty-modal.directive.d.ts +32 -0
- package/lib/pretty-modal.service.d.ts +27 -0
- package/lib/pretty-modal.types.d.ts +21 -0
- package/package.json +42 -0
- package/public-api.d.ts +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 srdavo
|
|
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,152 @@
|
|
|
1
|
+
# prettier-modals-angular
|
|
2
|
+
|
|
3
|
+
Angular directives and an injectable service for [Prettier Modals](https://github.com/antuuanyf/prettier-modals) — beautiful open/close animations for native `<dialog>` elements, powered by GSAP Flip.
|
|
4
|
+
|
|
5
|
+
Standalone (no `NgModule`), SSR-safe, and runs animations outside the Angular zone.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install prettier-modals-angular prettier-modals gsap
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`prettier-modals`, `gsap`, and `@angular/core`/`@angular/common` are peer dependencies (Angular `>=17`).
|
|
14
|
+
|
|
15
|
+
Register the GSAP plugins once, e.g. in `main.ts`:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import gsap from 'gsap'
|
|
19
|
+
import { Flip } from 'gsap/Flip'
|
|
20
|
+
import { CustomEase } from 'gsap/CustomEase'
|
|
21
|
+
|
|
22
|
+
gsap.registerPlugin(Flip, CustomEase)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Declarative usage (directives)
|
|
26
|
+
|
|
27
|
+
Import the directives you need — or `PRETTY_MODAL_DIRECTIVES` for all of them — into a standalone component:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { Component } from '@angular/core'
|
|
31
|
+
import { PRETTY_MODAL_DIRECTIVES } from 'prettier-modals-angular'
|
|
32
|
+
|
|
33
|
+
@Component({
|
|
34
|
+
selector: 'app-settings',
|
|
35
|
+
standalone: true,
|
|
36
|
+
imports: [PRETTY_MODAL_DIRECTIVES],
|
|
37
|
+
template: `
|
|
38
|
+
<button [prettyModalTrigger]="'settings'" anchor="origin">Open</button>
|
|
39
|
+
|
|
40
|
+
<dialog id="settings" prettyModal anchor="origin"
|
|
41
|
+
(opened)="onOpen()" (closed)="onClose()">
|
|
42
|
+
<h1>Settings</h1>
|
|
43
|
+
<button prettyModalClose>Close</button>
|
|
44
|
+
</dialog>
|
|
45
|
+
`,
|
|
46
|
+
})
|
|
47
|
+
export class SettingsComponent {
|
|
48
|
+
onOpen() {}
|
|
49
|
+
onClose() {}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
No `ViewChild`, no `NgZone` boilerplate — the directives wire everything to the core.
|
|
54
|
+
|
|
55
|
+
### Directives
|
|
56
|
+
|
|
57
|
+
| Directive | Selector | Description |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `PrettyModalDirective` | `dialog[prettyModal]` | Marks the dialog (needs an `id`). Inputs: `anchor`, `animateCancel`. Outputs: `(opened)`, `(closed)`. |
|
|
60
|
+
| `PrettyModalTriggerDirective` | `[prettyModalTrigger]` | Opens the dialog whose id/element it's bound to, morphing from the host. Input: `anchor`. |
|
|
61
|
+
| `PrettyModalCloseDirective` | `[prettyModalClose]` | Closes the nearest ancestor `<dialog>` (or a given id/element). |
|
|
62
|
+
|
|
63
|
+
`animateCancel` (default `true`) intercepts the native Escape key so it closes with the animation instead of instantly.
|
|
64
|
+
|
|
65
|
+
## Trigger and dialog in separate components
|
|
66
|
+
|
|
67
|
+
The trigger and the `<dialog>` **don't have to live in the same component**. They're linked only by the dialog's `id`: the `PrettyModalService` is a root singleton shared by the whole app, and the core resolves the dialog through `document.getElementById`. So you can wrap each part in its own reusable component:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// button.component.ts — knows only the target dialog id
|
|
71
|
+
import { Component, Input } from '@angular/core'
|
|
72
|
+
import { PrettyModalTriggerDirective, type PrettyModalAnchor } from 'prettier-modals-angular'
|
|
73
|
+
|
|
74
|
+
@Component({
|
|
75
|
+
selector: 'app-modal-button',
|
|
76
|
+
standalone: true,
|
|
77
|
+
imports: [PrettyModalTriggerDirective],
|
|
78
|
+
template: `<button [prettyModalTrigger]="target" [anchor]="anchor"><ng-content /></button>`,
|
|
79
|
+
})
|
|
80
|
+
export class ModalButtonComponent {
|
|
81
|
+
@Input({ required: true }) target!: string
|
|
82
|
+
@Input() anchor?: PrettyModalAnchor
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// modal.component.ts — owns the dialog, declared independently
|
|
88
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core'
|
|
89
|
+
import { PrettyModalDirective, PrettyModalCloseDirective, type PrettyModalAnchor } from 'prettier-modals-angular'
|
|
90
|
+
|
|
91
|
+
@Component({
|
|
92
|
+
selector: 'app-modal',
|
|
93
|
+
standalone: true,
|
|
94
|
+
imports: [PrettyModalDirective, PrettyModalCloseDirective],
|
|
95
|
+
template: `
|
|
96
|
+
<dialog [id]="modalId" prettyModal [anchor]="anchor"
|
|
97
|
+
(opened)="opened.emit($event)" (closed)="closed.emit($event)">
|
|
98
|
+
<button prettyModalClose>Close</button>
|
|
99
|
+
<ng-content />
|
|
100
|
+
</dialog>
|
|
101
|
+
`,
|
|
102
|
+
})
|
|
103
|
+
export class ModalComponent {
|
|
104
|
+
// Don't name this input `id`: a native `id` would also be reflected onto the
|
|
105
|
+
// host <app-modal>, duplicating the id and breaking document.getElementById.
|
|
106
|
+
@Input({ required: true }) modalId!: string
|
|
107
|
+
@Input() anchor?: PrettyModalAnchor
|
|
108
|
+
@Output() opened = new EventEmitter<HTMLDialogElement>()
|
|
109
|
+
@Output() closed = new EventEmitter<HTMLDialogElement>()
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
A parent just drops both in and matches the id:
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<app-modal-button target="settings" anchor="origin">Open</app-modal-button>
|
|
117
|
+
|
|
118
|
+
<app-modal modalId="settings" anchor="origin">
|
|
119
|
+
<h1>Settings</h1>
|
|
120
|
+
</app-modal>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Two things to keep in mind:
|
|
124
|
+
|
|
125
|
+
- The dialog `id` must be **unique in the document** — Angular's view encapsulation scopes CSS, not `id` attributes. Avoid exposing a wrapper input literally named `id`: Angular reflects it onto the host element too, so it ends up duplicated (use `modalId` or similar, as above).
|
|
126
|
+
- The `<dialog>` must be **rendered in the DOM** when the trigger fires. Don't strip it with `@if`/`*ngIf`; it stays hidden until opened anyway.
|
|
127
|
+
|
|
128
|
+
## Imperative usage (service)
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { Component, inject } from '@angular/core'
|
|
132
|
+
import { PrettyModalService } from 'prettier-modals-angular'
|
|
133
|
+
|
|
134
|
+
@Component({ /* … */ })
|
|
135
|
+
export class MyComponent {
|
|
136
|
+
private readonly modal = inject(PrettyModalService)
|
|
137
|
+
|
|
138
|
+
open(trigger: HTMLElement) {
|
|
139
|
+
this.modal.open('settings', { trigger, anchor: 'origin' })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
close() {
|
|
143
|
+
this.modal.close('settings')
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`PrettyModalService` lazily creates the core in the browser only (SSR-safe) and runs every animation outside the Angular zone.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT © Antonio Monreal Diaz
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, NgZone, PLATFORM_ID, Injectable, ElementRef, EventEmitter, booleanAttribute, Output, Input, Directive, HostListener } from '@angular/core';
|
|
3
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
4
|
+
import { PrettyModal } from 'prettier-modals';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Injectable wrapper around the vanilla `PrettyModal` core.
|
|
8
|
+
*
|
|
9
|
+
* - Lazily instantiates the core in the browser only (SSR-safe).
|
|
10
|
+
* - Runs GSAP animations outside the Angular zone to avoid change detection
|
|
11
|
+
* on every animation frame.
|
|
12
|
+
*/
|
|
13
|
+
class PrettyModalService {
|
|
14
|
+
zone = inject(NgZone);
|
|
15
|
+
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
16
|
+
modal = null;
|
|
17
|
+
registry = new Map();
|
|
18
|
+
/** Open a dialog (id or element), morphing from `options.trigger`. */
|
|
19
|
+
open(dialog, options = {}) {
|
|
20
|
+
const modal = this.ensure();
|
|
21
|
+
if (!modal)
|
|
22
|
+
return;
|
|
23
|
+
this.zone.runOutsideAngular(() => modal.open(dialog, options));
|
|
24
|
+
}
|
|
25
|
+
/** Close a dialog, morphing back into its trigger. */
|
|
26
|
+
close(dialog, options = {}) {
|
|
27
|
+
const modal = this.ensure();
|
|
28
|
+
if (!modal)
|
|
29
|
+
return;
|
|
30
|
+
this.zone.runOutsideAngular(() => modal.close(dialog, options));
|
|
31
|
+
}
|
|
32
|
+
/** Tear down the core instance and remove injected styles. */
|
|
33
|
+
destroy() {
|
|
34
|
+
this.modal?.destroy();
|
|
35
|
+
this.modal = null;
|
|
36
|
+
}
|
|
37
|
+
// --- directive wiring --------------------------------------------------
|
|
38
|
+
register(id, registration) {
|
|
39
|
+
this.registry.set(id, registration);
|
|
40
|
+
}
|
|
41
|
+
unregister(id) {
|
|
42
|
+
this.registry.delete(id);
|
|
43
|
+
}
|
|
44
|
+
registration(id) {
|
|
45
|
+
return this.registry.get(id);
|
|
46
|
+
}
|
|
47
|
+
ensure() {
|
|
48
|
+
if (!this.isBrowser)
|
|
49
|
+
return null;
|
|
50
|
+
if (!this.modal) {
|
|
51
|
+
this.zone.runOutsideAngular(() => {
|
|
52
|
+
this.modal = new PrettyModal();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return this.modal;
|
|
56
|
+
}
|
|
57
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
58
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalService, providedIn: 'root' });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalService, decorators: [{
|
|
61
|
+
type: Injectable,
|
|
62
|
+
args: [{ providedIn: 'root' }]
|
|
63
|
+
}] });
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Marks a `<dialog>` as Pretty Modal managed. The dialog **must have an id** so
|
|
67
|
+
* triggers and close buttons can reference it.
|
|
68
|
+
*
|
|
69
|
+
* ```html
|
|
70
|
+
* <dialog id="settings" prettyModal anchor="origin"
|
|
71
|
+
* (opened)="onOpen()" (closed)="onClose()">…</dialog>
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
class PrettyModalDirective {
|
|
75
|
+
host = inject(ElementRef);
|
|
76
|
+
service = inject(PrettyModalService);
|
|
77
|
+
zone = inject(NgZone);
|
|
78
|
+
/** Default anchor for this dialog. Overridable per trigger. */
|
|
79
|
+
anchor;
|
|
80
|
+
/** Animate the close when the user presses Escape (native `cancel`). */
|
|
81
|
+
animateCancel = true;
|
|
82
|
+
opened = new EventEmitter();
|
|
83
|
+
closed = new EventEmitter();
|
|
84
|
+
get element() {
|
|
85
|
+
return this.host.nativeElement;
|
|
86
|
+
}
|
|
87
|
+
ngOnInit() {
|
|
88
|
+
const id = this.element.id;
|
|
89
|
+
if (!id) {
|
|
90
|
+
console.warn('[prettyModal] The <dialog> needs an id to be linked to its triggers.');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.service.register(id, this);
|
|
94
|
+
// Native Escape closes the dialog instantly, bypassing the animation.
|
|
95
|
+
// Intercept it and route through the service so it animates.
|
|
96
|
+
this.element.addEventListener('cancel', this.onCancel);
|
|
97
|
+
}
|
|
98
|
+
ngOnDestroy() {
|
|
99
|
+
if (this.element.id)
|
|
100
|
+
this.service.unregister(this.element.id);
|
|
101
|
+
this.element.removeEventListener('cancel', this.onCancel);
|
|
102
|
+
}
|
|
103
|
+
notifyOpened(dialog) {
|
|
104
|
+
this.zone.run(() => this.opened.emit(dialog));
|
|
105
|
+
}
|
|
106
|
+
notifyClosed(dialog) {
|
|
107
|
+
this.zone.run(() => this.closed.emit(dialog));
|
|
108
|
+
}
|
|
109
|
+
onCancel = (event) => {
|
|
110
|
+
if (!this.animateCancel)
|
|
111
|
+
return;
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
this.service.close(this.element, { onClose: (d) => this.notifyClosed(d) });
|
|
114
|
+
};
|
|
115
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
116
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.24", type: PrettyModalDirective, isStandalone: true, selector: "dialog[prettyModal]", inputs: { anchor: "anchor", animateCancel: ["animateCancel", "animateCancel", booleanAttribute] }, outputs: { opened: "opened", closed: "closed" }, ngImport: i0 });
|
|
117
|
+
}
|
|
118
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalDirective, decorators: [{
|
|
119
|
+
type: Directive,
|
|
120
|
+
args: [{
|
|
121
|
+
selector: 'dialog[prettyModal]',
|
|
122
|
+
standalone: true,
|
|
123
|
+
}]
|
|
124
|
+
}], propDecorators: { anchor: [{
|
|
125
|
+
type: Input
|
|
126
|
+
}], animateCancel: [{
|
|
127
|
+
type: Input,
|
|
128
|
+
args: [{ transform: booleanAttribute }]
|
|
129
|
+
}], opened: [{
|
|
130
|
+
type: Output
|
|
131
|
+
}], closed: [{
|
|
132
|
+
type: Output
|
|
133
|
+
}] } });
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Opens a Pretty Modal dialog when the host element is clicked, morphing the
|
|
137
|
+
* dialog out of this element.
|
|
138
|
+
*
|
|
139
|
+
* ```html
|
|
140
|
+
* <button [prettyModalTrigger]="'settings'" anchor="origin">Open</button>
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
class PrettyModalTriggerDirective {
|
|
144
|
+
host = inject(ElementRef);
|
|
145
|
+
service = inject(PrettyModalService);
|
|
146
|
+
/** Dialog id or element to open. */
|
|
147
|
+
target;
|
|
148
|
+
/** Overrides the dialog's default anchor for this trigger. */
|
|
149
|
+
anchor;
|
|
150
|
+
onClick() {
|
|
151
|
+
const id = typeof this.target === 'string' ? this.target : this.target.id;
|
|
152
|
+
const registration = id ? this.service.registration(id) : undefined;
|
|
153
|
+
this.service.open(this.target, {
|
|
154
|
+
trigger: this.host.nativeElement,
|
|
155
|
+
anchor: this.anchor ?? registration?.anchor,
|
|
156
|
+
onOpen: registration ? (d) => registration.notifyOpened(d) : undefined,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
160
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.24", type: PrettyModalTriggerDirective, isStandalone: true, selector: "[prettyModalTrigger]", inputs: { target: ["prettyModalTrigger", "target"], anchor: "anchor" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 });
|
|
161
|
+
}
|
|
162
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalTriggerDirective, decorators: [{
|
|
163
|
+
type: Directive,
|
|
164
|
+
args: [{
|
|
165
|
+
selector: '[prettyModalTrigger]',
|
|
166
|
+
standalone: true,
|
|
167
|
+
}]
|
|
168
|
+
}], propDecorators: { target: [{
|
|
169
|
+
type: Input,
|
|
170
|
+
args: [{ alias: 'prettyModalTrigger', required: true }]
|
|
171
|
+
}], anchor: [{
|
|
172
|
+
type: Input
|
|
173
|
+
}], onClick: [{
|
|
174
|
+
type: HostListener,
|
|
175
|
+
args: ['click']
|
|
176
|
+
}] } });
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Closes a Pretty Modal dialog when the host element is clicked. By default it
|
|
180
|
+
* closes the nearest ancestor `<dialog>`; pass an id/element to target another.
|
|
181
|
+
*
|
|
182
|
+
* ```html
|
|
183
|
+
* <button prettyModalClose>Close</button>
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
class PrettyModalCloseDirective {
|
|
187
|
+
host = inject(ElementRef);
|
|
188
|
+
service = inject(PrettyModalService);
|
|
189
|
+
/** Optional dialog id/element. Defaults to the nearest ancestor `<dialog>`. */
|
|
190
|
+
target;
|
|
191
|
+
onClick() {
|
|
192
|
+
const dialog = this.resolve();
|
|
193
|
+
if (!dialog)
|
|
194
|
+
return;
|
|
195
|
+
const id = typeof dialog === 'string' ? dialog : dialog.id;
|
|
196
|
+
const registration = id ? this.service.registration(id) : undefined;
|
|
197
|
+
this.service.close(dialog, {
|
|
198
|
+
onClose: registration ? (d) => registration.notifyClosed(d) : undefined,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
resolve() {
|
|
202
|
+
if (this.target)
|
|
203
|
+
return this.target;
|
|
204
|
+
return this.host.nativeElement.closest('dialog');
|
|
205
|
+
}
|
|
206
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalCloseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
207
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.24", type: PrettyModalCloseDirective, isStandalone: true, selector: "[prettyModalClose]", inputs: { target: ["prettyModalClose", "target"] }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 });
|
|
208
|
+
}
|
|
209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.24", ngImport: i0, type: PrettyModalCloseDirective, decorators: [{
|
|
210
|
+
type: Directive,
|
|
211
|
+
args: [{
|
|
212
|
+
selector: '[prettyModalClose]',
|
|
213
|
+
standalone: true,
|
|
214
|
+
}]
|
|
215
|
+
}], propDecorators: { target: [{
|
|
216
|
+
type: Input,
|
|
217
|
+
args: [{ alias: 'prettyModalClose' }]
|
|
218
|
+
}], onClick: [{
|
|
219
|
+
type: HostListener,
|
|
220
|
+
args: ['click']
|
|
221
|
+
}] } });
|
|
222
|
+
|
|
223
|
+
/** Convenience array to import all Pretty Modal directives at once. */
|
|
224
|
+
const PRETTY_MODAL_DIRECTIVES = [
|
|
225
|
+
PrettyModalDirective,
|
|
226
|
+
PrettyModalTriggerDirective,
|
|
227
|
+
PrettyModalCloseDirective,
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Generated bundle index. Do not edit.
|
|
232
|
+
*/
|
|
233
|
+
|
|
234
|
+
export { PRETTY_MODAL_DIRECTIVES, PrettyModalCloseDirective, PrettyModalDirective, PrettyModalService, PrettyModalTriggerDirective };
|
|
235
|
+
//# sourceMappingURL=prettier-modals-angular.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prettier-modals-angular.mjs","sources":["../../src/lib/pretty-modal.service.ts","../../src/lib/pretty-modal.directive.ts","../../src/lib/pretty-modal-trigger.directive.ts","../../src/lib/pretty-modal-close.directive.ts","../../src/public-api.ts","../../src/prettier-modals-angular.ts"],"sourcesContent":["import { Injectable, NgZone, PLATFORM_ID, inject } from '@angular/core'\nimport { isPlatformBrowser } from '@angular/common'\nimport { PrettyModal } from 'prettier-modals'\nimport type { PrettyModalOptions, PrettyModalRegistration } from './pretty-modal.types'\n\n/**\n * Injectable wrapper around the vanilla `PrettyModal` core.\n *\n * - Lazily instantiates the core in the browser only (SSR-safe).\n * - Runs GSAP animations outside the Angular zone to avoid change detection\n * on every animation frame.\n */\n@Injectable({ providedIn: 'root' })\nexport class PrettyModalService {\n private readonly zone = inject(NgZone)\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID))\n private modal: PrettyModal | null = null\n private readonly registry = new Map<string, PrettyModalRegistration>()\n\n /** Open a dialog (id or element), morphing from `options.trigger`. */\n open(dialog: string | HTMLDialogElement, options: PrettyModalOptions = {}): void {\n const modal = this.ensure()\n if (!modal) return\n this.zone.runOutsideAngular(() => modal.open(dialog, options))\n }\n\n /** Close a dialog, morphing back into its trigger. */\n close(dialog: string | HTMLDialogElement, options: PrettyModalOptions = {}): void {\n const modal = this.ensure()\n if (!modal) return\n this.zone.runOutsideAngular(() => modal.close(dialog, options))\n }\n\n /** Tear down the core instance and remove injected styles. */\n destroy(): void {\n this.modal?.destroy()\n this.modal = null\n }\n\n // --- directive wiring --------------------------------------------------\n\n register(id: string, registration: PrettyModalRegistration): void {\n this.registry.set(id, registration)\n }\n\n unregister(id: string): void {\n this.registry.delete(id)\n }\n\n registration(id: string): PrettyModalRegistration | undefined {\n return this.registry.get(id)\n }\n\n private ensure(): PrettyModal | null {\n if (!this.isBrowser) return null\n if (!this.modal) {\n this.zone.runOutsideAngular(() => {\n this.modal = new PrettyModal()\n })\n }\n return this.modal\n }\n}\n","import {\n Directive,\n ElementRef,\n EventEmitter,\n Input,\n NgZone,\n OnDestroy,\n OnInit,\n Output,\n booleanAttribute,\n inject,\n} from '@angular/core'\nimport { PrettyModalService } from './pretty-modal.service'\nimport type { PrettyModalAnchor, PrettyModalRegistration } from './pretty-modal.types'\n\n/**\n * Marks a `<dialog>` as Pretty Modal managed. The dialog **must have an id** so\n * triggers and close buttons can reference it.\n *\n * ```html\n * <dialog id=\"settings\" prettyModal anchor=\"origin\"\n * (opened)=\"onOpen()\" (closed)=\"onClose()\">…</dialog>\n * ```\n */\n@Directive({\n selector: 'dialog[prettyModal]',\n standalone: true,\n})\nexport class PrettyModalDirective implements PrettyModalRegistration, OnInit, OnDestroy {\n private readonly host = inject<ElementRef<HTMLDialogElement>>(ElementRef)\n private readonly service = inject(PrettyModalService)\n private readonly zone = inject(NgZone)\n\n /** Default anchor for this dialog. Overridable per trigger. */\n @Input() anchor?: PrettyModalAnchor\n\n /** Animate the close when the user presses Escape (native `cancel`). */\n @Input({ transform: booleanAttribute }) animateCancel = true\n\n @Output() opened = new EventEmitter<HTMLDialogElement>()\n @Output() closed = new EventEmitter<HTMLDialogElement>()\n\n get element(): HTMLDialogElement {\n return this.host.nativeElement\n }\n\n ngOnInit(): void {\n const id = this.element.id\n if (!id) {\n console.warn('[prettyModal] The <dialog> needs an id to be linked to its triggers.')\n return\n }\n this.service.register(id, this)\n // Native Escape closes the dialog instantly, bypassing the animation.\n // Intercept it and route through the service so it animates.\n this.element.addEventListener('cancel', this.onCancel)\n }\n\n ngOnDestroy(): void {\n if (this.element.id) this.service.unregister(this.element.id)\n this.element.removeEventListener('cancel', this.onCancel)\n }\n\n notifyOpened(dialog: HTMLDialogElement): void {\n this.zone.run(() => this.opened.emit(dialog))\n }\n\n notifyClosed(dialog: HTMLDialogElement): void {\n this.zone.run(() => this.closed.emit(dialog))\n }\n\n private readonly onCancel = (event: Event): void => {\n if (!this.animateCancel) return\n event.preventDefault()\n this.service.close(this.element, { onClose: (d) => this.notifyClosed(d) })\n }\n}\n","import { Directive, ElementRef, HostListener, Input, inject } from '@angular/core'\nimport { PrettyModalService } from './pretty-modal.service'\nimport type { PrettyModalAnchor } from './pretty-modal.types'\n\n/**\n * Opens a Pretty Modal dialog when the host element is clicked, morphing the\n * dialog out of this element.\n *\n * ```html\n * <button [prettyModalTrigger]=\"'settings'\" anchor=\"origin\">Open</button>\n * ```\n */\n@Directive({\n selector: '[prettyModalTrigger]',\n standalone: true,\n})\nexport class PrettyModalTriggerDirective {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef)\n private readonly service = inject(PrettyModalService)\n\n /** Dialog id or element to open. */\n @Input({ alias: 'prettyModalTrigger', required: true })\n target!: string | HTMLDialogElement\n\n /** Overrides the dialog's default anchor for this trigger. */\n @Input() anchor?: PrettyModalAnchor\n\n @HostListener('click')\n onClick(): void {\n const id = typeof this.target === 'string' ? this.target : this.target.id\n const registration = id ? this.service.registration(id) : undefined\n\n this.service.open(this.target, {\n trigger: this.host.nativeElement,\n anchor: this.anchor ?? registration?.anchor,\n onOpen: registration ? (d) => registration.notifyOpened(d) : undefined,\n })\n }\n}\n","import { Directive, ElementRef, HostListener, Input, inject } from '@angular/core'\nimport { PrettyModalService } from './pretty-modal.service'\n\n/**\n * Closes a Pretty Modal dialog when the host element is clicked. By default it\n * closes the nearest ancestor `<dialog>`; pass an id/element to target another.\n *\n * ```html\n * <button prettyModalClose>Close</button>\n * ```\n */\n@Directive({\n selector: '[prettyModalClose]',\n standalone: true,\n})\nexport class PrettyModalCloseDirective {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef)\n private readonly service = inject(PrettyModalService)\n\n /** Optional dialog id/element. Defaults to the nearest ancestor `<dialog>`. */\n @Input({ alias: 'prettyModalClose' })\n target?: string | HTMLDialogElement | ''\n\n @HostListener('click')\n onClick(): void {\n const dialog = this.resolve()\n if (!dialog) return\n\n const id = typeof dialog === 'string' ? dialog : dialog.id\n const registration = id ? this.service.registration(id) : undefined\n\n this.service.close(dialog, {\n onClose: registration ? (d) => registration.notifyClosed(d) : undefined,\n })\n }\n\n private resolve(): string | HTMLDialogElement | null {\n if (this.target) return this.target\n return this.host.nativeElement.closest('dialog')\n }\n}\n","import { PrettyModalDirective } from './lib/pretty-modal.directive'\nimport { PrettyModalTriggerDirective } from './lib/pretty-modal-trigger.directive'\nimport { PrettyModalCloseDirective } from './lib/pretty-modal-close.directive'\n\nexport { PrettyModalService } from './lib/pretty-modal.service'\nexport { PrettyModalDirective } from './lib/pretty-modal.directive'\nexport { PrettyModalTriggerDirective } from './lib/pretty-modal-trigger.directive'\nexport { PrettyModalCloseDirective } from './lib/pretty-modal-close.directive'\nexport type {\n PrettyModalAnchor,\n PrettyModalOptions,\n PrettyModalRegistration,\n} from './lib/pretty-modal.types'\n\n/** Convenience array to import all Pretty Modal directives at once. */\nexport const PRETTY_MODAL_DIRECTIVES = [\n PrettyModalDirective,\n PrettyModalTriggerDirective,\n PrettyModalCloseDirective,\n] as const\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;AAKA;;;;;;AAMG;MAEU,kBAAkB,CAAA;AACZ,IAAA,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;IACrB,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3D,KAAK,GAAuB,IAAI;AACvB,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAmC;;AAGtE,IAAA,IAAI,CAAC,MAAkC,EAAE,OAAA,GAA8B,EAAE,EAAA;AACvE,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC3B,QAAA,IAAI,CAAC,KAAK;YAAE;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChE;;AAGA,IAAA,KAAK,CAAC,MAAkC,EAAE,OAAA,GAA8B,EAAE,EAAA;AACxE,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC3B,QAAA,IAAI,CAAC,KAAK;YAAE;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjE;;IAGA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE;AACrB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;;IAIA,QAAQ,CAAC,EAAU,EAAE,YAAqC,EAAA;QACxD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC;IACrC;AAEA,IAAA,UAAU,CAAC,EAAU,EAAA;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B;AAEA,IAAA,YAAY,CAAC,EAAU,EAAA;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9B;IAEQ,MAAM,GAAA;QACZ,IAAI,CAAC,IAAI,CAAC,SAAS;AAAE,YAAA,OAAO,IAAI;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;AACf,YAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAK;AAC/B,gBAAA,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,EAAE;AAChC,YAAA,CAAC,CAAC;QACJ;QACA,OAAO,IAAI,CAAC,KAAK;IACnB;wGAhDW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,kBAAkB,cADL,MAAM,EAAA,CAAA;;4FACnB,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAD9B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACGlC;;;;;;;;AAQG;MAKU,oBAAoB,CAAA;AACd,IAAA,IAAI,GAAG,MAAM,CAAgC,UAAU,CAAC;AACxD,IAAA,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC;AACpC,IAAA,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;;AAG7B,IAAA,MAAM;;IAGyB,aAAa,GAAG,IAAI;AAElD,IAAA,MAAM,GAAG,IAAI,YAAY,EAAqB;AAC9C,IAAA,MAAM,GAAG,IAAI,YAAY,EAAqB;AAExD,IAAA,IAAI,OAAO,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa;IAChC;IAEA,QAAQ,GAAA;AACN,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE;QAC1B,IAAI,CAAC,EAAE,EAAE;AACP,YAAA,OAAO,CAAC,IAAI,CAAC,sEAAsE,CAAC;YACpF;QACF;QACA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;;;QAG/B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;IACxD;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;IAC3D;AAEA,IAAA,YAAY,CAAC,MAAyB,EAAA;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C;AAEA,IAAA,YAAY,CAAC,MAAyB,EAAA;AACpC,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C;AAEiB,IAAA,QAAQ,GAAG,CAAC,KAAY,KAAU;QACjD,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;QACzB,KAAK,CAAC,cAAc,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5E,IAAA,CAAC;wGA/CU,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,oBAAoB,qIASX,gBAAgB,CAAA,EAAA,EAAA,OAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FATzB,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAJhC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,qBAAqB;AAC/B,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;8BAOU,MAAM,EAAA,CAAA;sBAAd;gBAGuC,aAAa,EAAA,CAAA;sBAApD,KAAK;uBAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE;gBAE5B,MAAM,EAAA,CAAA;sBAAf;gBACS,MAAM,EAAA,CAAA;sBAAf;;;ACpCH;;;;;;;AAOG;MAKU,2BAA2B,CAAA;AACrB,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC;;AAIrD,IAAA,MAAM;;AAGG,IAAA,MAAM;IAGf,OAAO,GAAA;QACL,MAAM,EAAE,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE;AACzE,QAAA,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS;QAEnE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AAC7B,YAAA,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa;AAChC,YAAA,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,YAAY,EAAE,MAAM;AAC3C,YAAA,MAAM,EAAE,YAAY,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS;AACvE,SAAA,CAAC;IACJ;wGArBW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAA3B,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,sBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,CAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAA3B,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAJvC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,sBAAsB;AAChC,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;8BAOC,MAAM,EAAA,CAAA;sBADL,KAAK;AAAC,gBAAA,IAAA,EAAA,CAAA,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAI7C,MAAM,EAAA,CAAA;sBAAd;gBAGD,OAAO,EAAA,CAAA;sBADN,YAAY;uBAAC,OAAO;;;ACxBvB;;;;;;;AAOG;MAKU,yBAAyB,CAAA;AACnB,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC;;AAIrD,IAAA,MAAM;IAGN,OAAO,GAAA;AACL,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;AAC7B,QAAA,IAAI,CAAC,MAAM;YAAE;AAEb,QAAA,MAAM,EAAE,GAAG,OAAO,MAAM,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE;AAC1D,QAAA,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,SAAS;AAEnE,QAAA,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE;AACzB,YAAA,OAAO,EAAE,YAAY,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS;AACxE,SAAA,CAAC;IACJ;IAEQ,OAAO,GAAA;QACb,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC;IAClD;wGAxBW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAzB,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,CAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAAzB,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAJrC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;8BAOC,MAAM,EAAA,CAAA;sBADL,KAAK;uBAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAIpC,OAAO,EAAA,CAAA;sBADN,YAAY;uBAAC,OAAO;;;ACTvB;AACO,MAAM,uBAAuB,GAAG;IACrC,oBAAoB;IACpB,2BAA2B;IAC3B,yBAAyB;;;AClB3B;;AAEG;;;;"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/**
|
|
3
|
+
* Closes a Pretty Modal dialog when the host element is clicked. By default it
|
|
4
|
+
* closes the nearest ancestor `<dialog>`; pass an id/element to target another.
|
|
5
|
+
*
|
|
6
|
+
* ```html
|
|
7
|
+
* <button prettyModalClose>Close</button>
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare class PrettyModalCloseDirective {
|
|
11
|
+
private readonly host;
|
|
12
|
+
private readonly service;
|
|
13
|
+
/** Optional dialog id/element. Defaults to the nearest ancestor `<dialog>`. */
|
|
14
|
+
target?: string | HTMLDialogElement | '';
|
|
15
|
+
onClick(): void;
|
|
16
|
+
private resolve;
|
|
17
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PrettyModalCloseDirective, never>;
|
|
18
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PrettyModalCloseDirective, "[prettyModalClose]", never, { "target": { "alias": "prettyModalClose"; "required": false; }; }, {}, never, never, true, never>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PrettyModalAnchor } from './pretty-modal.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Opens a Pretty Modal dialog when the host element is clicked, morphing the
|
|
5
|
+
* dialog out of this element.
|
|
6
|
+
*
|
|
7
|
+
* ```html
|
|
8
|
+
* <button [prettyModalTrigger]="'settings'" anchor="origin">Open</button>
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare class PrettyModalTriggerDirective {
|
|
12
|
+
private readonly host;
|
|
13
|
+
private readonly service;
|
|
14
|
+
/** Dialog id or element to open. */
|
|
15
|
+
target: string | HTMLDialogElement;
|
|
16
|
+
/** Overrides the dialog's default anchor for this trigger. */
|
|
17
|
+
anchor?: PrettyModalAnchor;
|
|
18
|
+
onClick(): void;
|
|
19
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PrettyModalTriggerDirective, never>;
|
|
20
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PrettyModalTriggerDirective, "[prettyModalTrigger]", never, { "target": { "alias": "prettyModalTrigger"; "required": true; }; "anchor": { "alias": "anchor"; "required": false; }; }, {}, never, never, true, never>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
+
import type { PrettyModalAnchor, PrettyModalRegistration } from './pretty-modal.types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Marks a `<dialog>` as Pretty Modal managed. The dialog **must have an id** so
|
|
6
|
+
* triggers and close buttons can reference it.
|
|
7
|
+
*
|
|
8
|
+
* ```html
|
|
9
|
+
* <dialog id="settings" prettyModal anchor="origin"
|
|
10
|
+
* (opened)="onOpen()" (closed)="onClose()">…</dialog>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare class PrettyModalDirective implements PrettyModalRegistration, OnInit, OnDestroy {
|
|
14
|
+
private readonly host;
|
|
15
|
+
private readonly service;
|
|
16
|
+
private readonly zone;
|
|
17
|
+
/** Default anchor for this dialog. Overridable per trigger. */
|
|
18
|
+
anchor?: PrettyModalAnchor;
|
|
19
|
+
/** Animate the close when the user presses Escape (native `cancel`). */
|
|
20
|
+
animateCancel: boolean;
|
|
21
|
+
opened: EventEmitter<HTMLDialogElement>;
|
|
22
|
+
closed: EventEmitter<HTMLDialogElement>;
|
|
23
|
+
get element(): HTMLDialogElement;
|
|
24
|
+
ngOnInit(): void;
|
|
25
|
+
ngOnDestroy(): void;
|
|
26
|
+
notifyOpened(dialog: HTMLDialogElement): void;
|
|
27
|
+
notifyClosed(dialog: HTMLDialogElement): void;
|
|
28
|
+
private readonly onCancel;
|
|
29
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PrettyModalDirective, never>;
|
|
30
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PrettyModalDirective, "dialog[prettyModal]", never, { "anchor": { "alias": "anchor"; "required": false; }; "animateCancel": { "alias": "animateCancel"; "required": false; }; }, { "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
|
|
31
|
+
static ngAcceptInputType_animateCancel: unknown;
|
|
32
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PrettyModalOptions, PrettyModalRegistration } from './pretty-modal.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Injectable wrapper around the vanilla `PrettyModal` core.
|
|
5
|
+
*
|
|
6
|
+
* - Lazily instantiates the core in the browser only (SSR-safe).
|
|
7
|
+
* - Runs GSAP animations outside the Angular zone to avoid change detection
|
|
8
|
+
* on every animation frame.
|
|
9
|
+
*/
|
|
10
|
+
export declare class PrettyModalService {
|
|
11
|
+
private readonly zone;
|
|
12
|
+
private readonly isBrowser;
|
|
13
|
+
private modal;
|
|
14
|
+
private readonly registry;
|
|
15
|
+
/** Open a dialog (id or element), morphing from `options.trigger`. */
|
|
16
|
+
open(dialog: string | HTMLDialogElement, options?: PrettyModalOptions): void;
|
|
17
|
+
/** Close a dialog, morphing back into its trigger. */
|
|
18
|
+
close(dialog: string | HTMLDialogElement, options?: PrettyModalOptions): void;
|
|
19
|
+
/** Tear down the core instance and remove injected styles. */
|
|
20
|
+
destroy(): void;
|
|
21
|
+
register(id: string, registration: PrettyModalRegistration): void;
|
|
22
|
+
unregister(id: string): void;
|
|
23
|
+
registration(id: string): PrettyModalRegistration | undefined;
|
|
24
|
+
private ensure;
|
|
25
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PrettyModalService, never>;
|
|
26
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PrettyModalService>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PrettyModalAnchor = 'center' | 'origin';
|
|
2
|
+
/** Options accepted by {@link PrettyModalService.open} / `.close`. */
|
|
3
|
+
export interface PrettyModalOptions {
|
|
4
|
+
/** Element (or its id) the modal morphs from. */
|
|
5
|
+
trigger?: string | HTMLElement;
|
|
6
|
+
anchor?: PrettyModalAnchor;
|
|
7
|
+
duration?: number;
|
|
8
|
+
respectReducedMotion?: boolean;
|
|
9
|
+
onOpen?: (dialog: HTMLDialogElement) => void;
|
|
10
|
+
onClose?: (dialog: HTMLDialogElement) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Contract a `[prettyModal]` directive exposes to the service so triggers can
|
|
14
|
+
* read its default anchor and notify it of open/close events. Kept as an
|
|
15
|
+
* interface to avoid a circular dependency between the directive and service.
|
|
16
|
+
*/
|
|
17
|
+
export interface PrettyModalRegistration {
|
|
18
|
+
readonly anchor?: PrettyModalAnchor;
|
|
19
|
+
notifyOpened(dialog: HTMLDialogElement): void;
|
|
20
|
+
notifyClosed(dialog: HTMLDialogElement): void;
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prettier-modals-angular",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Angular directives and service for Prettier Modals — beautiful <dialog> animations powered by GSAP Flip.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"angular",
|
|
7
|
+
"modal",
|
|
8
|
+
"dialog",
|
|
9
|
+
"gsap",
|
|
10
|
+
"flip",
|
|
11
|
+
"animation",
|
|
12
|
+
"directive"
|
|
13
|
+
],
|
|
14
|
+
"author": "Antonio Monreal Diaz",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/antuuanyf/prettier-modals.git",
|
|
19
|
+
"directory": "packages/angular"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@angular/common": ">=17",
|
|
23
|
+
"@angular/core": ">=17",
|
|
24
|
+
"gsap": ">=3.12",
|
|
25
|
+
"prettier-modals": "^0.1.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"tslib": "^2.3.0"
|
|
29
|
+
},
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"module": "fesm2022/prettier-modals-angular.mjs",
|
|
32
|
+
"typings": "index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
"./package.json": {
|
|
35
|
+
"default": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./index.d.ts",
|
|
39
|
+
"default": "./fesm2022/prettier-modals-angular.mjs"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/public-api.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PrettyModalDirective } from './lib/pretty-modal.directive';
|
|
2
|
+
import { PrettyModalTriggerDirective } from './lib/pretty-modal-trigger.directive';
|
|
3
|
+
import { PrettyModalCloseDirective } from './lib/pretty-modal-close.directive';
|
|
4
|
+
export { PrettyModalService } from './lib/pretty-modal.service';
|
|
5
|
+
export { PrettyModalDirective } from './lib/pretty-modal.directive';
|
|
6
|
+
export { PrettyModalTriggerDirective } from './lib/pretty-modal-trigger.directive';
|
|
7
|
+
export { PrettyModalCloseDirective } from './lib/pretty-modal-close.directive';
|
|
8
|
+
export type { PrettyModalAnchor, PrettyModalOptions, PrettyModalRegistration, } from './lib/pretty-modal.types';
|
|
9
|
+
/** Convenience array to import all Pretty Modal directives at once. */
|
|
10
|
+
export declare const PRETTY_MODAL_DIRECTIVES: readonly [typeof PrettyModalDirective, typeof PrettyModalTriggerDirective, typeof PrettyModalCloseDirective];
|