@cdevhub/ngx-tw 0.4.0 → 0.6.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 +78 -15
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs +198 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +199 -220
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs +256 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +197 -278
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs +616 -0
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +556 -945
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +63 -2
- package/theme/_base.css +13 -0
- package/theme/_dark.css +110 -36
- package/theme/_high-contrast-dark.css +367 -0
- package/theme/_high-contrast.css +13 -2
- package/theme/_light.css +276 -0
- package/theme/_semantic.css +47 -12
- package/theme/_typography.css +17 -0
- package/theme/index.css +86 -7
- package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
- package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
- package/types/cdevhub-ngx-tw-button.d.ts +1 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
- package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
- package/types/cdevhub-ngx-tw-card.d.ts +11 -3
- package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
- package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
- package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
- package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
- package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
- package/types/cdevhub-ngx-tw-core.d.ts +152 -21
- package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
- package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
- package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +89 -19
- package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
- package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
- package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
- package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
- package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
- package/types/cdevhub-ngx-tw-input.d.ts +5 -8
- package/types/cdevhub-ngx-tw-item.d.ts +2 -0
- package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
- package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
- package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
- package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
- package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
- package/types/cdevhub-ngx-tw-select.d.ts +104 -33
- package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +96 -21
- package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
- package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
- package/types/cdevhub-ngx-tw-split.d.ts +32 -2
- package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
- package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
- package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
- package/types/cdevhub-ngx-tw-table.d.ts +53 -10
- package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
- package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
- package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
- package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
- package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
- package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
- package/types/cdevhub-ngx-tw-toast.d.ts +61 -12
- package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
- package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
- package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
- package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { ReplaySubject, filter, take, merge, Subject, defer, startWith } from 'rxjs';
|
|
6
|
-
import { CdkPortalOutlet } from '@angular/cdk/portal';
|
|
7
|
-
import { OverlayContainerCoordinator, mergeOverlayPanelClass, coerceOverlayDuration } from '@cdevhub/ngx-tw/core';
|
|
8
|
-
import { tv } from 'tailwind-variants';
|
|
2
|
+
import { InjectionToken, signal, inject, Injector, Injectable, makeEnvironmentProviders, Directive, input, computed } from '@angular/core';
|
|
3
|
+
import { ReplaySubject, Subject, filter, take, merge, defer, startWith } from 'rxjs';
|
|
4
|
+
import { DialogConfig } from '@angular/cdk/dialog';
|
|
9
5
|
import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
10
6
|
import { _IdGenerator } from '@angular/cdk/a11y';
|
|
11
7
|
import * as i1 from '@angular/cdk/scrolling';
|
|
@@ -55,130 +51,22 @@ const TW_DIALOG_DATA = new InjectionToken('TW_DIALOG_DATA');
|
|
|
55
51
|
/** Injection token for application-wide default dialog options. Set via `provideTwDialog()`. */
|
|
56
52
|
const TW_DIALOG_DEFAULT_OPTIONS = new InjectionToken('TW_DIALOG_DEFAULT_OPTIONS');
|
|
57
53
|
|
|
58
|
-
// Dialog uses a `data-[state]` driven CSS transition rather than the project's
|
|
59
|
-
// `animate.enter`/`animate.leave` keyframes. Justification:
|
|
60
|
-
// 1. The ref owns the open/close lifecycle (state signal, observables) and
|
|
61
|
-
// needs runtime-configurable enter/exit durations per `TwDialog.open()`
|
|
62
|
-
// call — `animate.enter` only accepts a static class name.
|
|
63
|
-
// 2. The container drives the same CSS variables (opacity + scale) for both
|
|
64
|
-
// transitions, so a single `transition-[opacity,transform]` rule with a
|
|
65
|
-
// data-state attribute is simpler than two keyframe declarations.
|
|
66
|
-
// All other library overlays (popover, menu, tooltip) use animate.enter/leave;
|
|
67
|
-
// this divergence is intentional and isolated to the dialog container.
|
|
68
|
-
const dialogContainerVariants = tv({
|
|
69
|
-
slots: {
|
|
70
|
-
host: 'relative flex flex-col outline-none bg-surface-raised text-fg rounded-lg shadow-md border border-border overflow-hidden transition-[opacity,transform] ease-out motion-reduce:transition-none opacity-0 scale-95 data-[state=open]:opacity-100 data-[state=open]:scale-100 data-[state=closing]:opacity-0 data-[state=closing]:scale-95',
|
|
71
|
-
},
|
|
72
|
-
variants: {
|
|
73
|
-
size: {
|
|
74
|
-
xs: { host: 'w-full max-w-sm max-h-[85vh]' },
|
|
75
|
-
sm: { host: 'w-full max-w-md max-h-[85vh]' },
|
|
76
|
-
md: { host: 'w-full max-w-lg max-h-[85vh]' },
|
|
77
|
-
lg: { host: 'w-full max-w-2xl max-h-[85vh]' },
|
|
78
|
-
xl: { host: 'w-full max-w-4xl max-h-[85vh]' },
|
|
79
|
-
fullscreen: {
|
|
80
|
-
host: 'w-screen h-screen max-w-none max-h-none rounded-none border-0',
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
defaultVariants: { size: 'md' },
|
|
85
|
-
}, { twMerge: true });
|
|
86
|
-
/**
|
|
87
|
-
* Dialog container rendered inside the CDK overlay. Wraps the user-provided
|
|
88
|
-
* content in a Tailwind-styled surface and coordinates enter/exit transitions
|
|
89
|
-
* with {@link TwDialogRef}.
|
|
90
|
-
*
|
|
91
|
-
* The animation state machine, `aria-describedby` queue, and panel-class
|
|
92
|
-
* merge are shared with `SheetContainer` via {@link OverlayContainerCoordinator}
|
|
93
|
-
* (component-scoped — see `providers: [OverlayContainerCoordinator]`).
|
|
94
|
-
*
|
|
95
|
-
* @docs-private
|
|
96
|
-
*/
|
|
97
|
-
class DialogContainer extends CdkDialogContainer {
|
|
98
|
-
coordinator = inject(OverlayContainerCoordinator);
|
|
99
|
-
/** Lifecycle state of the dialog's enter/exit animation. */
|
|
100
|
-
state = this.coordinator.state;
|
|
101
|
-
/** Emits whenever the animation state transitions. */
|
|
102
|
-
animationStateChanged = this.coordinator.animationStateChanged;
|
|
103
|
-
/** Resolved enter-animation duration in ms. */
|
|
104
|
-
enterAnimationDuration;
|
|
105
|
-
/** Resolved exit-animation duration in ms. */
|
|
106
|
-
exitAnimationDuration;
|
|
107
|
-
sizeVariant = computed(() => {
|
|
108
|
-
const size = this._config.size ?? 'md';
|
|
109
|
-
return dialogContainerVariants({ size });
|
|
110
|
-
}, /* @ts-ignore */
|
|
111
|
-
...(ngDevMode ? [{ debugName: "sizeVariant" }] : /* istanbul ignore next */ []));
|
|
112
|
-
hostClasses = computed(() => mergeOverlayPanelClass(this.sizeVariant().host(), this._config.panelClass), /* @ts-ignore */
|
|
113
|
-
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
114
|
-
ariaDescribedByAttr = computed(() => this._config.ariaDescribedBy ||
|
|
115
|
-
this.coordinator.describedByIds()[0] ||
|
|
116
|
-
null, /* @ts-ignore */
|
|
117
|
-
...(ngDevMode ? [{ debugName: "ariaDescribedByAttr" }] : /* istanbul ignore next */ []));
|
|
118
|
-
transitionDuration = this.coordinator.transitionDuration;
|
|
119
|
-
constructor() {
|
|
120
|
-
super();
|
|
121
|
-
this.enterAnimationDuration = coerceOverlayDuration(this._config.enterAnimationDuration, 150);
|
|
122
|
-
this.exitAnimationDuration = coerceOverlayDuration(this._config.exitAnimationDuration, 120);
|
|
123
|
-
this.coordinator.setDurations(this.enterAnimationDuration, this.exitAnimationDuration);
|
|
124
|
-
}
|
|
125
|
-
_contentAttached() {
|
|
126
|
-
super._contentAttached();
|
|
127
|
-
this.coordinator.startEnterAnimation();
|
|
128
|
-
}
|
|
129
|
-
/** Triggered by the dialog ref to play the exit transition before disposing the overlay. */
|
|
130
|
-
_startExitAnimation() {
|
|
131
|
-
this.coordinator.startExitAnimation();
|
|
132
|
-
}
|
|
133
|
-
/** Registers a description id for the container's `aria-describedby`. */
|
|
134
|
-
_addAriaDescribedBy(id) {
|
|
135
|
-
this.coordinator.addAriaDescribedBy(id);
|
|
136
|
-
}
|
|
137
|
-
/** Removes a previously registered description id. */
|
|
138
|
-
_removeAriaDescribedBy(id) {
|
|
139
|
-
this.coordinator.removeAriaDescribedBy(id);
|
|
140
|
-
}
|
|
141
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DialogContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
142
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: DialogContainer, isStandalone: true, selector: "tw-dialog-container", host: { attributes: { "tabindex": "-1" }, properties: { "attr.id": "_config.id || null", "attr.role": "_config.role", "attr.aria-modal": "_config.ariaModal", "attr.aria-labelledby": "_config.ariaLabel ? null : _ariaLabelledByQueue[0]", "attr.aria-label": "_config.ariaLabel", "attr.aria-describedby": "ariaDescribedByAttr()", "attr.data-state": "state()", "class": "hostClasses()", "style.transition-duration.ms": "transitionDuration()" } }, providers: [OverlayContainerCoordinator], usesInheritance: true, ngImport: i0, template: '<ng-template cdkPortalOutlet />', isInline: true, dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
143
|
-
}
|
|
144
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: DialogContainer, decorators: [{
|
|
145
|
-
type: Component,
|
|
146
|
-
args: [{
|
|
147
|
-
selector: 'tw-dialog-container',
|
|
148
|
-
template: '<ng-template cdkPortalOutlet />',
|
|
149
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
150
|
-
encapsulation: ViewEncapsulation.None,
|
|
151
|
-
imports: [CdkPortalOutlet],
|
|
152
|
-
providers: [OverlayContainerCoordinator],
|
|
153
|
-
host: {
|
|
154
|
-
tabindex: '-1',
|
|
155
|
-
'[attr.id]': '_config.id || null',
|
|
156
|
-
'[attr.role]': '_config.role',
|
|
157
|
-
'[attr.aria-modal]': '_config.ariaModal',
|
|
158
|
-
'[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledByQueue[0]',
|
|
159
|
-
'[attr.aria-label]': '_config.ariaLabel',
|
|
160
|
-
'[attr.aria-describedby]': 'ariaDescribedByAttr()',
|
|
161
|
-
'[attr.data-state]': 'state()',
|
|
162
|
-
'[class]': 'hostClasses()',
|
|
163
|
-
'[style.transition-duration.ms]': 'transitionDuration()',
|
|
164
|
-
},
|
|
165
|
-
}]
|
|
166
|
-
}], ctorParameters: () => [] });
|
|
167
|
-
|
|
168
54
|
/**
|
|
169
55
|
* Reference to a dialog opened via {@link TwDialog.open}. Drives the dialog
|
|
170
56
|
* lifecycle (close, state, observables) and forwards useful overlay streams.
|
|
57
|
+
*
|
|
58
|
+
* The ref is returned **synchronously** from `open()`, but the dialog's render
|
|
59
|
+
* layer (`@angular/cdk/dialog` + the Tailwind container) is loaded through a
|
|
60
|
+
* dynamic `import()`. The ref therefore starts *detached*: `id`, `state`,
|
|
61
|
+
* `close()`, the lifecycle observables, and panel/size mutations all work
|
|
62
|
+
* immediately (mutations are buffered and replayed on attach), but the rendered
|
|
63
|
+
* component instance does not exist yet — read it via {@link whenComponentReady}
|
|
64
|
+
* instead of a synchronous `componentInstance` field.
|
|
171
65
|
*/
|
|
172
66
|
class TwDialogRef {
|
|
173
|
-
cdkRef;
|
|
174
67
|
config;
|
|
175
|
-
|
|
176
|
-
/** Unique ID of the dialog. */
|
|
68
|
+
/** Unique ID of the dialog. Generated eagerly by the service, so it is valid the instant `open()` returns. */
|
|
177
69
|
id;
|
|
178
|
-
/** Instance of the component rendered inside the dialog, or `null` for template dialogs. */
|
|
179
|
-
componentInstance = null;
|
|
180
|
-
/** `ComponentRef` of the content component, or `null` for template dialogs. */
|
|
181
|
-
componentRef = null;
|
|
182
70
|
/** Current lifecycle state. Reactively readable. */
|
|
183
71
|
state;
|
|
184
72
|
/** When `true`, close-via-escape and close-via-backdrop are disabled. */
|
|
@@ -188,17 +76,67 @@ class TwDialogRef {
|
|
|
188
76
|
afterOpenedSubject = new ReplaySubject(1);
|
|
189
77
|
beforeClosedSubject = new ReplaySubject(1);
|
|
190
78
|
afterClosedSubject = new ReplaySubject(1);
|
|
79
|
+
// Facade-owned pass-throughs for the raw overlay streams, so a consumer that
|
|
80
|
+
// subscribes before the render chunk attaches still receives events once it
|
|
81
|
+
// does — the pre-deferral behaviour when `open()` wrapped a live `cdkRef`.
|
|
82
|
+
backdropClickSubject = new Subject();
|
|
83
|
+
keydownEventsSubject = new Subject();
|
|
84
|
+
cdkRef = null;
|
|
85
|
+
container = null;
|
|
86
|
+
componentInstanceValue = null;
|
|
87
|
+
componentRefValue = null;
|
|
88
|
+
resolveComponentReady;
|
|
89
|
+
componentReadyPromise = new Promise((resolve) => {
|
|
90
|
+
this.resolveComponentReady = resolve;
|
|
91
|
+
});
|
|
92
|
+
// Buffered mutations issued before the render chunk attached the CDK backend.
|
|
93
|
+
pendingPanelAdds = [];
|
|
94
|
+
pendingPanelRemoves = [];
|
|
95
|
+
pendingSize = null;
|
|
191
96
|
pendingResult;
|
|
192
97
|
closeFocusOrigin;
|
|
193
|
-
constructor(
|
|
194
|
-
this.cdkRef = cdkRef;
|
|
98
|
+
constructor(id, config) {
|
|
195
99
|
this.config = config;
|
|
196
|
-
this.
|
|
197
|
-
this.id = cdkRef.id;
|
|
100
|
+
this.id = id;
|
|
198
101
|
this.disableClose = config.disableClose;
|
|
199
102
|
this.state = this.stateSignal.asReadonly();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The Tailwind container instance, or `null` until the dialog has attached.
|
|
106
|
+
* `null` is the normal value for the first tick after `open()` returns,
|
|
107
|
+
* because the render layer is loaded through a dynamic `import()`.
|
|
108
|
+
*
|
|
109
|
+
* Only `state`, `animationStateChanged`, `enterAnimationDuration` and
|
|
110
|
+
* `exitAnimationDuration` are supported reads; the `_`-prefixed members are
|
|
111
|
+
* library-internal wiring and may change without a major bump. Prefer
|
|
112
|
+
* {@link state} and {@link afterOpened} on the ref itself.
|
|
113
|
+
*/
|
|
114
|
+
get containerInstance() {
|
|
115
|
+
return this.container;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @internal Wire this facade to its CDK backend. Called from the dialog
|
|
119
|
+
* renderer **inside** `cdkDialog.open()`'s `providers` callback — the same
|
|
120
|
+
* point the constructor ran before deferral — so subscriptions to
|
|
121
|
+
* `animationStateChanged` are in place before the container emits `'open'`.
|
|
122
|
+
*/
|
|
123
|
+
_attach(cdkRef, container) {
|
|
124
|
+
this.cdkRef = cdkRef;
|
|
125
|
+
this.container = container;
|
|
126
|
+
// Forward the raw overlay streams into the facade pass-throughs.
|
|
127
|
+
cdkRef.backdropClick.subscribe(this.backdropClickSubject);
|
|
128
|
+
cdkRef.keydownEvents.subscribe(this.keydownEventsSubject);
|
|
200
129
|
cdkRef.addPanelClass('tw-dialog-panel');
|
|
201
|
-
const
|
|
130
|
+
for (const cls of this.pendingPanelAdds)
|
|
131
|
+
cdkRef.addPanelClass(cls);
|
|
132
|
+
for (const cls of this.pendingPanelRemoves)
|
|
133
|
+
cdkRef.removePanelClass(cls);
|
|
134
|
+
if (this.pendingSize)
|
|
135
|
+
cdkRef.updateSize(this.pendingSize[0], this.pendingSize[1]);
|
|
136
|
+
this.pendingPanelAdds.length = 0;
|
|
137
|
+
this.pendingPanelRemoves.length = 0;
|
|
138
|
+
this.pendingSize = null;
|
|
139
|
+
const animationChanges = container.animationStateChanged;
|
|
202
140
|
animationChanges
|
|
203
141
|
.pipe(filter((event) => event.state === 'open'), take(1))
|
|
204
142
|
.subscribe(() => {
|
|
@@ -226,6 +164,38 @@ class TwDialogRef {
|
|
|
226
164
|
this.closeWithOrigin(event.type === 'keydown' ? 'keyboard' : 'mouse');
|
|
227
165
|
});
|
|
228
166
|
}
|
|
167
|
+
/** @internal Record the rendered component after `cdkDialog.open()` returns. */
|
|
168
|
+
_setComponent(instance, ref) {
|
|
169
|
+
this.componentInstanceValue = instance;
|
|
170
|
+
this.componentRefValue = ref;
|
|
171
|
+
this.resolveComponentReady(instance);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Resolves with the rendered content-component instance once the dialog's
|
|
175
|
+
* render chunk has loaded and attached. Resolves `null` for template dialogs,
|
|
176
|
+
* and for a dialog closed before it ever opened.
|
|
177
|
+
*
|
|
178
|
+
* Replaces the former synchronous `componentInstance` field, which cannot be
|
|
179
|
+
* populated before the deferred render chunk lands.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* const ref = dialog.open(EditorDialog);
|
|
184
|
+
* const editor = await ref.whenComponentReady();
|
|
185
|
+
* editor?.focusFirstField();
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
whenComponentReady() {
|
|
189
|
+
return this.componentReadyPromise;
|
|
190
|
+
}
|
|
191
|
+
/** The rendered component instance, or `null` if not yet attached / a template dialog. Prefer {@link whenComponentReady}. */
|
|
192
|
+
get componentInstance() {
|
|
193
|
+
return this.componentInstanceValue;
|
|
194
|
+
}
|
|
195
|
+
/** The rendered `ComponentRef`, or `null` if not yet attached / a template dialog. */
|
|
196
|
+
get componentRef() {
|
|
197
|
+
return this.componentRefValue;
|
|
198
|
+
}
|
|
229
199
|
/**
|
|
230
200
|
* Closes the dialog. The exit animation runs before the overlay is disposed.
|
|
231
201
|
* @param result Value forwarded to `afterClosed()` subscribers.
|
|
@@ -245,27 +215,42 @@ class TwDialogRef {
|
|
|
245
215
|
afterClosed() {
|
|
246
216
|
return this.afterClosedSubject.asObservable();
|
|
247
217
|
}
|
|
248
|
-
/** Backdrop click stream (emits even when `disableClose` is set). */
|
|
218
|
+
/** Backdrop click stream (emits even when `disableClose` is set). Buffered — a subscription made before the dialog attaches receives events once it does. */
|
|
249
219
|
backdropClick() {
|
|
250
|
-
return this.
|
|
220
|
+
return this.backdropClickSubject.asObservable();
|
|
251
221
|
}
|
|
252
|
-
/** Keydown event stream for the overlay. */
|
|
222
|
+
/** Keydown event stream for the overlay. Buffered — a subscription made before the dialog attaches receives events once it does. */
|
|
253
223
|
keydownEvents() {
|
|
254
|
-
return this.
|
|
224
|
+
return this.keydownEventsSubject.asObservable();
|
|
255
225
|
}
|
|
256
|
-
/** Updates the dialog's width/height. Pass empty string to reset a dimension. */
|
|
226
|
+
/** Updates the dialog's width/height. Pass empty string to reset a dimension. Buffered until attach. */
|
|
257
227
|
updateSize(width = '', height = '') {
|
|
258
|
-
this.cdkRef
|
|
228
|
+
if (this.cdkRef) {
|
|
229
|
+
this.cdkRef.updateSize(width, height);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
this.pendingSize = [width, height];
|
|
233
|
+
}
|
|
259
234
|
return this;
|
|
260
235
|
}
|
|
261
|
-
/** Adds CSS classes to the overlay panel. */
|
|
236
|
+
/** Adds CSS classes to the overlay panel. Buffered until attach. */
|
|
262
237
|
addPanelClass(classes) {
|
|
263
|
-
this.cdkRef
|
|
238
|
+
if (this.cdkRef) {
|
|
239
|
+
this.cdkRef.addPanelClass(classes);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
this.pendingPanelAdds.push(...(Array.isArray(classes) ? classes : [classes]));
|
|
243
|
+
}
|
|
264
244
|
return this;
|
|
265
245
|
}
|
|
266
|
-
/** Removes CSS classes from the overlay panel. */
|
|
246
|
+
/** Removes CSS classes from the overlay panel. Buffered until attach. */
|
|
267
247
|
removePanelClass(classes) {
|
|
268
|
-
this.cdkRef
|
|
248
|
+
if (this.cdkRef) {
|
|
249
|
+
this.cdkRef.removePanelClass(classes);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
this.pendingPanelRemoves.push(...(Array.isArray(classes) ? classes : [classes]));
|
|
253
|
+
}
|
|
269
254
|
return this;
|
|
270
255
|
}
|
|
271
256
|
closeWithOrigin(origin, result) {
|
|
@@ -273,7 +258,7 @@ class TwDialogRef {
|
|
|
273
258
|
return;
|
|
274
259
|
const predicate = this.config.closePredicate;
|
|
275
260
|
if (predicate &&
|
|
276
|
-
!predicate(result, this.config, this.
|
|
261
|
+
!predicate(result, this.config, this.componentInstanceValue)) {
|
|
277
262
|
return;
|
|
278
263
|
}
|
|
279
264
|
this.pendingResult = result;
|
|
@@ -281,8 +266,15 @@ class TwDialogRef {
|
|
|
281
266
|
this.stateSignal.set('closing');
|
|
282
267
|
this.beforeClosedSubject.next(result);
|
|
283
268
|
this.beforeClosedSubject.complete();
|
|
269
|
+
if (!this.cdkRef) {
|
|
270
|
+
// Closed before the render chunk attached: the overlay was never created,
|
|
271
|
+
// so there is nothing to animate or dispose. Synthesize the closed state
|
|
272
|
+
// and let the service skip opening entirely (it checks state()).
|
|
273
|
+
this.finishClose();
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
284
276
|
this.cdkRef.overlayRef.detachBackdrop();
|
|
285
|
-
this.
|
|
277
|
+
this.container._startExitAnimation();
|
|
286
278
|
}
|
|
287
279
|
finishClose() {
|
|
288
280
|
if (this.stateSignal() === 'closed')
|
|
@@ -290,25 +282,41 @@ class TwDialogRef {
|
|
|
290
282
|
this.stateSignal.set('closed');
|
|
291
283
|
this.afterClosedSubject.next(this.pendingResult);
|
|
292
284
|
this.afterClosedSubject.complete();
|
|
293
|
-
if
|
|
285
|
+
// Idempotent — a no-op if _setComponent already resolved with an instance.
|
|
286
|
+
this.resolveComponentReady(null);
|
|
287
|
+
this.backdropClickSubject.complete();
|
|
288
|
+
this.keydownEventsSubject.complete();
|
|
289
|
+
if (this.cdkRef?.containerInstance) {
|
|
294
290
|
this.cdkRef.close(this.pendingResult, { focusOrigin: this.closeFocusOrigin });
|
|
295
291
|
}
|
|
296
|
-
this.
|
|
292
|
+
this.componentInstanceValue = null;
|
|
297
293
|
}
|
|
298
294
|
}
|
|
299
295
|
|
|
296
|
+
let nextDialogId = 0;
|
|
297
|
+
function generateDialogId() {
|
|
298
|
+
return `tw-dialog-${++nextDialogId}`;
|
|
299
|
+
}
|
|
300
300
|
/**
|
|
301
301
|
* Opens Tailwind-styled modal dialogs. Composes `@angular/cdk/dialog` for focus
|
|
302
302
|
* trapping, portals, overlay plumbing, and adds a Tailwind container, richer
|
|
303
303
|
* ref API, and animation lifecycle.
|
|
304
304
|
*
|
|
305
|
+
* The rendering layer (`@angular/cdk/dialog` + the Tailwind container) is loaded
|
|
306
|
+
* through a dynamic `import()` on the first `open()` call, so merely registering
|
|
307
|
+
* this service costs nothing in the initial bundle. `open()` still returns its
|
|
308
|
+
* {@link TwDialogRef} synchronously — the dialog is rendered once the chunk
|
|
309
|
+
* lands. Read the rendered component via {@link TwDialogRef.whenComponentReady}.
|
|
310
|
+
*
|
|
305
311
|
* Not `providedIn: 'root'` — register it via {@link provideTwDialog}.
|
|
306
312
|
*/
|
|
307
313
|
class TwDialog {
|
|
308
|
-
cdkDialog = inject(Dialog);
|
|
309
314
|
injector = inject(Injector);
|
|
310
315
|
defaultOptions = inject(TW_DIALOG_DEFAULT_OPTIONS, { optional: true }) ?? {};
|
|
311
316
|
parentDialog = inject(TwDialog, { optional: true, skipSelf: true });
|
|
317
|
+
/** Cached renderer chunk import — kicked off on the first `open()`. */
|
|
318
|
+
rendererPromise = null;
|
|
319
|
+
destroyed = false;
|
|
312
320
|
openDialogsAtThisLevel = signal([], /* @ts-ignore */
|
|
313
321
|
...(ngDevMode ? [{ debugName: "openDialogsAtThisLevel" }] : /* istanbul ignore next */ []));
|
|
314
322
|
afterOpenedSubject = new Subject();
|
|
@@ -332,64 +340,25 @@ class TwDialog {
|
|
|
332
340
|
* Opens a dialog using the given component or template.
|
|
333
341
|
* @param content Component class or `TemplateRef`.
|
|
334
342
|
* @param config Options merged over the application defaults.
|
|
335
|
-
* @returns Reference controlling the opened dialog.
|
|
343
|
+
* @returns Reference controlling the opened dialog, returned synchronously.
|
|
336
344
|
*/
|
|
337
345
|
open(content, config) {
|
|
338
346
|
const merged = this.resolveConfig(config);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
height: merged.height,
|
|
349
|
-
minWidth: merged.minWidth,
|
|
350
|
-
minHeight: merged.minHeight,
|
|
351
|
-
maxWidth: merged.maxWidth,
|
|
352
|
-
maxHeight: merged.maxHeight,
|
|
353
|
-
direction: merged.direction,
|
|
354
|
-
ariaDescribedBy: merged.ariaDescribedBy,
|
|
355
|
-
ariaLabelledBy: merged.ariaLabelledBy,
|
|
356
|
-
ariaLabel: merged.ariaLabel,
|
|
357
|
-
ariaModal: merged.ariaModal,
|
|
358
|
-
autoFocus: merged.autoFocus,
|
|
359
|
-
restoreFocus: merged.restoreFocus,
|
|
360
|
-
scrollStrategy: merged.scrollStrategy ?? this.resolveScrollStrategy(merged.scrollBehavior),
|
|
361
|
-
closeOnNavigation: merged.closeOnNavigation,
|
|
362
|
-
viewContainerRef: merged.viewContainerRef,
|
|
363
|
-
injector: merged.injector,
|
|
364
|
-
// We handle close/Escape/backdrop ourselves so we can run the exit animation.
|
|
365
|
-
disableClose: true,
|
|
366
|
-
closeOnOverlayDetachments: false,
|
|
367
|
-
container: {
|
|
368
|
-
type: DialogContainer,
|
|
369
|
-
providers: () => [
|
|
370
|
-
{ provide: TwDialogConfig, useValue: merged },
|
|
371
|
-
{ provide: DialogConfig, useValue: merged },
|
|
372
|
-
],
|
|
373
|
-
},
|
|
374
|
-
providers: (_cdkRef, _cdkConfig, container) => {
|
|
375
|
-
twRef = new TwDialogRef(_cdkRef, merged, container);
|
|
376
|
-
const providers = [
|
|
377
|
-
{ provide: TwDialogRef, useValue: twRef },
|
|
378
|
-
{ provide: TW_DIALOG_DATA, useValue: merged.data ?? null },
|
|
379
|
-
];
|
|
380
|
-
if (Array.isArray(merged.providers))
|
|
381
|
-
providers.push(...merged.providers);
|
|
382
|
-
return providers;
|
|
383
|
-
},
|
|
384
|
-
});
|
|
385
|
-
// After CDK attaches the component, copy references onto our ref.
|
|
386
|
-
twRef.componentRef = cdkRef.componentRef;
|
|
387
|
-
twRef.componentInstance = cdkRef.componentInstance;
|
|
347
|
+
const id = merged.id ?? generateDialogId();
|
|
348
|
+
merged.id = id;
|
|
349
|
+
// Enforce id uniqueness eagerly. CDK throws this synchronously from
|
|
350
|
+
// `open()`; since our CDK open is now deferred, replicate the check here so
|
|
351
|
+
// the error still surfaces at the call site rather than in a later tick.
|
|
352
|
+
if (this.getDialogById(id)) {
|
|
353
|
+
throw new Error(`Dialog with id "${id}" exists already. The dialog id must be unique.`);
|
|
354
|
+
}
|
|
355
|
+
const twRef = new TwDialogRef(id, merged);
|
|
388
356
|
const scope = this.parentDialog ?? this;
|
|
389
357
|
scope.registerOpen(twRef);
|
|
390
358
|
twRef.afterClosed().subscribe(() => {
|
|
391
359
|
scope.unregister(twRef);
|
|
392
360
|
});
|
|
361
|
+
void this.renderWhenReady(content, merged, twRef);
|
|
393
362
|
return twRef;
|
|
394
363
|
}
|
|
395
364
|
/** Closes every open dialog managed by this service (and child services). */
|
|
@@ -403,12 +372,42 @@ class TwDialog {
|
|
|
403
372
|
return this.openDialogs().find((dialog) => dialog.id === id);
|
|
404
373
|
}
|
|
405
374
|
ngOnDestroy() {
|
|
375
|
+
this.destroyed = true;
|
|
406
376
|
const dialogs = [...this.openDialogsAtThisLevel()];
|
|
407
377
|
for (let i = dialogs.length - 1; i >= 0; i--)
|
|
408
378
|
dialogs[i].close();
|
|
409
379
|
this.afterOpenedSubject.complete();
|
|
410
380
|
this.afterAllClosedSubject.complete();
|
|
411
381
|
}
|
|
382
|
+
/**
|
|
383
|
+
* @internal Resolves once the renderer chunk has loaded. Exposed for tests,
|
|
384
|
+
* which must await the dynamic import before asserting on rendered DOM.
|
|
385
|
+
*/
|
|
386
|
+
async _whenRendered() {
|
|
387
|
+
await this.loadRenderer();
|
|
388
|
+
await Promise.resolve();
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Render a dialog once the renderer chunk has loaded. The ref was already
|
|
392
|
+
* returned to the caller, so it may have been closed (or the service
|
|
393
|
+
* destroyed) while the import was in flight — both skip the actual open.
|
|
394
|
+
*/
|
|
395
|
+
async renderWhenReady(content, merged, twRef) {
|
|
396
|
+
const openRendered = await this.loadRenderer();
|
|
397
|
+
if (!openRendered || this.destroyed)
|
|
398
|
+
return;
|
|
399
|
+
// Closed before the chunk landed — the facade already synthesized its
|
|
400
|
+
// closed state; never create the overlay.
|
|
401
|
+
if (twRef.state() === 'closed')
|
|
402
|
+
return;
|
|
403
|
+
openRendered(this.injector, content, merged, twRef);
|
|
404
|
+
}
|
|
405
|
+
loadRenderer() {
|
|
406
|
+
if (!this.rendererPromise) {
|
|
407
|
+
this.rendererPromise = import('./cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs').then(({ openRenderedDialog }) => this.destroyed ? null : openRenderedDialog);
|
|
408
|
+
}
|
|
409
|
+
return this.rendererPromise;
|
|
410
|
+
}
|
|
412
411
|
registerOpen(ref) {
|
|
413
412
|
if (this.parentDialog) {
|
|
414
413
|
this.parentDialog.registerOpen(ref);
|
|
@@ -439,19 +438,6 @@ class TwDialog {
|
|
|
439
438
|
Object.assign(merged, this.defaultOptions, config);
|
|
440
439
|
return merged;
|
|
441
440
|
}
|
|
442
|
-
resolveScrollStrategy(strategy) {
|
|
443
|
-
switch (strategy) {
|
|
444
|
-
case 'close':
|
|
445
|
-
return createCloseScrollStrategy(this.injector);
|
|
446
|
-
case 'reposition':
|
|
447
|
-
return createRepositionScrollStrategy(this.injector);
|
|
448
|
-
case 'noop':
|
|
449
|
-
return createNoopScrollStrategy();
|
|
450
|
-
case 'block':
|
|
451
|
-
default:
|
|
452
|
-
return createBlockScrollStrategy(this.injector);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
441
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TwDialog, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
456
442
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TwDialog });
|
|
457
443
|
}
|
|
@@ -540,21 +526,16 @@ class DialogTitleDirective {
|
|
|
540
526
|
dialogRef = inject(TwDialogRef, {
|
|
541
527
|
optional: true,
|
|
542
528
|
});
|
|
543
|
-
// Ancestor-DI fallback for the rare case where `TwDialogRef` is not in the
|
|
544
|
-
// directive's injector chain (e.g. heavily nested template portals). The
|
|
545
|
-
// container ALWAYS resolves via element-injector traversal because the
|
|
546
|
-
// directive lives inside `<tw-dialog-container>`'s DOM tree.
|
|
547
|
-
container = inject(DialogContainer, { optional: true, skipSelf: true });
|
|
548
529
|
/** Custom id for the title element. Defaults to a generated unique id. */
|
|
549
530
|
id = input(this.generatedId, /* @ts-ignore */
|
|
550
531
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
551
532
|
ngOnInit() {
|
|
552
|
-
const containerInstance = this.dialogRef?.containerInstance
|
|
533
|
+
const containerInstance = this.dialogRef?.containerInstance;
|
|
553
534
|
if (containerInstance)
|
|
554
535
|
containerInstance._addAriaLabelledBy(this.id());
|
|
555
536
|
}
|
|
556
537
|
ngOnDestroy() {
|
|
557
|
-
const containerInstance = this.dialogRef?.containerInstance
|
|
538
|
+
const containerInstance = this.dialogRef?.containerInstance;
|
|
558
539
|
if (containerInstance)
|
|
559
540
|
containerInstance._removeAriaLabelledBy(this.id());
|
|
560
541
|
}
|
|
@@ -595,18 +576,16 @@ class DialogDescriptionDirective {
|
|
|
595
576
|
dialogRef = inject(TwDialogRef, {
|
|
596
577
|
optional: true,
|
|
597
578
|
});
|
|
598
|
-
// Ancestor-DI fallback — see DialogTitleDirective.
|
|
599
|
-
container = inject(DialogContainer, { optional: true, skipSelf: true });
|
|
600
579
|
/** Custom id for the description element. Defaults to a generated unique id. */
|
|
601
580
|
id = input(this.generatedId, /* @ts-ignore */
|
|
602
581
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
603
582
|
ngOnInit() {
|
|
604
|
-
const containerInstance = this.dialogRef?.containerInstance
|
|
583
|
+
const containerInstance = this.dialogRef?.containerInstance;
|
|
605
584
|
if (containerInstance)
|
|
606
585
|
containerInstance._addAriaDescribedBy(this.id());
|
|
607
586
|
}
|
|
608
587
|
ngOnDestroy() {
|
|
609
|
-
const containerInstance = this.dialogRef?.containerInstance
|
|
588
|
+
const containerInstance = this.dialogRef?.containerInstance;
|
|
610
589
|
if (containerInstance)
|
|
611
590
|
containerInstance._removeAriaDescribedBy(this.id());
|
|
612
591
|
}
|
|
@@ -672,7 +651,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
672
651
|
* `[twDialogClose]` value to pass a result to `afterClosed()` subscribers.
|
|
673
652
|
*/
|
|
674
653
|
class DialogCloseDirective {
|
|
675
|
-
/** Value passed to `afterClosed()` when the button is clicked. */
|
|
654
|
+
/** Value passed to `afterClosed()` when the button is clicked. Defaults to `undefined`. */
|
|
676
655
|
twDialogClose = input(undefined, /* @ts-ignore */
|
|
677
656
|
...(ngDevMode ? [{ debugName: "twDialogClose" }] : /* istanbul ignore next */ []));
|
|
678
657
|
/** Native button `type`. Defaults to `'button'` to avoid accidental form submission. */
|
|
@@ -702,5 +681,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
702
681
|
* Generated bundle index. Do not edit.
|
|
703
682
|
*/
|
|
704
683
|
|
|
705
|
-
export { DialogActionsDirective, DialogCloseDirective,
|
|
684
|
+
export { DialogActionsDirective, DialogCloseDirective, DialogContentDirective, DialogDescriptionDirective, DialogHeaderDirective, DialogIconDirective, DialogSubtitleDirective, DialogTitleDirective, TW_DIALOG_DATA, TW_DIALOG_DEFAULT_OPTIONS, TwDialog, TwDialogConfig, TwDialogRef, provideTwDialog };
|
|
706
685
|
//# sourceMappingURL=cdevhub-ngx-tw-dialog.mjs.map
|