slicejs-web-framework 1.0.28 → 1.0.31
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/Slice/Components/Structural/Controller/Controller.js +125 -12
- package/Slice/Components/Structural/Debugger/Debugger.css +590 -65
- package/Slice/Components/Structural/Debugger/Debugger.html +72 -9
- package/Slice/Components/Structural/Debugger/Debugger.js +529 -216
- package/Slice/Components/Structural/Router/EventThrottler.js +110 -0
- package/Slice/Components/Structural/Router/RouteCache.js +245 -0
- package/Slice/Components/Structural/Router/RouteMatcher.js +236 -0
- package/Slice/Components/Structural/Router/RouteRenderer.js +324 -0
- package/Slice/Components/Structural/Router/Router.js +315 -240
- package/Slice/Slice.js +5 -0
- package/package.json +1 -1
- package/src/Components/Visual/Button/Button.js +40 -17
|
@@ -110,6 +110,14 @@ export default class Controller {
|
|
|
110
110
|
return this.componentCategories.get(componentSliceId);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/*
|
|
114
|
+
Fetches a text resource (HTML, CSS, theme, or styles) for a component.
|
|
115
|
+
@param {string} componentName - The name of the component.
|
|
116
|
+
@param {string} resourceType - The type of resource to fetch ('html', 'css', 'theme', or 'styles').
|
|
117
|
+
@param {string} [componentCategory] - Optional category of the component.
|
|
118
|
+
@param {string} [customPath] - Optional custom path to fetch the resource from.
|
|
119
|
+
@returns {Promise<string>} - A promise that resolves to the fetched text.
|
|
120
|
+
*/
|
|
113
121
|
async fetchText(componentName, resourceType, componentCategory, customPath) {
|
|
114
122
|
try {
|
|
115
123
|
const baseUrl = window.location.origin;
|
|
@@ -121,9 +129,20 @@ export default class Controller {
|
|
|
121
129
|
|
|
122
130
|
let isVisual = resourceType === 'html' || resourceType === 'css';
|
|
123
131
|
|
|
124
|
-
if(isVisual) {
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
if (isVisual) {
|
|
133
|
+
// ✅ CORREGIDO: Verificar que la categoría existe y agregar baseUrl
|
|
134
|
+
if (slice.paths.components[componentCategory]) {
|
|
135
|
+
path = `${baseUrl}${slice.paths.components[componentCategory].path}/${componentName}`;
|
|
136
|
+
resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
|
|
137
|
+
} else {
|
|
138
|
+
// ✅ FALLBACK: Para componentes Structural o categorías no configuradas
|
|
139
|
+
if (componentCategory === 'Structural') {
|
|
140
|
+
path = `${baseUrl}/Slice/Components/Structural/${componentName}`;
|
|
141
|
+
resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
|
|
142
|
+
} else {
|
|
143
|
+
throw new Error(`Component category '${componentCategory}' not found in paths configuration`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
127
146
|
}
|
|
128
147
|
|
|
129
148
|
if (resourceType === 'theme') {
|
|
@@ -134,35 +153,129 @@ export default class Controller {
|
|
|
134
153
|
path = `${baseUrl}${slice.paths.styles}/${componentName}.css`;
|
|
135
154
|
}
|
|
136
155
|
|
|
137
|
-
if(customPath){
|
|
156
|
+
if (customPath) {
|
|
138
157
|
path = customPath;
|
|
139
158
|
}
|
|
140
159
|
|
|
160
|
+
// ✅ MEJORADO: Logging para debugging
|
|
161
|
+
slice.logger.logInfo('Controller', `Fetching ${resourceType} from: ${path}`);
|
|
162
|
+
|
|
141
163
|
const response = await fetch(path);
|
|
142
164
|
|
|
143
165
|
if (!response.ok) {
|
|
144
166
|
throw new Error(`Failed to fetch ${path}: ${response.statusText}`);
|
|
145
167
|
}
|
|
146
168
|
|
|
147
|
-
const
|
|
148
|
-
|
|
169
|
+
const content = await response.text();
|
|
170
|
+
slice.logger.logInfo('Controller', `Successfully fetched ${resourceType} for ${componentName}`);
|
|
171
|
+
return content;
|
|
149
172
|
} catch (error) {
|
|
150
173
|
slice.logger.logError('Controller', `Error fetching ${resourceType} for component ${componentName}:`, error);
|
|
151
|
-
//
|
|
152
|
-
|
|
174
|
+
// ✅ CORREGIDO: Re-lanzar el error para que el debugger pueda manejarlo
|
|
175
|
+
throw error;
|
|
153
176
|
}
|
|
154
177
|
}
|
|
155
178
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
179
|
setComponentProps(component, props) {
|
|
180
|
+
const ComponentClass = component.constructor;
|
|
181
|
+
const componentName = ComponentClass.name;
|
|
182
|
+
|
|
183
|
+
// ✅ Aplicar defaults si tiene static props
|
|
184
|
+
if (ComponentClass.props) {
|
|
185
|
+
this.applyDefaultProps(component, ComponentClass.props, props);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ✅ Validar solo en desarrollo
|
|
189
|
+
if (ComponentClass.props && !slice.isProduction()) {
|
|
190
|
+
this.validatePropsInDevelopment(ComponentClass, props, componentName);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ✅ CÓDIGO EXISTENTE: Aplicar props
|
|
160
194
|
for (const prop in props) {
|
|
161
195
|
component[`_${prop}`] = null;
|
|
162
196
|
component[prop] = props[prop];
|
|
163
197
|
}
|
|
164
198
|
}
|
|
165
199
|
|
|
200
|
+
getComponentPropsForDebugger(component) {
|
|
201
|
+
const ComponentClass = component.constructor;
|
|
202
|
+
|
|
203
|
+
if (ComponentClass.props) {
|
|
204
|
+
// Si tiene props estáticos, usar esos como referencia
|
|
205
|
+
return {
|
|
206
|
+
availableProps: Object.keys(ComponentClass.props),
|
|
207
|
+
propsConfig: ComponentClass.props,
|
|
208
|
+
usedProps: this.extractUsedProps(component, ComponentClass.props)
|
|
209
|
+
};
|
|
210
|
+
} else {
|
|
211
|
+
// Si no tiene props estáticos, usar modo legacy
|
|
212
|
+
return {
|
|
213
|
+
availableProps: this.extractUsedProps(component),
|
|
214
|
+
propsConfig: null,
|
|
215
|
+
usedProps: this.extractUsedProps(component)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
applyDefaultProps(component, staticProps, providedProps) {
|
|
221
|
+
Object.entries(staticProps).forEach(([prop, config]) => {
|
|
222
|
+
if (config.default !== undefined && !(prop in (providedProps || {}))) {
|
|
223
|
+
component[`_${prop}`] = null;
|
|
224
|
+
component[prop] = config.default;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
validatePropsInDevelopment(ComponentClass, providedProps, componentName) {
|
|
230
|
+
const staticProps = ComponentClass.props;
|
|
231
|
+
const usedProps = Object.keys(providedProps || {});
|
|
232
|
+
|
|
233
|
+
const availableProps = Object.keys(staticProps);
|
|
234
|
+
const unknownProps = usedProps.filter(prop => !availableProps.includes(prop));
|
|
235
|
+
|
|
236
|
+
if (unknownProps.length > 0) {
|
|
237
|
+
slice.logger.logWarning(
|
|
238
|
+
'PropsValidator',
|
|
239
|
+
`${componentName}: Unknown props [${unknownProps.join(', ')}]. Available: [${availableProps.join(', ')}]`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const requiredProps = Object.entries(staticProps)
|
|
244
|
+
.filter(([_, config]) => config.required)
|
|
245
|
+
.map(([prop, _]) => prop);
|
|
246
|
+
|
|
247
|
+
const missingRequired = requiredProps.filter(prop => !(prop in (providedProps || {})));
|
|
248
|
+
if (missingRequired.length > 0) {
|
|
249
|
+
slice.logger.logError(
|
|
250
|
+
componentName,
|
|
251
|
+
`Missing required props: [${missingRequired.join(', ')}]`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
extractUsedProps(component, staticProps = null) {
|
|
257
|
+
const usedProps = {};
|
|
258
|
+
|
|
259
|
+
if (staticProps) {
|
|
260
|
+
// Si tiene props estáticos, buscar solo esos
|
|
261
|
+
Object.keys(staticProps).forEach(prop => {
|
|
262
|
+
if (component[prop] !== undefined) {
|
|
263
|
+
usedProps[prop] = component[prop];
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
} else {
|
|
267
|
+
// Modo legacy: buscar cualquier prop que empiece con _
|
|
268
|
+
Object.getOwnPropertyNames(component).forEach(key => {
|
|
269
|
+
if (key.startsWith('_') && key !== '_isActive') {
|
|
270
|
+
const propName = key.substring(1);
|
|
271
|
+
usedProps[propName] = component[propName];
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return usedProps;
|
|
277
|
+
}
|
|
278
|
+
|
|
166
279
|
destroyComponent(component) {
|
|
167
280
|
const sliceId = component.sliceId;
|
|
168
281
|
this.activeComponents.delete(sliceId);
|
|
@@ -172,4 +285,4 @@ export default class Controller {
|
|
|
172
285
|
|
|
173
286
|
function getRelativePath(levels) {
|
|
174
287
|
return '../'.repeat(levels);
|
|
175
|
-
}
|
|
288
|
+
}
|