ladrillosjs 2.0.0-beta.3 → 2.0.0-beta.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,6 +23,7 @@ A lightweight, zero-dependency web component framework for building modular web
23
23
  - [Slots](#slots)
24
24
  - [Component Props](#component-props)
25
25
  - [Advanced Features](#advanced-features)
26
+ - [Lazy Loading](#lazy-loading)
26
27
  - [Global Event Bus](#global-event-bus)
27
28
  - [External Scripts](#external-scripts)
28
29
  - [Shadow DOM](#shadow-dom)
@@ -48,8 +49,9 @@ A lightweight, zero-dependency web component framework for building modular web
48
49
  - 🔌 **Slots** - Content projection with named and default slots
49
50
  - 📝 **TypeScript** - Full type definitions and TypeScript source code
50
51
  - 🎭 **Conditional Rendering** - `$if`, `$else-if`, and `$else` directives
51
- - **List Rendering** - `$for` directive for rendering arrays
52
- - �🚄 **Smart Caching** - LRU cache for components and compiled functions
52
+ - 🔁 **List Rendering** - `$for` directive for rendering arrays
53
+ - **Lazy Loading** - Load components on-demand with Intersection Observer
54
+ - 🚄 **Smart Caching** - LRU cache for components and compiled functions
53
55
  - 🔧 **Framework Utilities** - Helper functions for common tasks
54
56
  - 🧩 **External Scripts** - Load and bind external JavaScript modules
55
57
 
@@ -193,6 +195,21 @@ await registerComponents([
193
195
 
194
196
  // Disable Shadow DOM for a component
195
197
  await registerComponent("global-styles", "./components/global.html", false);
198
+
199
+ // Enable lazy loading for a component
200
+ await registerComponent(
201
+ "footer-section",
202
+ "./components/footer.html",
203
+ true,
204
+ true
205
+ );
206
+
207
+ // Register multiple components with lazy loading
208
+ await registerComponents([
209
+ { name: "hero-section", path: "./components/hero.html" },
210
+ { name: "feature-section", path: "./components/features.html", lazy: true },
211
+ { name: "footer-section", path: "./components/footer.html", lazy: true },
212
+ ]);
196
213
  ```
197
214
 
198
215
  ### State Management
@@ -568,6 +585,93 @@ Pass data to components using HTML attributes:
568
585
 
569
586
  ## Advanced Features
570
587
 
588
+ ### Lazy Loading
589
+
590
+ LadrillosJS supports lazy loading components using the Intersection Observer API. Components are loaded only when they enter or are about to enter the viewport, improving initial page load performance.
591
+
592
+ #### Basic Usage
593
+
594
+ ```javascript
595
+ import { registerComponents } from "ladrillosjs";
596
+
597
+ await registerComponents([
598
+ // Eager loading (default) - loads immediately
599
+ { name: "hero-section", path: "./components/hero.html" },
600
+ { name: "navbar", path: "./components/navbar.html" },
601
+
602
+ // Lazy loading - loads when scrolled into view
603
+ { name: "feature-section", path: "./components/features.html", lazy: true },
604
+ { name: "testimonials", path: "./components/testimonials.html", lazy: true },
605
+ { name: "footer-section", path: "./components/footer.html", lazy: true },
606
+ ]);
607
+ ```
608
+
609
+ ```html
610
+ <body>
611
+ <!-- Loads immediately -->
612
+ <navbar></navbar>
613
+ <hero-section></hero-section>
614
+
615
+ <!-- Loads when user scrolls near these components -->
616
+ <feature-section></feature-section>
617
+ <testimonials></testimonials>
618
+ <footer-section></footer-section>
619
+ </body>
620
+ ```
621
+
622
+ #### Override Lazy Loading with `eager` Attribute
623
+
624
+ You can force a lazy component to load immediately using the `eager` attribute:
625
+
626
+ ```html
627
+ <!-- This lazy component loads immediately despite lazy registration -->
628
+ <footer-section eager></footer-section>
629
+ ```
630
+
631
+ #### Best Practices for Lazy Loading
632
+
633
+ **✅ Good candidates for lazy loading:**
634
+
635
+ - Below-the-fold content (footers, testimonials)
636
+ - Large components with heavy resources
637
+ - Components that may not be viewed by all users
638
+ - Third-party widgets or embeds
639
+
640
+ **❌ Avoid lazy loading for:**
641
+
642
+ - Above-the-fold content (heroes, navigation)
643
+ - Critical interactive elements
644
+ - Small, lightweight components
645
+ - Content needed for SEO
646
+
647
+ **Performance Tips:**
648
+
649
+ 1. **Reserve space for lazy components** to prevent layout shift:
650
+
651
+ ```css
652
+ /* In your global CSS */
653
+ feature-section,
654
+ testimonials,
655
+ footer-section {
656
+ display: block;
657
+ min-height: 400px; /* Approximate height */
658
+ }
659
+ ```
660
+
661
+ 2. **Load strategy**: Lazy components load **100px before** entering the viewport for smooth user experience and to account for network latency.
662
+
663
+ 3. **Multiple instances**: If you use the same lazy component multiple times on a page, only one network request is made. All instances share the loaded component definition.
664
+
665
+ 4. **Caching**: Once loaded, lazy components are cached and reused across page navigation.
666
+
667
+ #### How It Works
668
+
669
+ - **Placeholder**: Lazy components initially render as minimal placeholders
670
+ - **Intersection Observer**: Monitors when placeholders approach the viewport
671
+ - **Automatic Loading**: Component fetches and upgrades when visible
672
+ - **Seamless Swap**: Placeholder is replaced with the real component
673
+ - **Shared Loading**: Multiple instances coordinate to load only once
674
+
571
675
  ### Global Event Bus
572
676
 
573
677
  The global event bus enables communication between components without prop drilling:
@@ -943,8 +1047,48 @@ Show loading indicators while fetching data:
943
1047
  ### Registration Functions
944
1048
 
945
1049
  ```typescript
946
- registerComponent(name: string, path: string, useShadowDOM?: boolean): Promise<void>
947
- registerComponents(components: Array<{name, path, useShadowDOM?}>): Promise<void>
1050
+ registerComponent(
1051
+ name: string,
1052
+ path: string,
1053
+ useShadowDOM?: boolean,
1054
+ lazy?: boolean
1055
+ ): Promise<void>
1056
+
1057
+ registerComponents(
1058
+ components: Array<{
1059
+ name: string,
1060
+ path: string,
1061
+ useShadowDOM?: boolean,
1062
+ lazy?: boolean
1063
+ }>
1064
+ ): Promise<void>
1065
+ ```
1066
+
1067
+ **Parameters:**
1068
+
1069
+ - `name`: Component tag name (must include a hyphen)
1070
+ - `path`: Path to the component file
1071
+ - `useShadowDOM`: Use Shadow DOM for style encapsulation (default: `true`)
1072
+ - `lazy`: Enable lazy loading with Intersection Observer (default: `false`)
1073
+
1074
+ **Examples:**
1075
+
1076
+ ```javascript
1077
+ // Basic registration
1078
+ await registerComponent("my-button", "./button.html");
1079
+
1080
+ // Disable Shadow DOM
1081
+ await registerComponent("global-nav", "./nav.html", false);
1082
+
1083
+ // Enable lazy loading
1084
+ await registerComponent("footer", "./footer.html", true, true);
1085
+
1086
+ // Batch registration
1087
+ await registerComponents([
1088
+ { name: "hero", path: "./hero.html" },
1089
+ { name: "features", path: "./features.html", lazy: true },
1090
+ { name: "footer", path: "./footer.html", useShadowDOM: false, lazy: true },
1091
+ ]);
948
1092
  ```
949
1093
 
950
1094
  ### Component Utilities
@@ -984,6 +1128,10 @@ $reactive(name: string, initialValue: any): (value: any) => void
984
1128
  <li $for="(item, index) in items">{index}: {item}</li>
985
1129
  <div $for="user in users" $key="user.id">{user.name}</div>
986
1130
 
1131
+ <!-- Lazy loading override -->
1132
+ <footer-section eager></footer-section>
1133
+ <!-- Force immediate load -->
1134
+
987
1135
  <!-- Event handlers -->
988
1136
  <button onclick="methodName()">Click</button>
989
1137
  <button onclick="method(arg1, arg2)">Call with args</button>
@@ -4,6 +4,8 @@ declare class Ladrillos {
4
4
  components: Record<string, LadrillosComponent>;
5
5
  private lazyComponents;
6
6
  private intersectionObserver;
7
+ private lazyLoadingInProgress;
8
+ private lazyComponentsLoaded;
7
9
  constructor();
8
10
  registerComponent(name: string, path: string, useShadowDOM?: boolean, lazy?: boolean): Promise<void>;
9
11
  }