@scion/components 22.1.0 → 22.3.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/_index.scss +75 -5
- package/common/package.json +4 -0
- package/design/_theming.scss +25 -10
- package/design/components/_scion-component-dark-tokens.scss +153 -0
- package/design/components/_scion-component-light-tokens.scss +153 -0
- package/design/icons/_scion-icon-font.scss +50 -0
- package/design/themes/_scion-dark-theme.scss +2 -7
- package/design/themes/_scion-light-theme.scss +3 -8
- package/fesm2022/scion-components-common.mjs +251 -0
- package/fesm2022/scion-components-common.mjs.map +1 -0
- package/fesm2022/scion-components-dimension.mjs +7 -6
- package/fesm2022/scion-components-dimension.mjs.map +1 -1
- package/fesm2022/scion-components-icon.mjs +380 -0
- package/fesm2022/scion-components-icon.mjs.map +1 -0
- package/fesm2022/scion-components-menu.mjs +3271 -0
- package/fesm2022/scion-components-menu.mjs.map +1 -0
- package/fesm2022/scion-components-sashbox.mjs +21 -21
- package/fesm2022/scion-components-sashbox.mjs.map +1 -1
- package/fesm2022/scion-components-splitter.mjs +16 -13
- package/fesm2022/scion-components-splitter.mjs.map +1 -1
- package/fesm2022/scion-components-table.mjs +2265 -0
- package/fesm2022/scion-components-table.mjs.map +1 -0
- package/fesm2022/scion-components-text.mjs +322 -0
- package/fesm2022/scion-components-text.mjs.map +1 -0
- package/fesm2022/scion-components-throbber.mjs +15 -15
- package/fesm2022/scion-components-throbber.mjs.map +1 -1
- package/fesm2022/scion-components-viewport.mjs +142 -125
- package/fesm2022/scion-components-viewport.mjs.map +1 -1
- package/icon/package.json +4 -0
- package/menu/package.json +4 -0
- package/package.json +22 -2
- package/table/package.json +4 -0
- package/text/package.json +4 -0
- package/types/scion-components-common.d.ts +185 -0
- package/types/scion-components-icon.d.ts +146 -0
- package/types/scion-components-menu.d.ts +1922 -0
- package/types/scion-components-sashbox.d.ts +4 -2
- package/types/scion-components-splitter.d.ts +4 -3
- package/types/scion-components-table.d.ts +577 -0
- package/types/scion-components-text.d.ts +131 -0
- package/types/scion-components-viewport.d.ts +32 -39
- package/viewport/scrollbar/_scrollbar.scss +4 -4
- package/design/components/_scion-component-tokens.scss +0 -48
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { isSignal, signal, inject, Injector, effect, untracked, DestroyRef, assertInInjectionContext as assertInInjectionContext$1, input, ElementRef, IterableDiffers, Renderer2, Directive, ViewContainerRef, inputBinding } from '@angular/core';
|
|
3
|
+
import { of, Observable } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
7
|
+
*
|
|
8
|
+
* This program and the accompanying materials are made
|
|
9
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
10
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
11
|
+
*
|
|
12
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
13
|
+
*/
|
|
14
|
+
function coerceSignal(value, options) {
|
|
15
|
+
if (value === undefined && !options?.coerceUndefined) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return isSignal(value) ? value : signal(value);
|
|
19
|
+
}
|
|
20
|
+
function toLazyObservable(signal, options) {
|
|
21
|
+
if (signal === undefined) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
if (!isSignal(signal)) {
|
|
25
|
+
return of(signal);
|
|
26
|
+
}
|
|
27
|
+
const injector = options?.injector ?? inject(Injector);
|
|
28
|
+
return new Observable(observer => {
|
|
29
|
+
const initialValue = signal();
|
|
30
|
+
let isFirstEffectRun = true;
|
|
31
|
+
// Emit initial value synchronously.
|
|
32
|
+
observer.next(initialValue);
|
|
33
|
+
const effectRef = effect(() => {
|
|
34
|
+
const value = signal();
|
|
35
|
+
untracked(() => {
|
|
36
|
+
if (!isFirstEffectRun || initialValue !== value) {
|
|
37
|
+
observer.next(value);
|
|
38
|
+
}
|
|
39
|
+
isFirstEffectRun = false;
|
|
40
|
+
});
|
|
41
|
+
}, { ...(ngDevMode ? { debugName: "effectRef" } : /* istanbul ignore next */ {}), injector, manualCleanup: true });
|
|
42
|
+
return () => effectRef.destroy();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
48
|
+
*
|
|
49
|
+
* This program and the accompanying materials are made
|
|
50
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
51
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
52
|
+
*
|
|
53
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* Creates a {@link DestroyableInjector} bound to the lifecycle of its parent injector. Defaults to the current injector if not configuring a parent injector.
|
|
57
|
+
*
|
|
58
|
+
* Unlike injectors created via {@link Injector.create}, the returned injector:
|
|
59
|
+
* - Is destroyed with its parent, also if used outside a component injection context.
|
|
60
|
+
* - Does not throw an error when invoking {@link DestroyableInjector.destroy} if already destroyed.
|
|
61
|
+
* - Uses the current injection context as parent if no explicit parent injector is specified.
|
|
62
|
+
*
|
|
63
|
+
* @docs-private Not public API. For internal use only.
|
|
64
|
+
*
|
|
65
|
+
* @param options - Configures the injector.
|
|
66
|
+
* @param options.parent - Specifies the parent injector. Defaults to the current injector.
|
|
67
|
+
* @param options.providers - Specifies providers to associate with the injector.
|
|
68
|
+
* @param options.name - Names the injector, useful for debugging the injector hierarchy.
|
|
69
|
+
*/
|
|
70
|
+
function createDestroyableInjector(options) {
|
|
71
|
+
const parentInjector = options?.parent ?? inject(Injector);
|
|
72
|
+
const injector = Injector.create({ parent: parentInjector, providers: options?.providers ?? [], name: options?.name });
|
|
73
|
+
// Destroy injector manually since not destroyed when the parent injector is destroyed.
|
|
74
|
+
// Angular only destroys child injectors in the scope of a component injector.
|
|
75
|
+
parentInjector.get(DestroyRef).onDestroy(() => injector.destroy());
|
|
76
|
+
// Patch `Injector.destroy` to not error if already destroyed.
|
|
77
|
+
const realDestroyFn = injector.destroy;
|
|
78
|
+
const destroyRef = injector.get(DestroyRef);
|
|
79
|
+
injector.destroy = () => !destroyRef.destroyed && realDestroyFn.apply(injector);
|
|
80
|
+
return injector;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Asserts that the current stack frame is within an injection context and has access to inject.
|
|
84
|
+
*
|
|
85
|
+
* Delegates to `assertInInjectionContext` from @angular/core, adding the given message to the error if the assertion fails.
|
|
86
|
+
*
|
|
87
|
+
* @docs-private Not public API. For internal use only.
|
|
88
|
+
*/
|
|
89
|
+
function assertInInjectionContext(debugFn, message) {
|
|
90
|
+
try {
|
|
91
|
+
assertInInjectionContext$1(debugFn);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throw Error([`${debugFn.name}() can only be used within an injection context.`].concat(message ? message : []).join(' '));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
100
|
+
*
|
|
101
|
+
* This program and the accompanying materials are made
|
|
102
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
103
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
104
|
+
*
|
|
105
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
106
|
+
*/
|
|
107
|
+
/**
|
|
108
|
+
* Use to add specified attributes to the host element.
|
|
109
|
+
*/
|
|
110
|
+
class SciAttributesDirective {
|
|
111
|
+
/**
|
|
112
|
+
* Specifies attributes to add to the host element.
|
|
113
|
+
*
|
|
114
|
+
* Attributes with `null` or `undefined` values are removed.
|
|
115
|
+
*/
|
|
116
|
+
attributes = input(undefined, { ...(ngDevMode ? { debugName: "attributes" } : /* istanbul ignore next */ {}), alias: 'sciAttributes' });
|
|
117
|
+
constructor() {
|
|
118
|
+
const host = inject(ElementRef).nativeElement;
|
|
119
|
+
const attributeDiffer = inject(IterableDiffers).find([]).create();
|
|
120
|
+
const renderer = inject(Renderer2);
|
|
121
|
+
effect(() => {
|
|
122
|
+
const attributes = this.attributes() ?? {};
|
|
123
|
+
untracked(() => {
|
|
124
|
+
// Delete removed attributes.
|
|
125
|
+
const diff = attributeDiffer.diff(Object.keys(attributes));
|
|
126
|
+
diff?.forEachRemovedItem(({ item: name }) => renderer.removeAttribute(host, name));
|
|
127
|
+
// Update added or changed attributes.
|
|
128
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
129
|
+
if (value !== undefined && value !== null) {
|
|
130
|
+
renderer.setAttribute(host, key, `${value}`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
renderer.removeAttribute(host, key);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciAttributesDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
140
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: SciAttributesDirective, isStandalone: true, selector: "[sciAttributes]", inputs: { attributes: { classPropertyName: "attributes", publicName: "sciAttributes", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
141
|
+
}
|
|
142
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciAttributesDirective, decorators: [{
|
|
143
|
+
type: Directive,
|
|
144
|
+
args: [{ selector: '[sciAttributes]' }]
|
|
145
|
+
}], ctorParameters: () => [], propDecorators: { attributes: [{ type: i0.Input, args: [{ isSignal: true, alias: "sciAttributes", required: false }] }] } });
|
|
146
|
+
|
|
147
|
+
/*
|
|
148
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
149
|
+
*
|
|
150
|
+
* This program and the accompanying materials are made
|
|
151
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
152
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
153
|
+
*
|
|
154
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
155
|
+
*/
|
|
156
|
+
/**
|
|
157
|
+
* Renders a component based on a descriptor, similar to `ngComponentOutlet`, but with input bindings.
|
|
158
|
+
*
|
|
159
|
+
* Usage:
|
|
160
|
+
*
|
|
161
|
+
* ```html
|
|
162
|
+
* <ng-container *sciComponentOutlet="descriptor"/>
|
|
163
|
+
* ````
|
|
164
|
+
*
|
|
165
|
+
* ```ts
|
|
166
|
+
* protected readonly descriptor: SciComponentDescriptor = {
|
|
167
|
+
* component: FilterComponent,
|
|
168
|
+
* bindings: [
|
|
169
|
+
* inputBinding('placeholder', signal('Filter items...')),
|
|
170
|
+
* ],
|
|
171
|
+
* };
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
class SciComponentOutletDirective {
|
|
175
|
+
/**
|
|
176
|
+
* Specifies the component to render.
|
|
177
|
+
*/
|
|
178
|
+
descriptor = input.required({ ...(ngDevMode ? { debugName: "descriptor" } : /* istanbul ignore next */ {}), alias: 'sciComponentOutlet' });
|
|
179
|
+
constructor() {
|
|
180
|
+
const viewContainerRef = inject(ViewContainerRef);
|
|
181
|
+
effect(onCleanup => {
|
|
182
|
+
const descriptor = this.descriptor();
|
|
183
|
+
untracked(() => {
|
|
184
|
+
const component = descriptor && createComponent(viewContainerRef, descriptor);
|
|
185
|
+
onCleanup(() => component?.destroy());
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciComponentOutletDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
190
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: SciComponentOutletDirective, isStandalone: true, selector: "ng-template[sciComponentOutlet]", inputs: { descriptor: { classPropertyName: "descriptor", publicName: "sciComponentOutlet", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
191
|
+
}
|
|
192
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciComponentOutletDirective, decorators: [{
|
|
193
|
+
type: Directive,
|
|
194
|
+
args: [{ selector: 'ng-template[sciComponentOutlet]' }]
|
|
195
|
+
}], ctorParameters: () => [], propDecorators: { descriptor: [{ type: i0.Input, args: [{ isSignal: true, alias: "sciComponentOutlet", required: true }] }] } });
|
|
196
|
+
/**
|
|
197
|
+
* Instantiates the specified component and inserts it after the specified view container.
|
|
198
|
+
*/
|
|
199
|
+
function createComponent(viewContainerRef, descriptor) {
|
|
200
|
+
// Provide providers via host directive.
|
|
201
|
+
class ProvidersDirective {
|
|
202
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ProvidersDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
203
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: ProvidersDirective, isStandalone: true, providers: descriptor.providers ?? [], ngImport: i0 });
|
|
204
|
+
}
|
|
205
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ProvidersDirective, decorators: [{
|
|
206
|
+
type: Directive,
|
|
207
|
+
args: [{ providers: descriptor.providers ?? [] }]
|
|
208
|
+
}] });
|
|
209
|
+
// Provide CSS classes via host directive.
|
|
210
|
+
class CssClassDirective {
|
|
211
|
+
cssClass = coerceSignal(descriptor.cssClass);
|
|
212
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CssClassDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
213
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: CssClassDirective, isStandalone: true, host: { properties: { "class": "cssClass?.()" } }, ngImport: i0 });
|
|
214
|
+
}
|
|
215
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: CssClassDirective, decorators: [{
|
|
216
|
+
type: Directive,
|
|
217
|
+
args: [{ host: { '[class]': 'cssClass?.()' } }]
|
|
218
|
+
}] });
|
|
219
|
+
return viewContainerRef.createComponent(descriptor.component, {
|
|
220
|
+
directives: [
|
|
221
|
+
ProvidersDirective,
|
|
222
|
+
CssClassDirective,
|
|
223
|
+
{ type: SciAttributesDirective, bindings: [inputBinding('sciAttributes', coerceSignal(descriptor.attributes ?? {}))] },
|
|
224
|
+
...descriptor.directives ?? [],
|
|
225
|
+
],
|
|
226
|
+
bindings: descriptor.bindings,
|
|
227
|
+
injector: descriptor.injector,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* Copyright (c) 2018-2026 Swiss Federal Railways
|
|
233
|
+
*
|
|
234
|
+
* This program and the accompanying materials are made
|
|
235
|
+
* available under the terms of the Eclipse Public License 2.0
|
|
236
|
+
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
237
|
+
*
|
|
238
|
+
* SPDX-License-Identifier: EPL-2.0
|
|
239
|
+
*/
|
|
240
|
+
/*
|
|
241
|
+
* Secondary entrypoint: '@scion/components/common'
|
|
242
|
+
*
|
|
243
|
+
* @see https://github.com/ng-packagr/ng-packagr/blob/master/docs/secondary-entrypoints.md
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generated bundle index. Do not edit.
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
export { SciAttributesDirective, SciComponentOutletDirective, assertInInjectionContext, coerceSignal, createDestroyableInjector, toLazyObservable };
|
|
251
|
+
//# sourceMappingURL=scion-components-common.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scion-components-common.mjs","sources":["../../../../projects/scion/components/common/src/signal.util.ts","../../../../projects/scion/components/common/src/injector.util.ts","../../../../projects/scion/components/common/src/attributes.directive.ts","../../../../projects/scion/components/common/src/component-outlet.directive.ts","../../../../projects/scion/components/common/src/public_api.ts","../../../../projects/scion/components/common/src/scion-components-common.ts"],"sourcesContent":["/*\n * Copyright (c) 2018-2026 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {effect, inject, Injector, isSignal, signal, Signal, untracked} from '@angular/core';\nimport {Observable, of} from 'rxjs';\n\n/**\n * Represents a value or a {@link Signal} of that value.\n */\nexport type MaybeSignal<T> = T | Signal<T>;\n\n/**\n * Coerces the given value into a {@link Signal}. If the value is already a signal, it is returned as-is; otherwise, it is wrapped in a signal.\n *\n * Passing `undefined` returns `undefined`, unless the option `coerceUndefined` is set to `true`.\n *\n * @param value - Specifies the value to coerece.\n */\nexport function coerceSignal<T extends MaybeSignal<unknown>>(value: T): T extends Signal<unknown> ? T : T extends undefined ? undefined : Signal<T>;\n/**\n * Coerces the given value into a {@link Signal}. If the value is already a signal, it is returned as-is; otherwise, it is wrapped in a signal.\n *\n * @param value - Specifies the value to coerece.\n * @param options - Controls coercion.\n * @param options.coerceUndefined - If `true`, returns `signal(undefined)` for a `undefined` value. Defaults to `false`.\n */\nexport function coerceSignal<T>(value: MaybeSignal<T> | undefined, options: {coerceUndefined: true}): Signal<T | undefined>;\n\nexport function coerceSignal<T>(value: MaybeSignal<T>, options?: {coerceUndefined?: true}): Signal<T> | undefined {\n if (value === undefined && !options?.coerceUndefined) {\n return undefined;\n }\n return isSignal(value) ? value : signal(value);\n}\n\n/**\n * Like {@link toObservable}, but lazily creates the effect upon subscription, binding it to the subscription lifecycle instead of the injection context, plus, emits the signal's initial value synchronously.\n */\nexport function toLazyObservable<T>(signal: MaybeSignal<NonNullable<T>>, options?: {injector?: Injector}): Observable<NonNullable<T>>;\nexport function toLazyObservable<T>(signal: MaybeSignal<NonNullable<T>> | undefined, options?: {injector?: Injector}): Observable<NonNullable<T>> | undefined;\nexport function toLazyObservable<T>(signal: MaybeSignal<NonNullable<T>> | undefined, options?: {injector?: Injector}): Observable<NonNullable<T>> | undefined {\n if (signal === undefined) {\n return undefined;\n }\n if (!isSignal(signal)) {\n return of(signal);\n }\n\n const injector = options?.injector ?? inject(Injector);\n return new Observable(observer => {\n const initialValue = signal();\n let isFirstEffectRun = true;\n\n // Emit initial value synchronously.\n observer.next(initialValue);\n\n const effectRef = effect(() => {\n const value = signal();\n\n untracked(() => {\n if (!isFirstEffectRun || initialValue !== value) {\n observer.next(value);\n }\n isFirstEffectRun = false;\n });\n }, {injector, manualCleanup: true});\n\n return () => effectRef.destroy();\n });\n}\n","/*\n * Copyright (c) 2018-2026 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {assertInInjectionContext as ngAssertInInjectionContext, DestroyableInjector, DestroyRef, inject, Injector, Provider} from '@angular/core';\n\n/**\n * Creates a {@link DestroyableInjector} bound to the lifecycle of its parent injector. Defaults to the current injector if not configuring a parent injector.\n *\n * Unlike injectors created via {@link Injector.create}, the returned injector:\n * - Is destroyed with its parent, also if used outside a component injection context.\n * - Does not throw an error when invoking {@link DestroyableInjector.destroy} if already destroyed.\n * - Uses the current injection context as parent if no explicit parent injector is specified.\n *\n * @docs-private Not public API. For internal use only.\n *\n * @param options - Configures the injector.\n * @param options.parent - Specifies the parent injector. Defaults to the current injector.\n * @param options.providers - Specifies providers to associate with the injector.\n * @param options.name - Names the injector, useful for debugging the injector hierarchy.\n */\nexport function createDestroyableInjector(options?: {parent?: Injector; providers?: Provider[]; name?: string}): DestroyableInjector {\n const parentInjector = options?.parent ?? inject(Injector);\n const injector = Injector.create({parent: parentInjector, providers: options?.providers ?? [], name: options?.name});\n\n // Destroy injector manually since not destroyed when the parent injector is destroyed.\n // Angular only destroys child injectors in the scope of a component injector.\n parentInjector.get(DestroyRef).onDestroy(() => injector.destroy());\n\n // Patch `Injector.destroy` to not error if already destroyed.\n const realDestroyFn = injector.destroy;\n const destroyRef = injector.get(DestroyRef);\n injector.destroy = () => !destroyRef.destroyed && realDestroyFn.apply(injector);\n return injector;\n}\n\n/**\n * Asserts that the current stack frame is within an injection context and has access to inject.\n *\n * Delegates to `assertInInjectionContext` from @angular/core, adding the given message to the error if the assertion fails.\n *\n * @docs-private Not public API. For internal use only.\n */\nexport function assertInInjectionContext(debugFn: Function, message: string): void { // eslint-disable-line @typescript-eslint/no-unsafe-function-type\n try {\n ngAssertInInjectionContext(debugFn);\n }\n catch {\n throw Error([`${debugFn.name}() can only be used within an injection context.`].concat(message ? message : []).join(' '));\n }\n}\n","/*\n * Copyright (c) 2018-2026 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Directive, effect, ElementRef, inject, input, IterableDiffers, Renderer2, untracked} from '@angular/core';\n\n/**\n * Use to add specified attributes to the host element.\n */\n@Directive({selector: '[sciAttributes]'})\nexport class SciAttributesDirective {\n\n /**\n * Specifies attributes to add to the host element.\n *\n * Attributes with `null` or `undefined` values are removed.\n */\n public readonly attributes = input<{[name: string]: unknown | undefined | null} | undefined | null>(undefined, {alias: 'sciAttributes'});\n\n constructor() {\n const host = inject(ElementRef).nativeElement as HTMLElement;\n const attributeDiffer = inject(IterableDiffers).find([]).create<string>();\n const renderer = inject(Renderer2);\n\n effect(() => {\n const attributes = this.attributes() ?? {};\n\n untracked(() => {\n // Delete removed attributes.\n const diff = attributeDiffer.diff(Object.keys(attributes));\n diff?.forEachRemovedItem(({item: name}) => renderer.removeAttribute(host, name));\n\n // Update added or changed attributes.\n Object.entries(attributes).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n renderer.setAttribute(host, key, `${value}`);\n }\n else {\n renderer.removeAttribute(host, key);\n }\n });\n });\n });\n }\n}\n","/*\n * Copyright (c) 2018-2026 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Binding, ComponentRef, Directive, effect, inject, Injector, input, inputBinding, Provider, Type, untracked, ViewContainerRef} from '@angular/core';\nimport {ComponentType} from '@angular/cdk/portal';\nimport {SciAttributesDirective} from './attributes.directive';\nimport {coerceSignal, MaybeSignal} from './signal.util';\n\n/**\n * Renders a component based on a descriptor, similar to `ngComponentOutlet`, but with input bindings.\n *\n * Usage:\n *\n * ```html\n * <ng-container *sciComponentOutlet=\"descriptor\"/>\n * ````\n *\n * ```ts\n * protected readonly descriptor: SciComponentDescriptor = {\n * component: FilterComponent,\n * bindings: [\n * inputBinding('placeholder', signal('Filter items...')),\n * ],\n * };\n * ```\n */\n@Directive({selector: 'ng-template[sciComponentOutlet]'})\nexport class SciComponentOutletDirective {\n\n /**\n * Specifies the component to render.\n */\n public readonly descriptor = input.required<SciComponentDescriptor | undefined | null>({alias: 'sciComponentOutlet'});\n\n constructor() {\n const viewContainerRef = inject(ViewContainerRef);\n\n effect(onCleanup => {\n const descriptor = this.descriptor();\n\n untracked(() => {\n const component = descriptor && createComponent(viewContainerRef, descriptor);\n onCleanup(() => component?.destroy());\n });\n });\n }\n}\n\n/**\n * Instantiates the specified component and inserts it after the specified view container.\n */\nfunction createComponent(viewContainerRef: ViewContainerRef, descriptor: SciComponentDescriptor): ComponentRef<unknown> {\n // Provide providers via host directive.\n @Directive({providers: descriptor.providers ?? []})\n class ProvidersDirective {\n }\n\n // Provide CSS classes via host directive.\n @Directive({host: {'[class]': 'cssClass?.()'}})\n class CssClassDirective {\n protected readonly cssClass = coerceSignal(descriptor.cssClass);\n }\n\n return viewContainerRef.createComponent(descriptor.component, {\n directives: [\n ProvidersDirective,\n CssClassDirective,\n {type: SciAttributesDirective, bindings: [inputBinding('sciAttributes', coerceSignal(descriptor.attributes ?? {}))]},\n ...descriptor.directives ?? [],\n ],\n bindings: descriptor.bindings,\n injector: descriptor.injector,\n });\n}\n\n/**\n * Describes the rendering of a component.\n */\nexport interface SciComponentDescriptor {\n /**\n * Specifies the component to render.\n */\n component: ComponentType<unknown>;\n /**\n * Specifies input and output bindings.\n *\n * @example - Passing inputs to the component\n * ```ts\n * bindings: [inputBinding('placeholder', signal('Filter items...'))];\n * ```\n *\n * Inputs are available as input properties in the component.\n *\n * @example - Reading inputs in the component\n * ```ts\n * public placeholder = input.required<string>();\n * ```\n *\n * @see inputBinding\n * @see outputBinding\n * @see twoWayBinding\n */\n bindings?: Binding[];\n /**\n * Specifies directives to be applied to the component.\n */\n directives?: Array<Type<unknown> | {type: Type<unknown>; bindings: Binding[]}>;\n /**\n * Specifies the injector used to instantiate the component, giving control over which objects are available for injection. Defaults to the element injector.\n *\n * ```ts\n * Injector.create({\n * parent: ...,\n * providers: [\n * {provide: <TOKEN>, useValue: <VALUE>}\n * ],\n * })\n * ```\n */\n injector?: Injector;\n /**\n * Specifies providers available for injection in the component.\n */\n providers?: Provider[];\n /**\n * Specifies CSS classes to associate with the component.\n */\n cssClass?: MaybeSignal<string | string[]>;\n /**\n * Specifies HTML attributes to associate with the component.\n *\n * Data attributes should start with the `data-` prefix.\n */\n attributes?: MaybeSignal<{[name: string]: string | undefined}>;\n}\n","/*\n * Copyright (c) 2018-2026 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\n/*\n * Secondary entrypoint: '@scion/components/common'\n *\n * @see https://github.com/ng-packagr/ng-packagr/blob/master/docs/secondary-entrypoints.md\n */\nexport {coerceSignal, type MaybeSignal, toLazyObservable} from './signal.util';\nexport {createDestroyableInjector, assertInInjectionContext} from './injector.util';\nexport {type SciComponentDescriptor, SciComponentOutletDirective} from './component-outlet.directive';\nexport {SciAttributesDirective} from './attributes.directive';\nexport {type SciTemplateDescriptor} from './template-descriptor';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["ngAssertInInjectionContext"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, inject, ElementRef, NgZone, ɵZONELESS_ENABLED as _ZONELESS_ENABLED, Directive, assertNotInReactiveContext,
|
|
2
|
+
import { input, output, inject, ElementRef, NgZone, ɵZONELESS_ENABLED as _ZONELESS_ENABLED, Directive, assertNotInReactiveContext, Injector, computed, isSignal, signal, effect, untracked } from '@angular/core';
|
|
3
3
|
import { fromResize$, fromBoundingClientRect$ } from '@scion/toolkit/observable';
|
|
4
4
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
5
|
import { subscribeIn, observeIn } from '@scion/toolkit/operators';
|
|
6
6
|
import { coerceElement } from '@angular/cdk/coercion';
|
|
7
7
|
import { Objects } from '@scion/toolkit/util';
|
|
8
|
+
import { assertInInjectionContext } from '@scion/components/common';
|
|
8
9
|
|
|
9
10
|
/*
|
|
10
11
|
* Copyright (c) 2018-2024 Swiss Federal Railways
|
|
@@ -61,10 +62,10 @@ class SciDimensionDirective {
|
|
|
61
62
|
});
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
65
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
65
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciDimensionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
66
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: SciDimensionDirective, isStandalone: true, selector: "[sciDimension]", inputs: { emitOutsideAngular: { classPropertyName: "emitOutsideAngular", publicName: "emitOutsideAngular", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dimensionChange: "sciDimensionChange" }, ngImport: i0 });
|
|
66
67
|
}
|
|
67
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
68
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SciDimensionDirective, decorators: [{
|
|
68
69
|
type: Directive,
|
|
69
70
|
args: [{
|
|
70
71
|
selector: '[sciDimension]',
|
|
@@ -83,7 +84,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
83
84
|
function dimension(elementLike, options) {
|
|
84
85
|
assertNotInReactiveContext(dimension, 'Invoking `dimension` causes new subscriptions every time. Move `dimension` outside of the reactive context and read the signal value where needed.');
|
|
85
86
|
if (!options?.injector) {
|
|
86
|
-
assertInInjectionContext(dimension);
|
|
87
|
+
assertInInjectionContext(dimension, 'Must be called within an injection context, or an explicit `Injector` passed via options. Stops tracking the dimension when the injection context is destroyed.');
|
|
87
88
|
}
|
|
88
89
|
const injector = options?.injector ?? inject(Injector);
|
|
89
90
|
const zone = injector.get(NgZone);
|
|
@@ -142,7 +143,7 @@ function dimension(elementLike, options) {
|
|
|
142
143
|
function boundingClientRect(elementLike, options) {
|
|
143
144
|
assertNotInReactiveContext(boundingClientRect, 'Invoking `boundingClientRect` causes new subscriptions every time. Move `boundingClientRect` outside of the reactive context and read the signal value where needed.');
|
|
144
145
|
if (!options?.injector) {
|
|
145
|
-
assertInInjectionContext(boundingClientRect);
|
|
146
|
+
assertInInjectionContext(boundingClientRect, 'Must be called within an injection context, or an explicit `Injector` passed via options. Stops tracking the bounding box when the injection context is destroyed.');
|
|
146
147
|
}
|
|
147
148
|
const injector = options?.injector ?? inject(Injector);
|
|
148
149
|
const zone = injector.get(NgZone);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scion-components-dimension.mjs","sources":["../../../../projects/scion/components/dimension/src/dimension.directive.ts","../../../../projects/scion/components/dimension/src/dimension.signal.ts","../../../../projects/scion/components/dimension/src/bounding-client-rect.signal.ts","../../../../projects/scion/components/dimension/src/public_api.ts","../../../../projects/scion/components/dimension/src/scion-components-dimension.ts"],"sourcesContent":["/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Directive, ElementRef, inject, input, NgZone, output, ɵZONELESS_ENABLED} from '@angular/core';\nimport {fromResize$} from '@scion/toolkit/observable';\nimport {takeUntilDestroyed} from '@angular/core/rxjs-interop';\nimport {observeIn, subscribeIn} from '@scion/toolkit/operators';\nimport {SciDimension} from './dimension';\n\n/**\n * Observes the size of the host element.\n *\n * ---\n * Usage:\n *\n * ```html\n * <div sciDimension (sciDimensionChange)=\"onDimensionChange($event)\"></div>\n * ```\n */\n@Directive({\n selector: '[sciDimension]',\n})\nexport class SciDimensionDirective {\n\n /**\n * Controls if to output outside the Angular zone. Defaults to `false`.\n */\n public readonly emitOutsideAngular = input(false);\n\n /**\n * Outputs the size of the element.\n */\n public readonly dimensionChange = output<SciDimension>({alias: 'sciDimensionChange'});\n\n constructor() {\n const host = inject(ElementRef).nativeElement as HTMLElement;\n const zone = inject(NgZone);\n const zonelessEnabled = inject(ɵZONELESS_ENABLED);\n\n fromResize$(host)\n .pipe(\n // Avoid triggering change detection cycle.\n subscribeIn(fn => zone.runOutsideAngular(fn)),\n // Run in animation frame to prevent 'ResizeObserver loop completed with undelivered notifications' error.\n // Do not use `animationFrameScheduler` because the scheduler does not necessarily execute in the current execution context, such as inside or outside Angular.\n // The scheduler always executes tasks in the context (e.g. zone) where the scheduler was first used in the application.\n observeIn(fn => requestAnimationFrame(fn)),\n observeIn(fn => this.emitOutsideAngular() ? fn() : zone.run(fn)),\n takeUntilDestroyed(),\n )\n .subscribe(() => {\n if (!zonelessEnabled) {\n // Assert Angular zone.\n this.emitOutsideAngular() ? NgZone.assertNotInAngularZone() : NgZone.assertInAngularZone();\n }\n\n this.dimensionChange.emit({\n clientWidth: host.clientWidth,\n offsetWidth: host.offsetWidth,\n clientHeight: host.clientHeight,\n offsetHeight: host.offsetHeight,\n element: host,\n });\n });\n }\n}\n","/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {assertInInjectionContext, assertNotInReactiveContext, computed, effect, ElementRef, inject, Injector, isSignal, NgZone, signal, Signal, untracked} from '@angular/core';\nimport {SciDimension} from './dimension';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {Objects} from '@scion/toolkit/util';\nimport {fromResize$} from '@scion/toolkit/observable';\nimport {observeIn, subscribeIn} from '@scion/toolkit/operators';\n\n/**\n * Creates a signal observing the size of an element.\n *\n * The element can be passed as a signal, enabling observation of view children in the component constructor.\n *\n * The signal subscribes to the native {@link ResizeObserver} to monitor element size changes. Destroying the injection context will unsubscribe the observer.\n *\n * Usage:\n * - Must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.\n * - Must not be called within a reactive context to avoid repeated subscriptions.\n */\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement>>, options?: {injector?: Injector}): Signal<SciDimension>;\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<SciDimension | undefined>;\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<SciDimension | undefined> {\n assertNotInReactiveContext(dimension, 'Invoking `dimension` causes new subscriptions every time. Move `dimension` outside of the reactive context and read the signal value where needed.');\n if (!options?.injector) {\n assertInInjectionContext(dimension);\n }\n\n const injector = options?.injector ?? inject(Injector);\n const zone = injector.get(NgZone);\n const element = computed(() => coerceElement(isSignal(elementLike) ? elementLike() : elementLike));\n const onResize = signal<void>(undefined, {equal: () => false});\n\n // Subscribe to element size changes.\n effect(onCleanup => {\n const el = element();\n if (!el) {\n return;\n }\n\n untracked(() => {\n const subscription = fromResize$(el)\n .pipe(\n // Avoid triggering change detection cycle.\n subscribeIn(fn => zone.runOutsideAngular(fn)),\n // Run in animation frame to prevent 'ResizeObserver loop completed with undelivered notifications' error.\n // Do not use `animationFrameScheduler` because the scheduler does not necessarily execute in the current execution context, such as inside or outside Angular.\n // The scheduler always executes tasks in the context (e.g. zone) where the scheduler was first used in the application.\n observeIn(fn => requestAnimationFrame(fn)),\n )\n .subscribe(() => {\n NgZone.assertNotInAngularZone();\n onResize.set();\n });\n onCleanup(() => subscription.unsubscribe());\n });\n }, {injector});\n\n // Create signal that recomputes each time the size changes.\n return computed(() => {\n const el = element();\n if (!el) {\n return undefined;\n }\n\n // Track element size.\n onResize();\n\n return {\n clientWidth: el.clientWidth,\n offsetWidth: el.offsetWidth,\n clientHeight: el.clientHeight,\n offsetHeight: el.offsetHeight,\n element: el,\n };\n }, {equal: Objects.isEqual});\n}\n","/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {assertInInjectionContext, assertNotInReactiveContext, computed, effect, ElementRef, inject, Injector, isSignal, NgZone, signal, Signal, untracked} from '@angular/core';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {fromBoundingClientRect$} from '@scion/toolkit/observable';\nimport {subscribeIn} from '@scion/toolkit/operators';\n\n/**\n * Creates a signal observing the bounding box of an element.\n *\n * The bounding box includes the element's position relative to the top-left of the viewport and its size.\n * Refer to https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect for more details.\n *\n * The element can be passed as a signal, enabling observation of view children in the component constructor.\n *\n * There is no native browser API to observe the position of an element. The signal uses {@link IntersectionObserver} and\n * {@link ResizeObserver} to detect position changes. For tracking only size changes, use the {@link dimension} signal instead.\n *\n * Usage:\n * - Must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.\n * - Must not be called within a reactive context to avoid repeated subscriptions.\n * - The element and the document root (`<html>`) must be positioned `relative` or `absolute`. If not, positioning is changed to `relative`.\n */\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement>>, options?: {injector?: Injector}): Signal<DOMRect>;\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<DOMRect | undefined>;\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<DOMRect | undefined> {\n assertNotInReactiveContext(boundingClientRect, 'Invoking `boundingClientRect` causes new subscriptions every time. Move `boundingClientRect` outside of the reactive context and read the signal value where needed.');\n if (!options?.injector) {\n assertInInjectionContext(boundingClientRect);\n }\n\n const injector = options?.injector ?? inject(Injector);\n const zone = injector.get(NgZone);\n const element = computed(() => coerceElement(isSignal(elementLike) ? elementLike() : elementLike));\n const onBoundingBoxChange = signal<void>(undefined, {equal: () => false});\n\n // Subscribe to element bounding box changes.\n effect(onCleanup => {\n const el = element();\n if (!el) {\n return;\n }\n\n untracked(() => {\n const subscription = fromBoundingClientRect$(el)\n // Avoid triggering change detection cycle.\n .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)))\n .subscribe(() => {\n NgZone.assertNotInAngularZone();\n onBoundingBoxChange.set();\n });\n onCleanup(() => subscription.unsubscribe());\n });\n }, {injector});\n\n // Create signal that recomputes each time the bounding box changes.\n return computed(() => {\n const el = element();\n if (!el) {\n return undefined;\n }\n\n // Track bounding box.\n onBoundingBoxChange();\n\n return el.getBoundingClientRect();\n }, {equal: isEqualDomRect});\n}\n\nfunction isEqualDomRect(a: DOMRect | undefined, b: DOMRect | undefined): boolean {\n return a?.top === b?.top && a?.right === b?.right && a?.bottom === b?.bottom && a?.left === b?.left;\n}\n","/*\n * Copyright (c) 2018-2019 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\n/*\n * Secondary entrypoint: '@scion/components/dimension'\n *\n * @see https://github.com/ng-packagr/ng-packagr/blob/master/docs/secondary-entrypoints.md\n */\nexport {SciDimensionDirective} from './dimension.directive';\nexport {dimension} from './dimension.signal';\nexport {boundingClientRect} from './bounding-client-rect.signal';\nexport {type SciDimension} from './dimension';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["ɵZONELESS_ENABLED"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scion-components-dimension.mjs","sources":["../../../../projects/scion/components/dimension/src/dimension.directive.ts","../../../../projects/scion/components/dimension/src/dimension.signal.ts","../../../../projects/scion/components/dimension/src/bounding-client-rect.signal.ts","../../../../projects/scion/components/dimension/src/public_api.ts","../../../../projects/scion/components/dimension/src/scion-components-dimension.ts"],"sourcesContent":["/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {Directive, ElementRef, inject, input, NgZone, output, ɵZONELESS_ENABLED} from '@angular/core';\nimport {fromResize$} from '@scion/toolkit/observable';\nimport {takeUntilDestroyed} from '@angular/core/rxjs-interop';\nimport {observeIn, subscribeIn} from '@scion/toolkit/operators';\nimport {SciDimension} from './dimension';\n\n/**\n * Observes the size of the host element.\n *\n * ---\n * Usage:\n *\n * ```html\n * <div sciDimension (sciDimensionChange)=\"onDimensionChange($event)\"></div>\n * ```\n */\n@Directive({\n selector: '[sciDimension]',\n})\nexport class SciDimensionDirective {\n\n /**\n * Controls if to output outside the Angular zone. Defaults to `false`.\n */\n public readonly emitOutsideAngular = input(false);\n\n /**\n * Outputs the size of the element.\n */\n public readonly dimensionChange = output<SciDimension>({alias: 'sciDimensionChange'});\n\n constructor() {\n const host = inject(ElementRef).nativeElement as HTMLElement;\n const zone = inject(NgZone);\n const zonelessEnabled = inject(ɵZONELESS_ENABLED);\n\n fromResize$(host)\n .pipe(\n // Avoid triggering change detection cycle.\n subscribeIn(fn => zone.runOutsideAngular(fn)),\n // Run in animation frame to prevent 'ResizeObserver loop completed with undelivered notifications' error.\n // Do not use `animationFrameScheduler` because the scheduler does not necessarily execute in the current execution context, such as inside or outside Angular.\n // The scheduler always executes tasks in the context (e.g. zone) where the scheduler was first used in the application.\n observeIn(fn => requestAnimationFrame(fn)),\n observeIn(fn => this.emitOutsideAngular() ? fn() : zone.run(fn)),\n takeUntilDestroyed(),\n )\n .subscribe(() => {\n if (!zonelessEnabled) {\n // Assert Angular zone.\n this.emitOutsideAngular() ? NgZone.assertNotInAngularZone() : NgZone.assertInAngularZone();\n }\n\n this.dimensionChange.emit({\n clientWidth: host.clientWidth,\n offsetWidth: host.offsetWidth,\n clientHeight: host.clientHeight,\n offsetHeight: host.offsetHeight,\n element: host,\n });\n });\n }\n}\n","/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {assertNotInReactiveContext, computed, effect, ElementRef, inject, Injector, isSignal, NgZone, signal, Signal, untracked} from '@angular/core';\nimport {SciDimension} from './dimension';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {Objects} from '@scion/toolkit/util';\nimport {fromResize$} from '@scion/toolkit/observable';\nimport {observeIn, subscribeIn} from '@scion/toolkit/operators';\nimport {assertInInjectionContext} from '@scion/components/common';\n\n/**\n * Creates a signal observing the size of an element.\n *\n * The element can be passed as a signal, enabling observation of view children in the component constructor.\n *\n * The signal subscribes to the native {@link ResizeObserver} to monitor element size changes. Destroying the injection context will unsubscribe the observer.\n *\n * Usage:\n * - Must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.\n * - Must not be called within a reactive context to avoid repeated subscriptions.\n */\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement>>, options?: {injector?: Injector}): Signal<SciDimension>;\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<SciDimension | undefined>;\nexport function dimension(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<SciDimension | undefined> {\n assertNotInReactiveContext(dimension, 'Invoking `dimension` causes new subscriptions every time. Move `dimension` outside of the reactive context and read the signal value where needed.');\n if (!options?.injector) {\n assertInInjectionContext(dimension, 'Must be called within an injection context, or an explicit `Injector` passed via options. Stops tracking the dimension when the injection context is destroyed.');\n }\n\n const injector = options?.injector ?? inject(Injector);\n const zone = injector.get(NgZone);\n const element = computed(() => coerceElement(isSignal(elementLike) ? elementLike() : elementLike));\n const onResize = signal<void>(undefined, {equal: () => false});\n\n // Subscribe to element size changes.\n effect(onCleanup => {\n const el = element();\n if (!el) {\n return;\n }\n\n untracked(() => {\n const subscription = fromResize$(el)\n .pipe(\n // Avoid triggering change detection cycle.\n subscribeIn(fn => zone.runOutsideAngular(fn)),\n // Run in animation frame to prevent 'ResizeObserver loop completed with undelivered notifications' error.\n // Do not use `animationFrameScheduler` because the scheduler does not necessarily execute in the current execution context, such as inside or outside Angular.\n // The scheduler always executes tasks in the context (e.g. zone) where the scheduler was first used in the application.\n observeIn(fn => requestAnimationFrame(fn)),\n )\n .subscribe(() => {\n NgZone.assertNotInAngularZone();\n onResize.set();\n });\n onCleanup(() => subscription.unsubscribe());\n });\n }, {injector});\n\n // Create signal that recomputes each time the size changes.\n return computed(() => {\n const el = element();\n if (!el) {\n return undefined;\n }\n\n // Track element size.\n onResize();\n\n return {\n clientWidth: el.clientWidth,\n offsetWidth: el.offsetWidth,\n clientHeight: el.clientHeight,\n offsetHeight: el.offsetHeight,\n element: el,\n };\n }, {equal: Objects.isEqual});\n}\n","/*\n * Copyright (c) 2018-2024 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\nimport {assertNotInReactiveContext, computed, effect, ElementRef, inject, Injector, isSignal, NgZone, signal, Signal, untracked} from '@angular/core';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {fromBoundingClientRect$} from '@scion/toolkit/observable';\nimport {subscribeIn} from '@scion/toolkit/operators';\nimport {assertInInjectionContext} from '@scion/components/common';\n\n/**\n * Creates a signal observing the bounding box of an element.\n *\n * The bounding box includes the element's position relative to the top-left of the viewport and its size.\n * Refer to https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect for more details.\n *\n * The element can be passed as a signal, enabling observation of view children in the component constructor.\n *\n * There is no native browser API to observe the position of an element. The signal uses {@link IntersectionObserver} and\n * {@link ResizeObserver} to detect position changes. For tracking only size changes, use the {@link dimension} signal instead.\n *\n * Usage:\n * - Must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.\n * - Must not be called within a reactive context to avoid repeated subscriptions.\n * - The element and the document root (`<html>`) must be positioned `relative` or `absolute`. If not, positioning is changed to `relative`.\n */\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement>>, options?: {injector?: Injector}): Signal<DOMRect>;\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<DOMRect | undefined>;\nexport function boundingClientRect(elementLike: HTMLElement | ElementRef<HTMLElement> | Signal<HTMLElement | ElementRef<HTMLElement> | undefined>, options?: {injector?: Injector}): Signal<DOMRect | undefined> {\n assertNotInReactiveContext(boundingClientRect, 'Invoking `boundingClientRect` causes new subscriptions every time. Move `boundingClientRect` outside of the reactive context and read the signal value where needed.');\n if (!options?.injector) {\n assertInInjectionContext(boundingClientRect, 'Must be called within an injection context, or an explicit `Injector` passed via options. Stops tracking the bounding box when the injection context is destroyed.');\n }\n\n const injector = options?.injector ?? inject(Injector);\n const zone = injector.get(NgZone);\n const element = computed(() => coerceElement(isSignal(elementLike) ? elementLike() : elementLike));\n const onBoundingBoxChange = signal<void>(undefined, {equal: () => false});\n\n // Subscribe to element bounding box changes.\n effect(onCleanup => {\n const el = element();\n if (!el) {\n return;\n }\n\n untracked(() => {\n const subscription = fromBoundingClientRect$(el)\n // Avoid triggering change detection cycle.\n .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)))\n .subscribe(() => {\n NgZone.assertNotInAngularZone();\n onBoundingBoxChange.set();\n });\n onCleanup(() => subscription.unsubscribe());\n });\n }, {injector});\n\n // Create signal that recomputes each time the bounding box changes.\n return computed(() => {\n const el = element();\n if (!el) {\n return undefined;\n }\n\n // Track bounding box.\n onBoundingBoxChange();\n\n return el.getBoundingClientRect();\n }, {equal: isEqualDomRect});\n}\n\nfunction isEqualDomRect(a: DOMRect | undefined, b: DOMRect | undefined): boolean {\n return a?.top === b?.top && a?.right === b?.right && a?.bottom === b?.bottom && a?.left === b?.left;\n}\n","/*\n * Copyright (c) 2018-2019 Swiss Federal Railways\n *\n * This program and the accompanying materials are made\n * available under the terms of the Eclipse Public License 2.0\n * which is available at https://www.eclipse.org/legal/epl-2.0/\n *\n * SPDX-License-Identifier: EPL-2.0\n */\n\n/*\n * Secondary entrypoint: '@scion/components/dimension'\n *\n * @see https://github.com/ng-packagr/ng-packagr/blob/master/docs/secondary-entrypoints.md\n */\nexport {SciDimensionDirective} from './dimension.directive';\nexport {dimension} from './dimension.signal';\nexport {boundingClientRect} from './bounding-client-rect.signal';\nexport {type SciDimension} from './dimension';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["ɵZONELESS_ENABLED"],"mappings":"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"}
|