@shimmer-from-structure/svelte 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +310 -11
  2. package/dist/index.js +2 -2
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # ✨ Shimmer From Structure
2
2
 
3
- A **React, Vue & Svelte** shimmer/skeleton library that **automatically adapts to your component's runtime structure**. Unlike traditional shimmer libraries that require pre-defined skeleton structures, this library analyzes your actual component's DOM at runtime and generates a shimmer effect that perfectly matches its layout.
3
+ A **React, Vue, Svelte, Angular & SolidJS** shimmer/skeleton library that **automatically adapts to your component's runtime structure**. Unlike traditional shimmer libraries that require pre-defined skeleton structures, this library analyzes your actual component's DOM at runtime and generates a shimmer effect that perfectly matches its layout.
4
4
 
5
5
  ![React](https://img.shields.io/badge/React-%2320232a.svg?style=for-the-badge&logo=react&logoColor=%2361DAFB)
6
6
  ![Vue](https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vuedotjs&logoColor=4FC08D)
7
7
  ![Svelte](https://img.shields.io/badge/Svelte-ff3e00?style=for-the-badge&logo=svelte&logoColor=white)
8
+ ![Angular](https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white)
9
+ ![SolidJS](https://img.shields.io/badge/SolidJS-%232c4f7c?style=for-the-badge&logo=solid&logoColor=white)
8
10
 
9
11
  ![Shimmer From Structure Demo](https://github.com/darula-hpp/shimmer-from-structure/raw/main/example/preview.gif)
10
12
 
@@ -18,7 +20,7 @@ Traditional shimmer libraries require you to:
18
20
 
19
21
  **Shimmer From Structure** eliminates all of that:
20
22
 
21
- - ✅ **Works with React, Vue & Svelte** - Simple, framework-specific drivers
23
+ - ✅ **Works with React, Vue, Svelte, Angular & SolidJS** - Simple, framework-specific adapters
22
24
  - ✅ Automatically measures your component's structure at runtime
23
25
  - ✅ Generates shimmer effects that match actual dimensions
24
26
  - ✅ Zero maintenance - works with any layout changes
@@ -43,7 +45,7 @@ Shimmer From Structure provides dedicated packages for **React and Vue**.
43
45
 
44
46
  ### React
45
47
 
46
- React support is built-in to the main package for backward compatibility:
48
+ React support is built into the main package for backward compatibility:
47
49
 
48
50
  ```javascript
49
51
  // React projects (or @shimmer-from-structure/react)
@@ -68,6 +70,24 @@ Svelte support is provided via its own adapter:
68
70
  import { Shimmer } from '@shimmer-from-structure/svelte';
69
71
  ```
70
72
 
73
+ ### Angular
74
+
75
+ Angular support requires importing from the specific adapter:
76
+
77
+ ```typescript
78
+ // Angular projects
79
+ import { ShimmerComponent } from '@shimmer-from-structure/angular';
80
+ ```
81
+
82
+ ### SolidJS
83
+
84
+ SolidJS support requires importing from the specific adapter:
85
+
86
+ ```tsx
87
+ // SolidJS projects
88
+ import { Shimmer } from '@shimmer-from-structure/solid';
89
+ ```
90
+
71
91
  ---
72
92
 
73
93
  # 📖 Basic Usage
@@ -137,6 +157,56 @@ let isLoading = $state(true);
137
157
  </Shimmer>
138
158
  ```
139
159
 
160
+ ## Angular
161
+
162
+ ### Static Content
163
+
164
+ ```typescript
165
+ import { Component, signal } from '@angular/core';
166
+ import { ShimmerComponent } from '@shimmer-from-structure/angular';
167
+
168
+ @Component({
169
+ selector: 'app-user-card',
170
+ standalone: true,
171
+ imports: [ShimmerComponent],
172
+ template: `
173
+ <shimmer [loading]="isLoading()">
174
+ <div class="card">
175
+ <img src="avatar.jpg" class="avatar" />
176
+ <h2>John Doe</h2>
177
+ <p>Software Engineer</p>
178
+ </div>
179
+ </shimmer>
180
+ `,
181
+ })
182
+ export class UserCardComponent {
183
+ isLoading = signal(true);
184
+ }
185
+ ```
186
+
187
+ ## SolidJS
188
+
189
+ ### Static Content
190
+
191
+ ```tsx
192
+ import { createSignal } from 'solid-js';
193
+ import { Shimmer } from '@shimmer-from-structure/solid';
194
+
195
+ function UserCard() {
196
+ const [isLoading, setIsLoading] = createSignal(true);
197
+
198
+ return (
199
+ <Shimmer loading={isLoading()}>
200
+ <div class="card">
201
+ <img src="avatar.jpg" class="avatar" />
202
+ <h2>John Doe</h2>
203
+ <p>Software Engineer</p>
204
+ </div>
205
+ </Shimmer>
206
+ );
207
+ }
208
+ ```
209
+
140
210
  ---
141
211
 
142
212
  ### Dynamic Content with `templateProps`
@@ -221,6 +291,60 @@ const userTemplate = {
221
291
  </Shimmer>
222
292
  ```
223
293
 
294
+ **Angular**
295
+
296
+ ```typescript
297
+ import { Component, signal } from '@angular/core';
298
+ import { ShimmerComponent } from '@shimmer-from-structure/angular';
299
+ import { UserCardComponent } from './user-card.component';
300
+
301
+ @Component({
302
+ selector: 'app-root',
303
+ standalone: true,
304
+ imports: [ShimmerComponent, UserCardComponent],
305
+ template: `
306
+ <shimmer [loading]="loading()" [templateProps]="{ user: userTemplate }">
307
+ <app-user-card [user]="user() || userTemplate" />
308
+ </shimmer>
309
+ `,
310
+ })
311
+ export class AppComponent {
312
+ loading = signal(true);
313
+ user = signal<User | null>(null);
314
+
315
+ userTemplate = {
316
+ name: 'Loading...',
317
+ role: 'Loading role...',
318
+ avatar: 'placeholder.jpg',
319
+ };
320
+ }
321
+ ```
322
+
323
+ **SolidJS**
324
+
325
+ ```tsx
326
+ import { createSignal } from 'solid-js';
327
+ import { Shimmer } from '@shimmer-from-structure/solid';
328
+ import { UserCard } from './UserCard';
329
+
330
+ function App() {
331
+ const [loading, setLoading] = createSignal(true);
332
+ const [user, setUser] = createSignal(null);
333
+
334
+ const userTemplate = {
335
+ name: 'Loading...',
336
+ role: 'Loading role...',
337
+ avatar: 'placeholder.jpg',
338
+ };
339
+
340
+ return (
341
+ <Shimmer loading={loading()} templateProps={{ user: userTemplate }}>
342
+ <UserCard user={user() || userTemplate} />
343
+ </Shimmer>
344
+ );
345
+ }
346
+ ```
347
+
224
348
  The `templateProps` object is spread onto the first child component when loading, allowing it to render with mock data for measurement.
225
349
 
226
350
  ## 🎨 API Reference
@@ -293,6 +417,43 @@ The `templateProps` object is spread onto the first child component when loading
293
417
  </Shimmer>
294
418
  ```
295
419
 
420
+ **Angular**
421
+
422
+ ```typescript
423
+ <shimmer
424
+ [loading]="isLoading()"
425
+ shimmerColor="rgba(255, 255, 255, 0.2)"
426
+ backgroundColor="rgba(255, 255, 255, 0.1)"
427
+ [duration]="2"
428
+ [fallbackBorderRadius]="8"
429
+ [templateProps]="{
430
+ user: userTemplate,
431
+ settings: settingsTemplate
432
+ }">
433
+ <app-my-component
434
+ [user]="user()"
435
+ [settings]="settings()" />
436
+ </shimmer>
437
+ ```
438
+
439
+ **SolidJS**
440
+
441
+ ```tsx
442
+ <Shimmer
443
+ loading={isLoading()}
444
+ shimmerColor="rgba(255, 255, 255, 0.2)"
445
+ backgroundColor="rgba(255, 255, 255, 0.1)"
446
+ duration={2}
447
+ fallbackBorderRadius={8}
448
+ templateProps={{
449
+ user: userTemplate,
450
+ settings: settingsTemplate,
451
+ }}
452
+ >
453
+ <MyComponent user={user()} settings={settings()} />
454
+ </Shimmer>
455
+ ```
456
+
296
457
  ## 🔧 How It Works
297
458
 
298
459
  1. **Visible Container Rendering**: When `loading={true}`, your component renders with transparent text but **visible container backgrounds**
@@ -378,6 +539,33 @@ function Dashboard() {
378
539
  </Shimmer>
379
540
  ```
380
541
 
542
+ **Angular**
543
+
544
+ ```typescript
545
+ @Component({
546
+ template: `
547
+ <!-- User profile section -->
548
+ <shimmer [loading]="loadingUser()" [templateProps]="{ user: userTemplate }">
549
+ <app-user-profile [user]="user()" />
550
+ </shimmer>
551
+
552
+ <!-- Stats section - with custom colors -->
553
+ <shimmer
554
+ [loading]="loadingStats()"
555
+ [templateProps]="{ stats: statsTemplate }"
556
+ shimmerColor="rgba(20, 184, 166, 0.2)"
557
+ >
558
+ <app-stats-grid [stats]="stats()" />
559
+ </shimmer>
560
+ `,
561
+ })
562
+ export class DashboardComponent {
563
+ loadingUser = signal(true);
564
+ loadingStats = signal(true);
565
+ // ...
566
+ }
567
+ ```
568
+
381
569
  ### Transactions List
382
570
 
383
571
  **React**
@@ -404,6 +592,16 @@ function Dashboard() {
404
592
  </Shimmer>
405
593
  ```
406
594
 
595
+ **Angular**
596
+
597
+ ```typescript
598
+ <shimmer
599
+ [loading]="loadingTransactions()"
600
+ [templateProps]="{ transactions: transactionsTemplate }">
601
+ <app-transactions-list [transactions]="transactions()" />
602
+ </shimmer>
603
+ ```
604
+
407
605
  ### Team Members Grid
408
606
 
409
607
  **React**
@@ -430,6 +628,16 @@ function Dashboard() {
430
628
  </Shimmer>
431
629
  ```
432
630
 
631
+ **Angular**
632
+
633
+ ```typescript
634
+ <shimmer
635
+ [loading]="loadingTeam()"
636
+ [templateProps]="{ members: teamTemplate }">
637
+ <app-team-members [members]="team()" />
638
+ </shimmer>
639
+ ```
640
+
433
641
  ## 🔄 Using with React Suspense
434
642
 
435
643
  Shimmer works seamlessly as a Suspense fallback. When used this way, `loading` is always `true` because React automatically unmounts the fallback and replaces it with the resolved component.
@@ -550,6 +758,47 @@ setShimmerConfig({
550
758
  <Dashboard />
551
759
  ```
552
760
 
761
+ ### Angular (Dependency Injection)
762
+
763
+ ```typescript
764
+ // main.ts or bootstrapApplication
765
+ import { bootstrapApplication } from '@angular/platform-browser';
766
+ import { provideShimmerConfig } from '@shimmer-from-structure/angular';
767
+ import { AppComponent } from './app/app.component';
768
+
769
+ bootstrapApplication(AppComponent, {
770
+ providers: [
771
+ provideShimmerConfig({
772
+ shimmerColor: 'rgba(56, 189, 248, 0.4)',
773
+ backgroundColor: 'rgba(56, 189, 248, 0.1)',
774
+ duration: 2.5,
775
+ fallbackBorderRadius: 8,
776
+ }),
777
+ ],
778
+ });
779
+ ```
780
+
781
+ ### SolidJS (ShimmerProvider)
782
+
783
+ ```tsx
784
+ import { Shimmer, ShimmerProvider } from '@shimmer-from-structure/solid';
785
+
786
+ function App() {
787
+ return (
788
+ <ShimmerProvider
789
+ config={{
790
+ shimmerColor: 'rgba(56, 189, 248, 0.4)',
791
+ backgroundColor: 'rgba(56, 189, 248, 0.1)',
792
+ duration: 2.5,
793
+ fallbackBorderRadius: 8,
794
+ }}
795
+ >
796
+ <Dashboard />
797
+ </ShimmerProvider>
798
+ );
799
+ }
800
+ ```
801
+
553
802
  ---
554
803
 
555
804
  Components inside the provider automatically inherit values. You can still override them locally:
@@ -584,6 +833,26 @@ Components inside the provider automatically inherit values. You can still overr
584
833
  <Shimmer loading={true} duration={0.5}><FastCard /></Shimmer>
585
834
  ```
586
835
 
836
+ **Angular**
837
+
838
+ ```typescript
839
+ <!-- Inherits blue theme from injected config -->
840
+ <shimmer [loading]="true"><app-user-card /></shimmer>
841
+
842
+ <!-- Overrides injected settings -->
843
+ <shimmer [loading]="true" [duration]="0.5"><app-fast-card /></shimmer>
844
+ ```
845
+
846
+ **SolidJS**
847
+
848
+ ```tsx
849
+ <!-- Inherits blue theme from provider -->
850
+ <Shimmer loading={true()}><UserCard /></Shimmer>
851
+
852
+ <!-- Overrides provider settings -->
853
+ <Shimmer loading={true()} duration={0.5}><FastCard /></Shimmer>
854
+ ```
855
+
587
856
  ### Accessing Config in Hooks/Composables
588
857
 
589
858
  If you need to access the current configuration in your own components:
@@ -617,6 +886,32 @@ const config = getShimmerConfig();
617
886
  console.log(config.backgroundColor);
618
887
  ```
619
888
 
889
+ **Angular**
890
+
891
+ ```typescript
892
+ import { Component, inject } from '@angular/core';
893
+ import { injectShimmerConfig } from '@shimmer-from-structure/angular';
894
+
895
+ @Component({
896
+ selector: 'app-my-component',
897
+ template: `<div [style.background]="config.backgroundColor">...</div>`,
898
+ })
899
+ export class MyComponent {
900
+ config = injectShimmerConfig();
901
+ }
902
+ ```
903
+
904
+ **SolidJS**
905
+
906
+ ```tsx
907
+ import { useShimmerConfig } from '@shimmer-from-structure/solid';
908
+
909
+ function MyComponent() {
910
+ const config = useShimmerConfig();
911
+ return <div style={{ background: config.backgroundColor }}>...</div>;
912
+ }
913
+ ```
914
+
620
915
  ## Best Practices
621
916
 
622
917
  ### 1. Use `templateProps` for Dynamic Data
@@ -706,15 +1001,17 @@ Contributions are welcome! Please feel free to submit a Pull Request.
706
1001
 
707
1002
  This library is organized as a monorepo with four packages:
708
1003
 
709
- | Package | Description | Size |
710
- | -------------------------------- | ------------------------------------------- | -------- |
711
- | `@shimmer-from-structure/core` | Framework-agnostic DOM utilities | 1.44 kB |
712
- | `@shimmer-from-structure/react` | React adapter | 12.84 kB |
713
- | `@shimmer-from-structure/vue` | Vue 3 adapter | 3.89 kB |
714
- | `@shimmer-from-structure/svelte` | Svelte adapter | 4.60 kB |
715
- | `shimmer-from-structure` | Main package (React backward compatibility) | 0.93 kB |
1004
+ | Package | Description | Size |
1005
+ | --------------------------------- | ------------------------------------------- | -------- |
1006
+ | `@shimmer-from-structure/core` | Framework-agnostic DOM utilities | 1.44 kB |
1007
+ | `@shimmer-from-structure/react` | React adapter | 12.84 kB |
1008
+ | `@shimmer-from-structure/vue` | Vue 3 adapter | 3.89 kB |
1009
+ | `@shimmer-from-structure/svelte` | Svelte adapter | 4.60 kB |
1010
+ | `@shimmer-from-structure/angular` | Angular adapter | 6.83 kB |
1011
+ | `@shimmer-from-structure/solid` | SolidJS adapter | 4.01 kB |
1012
+ | `shimmer-from-structure` | Main package (React backward compatibility) | 0.93 kB |
716
1013
 
717
- The core package contains all DOM measurement logic, while React and Vue packages are thin wrappers that provide framework-specific APIs.
1014
+ The core package contains all DOM measurement logic, while React, Vue, Svelte, Angular and SolidJS packages are thin wrappers that provide framework-specific APIs.
718
1015
 
719
1016
  ## 🚧 Roadmap
720
1017
 
@@ -723,6 +1020,8 @@ The core package contains all DOM measurement logic, while React and Vue package
723
1020
  - [x] Container background visibility
724
1021
  - [x] **Vue.js adapter**
725
1022
  - [x] **Svelte adapter**
1023
+ - [x] **Angular adapter**
1024
+ - [x] **SolidJS adapter**
726
1025
  - [ ] Better async component support
727
1026
  - [ ] Customizable shimmer direction (vertical, diagonal)
728
1027
  - [ ] React Native support
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(n,v){typeof exports=="object"&&typeof module<"u"?v(exports,require("svelte/internal/disclose-version"),require("svelte/internal/client"),require("svelte"),require("@shimmer-from-structure/core")):typeof define=="function"&&define.amd?define(["exports","svelte/internal/disclose-version","svelte/internal/client","svelte","@shimmer-from-structure/core"],v):(n=typeof globalThis<"u"?globalThis:n||self,v(n.ShimmerSvelte={},null,n.SvelteInternalClient,n.Svelte,n.ShimmerCore))})(this,function(n,v,B,h,g){"use strict";function w(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const i in r)if(i!=="default"){const p=Object.getOwnPropertyDescriptor(r,i);Object.defineProperty(t,i,p.get?p:{enumerable:!0,get:()=>r[i]})}}return t.default=r,Object.freeze(t)}const e=w(B),k=Symbol("SHIMMER_CONFIG");function _(){return h.getContext(k)||g.shimmerDefaults}function D(r={}){const t=_(),i={shimmerColor:r.shimmerColor??t.shimmerColor,backgroundColor:r.backgroundColor??t.backgroundColor,duration:r.duration??t.duration,fallbackBorderRadius:r.fallbackBorderRadius??t.fallbackBorderRadius};h.setContext(k,i)}var M=e.from_html("<div><div></div></div>"),j=e.from_html(`<div style="position: relative;"><div class="shimmer-measure-container svelte-euvo5u" style="pointer-events: none;" aria-hidden="true"><!></div> <div style="
1
+ (function(n,v){typeof exports=="object"&&typeof module<"u"?v(exports,require("svelte/internal/disclose-version"),require("svelte/internal/client"),require("svelte"),require("@shimmer-from-structure/core")):typeof define=="function"&&define.amd?define(["exports","svelte/internal/disclose-version","svelte/internal/client","svelte","@shimmer-from-structure/core"],v):(n=typeof globalThis<"u"?globalThis:n||self,v(n.ShimmerSvelte={},null,n.SvelteInternalClient,n.Svelte,n.ShimmerCore))})(this,(function(n,v,B,h,g){"use strict";function w(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const i in r)if(i!=="default"){const p=Object.getOwnPropertyDescriptor(r,i);Object.defineProperty(t,i,p.get?p:{enumerable:!0,get:()=>r[i]})}}return t.default=r,Object.freeze(t)}const e=w(B),k=Symbol("SHIMMER_CONFIG");function _(){return h.getContext(k)||g.shimmerDefaults}function D(r={}){const t=_(),i={shimmerColor:r.shimmerColor??t.shimmerColor,backgroundColor:r.backgroundColor??t.backgroundColor,duration:r.duration??t.duration,fallbackBorderRadius:r.fallbackBorderRadius??t.fallbackBorderRadius};h.setContext(k,i)}var M=e.from_html("<div><div></div></div>"),j=e.from_html(`<div style="position: relative;"><div class="shimmer-measure-container svelte-euvo5u" style="pointer-events: none;" aria-hidden="true"><!></div> <div style="
2
2
  position: absolute;
3
3
  top: 0;
4
4
  left: 0;
@@ -30,4 +30,4 @@
30
30
  height: 100%;
31
31
  background: linear-gradient(90deg, transparent, ${e.get(z)??""}, transparent);
32
32
  animation: shimmer-animation ${e.get(N)??""}s infinite;
33
- `)}),e.append(C,m)}),e.reset(R),e.reset(u),e.append(d,u)};e.if(X,d=>{i()?d(K,!1):d(A)})}return e.append(r,x),e.pop(V)}Object.defineProperty(n,"shimmerDefaults",{enumerable:!0,get:()=>g.shimmerDefaults}),n.Shimmer=I,n.getShimmerConfig=_,n.setShimmerConfig=D,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
33
+ `)}),e.append(C,m)}),e.reset(R),e.reset(u),e.append(d,u)};e.if(X,d=>{i()?d(K,!1):d(A)})}return e.append(r,x),e.pop(V)}Object.defineProperty(n,"shimmerDefaults",{enumerable:!0,get:()=>g.shimmerDefaults}),n.Shimmer=I,n.getShimmerConfig=_,n.setShimmerConfig=D,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shimmer-from-structure/svelte",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "type": "module",
5
5
  "description": "Svelte adapter for shimmer-from-structure",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "@shimmer-from-structure/core": "*"
31
31
  },
32
32
  "devDependencies": {
33
- "@sveltejs/vite-plugin-svelte": "^4.0.0",
33
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
34
34
  "@testing-library/dom": "^10.4.1",
35
35
  "@testing-library/jest-dom": "^6.9.1",
36
36
  "@testing-library/svelte": "^5.3.1",
@@ -38,7 +38,8 @@
38
38
  "svelte": "^5.0.0",
39
39
  "svelte-check": "^4.0.0",
40
40
  "tslib": "^2.0.0",
41
- "typescript": "^5.0.0"
41
+ "typescript": "^5.0.0",
42
+ "vitefu": "^1.1.1"
42
43
  },
43
44
  "keywords": [
44
45
  "svelte",