ng-hub-ui-utils 22.11.1 → 22.12.1
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 +173 -25
- package/fesm2022/ng-hub-ui-utils.mjs +737 -4
- package/fesm2022/ng-hub-ui-utils.mjs.map +1 -1
- package/package.json +13 -9
- package/styles/tooltip.scss +10 -3
- package/types/ng-hub-ui-utils.d.ts +217 -2
package/README.md
CHANGED
|
@@ -116,8 +116,8 @@ export class ExampleComponent {
|
|
|
116
116
|
overlayY: 'top'
|
|
117
117
|
}]);
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
const
|
|
119
|
+
// Render a component (or a TemplateRef) into the overlay; you get the host element back
|
|
120
|
+
const overlayElement = overlayRef.attach(MyComponent);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
```
|
|
@@ -128,9 +128,11 @@ export class ExampleComponent {
|
|
|
128
128
|
this.overlayService.create({ zIndex: 1100 }); // OverlayConfig.zIndex: number | string — takes precedence over the token
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
### 🎯 Popup Service
|
|
131
|
+
### 🎯 Popup Service
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
`PopupService<T>` hosts a dynamically created popup component and runs its show/hide
|
|
134
|
+
transition. It is a concrete class — subclass it when the popup needs its own API, as
|
|
135
|
+
below, or provide it through a factory.
|
|
134
136
|
|
|
135
137
|
```typescript
|
|
136
138
|
import { PopupService } from 'ng-hub-ui-utils';
|
|
@@ -356,16 +358,17 @@ import { GetPipe, UcfirstPipe } from 'ng-hub-ui-utils';
|
|
|
356
358
|
|
|
357
359
|
### 🏷️ Tooltip Directive
|
|
358
360
|
|
|
359
|
-
Add a lightweight, themeable tooltip to any element with the `
|
|
360
|
-
The tooltip is appended to `<body>` (never clipped) and shows on
|
|
361
|
+
Add a lightweight, themeable tooltip to any element with the `HubTooltipDirective`
|
|
362
|
+
(`[hubTooltip]`). The tooltip is appended to `<body>` (never clipped) and shows on
|
|
363
|
+
hover/focus.
|
|
361
364
|
|
|
362
365
|
```typescript
|
|
363
|
-
import {
|
|
366
|
+
import { HubTooltipDirective } from 'ng-hub-ui-utils';
|
|
364
367
|
|
|
365
368
|
@Component({
|
|
366
369
|
standalone: true,
|
|
367
|
-
imports: [
|
|
368
|
-
template: `<button
|
|
370
|
+
imports: [HubTooltipDirective],
|
|
371
|
+
template: `<button hubTooltip="Save changes" hubTooltipPlacement="top">Save</button>`
|
|
369
372
|
})
|
|
370
373
|
export class ExampleComponent {}
|
|
371
374
|
```
|
|
@@ -378,8 +381,24 @@ export class ExampleComponent {}
|
|
|
378
381
|
> @use 'ng-hub-ui-utils/styles/tooltip';
|
|
379
382
|
> ```
|
|
380
383
|
|
|
381
|
-
Inputs: `
|
|
382
|
-
`
|
|
384
|
+
Inputs: `hubTooltip` (text), `hubTooltipPlacement` (`top` | `bottom` | `left` | `right`,
|
|
385
|
+
default `top`), `hubTooltipDelay` (fade ms, default `150`), `hubTooltipOffset` (px, default `8`).
|
|
386
|
+
|
|
387
|
+
> **`TooltipDirective` (`[tooltip]`) is deprecated since 22.9.0.** It still works,
|
|
388
|
+
> unchanged — both directives are thin shells over the same `HubTooltipController` — but its
|
|
389
|
+
> bare input names (`tooltip`, `placement`, `delay`, `offset`) belong to every directive on
|
|
390
|
+
> the element that declares them, which is how it collided with `[hubDropdown]`'s own
|
|
391
|
+
> `placement` and with the `tooltip` input of `<hub-badge>`. Migration is attribute for
|
|
392
|
+
> attribute: `tooltip` → `hubTooltip`, `placement` → `hubTooltipPlacement`,
|
|
393
|
+
> `delay` → `hubTooltipDelay`, `offset` → `hubTooltipOffset`.
|
|
394
|
+
|
|
395
|
+
Show the label **only while the host is truncated** with `HubOverflowTooltipDirective`
|
|
396
|
+
(`[hubOverflowTooltip]`), which tracks truncation live with a `ResizeObserver` and a
|
|
397
|
+
`MutationObserver` and resolves its tooltip through `HUB_TOOLTIP_ADAPTER`:
|
|
398
|
+
|
|
399
|
+
```html
|
|
400
|
+
<span class="label" [hubOverflowTooltip]="item.label">{{ item.label }}</span>
|
|
401
|
+
```
|
|
383
402
|
|
|
384
403
|
Theme it from any scope with `--hub-tooltip-*` variables:
|
|
385
404
|
|
|
@@ -394,8 +413,14 @@ Theme it from any scope with `--hub-tooltip-*` variables:
|
|
|
394
413
|
|
|
395
414
|
Available tokens: `--hub-tooltip-bg`, `--hub-tooltip-color`, `--hub-tooltip-opacity`,
|
|
396
415
|
`--hub-tooltip-padding-x`, `--hub-tooltip-padding-y`, `--hub-tooltip-border-radius`,
|
|
397
|
-
`--hub-tooltip-font-size`, `--hub-tooltip-
|
|
398
|
-
`--hub-tooltip-
|
|
416
|
+
`--hub-tooltip-font-size`, `--hub-tooltip-font-weight`, `--hub-tooltip-line-height`,
|
|
417
|
+
`--hub-tooltip-max-width`, `--hub-tooltip-zindex`, `--hub-tooltip-transition-duration`,
|
|
418
|
+
`--hub-tooltip-shadow`, `--hub-tooltip-font-family`, `--hub-tooltip-white-space`,
|
|
419
|
+
`--hub-tooltip-text-align`.
|
|
420
|
+
|
|
421
|
+
The last two arrived in 22.10.0, for the tooltip that carries a sentence rather than a
|
|
422
|
+
name: they are set on the **host**, which is the only element you can reach, because the
|
|
423
|
+
bubble itself lives on `<body>`, outside every component's styles.
|
|
399
424
|
|
|
400
425
|
#### Tooltip adapter for other libraries (`hubTooltipAdapter`)
|
|
401
426
|
|
|
@@ -414,10 +439,26 @@ providers: [
|
|
|
414
439
|
];
|
|
415
440
|
```
|
|
416
441
|
|
|
442
|
+
Inside this package the same token works the other way round: `[hubOverflowTooltip]`
|
|
443
|
+
resolves its tooltip through `HUB_TOOLTIP_ADAPTER`, which defaults to `hubTooltipAdapter`.
|
|
444
|
+
Swap it app-wide, or for one subtree, with `provideHubTooltip()`:
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
import { provideHubTooltip, HubTooltipAdapter } from 'ng-hub-ui-utils';
|
|
448
|
+
|
|
449
|
+
const myTooltip: HubTooltipAdapter = {
|
|
450
|
+
attach(host, text, options) {
|
|
451
|
+
/* … returns a HubTooltipHandle with update(text) and destroy() */
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
providers: [provideHubTooltip(myTooltip)];
|
|
456
|
+
```
|
|
457
|
+
|
|
417
458
|
Also available: the imperative `HubTooltipController` (engine) and the
|
|
418
|
-
`HubTooltipAdapter` / `HubTooltipHandle` / `HubTooltipOptions`
|
|
419
|
-
ecosystem-wide
|
|
420
|
-
section.
|
|
459
|
+
`HubTooltipAdapter` / `HubTooltipHandle` / `HubTooltipOptions` / `HubTooltipPlacement`
|
|
460
|
+
types. See the ecosystem-wide
|
|
461
|
+
[Synergies & agnosticism](../../README.md#synergies--agnosticism) section.
|
|
421
462
|
|
|
422
463
|
## 🚀 Installation
|
|
423
464
|
|
|
@@ -505,6 +546,20 @@ interface HubTranslationConfig {
|
|
|
505
546
|
|
|
506
547
|
The configuration is also exposed through the `HUB_TRANSLATION_CONFIG` injection token for advanced scenarios.
|
|
507
548
|
|
|
549
|
+
### `HUB_TRANSLATION_PREFIX`
|
|
550
|
+
|
|
551
|
+
Injection token that scopes a library's lookups to a collision-safe `HUBUI.<LIBRARY>.*`
|
|
552
|
+
namespace. `TranslatePipe` resolves the prefixed key first and falls back to the bare key,
|
|
553
|
+
so a flat dictionary that predates the token keeps working untouched.
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
providers: [{ provide: HUB_TRANSLATION_PREFIX, useValue: 'HUBUI.TABLE' }];
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
The adapter types are exported alongside it: `HubTranslationSource`,
|
|
560
|
+
`HubTranslationOverrides`, `HubTranslationAdapterConfig`, `HubTranslationAdapterFactory`
|
|
561
|
+
and the `HUB_TRANSLATION_SOURCE` token `provideHubTranslationAdapter()` registers.
|
|
562
|
+
|
|
508
563
|
### `HubTranslationService`
|
|
509
564
|
|
|
510
565
|
Injectable service that holds the active translations and notifies subscribers when they change.
|
|
@@ -584,6 +639,19 @@ These functions back the i18n system and are exported for direct use:
|
|
|
584
639
|
|
|
585
640
|
- `regExpEscape(text: string): string` - Escapes special characters for RegExp
|
|
586
641
|
- `removeAccents(str: string): string` - Removes accents from text
|
|
642
|
+
- `interpolateString(expr?: string, params?: any, templateMatcher?: RegExp): string` - Replaces `{{ token }}` placeholders
|
|
643
|
+
- `generateUniqueId(length: number): string` - Random alphanumeric id, for a DOM node that needs one
|
|
644
|
+
|
|
645
|
+
### Object Functions
|
|
646
|
+
|
|
647
|
+
- `equals(o1: any, o2: any): boolean` - Deep equality
|
|
648
|
+
- `getValue(target: any, key: string): any` - Reads a nested value by dot-notation key
|
|
649
|
+
- `isObject(item: any): boolean` - Whether the value is a non-array object
|
|
650
|
+
- `mergeDeep(target: any, source: any): any` - Recursive merge; the only deep object helper in the package
|
|
651
|
+
|
|
652
|
+
### Signal Utilities
|
|
653
|
+
|
|
654
|
+
- `debouncedSignal<T>(source: Signal<T>, delay?: number | Signal<number>): Signal<T>` - Mirrors a signal, delaying each change; the delay can itself be a signal
|
|
587
655
|
|
|
588
656
|
### DOM Functions
|
|
589
657
|
|
|
@@ -591,12 +659,61 @@ These functions back the i18n system and are exported for direct use:
|
|
|
591
659
|
- `reflow(element: HTMLElement): DOMRect` - Forces browser reflow
|
|
592
660
|
- `getActiveElement(root?: Document | ShadowRoot): Element | null` - Gets active element including Shadow DOM
|
|
593
661
|
|
|
662
|
+
### Accent Resolution
|
|
663
|
+
|
|
664
|
+
- `resolveHubAccent(value: string | null | undefined): string | null` - The "any colour" accent resolver shared across the family: a bareword becomes `var(--hub-sys-color-<name>, <name>)`, a literal `#hex` / `rgb()` / `oklch()` / `var()` passes through unchanged, and an empty value yields `null`
|
|
665
|
+
|
|
666
|
+
### Colour Functions
|
|
667
|
+
|
|
668
|
+
- `parseColor(value): HubRgb | null` - Parses hex (3/4/6/8), `rgb()`, `hsl()`, `oklch()`, `oklab()`, the 148 CSS named colours and `transparent`, in modern and legacy syntax. No DOM, so it runs under SSR. Returns `null` — never throws — for anything it cannot resolve, `var()` and `currentColor` included
|
|
669
|
+
- `toRgb(color): HubRgb | null` - Normalises a string or parsed colour to channels
|
|
670
|
+
- `toHex(color): string | null` - Renders as `#rrggbb`, or `#rrggbbaa` when translucent
|
|
671
|
+
- `isValidColor(value): boolean` - Whether the parser can resolve the string
|
|
672
|
+
- `HUB_NAMED_COLORS: Readonly<Record<string, string>>` - The 148 CSS named colours
|
|
673
|
+
|
|
674
|
+
### Contrast Functions
|
|
675
|
+
|
|
676
|
+
- `relativeLuminance(color): number | null` - WCAG 2 relative luminance, 0 to 1
|
|
677
|
+
- `contrastRatio(a, b): number | null` - WCAG 2 contrast ratio, 1 to 21
|
|
678
|
+
- `contrastAPCA(text, background): number | null` - APCA lightness contrast, polarity-aware
|
|
679
|
+
- `compositeOver(foreground, background): HubColor` - Blends translucent over opaque
|
|
680
|
+
- `readableOn(background, metric?): string` - Black or white, whichever reads better. Defaults to `'lightness'`, the same decision `--hub-sys-color-*-on` makes in CSS; `'apca'` and `'wcag'` are also available
|
|
681
|
+
- `HUB_INK_LIGHTNESS_THRESHOLD: number` - The OKLCh lightness above which a surface takes dark ink
|
|
682
|
+
|
|
683
|
+
### OKLCh Functions
|
|
684
|
+
|
|
685
|
+
- `rgbToOklch(color): HubOklch` / `oklchToRgb(color): HubRgb` - Conversions in the space the design system mixes in
|
|
686
|
+
- `maxSrgbChroma(l, h): number` - Highest in-gamut chroma for a hue at a lightness. The sRGB gamut is not a cylinder — at L 0.578 blue reaches 0.232 and amber only 0.119 — so a palette cannot give every hue the same absolute chroma
|
|
687
|
+
- `isInSrgbGamut(color): boolean` - Whether the colour survives the trip to sRGB
|
|
688
|
+
- `clampToSrgbGamut(color): HubOklch` - Reduces chroma until it fits, preserving lightness and hue
|
|
689
|
+
|
|
594
690
|
### Focus Functions
|
|
595
691
|
|
|
596
692
|
- `getFocusableBoundaryElements(element: HTMLElement): HTMLElement[]` - Gets first and last focusable elements
|
|
597
693
|
- `hubFocusTrap(zone, element, stopFocusTrap$, refocusOnClick?)` - Creates focus trap for modals/overlays
|
|
598
694
|
- `FOCUSABLE_ELEMENTS_SELECTOR: string` - CSS selector for focusable elements
|
|
599
695
|
|
|
696
|
+
### Drag and Drop
|
|
697
|
+
|
|
698
|
+
The engine-agnostic half of native HTML5 drag and drop, shared by the libraries that
|
|
699
|
+
implement it. The UI primitives — handle, placeholder and preview directives — stay in each
|
|
700
|
+
library, because their selectors and data models differ.
|
|
701
|
+
|
|
702
|
+
- `HubDragDropService` - Root-provided coordinator. A drag spans two component instances and the native `dataTransfer` payload is unreadable during `dragover`, so a shared service is the only reliable channel for what is being dragged and from where. Owners `register()` / `unregister()`; `begin()`, `setTarget()` and the readonly `active` / `target` / `isDragging` signals report the drag in progress. It coordinates state only — it never mutates your collections
|
|
703
|
+
- `moveItemInArray<T>(array, fromIndex, toIndex): void` / `transferArrayItem<T>(source, target, fromIndex, toIndex): void` / `copyArrayItem<T>(source, target, fromIndex, toIndex): void` - In-place array moves, mirroring the `@angular/cdk` helpers of the same names
|
|
704
|
+
- `clamp(value, max)`, `computeTargetIndex(...)`, `toAbsoluteIndex(...)`, `containsNode(...)` - Index arithmetic for sliced and nested lists
|
|
705
|
+
- `resolveDropPosition(...)` with `DropRect` and `DragAxis` - Where a pointer sits relative to an item: `'before'` or `'after'`, on a vertical, horizontal or grid axis
|
|
706
|
+
- `createNativeDragImage(...)` returning `DragImageResult` - Renders the drag preview the browser shows
|
|
707
|
+
- `createPointerDragSession(config: PointerDragSessionConfig): PointerDragSession` - Pointer Events fallback for touch, where native drag events are not delivered
|
|
708
|
+
- Types: `DropPosition`, `DragPointerMode`, `DragContainerRef<T>`, `ActiveDrag<T>`, `DragTarget<T>`, `DragRegistration`
|
|
709
|
+
|
|
710
|
+
### Directives
|
|
711
|
+
|
|
712
|
+
- `HubTooltipDirective` (`[hubTooltip]`) - Tooltip on hover/focus. Inputs: `hubTooltip`, `hubTooltipPlacement`, `hubTooltipDelay`, `hubTooltipOffset`
|
|
713
|
+
- `HubOverflowTooltipDirective` (`[hubOverflowTooltip]`) - Tooltip shown only while the host label is truncated. Inputs: `hubOverflowTooltip`, `placement`
|
|
714
|
+
- `TooltipDirective` (`[tooltip]`) - **Deprecated since 22.9.0**, kept working. Inputs: `tooltip`, `placement`, `delay`, `offset`
|
|
715
|
+
- `provideHubTooltip(adapter: HubTooltipAdapter)` and `HUB_TOOLTIP_ADAPTER` - Swap the implementation behind `[hubOverflowTooltip]`, app-wide or per subtree; defaults to `hubTooltipAdapter`
|
|
716
|
+
|
|
600
717
|
### Pipes
|
|
601
718
|
|
|
602
719
|
#### GetPipe
|
|
@@ -657,18 +774,37 @@ class OverlayService {
|
|
|
657
774
|
}
|
|
658
775
|
|
|
659
776
|
class OverlayRef {
|
|
660
|
-
|
|
777
|
+
// Renders a template or a component into the overlay and returns the host element,
|
|
778
|
+
// not a ComponentRef: the overlay owns the view it created and tears it down itself.
|
|
779
|
+
attach(content: TemplateRef<unknown> | Type<unknown>, viewContainerRef?: ViewContainerRef): HTMLElement;
|
|
661
780
|
detach(): void;
|
|
662
781
|
dispose(): void;
|
|
782
|
+
hasAttached(): boolean;
|
|
663
783
|
updatePosition(): void;
|
|
784
|
+
onBackdropClick(callback: () => void): void;
|
|
785
|
+
// Only the topmost open overlay is told, so a dropdown inside a dialog takes Escape
|
|
786
|
+
// for itself and leaves the dialog open.
|
|
787
|
+
onKeydown(callback: (event: KeyboardEvent) => void): void;
|
|
664
788
|
}
|
|
665
789
|
|
|
666
790
|
class OverlayPosition {
|
|
667
|
-
flexibleConnectedTo(
|
|
791
|
+
flexibleConnectedTo(origin: ElementRef | HTMLElement): this;
|
|
668
792
|
withPositions(positions: ConnectionPosition[]): this;
|
|
793
|
+
// `start` / `end` are logical and read from the origin element; this overrides that.
|
|
794
|
+
withDirection(direction: 'ltr' | 'rtl' | null): this;
|
|
669
795
|
}
|
|
670
796
|
```
|
|
671
797
|
|
|
798
|
+
`HUB_DROPDOWN_POSITIONS` is the ready-made fallback chain for a dropdown — below the
|
|
799
|
+
origin, flipping above when there is no room — expressed logically so one list serves
|
|
800
|
+
both text directions:
|
|
801
|
+
|
|
802
|
+
```typescript
|
|
803
|
+
import { HUB_DROPDOWN_POSITIONS } from 'ng-hub-ui-utils';
|
|
804
|
+
|
|
805
|
+
overlayService.position().flexibleConnectedTo(origin).withPositions([...HUB_DROPDOWN_POSITIONS]);
|
|
806
|
+
```
|
|
807
|
+
|
|
672
808
|
#### ScrollBar Service
|
|
673
809
|
|
|
674
810
|
```typescript
|
|
@@ -678,14 +814,26 @@ class ScrollBar {
|
|
|
678
814
|
}
|
|
679
815
|
```
|
|
680
816
|
|
|
681
|
-
#### PopupService
|
|
817
|
+
#### PopupService<T>
|
|
818
|
+
|
|
819
|
+
A concrete generic class, not an abstract one: it takes the popup component type in its
|
|
820
|
+
constructor, and it reads its collaborators with `inject()`, so it has to be created inside
|
|
821
|
+
an injection context — as an `@Injectable()` subclass, or from a factory provider.
|
|
682
822
|
|
|
683
823
|
```typescript
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
824
|
+
class PopupService<T> {
|
|
825
|
+
constructor(componentType: Type<T>);
|
|
826
|
+
open(
|
|
827
|
+
content?: string | TemplateRef<any>,
|
|
828
|
+
templateContext?: any,
|
|
829
|
+
animation?: boolean
|
|
830
|
+
): { windowRef: ComponentRef<T>; transition$: Observable<void> };
|
|
831
|
+
close(animation?: boolean): Observable<void>;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// The nodes and view a popup projects, returned internally by the content resolver.
|
|
835
|
+
class ContentRef {
|
|
836
|
+
constructor(nodes: Node[][], viewRef?: ViewRef, componentRef?: ComponentRef<any>);
|
|
689
837
|
}
|
|
690
838
|
```
|
|
691
839
|
|
|
@@ -705,7 +853,7 @@ This library doesn't include visual components, but support utilities used by ot
|
|
|
705
853
|
| Overlay Service | Flexible overlay positioning system | ng-hub-ui-modal, ng-hub-ui-portal |
|
|
706
854
|
| Focus Trap | Focus management in modals/overlays | ng-hub-ui-modal, ng-hub-ui-portal |
|
|
707
855
|
| Scrollbar | Scrollbar compensation | ng-hub-ui-modal, ng-hub-ui-portal |
|
|
708
|
-
| Popup Service |
|
|
856
|
+
| Popup Service | Host for dynamically created popups | ng-hub-ui-modal, ng-hub-ui-portal |
|
|
709
857
|
| Transitions | Smooth animations | ng-hub-ui-accordion, ng-hub-ui-modal |
|
|
710
858
|
| Type Guards | Type validation functions | ng-hub-ui-stepper |
|
|
711
859
|
| Pipes | Template utilities | All Hub UI components |
|