@ngutil/layout 0.0.3-dev.9 → 0.0.4

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.
@@ -1,115 +1,8 @@
1
+ import { BehaviorSubject, map, shareReplay, ReplaySubject, combineLatest, switchMap, of, Subject, startWith, scan, tap, distinctUntilChanged, finalize } from 'rxjs';
1
2
  import * as i0 from '@angular/core';
2
- import { inject, NgZone, Component, ElementRef, Input, Output, ChangeDetectionStrategy, ContentChild, ContentChildren, NgModule, Injectable, TemplateRef, Directive, ViewContainerRef, Injector } from '@angular/core';
3
- import { Observable, distinctUntilChanged, shareReplay, BehaviorSubject, map, combineLatest, switchMap, of, Subject, startWith, scan, tap, finalize } from 'rxjs';
3
+ import { Component, HostBinding, inject, ElementRef, ViewChild, Input, Output, ChangeDetectionStrategy, ContentChild, ContentChildren, NgModule, Injectable, TemplateRef, Directive, ViewContainerRef, Injector } from '@angular/core';
4
4
  import { NumberWithUnit, Destructible, coerceBoolAttr, FastDOM } from '@ngutil/common';
5
-
6
- const WATCHES = {};
7
- /**
8
- * watchMedia("(display-mode: standalone)")
9
- */
10
- function watchMedia(expr) {
11
- const existing = WATCHES[expr];
12
- if (existing == null) {
13
- return (WATCHES[expr] = _createWatcher(expr));
14
- }
15
- return existing;
16
- }
17
- function _createWatcher(expr) {
18
- const zone = inject(NgZone);
19
- return zone.runOutsideAngular(() => new Observable((sub) => {
20
- const query = window.matchMedia(expr);
21
- const listener = (event) => {
22
- sub.next(event.matches);
23
- };
24
- query.addEventListener("change", listener);
25
- sub.next(query.matches);
26
- return () => {
27
- query.removeEventListener("change", listener);
28
- delete WATCHES[expr];
29
- };
30
- }).pipe(distinctUntilChanged(), shareReplay(1)));
31
- }
32
-
33
- const RESIZE_WATCHES = new Map();
34
- const SCROLL_WATCHES = new Map();
35
- function watchDimension(el, box = "border-box") {
36
- const zone = inject(NgZone);
37
- return box === "scroll-box" ? _watchScroll(zone, el) : _watchResize(zone, el, box);
38
- }
39
- function _watchResize(zone, el, box) {
40
- return _watch(zone, el, RESIZE_WATCHES, () => _createResizeWatcher(zone, el, box));
41
- }
42
- function _watchScroll(zone, el) {
43
- return _watch(zone, el, SCROLL_WATCHES, () => _createScollWatcher(zone, el));
44
- }
45
- function _watch(zone, el, watches, factory) {
46
- const existing = watches.get(el);
47
- if (existing == null) {
48
- const watcher = factory();
49
- watches.set(el, watcher);
50
- return watcher;
51
- }
52
- return existing;
53
- }
54
- function _createResizeWatcher(zone, el, box) {
55
- if (box !== "border-box") {
56
- throw new Error(`Currently not implemented box mode: ${box}`);
57
- }
58
- return zone.runOutsideAngular(() => new Observable((sub) => {
59
- const observer = new ResizeObserver(entries => {
60
- for (const entry of entries) {
61
- if (entry.borderBoxSize) {
62
- sub.next({
63
- width: _number(entry.borderBoxSize[0].inlineSize),
64
- height: _number(entry.borderBoxSize[0].blockSize)
65
- });
66
- }
67
- else {
68
- sub.next({
69
- width: _number(el.offsetWidth),
70
- height: _number(el.offsetHeight)
71
- });
72
- }
73
- }
74
- });
75
- observer.observe(el, { box: box });
76
- return () => {
77
- observer.disconnect();
78
- RESIZE_WATCHES.delete(el);
79
- };
80
- }).pipe(distinctUntilChanged((p, c) => p && c && p.width === c.width && p.height === c.height), shareReplay(1)));
81
- }
82
- function _createScollWatcher(zone, el) {
83
- return zone.runOutsideAngular(() => new Observable((sub) => {
84
- let lastSw = 0;
85
- let lastSh = 0;
86
- const emit = () => {
87
- const sw = el.scrollWidth;
88
- const sh = el.scrollHeight;
89
- if (lastSw !== sw || lastSh !== sh) {
90
- lastSw = sw;
91
- lastSh = sh;
92
- sub.next({ width: _number(lastSw), height: _number(lastSh) });
93
- }
94
- };
95
- const dimSum = _watchResize(zone, el, "border-box").subscribe(emit);
96
- const mutation = new MutationObserver(emit);
97
- mutation.observe(el, {
98
- subtree: true,
99
- childList: true,
100
- attributes: true,
101
- characterData: true
102
- });
103
- return () => {
104
- dimSum.unsubscribe();
105
- mutation.disconnect();
106
- SCROLL_WATCHES.delete(el);
107
- };
108
- }).pipe(shareReplay(1)));
109
- }
110
- function _number(val) {
111
- return new NumberWithUnit(val, "pk");
112
- }
5
+ import { DimensionWatcher } from '@ngutil/style';
113
6
 
114
7
  /**
115
8
  * -----------------------------------------------
@@ -238,26 +131,37 @@ class L9State {
238
131
  return res;
239
132
  }), shareReplay(1));
240
133
  }
241
- update(range, dim) {
242
- range = L9Range.coerce(range);
243
- const dims = { ...this.#dims.value };
244
- // for (const cell of range.horizontals) {
245
- // dims[cell] = dim.width
246
- // }
247
- }
248
134
  }
249
135
 
250
136
  class DockingContentComponent {
251
137
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
252
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DockingContentComponent, isStandalone: true, selector: "nu-docking-content", ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [":host{display:flex;flex-flow:column nowrap;align-items:stretch;box-sizing:border-box;flex:1;overflow:auto}\n"] }); }
138
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DockingContentComponent, isStandalone: true, selector: "nu-docking-content", exportAs: ["nuDockingContent"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [":host{display:flex;flex-flow:column nowrap;align-items:stretch;box-sizing:border-box;flex:1}\n"] }); }
253
139
  }
254
140
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingContentComponent, decorators: [{
255
141
  type: Component,
256
- args: [{ standalone: true, selector: "nu-docking-content", template: `<ng-content></ng-content>`, styles: [":host{display:flex;flex-flow:column nowrap;align-items:stretch;box-sizing:border-box;flex:1;overflow:auto}\n"] }]
142
+ args: [{ standalone: true, selector: "nu-docking-content", exportAs: "nuDockingContent", template: `<ng-content></ng-content>`, styles: [":host{display:flex;flex-flow:column nowrap;align-items:stretch;box-sizing:border-box;flex:1}\n"] }]
257
143
  }] });
258
144
 
145
+ class DockingBackdropComponent {
146
+ constructor() {
147
+ this.state = "hidden";
148
+ }
149
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingBackdropComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
150
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DockingBackdropComponent, isStandalone: true, selector: "nu-docking-backdrop", host: { properties: { "[attr.state]": "this.state" } }, ngImport: i0, template: ``, isInline: true, styles: [":host{display:flex;flex-direction:column;align-items:stretch;position:absolute;inset:0;transition:opacity var(---docking-layout-anim-duration) var(---docking-layout-anim-ease);z-index:-1;background-color:var(---docking-layout-backdrop-color)}:host[state=hidden]{animation:var(---docking-layout-anim-duration) var(---docking-layout-anim-ease) hide;animation-fill-mode:forwards;pointer-events:none;touch-action:none;opacity:0}:host[state=visible]{visibility:visible;opacity:.3}@keyframes hide{99%{visibility:visible}to{visibility:hidden}}\n"] }); }
151
+ }
152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingBackdropComponent, decorators: [{
153
+ type: Component,
154
+ args: [{ standalone: true, selector: "nu-docking-backdrop", template: ``, styles: [":host{display:flex;flex-direction:column;align-items:stretch;position:absolute;inset:0;transition:opacity var(---docking-layout-anim-duration) var(---docking-layout-anim-ease);z-index:-1;background-color:var(---docking-layout-backdrop-color)}:host[state=hidden]{animation:var(---docking-layout-anim-duration) var(---docking-layout-anim-ease) hide;animation-fill-mode:forwards;pointer-events:none;touch-action:none;opacity:0}:host[state=visible]{visibility:visible;opacity:.3}@keyframes hide{99%{visibility:visible}to{visibility:hidden}}\n"] }]
155
+ }], propDecorators: { state: [{
156
+ type: HostBinding,
157
+ args: ["[attr.state]"]
158
+ }] } });
159
+
259
160
  const DEFAULT_POSITION = L9Range.coerce("left");
161
+ const HIDDEN_SIZE = new NumberWithUnit(0, "px");
162
+ const AUTO_SIZE = NumberWithUnit.coerce("auto");
260
163
  class DockingPanelComponent extends Destructible {
164
+ #dimWatcher;
261
165
  set positionInput(val) {
262
166
  const coerced = L9Range.coerce(val);
263
167
  if (coerced.orient === "rect") {
@@ -300,19 +204,31 @@ class DockingPanelComponent extends Destructible {
300
204
  }
301
205
  #minimizable;
302
206
  #minimizableAuto;
207
+ set backdrop(val) {
208
+ this.#backdrop = coerceBoolAttr(val);
209
+ }
210
+ get backdrop() {
211
+ return this.#backdrop;
212
+ }
213
+ #backdrop;
214
+ #contentSize;
303
215
  #autoSize;
216
+ // TODO: better animation handling in min -> hidden -> min -> full
304
217
  constructor() {
305
218
  super();
306
219
  this.el = inject((ElementRef));
220
+ this.#dimWatcher = inject(DimensionWatcher);
307
221
  this.position = new BehaviorSubject(DEFAULT_POSITION);
308
- this.state = new BehaviorSubject("invisible");
309
- this.mode = new BehaviorSubject("overlay");
310
- this.#fullSize = new BehaviorSubject(NumberWithUnit.coerce(0));
311
- this.#miniSize = new BehaviorSubject(NumberWithUnit.coerce(0));
222
+ this.state = new BehaviorSubject("full");
223
+ this.mode = new BehaviorSubject("rigid");
224
+ this.#fullSize = new BehaviorSubject(AUTO_SIZE);
225
+ this.#miniSize = new BehaviorSubject(HIDDEN_SIZE);
312
226
  this.#minimizable = false;
313
227
  this.#minimizableAuto = true;
228
+ this.#backdrop = false;
229
+ this.#contentSize = new ReplaySubject(1);
314
230
  this.#autoSize = combineLatest({
315
- dim: watchDimension(this.el.nativeElement, "scroll-box"),
231
+ dim: this.#contentSize,
316
232
  pos: this.position
317
233
  }).pipe(map(({ dim, pos }) => {
318
234
  if (pos.orient === "horizontal") {
@@ -343,7 +259,8 @@ class DockingPanelComponent extends Destructible {
343
259
  state: this.state,
344
260
  mode: this.mode,
345
261
  fullSize: this.fullSize,
346
- miniSize: this.miniSize
262
+ miniSize: this.miniSize,
263
+ contentSize: this.#contentSize
347
264
  });
348
265
  this.d.sub(this.changes).subscribe(changes => {
349
266
  if (this.#minimizableAuto) {
@@ -355,13 +272,51 @@ class DockingPanelComponent extends Destructible {
355
272
  mode: changes.mode,
356
273
  side: changes.position.orient === "horizontal" ? changes.position.cells[0].v : changes.position.cells[0].h
357
274
  });
275
+ const isHorizontal = changes.position.orient === "horizontal";
276
+ let w = null;
277
+ let h = null;
278
+ // TODO: when change state from mini -> hidden, currently wrong behavior
279
+ // the good behavior is to not gain fullSize ang go to hidden
280
+ if (changes.state === "mini") {
281
+ if (isHorizontal) {
282
+ h = changes.miniSize.unit === "auto" ? changes.contentSize.height : changes.miniSize;
283
+ }
284
+ else {
285
+ w = changes.miniSize.unit === "auto" ? changes.contentSize.width : changes.miniSize;
286
+ }
287
+ }
288
+ else {
289
+ if (isHorizontal) {
290
+ h = changes.fullSize.unit === "auto" ? changes.contentSize.height : changes.fullSize;
291
+ }
292
+ else {
293
+ w = changes.fullSize.unit === "auto" ? changes.contentSize.width : changes.fullSize;
294
+ }
295
+ }
296
+ FastDOM.setStyle(this.el.nativeElement, {
297
+ "--docking-panel-w": w != null ? `${w}` : null,
298
+ "--docking-panel-h": h != null ? `${h}` : null,
299
+ "--docking-panel-content-w": changes.contentSize.width,
300
+ "--docking-panel-content-h": changes.contentSize.height
301
+ }, () => FastDOM.setAttributes(this.el.nativeElement, { animate: "" }));
358
302
  });
359
303
  }
304
+ ngAfterViewInit() {
305
+ this.d
306
+ .sub(this.#dimWatcher.watch(this.content, "scroll-box"))
307
+ .pipe(map(dim => {
308
+ return {
309
+ width: new NumberWithUnit(dim.width, "px"),
310
+ height: new NumberWithUnit(dim.height, "px")
311
+ };
312
+ }))
313
+ .subscribe(this.#contentSize);
314
+ }
360
315
  open() {
361
316
  this.state.next("full");
362
317
  }
363
318
  close() {
364
- this.state.next("invisible");
319
+ this.state.next("hidden");
365
320
  }
366
321
  minimize() {
367
322
  if (this.minimizable) {
@@ -369,12 +324,23 @@ class DockingPanelComponent extends Destructible {
369
324
  }
370
325
  }
371
326
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
372
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DockingPanelComponent, isStandalone: true, selector: "nu-docking-panel", inputs: { positionInput: ["position", "positionInput"], stateInput: ["state", "stateInput"], modeInput: ["mode", "modeInput"], fullSizeInput: ["fullSize", "fullSizeInput"], miniSizeInput: ["miniSize", "miniSizeInput"], minimizable: "minimizable" }, outputs: { state: "stateChanges" }, exportAs: ["nuDockingPanel"], usesInheritance: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [":host{---docking-panel-t: var(--docking-panel-t, auto);---docking-panel-r: var(--docking-panel-r, auto);---docking-panel-b: var(--docking-panel-b, auto);---docking-panel-l: var(--docking-panel-l, auto);---docking-panel-w: var(--docking-panel-w, auto);---docking-panel-h: var(--docking-panel-h, auto);---docking-panel-real-w: var(--docking-panel-real-w, var(---docking-panel-w));---docking-panel-real-h: var(--docking-panel-real-h, var(---docking-panel-h));display:flex;flex-flow:column nowrap;align-items:stretch;position:absolute;box-sizing:border-box;top:var(---docking-panel-t);right:var(---docking-panel-r);bottom:var(---docking-panel-b);left:var(---docking-panel-l);width:var(---docking-panel-w);height:var(---docking-panel-h);transition:transform var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),width var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),height var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}:host[side=top],:host[side=left]{---docking-panel-t-hide: -100%;---docking-panel-t-visible: 0%}:host[side=bottom],:host[side=right]{---docking-panel-t-hide: 100%;---docking-panel-t-visible: 0%}:host[state=invisible][orient=horizontal]{transform:translateY(var(---docking-panel-t-hide))}:host[state=invisible][orient=vertical]{transform:translate(var(---docking-panel-t-hide))}:host:not([state=invisible])[orient=horizontal]{transform:translateY(var(---docking-panel-t-visible))}:host:not([state=invisible])[orient=vertical]{transform:translate(var(---docking-panel-t-visible))}\n"] }); }
327
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: DockingPanelComponent, isStandalone: true, selector: "nu-docking-panel", inputs: { positionInput: ["position", "positionInput"], stateInput: ["state", "stateInput"], modeInput: ["mode", "modeInput"], fullSizeInput: ["fullSize", "fullSizeInput"], miniSizeInput: ["miniSize", "miniSizeInput"], minimizable: "minimizable", backdrop: "backdrop" }, outputs: { state: "stateChanges" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, read: ElementRef, static: true }], exportAs: ["nuDockingPanel"], usesInheritance: true, ngImport: i0, template: `
328
+ <div class="content" #content>
329
+ <ng-content></ng-content>
330
+ </div>
331
+ `, isInline: true, styles: [":host{---docking-panel-t: var(--docking-panel-t, auto);---docking-panel-r: var(--docking-panel-r, auto);---docking-panel-b: var(--docking-panel-b, auto);---docking-panel-l: var(--docking-panel-l, auto);---docking-panel-w: var(--docking-panel-w, auto);---docking-panel-h: var(--docking-panel-h, auto);---docking-panel-content-w: var(--docking-panel-content-w, var(---docking-panel-w));---docking-panel-content-g: var(--docking-panel-content-g, var(---docking-panel-h));display:flex;flex-flow:column nowrap;align-items:stretch;position:absolute;box-sizing:border-box;overflow:hidden;top:var(---docking-panel-t);right:var(---docking-panel-r);bottom:var(---docking-panel-b);left:var(---docking-panel-l);width:var(---docking-panel-w);height:var(---docking-panel-h)}:host[animate]{transition:transform var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),width var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),height var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}:host[side=top],:host[side=left]{---docking-panel-t-hide: -100%;---docking-panel-t-visible: 0%}:host[side=bottom],:host[side=right]{---docking-panel-t-hide: 100%;---docking-panel-t-visible: 0%}:host[state=hidden]{animation:var(---docking-layout-anim-duration) var(---docking-layout-anim-ease) hide;animation-fill-mode:forwards}:host[state=hidden][orient=horizontal]{transform:translateY(var(---docking-panel-t-hide))}:host[state=hidden][orient=vertical]{transform:translate(var(---docking-panel-t-hide))}:host:not([state=hidden]){visibility:visible}:host:not([state=hidden])[orient=horizontal]{transform:translateY(var(---docking-panel-t-visible))}:host:not([state=hidden])[orient=vertical]{transform:translate(var(---docking-panel-t-visible))}:host .content{display:flex;flex-direction:column;align-items:stretch}:host[orient=horizontal] .content{width:100%;min-width:100%;max-width:100%}:host[orient=vertical] .content{height:100%;min-height:100%;max-height:100%}@keyframes hide{99%{visibility:visible}to{visibility:hidden}}\n"] }); }
373
332
  }
374
333
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingPanelComponent, decorators: [{
375
334
  type: Component,
376
- args: [{ standalone: true, selector: "nu-docking-panel", exportAs: "nuDockingPanel", template: `<ng-content></ng-content>`, styles: [":host{---docking-panel-t: var(--docking-panel-t, auto);---docking-panel-r: var(--docking-panel-r, auto);---docking-panel-b: var(--docking-panel-b, auto);---docking-panel-l: var(--docking-panel-l, auto);---docking-panel-w: var(--docking-panel-w, auto);---docking-panel-h: var(--docking-panel-h, auto);---docking-panel-real-w: var(--docking-panel-real-w, var(---docking-panel-w));---docking-panel-real-h: var(--docking-panel-real-h, var(---docking-panel-h));display:flex;flex-flow:column nowrap;align-items:stretch;position:absolute;box-sizing:border-box;top:var(---docking-panel-t);right:var(---docking-panel-r);bottom:var(---docking-panel-b);left:var(---docking-panel-l);width:var(---docking-panel-w);height:var(---docking-panel-h);transition:transform var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),width var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),height var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}:host[side=top],:host[side=left]{---docking-panel-t-hide: -100%;---docking-panel-t-visible: 0%}:host[side=bottom],:host[side=right]{---docking-panel-t-hide: 100%;---docking-panel-t-visible: 0%}:host[state=invisible][orient=horizontal]{transform:translateY(var(---docking-panel-t-hide))}:host[state=invisible][orient=vertical]{transform:translate(var(---docking-panel-t-hide))}:host:not([state=invisible])[orient=horizontal]{transform:translateY(var(---docking-panel-t-visible))}:host:not([state=invisible])[orient=vertical]{transform:translate(var(---docking-panel-t-visible))}\n"] }]
377
- }], ctorParameters: () => [], propDecorators: { positionInput: [{
335
+ args: [{ standalone: true, selector: "nu-docking-panel", exportAs: "nuDockingPanel", template: `
336
+ <div class="content" #content>
337
+ <ng-content></ng-content>
338
+ </div>
339
+ `, styles: [":host{---docking-panel-t: var(--docking-panel-t, auto);---docking-panel-r: var(--docking-panel-r, auto);---docking-panel-b: var(--docking-panel-b, auto);---docking-panel-l: var(--docking-panel-l, auto);---docking-panel-w: var(--docking-panel-w, auto);---docking-panel-h: var(--docking-panel-h, auto);---docking-panel-content-w: var(--docking-panel-content-w, var(---docking-panel-w));---docking-panel-content-g: var(--docking-panel-content-g, var(---docking-panel-h));display:flex;flex-flow:column nowrap;align-items:stretch;position:absolute;box-sizing:border-box;overflow:hidden;top:var(---docking-panel-t);right:var(---docking-panel-r);bottom:var(---docking-panel-b);left:var(---docking-panel-l);width:var(---docking-panel-w);height:var(---docking-panel-h)}:host[animate]{transition:transform var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),width var(---docking-layout-anim-duration) var(---docking-layout-anim-ease),height var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}:host[side=top],:host[side=left]{---docking-panel-t-hide: -100%;---docking-panel-t-visible: 0%}:host[side=bottom],:host[side=right]{---docking-panel-t-hide: 100%;---docking-panel-t-visible: 0%}:host[state=hidden]{animation:var(---docking-layout-anim-duration) var(---docking-layout-anim-ease) hide;animation-fill-mode:forwards}:host[state=hidden][orient=horizontal]{transform:translateY(var(---docking-panel-t-hide))}:host[state=hidden][orient=vertical]{transform:translate(var(---docking-panel-t-hide))}:host:not([state=hidden]){visibility:visible}:host:not([state=hidden])[orient=horizontal]{transform:translateY(var(---docking-panel-t-visible))}:host:not([state=hidden])[orient=vertical]{transform:translate(var(---docking-panel-t-visible))}:host .content{display:flex;flex-direction:column;align-items:stretch}:host[orient=horizontal] .content{width:100%;min-width:100%;max-width:100%}:host[orient=vertical] .content{height:100%;min-height:100%;max-height:100%}@keyframes hide{99%{visibility:visible}to{visibility:hidden}}\n"] }]
340
+ }], ctorParameters: () => [], propDecorators: { content: [{
341
+ type: ViewChild,
342
+ args: ["content", { read: ElementRef, static: true }]
343
+ }], positionInput: [{
378
344
  type: Input,
379
345
  args: ["position"]
380
346
  }], stateInput: [{
@@ -395,57 +361,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImpor
395
361
  }], minimizable: [{
396
362
  type: Input,
397
363
  args: ["minimizable"]
364
+ }], backdrop: [{
365
+ type: Input,
366
+ args: ["backdrop"]
398
367
  }] } });
399
368
 
400
- const EMBEDDED_ZINDEX = 20;
401
- const OVERLAY_ZINDEX = EMBEDDED_ZINDEX * 2;
402
- // interface PanelRefChanges {
403
- // ref: PanelRef
404
- // changes: DockingPanelChanges
405
- // }
406
- // class PanelRef {
407
- // style: Partial<CSSStyleDeclaration> = {}
408
- // readonly changes: Observable<PanelRefChanges>
409
- // constructor(public readonly panel: DockingPanelDirective) {
410
- // this.changes = panel.changes.pipe(
411
- // map(changes => {
412
- // return { ref: this, changes }
413
- // })
414
- // )
415
- // }
416
- // }
369
+ const RIGID_ZINDEX = 100;
370
+ const OVER_ZINDEX = RIGID_ZINDEX * 2;
371
+ const BACKDROP_ZINDEX = 10000;
417
372
  class DockingLayoutComponent extends Destructible {
418
373
  constructor() {
419
374
  super(...arguments);
420
375
  this.#el = inject((ElementRef));
421
376
  this.contentOnly = false;
422
- this.positionMode = "absolute";
423
377
  this.#reflow = new Subject();
378
+ this.#backdropPanel = null;
424
379
  }
425
380
  #el;
426
381
  #reflow;
382
+ #backdropPanel;
427
383
  ngAfterViewInit() {
428
384
  // eslint-disable-next-line prettier/prettier
429
385
  this.panels = this.dockingPanels.changes.pipe(startWith(null), map(() => this.dockingPanels.toArray()), shareReplay(1));
430
- // this.panels.subscribe(panels => console.log({ panels }))
431
386
  this.d
432
387
  .sub(combineLatest({ panels: this.panels, reflow: this.#reflow.pipe(startWith(null)) }))
433
388
  .pipe(switchMap(({ panels }) => combineLatest(panels.map(panel => panel.changes.pipe(map(changes => {
434
389
  return { panel, changes };
435
390
  }))))))
436
391
  .subscribe(this.#layout.bind(this));
437
- // this.d
438
- // .sub(merge(this.dockingPanels.changes, this.#reflow))
439
- // .pipe(
440
- // startWith(null),
441
- // map(() => this.dockingPanels.map(panel => new PanelRef(panel))),
442
- // switchMap(refs => combineLatest(refs.map(ref => ref.changes))),
443
- // map(changes => {
444
- // this.#layout(changes)
445
- // return changes.map(c => c.ref)
446
- // })
447
- // )
448
- // .subscribe(this.panels)
449
392
  }
450
393
  ngOnChanges(changes) {
451
394
  if ("contentOnly" in changes || "positionMode" in changes) {
@@ -457,8 +400,10 @@ class DockingLayoutComponent extends Destructible {
457
400
  let paddingRight = 0;
458
401
  let paddingBottom = 0;
459
402
  let paddingLeft = 0;
460
- let embeddedZIndex = EMBEDDED_ZINDEX;
461
- let overlayZIndex = OVERLAY_ZINDEX;
403
+ let rigidZIndex = RIGID_ZINDEX;
404
+ let overZIndex = OVER_ZINDEX;
405
+ let backdropZIndex = -1;
406
+ this.#backdropPanel = null;
462
407
  if (this.contentOnly) {
463
408
  // TODO:...
464
409
  }
@@ -471,7 +416,7 @@ class DockingLayoutComponent extends Destructible {
471
416
  ? panelState.miniSize.value
472
417
  : 0;
473
418
  const isHorizontal = panelState.position.orient === "horizontal";
474
- const isEmbedded = panelState.mode === "embedded";
419
+ const isRigid = panelState.mode === "rigid";
475
420
  let panelTop = null;
476
421
  let panelRight = null;
477
422
  let panelBottom = null;
@@ -480,13 +425,13 @@ class DockingLayoutComponent extends Destructible {
480
425
  panelLeft = 0;
481
426
  panelRight = 0;
482
427
  if (panelState.position.cells[0].v === "top") {
483
- if (isEmbedded) {
428
+ if (isRigid) {
484
429
  paddingTop = Math.max(paddingTop, panelSize);
485
430
  }
486
431
  panelTop = 0;
487
432
  }
488
433
  else if (panelState.position.cells[0].v === "bottom") {
489
- if (isEmbedded) {
434
+ if (isRigid) {
490
435
  paddingBottom = Math.max(paddingBottom, panelSize);
491
436
  }
492
437
  panelBottom = 0;
@@ -496,37 +441,30 @@ class DockingLayoutComponent extends Destructible {
496
441
  panelTop = 0;
497
442
  panelBottom = 0;
498
443
  if (panelState.position.cells[0].h === "left") {
499
- if (isEmbedded) {
444
+ if (isRigid) {
500
445
  paddingLeft = Math.max(paddingLeft, panelSize);
501
446
  }
502
447
  panelLeft = 0;
503
448
  }
504
449
  else if (panelState.position.cells[0].h === "right") {
505
- if (isEmbedded) {
450
+ if (isRigid) {
506
451
  paddingRight = Math.max(paddingRight, panelSize);
507
452
  }
508
453
  panelRight = 0;
509
454
  }
510
455
  }
511
- const panelGivenSize = panelState.state === "full"
512
- ? panelState.fullSize
513
- : panelState.state === "mini"
514
- ? panelState.miniSize
515
- : new NumberWithUnit(0, "px");
456
+ let panelZIndex = isRigid ? (rigidZIndex += 2) : (overZIndex += 2);
457
+ if (panelState.state !== "hidden" && entry.panel.backdrop) {
458
+ backdropZIndex = BACKDROP_ZINDEX;
459
+ panelZIndex = backdropZIndex + 1;
460
+ this.#backdropPanel = entry.panel;
461
+ }
516
462
  FastDOM.setStyle(entry.panel.el.nativeElement, {
517
- "z-index": `${isEmbedded ? embeddedZIndex++ : overlayZIndex++}`,
463
+ "z-index": `${panelZIndex}`,
518
464
  "--docking-panel-t": panelTop != null ? `${panelTop}px` : null,
519
465
  "--docking-panel-r": panelRight != null ? `${panelRight}px` : null,
520
466
  "--docking-panel-b": panelBottom != null ? `${panelBottom}px` : null,
521
- "--docking-panel-l": panelLeft != null ? `${panelLeft}px` : null,
522
- "--docking-panel-w": !isHorizontal
523
- ? `${panelGivenSize.unit === "auto" ? "auto" : panelGivenSize}`
524
- : null,
525
- "--docking-panel-h": isHorizontal
526
- ? `${panelGivenSize.unit === "auto" ? "auto" : panelGivenSize}`
527
- : null,
528
- "--docking-panel-real-w": !isHorizontal ? `${panelSize}px` : null,
529
- "--docking-panel-real-h": isHorizontal ? `${panelSize}px` : null
467
+ "--docking-panel-l": panelLeft != null ? `${panelLeft}px` : null
530
468
  });
531
469
  }
532
470
  FastDOM.setStyle(this.#el.nativeElement, {
@@ -535,10 +473,22 @@ class DockingLayoutComponent extends Destructible {
535
473
  "--docking-layout-bottom": `${paddingBottom}px`,
536
474
  "--docking-layout-left": `${paddingLeft}px`
537
475
  });
476
+ if (this.backdropEl) {
477
+ FastDOM.setAttributes(this.backdropEl.nativeElement, {
478
+ state: backdropZIndex < 0 ? "hidden" : "visible"
479
+ });
480
+ FastDOM.setStyle(this.backdropEl.nativeElement, { "z-index": `${backdropZIndex}` });
481
+ }
482
+ }
483
+ }
484
+ onHideBackdropPanel(event) {
485
+ event.preventDefault();
486
+ if (this.#backdropPanel) {
487
+ this.#backdropPanel.close();
538
488
  }
539
489
  }
540
490
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingLayoutComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
541
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.3", type: DockingLayoutComponent, isStandalone: true, selector: "nu-docking", inputs: { contentOnly: "contentOnly", positionMode: "positionMode" }, queries: [{ propertyName: "contentComponent", first: true, predicate: DockingContentComponent, descendants: true }, { propertyName: "dockingPanels", predicate: DockingPanelComponent }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
491
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.3", type: DockingLayoutComponent, isStandalone: true, selector: "nu-docking", inputs: { contentOnly: "contentOnly" }, queries: [{ propertyName: "contentComponent", first: true, predicate: DockingContentComponent, descendants: true }, { propertyName: "dockingPanels", predicate: DockingPanelComponent }], viewQueries: [{ propertyName: "backdropEl", first: true, predicate: ["backdrop"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
542
492
  <ng-content select="nu-docking-panel"></ng-content>
543
493
 
544
494
  @if (!contentComponent) {
@@ -548,11 +498,13 @@ class DockingLayoutComponent extends Destructible {
548
498
  } @else {
549
499
  <ng-content select="nu-docking-content"></ng-content>
550
500
  }
551
- `, isInline: true, styles: [":host{---docking-layout-top: var(--docking-layout-top, 0px);---docking-layout-right: var(--docking-layout-right, 0px);---docking-layout-bottom: var(--docking-layout-bottom, 0px);---docking-layout-left: var(--docking-layout-left, 0px);---docking-layout-anim-duration: var(--docking-layout-anim-duration, .2s);---docking-layout-anim-ease: var(--docking-layout-anim-ease, ease-out);display:flex;flex-flow:column nowrap;align-items:stretch;position:relative;overflow:hidden;box-sizing:border-box;z-index:0;padding:var(---docking-layout-top) var(---docking-layout-right) var(---docking-layout-bottom) var(---docking-layout-left);transition:padding var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}\n"], dependencies: [{ kind: "component", type: DockingContentComponent, selector: "nu-docking-content" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
501
+
502
+ <nu-docking-backdrop #backdrop (click)="onHideBackdropPanel($event)" />
503
+ `, isInline: true, styles: [":host{---docking-layout-top: var(--docking-layout-top, 0px);---docking-layout-right: var(--docking-layout-right, 0px);---docking-layout-bottom: var(--docking-layout-bottom, 0px);---docking-layout-left: var(--docking-layout-left, 0px);---docking-layout-anim-duration: var(--docking-layout-anim-duration, .3s);---docking-layout-anim-ease: var(--docking-layout-anim-ease, cubic-bezier(.4, 0, .2, 1));---docking-layout-backdrop-color: var(--docking-layout-backdrop-color, #000);display:flex;flex-flow:column nowrap;align-items:stretch;position:relative;overflow:hidden;box-sizing:border-box;z-index:0;padding:var(---docking-layout-top) var(---docking-layout-right) var(---docking-layout-bottom) var(---docking-layout-left);transition:padding var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}\n"], dependencies: [{ kind: "component", type: DockingContentComponent, selector: "nu-docking-content", exportAs: ["nuDockingContent"] }, { kind: "component", type: DockingBackdropComponent, selector: "nu-docking-backdrop" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
552
504
  }
553
505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: DockingLayoutComponent, decorators: [{
554
506
  type: Component,
555
- args: [{ selector: "nu-docking", standalone: true, imports: [DockingContentComponent], template: `
507
+ args: [{ selector: "nu-docking", standalone: true, imports: [DockingContentComponent, DockingBackdropComponent], template: `
556
508
  <ng-content select="nu-docking-panel"></ng-content>
557
509
 
558
510
  @if (!contentComponent) {
@@ -562,14 +514,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImpor
562
514
  } @else {
563
515
  <ng-content select="nu-docking-content"></ng-content>
564
516
  }
565
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{---docking-layout-top: var(--docking-layout-top, 0px);---docking-layout-right: var(--docking-layout-right, 0px);---docking-layout-bottom: var(--docking-layout-bottom, 0px);---docking-layout-left: var(--docking-layout-left, 0px);---docking-layout-anim-duration: var(--docking-layout-anim-duration, .2s);---docking-layout-anim-ease: var(--docking-layout-anim-ease, ease-out);display:flex;flex-flow:column nowrap;align-items:stretch;position:relative;overflow:hidden;box-sizing:border-box;z-index:0;padding:var(---docking-layout-top) var(---docking-layout-right) var(---docking-layout-bottom) var(---docking-layout-left);transition:padding var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}\n"] }]
517
+
518
+ <nu-docking-backdrop #backdrop (click)="onHideBackdropPanel($event)" />
519
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{---docking-layout-top: var(--docking-layout-top, 0px);---docking-layout-right: var(--docking-layout-right, 0px);---docking-layout-bottom: var(--docking-layout-bottom, 0px);---docking-layout-left: var(--docking-layout-left, 0px);---docking-layout-anim-duration: var(--docking-layout-anim-duration, .3s);---docking-layout-anim-ease: var(--docking-layout-anim-ease, cubic-bezier(.4, 0, .2, 1));---docking-layout-backdrop-color: var(--docking-layout-backdrop-color, #000);display:flex;flex-flow:column nowrap;align-items:stretch;position:relative;overflow:hidden;box-sizing:border-box;z-index:0;padding:var(---docking-layout-top) var(---docking-layout-right) var(---docking-layout-bottom) var(---docking-layout-left);transition:padding var(---docking-layout-anim-duration) var(---docking-layout-anim-ease)}\n"] }]
566
520
  }], propDecorators: { contentOnly: [{
567
521
  type: Input
568
- }], positionMode: [{
569
- type: Input
570
522
  }], contentComponent: [{
571
523
  type: ContentChild,
572
524
  args: [DockingContentComponent]
525
+ }], backdropEl: [{
526
+ type: ViewChild,
527
+ args: ["backdrop", { read: ElementRef, static: true }]
573
528
  }], dockingPanels: [{
574
529
  type: ContentChildren,
575
530
  args: [DockingPanelComponent]
@@ -829,5 +784,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImpor
829
784
  * Generated bundle index. Do not edit.
830
785
  */
831
786
 
832
- export { DockingContentComponent, DockingLayoutComponent, DockingPanelComponent, L9Cell, L9Range, L9State, NuDockingLayout, SlotDef, SlotDirective, SlotOutletDirective, SlotsService, watchDimension, watchMedia };
787
+ export { DockingContentComponent, DockingLayoutComponent, DockingPanelComponent, L9Cell, L9Range, L9State, NuDockingLayout, SlotDef, SlotDirective, SlotOutletDirective, SlotsService };
833
788
  //# sourceMappingURL=ngutil-layout.mjs.map