ladrillosjs 2.0.0-beta.3.3 → 2.0.0-beta.3.5

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
@@ -12,6 +12,7 @@ A lightweight, zero-dependency web component framework for building modular web
12
12
 
13
13
  - [Features](#features)
14
14
  - [Installation](#installation)
15
+ - [Using with Vite](#using-with-vite)
15
16
  - [Quick Start](#quick-start)
16
17
  - [Core Concepts](#core-concepts)
17
18
  - [Component Registration](#component-registration)
@@ -79,6 +80,131 @@ npm install ladrillosjs
79
80
  </script>
80
81
  ```
81
82
 
83
+ ## Using with Vite
84
+
85
+ LadrillosJS includes a Vite plugin to automatically copy your component files to the distribution folder during build. This is useful when you have static component files that need to be served with your application.
86
+
87
+ ### Installation
88
+
89
+ If you haven't already:
90
+
91
+ ```bash
92
+ npm install --save-dev vite
93
+ npm install ladrillosjs
94
+ ```
95
+
96
+ ### Setup
97
+
98
+ Create or update your `vite.config.js`:
99
+
100
+ ```javascript
101
+ import { defineConfig } from "vite";
102
+ import { copyComponentsPlugin } from "ladrillosjs/vite";
103
+
104
+ export default defineConfig({
105
+ plugins: [
106
+ copyComponentsPlugin({
107
+ src: "components", // Source directory with your components
108
+ dest: "components", // Destination in dist/ folder
109
+ copyOnDev: false, // Only copy during build (not dev server)
110
+ }),
111
+ ],
112
+ });
113
+ ```
114
+
115
+ ### Basic Usage
116
+
117
+ ```javascript
118
+ // vite.config.js with default settings
119
+ import { defineConfig } from "vite";
120
+ import { copyComponentsPlugin } from "ladrillosjs/vite";
121
+
122
+ export default defineConfig({
123
+ plugins: [copyComponentsPlugin()],
124
+ });
125
+ ```
126
+
127
+ The plugin will:
128
+
129
+ - 📁 Copy your `components/` folder to `dist/components/` during build
130
+ - 🛡️ Handle errors gracefully with helpful logging
131
+ - ⚙️ Use sensible defaults (src: 'components', dest: 'components')
132
+
133
+ ### Plugin Options
134
+
135
+ ```typescript
136
+ interface CopyComponentsOptions {
137
+ /** Source directory containing components (default: 'components') */
138
+ src?: string;
139
+
140
+ /** Destination directory in dist/ (default: 'components') */
141
+ dest?: string;
142
+
143
+ /** Copy during development server (default: false) */
144
+ copyOnDev?: boolean;
145
+ }
146
+ ```
147
+
148
+ ### Complete Example
149
+
150
+ Project structure:
151
+
152
+ ```
153
+ my-app/
154
+ ├── components/
155
+ │ ├── header.html
156
+ │ ├── footer.html
157
+ │ └── card.html
158
+ ├── src/
159
+ │ └── main.js
160
+ ├── index.html
161
+ └── vite.config.js
162
+ ```
163
+
164
+ Configuration:
165
+
166
+ ```javascript
167
+ import { defineConfig } from "vite";
168
+ import { copyComponentsPlugin } from "ladrillosjs/vite";
169
+
170
+ export default defineConfig({
171
+ plugins: [
172
+ copyComponentsPlugin({
173
+ src: "components",
174
+ dest: "components",
175
+ }),
176
+ ],
177
+ });
178
+ ```
179
+
180
+ Usage in your app:
181
+
182
+ ```javascript
183
+ // src/main.js
184
+ import { registerComponents } from "ladrillosjs";
185
+
186
+ await registerComponents([
187
+ { name: "app-header", path: "./components/header.html" },
188
+ { name: "app-footer", path: "./components/footer.html" },
189
+ { name: "app-card", path: "./components/card.html" },
190
+ ]);
191
+ ```
192
+
193
+ After running `npm run build`, your components will be copied to `dist/components/` and be ready for production deployment.
194
+
195
+ ### Development Workflow
196
+
197
+ ```bash
198
+ # Start dev server (components served from source)
199
+ npm run dev
200
+
201
+ # Build for production (components copied to dist)
202
+ npm run build
203
+
204
+ # Preview production build
205
+ npm run preview
206
+ ```
207
+
82
208
  ## Quick Start
83
209
 
84
210
  ### 1. Create Your First Component
@@ -742,33 +868,9 @@ $listen("user-logged-in", (data) => {
742
868
 
743
869
  LadrillosJS supports three ways to include external JavaScript:
744
870
 
745
- #### 1. Component-Scoped Scripts (Default)
746
-
747
- Regular script tags execute within the component's context and have access to component state and utilities:
748
-
749
- ```html
750
- <!-- alert-button.html -->
751
- <button onclick="increaseCount()">{title}: {count}</button>
752
-
753
- <!-- This script runs in the component context -->
754
- <script src="./alert.js"></script>
755
- ```
756
-
757
- **alert.js:**
758
-
759
- ```javascript
760
- // Variables and functions are available to the component
761
- let count = 0;
762
- const title = "Button Count";
763
-
764
- const increaseCount = () => {
765
- count++; // Updates component state
766
- };
767
- ```
768
-
769
- #### 2. ES Modules
871
+ #### 1. ES Modules (Recommended for Complex Logic)
770
872
 
771
- Use `type="module"` for standard ES module imports:
873
+ Use `type="module"` for standard ES modules with automatic state synchronization. Variables declared in modules are automatically initialized in component state and mutations are automatically synced:
772
874
 
773
875
  ```html
774
876
  <!-- side-nav.html -->
@@ -778,7 +880,7 @@ Use `type="module"` for standard ES module imports:
778
880
  <ul></ul>
779
881
  </nav>
780
882
 
781
- <!-- Load as ES module -->
883
+ <!-- Load as ES module - variables and exports are auto-synced to state -->
782
884
  <script type="module" src="../js/side.js"></script>
783
885
  ```
784
886
 
@@ -787,9 +889,21 @@ Use `type="module"` for standard ES module imports:
787
889
  ```javascript
788
890
  import { registerComponent, $listen, $querySelector } from "ladrillosjs";
789
891
 
892
+ // Declare variables that are used in template bindings
893
+ // They are automatically initialized in component state
790
894
  const notes = [];
895
+
791
896
  registerComponent("note-item", "./components/note-item.html");
792
897
 
898
+ // Export functions so they're available to event handlers
899
+ export const createNote = () => {
900
+ const title = prompt("Note title:");
901
+ if (title) {
902
+ notes.push({ title, content: "" });
903
+ }
904
+ };
905
+
906
+ // Listen to global events
793
907
  $listen("note_saved", (data) => {
794
908
  notes.push({ ...data });
795
909
  const ul = $querySelector("ul");
@@ -801,6 +915,110 @@ $listen("note_saved", (data) => {
801
915
  });
802
916
  ```
803
917
 
918
+ **How Module State Sync Works:**
919
+
920
+ When a module script is loaded, LadrillosJS:
921
+
922
+ 1. **Detects variables used in template bindings** (e.g., variables in `{}` expressions)
923
+ 2. **Initializes them in component state** automatically when declared
924
+ 3. **Syncs mutations to state** automatically when assigned
925
+ 4. **Auto-attaches exports** to the component so event handlers can access them
926
+
927
+ This means you write natural JavaScript without boilerplate:
928
+
929
+ ```javascript
930
+ // ✨ This is all you need!
931
+ let count = 0; // Auto-initialized in state
932
+ let user = { name: "" }; // Works with objects too
933
+
934
+ export const increment = () => {
935
+ count++; // Auto-synced to state!
936
+ };
937
+
938
+ export const updateUser = (name) => {
939
+ user.name = name; // Auto-synced to state!
940
+ };
941
+ ```
942
+
943
+ **ES Module Benefits:**
944
+
945
+ - ✅ Import external libraries and utilities
946
+ - ✅ Organize code across multiple files
947
+ - ✅ Automatic state initialization for binding variables
948
+ - ✅ Automatic state sync on variable mutations
949
+ - ✅ Clean separation of concerns
950
+ - ✅ Standard JavaScript module syntax
951
+
952
+ **Example: Counter Component**
953
+
954
+ ```html
955
+ <!-- counter.html -->
956
+ <div>
957
+ <h2>Counter: {count}</h2>
958
+ <button onclick="increment()">+1</button>
959
+ <button onclick="decrement()">-1</button>
960
+ <button onclick="reset()">Reset</button>
961
+ </div>
962
+
963
+ <script type="module" src="./counter.js"></script>
964
+
965
+ <style>
966
+ div {
967
+ text-align: center;
968
+ padding: 2rem;
969
+ }
970
+ button {
971
+ padding: 0.5rem 1rem;
972
+ margin: 0.5rem;
973
+ cursor: pointer;
974
+ }
975
+ </style>
976
+ ```
977
+
978
+ **counter.js:**
979
+
980
+ ```javascript
981
+ // Variables used in template are auto-initialized
982
+ let count = 0;
983
+
984
+ // Exports are auto-attached to component for event handlers
985
+ export const increment = () => {
986
+ count++;
987
+ };
988
+
989
+ export const decrement = () => {
990
+ count--;
991
+ };
992
+
993
+ export const reset = () => {
994
+ count = 0;
995
+ };
996
+ ```
997
+
998
+ #### 2. Component-Scoped Scripts
999
+
1000
+ Regular script tags execute within the component's context and have access to component state and utilities:
1001
+
1002
+ ```html
1003
+ <!-- alert-button.html -->
1004
+ <button onclick="increaseCount()">{title}: {count}</button>
1005
+
1006
+ <!-- This script runs in the component context -->
1007
+ <script src="./alert.js"></script>
1008
+ ```
1009
+
1010
+ **alert.js:**
1011
+
1012
+ ```javascript
1013
+ // Variables and functions are available to the component
1014
+ let count = 0;
1015
+ const title = "Button Count";
1016
+
1017
+ const increaseCount = () => {
1018
+ count++; // Updates component state
1019
+ };
1020
+ ```
1021
+
804
1022
  #### 3. External Libraries
805
1023
 
806
1024
  Use the `external` attribute for third-party libraries that shouldn't be bound to component context:
@@ -834,6 +1052,177 @@ Use the `external` attribute for third-party libraries that shouldn't be bound t
834
1052
  - Libraries that need to be loaded globally
835
1053
  - Scripts that don't need component context or utilities
836
1054
 
1055
+ #### Module Script Best Practices
1056
+
1057
+ **✅ Use modules for:**
1058
+
1059
+ - Component-specific logic and functions
1060
+ - Local state management
1061
+ - Importing utilities and helpers
1062
+ - Organizing complex components
1063
+
1064
+ **❌ Don't use modules for:**
1065
+
1066
+ - Simple inline event handlers (use inline scripts)
1067
+ - Global libraries (use `external` attribute)
1068
+ - Scripts that need global scope
1069
+
1070
+ **Relative Imports:**
1071
+
1072
+ Modules automatically resolve relative imports to their proper URLs:
1073
+
1074
+ ```javascript
1075
+ // These work automatically with modules
1076
+ import { helper } from "./utils.js";
1077
+ import { Component } from "../components/component.js";
1078
+ import { api } from "../../api/client.js";
1079
+ ```
1080
+
1081
+ #### Legacy: Using `$reactive` (Optional)
1082
+
1083
+ The `$reactive` function is still available for explicit state initialization in edge cases:
1084
+
1085
+ ```javascript
1086
+ import { $reactive } from "ladrillosjs";
1087
+
1088
+ let count = 0;
1089
+ const setCount = $reactive("count", count); // Manual initialization
1090
+
1091
+ // Later updates
1092
+ setCount(newValue);
1093
+ ```
1094
+
1095
+ However, this is **no longer necessary for module scripts** since variables are automatically initialized. Use it only if you need:
1096
+
1097
+ - Explicit control over initialization timing
1098
+ - Manual setter functions
1099
+ - Backward compatibility with older code
1100
+
1101
+ #### Advanced Module Patterns
1102
+
1103
+ **Pattern 1: Async Data Loading**
1104
+
1105
+ ```html
1106
+ <!-- user-profile.html -->
1107
+ <div $if="{loading}">Loading user...</div>
1108
+ <div $else-if="{error}">{error}</div>
1109
+ <div $else>
1110
+ <h1>{user.name}</h1>
1111
+ <p>Email: {user.email}</p>
1112
+ <p>Bio: {user.bio}</p>
1113
+ </div>
1114
+
1115
+ <script type="module" src="./user-profile.js"></script>
1116
+ ```
1117
+
1118
+ **user-profile.js:**
1119
+
1120
+ ```javascript
1121
+ // Variables auto-initialized in component state
1122
+ let user = { name: "", email: "", bio: "" };
1123
+ let loading = true;
1124
+ let error = null;
1125
+
1126
+ // Auto-exported so it's available as event handler
1127
+ export const loadUser = async (userId) => {
1128
+ loading = true;
1129
+ error = null;
1130
+
1131
+ try {
1132
+ const response = await fetch(`/api/users/${userId}`);
1133
+ user = await response.json();
1134
+ } catch (e) {
1135
+ error = e.message;
1136
+ } finally {
1137
+ loading = false;
1138
+ }
1139
+ };
1140
+
1141
+ // Load user on component mount
1142
+ loadUser(1);
1143
+ ```
1144
+
1145
+ **Pattern 2: Composable Logic**
1146
+
1147
+ ```javascript
1148
+ // utils/counter.js
1149
+ export const createCounter = (initial = 0) => {
1150
+ let count = initial;
1151
+
1152
+ return {
1153
+ increment: () => count++,
1154
+ decrement: () => count--,
1155
+ reset: () => (count = initial),
1156
+ get value() {
1157
+ return count;
1158
+ },
1159
+ };
1160
+ };
1161
+
1162
+ // counter.js (module script)
1163
+ import { createCounter } from "./utils/counter.js";
1164
+
1165
+ const counter = createCounter(0);
1166
+
1167
+ export const increment = () => counter.increment();
1168
+ export const decrement = () => counter.decrement();
1169
+ export const reset = () => counter.reset();
1170
+ ```
1171
+
1172
+ **Pattern 3: Shared State Between Components**
1173
+
1174
+ ```javascript
1175
+ // store.js - shared module
1176
+ export let globalState = {
1177
+ user: null,
1178
+ notifications: [],
1179
+ theme: "light",
1180
+ };
1181
+
1182
+ export const updateUser = (user) => {
1183
+ globalState.user = user;
1184
+ };
1185
+
1186
+ export const addNotification = (msg) => {
1187
+ globalState.notifications.push(msg);
1188
+ };
1189
+
1190
+ // In component module script:
1191
+ import { globalState, updateUser } from "./store.js";
1192
+
1193
+ let user = globalState.user;
1194
+
1195
+ export const switchTheme = () => {
1196
+ globalState.theme = globalState.theme === "light" ? "dark" : "light";
1197
+ };
1198
+ ```
1199
+
1200
+ **Pattern 4: Event-Driven Updates**
1201
+
1202
+ ```javascript
1203
+ import { $listen, $emit } from "ladrillosjs";
1204
+
1205
+ let items = [];
1206
+ let selectedId = null;
1207
+
1208
+ $listen("item:created", (item) => {
1209
+ items = [...items, item];
1210
+ });
1211
+
1212
+ $listen("item:deleted", (itemId) => {
1213
+ items = items.filter((i) => i.id !== itemId);
1214
+ });
1215
+
1216
+ export const selectItem = (id) => {
1217
+ selectedId = id;
1218
+ $emit("item:selected", { id, item: items.find((i) => i.id === id) });
1219
+ };
1220
+
1221
+ export const deleteItem = (id) => {
1222
+ $emit("item:delete-request", { id });
1223
+ };
1224
+ ```
1225
+
837
1226
  ### Shadow DOM
838
1227
 
839
1228
  Components use Shadow DOM by default for style encapsulation:
@@ -1108,7 +1497,8 @@ $listen(eventName: string, callback: (data?) => void): () => void
1108
1497
  $querySelector(selector: string): Element | null
1109
1498
  $querySelectorAll(selector: string): NodeListOf<Element>
1110
1499
 
1111
- // Reactive variables (for external modules)
1500
+ // Manual reactive initialization (optional - mainly for backward compatibility)
1501
+ // Module scripts automatically initialize and sync variables
1112
1502
  $reactive(name: string, initialValue: any): (value: any) => void
1113
1503
  ```
1114
1504
 
@@ -0,0 +1,19 @@
1
+ "use strict";var X=Object.defineProperty,J=Object.defineProperties;var V=Object.getOwnPropertyDescriptors;var L=Object.getOwnPropertySymbols;var Y=Object.prototype.hasOwnProperty,Q=Object.prototype.propertyIsEnumerable;var z=t=>{throw TypeError(t)};var _=(t,e,r)=>e in t?X(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,m=(t,e)=>{for(var r in e||(e={}))Y.call(e,r)&&_(t,r,e[r]);if(L)for(var r of L(e))Q.call(e,r)&&_(t,r,e[r]);return t},h=(t,e)=>J(t,V(e));var U=(t,e,r)=>e.has(t)||z("Cannot "+r);var N=(t,e,r)=>e.has(t)?z("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r);var b=(t,e,r)=>(U(t,e,"access private method"),r);var p=(t,e,r)=>new Promise((s,o)=>{var i=c=>{try{l(r.next(c))}catch(d){o(d)}},a=c=>{try{l(r.throw(c))}catch(d){o(d)}},l=c=>c.done?s(c.value):Promise.resolve(c.value).then(i,a);l((r=r.apply(t,e)).next())});const H=()=>{try{return!1}catch(t){return process.env.NODE_ENV==="development"}},n={log(t,...e){H()&&console.log(t,...e)},error(t,...e){console.error(t,...e)},warn(t,...e){H()&&console.warn(t,...e)}},g=(t,e)=>{const r=[t];return e&&(e.componentName&&r.push(`
2
+ Component: <${e.componentName}>`),e.componentPath&&r.push(`
3
+ File: ${e.componentPath}`),e.expression&&r.push(`
4
+ Expression: ${e.expression}`),e.attributeName&&r.push(`
5
+ Attribute: ${e.attributeName}`),e.eventType&&r.push(`
6
+ Event: ${e.eventType}`),e.elementTag&&r.push(`
7
+ Element: <${e.elementTag}>`),e.lineHint&&r.push(`
8
+ Location: ${e.lineHint}`)),r.join("")},Z=(t,e,r)=>{const s=g("⚠️ Binding Error: Failed to evaluate expression",h(m({},r),{expression:t,lineHint:(r==null?void 0:r.lineHint)||"Template binding expression"}));n.error(s),n.error(` Error details: ${e.message}`),e.stack&&console.debug(" Stack trace:",e.stack)},ee=(t,e,r,s)=>{const o=g("⚠️ Event Handler Error: Failed to execute handler",h(m({},s),{eventType:t,expression:e,lineHint:(s==null?void 0:s.lineHint)||`on${t} handler`}));n.error(o),n.error(` Error details: ${r.message}`),r.stack&&console.debug(" Stack trace:",r.stack)},te=(t,e,r)=>{const s=g("⚠️ Conditional Error: Failed to evaluate condition",h(m({},r),{expression:t,lineHint:(r==null?void 0:r.lineHint)||"$if/$else-if condition"}));n.error(s),n.error(` Error details: ${e.message}`),e.stack&&console.debug(" Stack trace:",e.stack)},re=(t,e,r)=>{const s=g("⚠️ Loop Error: Failed to process loop",h(m({},r),{expression:t,lineHint:(r==null?void 0:r.lineHint)||"$for loop expression"}));n.error(s),n.error(` Error details: ${e.message}`),e.stack&&console.debug(" Stack trace:",e.stack)},M=(t,e,r)=>{const s=g("⚠️ Registration Error: Failed to register component",{componentName:t,componentPath:e});n.error(s),n.error(` Error details: ${r.message}`),r.stack&&console.debug(" Stack trace:",r.stack)},x=(t,e,r)=>{const s=g("⚠️ Fetch Error: Failed to load resource",h(m({},r),{componentPath:t}));n.error(s),n.error(` Error details: ${e.message}`)},P=(t,e)=>{const r=g(`⚠️ Parse Error: ${t}`,e);n.error(r)},se=(t,e)=>{const r=g("⚠️ Script Error: Failed to execute component script",e);n.error(r),n.error(` Error details: ${t.message}`),t.stack&&console.debug(" Stack trace:",t.stack)},oe=(t,e,r)=>{const s=g("⚠️ Two-Way Binding Error: Failed to setup binding",h(m({},r),{expression:t,lineHint:(r==null?void 0:r.lineHint)||"$model binding"}));n.error(s),n.error(` Error details: ${e.message}`)},ne=(t,e)=>{var r;return m({componentName:(t==null?void 0:t.tagName)||((r=t==null?void 0:t.constructor)==null?void 0:r.name),componentPath:(t==null?void 0:t.sourcePath)||(t==null?void 0:t._sourcePath)},e)},u=new Map,ie=25,le=t=>{const e=u.get(t);return e&&(u.delete(t),u.set(t,e)),e},ae=(t,e)=>{if(u.has(t))u.delete(t);else if(u.size>=ie){const r=u.keys().next().value;r&&u.delete(r)}u.set(t,e)},T=t=>p(null,null,function*(){if(!t)throw new Error("Path cannot be null or empty");const e=le(t);if(e)return e;try{const r=yield fetch(t);if(!r.ok)throw new Error(`Failed to fetch component from ${t}: ${r.statusText}`);const s=yield r.text();return ae(t,s),s}catch(r){x(t,r,{componentPath:t})}}),ce=t=>p(null,null,function*(){try{const e=yield fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);return yield e.text()}catch(e){return x(t,e),""}}),$={bindings:/{([^}]+)}/g,comments:{js:/\/\*[\s\S]*?\*\/|\/\/.*$/gm,css:/\/\*[\s\S]*?\*\//g,html:/<!--[\s\S]*?-->/g}},de=new DOMParser,A=(t,e)=>p(null,null,function*(){const r=pe(t),{scripts:s,externalScripts:o}=ge(r),i=yield he(r),a=r.body.innerHTML.trim();return{tagName:e,template:a,scripts:s,externalScripts:o,styles:i}}),pe=t=>de.parseFromString(t.replace($.comments.html,""),"text/html"),ue=t=>["/@vite/","/__vite","/webpack-dev-server","/hot-update","/__webpack_hmr","/browser-sync/","/livereload.js"].some(r=>t.includes(r)),ge=t=>{var s,o;const e=[],r=[];for(const i of t.querySelectorAll("script")){if(i.src){if(ue(i.src)){i.remove();continue}const a=i.hasAttribute("external");r.push({src:i.getAttribute("src")||i.src,type:(s=i.type)!=null?s:null,external:a})}else if(i.textContent){let a=i.textContent.trim();a=a.replace($.comments.js,"").trim(),e.push({content:a,type:(o=i.type)!=null?o:null})}i.remove()}return{scripts:e,externalScripts:r}},me=t=>{const e=t.match(/const __vite__css = "((?:[^"\\]|\\.)*)"/);if(e&&e[1])return e[1].replace(/\\r\\n/g,`
9
+ `).replace(/\\n/g,`
10
+ `).replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\");const r=t.match(/export\s+default\s+"((?:[^"\\]|\\.)*)"/);return r&&r[1]?r[1].replace(/\\r\\n/g,`
11
+ `).replace(/\\n/g,`
12
+ `).replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\"):t.includes("import")||t.includes("export")?(n.warn("CSS file returned JavaScript module format. CSS may not load correctly."),""):t},he=t=>p(null,null,function*(){let e="";const r=t.querySelectorAll("style, link[rel='stylesheet']");for(const s of r){if(s.tagName==="LINK"){const i=yield ce(s.href),a=me(i);a&&(e+=`
13
+ `+a)}else if(s.tagName==="STYLE"){const o=s;if(o.textContent){let i=o.textContent.trim();i=i.replace($.comments.css,"").trim(),e+=`
14
+ `+i}}s.remove()}return e.trim()});var E,q,F;class fe{constructor(){N(this,E);this.components={},this.lazyComponents=new Set,this.intersectionObserver=null,this.lazyLoadingInProgress=new Map,this.lazyComponentsLoaded=new Set}registerComponent(e,r,s=!0,o=!1){return p(this,null,function*(){if(this.components[e]){n.warn(`Component with name "${e}" is already registered.`);return}if(o){this.lazyComponents.add(e),b(this,E,q).call(this,e,r,s),n.log(`Component ${e} registered as lazy-loaded`);return}try{const i=yield T(r),a=yield A(i,e);this.components[e]={tagName:e,template:a.template,scripts:a.scripts,externalScripts:a.externalScripts,styles:a.styles,sourcePath:r,lazy:!1},n.log(`Component ${e} registered successfully`),yield b(this,E,F).call(this,e,s)}catch(i){M(e,r,i);return}})}}E=new WeakSet,q=function(e,r,s){const o=this;class i extends HTMLElement{constructor(){super(),this.loaded=!1,this.observer=null,s&&(this.attachShadow({mode:"open"}),this.shadowRoot&&(this.shadowRoot.innerHTML=`
15
+ <style>
16
+ :host { display: block; min-height: 1px; }
17
+ </style>
18
+ `))}connectedCallback(){if(!this.loaded){if(this.hasAttribute("eager")){this.loaded=!0,this.loadComponent();return}this.observer=new IntersectionObserver(l=>{l.forEach(c=>{c.isIntersecting&&!this.loaded&&(this.loaded=!0,this.loadComponent())})},{rootMargin:"100px"}),this.observer.observe(this)}}disconnectedCallback(){this.observer&&(this.observer.disconnect(),this.observer=null)}loadComponent(){return p(this,null,function*(){try{if(o.lazyComponentsLoaded.has(e)){n.log(`Component ${e} already loaded, upgrading placeholder...`),this.upgradePlaceholder();return}if(o.lazyLoadingInProgress.has(e)){n.log(`Component ${e} is already loading, waiting...`),yield o.lazyLoadingInProgress.get(e),this.upgradePlaceholder();return}const l=this.performLoad();o.lazyLoadingInProgress.set(e,l),yield l,o.lazyLoadingInProgress.delete(e),o.lazyComponentsLoaded.add(e),o.lazyComponents.delete(e),n.log(`Component ${e} lazy-loaded successfully`)}catch(l){o.lazyLoadingInProgress.delete(e),M(e,r,l)}})}performLoad(){return p(this,null,function*(){n.log(`Lazy loading component: ${e}`);const l=this.parentNode;if(this.nextSibling,!l){P(`Placeholder for ${e} has no parent node`,{componentName:e,componentPath:r});return}const c=yield T(r),d=yield A(c,e);n.log(`Component ${e} parsed successfully`),o.components[e]={tagName:e,template:d.template,scripts:d.scripts,externalScripts:d.externalScripts,styles:d.styles,sourcePath:r,lazy:!0};const f=`${e}-real`;n.log(`Defining real component with temp name: ${f}`);const y=o.components[e].tagName;o.components[e].tagName=f;const{defineWebComponent:C}=yield Promise.resolve().then(()=>require("./webcomponent-BdxW-3sK.js"));C(o.components[e],s),n.log(`Real component ${f} defined`),o.components[e].tagName=y,this.upgradePlaceholder()})}upgradePlaceholder(){const l=this,c=this.parentNode,d=this.nextSibling;if(!c){P(`Placeholder for ${e} has no parent node`,{componentName:e,componentPath:r});return}const f=`${e}-real`,y=document.createElement(f);for(n.log(`Created real component instance: ${f}`),Array.from(l.attributes).forEach(C=>{C.name!=="eager"&&y.setAttribute(C.name,C.value)});l.firstChild;)y.appendChild(l.firstChild);d?(c.insertBefore(y,d),n.log("Inserted real component before next sibling")):(c.appendChild(y),n.log("Appended real component to parent")),c.removeChild(l),n.log("Removed placeholder element")}}customElements.get(e)||customElements.define(e,i)},F=function(e,r){return p(this,null,function*(){const{defineWebComponent:s}=yield Promise.resolve().then(()=>require("./webcomponent-BdxW-3sK.js"));this.components[e]&&s(this.components[e],r)})};const R=new fe;class ye{constructor(){this.listeners=new Map}emit(e,r){const s=new CustomEvent(e,{detail:r,bubbles:!0,composed:!0});document.dispatchEvent(s);const o=this.listeners.get(e);if(!o||o.size===0)return Promise.resolve();const i=[];return o.forEach(a=>{try{const l=a(r);l instanceof Promise&&i.push(l)}catch(l){n.error(`⚠️ Event Bus Error: Failed to execute listener for "${e}"`),n.error(` Error details: ${l.message}`),i.push(Promise.reject(l))}}),i.length>0?Promise.all(i).then(()=>{}):Promise.resolve()}listen(e,r){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(r),()=>{this.off(e,r)}}off(e,r){const s=this.listeners.get(e);s&&(s.delete(r),s.size===0&&this.listeners.delete(e))}clear(e){e?this.listeners.delete(e):this.listeners.clear()}listenerCount(e){var r,s;return(s=(r=this.listeners.get(e))==null?void 0:r.size)!=null?s:0}}const k=new ye,w={};function we(t={}){const{src:e="components",dest:r="components",copyOnDev:s=!1}=t;return{name:"ladrillosjs:copy-components",apply:s?"serve":"build",generateBundle(i,a){return p(this,null,function*(){const l=w.resolve(process.cwd(),e),c=w.resolve(process.cwd(),"dist",r);if(!w.existsSync(l)){console.warn(`[ladrillosjs:copy-components] Source directory not found: ${l}`);return}try{w.existsSync(c)&&w.rmSync(c,{recursive:!0,force:!0}),w.cpSync(l,c,{recursive:!0}),console.log(`[ladrillosjs:copy-components] Copied components from ${l} to ${c}`)}catch(d){throw console.error("[ladrillosjs:copy-components] Error copying components:",d),d}})}}}const B=(t,e,r,s)=>R.registerComponent(t,e,r,s),j=t=>p(null,null,function*(){yield Promise.all(t.map(({name:e,path:r,useShadowDOM:s,lazy:o})=>R.registerComponent(e,r,s,o)))}),I=(t,e)=>k.listen(t,e),D=(t,e)=>{k.emit(t,e)},Ee=(t,e)=>{if(e){const r=e.tagName.toLowerCase();window.__ladrilloContexts||(window.__ladrilloContexts=new Map),window.__ladrilloContexts.set(r,{shadowRoot:t,element:e})}},v=()=>{const t=window.__ladrilloContexts;if(t&&t.size>0){const e=Array.from(t.values());return e[e.length-1]}return null},W=()=>{const t=v();return t&&t.element?t.element.state||{}:{}},S=t=>{const e=v();e&&e.setState&&e.setState(t)},O=(t,e)=>(S({[t]:e}),r=>{S({[t]:r})}),G=(t,e)=>{if(e)return e.querySelector(t);const r=v();if(r){const s=r.shadowRoot||r.element;if(s){const o=s.querySelector(t);if(o)return o}}return document.querySelector(t)},K=(t,e)=>{if(e)return e.querySelectorAll(t);const r=v();if(r){const s=r.shadowRoot||r.element;if(s){const o=s.querySelectorAll(t);if(o.length>0)return o}}return document.querySelectorAll(t)};typeof window!="undefined"&&(window.ladrillosjs={registerComponent:B,registerComponents:j},window.$listen=I,window.$emit=D,window.$querySelector=G,window.$querySelectorAll=K,window.$reactive=O,window.$setState=S,window.$getState=W);exports.$emit=D;exports.$getState=W;exports.$listen=I;exports.$querySelector=G;exports.$querySelectorAll=K;exports.$reactive=O;exports.$setState=S;exports.REGEX_PATTERNS=$;exports.__setComponentContext=Ee;exports.copyComponentsPlugin=we;exports.createErrorContext=ne;exports.eventBus=k;exports.logBindingError=Z;exports.logConditionalError=te;exports.logEventHandlerError=ee;exports.logLoopError=re;exports.logParseError=P;exports.logScriptError=se;exports.logTwoWayBindingError=oe;exports.logger=n;exports.registerComponent=B;exports.registerComponents=j;
19
+ //# sourceMappingURL=index-CBW3yTb-.js.map