@ngutil/floating 0.0.64 → 0.0.65

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,10 +1,9 @@
1
1
  import { AnimationBuilder, style as style$1, animate } from '@angular/animations';
2
- import { Observable, switchMap, tap, timer, take, map, fromEvent, filter, from, of, race, exhaustMap, distinctUntilChanged, combineLatest, takeUntil, share, ReplaySubject, shareReplay, takeWhile, debounceTime, startWith, EMPTY } from 'rxjs';
2
+ import { Observable, switchMap, tap, timer, take, map, fromEvent, filter, from, of, race, exhaustMap, distinctUntilChanged, combineLatest, takeUntil, isObservable, share, ReplaySubject, shareReplay, takeWhile, debounceTime, startWith, EMPTY } from 'rxjs';
3
3
  import { animationObservable, CoverService } from '@ngutil/graphics';
4
- import { Duration, Ease, alignmentToTransformOrigin, DimensionWatcher, rectExpand, rectOrigin, rectMoveOrigin, rectContract, alignmentNormalize, RectWatcher } from '@ngutil/style';
4
+ import { Duration, Ease, alignmentToTransformOrigin, DimensionWatcher, RectWatcher, floatingPosition, floatingPositionToStyle } from '@ngutil/style';
5
5
  import { KeystrokeService, FocusService } from '@ngutil/aria';
6
6
  import { coerceElement, isElementInput, Lifecycle, toSorted } from '@ngutil/common';
7
- import { clamp } from 'lodash';
8
7
  import * as i0 from '@angular/core';
9
8
  import { ElementRef, Injector, InjectionToken, inject, Directive, Injectable, ComponentFactoryResolver, ViewContainerRef, ApplicationRef, Inject, TemplateRef } from '@angular/core';
10
9
  import { DOCUMENT } from '@angular/common';
@@ -45,7 +44,7 @@ function animationParams(floatingRef, delay, overrides) {
45
44
  ? timer(delay).pipe(switchMap(() => floatingRef.watchTrait("position")))
46
45
  : floatingRef.watchTrait("position");
47
46
  return src.pipe(take(1), map(position => {
48
- const origin = position.computed ? alignmentToTransformOrigin(position.computed.content.align) : "center";
47
+ const origin = alignmentToTransformOrigin(position.content.link);
49
48
  return {
50
49
  origin,
51
50
  ...overrides
@@ -234,68 +233,6 @@ function getFloatingUid(el, attr, dataset) {
234
233
  return undefined;
235
234
  }
236
235
 
237
- const DIM_MAP = {
238
- maxWidth: { computedRef: "max", dimension: "width" },
239
- maxHeight: { computedRef: "max", dimension: "height" },
240
- minWidth: { computedRef: "min", dimension: "width" },
241
- minHeight: { computedRef: "min", dimension: "height" }
242
- };
243
- class DimensionConstraintTrait {
244
- #map;
245
- constructor(name, value) {
246
- this.value = value;
247
- this.name = name;
248
- this.#map = DIM_MAP[name];
249
- }
250
- connect(floatingRef) {
251
- return new Observable((dst) => {
252
- if (isElementInput(this.value)) {
253
- const watcher = floatingRef.container.injector.get(DimensionWatcher);
254
- const refDim = watcher.watch(this.value, "border-box").pipe(map(value => value[this.#map.dimension]));
255
- return combineLatest({
256
- refDim: refDim,
257
- position: floatingRef.watchTrait("position")
258
- }).subscribe(({ refDim, position }) => {
259
- const floating = position.computed?.content;
260
- if (!floating) {
261
- return;
262
- }
263
- dst.next(clamp(refDim, floating.min[this.#map.dimension] || 0, floating.max[this.#map.dimension] || Infinity));
264
- });
265
- }
266
- else {
267
- return floatingRef.watchTrait("position").subscribe(position => {
268
- const floating = position.computed?.content;
269
- if (!floating) {
270
- return;
271
- }
272
- if (isNaN(this.value)) {
273
- dst.next(floating[this.#map.computedRef][this.#map.dimension]);
274
- }
275
- else {
276
- dst.next(clamp(this.value, floating.min[this.#map.dimension] || 0, floating.max[this.#map.dimension] || Infinity));
277
- }
278
- });
279
- }
280
- }).pipe(takeUntil(floatingRef.state.onExecute("disposing")), distinctUntilChanged(), tap(value => {
281
- const floatingEl = floatingRef.container.nativeElement;
282
- floatingEl.style[this.name] = `${value}px`;
283
- }));
284
- }
285
- }
286
- function maxWidth(value) {
287
- return new DimensionConstraintTrait("maxWidth", value);
288
- }
289
- function maxHeight(value) {
290
- return new DimensionConstraintTrait("maxHeight", value);
291
- }
292
- function minWidth(value) {
293
- return new DimensionConstraintTrait("minWidth", value);
294
- }
295
- function minHeight(value) {
296
- return new DimensionConstraintTrait("minHeight", value);
297
- }
298
-
299
236
  class FocusTrait {
300
237
  constructor(options) {
301
238
  this.options = options;
@@ -340,48 +277,6 @@ function focus(options) {
340
277
  return new FocusTrait(options);
341
278
  }
342
279
 
343
- function computePosition({ floating, anchor, placement, options }) {
344
- if (options.anchor.margin) {
345
- anchor = rectExpand(anchor, options.anchor.margin);
346
- }
347
- const anchorPoint = rectOrigin(anchor, options.anchor.align);
348
- let contentRect = rectMoveOrigin(floating, options.content.align, anchorPoint);
349
- if (options.content.margin) {
350
- contentRect = rectContract(contentRect, options.content.margin);
351
- }
352
- if (options.placement.padding) {
353
- placement = rectContract(placement, options.placement.padding);
354
- }
355
- return {
356
- content: {
357
- ...addTLRB(contentRect, placement),
358
- align: alignmentNormalize(options.content.align),
359
- connect: anchorPoint,
360
- max: { width: placement.width - contentRect.x, height: placement.height - contentRect.y },
361
- min: { width: 0, height: 0 }
362
- },
363
- anchor: {
364
- ...addTLRB(anchor, placement),
365
- align: alignmentNormalize(options.anchor.align),
366
- connect: anchorPoint
367
- },
368
- placement: addTLRB(placement, placement)
369
- };
370
- }
371
- function addTLRB(rect, container) {
372
- return {
373
- ...rect,
374
- top: rect.y,
375
- left: rect.x,
376
- right: container.width - (rect.x + rect.width),
377
- bottom: container.height - (rect.y + rect.height)
378
- };
379
- }
380
-
381
- class FloatingAnchorRef extends ElementRef {
382
- }
383
- class FloatingPlacementRef extends ElementRef {
384
- }
385
280
  class PositionTrait {
386
281
  constructor(options) {
387
282
  this.name = "position";
@@ -390,10 +285,10 @@ class PositionTrait {
390
285
  cloned.placement = { ref: "viewport" };
391
286
  }
392
287
  if (!cloned.anchor) {
393
- cloned.anchor = { ref: cloned.placement.ref, align: "center middle" };
288
+ cloned.anchor = { ref: cloned.placement.ref, link: "center middle" };
394
289
  }
395
290
  if (!cloned.content) {
396
- cloned.content = { align: "center middle" };
291
+ cloned.content = { link: "center middle" };
397
292
  }
398
293
  this.options = cloned;
399
294
  }
@@ -402,16 +297,31 @@ class PositionTrait {
402
297
  const injector = floatingRef.container.injector;
403
298
  const dimWatcher = injector.get(DimensionWatcher);
404
299
  const rectWatcher = injector.get(RectWatcher);
405
- const watches = {
406
- floating: dimWatcher.watch(floatingRef.container, "border-box"),
300
+ const dimWatches = {
301
+ content: dimWatcher.watch(floatingRef.container, "border-box"),
407
302
  anchor: refWatcher(rectWatcher, this.options.anchor.ref, floatingRef),
408
303
  placement: refWatcher(rectWatcher, this.options.placement.ref, floatingRef)
409
304
  };
410
- return combineLatest(watches).subscribe(({ floating, anchor, placement }) => {
411
- const res = new FloatingPosition(this.options, floating, anchor, placement);
412
- res.apply(floatingRef);
413
- dest.next(res);
414
- });
305
+ const sizeWatches = {
306
+ minWidth: sizeWatcher(dimWatcher, "width", this.options.content.minWidth),
307
+ maxWidth: sizeWatcher(dimWatcher, "width", this.options.content.maxWidth),
308
+ minHeight: sizeWatcher(dimWatcher, "height", this.options.content.minHeight),
309
+ maxHeight: sizeWatcher(dimWatcher, "height", this.options.content.maxHeight)
310
+ };
311
+ const watches = {
312
+ dims: combineLatest(dimWatches),
313
+ size: combineLatest(sizeWatches)
314
+ };
315
+ return (combineLatest(watches)
316
+ // .pipe(distinctUntilChanged(isEqual))
317
+ .subscribe(({ dims, size }) => {
318
+ console.log(size);
319
+ const pos = floatingPosition({ dims, options: this.options });
320
+ const floatingEl = floatingRef.container.nativeElement;
321
+ Object.assign(floatingEl.style, floatingPositionToStyle(pos));
322
+ Object.assign(floatingEl.style, sizesToStyle(pos, size));
323
+ dest.next(pos);
324
+ }));
415
325
  }).pipe(takeUntil(floatingRef.state.onExecute("disposing")));
416
326
  }
417
327
  }
@@ -426,39 +336,30 @@ function refWatcher(rectWatcher, ref, floatingRef) {
426
336
  return rectWatcher.watch(ref, "border-box");
427
337
  }
428
338
  }
429
- function position(options) {
430
- return [new PositionTrait(options), maxWidth(NaN), maxHeight(NaN)];
431
- }
432
- class FloatingPosition {
433
- constructor(options, floating, anchor, placement) {
434
- this.options = options;
435
- this.floating = floating;
436
- this.anchor = anchor;
437
- this.placement = placement;
438
- // const frect: Rect = { x: 0, y: 0, ...floating }
439
- this.computed = computePosition({ floating, anchor, placement, options });
440
- }
441
- apply(floatingRef) {
442
- if (this.computed == null) {
443
- return;
444
- }
445
- const floatingEl = floatingRef.container.nativeElement;
446
- const computedContent = this.computed.content;
447
- const style = { top: null, right: null, bottom: null, left: null };
448
- if (computedContent.align.horizontal === "right") {
449
- style["right"] = `${computedContent.right}px`;
450
- }
451
- else {
452
- style["left"] = `${computedContent.left}px`;
453
- }
454
- if (computedContent.align.vertical === "bottom") {
455
- style["bottom"] = `${computedContent.bottom}px`;
456
- }
457
- else {
458
- style["top"] = `${computedContent.top}px`;
459
- }
460
- Object.assign(floatingEl.style, style);
339
+ function sizeWatcher(dimWatcher, prop, size) {
340
+ if (typeof size === "number") {
341
+ return of(size);
342
+ }
343
+ else if (isElementInput(size)) {
344
+ return dimWatcher.watch(size, "border-box").pipe(map(value => value[prop]));
461
345
  }
346
+ else if (isObservable(size)) {
347
+ return size.pipe(switchMap(value => sizeWatcher(dimWatcher, prop, value)));
348
+ }
349
+ return of(NaN);
350
+ }
351
+ function sizesToStyle(pos, sizes) {
352
+ const { minWidth, maxWidth, minHeight, maxHeight } = sizes;
353
+ const { width, height } = pos.placement.area;
354
+ return {
355
+ minWidth: isNaN(minWidth) ? "auto" : `${Math.min(width, minWidth)}px`,
356
+ minHeight: isNaN(minHeight) ? "auto" : `${Math.min(height, minHeight)}px`,
357
+ maxWidth: isNaN(maxWidth) ? `${width}px` : `${Math.min(width, maxWidth)}px`,
358
+ maxHeight: isNaN(maxHeight) ? `${height}px` : `${Math.min(height, maxHeight)}px`
359
+ };
360
+ }
361
+ function position(options) {
362
+ return new PositionTrait(options);
462
363
  }
463
364
 
464
365
  function modal() {
@@ -466,7 +367,7 @@ function modal() {
466
367
  position({
467
368
  anchor: {
468
369
  ref: "viewport",
469
- align: "center middle"
370
+ link: "center middle"
470
371
  },
471
372
  placement: {
472
373
  ref: "viewport",
@@ -614,6 +515,7 @@ function createElement(options) {
614
515
  div.style.flexDirection = "column";
615
516
  div.style.alignItems = "stretch";
616
517
  div.style.justifyContent = "stretch";
518
+ div.style.boxSizing = "border-box";
617
519
  if (options.classes) {
618
520
  div.classList.add(...options.classes);
619
521
  }
@@ -1101,5 +1003,5 @@ function provideFloating(options = {}) {
1101
1003
  * Generated bundle index. Do not edit.
1102
1004
  */
1103
1005
 
1104
- export { AlwaysOnTop, AnimationTrait, AttributeTrait, BackdropRef, BackdropTrait, ChildRef, ComponentPortalRef, ContainerRef, DimensionConstraintTrait, DropAnimation, FadeAnimation, FallAnimation, FloatingAnchorRef, FloatingComponentFactory, FloatingFactory, FloatingPlacementRef, FloatingPosition, FloatingRef, FloatingService, FloatingTemplateFactory, FocusTrait, IndividualLayer, LAYER_CONTAINER_ZINDEX_START, LayerContainer, LayerService, PortalRef, PositionTrait, RootLayer, StyleTrait, TRAITS, TemplatePortalRef, attribute, backdrop, closeTrigger, computePosition, dropAnimation, fadeAnimation, fallAnimation, focus, maxHeight, maxWidth, minHeight, minWidth, modal, position, provideFloating, style };
1006
+ export { AlwaysOnTop, AnimationTrait, AttributeTrait, BackdropRef, BackdropTrait, ChildRef, ComponentPortalRef, ContainerRef, DropAnimation, FadeAnimation, FallAnimation, FloatingComponentFactory, FloatingFactory, FloatingRef, FloatingService, FloatingTemplateFactory, FocusTrait, IndividualLayer, LAYER_CONTAINER_ZINDEX_START, LayerContainer, LayerService, PortalRef, PositionTrait, RootLayer, StyleTrait, TRAITS, TemplatePortalRef, attribute, backdrop, closeTrigger, dropAnimation, fadeAnimation, fallAnimation, focus, modal, position, provideFloating, style };
1105
1007
  //# sourceMappingURL=ngutil-floating.mjs.map