slicejs-web-framework 3.0.0 → 3.1.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 (118) hide show
  1. package/.worktrees/public-env-browser-exposure/LICENSE +21 -0
  2. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/ContextManager/ContextManager.js +369 -0
  3. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +297 -0
  4. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Controller/Controller.js +972 -0
  5. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.css +620 -0
  6. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.html +73 -0
  7. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.js +1548 -0
  8. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/EventManager/EventManager.js +338 -0
  9. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/EventManager/EventManagerDebugger.js +361 -0
  10. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Logger/Log.js +10 -0
  11. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Logger/Logger.js +146 -0
  12. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Router/Router.js +721 -0
  13. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/StylesManager/StylesManager.js +78 -0
  14. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/StylesManager/ThemeManager/ThemeManager.js +84 -0
  15. package/.worktrees/public-env-browser-exposure/Slice/Slice.js +533 -0
  16. package/.worktrees/public-env-browser-exposure/Slice/tests/bundle-v2-runtime-contract.test.js +268 -0
  17. package/.worktrees/public-env-browser-exposure/Slice/tests/public-env-runtime-accessors.test.js +44 -0
  18. package/.worktrees/public-env-browser-exposure/Slice/tests/router-loading-finally.test.js +68 -0
  19. package/.worktrees/public-env-browser-exposure/api/index.js +286 -0
  20. package/.worktrees/public-env-browser-exposure/api/middleware/securityMiddleware.js +253 -0
  21. package/.worktrees/public-env-browser-exposure/api/tests/public-env-resolver.test.js +193 -0
  22. package/.worktrees/public-env-browser-exposure/api/utils/publicEnvResolver.js +117 -0
  23. package/.worktrees/public-env-browser-exposure/package.json +37 -0
  24. package/.worktrees/public-env-browser-exposure/sliceConfig.schema.json +109 -0
  25. package/.worktrees/public-env-browser-exposure/src/App/index.html +22 -0
  26. package/.worktrees/public-env-browser-exposure/src/App/index.js +23 -0
  27. package/.worktrees/public-env-browser-exposure/src/App/style.css +40 -0
  28. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.css +201 -0
  29. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.html +37 -0
  30. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.js +210 -0
  31. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.css +12 -0
  32. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.html +0 -0
  33. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.js +111 -0
  34. package/.worktrees/public-env-browser-exposure/src/Components/Service/FetchManager/FetchManager.js +133 -0
  35. package/.worktrees/public-env-browser-exposure/src/Components/Service/IndexedDbManager/IndexedDbManager.js +141 -0
  36. package/.worktrees/public-env-browser-exposure/src/Components/Service/LocalStorageManager/LocalStorageManager.js +45 -0
  37. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.css +47 -0
  38. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.html +5 -0
  39. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.js +93 -0
  40. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.css +68 -0
  41. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.html +7 -0
  42. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.js +107 -0
  43. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.css +87 -0
  44. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.html +8 -0
  45. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.js +86 -0
  46. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.css +130 -0
  47. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.html +4 -0
  48. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +262 -0
  49. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.css +70 -0
  50. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.html +9 -0
  51. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.js +76 -0
  52. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.css +60 -0
  53. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.html +5 -0
  54. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.js +63 -0
  55. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.css +7 -0
  56. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.html +1 -0
  57. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.js +57 -0
  58. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.css +510 -0
  59. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.html +1 -0
  60. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.js +89 -0
  61. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.eot +0 -0
  62. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.json +555 -0
  63. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.styl +507 -0
  64. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.svg +1485 -0
  65. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.symbol.svg +1059 -0
  66. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.ttf +0 -0
  67. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.woff +0 -0
  68. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.woff2 +0 -0
  69. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.css +91 -0
  70. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.html +4 -0
  71. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.js +215 -0
  72. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.css +0 -0
  73. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.html +0 -0
  74. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.js +49 -0
  75. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.css +8 -0
  76. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.html +1 -0
  77. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.js +63 -0
  78. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.css +56 -0
  79. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.html +83 -0
  80. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.js +38 -0
  81. package/.worktrees/public-env-browser-exposure/src/Components/Visual/MultiRoute/MultiRoute.js +93 -0
  82. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.css +115 -0
  83. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.html +44 -0
  84. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.js +141 -0
  85. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.css +117 -0
  86. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.html +24 -0
  87. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.js +16 -0
  88. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Route/Route.js +93 -0
  89. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.css +84 -0
  90. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.html +8 -0
  91. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.js +195 -0
  92. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.css +76 -0
  93. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.html +8 -0
  94. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.js +102 -0
  95. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.css +36 -0
  96. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.html +1 -0
  97. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.js +126 -0
  98. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.css +8 -0
  99. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.html +1 -0
  100. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.js +48 -0
  101. package/.worktrees/public-env-browser-exposure/src/Components/components.js +27 -0
  102. package/.worktrees/public-env-browser-exposure/src/Styles/sliceStyles.css +34 -0
  103. package/.worktrees/public-env-browser-exposure/src/Themes/Dark.css +42 -0
  104. package/.worktrees/public-env-browser-exposure/src/Themes/Light.css +31 -0
  105. package/.worktrees/public-env-browser-exposure/src/Themes/Slice.css +47 -0
  106. package/.worktrees/public-env-browser-exposure/src/images/Slice.js-logo.png +0 -0
  107. package/.worktrees/public-env-browser-exposure/src/images/favicon.ico +0 -0
  108. package/.worktrees/public-env-browser-exposure/src/images/im2/Slice.js-logo.png +0 -0
  109. package/.worktrees/public-env-browser-exposure/src/routes.js +16 -0
  110. package/.worktrees/public-env-browser-exposure/src/sliceConfig.json +73 -0
  111. package/.worktrees/public-env-browser-exposure/src/testing.js +888 -0
  112. package/Slice/Slice.js +38 -8
  113. package/Slice/tests/build-js-only-visual-components.test.js +129 -0
  114. package/Slice/tests/public-env-runtime-accessors.test.js +44 -0
  115. package/api/index.js +12 -12
  116. package/api/tests/public-env-resolver.test.js +193 -0
  117. package/api/utils/publicEnvResolver.js +117 -0
  118. package/package.json +1 -1
@@ -0,0 +1,1548 @@
1
+ // ✅ VERSIÓN ANTI-INTERFERENCIA - Aislada del Router y con debugging
2
+
3
+ /**
4
+ * Runtime UI debugger for Slice components.
5
+ */
6
+ export default class Debugger extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this.toggleClick = slice.debuggerConfig.click;
10
+ this.toggle = 'click';
11
+ this.selectedComponentSliceId = null;
12
+ this.isActive = false;
13
+ this.activeTab = 'props';
14
+ this.currentComponent = null;
15
+ this.componentProps = {};
16
+ this.currentEditingProp = null;
17
+ this.currentEditingType = null;
18
+
19
+ // ✅ Flag para prevenir interferencias externas
20
+ this.isDebuggerInput = false;
21
+ }
22
+
23
+ /**
24
+ * Load debugger UI and enable interactions.
25
+ * @returns {Promise<boolean>}
26
+ */
27
+ async enableDebugMode() {
28
+ //const html = await slice.controller.fetchText('Debugger', 'html', 'Structural');
29
+ //const css = await slice.controller.fetchText('Debugger', 'css', 'Structural');
30
+
31
+ const html = productionOnlyHtml();
32
+ const css = productionOnlyCSS();
33
+
34
+ this.innerHTML = html;
35
+ slice.stylesManager.registerComponentStyles('Debugger', css);
36
+
37
+ this.setupElements();
38
+ this.setupEventListeners();
39
+ this.makeDraggable();
40
+
41
+ slice.logger.logInfo('Debugger', 'Advanced Debug mode enabled');
42
+ return true;
43
+ }
44
+
45
+ /**
46
+ * Cache UI elements.
47
+ * @returns {void}
48
+ */
49
+ setupElements() {
50
+ this.debuggerContainer = this.querySelector('#debugger-container');
51
+ this.closeDebugger = this.querySelector('#close-debugger');
52
+ this.propsContainer = this.querySelector('.props-container');
53
+ this.infoContainer = this.querySelector('.info-list');
54
+ this.editorModal = this.querySelector('#editor-modal');
55
+ this.propertyEditor = this.querySelector('#property-editor');
56
+ this.modalTitle = this.querySelector('#modal-title');
57
+ this.validationMessage = this.querySelector('.validation-message');
58
+
59
+ // Header elements
60
+ this.componentName = this.querySelector('.component-name');
61
+ this.componentId = this.querySelector('.component-id');
62
+ }
63
+
64
+ /**
65
+ * Bind UI event listeners.
66
+ * @returns {void}
67
+ */
68
+ setupEventListeners() {
69
+ // Tab navigation
70
+ this.querySelectorAll('.tab-btn').forEach(btn => {
71
+ btn.addEventListener('click', (e) => {
72
+ this.switchTab(e.target.dataset.tab);
73
+ });
74
+ });
75
+
76
+ // Close and minimize
77
+ this.closeDebugger.addEventListener('click', () => {
78
+ this.hide();
79
+ this.isActive = false;
80
+ });
81
+
82
+ // Modal events
83
+ this.querySelector('#modal-close').addEventListener('click', () => {
84
+ this.closeModal();
85
+ });
86
+
87
+ this.querySelector('#modal-cancel').addEventListener('click', () => {
88
+ this.closeModal();
89
+ });
90
+
91
+ this.querySelector('#modal-save').addEventListener('click', () => {
92
+ this.savePropertyValue();
93
+ });
94
+
95
+ // Editor type selector
96
+ this.querySelectorAll('.type-btn').forEach(btn => {
97
+ btn.addEventListener('click', (e) => {
98
+ this.switchEditorType(e.target.dataset.type);
99
+ });
100
+ });
101
+
102
+ // Action buttons
103
+ this.querySelector('#apply-changes')?.addEventListener('click', (e) => {
104
+ e.stopPropagation();
105
+ this.applyAllChanges();
106
+ });
107
+
108
+ this.querySelector('#reset-values')?.addEventListener('click', (e) => {
109
+ e.stopPropagation();
110
+ this.resetValues();
111
+ });
112
+
113
+ // Property editor validation
114
+ this.propertyEditor.addEventListener('input', () => {
115
+ this.validateEditor();
116
+ });
117
+
118
+ // Modal backdrop click
119
+ this.editorModal.addEventListener('click', (e) => {
120
+ if (e.target === this.editorModal) {
121
+ this.closeModal();
122
+ }
123
+ });
124
+
125
+ // ✅ EVENTOS PRINCIPALES - Con protecciÃŗn anti-interferencia
126
+ this.addEventListener('mousedown', (event) => {
127
+ if (event.target.classList.contains('prop-control')) {
128
+ this.isDebuggerInput = true;
129
+ // Prevenir interferencias del Router u otros sistemas
130
+ event.stopPropagation();
131
+ }
132
+ });
133
+
134
+ this.addEventListener('focus', (event) => {
135
+ if (event.target.classList.contains('prop-control')) {
136
+ this.isDebuggerInput = true;
137
+ event.stopPropagation();
138
+ }
139
+ }, true);
140
+
141
+ this.addEventListener('blur', (event) => {
142
+ if (event.target.classList.contains('prop-control')) {
143
+ this.isDebuggerInput = false;
144
+ }
145
+ }, true);
146
+
147
+ this.addEventListener('keypress', (event) => {
148
+ if (event.key === 'Enter' && event.target.classList.contains('prop-control')) {
149
+ event.preventDefault();
150
+ event.stopPropagation();
151
+ this.applyPropertyChange(event.target);
152
+ }
153
+ });
154
+
155
+ this.addEventListener('change', (event) => {
156
+ if (event.target.type === 'checkbox' && event.target.classList.contains('prop-control')) {
157
+ event.stopPropagation();
158
+ this.applyPropertyChange(event.target);
159
+ }
160
+ });
161
+
162
+ // ✅ PROTECCIÓN GLOBAL: Prevenir que eventos externos interfieran
163
+ this.addEventListener('click', (event) => {
164
+ if (this.contains(event.target)) {
165
+ event.stopPropagation();
166
+ }
167
+ });
168
+
169
+ // ✅ Los eventos DOMNodeInserted/Removed estÃĄn deprecated,
170
+ // pero la protecciÃŗn con stopPropagation() ya es suficiente
171
+ }
172
+
173
+ /**
174
+ * Switch active tab.
175
+ * @param {string} tabName
176
+ * @returns {void}
177
+ */
178
+ switchTab(tabName) {
179
+ this.activeTab = tabName;
180
+
181
+ this.querySelectorAll('.tab-btn').forEach(btn => {
182
+ btn.classList.toggle('active', btn.dataset.tab === tabName);
183
+ });
184
+
185
+ this.querySelectorAll('.tab-pane').forEach(pane => {
186
+ pane.classList.toggle('active', pane.id === `${tabName}-tab`);
187
+ });
188
+ }
189
+
190
+ /**
191
+ * Switch editor type (json | function).
192
+ * @param {string} type
193
+ * @returns {void}
194
+ */
195
+ switchEditorType(type) {
196
+ const normalized = this.normalizeEditorType(type);
197
+ if (!normalized) {
198
+ return;
199
+ }
200
+ this.querySelectorAll('.type-btn').forEach(btn => {
201
+ btn.classList.toggle('active', btn.dataset.type === normalized);
202
+ });
203
+ this.currentEditingType = normalized;
204
+ }
205
+
206
+ /**
207
+ * Normalize editor type to supported values.
208
+ * @param {string} type
209
+ * @returns {string|null}
210
+ */
211
+ normalizeEditorType(type) {
212
+ if (type === 'json' || type === 'function') {
213
+ return type;
214
+ }
215
+ return null;
216
+ }
217
+
218
+ /**
219
+ * Attach debugger toggle handler to a component.
220
+ * @param {HTMLElement} component
221
+ * @returns {void}
222
+ */
223
+ attachDebugMode(component) {
224
+ if (this.toggleClick === 'right') {
225
+ this.toggle = 'contextmenu';
226
+ } else {
227
+ this.toggle = 'click';
228
+ }
229
+ component.addEventListener(this.toggle, (event) => this.handleDebugClick(event, component));
230
+ }
231
+
232
+ /**
233
+ * Enable drag interaction for the debugger panel.
234
+ * @returns {void}
235
+ */
236
+ makeDraggable() {
237
+ let offset = { x: 0, y: 0 };
238
+ let isDragging = false;
239
+
240
+ const header = this.querySelector('.debugger-header');
241
+
242
+ header.addEventListener('mousedown', (event) => {
243
+ isDragging = true;
244
+ offset.x = event.clientX - this.debuggerContainer.getBoundingClientRect().left;
245
+ offset.y = event.clientY - this.debuggerContainer.getBoundingClientRect().top;
246
+ header.style.cursor = 'grabbing';
247
+ });
248
+
249
+ document.addEventListener('mousemove', (event) => {
250
+ if (isDragging) {
251
+ const x = event.clientX - offset.x;
252
+ const y = event.clientY - offset.y;
253
+ this.debuggerContainer.style.left = `${x}px`;
254
+ this.debuggerContainer.style.top = `${y}px`;
255
+ this.debuggerContainer.style.right = 'auto';
256
+ }
257
+ });
258
+
259
+ document.addEventListener('mouseup', () => {
260
+ if (isDragging) {
261
+ isDragging = false;
262
+ header.style.cursor = 'grab';
263
+ }
264
+ });
265
+ }
266
+
267
+ /**
268
+ * Handle toggle click and load component info.
269
+ * @param {Event} event
270
+ * @param {HTMLElement} component
271
+ * @returns {void}
272
+ */
273
+ handleDebugClick(event, component) {
274
+ event.preventDefault();
275
+ event.stopPropagation();
276
+
277
+ this.selectedComponentSliceId = component.sliceId;
278
+ this.currentComponent = component;
279
+ this.isActive = true;
280
+
281
+ // Update header info
282
+ this.componentName.textContent = component.constructor.name;
283
+ this.componentId.textContent = `ID: ${component.sliceId}`;
284
+
285
+ // Gather component data
286
+ const realComponentProps = this.getComponentPropsForDebugger(component);
287
+ this.componentProps = {};
288
+
289
+ realComponentProps.forEach((attr) => {
290
+ if (component[attr] === undefined) {
291
+ this.componentProps[attr] = component[`_${attr}`];
292
+ } else {
293
+ this.componentProps[attr] = component[attr];
294
+ }
295
+ });
296
+
297
+ // ✅ Crear UI sin interferencias
298
+ this.updateDebuggerContent();
299
+ this.debuggerContainer.classList.add('active');
300
+ }
301
+
302
+ updateDebuggerContent() {
303
+ this.updatePropsTab();
304
+ this.updateInfoTab();
305
+ }
306
+
307
+ /**
308
+ * Render props tab content.
309
+ * @returns {void}
310
+ */
311
+ updatePropsTab() {
312
+ const propsContainer = this.querySelector('.props-container');
313
+ if (!propsContainer) {
314
+ return;
315
+ }
316
+
317
+ propsContainer.innerHTML = '';
318
+
319
+ const realComponentProps = this.getComponentPropsForDebugger(this.currentComponent);
320
+ const ComponentClass = this.currentComponent.constructor;
321
+ const configuredProps = ComponentClass.props || {};
322
+
323
+ realComponentProps.forEach(prop => {
324
+ const propElement = this.createPropElement(prop, configuredProps[prop]);
325
+ propsContainer.appendChild(propElement);
326
+ });
327
+ }
328
+
329
+ /**
330
+ * Build a prop row element.
331
+ * @param {string} prop
332
+ * @param {Object} [config]
333
+ * @returns {HTMLElement}
334
+ */
335
+ createPropElement(prop, config = {}) {
336
+ const propWrapper = document.createElement('div');
337
+ propWrapper.className = 'prop-item';
338
+ propWrapper.dataset.prop = prop;
339
+
340
+ const currentValue = this.currentComponent[prop];
341
+ const valueType = this.getValueType(currentValue);
342
+
343
+ // Status based on usage
344
+ let status, statusClass;
345
+ if (currentValue !== undefined && currentValue !== null) {
346
+ status = 'Used';
347
+ statusClass = 'status-used';
348
+ } else if (config.required) {
349
+ status = 'Missing';
350
+ statusClass = 'status-missing';
351
+ } else {
352
+ status = 'Optional';
353
+ statusClass = 'status-optional';
354
+ }
355
+
356
+ propWrapper.innerHTML = `
357
+ <div class="prop-header">
358
+ <div class="prop-title">
359
+ <strong>${prop}</strong>
360
+ <span class="prop-type">${valueType}</span>
361
+ </div>
362
+ <div class="prop-status ${statusClass}">${status}</div>
363
+ </div>
364
+ <div class="prop-input">
365
+ ${this.createInputForType(prop, currentValue, valueType, config)}
366
+ </div>
367
+ ${config.default !== undefined ? `<div class="default-value">Default: ${JSON.stringify(config.default)}</div>` : ''}
368
+ `;
369
+
370
+ return propWrapper;
371
+ }
372
+
373
+ /**
374
+ * Build input HTML for a prop type.
375
+ * @param {string} prop
376
+ * @param {any} value
377
+ * @param {string} type
378
+ * @param {Object} [config]
379
+ * @returns {string}
380
+ */
381
+ createInputForType(prop, value, type, config = {}) {
382
+ const serializedValue = this.serializeValue(value);
383
+
384
+ if (type === 'boolean') {
385
+ return `
386
+ <div class="input-group">
387
+ <input type="checkbox"
388
+ class="prop-control debugger-input"
389
+ data-prop="${prop}"
390
+ ${value ? 'checked' : ''}
391
+ data-debugger-input="true">
392
+ <span class="checkbox-label">${value ? 'true' : 'false'}</span>
393
+ </div>
394
+ `;
395
+ } else if (type === 'number') {
396
+ return `
397
+ <div class="input-group">
398
+ <input type="number"
399
+ class="prop-control debugger-input"
400
+ data-prop="${prop}"
401
+ value="${serializedValue}"
402
+ step="any"
403
+ placeholder="Enter number..."
404
+ data-debugger-input="true">
405
+ </div>
406
+ `;
407
+ } else if (type === 'object' || type === 'array' || type === 'function') {
408
+ return `
409
+ <div class="input-group">
410
+ <input type="text"
411
+ class="prop-control debugger-input"
412
+ data-prop="${prop}"
413
+ value="${serializedValue}"
414
+ readonly
415
+ title="Click edit button to modify"
416
+ data-debugger-input="true">
417
+ <button class="edit-btn" onclick="slice.debugger.openAdvancedEditor('${prop}', '${type}')">âœī¸</button>
418
+ </div>
419
+ `;
420
+ } else {
421
+ return `
422
+ <div class="input-group">
423
+ <input type="text"
424
+ class="prop-control debugger-input"
425
+ data-prop="${prop}"
426
+ value="${serializedValue}"
427
+ placeholder="Enter value..."
428
+ data-debugger-input="true">
429
+ </div>
430
+ `;
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Apply a single prop change from an input.
436
+ * @param {HTMLInputElement} inputElement
437
+ * @returns {void}
438
+ */
439
+ applyPropertyChange(inputElement) {
440
+ const prop = inputElement.dataset.prop;
441
+ if (!prop) return;
442
+
443
+ let newValue;
444
+
445
+ if (inputElement.type === 'checkbox') {
446
+ newValue = inputElement.checked;
447
+ const label = inputElement.parentNode.querySelector('.checkbox-label');
448
+ if (label) {
449
+ label.textContent = newValue ? 'true' : 'false';
450
+ }
451
+ } else if (inputElement.type === 'number') {
452
+ newValue = Number(inputElement.value);
453
+ } else {
454
+ newValue = inputElement.value;
455
+
456
+ // Convert string values
457
+ if (newValue === 'true') newValue = true;
458
+ if (newValue === 'false') newValue = false;
459
+ if (!isNaN(newValue) && newValue !== '' && newValue !== null) newValue = Number(newValue);
460
+ }
461
+
462
+ const oldValue = this.currentComponent[prop];
463
+
464
+ this.currentComponent[prop] = newValue;
465
+ slice.logger.logInfo('Debugger', `Updated ${prop}: ${oldValue} → ${newValue}`);
466
+
467
+ this.showVisualFeedback(inputElement);
468
+ }
469
+
470
+ /**
471
+ * Show temporary highlight on updated input.
472
+ * @param {HTMLElement} inputElement
473
+ * @returns {void}
474
+ */
475
+ showVisualFeedback(inputElement) {
476
+ const originalBorder = inputElement.style.borderColor;
477
+ const originalBoxShadow = inputElement.style.boxShadow;
478
+
479
+ inputElement.style.borderColor = '#4CAF50';
480
+ inputElement.style.boxShadow = '0 0 0 2px rgba(76, 175, 80, 0.3)';
481
+
482
+ setTimeout(() => {
483
+ inputElement.style.borderColor = originalBorder;
484
+ inputElement.style.boxShadow = originalBoxShadow;
485
+ }, 1500);
486
+ }
487
+
488
+ /**
489
+ * Apply all editable prop changes in the panel.
490
+ * @returns {void}
491
+ */
492
+ applyAllChanges() {
493
+ const inputs = this.querySelectorAll('.prop-control:not([readonly])');
494
+ let changeCount = 0;
495
+
496
+ inputs.forEach(input => {
497
+ if (!input.readOnly) {
498
+ this.applyPropertyChange(input);
499
+ changeCount++;
500
+ }
501
+ });
502
+
503
+ slice.logger.logInfo('Debugger', `Applied ${changeCount} property changes`);
504
+ this.showApplyFeedback(changeCount);
505
+ }
506
+
507
+ /**
508
+ * Show apply feedback in button.
509
+ * @param {number} changeCount
510
+ * @returns {void}
511
+ */
512
+ showApplyFeedback(changeCount) {
513
+ const applyBtn = this.querySelector('#apply-changes');
514
+ if (!applyBtn) return;
515
+
516
+ const originalText = applyBtn.textContent;
517
+
518
+ if (changeCount > 0) {
519
+ applyBtn.textContent = `✅ Applied ${changeCount} changes!`;
520
+ applyBtn.style.background = '#4CAF50';
521
+ } else {
522
+ applyBtn.textContent = '✅ No changes to apply';
523
+ applyBtn.style.background = '#9E9E9E';
524
+ }
525
+
526
+ setTimeout(() => {
527
+ applyBtn.textContent = originalText;
528
+ applyBtn.style.background = '';
529
+ }, 2000);
530
+ }
531
+
532
+ /**
533
+ * Open advanced editor for objects/functions.
534
+ * @param {string} prop
535
+ * @param {string} type
536
+ * @returns {void}
537
+ */
538
+ openAdvancedEditor(prop, type) {
539
+ this.currentEditingProp = prop;
540
+ this.currentEditingType = this.normalizeEditorType(type) || 'json';
541
+
542
+ const value = this.currentComponent[prop];
543
+
544
+ this.modalTitle.textContent = `Edit ${prop} (${this.currentEditingType})`;
545
+
546
+ this.querySelectorAll('.type-btn').forEach(btn => {
547
+ btn.classList.toggle('active', btn.dataset.type === this.currentEditingType);
548
+ });
549
+
550
+ if (this.currentEditingType === 'function') {
551
+ if (typeof value === 'function') {
552
+ this.propertyEditor.value = value.toString();
553
+ } else {
554
+ this.propertyEditor.value = 'function() {\n // Your code here\n}';
555
+ }
556
+ } else {
557
+ try {
558
+ this.propertyEditor.value = JSON.stringify(value, null, 2);
559
+ } catch (error) {
560
+ this.propertyEditor.value = 'null';
561
+ }
562
+ }
563
+
564
+ this.editorModal.classList.add('active');
565
+ this.propertyEditor.focus();
566
+ }
567
+
568
+ /**
569
+ * Validate editor contents for current type.
570
+ * @returns {void}
571
+ */
572
+ validateEditor() {
573
+ const value = this.propertyEditor.value.trim();
574
+ const type = this.normalizeEditorType(this.currentEditingType) || 'json';
575
+
576
+ try {
577
+ if (type === 'function') {
578
+ new Function('return ' + value)();
579
+ } else {
580
+ JSON.parse(value);
581
+ }
582
+
583
+ this.validationMessage.textContent = '✅ Valid syntax';
584
+ this.validationMessage.style.color = '#4CAF50';
585
+ this.querySelector('#modal-save').disabled = false;
586
+ } catch (error) {
587
+ this.validationMessage.textContent = `❌ ${error.message}`;
588
+ this.validationMessage.style.color = '#F44336';
589
+ this.querySelector('#modal-save').disabled = true;
590
+ }
591
+ }
592
+
593
+ /**
594
+ * Save editor value to component.
595
+ * @returns {void}
596
+ */
597
+ savePropertyValue() {
598
+ const value = this.propertyEditor.value.trim();
599
+ const type = this.normalizeEditorType(this.currentEditingType) || 'json';
600
+
601
+ try {
602
+ let newValue;
603
+
604
+ if (type === 'function') {
605
+ newValue = new Function('return ' + value)();
606
+ } else {
607
+ newValue = JSON.parse(value);
608
+ }
609
+
610
+ this.currentComponent[this.currentEditingProp] = newValue;
611
+ this.closeModal();
612
+
613
+ slice.logger.logInfo('Debugger', `Updated ${this.currentEditingProp} via advanced editor`);
614
+
615
+ const input = this.querySelector(`[data-prop="${this.currentEditingProp}"]`);
616
+ if (input) {
617
+ input.value = this.serializeValue(newValue);
618
+ this.showVisualFeedback(input);
619
+ }
620
+
621
+ } catch (error) {
622
+ this.validationMessage.textContent = `❌ ${error.message}`;
623
+ this.validationMessage.style.color = '#F44336';
624
+ }
625
+ }
626
+
627
+ /**
628
+ * Close the advanced editor modal.
629
+ * @returns {void}
630
+ */
631
+ closeModal() {
632
+ this.editorModal.classList.remove('active');
633
+ this.currentEditingProp = null;
634
+ this.currentEditingType = null;
635
+ this.validationMessage.textContent = '';
636
+ }
637
+
638
+ /**
639
+ * Reset props to defaults (if defined in static props).
640
+ * @returns {void}
641
+ */
642
+ resetValues() {
643
+ const ComponentClass = this.currentComponent.constructor;
644
+ const configuredProps = ComponentClass.props || {};
645
+ let resetCount = 0;
646
+
647
+ Object.entries(configuredProps).forEach(([prop, config]) => {
648
+ if (config.default !== undefined) {
649
+ this.currentComponent[prop] = config.default;
650
+
651
+ const input = this.querySelector(`[data-prop="${prop}"]`);
652
+ if (input && !input.readOnly) {
653
+ if (input.type === 'checkbox') {
654
+ input.checked = config.default;
655
+ const label = input.parentNode.querySelector('.checkbox-label');
656
+ if (label) {
657
+ label.textContent = config.default ? 'true' : 'false';
658
+ }
659
+ } else {
660
+ input.value = this.serializeValue(config.default);
661
+ }
662
+ resetCount++;
663
+ }
664
+ }
665
+ });
666
+
667
+ slice.logger.logInfo('Debugger', 'Reset values to defaults');
668
+ this.showResetFeedback(resetCount);
669
+ }
670
+
671
+ /**
672
+ * Show reset feedback in button.
673
+ * @param {number} resetCount
674
+ * @returns {void}
675
+ */
676
+ showResetFeedback(resetCount) {
677
+ const resetBtn = this.querySelector('#reset-values');
678
+ if (!resetBtn) return;
679
+
680
+ const originalText = resetBtn.textContent;
681
+
682
+ resetBtn.textContent = `🔄 Reset ${resetCount} values!`;
683
+ resetBtn.style.background = '#FF9800';
684
+
685
+ setTimeout(() => {
686
+ resetBtn.textContent = originalText;
687
+ resetBtn.style.background = '';
688
+ }, 1500);
689
+ }
690
+
691
+ /**
692
+ * Render info tab content.
693
+ * @returns {void}
694
+ */
695
+ updateInfoTab() {
696
+ const infoContainer = this.querySelector('.info-list');
697
+ if (!infoContainer) return;
698
+
699
+ const component = this.currentComponent;
700
+
701
+ const info = [
702
+ { label: 'Component Type', value: component.constructor.name },
703
+ { label: 'Slice ID', value: component.sliceId || 'Not assigned' },
704
+ { label: 'Tag Name', value: component.tagName },
705
+ { label: 'Connected', value: component.isConnected ? 'Yes' : 'No' },
706
+ { label: 'Props Count', value: Object.keys(this.componentProps).length },
707
+ { label: 'Children', value: component.children.length }
708
+ ];
709
+
710
+ infoContainer.innerHTML = info.map(item => `
711
+ <div class="info-item">
712
+ <span class="info-label">${item.label}</span>
713
+ <span class="info-value">${item.value}</span>
714
+ </div>
715
+ `).join('');
716
+ }
717
+
718
+ /**
719
+ * Get a simple value type label.
720
+ * @param {any} value
721
+ * @returns {string}
722
+ */
723
+ getValueType(value) {
724
+ if (value === null) return 'null';
725
+ if (value === undefined) return 'undefined';
726
+ if (Array.isArray(value)) return 'array';
727
+ return typeof value;
728
+ }
729
+
730
+ /**
731
+ * Serialize a value for input display.
732
+ * @param {any} value
733
+ * @returns {string}
734
+ */
735
+ serializeValue(value) {
736
+ if (value === null || value === undefined) {
737
+ return '';
738
+ }
739
+
740
+ if (typeof value === 'object' || typeof value === 'function') {
741
+ try {
742
+ return JSON.stringify(value);
743
+ } catch {
744
+ return String(value);
745
+ }
746
+ }
747
+
748
+ return String(value);
749
+ }
750
+
751
+ /**
752
+ * Resolve which props to show in the debugger.
753
+ * @param {HTMLElement} component
754
+ * @returns {string[]}
755
+ */
756
+ getComponentPropsForDebugger(component) {
757
+ const ComponentClass = component.constructor;
758
+
759
+ if (ComponentClass.props) {
760
+ return Object.keys(ComponentClass.props);
761
+ }
762
+
763
+ if (component.debuggerProps && Array.isArray(component.debuggerProps)) {
764
+ return component.debuggerProps;
765
+ }
766
+
767
+ return this.detectUsedProps(component);
768
+ }
769
+
770
+ /**
771
+ * Detect props from backing fields on the component.
772
+ * @param {HTMLElement} component
773
+ * @returns {string[]}
774
+ */
775
+ detectUsedProps(component) {
776
+ const usedProps = [];
777
+
778
+ Object.getOwnPropertyNames(component).forEach(key => {
779
+ if (key.startsWith('_') && key !== '_isActive') {
780
+ const propName = key.substring(1);
781
+ usedProps.push(propName);
782
+ }
783
+ });
784
+
785
+ return usedProps;
786
+ }
787
+
788
+ /**
789
+ * Hide the debugger UI.
790
+ * @returns {void}
791
+ */
792
+ hide() {
793
+ this.debuggerContainer.classList.remove('active');
794
+ this.closeModal();
795
+ }
796
+ }
797
+
798
+ customElements.define('slice-debugger', Debugger);
799
+
800
+ function productionOnlyCSS(){
801
+ return `
802
+ #debugger-container {
803
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
804
+ display: none;
805
+ position: fixed;
806
+ top: 20px;
807
+ right: 20px;
808
+ width: min(420px, calc(100vw - 40px));
809
+ height: 85vh;
810
+ max-height: 85vh;
811
+ background: var(--primary-background-color);
812
+ border: 1px solid var(--medium-color);
813
+ border-radius: 12px;
814
+ box-shadow: 0 20px 40px rgba(var(--primary-color-rgb), 0.15), 0 4px 12px rgba(0, 0, 0, 0.1);
815
+ z-index: 10000;
816
+ overflow: hidden;
817
+ backdrop-filter: blur(10px);
818
+ box-sizing: border-box;
819
+ }
820
+
821
+ #debugger-container.active {
822
+ display: flex;
823
+ flex-direction: column;
824
+ }
825
+
826
+ .debugger-header {
827
+ background: linear-gradient(135deg, var(--primary-color), var(--primary-color-shade));
828
+ color: var(--primary-color-contrast);
829
+ padding: 12px 16px;
830
+ border-radius: 12px 12px 0 0;
831
+ user-select: none;
832
+ cursor: grab;
833
+ }
834
+
835
+ .debugger-header:active {
836
+ cursor: grabbing;
837
+ }
838
+
839
+ .header-content {
840
+ display: flex;
841
+ justify-content: space-between;
842
+ align-items: center;
843
+ }
844
+
845
+ .component-info {
846
+ display: flex;
847
+ align-items: center;
848
+ gap: 10px;
849
+ }
850
+
851
+ .component-icon {
852
+ font-size: 20px;
853
+ opacity: 0.9;
854
+ }
855
+
856
+ .component-name {
857
+ font-size: 14px;
858
+ font-weight: 600;
859
+ margin-bottom: 2px;
860
+ }
861
+
862
+ .component-id {
863
+ font-size: 11px;
864
+ opacity: 0.8;
865
+ }
866
+
867
+ .header-actions {
868
+ display: flex;
869
+ gap: 8px;
870
+ }
871
+
872
+ .minimize-btn, #close-debugger {
873
+ background: rgba(255, 255, 255, 0.2);
874
+ border: none;
875
+ color: var(--primary-color-contrast);
876
+ width: 28px;
877
+ height: 28px;
878
+ border-radius: 6px;
879
+ cursor: pointer;
880
+ display: flex;
881
+ align-items: center;
882
+ justify-content: center;
883
+ font-size: 16px;
884
+ font-weight: bold;
885
+ transition: background 0.2s ease;
886
+ }
887
+
888
+ .minimize-btn:hover, #close-debugger:hover {
889
+ background: rgba(255, 255, 255, 0.3);
890
+ }
891
+
892
+ .debugger-content {
893
+ flex: 1;
894
+ display: flex;
895
+ flex-direction: column;
896
+ overflow: hidden;
897
+ }
898
+
899
+ .tabs-container {
900
+ border-bottom: 1px solid var(--medium-color);
901
+ }
902
+
903
+ .tab-nav {
904
+ display: flex;
905
+ background: var(--tertiary-background-color);
906
+ }
907
+
908
+ .tab-btn {
909
+ flex: 1;
910
+ padding: 10px 14px;
911
+ border: none;
912
+ background: transparent;
913
+ color: var(--font-secondary-color);
914
+ font-size: 12px;
915
+ font-weight: 500;
916
+ cursor: pointer;
917
+ transition: all 0.2s ease;
918
+ border-bottom: 2px solid transparent;
919
+ }
920
+
921
+ .tab-btn:hover {
922
+ background: var(--secondary-background-color);
923
+ color: var(--font-primary-color);
924
+ }
925
+
926
+ .tab-btn.active {
927
+ background: var(--primary-background-color);
928
+ color: var(--primary-color);
929
+ border-bottom-color: var(--primary-color);
930
+ font-weight: 600;
931
+ }
932
+
933
+ .tab-content {
934
+ flex: 1;
935
+ overflow: hidden;
936
+ min-height: 0;
937
+ }
938
+
939
+ .tab-pane {
940
+ display: none;
941
+ height: 100%;
942
+ overflow-y: auto;
943
+ overflow-x: hidden;
944
+ padding: 16px;
945
+ box-sizing: border-box;
946
+ }
947
+
948
+ .tab-pane.active {
949
+ display: block;
950
+ }
951
+
952
+ .tab-pane::-webkit-scrollbar {
953
+ width: 4px;
954
+ }
955
+
956
+ .tab-pane::-webkit-scrollbar-track {
957
+ background: var(--tertiary-background-color);
958
+ border-radius: 2px;
959
+ }
960
+
961
+ .tab-pane::-webkit-scrollbar-thumb {
962
+ background: var(--medium-color);
963
+ border-radius: 2px;
964
+ }
965
+
966
+ .tab-pane::-webkit-scrollbar-thumb:hover {
967
+ background: var(--primary-color);
968
+ }
969
+
970
+ .props-container {
971
+ display: flex;
972
+ flex-direction: column;
973
+ gap: 12px;
974
+ margin-bottom: 16px;
975
+ min-width: 0;
976
+ overflow-x: hidden;
977
+ }
978
+
979
+ #debugger-container *,
980
+ #debugger-container *::before,
981
+ #debugger-container *::after {
982
+ box-sizing: border-box;
983
+ }
984
+
985
+ .props-actions {
986
+ border-top: 1px solid var(--medium-color);
987
+ padding-top: 16px;
988
+ margin-top: 8px;
989
+ }
990
+
991
+ .actions-note {
992
+ margin-top: 12px;
993
+ padding: 8px 12px;
994
+ background: var(--tertiary-background-color);
995
+ border-radius: 6px;
996
+ border: 1px solid var(--medium-color);
997
+ }
998
+
999
+ .actions-note small {
1000
+ color: var(--font-secondary-color);
1001
+ font-size: 11px;
1002
+ display: flex;
1003
+ align-items: center;
1004
+ gap: 6px;
1005
+ }
1006
+
1007
+ .props-section {
1008
+ background: var(--tertiary-background-color);
1009
+ border: 1px solid var(--medium-color);
1010
+ border-radius: 8px;
1011
+ padding: 12px;
1012
+ }
1013
+
1014
+ .section-title {
1015
+ font-size: 12px;
1016
+ font-weight: 600;
1017
+ color: var(--font-primary-color);
1018
+ margin-bottom: 12px;
1019
+ display: flex;
1020
+ align-items: center;
1021
+ gap: 6px;
1022
+ }
1023
+
1024
+ .prop-item {
1025
+ display: flex;
1026
+ flex-direction: column;
1027
+ gap: 6px;
1028
+ padding: 12px;
1029
+ background: var(--primary-background-color);
1030
+ border: 1px solid var(--medium-color);
1031
+ border-radius: 6px;
1032
+ margin-bottom: 8px;
1033
+ transition: border-color 0.2s ease;
1034
+ min-width: 0;
1035
+ overflow: hidden;
1036
+ }
1037
+
1038
+ .prop-item:hover {
1039
+ border-color: var(--primary-color);
1040
+ }
1041
+
1042
+ .prop-header {
1043
+ display: flex;
1044
+ justify-content: space-between;
1045
+ align-items: center;
1046
+ gap: 8px;
1047
+ min-width: 0;
1048
+ }
1049
+
1050
+ .prop-title {
1051
+ display: flex;
1052
+ align-items: center;
1053
+ gap: 6px;
1054
+ min-width: 0;
1055
+ flex: 1;
1056
+ }
1057
+
1058
+ .prop-title strong {
1059
+ min-width: 0;
1060
+ overflow: hidden;
1061
+ text-overflow: ellipsis;
1062
+ white-space: nowrap;
1063
+ }
1064
+
1065
+ .prop-name {
1066
+ font-size: 13px;
1067
+ font-weight: 600;
1068
+ color: var(--font-primary-color);
1069
+ }
1070
+
1071
+ .prop-name.required::after {
1072
+ content: " *";
1073
+ color: var(--danger-color);
1074
+ }
1075
+
1076
+ .prop-meta {
1077
+ display: flex;
1078
+ align-items: center;
1079
+ gap: 8px;
1080
+ }
1081
+
1082
+ .prop-type {
1083
+ font-size: 11px;
1084
+ padding: 2px 6px;
1085
+ background: var(--secondary-color);
1086
+ color: var(--secondary-color-contrast);
1087
+ border-radius: 4px;
1088
+ font-family: monospace;
1089
+ font-weight: 500;
1090
+ flex-shrink: 0;
1091
+ }
1092
+
1093
+ .prop-status {
1094
+ font-size: 12px;
1095
+ font-weight: 500;
1096
+ flex-shrink: 0;
1097
+ }
1098
+
1099
+ .status-used {
1100
+ color: var(--success-color);
1101
+ }
1102
+
1103
+ .status-missing {
1104
+ color: var(--danger-color);
1105
+ }
1106
+
1107
+ .status-optional {
1108
+ color: var(--medium-color);
1109
+ }
1110
+
1111
+ .prop-input {
1112
+ margin-top: 8px;
1113
+ min-width: 0;
1114
+ overflow: hidden;
1115
+ }
1116
+
1117
+ .input-group {
1118
+ position: relative;
1119
+ max-width: 100%;
1120
+ min-width: 0;
1121
+ overflow: hidden;
1122
+ }
1123
+
1124
+ .prop-control {
1125
+ width: 100%;
1126
+ max-width: 100%;
1127
+ min-width: 0;
1128
+ padding: 8px 32px 8px 10px;
1129
+ border: 1px solid var(--medium-color);
1130
+ border-radius: 6px;
1131
+ background: var(--primary-background-color);
1132
+ color: var(--font-primary-color);
1133
+ font-size: 13px;
1134
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
1135
+ font-family: monospace;
1136
+ box-sizing: border-box;
1137
+ display: block;
1138
+ }
1139
+
1140
+ .prop-control:focus {
1141
+ outline: none;
1142
+ border-color: var(--primary-color);
1143
+ box-shadow: 0 0 0 3px rgba(var(--primary-color-rgb), 0.1);
1144
+ }
1145
+
1146
+ .prop-control:disabled {
1147
+ background: var(--disabled-color);
1148
+ color: var(--font-secondary-color);
1149
+ cursor: not-allowed;
1150
+ }
1151
+
1152
+ .prop-control[readonly] {
1153
+ background: var(--tertiary-background-color);
1154
+ cursor: pointer;
1155
+ text-overflow: ellipsis;
1156
+ overflow: hidden;
1157
+ white-space: nowrap;
1158
+ max-width: 100%;
1159
+ }
1160
+
1161
+ .prop-control[readonly]:focus {
1162
+ border-color: var(--accent-color);
1163
+ box-shadow: 0 0 0 3px rgba(var(--accent-color), 0.1);
1164
+ }
1165
+
1166
+ /* Estilos específicos para checkboxes */
1167
+ .prop-control[type="checkbox"] {
1168
+ width: auto;
1169
+ padding: 0;
1170
+ margin: 0;
1171
+ cursor: pointer;
1172
+ }
1173
+
1174
+ .edit-btn {
1175
+ position: absolute;
1176
+ right: 4px;
1177
+ top: 50%;
1178
+ transform: translateY(-50%);
1179
+ background: var(--accent-color);
1180
+ border: none;
1181
+ color: white;
1182
+ width: 24px;
1183
+ height: 24px;
1184
+ border-radius: 4px;
1185
+ cursor: pointer;
1186
+ font-size: 12px;
1187
+ display: flex;
1188
+ align-items: center;
1189
+ justify-content: center;
1190
+ transition: background 0.2s ease;
1191
+ }
1192
+
1193
+ .edit-btn:hover {
1194
+ background: var(--primary-color);
1195
+ }
1196
+
1197
+ .default-value {
1198
+ font-size: 11px;
1199
+ color: var(--font-secondary-color);
1200
+ font-style: italic;
1201
+ margin-top: 4px;
1202
+ }
1203
+
1204
+ .info-list {
1205
+ display: flex;
1206
+ flex-direction: column;
1207
+ gap: 12px;
1208
+ }
1209
+
1210
+ .info-item {
1211
+ display: flex;
1212
+ justify-content: space-between;
1213
+ padding: 12px;
1214
+ background: var(--tertiary-background-color);
1215
+ border-radius: 6px;
1216
+ border: 1px solid var(--medium-color);
1217
+ }
1218
+
1219
+ .info-label {
1220
+ font-weight: 600;
1221
+ color: var(--font-primary-color);
1222
+ font-size: 13px;
1223
+ }
1224
+
1225
+ .info-value {
1226
+ color: var(--font-secondary-color);
1227
+ font-family: monospace;
1228
+ font-size: 12px;
1229
+ }
1230
+
1231
+ .actions-container {
1232
+ display: flex;
1233
+ flex-direction: column;
1234
+ gap: 16px;
1235
+ }
1236
+
1237
+ .action-buttons {
1238
+ display: flex;
1239
+ flex-direction: column;
1240
+ gap: 8px;
1241
+ }
1242
+
1243
+ .action-btn {
1244
+ padding: 12px 16px;
1245
+ border: none;
1246
+ border-radius: 6px;
1247
+ font-size: 13px;
1248
+ font-weight: 500;
1249
+ cursor: pointer;
1250
+ transition: all 0.2s ease;
1251
+ display: flex;
1252
+ align-items: center;
1253
+ justify-content: center;
1254
+ gap: 8px;
1255
+ }
1256
+
1257
+ .action-btn.primary {
1258
+ background: var(--primary-color);
1259
+ color: var(--primary-color-contrast);
1260
+ }
1261
+
1262
+ .action-btn.primary:hover {
1263
+ background: var(--primary-color-shade);
1264
+ }
1265
+
1266
+ .action-btn.secondary {
1267
+ background: var(--secondary-color);
1268
+ color: var(--secondary-color-contrast);
1269
+ }
1270
+
1271
+ .action-btn.secondary:hover {
1272
+ opacity: 0.9;
1273
+ }
1274
+
1275
+ .action-btn.tertiary {
1276
+ background: var(--tertiary-background-color);
1277
+ color: var(--font-primary-color);
1278
+ border: 1px solid var(--medium-color);
1279
+ }
1280
+
1281
+ .action-btn.tertiary:hover {
1282
+ background: var(--secondary-background-color);
1283
+ }
1284
+
1285
+ /* Modal Styles */
1286
+ .editor-modal {
1287
+ display: none;
1288
+ position: fixed;
1289
+ top: 0;
1290
+ left: 0;
1291
+ width: 100%;
1292
+ height: 100%;
1293
+ background: rgba(0, 0, 0, 0.6);
1294
+ z-index: 20000;
1295
+ backdrop-filter: blur(4px);
1296
+ }
1297
+
1298
+ .editor-modal.active {
1299
+ display: flex;
1300
+ align-items: center;
1301
+ justify-content: center;
1302
+ }
1303
+
1304
+ .modal-content {
1305
+ background: var(--primary-background-color);
1306
+ border-radius: 12px;
1307
+ width: min(600px, 92vw);
1308
+ max-width: 600px;
1309
+ max-height: 80%;
1310
+ display: flex;
1311
+ flex-direction: column;
1312
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
1313
+ border: 1px solid var(--medium-color);
1314
+ box-sizing: border-box;
1315
+ }
1316
+
1317
+ .modal-header {
1318
+ padding: 16px 20px;
1319
+ background: var(--tertiary-background-color);
1320
+ border-radius: 12px 12px 0 0;
1321
+ border-bottom: 1px solid var(--medium-color);
1322
+ display: flex;
1323
+ justify-content: space-between;
1324
+ align-items: center;
1325
+ }
1326
+
1327
+ .modal-header h3 {
1328
+ margin: 0;
1329
+ font-size: 16px;
1330
+ font-weight: 600;
1331
+ color: var(--font-primary-color);
1332
+ }
1333
+
1334
+ .modal-close {
1335
+ background: none;
1336
+ border: none;
1337
+ font-size: 20px;
1338
+ color: var(--font-secondary-color);
1339
+ cursor: pointer;
1340
+ width: 32px;
1341
+ height: 32px;
1342
+ border-radius: 6px;
1343
+ display: flex;
1344
+ align-items: center;
1345
+ justify-content: center;
1346
+ transition: background 0.2s ease;
1347
+ }
1348
+
1349
+ .modal-close:hover {
1350
+ background: var(--secondary-background-color);
1351
+ }
1352
+
1353
+ .modal-body {
1354
+ flex: 1;
1355
+ padding: 20px;
1356
+ display: flex;
1357
+ flex-direction: column;
1358
+ gap: 16px;
1359
+ overflow: hidden;
1360
+ min-height: 0;
1361
+ }
1362
+
1363
+ .editor-type-selector {
1364
+ display: flex;
1365
+ gap: 4px;
1366
+ background: var(--tertiary-background-color);
1367
+ padding: 4px;
1368
+ border-radius: 6px;
1369
+ }
1370
+
1371
+ .type-btn {
1372
+ flex: 1;
1373
+ padding: 8px 12px;
1374
+ border: none;
1375
+ background: transparent;
1376
+ color: var(--font-secondary-color);
1377
+ font-size: 12px;
1378
+ font-weight: 500;
1379
+ cursor: pointer;
1380
+ border-radius: 4px;
1381
+ transition: all 0.2s ease;
1382
+ }
1383
+
1384
+ .type-btn.active {
1385
+ background: var(--primary-color);
1386
+ color: var(--primary-color-contrast);
1387
+ }
1388
+
1389
+ .editor-container {
1390
+ flex: 1;
1391
+ position: relative;
1392
+ min-height: 200px;
1393
+ min-width: 0;
1394
+ }
1395
+
1396
+ #property-editor {
1397
+ width: 100%;
1398
+ height: 100%;
1399
+ border: 1px solid var(--medium-color);
1400
+ border-radius: 6px;
1401
+ padding: 12px;
1402
+ background: var(--primary-background-color);
1403
+ color: var(--font-primary-color);
1404
+ font-family: 'Monaco', 'Consolas', monospace;
1405
+ font-size: 13px;
1406
+ line-height: 1.5;
1407
+ resize: none;
1408
+ outline: none;
1409
+ min-height: 200px;
1410
+ box-sizing: border-box;
1411
+ }
1412
+
1413
+ #property-editor:focus {
1414
+ border-color: var(--primary-color);
1415
+ box-shadow: 0 0 0 3px rgba(var(--primary-color-rgb), 0.1);
1416
+ }
1417
+
1418
+ .validation-message {
1419
+ font-size: 12px;
1420
+ color: var(--danger-color);
1421
+ min-height: 18px;
1422
+ display: flex;
1423
+ align-items: center;
1424
+ gap: 6px;
1425
+ }
1426
+
1427
+ .modal-actions {
1428
+ padding: 16px 20px;
1429
+ background: var(--tertiary-background-color);
1430
+ border-radius: 0 0 12px 12px;
1431
+ border-top: 1px solid var(--medium-color);
1432
+ display: flex;
1433
+ gap: 12px;
1434
+ justify-content: flex-end;
1435
+ }
1436
+
1437
+ .modal-btn {
1438
+ padding: 10px 20px;
1439
+ border: none;
1440
+ border-radius: 6px;
1441
+ font-size: 13px;
1442
+ font-weight: 500;
1443
+ cursor: pointer;
1444
+ transition: all 0.2s ease;
1445
+ }
1446
+
1447
+ .modal-btn.cancel {
1448
+ background: var(--tertiary-background-color);
1449
+ color: var(--font-primary-color);
1450
+ border: 1px solid var(--medium-color);
1451
+ }
1452
+
1453
+ .modal-btn.cancel:hover {
1454
+ background: var(--secondary-background-color);
1455
+ }
1456
+
1457
+ .modal-btn.save {
1458
+ background: var(--success-color);
1459
+ color: var(--success-contrast);
1460
+ }
1461
+
1462
+ .modal-btn.save:hover {
1463
+ opacity: 0.9;
1464
+ }
1465
+
1466
+ .modal-btn.save:disabled {
1467
+ background: var(--disabled-color);
1468
+ cursor: not-allowed;
1469
+ }
1470
+ `
1471
+ }
1472
+
1473
+ function productionOnlyHtml(){
1474
+ return `
1475
+ <div id="debugger-container">
1476
+ <div class="debugger-header">
1477
+ <div class="header-content">
1478
+ <div class="component-info">
1479
+ <div class="component-icon">🔍</div>
1480
+ <div class="component-details">
1481
+ <div class="component-name">Component Inspector</div>
1482
+ <div class="component-id">Ready to debug</div>
1483
+ </div>
1484
+ </div>
1485
+ <div class="header-actions">
1486
+ <button class="minimize-btn" title="Minimize">−</button>
1487
+ <button id="close-debugger" title="Close">×</button>
1488
+ </div>
1489
+ </div>
1490
+ </div>
1491
+
1492
+ <div class="debugger-content">
1493
+ <div class="tabs-container">
1494
+ <div class="tab-nav">
1495
+ <button class="tab-btn active" data-tab="props">📋 Props</button>
1496
+ <button class="tab-btn" data-tab="info">â„šī¸ Info</button>
1497
+ </div>
1498
+ </div>
1499
+
1500
+ <div class="tab-content">
1501
+ <div class="tab-pane active" id="props-tab">
1502
+ <div class="props-container"></div>
1503
+ <div class="props-actions">
1504
+ <div class="action-buttons">
1505
+ <button class="action-btn primary" id="apply-changes">✅ Apply Changes</button>
1506
+ <button class="action-btn secondary" id="reset-values">🔄 Reset Values</button>
1507
+ </div>
1508
+ <div class="actions-note">
1509
+ <small>💡 Press Enter on any input to apply changes automatically</small>
1510
+ </div>
1511
+ </div>
1512
+ </div>
1513
+
1514
+ <div class="tab-pane" id="info-tab">
1515
+ <div class="info-container">
1516
+ <div class="info-list"></div>
1517
+ </div>
1518
+ </div>
1519
+ </div>
1520
+ </div>
1521
+
1522
+ <!-- Modal para editar objetos/funciones -->
1523
+ <div class="editor-modal" id="editor-modal">
1524
+ <div class="modal-content">
1525
+ <div class="modal-header">
1526
+ <h3 id="modal-title">Edit Property</h3>
1527
+ <button class="modal-close" id="modal-close">×</button>
1528
+ </div>
1529
+ <div class="modal-body">
1530
+ <div class="editor-type-selector">
1531
+ <button class="type-btn active" data-type="json">📋 JSON</button>
1532
+ <button class="type-btn" data-type="function">⚡ Function</button>
1533
+ </div>
1534
+ <div class="editor-container">
1535
+ <textarea id="property-editor" spellcheck="false"></textarea>
1536
+ </div>
1537
+ <div class="editor-footer">
1538
+ <div class="validation-message"></div>
1539
+ </div>
1540
+ </div>
1541
+ <div class="modal-actions">
1542
+ <button class="modal-btn cancel" id="modal-cancel">Cancel</button>
1543
+ <button class="modal-btn save" id="modal-save">Save Changes</button>
1544
+ </div>
1545
+ </div>
1546
+ </div>
1547
+ </div>`
1548
+ }