@shimmer-from-structure/angular 2.2.3 → 2.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.
@@ -0,0 +1,277 @@
1
+ import {
2
+ Component,
3
+ input,
4
+ signal,
5
+ computed,
6
+ effect,
7
+ ElementRef,
8
+ viewChild,
9
+ AfterViewInit,
10
+ OnDestroy,
11
+ ChangeDetectionStrategy,
12
+ ViewEncapsulation,
13
+ inject,
14
+ PLATFORM_ID,
15
+ } from '@angular/core';
16
+ import { NgIf, NgFor, isPlatformBrowser } from '@angular/common';
17
+ import {
18
+ extractElementInfo,
19
+ createResizeObserver,
20
+ type ElementInfo,
21
+ } from '@shimmer-from-structure/core';
22
+ import { injectShimmerConfig } from './shimmer-config.service';
23
+
24
+ /**
25
+ * Shimmer component that creates loading skeleton overlays based on content structure.
26
+ * Automatically measures projected content and creates matching shimmer blocks.
27
+ *
28
+ * @example
29
+ * ```html
30
+ * <shimmer [loading]="isLoading">
31
+ * <div class="card">
32
+ * <h2>{{ title }}</h2>
33
+ * <p>{{ description }}</p>
34
+ * </div>
35
+ * </shimmer>
36
+ * ```
37
+ */
38
+ @Component({
39
+ selector: 'shimmer',
40
+ standalone: true,
41
+ imports: [NgIf, NgFor],
42
+ changeDetection: ChangeDetectionStrategy.OnPush,
43
+ encapsulation: ViewEncapsulation.None,
44
+ template: `
45
+ <div style="position: relative;">
46
+ <!-- Always render content -->
47
+ <div
48
+ #measureContainer
49
+ [class.shimmer-measure-container]="loading()"
50
+ [attr.aria-hidden]="loading() ? 'true' : null"
51
+ [style.pointer-events]="loading() ? 'none' : null"
52
+ >
53
+ <ng-content></ng-content>
54
+ </div>
55
+
56
+ <!-- Shimmer overlay - only when loading -->
57
+ @if (loading()) {
58
+ <div
59
+ style="
60
+ position: absolute;
61
+ top: 0;
62
+ left: 0;
63
+ right: 0;
64
+ bottom: 0;
65
+ overflow: hidden;
66
+ pointer-events: none;
67
+ "
68
+ >
69
+ @for (element of elements(); track $index) {
70
+ <div
71
+ [style.position]="'absolute'"
72
+ [style.left.px]="element.x"
73
+ [style.top.px]="element.y"
74
+ [style.width.px]="element.width"
75
+ [style.height.px]="element.height"
76
+ [style.backgroundColor]="resolvedBackgroundColor()"
77
+ [style.borderRadius]="
78
+ element.borderRadius === '0px'
79
+ ? resolvedFallbackBorderRadius() + 'px'
80
+ : element.borderRadius
81
+ "
82
+ [style.overflow]="'hidden'"
83
+ >
84
+ <div
85
+ class="shimmer-animation-element"
86
+ [style.background]="
87
+ 'linear-gradient(90deg, transparent, ' + resolvedShimmerColor() + ', transparent)'
88
+ "
89
+ [style.animationDuration]="resolvedDuration() + 's'"
90
+ ></div>
91
+ </div>
92
+ }
93
+ </div>
94
+ }
95
+ </div>
96
+ `,
97
+ styles: [
98
+ `
99
+ :host {
100
+ display: contents;
101
+ }
102
+
103
+ .shimmer-measure-container * {
104
+ color: transparent !important;
105
+ }
106
+
107
+ .shimmer-measure-container img,
108
+ .shimmer-measure-container svg,
109
+ .shimmer-measure-container video {
110
+ opacity: 0;
111
+ }
112
+
113
+ .shimmer-animation-element {
114
+ position: absolute;
115
+ top: 0;
116
+ left: 0;
117
+ width: 100%;
118
+ height: 100%;
119
+ animation: shimmer-animation 1.5s infinite;
120
+ }
121
+
122
+ @keyframes shimmer-animation {
123
+ 0% {
124
+ transform: translateX(-100%);
125
+ }
126
+ 100% {
127
+ transform: translateX(100%);
128
+ }
129
+ }
130
+ `,
131
+ ],
132
+ })
133
+ export class ShimmerComponent implements AfterViewInit, OnDestroy {
134
+ // Inputs using Angular signals
135
+ loading = input<boolean>(true);
136
+ shimmerColor = input<string | undefined>(undefined);
137
+ backgroundColor = input<string | undefined>(undefined);
138
+ duration = input<number | undefined>(undefined);
139
+ fallbackBorderRadius = input<number | undefined>(undefined);
140
+
141
+ // View child reference
142
+ measureContainer = viewChild<ElementRef<HTMLDivElement>>('measureContainer');
143
+
144
+ // Internal state
145
+ elements = signal<ElementInfo[]>([]);
146
+
147
+ // Inject dependencies
148
+ private contextConfig = injectShimmerConfig();
149
+ private platformId = inject(PLATFORM_ID);
150
+ private isBrowser = isPlatformBrowser(this.platformId);
151
+
152
+ // Resolved values (props > context > defaults)
153
+ resolvedShimmerColor = computed(() => this.shimmerColor() ?? this.contextConfig.shimmerColor);
154
+ resolvedBackgroundColor = computed(
155
+ () => this.backgroundColor() ?? this.contextConfig.backgroundColor
156
+ );
157
+ resolvedDuration = computed(() => this.duration() ?? this.contextConfig.duration);
158
+ resolvedFallbackBorderRadius = computed(
159
+ () => this.fallbackBorderRadius() ?? this.contextConfig.fallbackBorderRadius
160
+ );
161
+
162
+ // Cleanup function for ResizeObserver
163
+ private resizeCleanup: (() => void) | undefined;
164
+ private mutationObserver: MutationObserver | undefined;
165
+
166
+ constructor() {
167
+ // Effect to re-measure when loading state changes
168
+ effect((onCleanup) => {
169
+ // Skip effect on server
170
+ if (!this.isBrowser) return;
171
+
172
+ const isLoading = this.loading();
173
+ const container = this.measureContainer();
174
+
175
+ if (isLoading && container) {
176
+ // Clean up existing observers before setting up new ones
177
+ this.cleanup();
178
+
179
+ // Set up observers for this loading session
180
+ this.setupObservers();
181
+
182
+ // Defer measurement to next frame to ensure content is rendered
183
+ requestAnimationFrame(() => this.measureElements());
184
+ } else {
185
+ // Cleanup when not loading
186
+ this.cleanup();
187
+ }
188
+
189
+ // Cleanup on effect re-run or component destruction
190
+ onCleanup(() => {
191
+ this.cleanup();
192
+ });
193
+ });
194
+ }
195
+
196
+ ngAfterViewInit(): void {
197
+ // Effect will handle setup when container becomes available
198
+ }
199
+
200
+ ngOnDestroy(): void {
201
+ this.cleanup();
202
+ }
203
+
204
+ private setupObservers(): void {
205
+ if (!this.isBrowser) return;
206
+
207
+ const container = this.measureContainer()?.nativeElement;
208
+ if (!container) return;
209
+
210
+ // Set up ResizeObserver
211
+ this.resizeCleanup = createResizeObserver(container, () => this.measureElements());
212
+
213
+ // Set up MutationObserver for content changes
214
+ this.mutationObserver = new MutationObserver(() => {
215
+ if (this.loading()) {
216
+ this.measureElements();
217
+ }
218
+ });
219
+
220
+ this.mutationObserver.observe(container, {
221
+ childList: true,
222
+ subtree: true,
223
+ characterData: true,
224
+ attributes: false,
225
+ });
226
+ }
227
+
228
+ private measureElements(): void {
229
+ if (!this.isBrowser) return;
230
+
231
+ const container = this.measureContainer()?.nativeElement;
232
+ if (!container || !this.loading()) return;
233
+
234
+ // Temporarily disconnect mutation observer to avoid recursion
235
+ this.mutationObserver?.disconnect();
236
+
237
+ const containerRect = container.getBoundingClientRect();
238
+ const extractedElements: ElementInfo[] = [];
239
+
240
+ Array.from(container.children).forEach((child) => {
241
+ extractedElements.push(...extractElementInfo(child, containerRect));
242
+ });
243
+
244
+ this.elements.set(extractedElements);
245
+
246
+ // Reconnect mutation observer
247
+ if (this.mutationObserver && container) {
248
+ this.mutationObserver.observe(container, {
249
+ childList: true,
250
+ subtree: true,
251
+ characterData: true,
252
+ attributes: false,
253
+ });
254
+ }
255
+ }
256
+
257
+ private cleanup(): void {
258
+ if (this.resizeCleanup) {
259
+ this.resizeCleanup();
260
+ this.resizeCleanup = undefined;
261
+ }
262
+ if (this.mutationObserver) {
263
+ this.mutationObserver.disconnect();
264
+ this.mutationObserver = undefined;
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Manually trigger re-measurement of elements.
270
+ * Useful when content changes programmatically.
271
+ */
272
+ remeasure(): void {
273
+ if (this.isBrowser) {
274
+ this.measureElements();
275
+ }
276
+ }
277
+ }
@@ -0,0 +1,52 @@
1
+ import 'zone.js';
2
+ import 'zone.js/testing';
3
+ import { vi, beforeAll } from 'vitest';
4
+ import { TestBed } from '@angular/core/testing';
5
+ import {
6
+ BrowserDynamicTestingModule,
7
+ platformBrowserDynamicTesting,
8
+ } from '@angular/platform-browser-dynamic/testing';
9
+
10
+ beforeAll(() => {
11
+ TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
12
+ });
13
+
14
+ // Mock getBoundingClientRect since jsdom doesn't support layout
15
+ Element.prototype.getBoundingClientRect = vi.fn(() => ({
16
+ width: 100,
17
+ height: 50,
18
+ top: 0,
19
+ left: 0,
20
+ bottom: 50,
21
+ right: 100,
22
+ x: 0,
23
+ y: 0,
24
+ toJSON: () => {},
25
+ }));
26
+
27
+ // Mock ResizeObserver
28
+ global.ResizeObserver = class ResizeObserver {
29
+ observe() {}
30
+ unobserve() {}
31
+ disconnect() {}
32
+ };
33
+
34
+ // Mock getComputedStyle
35
+ const originalGetComputedStyle = window.getComputedStyle;
36
+ window.getComputedStyle = (elt) => {
37
+ const styles = originalGetComputedStyle(elt);
38
+ // Add borderRadius support for our tests
39
+ if (!styles.borderRadius) {
40
+ Object.defineProperty(styles, 'borderRadius', {
41
+ value: '4px',
42
+ writable: true,
43
+ });
44
+ }
45
+ return styles;
46
+ };
47
+
48
+ // Mock requestAnimationFrame
49
+ global.requestAnimationFrame = (cb) => {
50
+ setTimeout(cb, 0);
51
+ return 0;
52
+ };
package/src/types.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Input properties for the Shimmer component
3
+ */
4
+ export interface ShimmerInputs {
5
+ /**
6
+ * Whether the component is in loading state
7
+ * @default true
8
+ */
9
+ loading?: boolean;
10
+
11
+ /**
12
+ * Color of the shimmer effect gradient
13
+ */
14
+ shimmerColor?: string;
15
+
16
+ /**
17
+ * Background color of the shimmer blocks
18
+ */
19
+ backgroundColor?: string;
20
+
21
+ /**
22
+ * Duration of one shimmer animation cycle in seconds
23
+ */
24
+ duration?: number;
25
+
26
+ /**
27
+ * Fallback border radius (in pixels) when element has no border-radius
28
+ * @default 4
29
+ */
30
+ fallbackBorderRadius?: number;
31
+ }
32
+
33
+ // Re-export core types for convenience
34
+ export type { ShimmerConfig, ShimmerContextValue, ElementInfo } from '@shimmer-from-structure/core';
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src/**/*.ts", "vitest.config.ts"],
4
+ "exclude": ["node_modules", "dist"]
5
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "experimentalDecorators": true,
8
+ "emitDecoratorMetadata": true,
9
+ "target": "ES2022",
10
+ "module": "ES2022",
11
+ "moduleResolution": "bundler",
12
+ "useDefineForClassFields": false,
13
+ "lib": ["ES2022", "DOM"]
14
+ },
15
+ "include": ["src/**/*.ts"],
16
+ "exclude": ["src/**/*.test.ts", "node_modules", "dist"]
17
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ pool: 'threads',
6
+ globals: true,
7
+ environment: 'jsdom',
8
+ setupFiles: './src/test/setup.ts',
9
+ include: ['src/**/*.test.ts'],
10
+ css: true,
11
+ },
12
+ });
@@ -1,298 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, input, viewChild, signal, PLATFORM_ID, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { isPlatformBrowser, NgIf, NgFor } from '@angular/common';
4
- import { shimmerDefaults, createResizeObserver, extractElementInfo } from '@shimmer-from-structure/core';
5
- export { shimmerDefaults } from '@shimmer-from-structure/core';
6
-
7
- /**
8
- * Injection token for global shimmer configuration.
9
- * Use `provideShimmerConfig()` to configure in your app.
10
- */
11
- const SHIMMER_CONFIG = new InjectionToken('SHIMMER_CONFIG');
12
- /**
13
- * Provider function for shimmer configuration.
14
- * Use in your app's providers array.
15
- *
16
- * @example
17
- * ```typescript
18
- * bootstrapApplication(AppComponent, {
19
- * providers: [
20
- * provideShimmerConfig({
21
- * shimmerColor: 'rgba(255, 255, 255, 0.3)',
22
- * duration: 1.5
23
- * })
24
- * ]
25
- * });
26
- * ```
27
- */
28
- function provideShimmerConfig(config) {
29
- return { provide: SHIMMER_CONFIG, useValue: config };
30
- }
31
- /**
32
- * Inject and resolve shimmer configuration.
33
- * Merges injected config with defaults.
34
- * Returns fully resolved ShimmerContextValue with all properties defined.
35
- */
36
- function injectShimmerConfig() {
37
- const config = inject(SHIMMER_CONFIG, { optional: true }) ?? {};
38
- return {
39
- shimmerColor: config.shimmerColor ?? shimmerDefaults.shimmerColor,
40
- backgroundColor: config.backgroundColor ?? shimmerDefaults.backgroundColor,
41
- duration: config.duration ?? shimmerDefaults.duration,
42
- fallbackBorderRadius: config.fallbackBorderRadius ?? shimmerDefaults.fallbackBorderRadius,
43
- };
44
- }
45
-
46
- /**
47
- * Shimmer component that creates loading skeleton overlays based on content structure.
48
- * Automatically measures projected content and creates matching shimmer blocks.
49
- *
50
- * @example
51
- * ```html
52
- * <shimmer [loading]="isLoading">
53
- * <div class="card">
54
- * <h2>{{ title }}</h2>
55
- * <p>{{ description }}</p>
56
- * </div>
57
- * </shimmer>
58
- * ```
59
- */
60
- class ShimmerComponent {
61
- // Inputs using Angular signals
62
- loading = input(true);
63
- shimmerColor = input(undefined);
64
- backgroundColor = input(undefined);
65
- duration = input(undefined);
66
- fallbackBorderRadius = input(undefined);
67
- // View child reference
68
- measureContainer = viewChild('measureContainer');
69
- // Internal state
70
- elements = signal([]);
71
- // Inject dependencies
72
- contextConfig = injectShimmerConfig();
73
- platformId = inject(PLATFORM_ID);
74
- isBrowser = isPlatformBrowser(this.platformId);
75
- // Resolved values (props > context > defaults)
76
- resolvedShimmerColor = computed(() => this.shimmerColor() ?? this.contextConfig.shimmerColor);
77
- resolvedBackgroundColor = computed(() => this.backgroundColor() ?? this.contextConfig.backgroundColor);
78
- resolvedDuration = computed(() => this.duration() ?? this.contextConfig.duration);
79
- resolvedFallbackBorderRadius = computed(() => this.fallbackBorderRadius() ?? this.contextConfig.fallbackBorderRadius);
80
- // Cleanup function for ResizeObserver
81
- resizeCleanup;
82
- mutationObserver;
83
- constructor() {
84
- // Effect to re-measure when loading state changes
85
- effect((onCleanup) => {
86
- // Skip effect on server
87
- if (!this.isBrowser)
88
- return;
89
- const isLoading = this.loading();
90
- const container = this.measureContainer();
91
- if (isLoading && container) {
92
- // Clean up existing observers before setting up new ones
93
- this.cleanup();
94
- // Set up observers for this loading session
95
- this.setupObservers();
96
- // Defer measurement to next frame to ensure content is rendered
97
- requestAnimationFrame(() => this.measureElements());
98
- }
99
- else {
100
- // Cleanup when not loading
101
- this.cleanup();
102
- }
103
- // Cleanup on effect re-run or component destruction
104
- onCleanup(() => {
105
- this.cleanup();
106
- });
107
- });
108
- }
109
- ngAfterViewInit() {
110
- // Effect will handle setup when container becomes available
111
- }
112
- ngOnDestroy() {
113
- this.cleanup();
114
- }
115
- setupObservers() {
116
- if (!this.isBrowser)
117
- return;
118
- const container = this.measureContainer()?.nativeElement;
119
- if (!container)
120
- return;
121
- // Set up ResizeObserver
122
- this.resizeCleanup = createResizeObserver(container, () => this.measureElements());
123
- // Set up MutationObserver for content changes
124
- this.mutationObserver = new MutationObserver(() => {
125
- if (this.loading()) {
126
- this.measureElements();
127
- }
128
- });
129
- this.mutationObserver.observe(container, {
130
- childList: true,
131
- subtree: true,
132
- characterData: true,
133
- attributes: false,
134
- });
135
- }
136
- measureElements() {
137
- if (!this.isBrowser)
138
- return;
139
- const container = this.measureContainer()?.nativeElement;
140
- if (!container || !this.loading())
141
- return;
142
- // Temporarily disconnect mutation observer to avoid recursion
143
- this.mutationObserver?.disconnect();
144
- const containerRect = container.getBoundingClientRect();
145
- const extractedElements = [];
146
- Array.from(container.children).forEach((child) => {
147
- extractedElements.push(...extractElementInfo(child, containerRect));
148
- });
149
- this.elements.set(extractedElements);
150
- // Reconnect mutation observer
151
- if (this.mutationObserver && container) {
152
- this.mutationObserver.observe(container, {
153
- childList: true,
154
- subtree: true,
155
- characterData: true,
156
- attributes: false,
157
- });
158
- }
159
- }
160
- cleanup() {
161
- if (this.resizeCleanup) {
162
- this.resizeCleanup();
163
- this.resizeCleanup = undefined;
164
- }
165
- if (this.mutationObserver) {
166
- this.mutationObserver.disconnect();
167
- this.mutationObserver = undefined;
168
- }
169
- }
170
- /**
171
- * Manually trigger re-measurement of elements.
172
- * Useful when content changes programmatically.
173
- */
174
- remeasure() {
175
- if (this.isBrowser) {
176
- this.measureElements();
177
- }
178
- }
179
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: ShimmerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
180
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: ShimmerComponent, isStandalone: true, selector: "shimmer", inputs: { loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, shimmerColor: { classPropertyName: "shimmerColor", publicName: "shimmerColor", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, fallbackBorderRadius: { classPropertyName: "fallbackBorderRadius", publicName: "fallbackBorderRadius", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "measureContainer", first: true, predicate: ["measureContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
181
- <div style="position: relative;">
182
- <!-- Always render content -->
183
- <div
184
- #measureContainer
185
- [class.shimmer-measure-container]="loading()"
186
- [attr.aria-hidden]="loading() ? 'true' : null"
187
- [style.pointer-events]="loading() ? 'none' : null"
188
- >
189
- <ng-content></ng-content>
190
- </div>
191
-
192
- <!-- Shimmer overlay - only when loading -->
193
- @if (loading()) {
194
- <div
195
- style="
196
- position: absolute;
197
- top: 0;
198
- left: 0;
199
- right: 0;
200
- bottom: 0;
201
- overflow: hidden;
202
- pointer-events: none;
203
- "
204
- >
205
- @for (element of elements(); track $index) {
206
- <div
207
- [style.position]="'absolute'"
208
- [style.left.px]="element.x"
209
- [style.top.px]="element.y"
210
- [style.width.px]="element.width"
211
- [style.height.px]="element.height"
212
- [style.backgroundColor]="resolvedBackgroundColor()"
213
- [style.borderRadius]="
214
- element.borderRadius === '0px'
215
- ? resolvedFallbackBorderRadius() + 'px'
216
- : element.borderRadius
217
- "
218
- [style.overflow]="'hidden'"
219
- >
220
- <div
221
- class="shimmer-animation-element"
222
- [style.background]="
223
- 'linear-gradient(90deg, transparent, ' + resolvedShimmerColor() + ', transparent)'
224
- "
225
- [style.animationDuration]="resolvedDuration() + 's'"
226
- ></div>
227
- </div>
228
- }
229
- </div>
230
- }
231
- </div>
232
- `, isInline: true, styles: [":host{display:contents}.shimmer-measure-container *{color:transparent!important}.shimmer-measure-container img,.shimmer-measure-container svg,.shimmer-measure-container video{opacity:0}.shimmer-animation-element{position:absolute;top:0;left:0;width:100%;height:100%;animation:shimmer-animation 1.5s infinite}@keyframes shimmer-animation{0%{transform:translate(-100%)}to{transform:translate(100%)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
233
- }
234
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: ShimmerComponent, decorators: [{
235
- type: Component,
236
- args: [{ selector: 'shimmer', standalone: true, imports: [NgIf, NgFor], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
237
- <div style="position: relative;">
238
- <!-- Always render content -->
239
- <div
240
- #measureContainer
241
- [class.shimmer-measure-container]="loading()"
242
- [attr.aria-hidden]="loading() ? 'true' : null"
243
- [style.pointer-events]="loading() ? 'none' : null"
244
- >
245
- <ng-content></ng-content>
246
- </div>
247
-
248
- <!-- Shimmer overlay - only when loading -->
249
- @if (loading()) {
250
- <div
251
- style="
252
- position: absolute;
253
- top: 0;
254
- left: 0;
255
- right: 0;
256
- bottom: 0;
257
- overflow: hidden;
258
- pointer-events: none;
259
- "
260
- >
261
- @for (element of elements(); track $index) {
262
- <div
263
- [style.position]="'absolute'"
264
- [style.left.px]="element.x"
265
- [style.top.px]="element.y"
266
- [style.width.px]="element.width"
267
- [style.height.px]="element.height"
268
- [style.backgroundColor]="resolvedBackgroundColor()"
269
- [style.borderRadius]="
270
- element.borderRadius === '0px'
271
- ? resolvedFallbackBorderRadius() + 'px'
272
- : element.borderRadius
273
- "
274
- [style.overflow]="'hidden'"
275
- >
276
- <div
277
- class="shimmer-animation-element"
278
- [style.background]="
279
- 'linear-gradient(90deg, transparent, ' + resolvedShimmerColor() + ', transparent)'
280
- "
281
- [style.animationDuration]="resolvedDuration() + 's'"
282
- ></div>
283
- </div>
284
- }
285
- </div>
286
- }
287
- </div>
288
- `, styles: [":host{display:contents}.shimmer-measure-container *{color:transparent!important}.shimmer-measure-container img,.shimmer-measure-container svg,.shimmer-measure-container video{opacity:0}.shimmer-animation-element{position:absolute;top:0;left:0;width:100%;height:100%;animation:shimmer-animation 1.5s infinite}@keyframes shimmer-animation{0%{transform:translate(-100%)}to{transform:translate(100%)}}\n"] }]
289
- }], ctorParameters: () => [] });
290
-
291
- // Public API Surface
292
-
293
- /**
294
- * Generated bundle index. Do not edit.
295
- */
296
-
297
- export { SHIMMER_CONFIG, ShimmerComponent, injectShimmerConfig, provideShimmerConfig };
298
- //# sourceMappingURL=shimmer-from-structure-angular.mjs.map