@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';
|
|
@@ -69,184 +65,42 @@ class SheetConfig extends DialogConfig {
|
|
|
69
65
|
restoreFocus = true;
|
|
70
66
|
}
|
|
71
67
|
/** Injection token carrying the `data` value passed via {@link SheetConfig.data}. */
|
|
72
|
-
const
|
|
68
|
+
const TW_SHEET_DATA = new InjectionToken('TW_SHEET_DATA');
|
|
73
69
|
/** Injection token for application-wide default sheet options. Set via `provideSheet()`. */
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
// Sheet uses a `data-[state]` + `data-[side]` driven CSS transition rather than
|
|
77
|
-
// the project's `animate.enter`/`animate.leave` keyframes. Same rationale as
|
|
78
|
-
// the dialog container (see `dialog-container.ts`):
|
|
79
|
-
// 1. The ref owns the open/close lifecycle (state signal, observables) and
|
|
80
|
-
// needs runtime-configurable enter/exit durations per `Sheet.open()` call
|
|
81
|
-
// — `animate.enter` only accepts a static class name.
|
|
82
|
-
// 2. The transform direction depends on `side`, and encoding four pairs of
|
|
83
|
-
// keyframe classes (slide-in/out × 4 sides) is noisier than four
|
|
84
|
-
// `data-[side=…]` selectors on a single transition rule.
|
|
85
|
-
// All other library overlays (popover, menu, tooltip) use animate.enter/leave;
|
|
86
|
-
// this divergence is intentional and isolated to the sheet container.
|
|
87
|
-
const sheetContainerVariants = tv({
|
|
88
|
-
slots: {
|
|
89
|
-
host: 'fixed flex flex-col outline-none bg-surface-raised text-fg shadow-md overflow-hidden transition-[transform,opacity] ease-out motion-reduce:transition-none opacity-0 data-[state=open]:opacity-100',
|
|
90
|
-
},
|
|
91
|
-
variants: {
|
|
92
|
-
side: {
|
|
93
|
-
right: {
|
|
94
|
-
host: 'h-screen right-0 top-0 border-l border-border data-[state=opening]:translate-x-full data-[state=closing]:translate-x-full data-[state=open]:translate-x-0',
|
|
95
|
-
},
|
|
96
|
-
left: {
|
|
97
|
-
host: 'h-screen left-0 top-0 border-r border-border data-[state=opening]:-translate-x-full data-[state=closing]:-translate-x-full data-[state=open]:translate-x-0',
|
|
98
|
-
},
|
|
99
|
-
top: {
|
|
100
|
-
host: 'w-screen left-0 top-0 border-b border-border data-[state=opening]:-translate-y-full data-[state=closing]:-translate-y-full data-[state=open]:translate-y-0',
|
|
101
|
-
},
|
|
102
|
-
bottom: {
|
|
103
|
-
host: 'w-screen left-0 bottom-0 border-t border-border data-[state=opening]:translate-y-full data-[state=closing]:translate-y-full data-[state=open]:translate-y-0',
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
size: {
|
|
107
|
-
xs: { host: '' },
|
|
108
|
-
sm: { host: '' },
|
|
109
|
-
md: { host: '' },
|
|
110
|
-
lg: { host: '' },
|
|
111
|
-
xl: { host: '' },
|
|
112
|
-
full: { host: '' },
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
// Sheets are axis-aware: `size` controls width on horizontal sides and
|
|
116
|
-
// height on vertical sides. Encoded as compound variants so a single
|
|
117
|
-
// {side, size} pair resolves to one set of utility classes.
|
|
118
|
-
compoundVariants: [
|
|
119
|
-
// ── Right-anchored ─────────────────────────────────────────────
|
|
120
|
-
{ side: 'right', size: 'xs', class: { host: 'w-full max-w-xs' } },
|
|
121
|
-
{ side: 'right', size: 'sm', class: { host: 'w-full max-w-sm' } },
|
|
122
|
-
{ side: 'right', size: 'md', class: { host: 'w-full max-w-md' } },
|
|
123
|
-
{ side: 'right', size: 'lg', class: { host: 'w-full max-w-xl' } },
|
|
124
|
-
{ side: 'right', size: 'xl', class: { host: 'w-full max-w-2xl' } },
|
|
125
|
-
{ side: 'right', size: 'full', class: { host: 'w-screen max-w-none' } },
|
|
126
|
-
// ── Left-anchored ──────────────────────────────────────────────
|
|
127
|
-
{ side: 'left', size: 'xs', class: { host: 'w-full max-w-xs' } },
|
|
128
|
-
{ side: 'left', size: 'sm', class: { host: 'w-full max-w-sm' } },
|
|
129
|
-
{ side: 'left', size: 'md', class: { host: 'w-full max-w-md' } },
|
|
130
|
-
{ side: 'left', size: 'lg', class: { host: 'w-full max-w-xl' } },
|
|
131
|
-
{ side: 'left', size: 'xl', class: { host: 'w-full max-w-2xl' } },
|
|
132
|
-
{ side: 'left', size: 'full', class: { host: 'w-screen max-w-none' } },
|
|
133
|
-
// ── Top-anchored ───────────────────────────────────────────────
|
|
134
|
-
{ side: 'top', size: 'xs', class: { host: 'h-[20vh]' } },
|
|
135
|
-
{ side: 'top', size: 'sm', class: { host: 'h-[33vh]' } },
|
|
136
|
-
{ side: 'top', size: 'md', class: { host: 'h-[50vh]' } },
|
|
137
|
-
{ side: 'top', size: 'lg', class: { host: 'h-[66vh]' } },
|
|
138
|
-
{ side: 'top', size: 'xl', class: { host: 'h-[80vh]' } },
|
|
139
|
-
{ side: 'top', size: 'full', class: { host: 'h-screen' } },
|
|
140
|
-
// ── Bottom-anchored ────────────────────────────────────────────
|
|
141
|
-
{ side: 'bottom', size: 'xs', class: { host: 'h-[20vh]' } },
|
|
142
|
-
{ side: 'bottom', size: 'sm', class: { host: 'h-[33vh]' } },
|
|
143
|
-
{ side: 'bottom', size: 'md', class: { host: 'h-[50vh]' } },
|
|
144
|
-
{ side: 'bottom', size: 'lg', class: { host: 'h-[66vh]' } },
|
|
145
|
-
{ side: 'bottom', size: 'xl', class: { host: 'h-[80vh]' } },
|
|
146
|
-
{ side: 'bottom', size: 'full', class: { host: 'h-screen' } },
|
|
147
|
-
],
|
|
148
|
-
defaultVariants: { side: 'right', size: 'md' },
|
|
149
|
-
}, { twMerge: true });
|
|
70
|
+
const TW_SHEET_DEFAULT_OPTIONS = new InjectionToken('TW_SHEET_DEFAULT_OPTIONS');
|
|
150
71
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* merge are shared with `DialogContainer` via {@link OverlayContainerCoordinator}
|
|
157
|
-
* (component-scoped — see `providers: [OverlayContainerCoordinator]`).
|
|
158
|
-
*
|
|
159
|
-
* @docs-private
|
|
72
|
+
* @deprecated Renamed to {@link TW_SHEET_DATA} for consistency with every other
|
|
73
|
+
* ngx-tw injection token — and with `TW_DIALOG_DATA`, its direct counterpart.
|
|
74
|
+
* This is the *same token instance*, not a copy — providing under either name
|
|
75
|
+
* and injecting under the other resolves — so the rename is safe to adopt
|
|
76
|
+
* incrementally. Removed in the next major.
|
|
160
77
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
exitAnimationDuration;
|
|
171
|
-
sideAttr = computed(() => this._config.side ?? 'right', /* @ts-ignore */
|
|
172
|
-
...(ngDevMode ? [{ debugName: "sideAttr" }] : /* istanbul ignore next */ []));
|
|
173
|
-
variants = computed(() => {
|
|
174
|
-
const side = this._config.side ?? 'right';
|
|
175
|
-
const size = this._config.size ?? 'md';
|
|
176
|
-
return sheetContainerVariants({ side, size });
|
|
177
|
-
}, /* @ts-ignore */
|
|
178
|
-
...(ngDevMode ? [{ debugName: "variants" }] : /* istanbul ignore next */ []));
|
|
179
|
-
hostClasses = computed(() => mergeOverlayPanelClass(this.variants().host(), this._config.panelClass), /* @ts-ignore */
|
|
180
|
-
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
181
|
-
ariaDescribedByAttr = computed(() => this._config.ariaDescribedBy ||
|
|
182
|
-
this.coordinator.describedByIds()[0] ||
|
|
183
|
-
null, /* @ts-ignore */
|
|
184
|
-
...(ngDevMode ? [{ debugName: "ariaDescribedByAttr" }] : /* istanbul ignore next */ []));
|
|
185
|
-
transitionDuration = this.coordinator.transitionDuration;
|
|
186
|
-
constructor() {
|
|
187
|
-
super();
|
|
188
|
-
this.enterAnimationDuration = coerceOverlayDuration(this._config.enterAnimationDuration, 200);
|
|
189
|
-
this.exitAnimationDuration = coerceOverlayDuration(this._config.exitAnimationDuration, 160);
|
|
190
|
-
this.coordinator.setDurations(this.enterAnimationDuration, this.exitAnimationDuration);
|
|
191
|
-
}
|
|
192
|
-
_contentAttached() {
|
|
193
|
-
super._contentAttached();
|
|
194
|
-
this.coordinator.startEnterAnimation();
|
|
195
|
-
}
|
|
196
|
-
/** Triggered by the sheet ref to play the exit transition before disposing the overlay. */
|
|
197
|
-
_startExitAnimation() {
|
|
198
|
-
this.coordinator.startExitAnimation();
|
|
199
|
-
}
|
|
200
|
-
/** Registers a description id for the container's `aria-describedby`. */
|
|
201
|
-
_addAriaDescribedBy(id) {
|
|
202
|
-
this.coordinator.addAriaDescribedBy(id);
|
|
203
|
-
}
|
|
204
|
-
/** Removes a previously registered description id. */
|
|
205
|
-
_removeAriaDescribedBy(id) {
|
|
206
|
-
this.coordinator.removeAriaDescribedBy(id);
|
|
207
|
-
}
|
|
208
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SheetContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
209
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: SheetContainer, isStandalone: true, selector: "tw-sheet-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()", "attr.data-side": "sideAttr()", "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 });
|
|
210
|
-
}
|
|
211
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SheetContainer, decorators: [{
|
|
212
|
-
type: Component,
|
|
213
|
-
args: [{
|
|
214
|
-
selector: 'tw-sheet-container',
|
|
215
|
-
template: '<ng-template cdkPortalOutlet />',
|
|
216
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
217
|
-
encapsulation: ViewEncapsulation.None,
|
|
218
|
-
imports: [CdkPortalOutlet],
|
|
219
|
-
providers: [OverlayContainerCoordinator],
|
|
220
|
-
host: {
|
|
221
|
-
tabindex: '-1',
|
|
222
|
-
'[attr.id]': '_config.id || null',
|
|
223
|
-
'[attr.role]': '_config.role',
|
|
224
|
-
'[attr.aria-modal]': '_config.ariaModal',
|
|
225
|
-
'[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledByQueue[0]',
|
|
226
|
-
'[attr.aria-label]': '_config.ariaLabel',
|
|
227
|
-
'[attr.aria-describedby]': 'ariaDescribedByAttr()',
|
|
228
|
-
'[attr.data-state]': 'state()',
|
|
229
|
-
'[attr.data-side]': 'sideAttr()',
|
|
230
|
-
'[class]': 'hostClasses()',
|
|
231
|
-
'[style.transition-duration.ms]': 'transitionDuration()',
|
|
232
|
-
},
|
|
233
|
-
}]
|
|
234
|
-
}], ctorParameters: () => [] });
|
|
78
|
+
const SHEET_DATA = TW_SHEET_DATA;
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated Renamed to {@link TW_SHEET_DEFAULT_OPTIONS} for consistency with
|
|
81
|
+
* every other ngx-tw injection token — and with `TW_DIALOG_DEFAULT_OPTIONS`,
|
|
82
|
+
* its direct counterpart. This is the *same token instance*, not a copy —
|
|
83
|
+
* providing under either name and injecting under the other resolves — so the
|
|
84
|
+
* rename is safe to adopt incrementally. Removed in the next major.
|
|
85
|
+
*/
|
|
86
|
+
const SHEET_DEFAULT_OPTIONS = TW_SHEET_DEFAULT_OPTIONS;
|
|
235
87
|
|
|
236
88
|
/**
|
|
237
89
|
* Reference to a sheet opened via {@link Sheet.open}. Drives the sheet
|
|
238
90
|
* lifecycle (close, state, observables) and forwards useful overlay streams.
|
|
91
|
+
*
|
|
92
|
+
* The ref is returned **synchronously** from `open()`, but the sheet's render
|
|
93
|
+
* layer (`@angular/cdk/dialog` + the Tailwind container) is loaded through a
|
|
94
|
+
* dynamic `import()`. The ref therefore starts *detached*: `id`, `state`,
|
|
95
|
+
* `close()`, the lifecycle observables, and panel mutations all work
|
|
96
|
+
* immediately (mutations are buffered and replayed on attach), but the rendered
|
|
97
|
+
* component instance does not exist yet — read it via {@link whenComponentReady}
|
|
98
|
+
* instead of a synchronous `componentInstance` field.
|
|
239
99
|
*/
|
|
240
100
|
class SheetRef {
|
|
241
|
-
cdkRef;
|
|
242
101
|
config;
|
|
243
|
-
|
|
244
|
-
/** Unique ID of the sheet. */
|
|
102
|
+
/** Unique ID of the sheet. Generated eagerly by the service, so it is valid the instant `open()` returns. */
|
|
245
103
|
id;
|
|
246
|
-
/** Instance of the component rendered inside the sheet, or `null` for template sheets. */
|
|
247
|
-
componentInstance = null;
|
|
248
|
-
/** `ComponentRef` of the content component, or `null` for template sheets. */
|
|
249
|
-
componentRef = null;
|
|
250
104
|
/** Current lifecycle state. Reactively readable. */
|
|
251
105
|
state;
|
|
252
106
|
/** When `true`, close-via-escape AND close-via-backdrop are both disabled. */
|
|
@@ -260,19 +114,56 @@ class SheetRef {
|
|
|
260
114
|
afterOpenedSubject = new ReplaySubject(1);
|
|
261
115
|
beforeClosedSubject = new ReplaySubject(1);
|
|
262
116
|
afterClosedSubject = new ReplaySubject(1);
|
|
117
|
+
// Facade-owned pass-throughs for the raw overlay streams, so a consumer that
|
|
118
|
+
// subscribes before the render chunk attaches still receives events once it
|
|
119
|
+
// does — the pre-deferral behaviour when `open()` wrapped a live `cdkRef`.
|
|
120
|
+
backdropClickSubject = new Subject();
|
|
121
|
+
keydownEventsSubject = new Subject();
|
|
122
|
+
cdkRef = null;
|
|
123
|
+
container = null;
|
|
124
|
+
componentInstanceValue = null;
|
|
125
|
+
componentRefValue = null;
|
|
126
|
+
resolveComponentReady;
|
|
127
|
+
componentReadyPromise = new Promise((resolve) => {
|
|
128
|
+
this.resolveComponentReady = resolve;
|
|
129
|
+
});
|
|
130
|
+
// Buffered mutations issued before the render chunk attached the CDK backend.
|
|
131
|
+
pendingPanelAdds = [];
|
|
132
|
+
pendingPanelRemoves = [];
|
|
263
133
|
pendingResult;
|
|
264
134
|
closeFocusOrigin;
|
|
265
|
-
constructor(
|
|
266
|
-
this.cdkRef = cdkRef;
|
|
135
|
+
constructor(id, config) {
|
|
267
136
|
this.config = config;
|
|
268
|
-
this.
|
|
269
|
-
this.id = cdkRef.id;
|
|
137
|
+
this.id = id;
|
|
270
138
|
this.disableClose = config.disableClose;
|
|
271
139
|
this.closeOnEscape = config.closeOnEscape;
|
|
272
140
|
this.closeOnBackdropClick = config.closeOnBackdropClick;
|
|
273
141
|
this.state = this.stateSignal.asReadonly();
|
|
142
|
+
}
|
|
143
|
+
/** The Tailwind container instance, or `null` until the sheet has attached. */
|
|
144
|
+
get containerInstance() {
|
|
145
|
+
return this.container;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* @internal Wire this facade to its CDK backend. Called from the sheet
|
|
149
|
+
* renderer **inside** `cdkDialog.open()`'s `providers` callback — the same
|
|
150
|
+
* point the constructor ran before deferral — so subscriptions to
|
|
151
|
+
* `animationStateChanged` are in place before the container emits `'open'`.
|
|
152
|
+
*/
|
|
153
|
+
_attach(cdkRef, container) {
|
|
154
|
+
this.cdkRef = cdkRef;
|
|
155
|
+
this.container = container;
|
|
156
|
+
// Forward the raw overlay streams into the facade pass-throughs.
|
|
157
|
+
cdkRef.backdropClick.subscribe(this.backdropClickSubject);
|
|
158
|
+
cdkRef.keydownEvents.subscribe(this.keydownEventsSubject);
|
|
274
159
|
cdkRef.addPanelClass('tw-sheet-panel');
|
|
275
|
-
const
|
|
160
|
+
for (const cls of this.pendingPanelAdds)
|
|
161
|
+
cdkRef.addPanelClass(cls);
|
|
162
|
+
for (const cls of this.pendingPanelRemoves)
|
|
163
|
+
cdkRef.removePanelClass(cls);
|
|
164
|
+
this.pendingPanelAdds.length = 0;
|
|
165
|
+
this.pendingPanelRemoves.length = 0;
|
|
166
|
+
const animationChanges = container.animationStateChanged;
|
|
276
167
|
animationChanges
|
|
277
168
|
.pipe(filter((event) => event.state === 'open'), take(1))
|
|
278
169
|
.subscribe(() => {
|
|
@@ -301,6 +192,38 @@ class SheetRef {
|
|
|
301
192
|
this.closeWithOrigin(event.type === 'keydown' ? 'keyboard' : 'mouse');
|
|
302
193
|
});
|
|
303
194
|
}
|
|
195
|
+
/** @internal Record the rendered component after `cdkDialog.open()` returns. */
|
|
196
|
+
_setComponent(instance, ref) {
|
|
197
|
+
this.componentInstanceValue = instance;
|
|
198
|
+
this.componentRefValue = ref;
|
|
199
|
+
this.resolveComponentReady(instance);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Resolves with the rendered content-component instance once the sheet's
|
|
203
|
+
* render chunk has loaded and attached. Resolves `null` for template sheets,
|
|
204
|
+
* and for a sheet closed before it ever opened.
|
|
205
|
+
*
|
|
206
|
+
* Replaces the former synchronous `componentInstance` field, which cannot be
|
|
207
|
+
* populated before the deferred render chunk lands.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* const ref = sheet.open(FilterSheet);
|
|
212
|
+
* const filters = await ref.whenComponentReady();
|
|
213
|
+
* filters?.reset();
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
whenComponentReady() {
|
|
217
|
+
return this.componentReadyPromise;
|
|
218
|
+
}
|
|
219
|
+
/** The rendered component instance, or `null` if not yet attached / a template sheet. Prefer {@link whenComponentReady}. */
|
|
220
|
+
get componentInstance() {
|
|
221
|
+
return this.componentInstanceValue;
|
|
222
|
+
}
|
|
223
|
+
/** The rendered `ComponentRef`, or `null` if not yet attached / a template sheet. */
|
|
224
|
+
get componentRef() {
|
|
225
|
+
return this.componentRefValue;
|
|
226
|
+
}
|
|
304
227
|
/**
|
|
305
228
|
* Closes the sheet. The exit slide animation runs before the overlay is disposed.
|
|
306
229
|
* @param result Value forwarded to `afterClosed()` subscribers.
|
|
@@ -320,22 +243,32 @@ class SheetRef {
|
|
|
320
243
|
afterClosed() {
|
|
321
244
|
return this.afterClosedSubject.asObservable();
|
|
322
245
|
}
|
|
323
|
-
/** Backdrop click stream (emits even when `closeOnBackdropClick` / `disableClose` is set). */
|
|
246
|
+
/** Backdrop click stream (emits even when `closeOnBackdropClick` / `disableClose` is set). Buffered — a subscription made before the sheet attaches receives events once it does. */
|
|
324
247
|
backdropClick() {
|
|
325
|
-
return this.
|
|
248
|
+
return this.backdropClickSubject.asObservable();
|
|
326
249
|
}
|
|
327
|
-
/** Keydown event stream for the overlay. */
|
|
250
|
+
/** Keydown event stream for the overlay. Buffered — a subscription made before the sheet attaches receives events once it does. */
|
|
328
251
|
keydownEvents() {
|
|
329
|
-
return this.
|
|
252
|
+
return this.keydownEventsSubject.asObservable();
|
|
330
253
|
}
|
|
331
|
-
/** Adds CSS classes to the overlay panel. */
|
|
254
|
+
/** Adds CSS classes to the overlay panel. Buffered until attach. */
|
|
332
255
|
addPanelClass(classes) {
|
|
333
|
-
this.cdkRef
|
|
256
|
+
if (this.cdkRef) {
|
|
257
|
+
this.cdkRef.addPanelClass(classes);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this.pendingPanelAdds.push(...(Array.isArray(classes) ? classes : [classes]));
|
|
261
|
+
}
|
|
334
262
|
return this;
|
|
335
263
|
}
|
|
336
|
-
/** Removes CSS classes from the overlay panel. */
|
|
264
|
+
/** Removes CSS classes from the overlay panel. Buffered until attach. */
|
|
337
265
|
removePanelClass(classes) {
|
|
338
|
-
this.cdkRef
|
|
266
|
+
if (this.cdkRef) {
|
|
267
|
+
this.cdkRef.removePanelClass(classes);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
this.pendingPanelRemoves.push(...(Array.isArray(classes) ? classes : [classes]));
|
|
271
|
+
}
|
|
339
272
|
return this;
|
|
340
273
|
}
|
|
341
274
|
closeWithOrigin(origin, result) {
|
|
@@ -343,7 +276,7 @@ class SheetRef {
|
|
|
343
276
|
return;
|
|
344
277
|
const predicate = this.config.closePredicate;
|
|
345
278
|
if (predicate &&
|
|
346
|
-
!predicate(result, this.config, this.
|
|
279
|
+
!predicate(result, this.config, this.componentInstanceValue)) {
|
|
347
280
|
return;
|
|
348
281
|
}
|
|
349
282
|
this.pendingResult = result;
|
|
@@ -351,8 +284,15 @@ class SheetRef {
|
|
|
351
284
|
this.stateSignal.set('closing');
|
|
352
285
|
this.beforeClosedSubject.next(result);
|
|
353
286
|
this.beforeClosedSubject.complete();
|
|
287
|
+
if (!this.cdkRef) {
|
|
288
|
+
// Closed before the render chunk attached: the overlay was never created,
|
|
289
|
+
// so there is nothing to animate or dispose. Synthesize the closed state
|
|
290
|
+
// and let the service skip opening entirely (it checks state()).
|
|
291
|
+
this.finishClose();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
354
294
|
this.cdkRef.overlayRef.detachBackdrop();
|
|
355
|
-
this.
|
|
295
|
+
this.container._startExitAnimation();
|
|
356
296
|
}
|
|
357
297
|
finishClose() {
|
|
358
298
|
if (this.stateSignal() === 'closed')
|
|
@@ -360,26 +300,42 @@ class SheetRef {
|
|
|
360
300
|
this.stateSignal.set('closed');
|
|
361
301
|
this.afterClosedSubject.next(this.pendingResult);
|
|
362
302
|
this.afterClosedSubject.complete();
|
|
363
|
-
if
|
|
303
|
+
// Idempotent — a no-op if _setComponent already resolved with an instance.
|
|
304
|
+
this.resolveComponentReady(null);
|
|
305
|
+
this.backdropClickSubject.complete();
|
|
306
|
+
this.keydownEventsSubject.complete();
|
|
307
|
+
if (this.cdkRef?.containerInstance) {
|
|
364
308
|
this.cdkRef.close(this.pendingResult, { focusOrigin: this.closeFocusOrigin });
|
|
365
309
|
}
|
|
366
|
-
this.
|
|
310
|
+
this.componentInstanceValue = null;
|
|
367
311
|
}
|
|
368
312
|
}
|
|
369
313
|
|
|
314
|
+
let nextSheetId = 0;
|
|
315
|
+
function generateSheetId() {
|
|
316
|
+
return `tw-sheet-${++nextSheetId}`;
|
|
317
|
+
}
|
|
370
318
|
/**
|
|
371
319
|
* Opens edge-anchored sheet (drawer) overlays. Composes `@angular/cdk/dialog`
|
|
372
320
|
* for focus trapping, portals, and overlay plumbing — adds a `GlobalPositionStrategy`
|
|
373
321
|
* pinned to the requested viewport edge, a Tailwind container with axis-aware
|
|
374
322
|
* sizing, slide enter/exit animations, and split close-behavior flags.
|
|
375
323
|
*
|
|
324
|
+
* The rendering layer (`@angular/cdk/dialog` + the Tailwind container) is loaded
|
|
325
|
+
* through a dynamic `import()` on the first `open()` call, so merely registering
|
|
326
|
+
* this service costs nothing in the initial bundle. `open()` still returns its
|
|
327
|
+
* {@link SheetRef} synchronously — the sheet is rendered once the chunk lands.
|
|
328
|
+
* Read the rendered component via {@link SheetRef.whenComponentReady}.
|
|
329
|
+
*
|
|
376
330
|
* Not `providedIn: 'root'` — register it via {@link provideSheet}.
|
|
377
331
|
*/
|
|
378
332
|
class Sheet {
|
|
379
|
-
cdkDialog = inject(Dialog);
|
|
380
333
|
injector = inject(Injector);
|
|
381
|
-
defaultOptions = inject(
|
|
334
|
+
defaultOptions = inject(TW_SHEET_DEFAULT_OPTIONS, { optional: true }) ?? {};
|
|
382
335
|
parentSheet = inject(Sheet, { optional: true, skipSelf: true });
|
|
336
|
+
/** Cached renderer chunk import — kicked off on the first `open()`. */
|
|
337
|
+
rendererPromise = null;
|
|
338
|
+
destroyed = false;
|
|
383
339
|
openSheetsAtThisLevel = signal([], /* @ts-ignore */
|
|
384
340
|
...(ngDevMode ? [{ debugName: "openSheetsAtThisLevel" }] : /* istanbul ignore next */ []));
|
|
385
341
|
afterOpenedSubject = new Subject();
|
|
@@ -403,61 +359,25 @@ class Sheet {
|
|
|
403
359
|
* Opens a sheet using the given component or template.
|
|
404
360
|
* @param content Component class or `TemplateRef`.
|
|
405
361
|
* @param config Options merged over the application defaults.
|
|
406
|
-
* @returns Reference controlling the opened sheet.
|
|
362
|
+
* @returns Reference controlling the opened sheet, returned synchronously.
|
|
407
363
|
*/
|
|
408
364
|
open(content, config) {
|
|
409
365
|
const merged = this.resolveConfig(config);
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
// utilities). The overlay pane itself is the full-edge bounding box.
|
|
420
|
-
direction: merged.direction,
|
|
421
|
-
ariaDescribedBy: merged.ariaDescribedBy,
|
|
422
|
-
ariaLabelledBy: merged.ariaLabelledBy,
|
|
423
|
-
ariaLabel: merged.ariaLabel,
|
|
424
|
-
ariaModal: merged.ariaModal,
|
|
425
|
-
autoFocus: merged.autoFocus,
|
|
426
|
-
restoreFocus: merged.restoreFocus,
|
|
427
|
-
scrollStrategy: merged.scrollStrategy ?? this.resolveScrollStrategy(merged.scrollBehavior),
|
|
428
|
-
positionStrategy: merged.positionStrategy ?? this.resolvePositionStrategy(merged.side ?? 'right'),
|
|
429
|
-
closeOnNavigation: merged.closeOnNavigation,
|
|
430
|
-
viewContainerRef: merged.viewContainerRef,
|
|
431
|
-
injector: merged.injector,
|
|
432
|
-
// We handle close/Escape/backdrop ourselves so we can run the exit slide animation.
|
|
433
|
-
disableClose: true,
|
|
434
|
-
closeOnOverlayDetachments: false,
|
|
435
|
-
container: {
|
|
436
|
-
type: SheetContainer,
|
|
437
|
-
providers: () => [
|
|
438
|
-
{ provide: SheetConfig, useValue: merged },
|
|
439
|
-
{ provide: DialogConfig, useValue: merged },
|
|
440
|
-
],
|
|
441
|
-
},
|
|
442
|
-
providers: (_cdkRef, _cdkConfig, container) => {
|
|
443
|
-
sheetRef = new SheetRef(_cdkRef, merged, container);
|
|
444
|
-
const providers = [
|
|
445
|
-
{ provide: SheetRef, useValue: sheetRef },
|
|
446
|
-
{ provide: SHEET_DATA, useValue: merged.data ?? null },
|
|
447
|
-
];
|
|
448
|
-
if (Array.isArray(merged.providers))
|
|
449
|
-
providers.push(...merged.providers);
|
|
450
|
-
return providers;
|
|
451
|
-
},
|
|
452
|
-
});
|
|
453
|
-
// After CDK attaches the component, copy references onto our ref.
|
|
454
|
-
sheetRef.componentRef = cdkRef.componentRef;
|
|
455
|
-
sheetRef.componentInstance = cdkRef.componentInstance;
|
|
366
|
+
const id = merged.id ?? generateSheetId();
|
|
367
|
+
merged.id = id;
|
|
368
|
+
// Enforce id uniqueness eagerly. CDK throws this synchronously from
|
|
369
|
+
// `open()`; since our CDK open is now deferred, replicate the check here so
|
|
370
|
+
// the error still surfaces at the call site rather than in a later tick.
|
|
371
|
+
if (this.getSheetById(id)) {
|
|
372
|
+
throw new Error(`Sheet with id "${id}" exists already. The sheet id must be unique.`);
|
|
373
|
+
}
|
|
374
|
+
const sheetRef = new SheetRef(id, merged);
|
|
456
375
|
const scope = this.parentSheet ?? this;
|
|
457
376
|
scope.registerOpen(sheetRef);
|
|
458
377
|
sheetRef.afterClosed().subscribe(() => {
|
|
459
378
|
scope.unregister(sheetRef);
|
|
460
379
|
});
|
|
380
|
+
void this.renderWhenReady(content, merged, sheetRef);
|
|
461
381
|
return sheetRef;
|
|
462
382
|
}
|
|
463
383
|
/** Closes every open sheet managed by this service (and child services). */
|
|
@@ -471,12 +391,42 @@ class Sheet {
|
|
|
471
391
|
return this.openSheets().find((sheet) => sheet.id === id);
|
|
472
392
|
}
|
|
473
393
|
ngOnDestroy() {
|
|
394
|
+
this.destroyed = true;
|
|
474
395
|
const sheets = [...this.openSheetsAtThisLevel()];
|
|
475
396
|
for (let i = sheets.length - 1; i >= 0; i--)
|
|
476
397
|
sheets[i].close();
|
|
477
398
|
this.afterOpenedSubject.complete();
|
|
478
399
|
this.afterAllClosedSubject.complete();
|
|
479
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* @internal Resolves once the renderer chunk has loaded. Exposed for tests,
|
|
403
|
+
* which must await the dynamic import before asserting on rendered DOM.
|
|
404
|
+
*/
|
|
405
|
+
async _whenRendered() {
|
|
406
|
+
await this.loadRenderer();
|
|
407
|
+
await Promise.resolve();
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Render a sheet once the renderer chunk has loaded. The ref was already
|
|
411
|
+
* returned to the caller, so it may have been closed (or the service
|
|
412
|
+
* destroyed) while the import was in flight — both skip the actual open.
|
|
413
|
+
*/
|
|
414
|
+
async renderWhenReady(content, merged, sheetRef) {
|
|
415
|
+
const openRendered = await this.loadRenderer();
|
|
416
|
+
if (!openRendered || this.destroyed)
|
|
417
|
+
return;
|
|
418
|
+
// Closed before the chunk landed — the facade already synthesized its
|
|
419
|
+
// closed state; never create the overlay.
|
|
420
|
+
if (sheetRef.state() === 'closed')
|
|
421
|
+
return;
|
|
422
|
+
openRendered(this.injector, content, merged, sheetRef);
|
|
423
|
+
}
|
|
424
|
+
loadRenderer() {
|
|
425
|
+
if (!this.rendererPromise) {
|
|
426
|
+
this.rendererPromise = import('./cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs').then(({ openRenderedSheet }) => this.destroyed ? null : openRenderedSheet);
|
|
427
|
+
}
|
|
428
|
+
return this.rendererPromise;
|
|
429
|
+
}
|
|
480
430
|
registerOpen(ref) {
|
|
481
431
|
if (this.parentSheet) {
|
|
482
432
|
this.parentSheet.registerOpen(ref);
|
|
@@ -507,33 +457,6 @@ class Sheet {
|
|
|
507
457
|
Object.assign(merged, this.defaultOptions, config);
|
|
508
458
|
return merged;
|
|
509
459
|
}
|
|
510
|
-
resolveScrollStrategy(strategy) {
|
|
511
|
-
switch (strategy) {
|
|
512
|
-
case 'close':
|
|
513
|
-
return createCloseScrollStrategy(this.injector);
|
|
514
|
-
case 'reposition':
|
|
515
|
-
return createRepositionScrollStrategy(this.injector);
|
|
516
|
-
case 'noop':
|
|
517
|
-
return createNoopScrollStrategy();
|
|
518
|
-
case 'block':
|
|
519
|
-
default:
|
|
520
|
-
return createBlockScrollStrategy(this.injector);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
resolvePositionStrategy(side) {
|
|
524
|
-
const strategy = createGlobalPositionStrategy(this.injector);
|
|
525
|
-
switch (side) {
|
|
526
|
-
case 'left':
|
|
527
|
-
return strategy.top('0').left('0').bottom('0');
|
|
528
|
-
case 'top':
|
|
529
|
-
return strategy.top('0').left('0').right('0');
|
|
530
|
-
case 'bottom':
|
|
531
|
-
return strategy.bottom('0').left('0').right('0');
|
|
532
|
-
case 'right':
|
|
533
|
-
default:
|
|
534
|
-
return strategy.top('0').right('0').bottom('0');
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
460
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: Sheet, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
538
461
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: Sheet });
|
|
539
462
|
}
|
|
@@ -552,7 +475,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
552
475
|
function provideSheet(defaultOptions) {
|
|
553
476
|
const providers = [Sheet];
|
|
554
477
|
if (defaultOptions) {
|
|
555
|
-
providers.push({ provide:
|
|
478
|
+
providers.push({ provide: TW_SHEET_DEFAULT_OPTIONS, useValue: defaultOptions });
|
|
556
479
|
}
|
|
557
480
|
return makeEnvironmentProviders(providers);
|
|
558
481
|
}
|
|
@@ -620,21 +543,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
620
543
|
class SheetTitleDirective {
|
|
621
544
|
generatedId = inject(_IdGenerator).getId('tw-sheet-title-');
|
|
622
545
|
sheetRef = inject(SheetRef, { optional: true });
|
|
623
|
-
// Ancestor-DI fallback for the rare case where `SheetRef` is not in the
|
|
624
546
|
// directive's injector chain (e.g. heavily nested template portals). The
|
|
625
547
|
// container ALWAYS resolves via element-injector traversal because the
|
|
626
548
|
// directive lives inside `<tw-sheet-container>`'s DOM tree.
|
|
627
|
-
container = inject(SheetContainer, { optional: true, skipSelf: true });
|
|
628
549
|
/** Custom id for the title element. Defaults to a generated unique id. */
|
|
629
550
|
id = input(this.generatedId, /* @ts-ignore */
|
|
630
551
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
631
552
|
ngOnInit() {
|
|
632
|
-
const containerInstance = this.sheetRef?.containerInstance
|
|
553
|
+
const containerInstance = this.sheetRef?.containerInstance;
|
|
633
554
|
if (containerInstance)
|
|
634
555
|
containerInstance._addAriaLabelledBy(this.id());
|
|
635
556
|
}
|
|
636
557
|
ngOnDestroy() {
|
|
637
|
-
const containerInstance = this.sheetRef?.containerInstance
|
|
558
|
+
const containerInstance = this.sheetRef?.containerInstance;
|
|
638
559
|
if (containerInstance)
|
|
639
560
|
containerInstance._removeAriaLabelledBy(this.id());
|
|
640
561
|
}
|
|
@@ -673,18 +594,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
673
594
|
class SheetDescriptionDirective {
|
|
674
595
|
generatedId = inject(_IdGenerator).getId('tw-sheet-description-');
|
|
675
596
|
sheetRef = inject(SheetRef, { optional: true });
|
|
676
|
-
// Ancestor-DI fallback — see SheetTitleDirective.
|
|
677
|
-
container = inject(SheetContainer, { optional: true, skipSelf: true });
|
|
678
597
|
/** Custom id for the description element. Defaults to a generated unique id. */
|
|
679
598
|
id = input(this.generatedId, /* @ts-ignore */
|
|
680
599
|
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
681
600
|
ngOnInit() {
|
|
682
|
-
const containerInstance = this.sheetRef?.containerInstance
|
|
601
|
+
const containerInstance = this.sheetRef?.containerInstance;
|
|
683
602
|
if (containerInstance)
|
|
684
603
|
containerInstance._addAriaDescribedBy(this.id());
|
|
685
604
|
}
|
|
686
605
|
ngOnDestroy() {
|
|
687
|
-
const containerInstance = this.sheetRef?.containerInstance
|
|
606
|
+
const containerInstance = this.sheetRef?.containerInstance;
|
|
688
607
|
if (containerInstance)
|
|
689
608
|
containerInstance._removeAriaDescribedBy(this.id());
|
|
690
609
|
}
|
|
@@ -750,7 +669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
750
669
|
* `[twSheetClose]` value to pass a result to `afterClosed()` subscribers.
|
|
751
670
|
*/
|
|
752
671
|
class SheetCloseDirective {
|
|
753
|
-
/** Value passed to `afterClosed()` when the button is clicked. */
|
|
672
|
+
/** Value passed to `afterClosed()` when the button is clicked. Defaults to `undefined`. */
|
|
754
673
|
twSheetClose = input(undefined, /* @ts-ignore */
|
|
755
674
|
...(ngDevMode ? [{ debugName: "twSheetClose" }] : /* istanbul ignore next */ []));
|
|
756
675
|
/** Native button `type`. Defaults to `'button'` to avoid accidental form submission. */
|
|
@@ -778,5 +697,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
778
697
|
* Generated bundle index. Do not edit.
|
|
779
698
|
*/
|
|
780
699
|
|
|
781
|
-
export { SHEET_DATA, SHEET_DEFAULT_OPTIONS, Sheet, SheetActionsDirective, SheetCloseDirective, SheetConfig,
|
|
700
|
+
export { SHEET_DATA, SHEET_DEFAULT_OPTIONS, Sheet, SheetActionsDirective, SheetCloseDirective, SheetConfig, SheetContentDirective, SheetDescriptionDirective, SheetHeaderDirective, SheetIconDirective, SheetRef, SheetSubtitleDirective, SheetTitleDirective, TW_SHEET_DATA, TW_SHEET_DEFAULT_OPTIONS, provideSheet };
|
|
782
701
|
//# sourceMappingURL=cdevhub-ngx-tw-sheet.mjs.map
|