ng-primitives 0.52.0 → 0.54.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/fesm2022/ng-primitives-focus-trap.mjs +4 -2
- package/fesm2022/ng-primitives-focus-trap.mjs.map +1 -1
- package/fesm2022/ng-primitives-form-field.mjs +5 -3
- package/fesm2022/ng-primitives-form-field.mjs.map +1 -1
- package/fesm2022/ng-primitives-input.mjs +4 -3
- package/fesm2022/ng-primitives-input.mjs.map +1 -1
- package/fesm2022/ng-primitives-internal.mjs +4 -5
- package/fesm2022/ng-primitives-internal.mjs.map +1 -1
- package/fesm2022/ng-primitives-listbox.mjs +2 -3
- package/fesm2022/ng-primitives-listbox.mjs.map +1 -1
- package/fesm2022/ng-primitives-menu.mjs +3 -3
- package/fesm2022/ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/ng-primitives-popover.mjs +1 -1
- package/fesm2022/ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/ng-primitives-portal.mjs +5 -6
- package/fesm2022/ng-primitives-portal.mjs.map +1 -1
- package/fesm2022/ng-primitives-resize.mjs +2 -2
- package/fesm2022/ng-primitives-resize.mjs.map +1 -1
- package/fesm2022/ng-primitives-search.mjs +2 -2
- package/fesm2022/ng-primitives-search.mjs.map +1 -1
- package/fesm2022/ng-primitives-tooltip.mjs +1 -1
- package/fesm2022/ng-primitives-tooltip.mjs.map +1 -1
- package/fesm2022/ng-primitives-utils.mjs +51 -13
- package/fesm2022/ng-primitives-utils.mjs.map +1 -1
- package/form-field/form-control/form-control.d.ts +2 -1
- package/input/input/input.d.ts +6 -0
- package/package.json +1 -1
- package/portal/overlay-token.d.ts +3 -3
- package/portal/overlay.d.ts +3 -3
- package/schematics/ng-generate/templates/popover/popover.__fileSuffix@dasherize__.ts.template +1 -1
- package/schematics/ng-generate/templates/tooltip/tooltip.__fileSuffix@dasherize__.ts.template +1 -1
- package/utils/index.d.ts +1 -0
- package/utils/observables/take-until-destroyed.d.ts +10 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
2
|
-
import { inject, signal,
|
|
2
|
+
import { inject, DestroyRef, signal, afterNextRender, effect, untracked, Renderer2, ElementRef } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { pipe, NEVER, EMPTY } from 'rxjs';
|
|
5
|
+
import { takeUntil, catchError, defaultIfEmpty } from 'rxjs/operators';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* A simple helper function to provide a value accessor for a given type.
|
|
@@ -10,6 +12,39 @@ function provideValueAccessor(type) {
|
|
|
10
12
|
return { provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true };
|
|
11
13
|
}
|
|
12
14
|
|
|
15
|
+
/**
|
|
16
|
+
* The built-in `takeUntilDestroyed` operator does not handle the case when the component is destroyed before the source observable emits.
|
|
17
|
+
* This operator ensures that the source observable completes gracefully without throwing an error.
|
|
18
|
+
* https://github.com/angular/angular/issues/54527#issuecomment-2098254508
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
function safeTakeUntilDestroyed(destroyRef) {
|
|
23
|
+
return pipe(takeUntil(NEVER.pipe(takeUntilDestroyed(destroyRef), catchError(() => EMPTY), defaultIfEmpty(null))));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function setStatusSignal(control, status) {
|
|
27
|
+
if (!control?.control) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
status.set({
|
|
31
|
+
valid: control?.control?.valid ?? null,
|
|
32
|
+
invalid: control?.control?.invalid ?? null,
|
|
33
|
+
pristine: control?.control?.pristine ?? null,
|
|
34
|
+
dirty: control?.control?.dirty ?? null,
|
|
35
|
+
touched: control?.control?.touched ?? null,
|
|
36
|
+
pending: control?.control?.pending ?? null,
|
|
37
|
+
disabled: control?.control?.disabled ?? null,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function subscribeToControlStatus(control, status, destroyRef) {
|
|
41
|
+
if (!control?.control) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
control.control.events
|
|
45
|
+
.pipe(safeTakeUntilDestroyed(destroyRef))
|
|
46
|
+
.subscribe(() => setStatusSignal(control, status));
|
|
47
|
+
}
|
|
13
48
|
/**
|
|
14
49
|
* A utility function to get the status of an Angular form control as a reactive signal.
|
|
15
50
|
* This function injects the NgControl and returns a signal that reflects the control's status.
|
|
@@ -17,6 +52,7 @@ function provideValueAccessor(type) {
|
|
|
17
52
|
*/
|
|
18
53
|
function controlStatus() {
|
|
19
54
|
const control = inject(NgControl, { optional: true });
|
|
55
|
+
const destroyRef = inject(DestroyRef);
|
|
20
56
|
const status = signal({
|
|
21
57
|
valid: null,
|
|
22
58
|
invalid: null,
|
|
@@ -28,19 +64,21 @@ function controlStatus() {
|
|
|
28
64
|
});
|
|
29
65
|
// Fallback if control is not yet available
|
|
30
66
|
if (!control?.control) {
|
|
67
|
+
// There is still a chance that the control will be available i.e. after executing OnInit lifecycle hook
|
|
68
|
+
// in `formControlName` directive, so we set up an effect to subscribe to the control status
|
|
69
|
+
afterNextRender({
|
|
70
|
+
write: () => {
|
|
71
|
+
// If control is still not available, we do nothing, otherwise we subscribe to the control status
|
|
72
|
+
if (control?.control) {
|
|
73
|
+
subscribeToControlStatus(control, status, destroyRef);
|
|
74
|
+
// We re-set the status to ensure it reflects the current state on initialization
|
|
75
|
+
setStatusSignal(control, status);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
});
|
|
31
79
|
return status;
|
|
32
80
|
}
|
|
33
|
-
control
|
|
34
|
-
status.set({
|
|
35
|
-
valid: control?.control?.valid ?? null,
|
|
36
|
-
invalid: control?.control?.invalid ?? null,
|
|
37
|
-
pristine: control?.control?.pristine ?? null,
|
|
38
|
-
dirty: control?.control?.dirty ?? null,
|
|
39
|
-
touched: control?.control?.touched ?? null,
|
|
40
|
-
pending: control?.control?.pending ?? null,
|
|
41
|
-
disabled: control?.control?.disabled ?? null,
|
|
42
|
-
});
|
|
43
|
-
});
|
|
81
|
+
subscribeToControlStatus(control, status);
|
|
44
82
|
return status;
|
|
45
83
|
}
|
|
46
84
|
|
|
@@ -212,5 +250,5 @@ function injectDimensions() {
|
|
|
212
250
|
* Generated bundle index. Do not edit.
|
|
213
251
|
*/
|
|
214
252
|
|
|
215
|
-
export { controlStatus, injectDimensions, injectDisposables, onBooleanChange, onChange, provideValueAccessor, uniqueId };
|
|
253
|
+
export { controlStatus, injectDimensions, injectDisposables, onBooleanChange, onChange, provideValueAccessor, safeTakeUntilDestroyed, uniqueId };
|
|
216
254
|
//# sourceMappingURL=ng-primitives-utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-primitives-utils.mjs","sources":["../../../../packages/ng-primitives/utils/src/forms/providers.ts","../../../../packages/ng-primitives/utils/src/forms/status.ts","../../../../packages/ng-primitives/utils/src/helpers/disposables.ts","../../../../packages/ng-primitives/utils/src/helpers/unique-id.ts","../../../../packages/ng-primitives/utils/src/signals/index.ts","../../../../packages/ng-primitives/utils/src/ui/dimensions.ts","../../../../packages/ng-primitives/utils/src/ng-primitives-utils.ts"],"sourcesContent":["import { ExistingProvider, Type } from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * A simple helper function to provide a value accessor for a given type.\n * @param type The type to provide the value accessor for\n */\nexport function provideValueAccessor<T>(type: Type<T>): ExistingProvider {\n return { provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true };\n}\n","import { Signal, inject, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgControl } from '@angular/forms';\n\nexport interface NgpControlStatus {\n valid: boolean | null;\n invalid: boolean | null;\n pristine: boolean | null;\n dirty: boolean | null;\n touched: boolean | null;\n pending: boolean | null;\n disabled: boolean | null;\n}\n\n/**\n * A utility function to get the status of an Angular form control as a reactive signal.\n * This function injects the NgControl and returns a signal that reflects the control's status.\n * @internal\n */\nexport function controlStatus(): Signal<NgpControlStatus> {\n const control = inject(NgControl, { optional: true });\n\n const status = signal<NgpControlStatus>({\n valid: null,\n invalid: null,\n pristine: null,\n dirty: null,\n touched: null,\n pending: null,\n disabled: null,\n });\n\n // Fallback if control is not yet available\n if (!control?.control) {\n return status;\n }\n\n control.control.statusChanges.pipe(takeUntilDestroyed()).subscribe(() => {\n status.set({\n valid: control?.control?.valid ?? null,\n invalid: control?.control?.invalid ?? null,\n pristine: control?.control?.pristine ?? null,\n dirty: control?.control?.dirty ?? null,\n touched: control?.control?.touched ?? null,\n pending: control?.control?.pending ?? null,\n disabled: control?.control?.disabled ?? null,\n });\n });\n\n return status;\n}\n","import { DestroyRef, inject } from '@angular/core';\n\n/**\n * Disposable functions are a way to manage timers, intervals, and event listeners\n * that should be cleared when a component is destroyed.\n *\n * This is heavily inspired by Headless UI disposables:\n * https://github.com/tailwindlabs/headlessui/blob/main/packages/%40headlessui-react/src/utils/disposables.ts\n */\nexport function injectDisposables() {\n const destroyRef = inject(DestroyRef);\n let isDestroyed = false;\n\n destroyRef.onDestroy(() => (isDestroyed = true));\n\n return {\n /**\n * Set a timeout that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the timeout\n */\n setTimeout: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setTimeout(callback, delay);\n const cleanup = () => clearTimeout(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @param target\n * @param type\n * @param listener\n * @param options\n * @returns A function to clear the interval\n */\n addEventListener: <K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n target.addEventListener(type, listener as EventListenerOrEventListenerObject, options);\n const cleanup = () =>\n target.removeEventListener(type, listener as EventListenerOrEventListenerObject, options);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the interval\n */\n setInterval: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setInterval(callback, delay);\n const cleanup = () => clearInterval(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set a requestAnimationFrame that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @returns A function to clear the requestAnimationFrame\n */\n requestAnimationFrame: (callback: FrameRequestCallback) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = requestAnimationFrame(callback);\n const cleanup = () => cancelAnimationFrame(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n };\n}\n","/**\n * Store a map of unique ids for elements so that there are no collisions.\n */\nconst uniqueIdMap = new Map<string, number>();\n\n/**\n * Generate a unique id for an element\n * @param prefix - The prefix to use for the id\n * @returns The generated id\n */\nexport function uniqueId(prefix: string): string {\n const id = uniqueIdMap.get(prefix) ?? 0;\n uniqueIdMap.set(prefix, id + 1);\n return `${prefix}-${id}`;\n}\n","import { effect, Injector, Signal, signal, untracked } from '@angular/core';\n\n/**\n * Listen for changes to a signal and call a function when the signal changes.\n * @param source\n * @param fn\n * @param options\n * @param options.injector\n * @internal\n */\nexport function onChange<T>(\n source: Signal<T | null | undefined>,\n fn: (value: T | null | undefined, previousValue: T | null | undefined) => void,\n options?: { injector: Injector },\n): void {\n const previousValue = signal(source());\n\n effect(\n () => {\n const value = source();\n if (value !== previousValue()) {\n untracked(() => fn(value, previousValue()));\n previousValue.set(value);\n }\n },\n { injector: options?.injector },\n );\n\n // call the fn with the initial value\n fn(source(), null);\n}\n\n/**\n * Listen for changes to a boolean signal and call one of two functions when the signal changes.\n * @param source\n * @param onTrue\n * @param onFalse\n * @param options\n */\nexport function onBooleanChange(\n source: Signal<boolean>,\n onTrue?: () => void,\n onFalse?: () => void,\n options?: { injector: Injector },\n): void {\n onChange(source, value => (value ? onTrue?.() : onFalse?.()), options);\n}\n","import { ElementRef, Renderer2, afterNextRender, inject, signal } from '@angular/core';\n\n/**\n * Injects the dimensions of the element\n * @returns The dimensions of the element\n */\nexport function injectDimensions() {\n const renderer = inject(Renderer2);\n const element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const size = signal<{ width: number; height: number; mounted: boolean }>({\n width: 0,\n height: 0,\n mounted: false,\n });\n let transitionDuration: string | undefined, animationName: string | undefined;\n\n afterNextRender({\n earlyRead: () => {\n transitionDuration = element.style.transitionDuration;\n animationName = element.style.animationName;\n },\n write: () => {\n // block any animations/transitions so the element renders at its full dimensions\n renderer.setStyle(element, 'transitionDuration', '0s');\n renderer.setStyle(element, 'animationName', 'none');\n },\n read: () => {\n const { width, height } = element.getBoundingClientRect();\n size.set({ width, height, mounted: true });\n // restore the original transition duration and animation name\n renderer.setStyle(element, 'transitionDuration', transitionDuration);\n renderer.setStyle(element, 'animationName', animationName);\n },\n });\n\n return size;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ng-primitives-utils.mjs","sources":["../../../../packages/ng-primitives/utils/src/forms/providers.ts","../../../../packages/ng-primitives/utils/src/observables/take-until-destroyed.ts","../../../../packages/ng-primitives/utils/src/forms/status.ts","../../../../packages/ng-primitives/utils/src/helpers/disposables.ts","../../../../packages/ng-primitives/utils/src/helpers/unique-id.ts","../../../../packages/ng-primitives/utils/src/signals/index.ts","../../../../packages/ng-primitives/utils/src/ui/dimensions.ts","../../../../packages/ng-primitives/utils/src/ng-primitives-utils.ts"],"sourcesContent":["import { ExistingProvider, Type } from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * A simple helper function to provide a value accessor for a given type.\n * @param type The type to provide the value accessor for\n */\nexport function provideValueAccessor<T>(type: Type<T>): ExistingProvider {\n return { provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true };\n}\n","/* eslint-disable @nx/workspace-take-until-destroyed */\nimport { DestroyRef } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { EMPTY, MonoTypeOperatorFunction, NEVER, pipe } from 'rxjs';\nimport { catchError, defaultIfEmpty, takeUntil } from 'rxjs/operators';\n\n/**\n * The built-in `takeUntilDestroyed` operator does not handle the case when the component is destroyed before the source observable emits.\n * This operator ensures that the source observable completes gracefully without throwing an error.\n * https://github.com/angular/angular/issues/54527#issuecomment-2098254508\n *\n * @internal\n */\nexport function safeTakeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperatorFunction<T> {\n return pipe(\n takeUntil(\n NEVER.pipe(\n takeUntilDestroyed(destroyRef),\n catchError(() => EMPTY),\n defaultIfEmpty(null),\n ),\n ),\n );\n}\n","import { DestroyRef, Signal, WritableSignal, afterNextRender, inject, signal } from '@angular/core';\nimport { NgControl } from '@angular/forms';\nimport { safeTakeUntilDestroyed } from '../observables/take-until-destroyed';\n\nexport interface NgpControlStatus {\n valid: boolean | null;\n invalid: boolean | null;\n pristine: boolean | null;\n dirty: boolean | null;\n touched: boolean | null;\n pending: boolean | null;\n disabled: boolean | null;\n}\n\nfunction setStatusSignal(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n): void {\n if (!control?.control) {\n return;\n }\n\n status.set({\n valid: control?.control?.valid ?? null,\n invalid: control?.control?.invalid ?? null,\n pristine: control?.control?.pristine ?? null,\n dirty: control?.control?.dirty ?? null,\n touched: control?.control?.touched ?? null,\n pending: control?.control?.pending ?? null,\n disabled: control?.control?.disabled ?? null,\n });\n}\n\nfunction subscribeToControlStatus(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n destroyRef?: DestroyRef,\n): void {\n if (!control?.control) {\n return;\n }\n\n control.control.events\n .pipe(safeTakeUntilDestroyed(destroyRef))\n .subscribe(() => setStatusSignal(control, status));\n}\n\n/**\n * A utility function to get the status of an Angular form control as a reactive signal.\n * This function injects the NgControl and returns a signal that reflects the control's status.\n * @internal\n */\nexport function controlStatus(): Signal<NgpControlStatus> {\n const control = inject(NgControl, { optional: true });\n const destroyRef = inject(DestroyRef);\n\n const status = signal<NgpControlStatus>({\n valid: null,\n invalid: null,\n pristine: null,\n dirty: null,\n touched: null,\n pending: null,\n disabled: null,\n });\n\n // Fallback if control is not yet available\n if (!control?.control) {\n // There is still a chance that the control will be available i.e. after executing OnInit lifecycle hook\n // in `formControlName` directive, so we set up an effect to subscribe to the control status\n afterNextRender({\n write: () => {\n // If control is still not available, we do nothing, otherwise we subscribe to the control status\n if (control?.control) {\n subscribeToControlStatus(control, status, destroyRef);\n // We re-set the status to ensure it reflects the current state on initialization\n setStatusSignal(control, status);\n }\n },\n });\n return status;\n }\n\n subscribeToControlStatus(control, status);\n\n return status;\n}\n","import { DestroyRef, inject } from '@angular/core';\n\n/**\n * Disposable functions are a way to manage timers, intervals, and event listeners\n * that should be cleared when a component is destroyed.\n *\n * This is heavily inspired by Headless UI disposables:\n * https://github.com/tailwindlabs/headlessui/blob/main/packages/%40headlessui-react/src/utils/disposables.ts\n */\nexport function injectDisposables() {\n const destroyRef = inject(DestroyRef);\n let isDestroyed = false;\n\n destroyRef.onDestroy(() => (isDestroyed = true));\n\n return {\n /**\n * Set a timeout that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the timeout\n */\n setTimeout: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setTimeout(callback, delay);\n const cleanup = () => clearTimeout(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @param target\n * @param type\n * @param listener\n * @param options\n * @returns A function to clear the interval\n */\n addEventListener: <K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n target.addEventListener(type, listener as EventListenerOrEventListenerObject, options);\n const cleanup = () =>\n target.removeEventListener(type, listener as EventListenerOrEventListenerObject, options);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the interval\n */\n setInterval: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setInterval(callback, delay);\n const cleanup = () => clearInterval(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set a requestAnimationFrame that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @returns A function to clear the requestAnimationFrame\n */\n requestAnimationFrame: (callback: FrameRequestCallback) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = requestAnimationFrame(callback);\n const cleanup = () => cancelAnimationFrame(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n };\n}\n","/**\n * Store a map of unique ids for elements so that there are no collisions.\n */\nconst uniqueIdMap = new Map<string, number>();\n\n/**\n * Generate a unique id for an element\n * @param prefix - The prefix to use for the id\n * @returns The generated id\n */\nexport function uniqueId(prefix: string): string {\n const id = uniqueIdMap.get(prefix) ?? 0;\n uniqueIdMap.set(prefix, id + 1);\n return `${prefix}-${id}`;\n}\n","import { effect, Injector, Signal, signal, untracked } from '@angular/core';\n\n/**\n * Listen for changes to a signal and call a function when the signal changes.\n * @param source\n * @param fn\n * @param options\n * @param options.injector\n * @internal\n */\nexport function onChange<T>(\n source: Signal<T | null | undefined>,\n fn: (value: T | null | undefined, previousValue: T | null | undefined) => void,\n options?: { injector: Injector },\n): void {\n const previousValue = signal(source());\n\n effect(\n () => {\n const value = source();\n if (value !== previousValue()) {\n untracked(() => fn(value, previousValue()));\n previousValue.set(value);\n }\n },\n { injector: options?.injector },\n );\n\n // call the fn with the initial value\n fn(source(), null);\n}\n\n/**\n * Listen for changes to a boolean signal and call one of two functions when the signal changes.\n * @param source\n * @param onTrue\n * @param onFalse\n * @param options\n */\nexport function onBooleanChange(\n source: Signal<boolean>,\n onTrue?: () => void,\n onFalse?: () => void,\n options?: { injector: Injector },\n): void {\n onChange(source, value => (value ? onTrue?.() : onFalse?.()), options);\n}\n","import { ElementRef, Renderer2, afterNextRender, inject, signal } from '@angular/core';\n\n/**\n * Injects the dimensions of the element\n * @returns The dimensions of the element\n */\nexport function injectDimensions() {\n const renderer = inject(Renderer2);\n const element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const size = signal<{ width: number; height: number; mounted: boolean }>({\n width: 0,\n height: 0,\n mounted: false,\n });\n let transitionDuration: string | undefined, animationName: string | undefined;\n\n afterNextRender({\n earlyRead: () => {\n transitionDuration = element.style.transitionDuration;\n animationName = element.style.animationName;\n },\n write: () => {\n // block any animations/transitions so the element renders at its full dimensions\n renderer.setStyle(element, 'transitionDuration', '0s');\n renderer.setStyle(element, 'animationName', 'none');\n },\n read: () => {\n const { width, height } = element.getBoundingClientRect();\n size.set({ width, height, mounted: true });\n // restore the original transition duration and animation name\n renderer.setStyle(element, 'transitionDuration', transitionDuration);\n renderer.setStyle(element, 'animationName', animationName);\n },\n });\n\n return size;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BooleanInput } from '@angular/cdk/coercion';
|
|
2
2
|
import { Signal } from '@angular/core';
|
|
3
|
+
import { NgpControlStatus } from 'ng-primitives/utils';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
/**
|
|
5
6
|
* Typically this primitive would be not be used directly, but instead a more specific form control primitive would be used (e.g. `ngpInput`). All of our form control primitives use `ngpFormControl` internally so they will have the same accessibility features as described below.
|
|
@@ -27,5 +28,5 @@ interface FormControlState {
|
|
|
27
28
|
id: Signal<string>;
|
|
28
29
|
disabled?: Signal<boolean>;
|
|
29
30
|
}
|
|
30
|
-
export declare function setupFormControl({ id, disabled }: FormControlState):
|
|
31
|
+
export declare function setupFormControl({ id, disabled, }: FormControlState): Signal<NgpControlStatus>;
|
|
31
32
|
export {};
|
package/input/input/input.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { BooleanInput } from '@angular/cdk/coercion';
|
|
2
|
+
import { Signal } from '@angular/core';
|
|
3
|
+
import { NgpControlStatus } from 'ng-primitives/utils';
|
|
2
4
|
import * as i0 from "@angular/core";
|
|
3
5
|
import * as i1 from "ng-primitives/autofill";
|
|
4
6
|
export declare class NgpInput {
|
|
@@ -18,6 +20,10 @@ export declare class NgpInput {
|
|
|
18
20
|
* Whether the element is disabled.
|
|
19
21
|
*/
|
|
20
22
|
readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
|
|
23
|
+
/**
|
|
24
|
+
* The form control status.
|
|
25
|
+
*/
|
|
26
|
+
protected readonly status: Signal<NgpControlStatus>;
|
|
21
27
|
/**
|
|
22
28
|
* The input state.
|
|
23
29
|
*/
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "ng-primitives",
|
|
3
3
|
"description": "Angular Primitives is a low-level headless UI component library with a focus on accessibility, customization, and developer experience. ",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.54.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"angular",
|
|
8
8
|
"primitives",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ValueProvider } from '@angular/core';
|
|
1
|
+
import { Signal, ValueProvider } from '@angular/core';
|
|
2
2
|
/**
|
|
3
3
|
* Injects the context for the overlay.
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
|
-
export declare function injectOverlayContext<T>(): T
|
|
6
|
+
export declare function injectOverlayContext<T>(): Signal<T>;
|
|
7
7
|
/**
|
|
8
8
|
* Provides the context for the overlay.
|
|
9
9
|
* @param value The value to provide as the context.
|
|
10
10
|
* @internal
|
|
11
11
|
*/
|
|
12
|
-
export declare function provideOverlayContext<T>(value: T): ValueProvider;
|
|
12
|
+
export declare function provideOverlayContext<T>(value: Signal<T | undefined> | undefined): ValueProvider;
|
package/portal/overlay.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FocusOrigin } from '@angular/cdk/a11y';
|
|
2
|
-
import { Injector, Provider, TemplateRef, Type, ViewContainerRef } from '@angular/core';
|
|
2
|
+
import { Injector, Provider, Signal, TemplateRef, Type, ViewContainerRef } from '@angular/core';
|
|
3
3
|
import { Middleware, Placement, Strategy } from '@floating-ui/dom';
|
|
4
4
|
import { Subject } from 'rxjs';
|
|
5
5
|
/**
|
|
@@ -16,7 +16,7 @@ export interface NgpOverlayConfig<T = unknown> {
|
|
|
16
16
|
/** ViewContainerRef to use for creating the portal */
|
|
17
17
|
viewContainerRef: ViewContainerRef;
|
|
18
18
|
/** Context data to pass to the overlay content */
|
|
19
|
-
context?: T |
|
|
19
|
+
context?: Signal<T | undefined>;
|
|
20
20
|
/** Container element to attach the overlay to (defaults to document.body) */
|
|
21
21
|
container?: HTMLElement | null;
|
|
22
22
|
/** Preferred placement of the overlay relative to the trigger */
|
|
@@ -76,7 +76,7 @@ export declare class NgpOverlay<T = unknown> {
|
|
|
76
76
|
* Determine if the overlay has been positioned
|
|
77
77
|
* @internal
|
|
78
78
|
*/
|
|
79
|
-
readonly isPositioned:
|
|
79
|
+
readonly isPositioned: Signal<boolean>;
|
|
80
80
|
/** Signal tracking the trigger element width */
|
|
81
81
|
readonly triggerWidth: import("@angular/core").WritableSignal<number | null>;
|
|
82
82
|
/** The transform origin for the overlay */
|
package/schematics/ng-generate/templates/popover/popover.__fileSuffix@dasherize__.ts.template
CHANGED
|
@@ -5,7 +5,7 @@ import { injectPopoverContext, NgpPopover } from 'ng-primitives/popover';
|
|
|
5
5
|
selector: '<%= prefix %>-popover',
|
|
6
6
|
hostDirectives: [NgpPopover],
|
|
7
7
|
template: `
|
|
8
|
-
{{ content }}
|
|
8
|
+
{{ content() }}
|
|
9
9
|
`,
|
|
10
10
|
styles: `
|
|
11
11
|
/* These styles rely on CSS variables that can be imported from ng-primitives/example-theme/index.css in your global styles */
|
package/schematics/ng-generate/templates/tooltip/tooltip.__fileSuffix@dasherize__.ts.template
CHANGED
|
@@ -5,7 +5,7 @@ import { injectTooltipContext, NgpTooltip } from 'ng-primitives/tooltip';
|
|
|
5
5
|
selector: '<%= prefix %>-tooltip',
|
|
6
6
|
hostDirectives: [NgpTooltip],
|
|
7
7
|
template: `
|
|
8
|
-
{{ content }}
|
|
8
|
+
{{ content() }}
|
|
9
9
|
`,
|
|
10
10
|
styles: `
|
|
11
11
|
/* These styles rely on CSS variables that can be imported from ng-primitives/example-theme/index.css in your global styles */
|
package/utils/index.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export { injectDisposables } from './helpers/disposables';
|
|
|
5
5
|
export { uniqueId } from './helpers/unique-id';
|
|
6
6
|
export { onBooleanChange, onChange } from './signals';
|
|
7
7
|
export { injectDimensions } from './ui/dimensions';
|
|
8
|
+
export { safeTakeUntilDestroyed } from './observables/take-until-destroyed';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DestroyRef } from '@angular/core';
|
|
2
|
+
import { MonoTypeOperatorFunction } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* The built-in `takeUntilDestroyed` operator does not handle the case when the component is destroyed before the source observable emits.
|
|
5
|
+
* This operator ensures that the source observable completes gracefully without throwing an error.
|
|
6
|
+
* https://github.com/angular/angular/issues/54527#issuecomment-2098254508
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function safeTakeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperatorFunction<T>;
|