@spartan-ng/brain 0.0.1-alpha.719 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/fesm2022/spartan-ng-brain-accordion.mjs +7 -58
- package/fesm2022/spartan-ng-brain-accordion.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-alert-dialog.mjs +1 -2
- package/fesm2022/spartan-ng-brain-alert-dialog.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-autocomplete.mjs +3 -1
- package/fesm2022/spartan-ng-brain-autocomplete.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-collapsible.mjs +8 -56
- package/fesm2022/spartan-ng-brain-collapsible.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-combobox.mjs +22 -6
- package/fesm2022/spartan-ng-brain-combobox.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-core.mjs +89 -16
- package/fesm2022/spartan-ng-brain-core.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-dialog.mjs +8 -7
- package/fesm2022/spartan-ng-brain-dialog.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-drawer.mjs +8 -8
- package/fesm2022/spartan-ng-brain-drawer.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-field.mjs +7 -2
- package/fesm2022/spartan-ng-brain-field.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-navigation-menu.mjs +124 -34
- package/fesm2022/spartan-ng-brain-navigation-menu.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-overlay.mjs +27 -14
- package/fesm2022/spartan-ng-brain-overlay.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-select.mjs +3 -1
- package/fesm2022/spartan-ng-brain-select.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-tooltip.mjs +97 -14
- package/fesm2022/spartan-ng-brain-tooltip.mjs.map +1 -1
- package/package.json +6 -2
- package/types/spartan-ng-brain-accordion.d.ts +4 -22
- package/types/spartan-ng-brain-autocomplete.d.ts +1 -0
- package/types/spartan-ng-brain-collapsible.d.ts +5 -22
- package/types/spartan-ng-brain-combobox.d.ts +11 -2
- package/types/spartan-ng-brain-core.d.ts +40 -9
- package/types/spartan-ng-brain-dialog.d.ts +1 -3
- package/types/spartan-ng-brain-drawer.d.ts +3 -3
- package/types/spartan-ng-brain-navigation-menu.d.ts +9 -2
- package/types/spartan-ng-brain-overlay.d.ts +4 -5
- package/types/spartan-ng-brain-select.d.ts +1 -0
- package/types/spartan-ng-brain-tooltip.d.ts +38 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { untracked, computed, InjectionToken, forwardRef, inject,
|
|
1
|
+
import { untracked, computed, InjectionToken, forwardRef, inject, ElementRef, PLATFORM_ID, DestroyRef, signal, afterNextRender, runInInjectionContext, Injector } from '@angular/core';
|
|
2
2
|
import { Observable, pipe, merge, fromEvent } from 'rxjs';
|
|
3
3
|
import { map, filter, distinctUntilChanged, takeUntil, debounceTime } from 'rxjs/operators';
|
|
4
4
|
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
@@ -119,6 +119,60 @@ const [injectExposedSideProvider, provideExposedSideProvider, provideExposedSide
|
|
|
119
119
|
|
|
120
120
|
const [injectExposesStateProvider, provideExposesStateProvider, provideExposesStateProviderExisting, EXPOSES_STATE_TOKEN,] = createInjectionToken('@spartan-ng EXPOSES_STATE_TOKEN');
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Measures the natural size of a collapsible host's content via `scrollHeight` so it can animate
|
|
124
|
+
* between `height: 0` and a measured pixel height - the whole content is covered, regardless of how
|
|
125
|
+
* it is projected. A `ResizeObserver` on the content keeps the value live. SSR-safe; the host must
|
|
126
|
+
* be a block-level element for `scrollHeight` to reflect its content.
|
|
127
|
+
*
|
|
128
|
+
* @returns Signals with the content's width and height in px, or `null` before measurement.
|
|
129
|
+
*/
|
|
130
|
+
function injectContentDimensions() {
|
|
131
|
+
const host = inject(ElementRef).nativeElement;
|
|
132
|
+
const platformId = inject(PLATFORM_ID);
|
|
133
|
+
const destroyRef = inject(DestroyRef);
|
|
134
|
+
const width = signal(null, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
135
|
+
const height = signal(null, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
136
|
+
if (isPlatformServer(platformId)) {
|
|
137
|
+
return { width: width.asReadonly(), height: height.asReadonly() };
|
|
138
|
+
}
|
|
139
|
+
const measure = () => {
|
|
140
|
+
// Drop the clamped height for the read: scrollHeight is never smaller than the element's own
|
|
141
|
+
// height, so while clamped it would only ever grow. `height: auto` lets it reflect the real
|
|
142
|
+
// content size (and shrink). The read is synchronous, so the swap never paints.
|
|
143
|
+
const previousHeight = host.style.height;
|
|
144
|
+
host.style.height = 'auto';
|
|
145
|
+
width.set(host.scrollWidth);
|
|
146
|
+
height.set(host.scrollHeight);
|
|
147
|
+
host.style.height = previousHeight;
|
|
148
|
+
};
|
|
149
|
+
afterNextRender({
|
|
150
|
+
read: () => {
|
|
151
|
+
measure();
|
|
152
|
+
if (typeof ResizeObserver === 'undefined')
|
|
153
|
+
return;
|
|
154
|
+
// Observe the content wrapper (not the clamped/animated host) so re-measures fire on content
|
|
155
|
+
// changes, never on the open/close height animation. Re-measure on a fresh frame rather than
|
|
156
|
+
// inside the callback: measure() mutates the host's inline height, and doing that during
|
|
157
|
+
// delivery trips "ResizeObserver loop completed with undelivered notifications".
|
|
158
|
+
let frame = 0;
|
|
159
|
+
const observer = new ResizeObserver(() => {
|
|
160
|
+
cancelAnimationFrame(frame);
|
|
161
|
+
frame = requestAnimationFrame(measure);
|
|
162
|
+
});
|
|
163
|
+
const content = host.firstElementChild;
|
|
164
|
+
if (content) {
|
|
165
|
+
observer.observe(content);
|
|
166
|
+
}
|
|
167
|
+
destroyRef.onDestroy(() => {
|
|
168
|
+
cancelAnimationFrame(frame);
|
|
169
|
+
observer.disconnect();
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
return { width: width.asReadonly(), height: height.asReadonly() };
|
|
174
|
+
}
|
|
175
|
+
|
|
122
176
|
/**
|
|
123
177
|
* Returns a reactive signal that tracks the size of a DOM element.
|
|
124
178
|
*
|
|
@@ -197,21 +251,18 @@ function getSharedObserver() {
|
|
|
197
251
|
return sharedObserver;
|
|
198
252
|
}
|
|
199
253
|
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
elementToMeasure.style.height = previousHeight;
|
|
212
|
-
return { width, height };
|
|
254
|
+
const OPPOSITE_SIDE = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };
|
|
255
|
+
const MENU_SIDE = new InjectionToken('SpartanMenuSide');
|
|
256
|
+
// derive data-side from the transform-origin CDK sets on the content. the anchored corner faces the
|
|
257
|
+
// trigger, so the side is its opposite. the configured `side` tells us which axis carries the anchor
|
|
258
|
+
// (top/bottom -> vertical token, left/right -> horizontal), so a CDK flip is read off the right axis.
|
|
259
|
+
// CDK's origin is rtl-aware, so the derived side is too. falls back to the configured side when the
|
|
260
|
+
// transform-origin is missing or centered (no flip information to apply).
|
|
261
|
+
const deriveMenuSideFromTransformOrigin = (transformOrigin, side) => {
|
|
262
|
+
const [x, y] = transformOrigin.trim().split(/\s+/);
|
|
263
|
+
const anchor = side === 'top' || side === 'bottom' ? y : x;
|
|
264
|
+
return OPPOSITE_SIDE[anchor] ?? side;
|
|
213
265
|
};
|
|
214
|
-
|
|
215
266
|
const createMenuPosition = (align, side) => {
|
|
216
267
|
const verticalAlign = align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center';
|
|
217
268
|
const createPositions = (originX, originY, overlayX, overlayY) => [
|
|
@@ -259,6 +310,28 @@ function serializeValue(value) {
|
|
|
259
310
|
}
|
|
260
311
|
}
|
|
261
312
|
|
|
313
|
+
/** Must be called in an injection context; cleans up its pending timer on destroy. */
|
|
314
|
+
function injectSkipDelay(skipDelayDuration) {
|
|
315
|
+
const isOpenDelayed = signal(true, ...(ngDevMode ? [{ debugName: "isOpenDelayed" }] : /* istanbul ignore next */ []));
|
|
316
|
+
let timer;
|
|
317
|
+
inject(DestroyRef).onDestroy(() => clearTimeout(timer));
|
|
318
|
+
return {
|
|
319
|
+
isOpenDelayed: isOpenDelayed.asReadonly(),
|
|
320
|
+
open() {
|
|
321
|
+
clearTimeout(timer);
|
|
322
|
+
if (skipDelayDuration() > 0)
|
|
323
|
+
isOpenDelayed.set(false);
|
|
324
|
+
},
|
|
325
|
+
close() {
|
|
326
|
+
clearTimeout(timer);
|
|
327
|
+
const duration = skipDelayDuration();
|
|
328
|
+
if (duration > 0) {
|
|
329
|
+
timer = setTimeout(() => isOpenDelayed.set(true), duration);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
262
335
|
const [injectTableClassesSettable, provideTableClassesSettable, provideTableClassesSettableExisting, SET_TABLE_CLASSES_TOKEN,] = createInjectionToken('@spartan-ng SET_TABLE_CLASSES_TOKEN');
|
|
263
336
|
|
|
264
337
|
const MAX_ANIMATION_WAIT_MS = 5_000;
|
|
@@ -308,5 +381,5 @@ function getFallbackTimeout(animations) {
|
|
|
308
381
|
* Generated bundle index. Do not edit.
|
|
309
382
|
*/
|
|
310
383
|
|
|
311
|
-
export { EXPOSES_SIDE_TOKEN, EXPOSES_STATE_TOKEN, SET_CLASS_TO_CUSTOM_ELEMENT_TOKEN, SET_TABLE_CLASSES_TOKEN, brnDevMode, brnZoneFree, brnZoneFull, brnZoneOptimized, computedPrevious, createHoverObservable, createMenuPosition, cssClassesToArray, debouncedSignal, getActiveElementAnimations, injectCustomClassSettable, injectElementSize, injectExposedSideProvider, injectExposesStateProvider, injectTableClassesSettable, isElement,
|
|
384
|
+
export { EXPOSES_SIDE_TOKEN, EXPOSES_STATE_TOKEN, MENU_SIDE, SET_CLASS_TO_CUSTOM_ELEMENT_TOKEN, SET_TABLE_CLASSES_TOKEN, brnDevMode, brnZoneFree, brnZoneFull, brnZoneOptimized, computedPrevious, createHoverObservable, createMenuPosition, cssClassesToArray, debouncedSignal, deriveMenuSideFromTransformOrigin, getActiveElementAnimations, injectContentDimensions, injectCustomClassSettable, injectElementSize, injectExposedSideProvider, injectExposesStateProvider, injectSkipDelay, injectTableClassesSettable, isElement, provideCustomClassSettable, provideCustomClassSettableExisting, provideExposedSideProvider, provideExposedSideProviderExisting, provideExposesStateProvider, provideExposesStateProviderExisting, provideTableClassesSettable, provideTableClassesSettableExisting, serializeValue, stringifyAsLabel, waitForAnimations, waitForElementAnimations };
|
|
312
385
|
//# sourceMappingURL=spartan-ng-brain-core.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spartan-ng-brain-core.mjs","sources":["../../../../libs/brain/core/src/helpers/computed-previous.ts","../../../../libs/brain/core/src/helpers/zone-free.ts","../../../../libs/brain/core/src/helpers/create-hover-observable.ts","../../../../libs/brain/core/src/helpers/css-classes-to-array.ts","../../../../libs/brain/core/src/helpers/create-injection-token.ts","../../../../libs/brain/core/src/helpers/custom-element-class-settable.ts","../../../../libs/brain/core/src/helpers/debounced-signal.ts","../../../../libs/brain/core/src/helpers/dev-mode.ts","../../../../libs/brain/core/src/helpers/exposes-side.ts","../../../../libs/brain/core/src/helpers/exposes-state.ts","../../../../libs/brain/core/src/helpers/inject-element-size.ts","../../../../libs/brain/core/src/helpers/measure-dimensions.ts","../../../../libs/brain/core/src/helpers/menu-align.ts","../../../../libs/brain/core/src/helpers/resolve-value-label.ts","../../../../libs/brain/core/src/helpers/table-classes-settable.ts","../../../../libs/brain/core/src/helpers/wait-for-element-animations.ts","../../../../libs/brain/core/src/spartan-ng-brain-core.ts"],"sourcesContent":["import { computed, type Signal, untracked } from '@angular/core';\n\n/**\n * Returns a signal that emits the previous value of the given signal.\n * The first time the signal is emitted, the previous value will be the same as the current value.\n *\n * @example\n * ```ts\n * const value = signal(0);\n * const previous = computedPrevious(value);\n *\n * effect(() => {\n * console.log('Current value:', value());\n * console.log('Previous value:', previous());\n * });\n *\n * Logs:\n * // Current value: 0\n * // Previous value: 0\n *\n * value.set(1);\n *\n * Logs:\n * // Current value: 1\n * // Previous value: 0\n *\n * value.set(2);\n *\n * Logs:\n * // Current value: 2\n * // Previous value: 1\n *```\n *\n * @param computation Signal to compute previous value for\n * @returns Signal that emits previous value of `s`\n */\nexport function computedPrevious<T>(computation: Signal<T>): Signal<T> {\n\tlet current = null as T;\n\tlet previous = untracked(() => computation()); // initial value is the current value\n\n\treturn computed(() => {\n\t\tcurrent = computation();\n\t\tconst result = previous;\n\t\tprevious = current;\n\t\treturn result;\n\t});\n}\n","/**\n * We are building on shoulders of giants here and use the implementation provided by the incredible TaigaUI\n * team: https://github.com/taiga-family/taiga-ui/blob/main/projects/cdk/observables/zone-free.ts#L22\n * Check them out! Give them a try! Leave a star! Their work is incredible!\n */\nimport type { NgZone } from '@angular/core';\nimport { type MonoTypeOperatorFunction, Observable, pipe } from 'rxjs';\n\nexport function brnZoneFull<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn (source) =>\n\t\tnew Observable((subscriber) =>\n\t\t\tsource.subscribe({\n\t\t\t\tnext: (value) => zone.run(() => subscriber.next(value)),\n\t\t\t\terror: (error: unknown) => zone.run(() => subscriber.error(error)),\n\t\t\t\tcomplete: () => zone.run(() => subscriber.complete()),\n\t\t\t}),\n\t\t);\n}\n\nexport function brnZoneFree<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn (source) => new Observable((subscriber) => zone.runOutsideAngular(() => source.subscribe(subscriber)));\n}\n\nexport function brnZoneOptimized<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn pipe(brnZoneFree(zone), brnZoneFull(zone));\n}\n","import type { NgZone } from '@angular/core';\nimport { type Observable, type Subject, fromEvent, merge } from 'rxjs';\nimport { distinctUntilChanged, filter, map, takeUntil } from 'rxjs/operators';\nimport { brnZoneOptimized } from './zone-free';\n\nfunction movedOut({ currentTarget, relatedTarget }: MouseEvent): boolean {\n\treturn !isElement(relatedTarget) || !isElement(currentTarget) || !currentTarget.contains(relatedTarget);\n}\n\nexport function isElement(node?: Element | EventTarget | Node | null): node is Element {\n\treturn !!node && 'nodeType' in node && node.nodeType === Node.ELEMENT_NODE;\n}\n\nexport const createHoverObservable = (\n\tnativeElement: HTMLElement,\n\tzone: NgZone,\n\tdestroyed$: Subject<void>,\n): Observable<{ hover: boolean; relatedTarget?: EventTarget | null }> => {\n\treturn merge(\n\t\tfromEvent(nativeElement, 'mouseenter').pipe(map(() => ({ hover: true }))),\n\t\tfromEvent<MouseEvent>(nativeElement, 'mouseleave').pipe(\n\t\t\tmap((e) => ({ hover: false, relatedTarget: e.relatedTarget })),\n\t\t),\n\t\t// Hello, Safari\n\t\tfromEvent<MouseEvent>(nativeElement, 'mouseout').pipe(\n\t\t\tfilter(movedOut),\n\t\t\tmap((e) => ({ hover: false, relatedTarget: e.relatedTarget })),\n\t\t),\n\t).pipe(distinctUntilChanged(), brnZoneOptimized(zone), takeUntil(destroyed$));\n};\n","export function cssClassesToArray(classes: string | string[] | null | undefined, defaultClass = ''): string[] {\n\tconst value = classes ?? defaultClass;\n\treturn (Array.isArray(value) ? value : [value]).flatMap((className) => className.split(/\\s+/).filter(Boolean));\n}\n","import { type InjectOptions, InjectionToken, type Provider, type Type, forwardRef, inject } from '@angular/core';\n\ntype InjectFn<TTokenValue> = {\n\t(): TTokenValue;\n\t(injectOptions: InjectOptions & { optional?: false }): TTokenValue;\n\t(injectOptions: InjectOptions & { optional: true }): TTokenValue | null;\n};\n\ntype ProvideFn<TTokenValue> = (value: TTokenValue) => Provider;\n\ntype ProvideExistingFn<TTokenValue> = (valueFactory: () => Type<TTokenValue>) => Provider;\n\nexport type CreateInjectionTokenReturn<TTokenValue> = [\n\tInjectFn<TTokenValue>,\n\tProvideFn<TTokenValue>,\n\tProvideExistingFn<TTokenValue>,\n\tInjectionToken<TTokenValue>,\n];\n\nexport function createInjectionToken<TTokenValue>(description: string): CreateInjectionTokenReturn<TTokenValue> {\n\tconst token = new InjectionToken<TTokenValue>(description);\n\n\tconst provideFn = (value: TTokenValue) => {\n\t\treturn { provide: token, useValue: value };\n\t};\n\n\tconst provideExistingFn = (value: () => TTokenValue) => {\n\t\treturn { provide: token, useExisting: forwardRef(value) };\n\t};\n\n\tconst injectFn = (options: InjectOptions = {}) => {\n\t\treturn inject(token, options);\n\t};\n\n\treturn [injectFn, provideFn, provideExistingFn, token] as CreateInjectionTokenReturn<TTokenValue>;\n}\n","import { createInjectionToken } from './create-injection-token';\n\nexport interface CustomElementClassSettable {\n\tsetClassToCustomElement: (newClass: string) => void;\n}\n\nexport const [\n\tinjectCustomClassSettable,\n\tprovideCustomClassSettable,\n\tprovideCustomClassSettableExisting,\n\tSET_CLASS_TO_CUSTOM_ELEMENT_TOKEN,\n] = createInjectionToken<CustomElementClassSettable>('@spartan-ng SET_CLASS_TO_CUSTOM_ELEMENT_TOKEN');\n","import type { Signal } from '@angular/core';\nimport { toObservable, toSignal } from '@angular/core/rxjs-interop';\nimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';\n\n/**\n * Creates a debounced version of a source signal.\n *\n * @param source - The input signal to debounce.\n * @param delay - Debounce time in milliseconds.\n * @returns A new signal that updates only after the source has stopped changing for `delay` ms.\n */\nexport function debouncedSignal<T>(source: Signal<T>, delay: number): Signal<T> {\n\tconst source$ = toObservable(source);\n\n\tconst debounced$ = source$.pipe(debounceTime(delay), distinctUntilChanged());\n\n\treturn toSignal(debounced$, { initialValue: source() });\n}\n","declare const ngDevMode: boolean;\n/**\n * Set by Angular to true when in development mode.\n * Allows for tree-shaking code that is only used in development.\n */\nexport const brnDevMode = ngDevMode;\n","import type { Signal } from '@angular/core';\nimport { createInjectionToken } from './create-injection-token';\n\nexport interface ExposesSide {\n\tside: Signal<'top' | 'bottom' | 'left' | 'right'>;\n}\n\nexport const [\n\tinjectExposedSideProvider,\n\tprovideExposedSideProvider,\n\tprovideExposedSideProviderExisting,\n\tEXPOSES_SIDE_TOKEN,\n] = createInjectionToken<ExposesSide>('@spartan-ng EXPOSES_SIDE_TOKEN');\n","import type { Signal } from '@angular/core';\nimport { createInjectionToken } from './create-injection-token';\n\nexport interface ExposesState {\n\tstate: Signal<'open' | 'closed'>;\n}\n\nexport const [\n\tinjectExposesStateProvider,\n\tprovideExposesStateProvider,\n\tprovideExposesStateProviderExisting,\n\tEXPOSES_STATE_TOKEN,\n] = createInjectionToken<ExposesState>('@spartan-ng EXPOSES_STATE_TOKEN');\n","import { isPlatformServer } from '@angular/common';\nimport {\n\tafterNextRender,\n\tDestroyRef,\n\tElementRef,\n\tinject,\n\tInjector,\n\tPLATFORM_ID,\n\trunInInjectionContext,\n\ttype Signal,\n\tsignal,\n\ttype WritableSignal,\n} from '@angular/core';\n\n/**\n * Returns a reactive signal that tracks the size of a DOM element.\n *\n * This function uses a shared {@link ResizeObserver} internally to monitor multiple elements efficiently.\n * The returned signal updates whenever the element's width or height changes. It is fully SSR-safe.\n *\n * @param options Optional {@link ElementSizeOptions} configuration object.\n * @param options.elementRef The {@link ElementRef} of the element to observe. Defaults to the {@link ElementRef} injected in the current context.\n * @param options.injector Optional custom {@link Injector} to run the function in. Defaults to the current injection context.\n *\n * @returns A readonly {@link Signal} containing `{ width, height }` of the element, or `undefined` if the element has not yet been measured or on the server.\n *\n * Based on https://github.com/radix-ui/primitives/blob/main/packages/react/use-size/src/use-size.tsx\n */\nexport function injectElementSize(\n\toptions: ElementSizeOptions = {},\n): Signal<{ width: number; height: number } | undefined> {\n\treturn runInInjectionContext(options.injector ?? inject(Injector), () => {\n\t\tconst elementRef = options.elementRef ?? inject(ElementRef);\n\t\tconst platformId = inject(PLATFORM_ID);\n\t\tconst destroyRef = inject(DestroyRef);\n\n\t\tconst element = elementRef.nativeElement;\n\t\tconst size = signal<{ width: number; height: number } | undefined>(undefined);\n\n\t\tif (isPlatformServer(platformId)) {\n\t\t\treturn size;\n\t\t}\n\n\t\tafterNextRender({\n\t\t\tread: () => {\n\t\t\t\t// Initial read\n\t\t\t\tconst rect = element.getBoundingClientRect();\n\t\t\t\tsize.set({\n\t\t\t\t\twidth: rect.width || element.offsetWidth,\n\t\t\t\t\theight: rect.height || element.offsetHeight,\n\t\t\t\t});\n\n\t\t\t\t// Register element in shared observer\n\t\t\t\tobserverMap.set(element, { element, size });\n\t\t\t\tgetSharedObserver().observe(element, { box: 'border-box' });\n\n\t\t\t\tdestroyRef.onDestroy(() => {\n\t\t\t\t\tgetSharedObserver().unobserve(element);\n\t\t\t\t\tobserverMap.delete(element);\n\n\t\t\t\t\t// Disconnect global observer if no elements left\n\t\t\t\t\tif (observerMap.size === 0 && sharedObserver) {\n\t\t\t\t\t\tsharedObserver.disconnect();\n\t\t\t\t\t\tsharedObserver = undefined;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\treturn size.asReadonly();\n\t});\n}\n\nconst observerMap = new Map<HTMLElement, SizeEntry>();\nlet sharedObserver: ResizeObserver | undefined;\n\nfunction getSharedObserver() {\n\tif (!sharedObserver) {\n\t\tsharedObserver = new ResizeObserver((entries) => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst el = entry.target as HTMLElement;\n\t\t\t\tconst entryData = observerMap.get(el);\n\t\t\t\tif (!entryData) continue;\n\n\t\t\t\tlet width: number;\n\t\t\t\tlet height: number;\n\n\t\t\t\tif ('borderBoxSize' in entry) {\n\t\t\t\t\t// Iron out differences between browsers\n\t\t\t\t\tconst borderSize = Array.isArray(entry.borderBoxSize) ? entry.borderBoxSize[0] : entry.borderBoxSize;\n\t\t\t\t\twidth = borderSize.inlineSize;\n\t\t\t\t\theight = borderSize.blockSize;\n\t\t\t\t} else {\n\t\t\t\t\twidth = el.offsetWidth;\n\t\t\t\t\theight = el.offsetHeight;\n\t\t\t\t}\n\n\t\t\t\tentryData.size.set({ width, height });\n\t\t\t}\n\t\t});\n\t}\n\n\treturn sharedObserver;\n}\n\n/**\n * Options to configure `injectElementSize`.\n */\ninterface ElementSizeOptions {\n\t/** The ElementRef of the element to observe. Defaults to injected ElementRef in the current context. */\n\telementRef?: ElementRef<HTMLElement>;\n\t/** Optional Injector to run the function in. Defaults to the current injection context. */\n\tinjector?: Injector;\n}\n\n/**\n * Internal type used to track each observed element in the shared ResizeObserver.\n */\ninterface SizeEntry {\n\t/** The HTML element being observed. */\n\telement: HTMLElement;\n\t/** Writable signal storing the element's current width and height. */\n\tsize: WritableSignal<{ width: number; height: number } | undefined>;\n}\n","export type MeasurementDisplay = 'block' | 'inline-block' | 'flex' | 'grid' | 'table' | 'contents' | (string & {});\n\nexport const measureDimensions = (elementToMeasure: HTMLElement, measurementDisplay: MeasurementDisplay) => {\n\tconst previousHeight = elementToMeasure.style.height;\n\tconst previousDisplay = elementToMeasure.style.display;\n\tconst previousHidden = elementToMeasure.hidden;\n\n\telementToMeasure.hidden = false;\n\telementToMeasure.style.height = 'auto';\n\telementToMeasure.style.display =\n\t\t!previousDisplay || previousDisplay === 'none' ? measurementDisplay : previousDisplay;\n\n\tconst { width, height } = elementToMeasure.getBoundingClientRect();\n\n\telementToMeasure.hidden = previousHidden;\n\telementToMeasure.style.display = previousDisplay;\n\telementToMeasure.style.height = previousHeight;\n\n\treturn { width, height };\n};\n","import type { ConnectedPosition } from '@angular/cdk/overlay';\n\nexport type MenuAlign = 'start' | 'center' | 'end';\nexport type MenuSide = 'top' | 'bottom' | 'left' | 'right';\n\nexport const createMenuPosition = (align: MenuAlign, side: MenuSide): ConnectedPosition[] => {\n\tconst verticalAlign = align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center';\n\n\tconst createPositions = (\n\t\toriginX: 'start' | 'center' | 'end',\n\t\toriginY: 'top' | 'center' | 'bottom',\n\t\toverlayX: 'start' | 'center' | 'end',\n\t\toverlayY: 'top' | 'center' | 'bottom',\n\t): ConnectedPosition[] => [\n\t\t{ originX, originY, overlayX, overlayY },\n\t\t{ originX: overlayX, originY: overlayY, overlayX: originX, overlayY: originY },\n\t];\n\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn createPositions(align, 'top', align, 'bottom');\n\t\tcase 'bottom':\n\t\t\treturn createPositions(align, 'bottom', align, 'top');\n\t\tcase 'left':\n\t\t\treturn createPositions('start', verticalAlign, 'end', verticalAlign);\n\t\tcase 'right':\n\t\t\treturn createPositions('end', verticalAlign, 'start', verticalAlign);\n\t}\n};\n","export function stringifyAsLabel(item: any, itemToStringLabel?: (item: any) => string) {\n\tif (itemToStringLabel && item !== null && item !== undefined) {\n\t\treturn itemToStringLabel(item) ?? '';\n\t}\n\tif (item && typeof item === 'object') {\n\t\tif ('label' in item && item.label !== null && item.label !== undefined) {\n\t\t\treturn String(item.label);\n\t\t}\n\t\tif ('value' in item && item.value !== null && item.value !== undefined) {\n\t\t\treturn String(item.value);\n\t\t}\n\t}\n\treturn serializeValue(item);\n}\n\nexport function serializeValue(value: unknown): string {\n\tif (value === null || value === undefined) {\n\t\treturn '';\n\t}\n\tif (typeof value === 'string') {\n\t\treturn value;\n\t}\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n","import { createInjectionToken } from './create-injection-token';\n\nexport interface TableClassesSettable {\n\tsetTableClasses: (classes: Partial<{ table: string; headerRow: string; bodyRow: string }>) => void;\n}\n\nexport const [\n\tinjectTableClassesSettable,\n\tprovideTableClassesSettable,\n\tprovideTableClassesSettableExisting,\n\tSET_TABLE_CLASSES_TOKEN,\n] = createInjectionToken<TableClassesSettable>('@spartan-ng SET_TABLE_CLASSES_TOKEN');\n","const MAX_ANIMATION_WAIT_MS = 5_000;\nconst ANIMATION_WAIT_BUFFER_MS = 50;\n\nexport function getActiveElementAnimations(elements: readonly (HTMLElement | null | undefined)[]): Animation[] {\n\treturn elements\n\t\t.filter((element): element is HTMLElement => !!element)\n\t\t.flatMap((element) =>\n\t\t\ttypeof element.getAnimations === 'function'\n\t\t\t\t? element.getAnimations({ subtree: true }).filter((animation) => animation.playState !== 'finished')\n\t\t\t\t: [],\n\t\t);\n}\n\nexport async function waitForAnimations(animations: readonly Animation[]): Promise<void> {\n\tif (!animations.length) return;\n\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tconst fallbackMs = getFallbackTimeout(animations);\n\n\ttry {\n\t\tawait Promise.race([\n\t\t\tPromise.allSettled(animations.map((animation) => animation.finished)),\n\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\ttimeout = setTimeout(resolve, fallbackMs);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timeout) clearTimeout(timeout);\n\t}\n}\n\n/**\n * Waits for active animations, including subtree animations, within the given element to finish.\n */\nexport async function waitForElementAnimations(element: HTMLElement): Promise<void> {\n\tawait waitForAnimations(getActiveElementAnimations([element]));\n}\n\nfunction getFallbackTimeout(animations: readonly Animation[]): number {\n\tconst longestAnimation = animations.reduce((longest, animation) => {\n\t\tconst endTime = animation.effect?.getComputedTiming().endTime;\n\t\treturn typeof endTime === 'number' && Number.isFinite(endTime) ? Math.max(longest, endTime) : longest;\n\t}, 0);\n\n\tif (!longestAnimation) return MAX_ANIMATION_WAIT_MS;\n\treturn Math.min(longestAnimation + ANIMATION_WAIT_BUFFER_MS, MAX_ANIMATION_WAIT_MS);\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":"spartan-ng-brain-core.mjs","sources":["../../../../libs/brain/core/src/helpers/computed-previous.ts","../../../../libs/brain/core/src/helpers/zone-free.ts","../../../../libs/brain/core/src/helpers/create-hover-observable.ts","../../../../libs/brain/core/src/helpers/css-classes-to-array.ts","../../../../libs/brain/core/src/helpers/create-injection-token.ts","../../../../libs/brain/core/src/helpers/custom-element-class-settable.ts","../../../../libs/brain/core/src/helpers/debounced-signal.ts","../../../../libs/brain/core/src/helpers/dev-mode.ts","../../../../libs/brain/core/src/helpers/exposes-side.ts","../../../../libs/brain/core/src/helpers/exposes-state.ts","../../../../libs/brain/core/src/helpers/inject-content-dimensions.ts","../../../../libs/brain/core/src/helpers/inject-element-size.ts","../../../../libs/brain/core/src/helpers/menu-align.ts","../../../../libs/brain/core/src/helpers/resolve-value-label.ts","../../../../libs/brain/core/src/helpers/skip-delay.ts","../../../../libs/brain/core/src/helpers/table-classes-settable.ts","../../../../libs/brain/core/src/helpers/wait-for-element-animations.ts","../../../../libs/brain/core/src/spartan-ng-brain-core.ts"],"sourcesContent":["import { computed, type Signal, untracked } from '@angular/core';\n\n/**\n * Returns a signal that emits the previous value of the given signal.\n * The first time the signal is emitted, the previous value will be the same as the current value.\n *\n * @example\n * ```ts\n * const value = signal(0);\n * const previous = computedPrevious(value);\n *\n * effect(() => {\n * console.log('Current value:', value());\n * console.log('Previous value:', previous());\n * });\n *\n * Logs:\n * // Current value: 0\n * // Previous value: 0\n *\n * value.set(1);\n *\n * Logs:\n * // Current value: 1\n * // Previous value: 0\n *\n * value.set(2);\n *\n * Logs:\n * // Current value: 2\n * // Previous value: 1\n *```\n *\n * @param computation Signal to compute previous value for\n * @returns Signal that emits previous value of `s`\n */\nexport function computedPrevious<T>(computation: Signal<T>): Signal<T> {\n\tlet current = null as T;\n\tlet previous = untracked(() => computation()); // initial value is the current value\n\n\treturn computed(() => {\n\t\tcurrent = computation();\n\t\tconst result = previous;\n\t\tprevious = current;\n\t\treturn result;\n\t});\n}\n","/**\n * We are building on shoulders of giants here and use the implementation provided by the incredible TaigaUI\n * team: https://github.com/taiga-family/taiga-ui/blob/main/projects/cdk/observables/zone-free.ts#L22\n * Check them out! Give them a try! Leave a star! Their work is incredible!\n */\nimport type { NgZone } from '@angular/core';\nimport { type MonoTypeOperatorFunction, Observable, pipe } from 'rxjs';\n\nexport function brnZoneFull<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn (source) =>\n\t\tnew Observable((subscriber) =>\n\t\t\tsource.subscribe({\n\t\t\t\tnext: (value) => zone.run(() => subscriber.next(value)),\n\t\t\t\terror: (error: unknown) => zone.run(() => subscriber.error(error)),\n\t\t\t\tcomplete: () => zone.run(() => subscriber.complete()),\n\t\t\t}),\n\t\t);\n}\n\nexport function brnZoneFree<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn (source) => new Observable((subscriber) => zone.runOutsideAngular(() => source.subscribe(subscriber)));\n}\n\nexport function brnZoneOptimized<T>(zone: NgZone): MonoTypeOperatorFunction<T> {\n\treturn pipe(brnZoneFree(zone), brnZoneFull(zone));\n}\n","import type { NgZone } from '@angular/core';\nimport { type Observable, type Subject, fromEvent, merge } from 'rxjs';\nimport { distinctUntilChanged, filter, map, takeUntil } from 'rxjs/operators';\nimport { brnZoneOptimized } from './zone-free';\n\nfunction movedOut({ currentTarget, relatedTarget }: MouseEvent): boolean {\n\treturn !isElement(relatedTarget) || !isElement(currentTarget) || !currentTarget.contains(relatedTarget);\n}\n\nexport function isElement(node?: Element | EventTarget | Node | null): node is Element {\n\treturn !!node && 'nodeType' in node && node.nodeType === Node.ELEMENT_NODE;\n}\n\nexport const createHoverObservable = (\n\tnativeElement: HTMLElement,\n\tzone: NgZone,\n\tdestroyed$: Subject<void>,\n): Observable<{ hover: boolean; relatedTarget?: EventTarget | null }> => {\n\treturn merge(\n\t\tfromEvent(nativeElement, 'mouseenter').pipe(map(() => ({ hover: true }))),\n\t\tfromEvent<MouseEvent>(nativeElement, 'mouseleave').pipe(\n\t\t\tmap((e) => ({ hover: false, relatedTarget: e.relatedTarget })),\n\t\t),\n\t\t// Hello, Safari\n\t\tfromEvent<MouseEvent>(nativeElement, 'mouseout').pipe(\n\t\t\tfilter(movedOut),\n\t\t\tmap((e) => ({ hover: false, relatedTarget: e.relatedTarget })),\n\t\t),\n\t).pipe(distinctUntilChanged(), brnZoneOptimized(zone), takeUntil(destroyed$));\n};\n","export function cssClassesToArray(classes: string | string[] | null | undefined, defaultClass = ''): string[] {\n\tconst value = classes ?? defaultClass;\n\treturn (Array.isArray(value) ? value : [value]).flatMap((className) => className.split(/\\s+/).filter(Boolean));\n}\n","import { type InjectOptions, InjectionToken, type Provider, type Type, forwardRef, inject } from '@angular/core';\n\ntype InjectFn<TTokenValue> = {\n\t(): TTokenValue;\n\t(injectOptions: InjectOptions & { optional?: false }): TTokenValue;\n\t(injectOptions: InjectOptions & { optional: true }): TTokenValue | null;\n};\n\ntype ProvideFn<TTokenValue> = (value: TTokenValue) => Provider;\n\ntype ProvideExistingFn<TTokenValue> = (valueFactory: () => Type<TTokenValue>) => Provider;\n\nexport type CreateInjectionTokenReturn<TTokenValue> = [\n\tInjectFn<TTokenValue>,\n\tProvideFn<TTokenValue>,\n\tProvideExistingFn<TTokenValue>,\n\tInjectionToken<TTokenValue>,\n];\n\nexport function createInjectionToken<TTokenValue>(description: string): CreateInjectionTokenReturn<TTokenValue> {\n\tconst token = new InjectionToken<TTokenValue>(description);\n\n\tconst provideFn = (value: TTokenValue) => {\n\t\treturn { provide: token, useValue: value };\n\t};\n\n\tconst provideExistingFn = (value: () => TTokenValue) => {\n\t\treturn { provide: token, useExisting: forwardRef(value) };\n\t};\n\n\tconst injectFn = (options: InjectOptions = {}) => {\n\t\treturn inject(token, options);\n\t};\n\n\treturn [injectFn, provideFn, provideExistingFn, token] as CreateInjectionTokenReturn<TTokenValue>;\n}\n","import { createInjectionToken } from './create-injection-token';\n\nexport interface CustomElementClassSettable {\n\tsetClassToCustomElement: (newClass: string) => void;\n}\n\nexport const [\n\tinjectCustomClassSettable,\n\tprovideCustomClassSettable,\n\tprovideCustomClassSettableExisting,\n\tSET_CLASS_TO_CUSTOM_ELEMENT_TOKEN,\n] = createInjectionToken<CustomElementClassSettable>('@spartan-ng SET_CLASS_TO_CUSTOM_ELEMENT_TOKEN');\n","import type { Signal } from '@angular/core';\nimport { toObservable, toSignal } from '@angular/core/rxjs-interop';\nimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';\n\n/**\n * Creates a debounced version of a source signal.\n *\n * @param source - The input signal to debounce.\n * @param delay - Debounce time in milliseconds.\n * @returns A new signal that updates only after the source has stopped changing for `delay` ms.\n */\nexport function debouncedSignal<T>(source: Signal<T>, delay: number): Signal<T> {\n\tconst source$ = toObservable(source);\n\n\tconst debounced$ = source$.pipe(debounceTime(delay), distinctUntilChanged());\n\n\treturn toSignal(debounced$, { initialValue: source() });\n}\n","declare const ngDevMode: boolean;\n/**\n * Set by Angular to true when in development mode.\n * Allows for tree-shaking code that is only used in development.\n */\nexport const brnDevMode = ngDevMode;\n","import type { Signal } from '@angular/core';\nimport { createInjectionToken } from './create-injection-token';\n\nexport interface ExposesSide {\n\tside: Signal<'top' | 'bottom' | 'left' | 'right'>;\n}\n\nexport const [\n\tinjectExposedSideProvider,\n\tprovideExposedSideProvider,\n\tprovideExposedSideProviderExisting,\n\tEXPOSES_SIDE_TOKEN,\n] = createInjectionToken<ExposesSide>('@spartan-ng EXPOSES_SIDE_TOKEN');\n","import type { Signal } from '@angular/core';\nimport { createInjectionToken } from './create-injection-token';\n\nexport interface ExposesState {\n\tstate: Signal<'open' | 'closed'>;\n}\n\nexport const [\n\tinjectExposesStateProvider,\n\tprovideExposesStateProvider,\n\tprovideExposesStateProviderExisting,\n\tEXPOSES_STATE_TOKEN,\n] = createInjectionToken<ExposesState>('@spartan-ng EXPOSES_STATE_TOKEN');\n","import { isPlatformServer } from '@angular/common';\nimport { afterNextRender, DestroyRef, ElementRef, inject, PLATFORM_ID, type Signal, signal } from '@angular/core';\n\n/** Reactive natural size of a collapsible host's projected content, or `null` before measurement. */\nexport interface ContentDimensions {\n\twidth: Signal<number | null>;\n\theight: Signal<number | null>;\n}\n\n/**\n * Measures the natural size of a collapsible host's content via `scrollHeight` so it can animate\n * between `height: 0` and a measured pixel height - the whole content is covered, regardless of how\n * it is projected. A `ResizeObserver` on the content keeps the value live. SSR-safe; the host must\n * be a block-level element for `scrollHeight` to reflect its content.\n *\n * @returns Signals with the content's width and height in px, or `null` before measurement.\n */\nexport function injectContentDimensions(): ContentDimensions {\n\tconst host = inject(ElementRef).nativeElement as HTMLElement;\n\tconst platformId = inject(PLATFORM_ID);\n\tconst destroyRef = inject(DestroyRef);\n\n\tconst width = signal<number | null>(null);\n\tconst height = signal<number | null>(null);\n\n\tif (isPlatformServer(platformId)) {\n\t\treturn { width: width.asReadonly(), height: height.asReadonly() };\n\t}\n\n\tconst measure = (): void => {\n\t\t// Drop the clamped height for the read: scrollHeight is never smaller than the element's own\n\t\t// height, so while clamped it would only ever grow. `height: auto` lets it reflect the real\n\t\t// content size (and shrink). The read is synchronous, so the swap never paints.\n\t\tconst previousHeight = host.style.height;\n\t\thost.style.height = 'auto';\n\t\twidth.set(host.scrollWidth);\n\t\theight.set(host.scrollHeight);\n\t\thost.style.height = previousHeight;\n\t};\n\n\tafterNextRender({\n\t\tread: () => {\n\t\t\tmeasure();\n\t\t\tif (typeof ResizeObserver === 'undefined') return;\n\n\t\t\t// Observe the content wrapper (not the clamped/animated host) so re-measures fire on content\n\t\t\t// changes, never on the open/close height animation. Re-measure on a fresh frame rather than\n\t\t\t// inside the callback: measure() mutates the host's inline height, and doing that during\n\t\t\t// delivery trips \"ResizeObserver loop completed with undelivered notifications\".\n\t\t\tlet frame = 0;\n\t\t\tconst observer = new ResizeObserver(() => {\n\t\t\t\tcancelAnimationFrame(frame);\n\t\t\t\tframe = requestAnimationFrame(measure);\n\t\t\t});\n\t\t\tconst content = host.firstElementChild;\n\t\t\tif (content) {\n\t\t\t\tobserver.observe(content);\n\t\t\t}\n\t\t\tdestroyRef.onDestroy(() => {\n\t\t\t\tcancelAnimationFrame(frame);\n\t\t\t\tobserver.disconnect();\n\t\t\t});\n\t\t},\n\t});\n\n\treturn { width: width.asReadonly(), height: height.asReadonly() };\n}\n","import { isPlatformServer } from '@angular/common';\nimport {\n\tafterNextRender,\n\tDestroyRef,\n\tElementRef,\n\tinject,\n\tInjector,\n\tPLATFORM_ID,\n\trunInInjectionContext,\n\ttype Signal,\n\tsignal,\n\ttype WritableSignal,\n} from '@angular/core';\n\n/**\n * Returns a reactive signal that tracks the size of a DOM element.\n *\n * This function uses a shared {@link ResizeObserver} internally to monitor multiple elements efficiently.\n * The returned signal updates whenever the element's width or height changes. It is fully SSR-safe.\n *\n * @param options Optional {@link ElementSizeOptions} configuration object.\n * @param options.elementRef The {@link ElementRef} of the element to observe. Defaults to the {@link ElementRef} injected in the current context.\n * @param options.injector Optional custom {@link Injector} to run the function in. Defaults to the current injection context.\n *\n * @returns A readonly {@link Signal} containing `{ width, height }` of the element, or `undefined` if the element has not yet been measured or on the server.\n *\n * Based on https://github.com/radix-ui/primitives/blob/main/packages/react/use-size/src/use-size.tsx\n */\nexport function injectElementSize(\n\toptions: ElementSizeOptions = {},\n): Signal<{ width: number; height: number } | undefined> {\n\treturn runInInjectionContext(options.injector ?? inject(Injector), () => {\n\t\tconst elementRef = options.elementRef ?? inject(ElementRef);\n\t\tconst platformId = inject(PLATFORM_ID);\n\t\tconst destroyRef = inject(DestroyRef);\n\n\t\tconst element = elementRef.nativeElement;\n\t\tconst size = signal<{ width: number; height: number } | undefined>(undefined);\n\n\t\tif (isPlatformServer(platformId)) {\n\t\t\treturn size;\n\t\t}\n\n\t\tafterNextRender({\n\t\t\tread: () => {\n\t\t\t\t// Initial read\n\t\t\t\tconst rect = element.getBoundingClientRect();\n\t\t\t\tsize.set({\n\t\t\t\t\twidth: rect.width || element.offsetWidth,\n\t\t\t\t\theight: rect.height || element.offsetHeight,\n\t\t\t\t});\n\n\t\t\t\t// Register element in shared observer\n\t\t\t\tobserverMap.set(element, { element, size });\n\t\t\t\tgetSharedObserver().observe(element, { box: 'border-box' });\n\n\t\t\t\tdestroyRef.onDestroy(() => {\n\t\t\t\t\tgetSharedObserver().unobserve(element);\n\t\t\t\t\tobserverMap.delete(element);\n\n\t\t\t\t\t// Disconnect global observer if no elements left\n\t\t\t\t\tif (observerMap.size === 0 && sharedObserver) {\n\t\t\t\t\t\tsharedObserver.disconnect();\n\t\t\t\t\t\tsharedObserver = undefined;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\treturn size.asReadonly();\n\t});\n}\n\nconst observerMap = new Map<HTMLElement, SizeEntry>();\nlet sharedObserver: ResizeObserver | undefined;\n\nfunction getSharedObserver() {\n\tif (!sharedObserver) {\n\t\tsharedObserver = new ResizeObserver((entries) => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst el = entry.target as HTMLElement;\n\t\t\t\tconst entryData = observerMap.get(el);\n\t\t\t\tif (!entryData) continue;\n\n\t\t\t\tlet width: number;\n\t\t\t\tlet height: number;\n\n\t\t\t\tif ('borderBoxSize' in entry) {\n\t\t\t\t\t// Iron out differences between browsers\n\t\t\t\t\tconst borderSize = Array.isArray(entry.borderBoxSize) ? entry.borderBoxSize[0] : entry.borderBoxSize;\n\t\t\t\t\twidth = borderSize.inlineSize;\n\t\t\t\t\theight = borderSize.blockSize;\n\t\t\t\t} else {\n\t\t\t\t\twidth = el.offsetWidth;\n\t\t\t\t\theight = el.offsetHeight;\n\t\t\t\t}\n\n\t\t\t\tentryData.size.set({ width, height });\n\t\t\t}\n\t\t});\n\t}\n\n\treturn sharedObserver;\n}\n\n/**\n * Options to configure `injectElementSize`.\n */\ninterface ElementSizeOptions {\n\t/** The ElementRef of the element to observe. Defaults to injected ElementRef in the current context. */\n\telementRef?: ElementRef<HTMLElement>;\n\t/** Optional Injector to run the function in. Defaults to the current injection context. */\n\tinjector?: Injector;\n}\n\n/**\n * Internal type used to track each observed element in the shared ResizeObserver.\n */\ninterface SizeEntry {\n\t/** The HTML element being observed. */\n\telement: HTMLElement;\n\t/** Writable signal storing the element's current width and height. */\n\tsize: WritableSignal<{ width: number; height: number } | undefined>;\n}\n","import type { ConnectedPosition } from '@angular/cdk/overlay';\nimport { InjectionToken } from '@angular/core';\n\nexport type MenuAlign = 'start' | 'center' | 'end';\nexport type MenuSide = 'top' | 'bottom' | 'left' | 'right';\n\nconst OPPOSITE_SIDE: Record<string, MenuSide> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };\n\n/**\n * Lets a menu trigger expose its configured `side` to the portaled content. CDK gives the content a\n * child injector whose parent is the trigger's injector, so the content can resolve this token to\n * learn which axis to read off the transform-origin.\n */\nexport interface MenuSideProvider {\n\treadonly side: () => MenuSide;\n}\n\nexport const MENU_SIDE = new InjectionToken<MenuSideProvider>('SpartanMenuSide');\n\n// derive data-side from the transform-origin CDK sets on the content. the anchored corner faces the\n// trigger, so the side is its opposite. the configured `side` tells us which axis carries the anchor\n// (top/bottom -> vertical token, left/right -> horizontal), so a CDK flip is read off the right axis.\n// CDK's origin is rtl-aware, so the derived side is too. falls back to the configured side when the\n// transform-origin is missing or centered (no flip information to apply).\nexport const deriveMenuSideFromTransformOrigin = (transformOrigin: string, side: MenuSide): MenuSide => {\n\tconst [x, y] = transformOrigin.trim().split(/\\s+/);\n\tconst anchor = side === 'top' || side === 'bottom' ? y : x;\n\treturn OPPOSITE_SIDE[anchor] ?? side;\n};\n\nexport const createMenuPosition = (align: MenuAlign, side: MenuSide): ConnectedPosition[] => {\n\tconst verticalAlign = align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center';\n\n\tconst createPositions = (\n\t\toriginX: 'start' | 'center' | 'end',\n\t\toriginY: 'top' | 'center' | 'bottom',\n\t\toverlayX: 'start' | 'center' | 'end',\n\t\toverlayY: 'top' | 'center' | 'bottom',\n\t): ConnectedPosition[] => [\n\t\t{ originX, originY, overlayX, overlayY },\n\t\t{ originX: overlayX, originY: overlayY, overlayX: originX, overlayY: originY },\n\t];\n\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn createPositions(align, 'top', align, 'bottom');\n\t\tcase 'bottom':\n\t\t\treturn createPositions(align, 'bottom', align, 'top');\n\t\tcase 'left':\n\t\t\treturn createPositions('start', verticalAlign, 'end', verticalAlign);\n\t\tcase 'right':\n\t\t\treturn createPositions('end', verticalAlign, 'start', verticalAlign);\n\t}\n};\n","export function stringifyAsLabel(item: any, itemToStringLabel?: (item: any) => string) {\n\tif (itemToStringLabel && item !== null && item !== undefined) {\n\t\treturn itemToStringLabel(item) ?? '';\n\t}\n\tif (item && typeof item === 'object') {\n\t\tif ('label' in item && item.label !== null && item.label !== undefined) {\n\t\t\treturn String(item.label);\n\t\t}\n\t\tif ('value' in item && item.value !== null && item.value !== undefined) {\n\t\t\treturn String(item.value);\n\t\t}\n\t}\n\treturn serializeValue(item);\n}\n\nexport function serializeValue(value: unknown): string {\n\tif (value === null || value === undefined) {\n\t\treturn '';\n\t}\n\tif (typeof value === 'string') {\n\t\treturn value;\n\t}\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n","import { DestroyRef, inject, type Signal, signal } from '@angular/core';\n\n/** Skip-delay grouping: once one member opens, siblings skip their delay until the window elapses. */\nexport interface SkipDelay {\n\t/** Whether the next open should still wait for its delay (`true`) or open instantly (`false`). */\n\treadonly isOpenDelayed: Signal<boolean>;\n\t/** Report that a member opened: opens the skip window so siblings skip their delay. */\n\topen(): void;\n\t/** Report that a member closed: re-require the delay once the window elapses. */\n\tclose(): void;\n}\n\n/** Must be called in an injection context; cleans up its pending timer on destroy. */\nexport function injectSkipDelay(skipDelayDuration: () => number): SkipDelay {\n\tconst isOpenDelayed = signal(true);\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\n\tinject(DestroyRef).onDestroy(() => clearTimeout(timer));\n\n\treturn {\n\t\tisOpenDelayed: isOpenDelayed.asReadonly(),\n\t\topen(): void {\n\t\t\tclearTimeout(timer);\n\t\t\tif (skipDelayDuration() > 0) isOpenDelayed.set(false);\n\t\t},\n\t\tclose(): void {\n\t\t\tclearTimeout(timer);\n\t\t\tconst duration = skipDelayDuration();\n\t\t\tif (duration > 0) {\n\t\t\t\ttimer = setTimeout(() => isOpenDelayed.set(true), duration);\n\t\t\t}\n\t\t},\n\t};\n}\n","import { createInjectionToken } from './create-injection-token';\n\nexport interface TableClassesSettable {\n\tsetTableClasses: (classes: Partial<{ table: string; headerRow: string; bodyRow: string }>) => void;\n}\n\nexport const [\n\tinjectTableClassesSettable,\n\tprovideTableClassesSettable,\n\tprovideTableClassesSettableExisting,\n\tSET_TABLE_CLASSES_TOKEN,\n] = createInjectionToken<TableClassesSettable>('@spartan-ng SET_TABLE_CLASSES_TOKEN');\n","const MAX_ANIMATION_WAIT_MS = 5_000;\nconst ANIMATION_WAIT_BUFFER_MS = 50;\n\nexport function getActiveElementAnimations(elements: readonly (HTMLElement | null | undefined)[]): Animation[] {\n\treturn elements\n\t\t.filter((element): element is HTMLElement => !!element)\n\t\t.flatMap((element) =>\n\t\t\ttypeof element.getAnimations === 'function'\n\t\t\t\t? element.getAnimations({ subtree: true }).filter((animation) => animation.playState !== 'finished')\n\t\t\t\t: [],\n\t\t);\n}\n\nexport async function waitForAnimations(animations: readonly Animation[]): Promise<void> {\n\tif (!animations.length) return;\n\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tconst fallbackMs = getFallbackTimeout(animations);\n\n\ttry {\n\t\tawait Promise.race([\n\t\t\tPromise.allSettled(animations.map((animation) => animation.finished)),\n\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\ttimeout = setTimeout(resolve, fallbackMs);\n\t\t\t}),\n\t\t]);\n\t} finally {\n\t\tif (timeout) clearTimeout(timeout);\n\t}\n}\n\n/**\n * Waits for active animations, including subtree animations, within the given element to finish.\n */\nexport async function waitForElementAnimations(element: HTMLElement): Promise<void> {\n\tawait waitForAnimations(getActiveElementAnimations([element]));\n}\n\nfunction getFallbackTimeout(animations: readonly Animation[]): number {\n\tconst longestAnimation = animations.reduce((longest, animation) => {\n\t\tconst endTime = animation.effect?.getComputedTiming().endTime;\n\t\treturn typeof endTime === 'number' && Number.isFinite(endTime) ? Math.max(longest, endTime) : longest;\n\t}, 0);\n\n\tif (!longestAnimation) return MAX_ANIMATION_WAIT_MS;\n\treturn Math.min(longestAnimation + ANIMATION_WAIT_BUFFER_MS, MAX_ANIMATION_WAIT_MS);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,6 @@ const defaultOptions = {
|
|
|
18
18
|
attachTo: null,
|
|
19
19
|
autoFocus: 'first-tabbable',
|
|
20
20
|
backdropClass: '',
|
|
21
|
-
closeOnBackdropClick: true,
|
|
22
21
|
closeOnOutsidePointerEvents: false,
|
|
23
22
|
disableClose: false,
|
|
24
23
|
hasBackdrop: true,
|
|
@@ -96,8 +95,6 @@ class BrnDialogRef {
|
|
|
96
95
|
const options = this.initialOptions;
|
|
97
96
|
if (!this.open || options.disableClose)
|
|
98
97
|
return false;
|
|
99
|
-
if (reason === 'backdrop' && !options.closeOnBackdropClick)
|
|
100
|
-
return false;
|
|
101
98
|
if (reason === 'outside' && !options.closeOnOutsidePointerEvents)
|
|
102
99
|
return false;
|
|
103
100
|
this.close();
|
|
@@ -140,6 +137,12 @@ class BrnDialogRef {
|
|
|
140
137
|
if (generation !== this._closeGeneration || this._phase() !== 'closing')
|
|
141
138
|
return;
|
|
142
139
|
const exitAnimations = this._getActiveAnimations().filter((animation) => !animationsBeforeClose.has(animation));
|
|
140
|
+
// Pin each exit animation to its final frame. tw-animate-css uses `animation-fill-mode: none`,
|
|
141
|
+
// so a finished exit reverts the element to its visible state in the gap before we dispose it -
|
|
142
|
+
// that one-frame snap-back is the flicker. updateTiming pins only the animations we await.
|
|
143
|
+
for (const animation of exitAnimations) {
|
|
144
|
+
animation.effect?.updateTiming({ fill: 'forwards' });
|
|
145
|
+
}
|
|
143
146
|
await waitForAnimations(exitAnimations);
|
|
144
147
|
if (generation === this._closeGeneration && this._phase() === 'closing') {
|
|
145
148
|
this._phase.set('closed');
|
|
@@ -307,7 +310,6 @@ class BrnDialog {
|
|
|
307
310
|
scrollStrategy = input(this._defaultOptions.scrollStrategy, ...(ngDevMode ? [{ debugName: "scrollStrategy" }] : /* istanbul ignore next */ []));
|
|
308
311
|
restoreFocus = input(this._defaultOptions.restoreFocus, ...(ngDevMode ? [{ debugName: "restoreFocus" }] : /* istanbul ignore next */ []));
|
|
309
312
|
closeOnOutsidePointerEvents = input(this._defaultOptions.closeOnOutsidePointerEvents, { ...(ngDevMode ? { debugName: "closeOnOutsidePointerEvents" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
310
|
-
closeOnBackdropClick = input(this._defaultOptions.closeOnBackdropClick, { ...(ngDevMode ? { debugName: "closeOnBackdropClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
311
313
|
attachTo = input(this._defaultOptions.attachTo, ...(ngDevMode ? [{ debugName: "attachTo" }] : /* istanbul ignore next */ []));
|
|
312
314
|
attachPositions = input(this._defaultOptions.attachPositions, ...(ngDevMode ? [{ debugName: "attachPositions" }] : /* istanbul ignore next */ []));
|
|
313
315
|
autoFocus = input(this._defaultOptions.autoFocus, ...(ngDevMode ? [{ debugName: "autoFocus" }] : /* istanbul ignore next */ []));
|
|
@@ -326,7 +328,6 @@ class BrnDialog {
|
|
|
326
328
|
scrollStrategy: this.getScrollStrategy(),
|
|
327
329
|
restoreFocus: this.restoreFocus(),
|
|
328
330
|
closeOnOutsidePointerEvents: this.closeOnOutsidePointerEvents(),
|
|
329
|
-
closeOnBackdropClick: this.closeOnBackdropClick(),
|
|
330
331
|
attachTo: this.getAttachTo(),
|
|
331
332
|
attachPositions: this.attachPositions(),
|
|
332
333
|
autoFocus: this.autoFocus(),
|
|
@@ -432,7 +433,7 @@ class BrnDialog {
|
|
|
432
433
|
}, { injector: this._injector });
|
|
433
434
|
}
|
|
434
435
|
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BrnDialog, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
435
|
-
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: BrnDialog, isStandalone: true, selector: "[brnDialog],brn-dialog", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, scrollStrategy: { classPropertyName: "scrollStrategy", publicName: "scrollStrategy", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsidePointerEvents: { classPropertyName: "closeOnOutsidePointerEvents", publicName: "closeOnOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null },
|
|
436
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: BrnDialog, isStandalone: true, selector: "[brnDialog],brn-dialog", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, scrollStrategy: { classPropertyName: "scrollStrategy", publicName: "scrollStrategy", isSignal: true, isRequired: false, transformFunction: null }, restoreFocus: { classPropertyName: "restoreFocus", publicName: "restoreFocus", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsidePointerEvents: { classPropertyName: "closeOnOutsidePointerEvents", publicName: "closeOnOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null }, attachTo: { classPropertyName: "attachTo", publicName: "attachTo", isSignal: true, isRequired: false, transformFunction: null }, attachPositions: { classPropertyName: "attachPositions", publicName: "attachPositions", isSignal: true, isRequired: false, transformFunction: null }, autoFocus: { classPropertyName: "autoFocus", publicName: "autoFocus", isSignal: true, isRequired: false, transformFunction: null }, disableClose: { classPropertyName: "disableClose", publicName: "disableClose", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "aria-describedby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaModal: { classPropertyName: "ariaModal", publicName: "aria-modal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", stateChanged: "stateChanged" }, exportAs: ["brnDialog"], ngImport: i0 });
|
|
436
437
|
}
|
|
437
438
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BrnDialog, decorators: [{
|
|
438
439
|
type: Directive,
|
|
@@ -440,7 +441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
440
441
|
selector: '[brnDialog],brn-dialog',
|
|
441
442
|
exportAs: 'brnDialog',
|
|
442
443
|
}]
|
|
443
|
-
}], ctorParameters: () => [], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }], stateChanged: [{ type: i0.Output, args: ["stateChanged"] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], scrollStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStrategy", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], closeOnOutsidePointerEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsidePointerEvents", required: false }] }],
|
|
444
|
+
}], ctorParameters: () => [], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }], stateChanged: [{ type: i0.Output, args: ["stateChanged"] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], scrollStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStrategy", required: false }] }], restoreFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreFocus", required: false }] }], closeOnOutsidePointerEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsidePointerEvents", required: false }] }], attachTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachTo", required: false }] }], attachPositions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachPositions", required: false }] }], autoFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFocus", required: false }] }], disableClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableClose", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-describedby", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-modal", required: false }] }] } });
|
|
444
445
|
|
|
445
446
|
class BrnDialogClose {
|
|
446
447
|
_brnDialogRef = inject(BrnDialogRef);
|