juxscript 1.1.69 → 1.1.71

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.
@@ -5,347 +5,347 @@ const TRIGGER_EVENTS = [] as const;
5
5
  const CALLBACK_EVENTS = ['select', 'expand'] as const;
6
6
 
7
7
  export interface BlueprintOptions {
8
- structureData?: any; // dom-structure-map.json
9
- classData?: any; // css-classes-inventory.json
10
- filter?: string; // Filter by component name
11
- showMethods?: boolean;
12
- expandAll?: boolean;
13
- theme?: 'light' | 'dark' | 'auto';
14
- style?: string;
15
- class?: string;
8
+ structureData?: any; // dom-structure-map.json
9
+ classData?: any; // css-classes-inventory.json
10
+ filter?: string; // Filter by component name
11
+ showMethods?: boolean;
12
+ expandAll?: boolean;
13
+ theme?: 'light' | 'dark' | 'auto';
14
+ style?: string;
15
+ class?: string;
16
16
  }
17
17
 
18
18
  interface BlueprintState extends BaseState {
19
- structureData: any;
20
- classData: any;
21
- filter: string;
22
- showMethods: boolean;
23
- expandAll: boolean;
24
- theme: string;
25
- expandedComponents: Set<string>;
19
+ structureData: any;
20
+ classData: any;
21
+ filter: string;
22
+ showMethods: boolean;
23
+ expandAll: boolean;
24
+ theme: string;
25
+ expandedComponents: Set<string>;
26
26
  }
27
27
 
28
28
  interface ComponentHierarchy {
29
- tag: string;
30
- classes: string[];
31
- id: string | null;
32
- children?: ComponentHierarchy[];
29
+ tag: string;
30
+ classes: string[];
31
+ id: string | null;
32
+ children?: ComponentHierarchy[];
33
33
  }
34
34
 
35
35
  export class Blueprint extends BaseComponent<BlueprintState> {
36
- constructor(id: string, options: BlueprintOptions = {}) {
37
- super(id, {
38
- structureData: options.structureData ?? null,
39
- classData: options.classData ?? null,
40
- filter: options.filter ?? '',
41
- showMethods: options.showMethods ?? true,
42
- expandAll: options.expandAll ?? false,
43
- theme: options.theme ?? 'auto',
44
- expandedComponents: new Set<string>(),
45
- style: options.style ?? '',
46
- class: options.class ?? ''
47
- });
48
- }
49
-
50
- protected getTriggerEvents(): readonly string[] {
51
- return TRIGGER_EVENTS;
52
- }
53
-
54
- protected getCallbackEvents(): readonly string[] {
55
- return CALLBACK_EVENTS;
56
- }
57
-
58
- /* ═════════════════════════════════════════════════════════════════
59
- * FLUENT API
60
- * ═════════════════════════════════════════════════════════════════ */
61
-
62
- structureData(data: any): this {
63
- this.state.structureData = data;
64
- return this;
65
- }
66
-
67
- classData(data: any): this {
68
- this.state.classData = data;
69
- return this;
70
- }
71
-
72
- filter(value: string): this {
73
- this.state.filter = value;
74
- return this;
75
- }
76
-
77
- showMethods(value: boolean): this {
78
- this.state.showMethods = value;
79
- return this;
80
- }
81
-
82
- expandAll(value: boolean): this {
83
- this.state.expandAll = value;
84
- return this;
85
- }
86
-
87
- theme(value: 'light' | 'dark' | 'auto'): this {
88
- this.state.theme = value;
89
- return this;
90
- }
91
-
92
- toggleComponent(componentFile: string): this {
93
- if (this.state.expandedComponents.has(componentFile)) {
94
- this.state.expandedComponents.delete(componentFile);
95
- } else {
96
- this.state.expandedComponents.add(componentFile);
97
- }
98
- this._triggerCallback('expand', componentFile);
99
- return this;
100
- }
101
-
102
- /* ═════════════════════════════════════════════════════════════════
103
- * RENDER HELPERS
104
- * ═════════════════════════════════════════════════════════════════ */
105
-
106
- private _renderHierarchy(hierarchy: ComponentHierarchy[], depth: number = 0): HTMLElement {
107
- const container = document.createElement('div');
108
- container.className = 'jux-blueprint-hierarchy';
109
-
110
- hierarchy.forEach((node, index) => {
111
- const nodeEl = document.createElement('div');
112
- nodeEl.className = 'jux-blueprint-node';
113
- nodeEl.style.paddingLeft = `${depth * 20}px`;
114
-
115
- const isLast = index === hierarchy.length - 1;
116
- const connector = isLast ? '└─' : '├─';
117
-
118
- // Tree line
119
- const lineEl = document.createElement('span');
120
- lineEl.className = 'jux-blueprint-line';
121
- lineEl.textContent = connector + ' ';
122
- nodeEl.appendChild(lineEl);
123
-
124
- // Tag
125
- const tagEl = document.createElement('span');
126
- tagEl.className = 'jux-blueprint-tag';
127
- tagEl.textContent = `<${node.tag}>`;
128
- nodeEl.appendChild(tagEl);
129
-
130
- // ID
131
- if (node.id) {
132
- const idEl = document.createElement('span');
133
- idEl.className = 'jux-blueprint-id';
134
- idEl.textContent = ` #${node.id}`;
135
- nodeEl.appendChild(idEl);
136
- }
137
-
138
- // Classes
139
- if (node.classes && node.classes.length > 0) {
140
- const classesEl = document.createElement('span');
141
- classesEl.className = 'jux-blueprint-classes';
142
-
143
- node.classes.forEach(cls => {
144
- const classEl = document.createElement('span');
145
- classEl.className = 'jux-blueprint-class';
146
- classEl.textContent = `.${cls}`;
147
- classesEl.appendChild(classEl);
148
- classesEl.appendChild(document.createTextNode(' '));
36
+ constructor(id: string, options: BlueprintOptions = {}) {
37
+ super(id, {
38
+ structureData: options.structureData ?? null,
39
+ classData: options.classData ?? null,
40
+ filter: options.filter ?? '',
41
+ showMethods: options.showMethods ?? true,
42
+ expandAll: options.expandAll ?? false,
43
+ theme: options.theme ?? 'auto',
44
+ expandedComponents: new Set<string>(),
45
+ style: options.style ?? '',
46
+ class: options.class ?? ''
149
47
  });
48
+ }
150
49
 
151
- nodeEl.appendChild(classesEl);
152
- }
153
-
154
- container.appendChild(nodeEl);
155
-
156
- // Render children recursively
157
- if (node.children && node.children.length > 0) {
158
- container.appendChild(this._renderHierarchy(node.children, depth + 1));
159
- }
160
- });
161
-
162
- return container;
163
- }
164
-
165
- private _renderComponentCard(component: any): HTMLElement {
166
- const { showMethods, expandAll, expandedComponents } = this.state;
167
- const isExpanded = expandAll || expandedComponents.has(component.file);
168
-
169
- const card = document.createElement('div');
170
- card.className = 'jux-blueprint-card';
171
- if (isExpanded) card.classList.add('jux-blueprint-card-expanded');
172
-
173
- // Header
174
- const header = document.createElement('div');
175
- header.className = 'jux-blueprint-card-header';
176
- header.addEventListener('click', () => {
177
- this.toggleComponent(component.file);
178
- this.update('expandedComponents', this.state.expandedComponents);
179
- });
180
-
181
- const title = document.createElement('h4');
182
- title.className = 'jux-blueprint-card-title';
183
- title.textContent = component.file;
184
- header.appendChild(title);
185
-
186
- const badge = document.createElement('span');
187
- badge.className = 'jux-blueprint-badge';
188
- badge.textContent = `${component.classCount} classes`;
189
- header.appendChild(badge);
190
-
191
- const toggle = document.createElement('span');
192
- toggle.className = 'jux-blueprint-toggle-icon';
193
- toggle.textContent = isExpanded ? '▼' : '▶';
194
- header.appendChild(toggle);
195
-
196
- card.appendChild(header);
197
-
198
- // Body (collapsed by default)
199
- if (isExpanded) {
200
- const body = document.createElement('div');
201
- body.className = 'jux-blueprint-card-body';
202
-
203
- // Class list
204
- if (component.allClasses && component.allClasses.length > 0) {
205
- const classSection = document.createElement('div');
206
- classSection.className = 'jux-blueprint-section';
207
-
208
- const classTitle = document.createElement('h5');
209
- classTitle.className = 'jux-blueprint-section-title';
210
- classTitle.textContent = 'CSS Classes';
211
- classSection.appendChild(classTitle);
212
-
213
- const classList = document.createElement('div');
214
- classList.className = 'jux-blueprint-class-list';
215
-
216
- component.allClasses.forEach((cls: string) => {
217
- const classTag = document.createElement('span');
218
- classTag.className = 'jux-blueprint-class-tag';
219
- classTag.textContent = `.${cls}`;
220
- classList.appendChild(classTag);
221
- });
50
+ protected getTriggerEvents(): readonly string[] {
51
+ return TRIGGER_EVENTS;
52
+ }
222
53
 
223
- classSection.appendChild(classList);
224
- body.appendChild(classSection);
225
- }
54
+ protected getCallbackEvents(): readonly string[] {
55
+ return CALLBACK_EVENTS;
56
+ }
226
57
 
227
- // DOM Structures
228
- if (component.domStructures && component.domStructures.length > 0) {
229
- component.domStructures.forEach((structure: any) => {
230
- const structSection = document.createElement('div');
231
- structSection.className = 'jux-blueprint-section';
58
+ /* ═════════════════════════════════════════════════════════════════
59
+ * FLUENT API
60
+ * ═════════════════════════════════════════════════════════════════ */
232
61
 
233
- const methodTitle = document.createElement('h5');
234
- methodTitle.className = 'jux-blueprint-section-title';
235
- methodTitle.textContent = `Method: ${structure.method}()`;
236
- structSection.appendChild(methodTitle);
62
+ structureData(data: any): this {
63
+ this.state.structureData = data;
64
+ return this;
65
+ }
237
66
 
238
- // Render hierarchy if available
239
- if (structure.hierarchy && structure.hierarchy.length > 0) {
240
- const hierarchyEl = this._renderHierarchy(structure.hierarchy);
241
- structSection.appendChild(hierarchyEl);
242
- }
67
+ classData(data: any): this {
68
+ this.state.classData = data;
69
+ return this;
70
+ }
243
71
 
244
- body.appendChild(structSection);
245
- });
246
- }
72
+ filter(value: string): this {
73
+ this.state.filter = value;
74
+ return this;
75
+ }
247
76
 
248
- card.appendChild(body);
77
+ showMethods(value: boolean): this {
78
+ this.state.showMethods = value;
79
+ return this;
249
80
  }
250
81
 
251
- return card;
252
- }
82
+ expandAll(value: boolean): this {
83
+ this.state.expandAll = value;
84
+ return this;
85
+ }
253
86
 
254
- /* ═════════════════════════════════════════════════════════════════
255
- * REACTIVE UPDATE
256
- * ═════════════════════════════════════════════════════════════════ */
87
+ theme(value: 'light' | 'dark' | 'auto'): this {
88
+ this.state.theme = value;
89
+ return this;
90
+ }
257
91
 
258
- update(prop: string, value: any): void {
259
- super.update(prop, value);
92
+ toggleComponent(componentFile: string): this {
93
+ if (this.state.expandedComponents.has(componentFile)) {
94
+ this.state.expandedComponents.delete(componentFile);
95
+ } else {
96
+ this.state.expandedComponents.add(componentFile);
97
+ }
98
+ this._triggerCallback('expand', componentFile);
99
+ return this;
100
+ }
260
101
 
261
- if (!this.container) return;
102
+ /* ═════════════════════════════════════════════════════════════════
103
+ * RENDER HELPERS
104
+ * ═════════════════════════════════════════════════════════════════ */
105
+
106
+ private _renderHierarchy(hierarchy: ComponentHierarchy[], depth: number = 0): HTMLElement {
107
+ const container = document.createElement('div');
108
+ container.className = 'jux-blueprint-hierarchy';
109
+
110
+ hierarchy.forEach((node, index) => {
111
+ const nodeEl = document.createElement('div');
112
+ nodeEl.className = 'jux-blueprint-node';
113
+ nodeEl.style.paddingLeft = `${depth * 20}px`;
114
+
115
+ const isLast = index === hierarchy.length - 1;
116
+ const connector = isLast ? '└─' : '├─';
117
+
118
+ // Tree line
119
+ const lineEl = document.createElement('span');
120
+ lineEl.className = 'jux-blueprint-line';
121
+ lineEl.textContent = connector + ' ';
122
+ nodeEl.appendChild(lineEl);
123
+
124
+ // Tag
125
+ const tagEl = document.createElement('span');
126
+ tagEl.className = 'jux-blueprint-tag';
127
+ tagEl.textContent = `<${node.tag}>`;
128
+ nodeEl.appendChild(tagEl);
129
+
130
+ // ID
131
+ if (node.id) {
132
+ const idEl = document.createElement('span');
133
+ idEl.className = 'jux-blueprint-id';
134
+ idEl.textContent = ` #${node.id}`;
135
+ nodeEl.appendChild(idEl);
136
+ }
137
+
138
+ // Classes
139
+ if (node.classes && node.classes.length > 0) {
140
+ const classesEl = document.createElement('span');
141
+ classesEl.className = 'jux-blueprint-classes';
142
+
143
+ node.classes.forEach(cls => {
144
+ const classEl = document.createElement('span');
145
+ classEl.className = 'jux-blueprint-class';
146
+ classEl.textContent = `.${cls}`;
147
+ classesEl.appendChild(classEl);
148
+ classesEl.appendChild(document.createTextNode(' '));
149
+ });
150
+
151
+ nodeEl.appendChild(classesEl);
152
+ }
153
+
154
+ container.appendChild(nodeEl);
155
+
156
+ // Render children recursively
157
+ if (node.children && node.children.length > 0) {
158
+ container.appendChild(this._renderHierarchy(node.children, depth + 1));
159
+ }
160
+ });
262
161
 
263
- const blueprint = this.container.querySelector(`#${this._id}`) as HTMLElement;
264
- if (!blueprint) return;
162
+ return container;
163
+ }
265
164
 
266
- switch (prop) {
267
- case 'structureData':
268
- case 'classData':
269
- case 'filter':
270
- case 'showMethods':
271
- case 'expandAll':
272
- case 'expandedComponents':
273
- this._rebuildContent();
274
- break;
165
+ private _renderComponentCard(component: any): HTMLElement {
166
+ const { showMethods, expandAll, expandedComponents } = this.state;
167
+ const isExpanded = expandAll || expandedComponents.has(component.file);
275
168
 
276
- case 'theme':
277
- blueprint.dataset.theme = value;
278
- break;
169
+ const card = document.createElement('div');
170
+ card.className = 'jux-blueprint-card';
171
+ if (isExpanded) card.classList.add('jux-blueprint-card-expanded');
172
+
173
+ // Header
174
+ const header = document.createElement('div');
175
+ header.className = 'jux-blueprint-card-header';
176
+ header.addEventListener('click', () => {
177
+ this.toggleComponent(component.file);
178
+ this.update('expandedComponents', this.state.expandedComponents);
179
+ });
180
+
181
+ const title = document.createElement('h4');
182
+ title.className = 'jux-blueprint-card-title';
183
+ title.textContent = component.file;
184
+ header.appendChild(title);
185
+
186
+ const badge = document.createElement('span');
187
+ badge.className = 'jux-blueprint-badge';
188
+ badge.textContent = `${component.classCount} classes`;
189
+ header.appendChild(badge);
190
+
191
+ const toggle = document.createElement('span');
192
+ toggle.className = 'jux-blueprint-toggle-icon';
193
+ toggle.textContent = isExpanded ? '▼' : '▶';
194
+ header.appendChild(toggle);
195
+
196
+ card.appendChild(header);
197
+
198
+ // Body (collapsed by default)
199
+ if (isExpanded) {
200
+ const body = document.createElement('div');
201
+ body.className = 'jux-blueprint-card-body';
202
+
203
+ // Class list
204
+ if (component.allClasses && component.allClasses.length > 0) {
205
+ const classSection = document.createElement('div');
206
+ classSection.className = 'jux-blueprint-section';
207
+
208
+ const classTitle = document.createElement('h5');
209
+ classTitle.className = 'jux-blueprint-section-title';
210
+ classTitle.textContent = 'CSS Classes';
211
+ classSection.appendChild(classTitle);
212
+
213
+ const classList = document.createElement('div');
214
+ classList.className = 'jux-blueprint-class-list';
215
+
216
+ component.allClasses.forEach((cls: string) => {
217
+ const classTag = document.createElement('span');
218
+ classTag.className = 'jux-blueprint-class-tag';
219
+ classTag.textContent = `.${cls}`;
220
+ classList.appendChild(classTag);
221
+ });
222
+
223
+ classSection.appendChild(classList);
224
+ body.appendChild(classSection);
225
+ }
226
+
227
+ // DOM Structures
228
+ if (component.domStructures && component.domStructures.length > 0) {
229
+ component.domStructures.forEach((structure: any) => {
230
+ const structSection = document.createElement('div');
231
+ structSection.className = 'jux-blueprint-section';
232
+
233
+ const methodTitle = document.createElement('h5');
234
+ methodTitle.className = 'jux-blueprint-section-title';
235
+ methodTitle.textContent = `Method: ${structure.method}()`;
236
+ structSection.appendChild(methodTitle);
237
+
238
+ // Render hierarchy if available
239
+ if (structure.hierarchy && structure.hierarchy.length > 0) {
240
+ const hierarchyEl = this._renderHierarchy(structure.hierarchy);
241
+ structSection.appendChild(hierarchyEl);
242
+ }
243
+
244
+ body.appendChild(structSection);
245
+ });
246
+ }
247
+
248
+ card.appendChild(body);
249
+ }
250
+
251
+ return card;
279
252
  }
280
- }
281
253
 
282
- private _rebuildContent(): void {
283
- if (!this.container) return;
254
+ /* ═════════════════════════════════════════════════════════════════
255
+ * REACTIVE UPDATE
256
+ * ═════════════════════════════════════════════════════════════════ */
257
+
258
+ update(prop: string, value: any): void {
259
+ super.update(prop, value);
284
260
 
285
- const contentContainer = this.container.querySelector('.jux-blueprint-content');
286
- if (!contentContainer) return;
261
+ if (!this.container) return;
287
262
 
288
- contentContainer.innerHTML = '';
263
+ const blueprint = this.container.querySelector(`#${this._id}`) as HTMLElement;
264
+ if (!blueprint) return;
289
265
 
290
- const { classData, filter } = this.state;
266
+ switch (prop) {
267
+ case 'structureData':
268
+ case 'classData':
269
+ case 'filter':
270
+ case 'showMethods':
271
+ case 'expandAll':
272
+ case 'expandedComponents':
273
+ this._rebuildContent();
274
+ break;
291
275
 
292
- if (!classData || !classData.components) {
293
- const emptyEl = document.createElement('div');
294
- emptyEl.className = 'jux-blueprint-empty';
295
- emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
296
- contentContainer.appendChild(emptyEl);
297
- return;
276
+ case 'theme':
277
+ blueprint.dataset.theme = value;
278
+ break;
279
+ }
298
280
  }
299
281
 
300
- // Filter components
301
- const filteredComponents = classData.components.filter((comp: any) => {
302
- if (!filter) return true;
303
- return comp.file.toLowerCase().includes(filter.toLowerCase());
304
- });
305
-
306
- // Render component cards
307
- filteredComponents.forEach((component: any) => {
308
- const card = this._renderComponentCard(component);
309
- contentContainer.appendChild(card);
310
- });
311
-
312
- // Show count
313
- const countEl = this.container.querySelector('.jux-blueprint-count');
314
- if (countEl) {
315
- countEl.textContent = `Showing ${filteredComponents.length} of ${classData.components.length} components`;
282
+ private _rebuildContent(): void {
283
+ if (!this.container) return;
284
+
285
+ const contentContainer = this.container.querySelector('.jux-blueprint-content');
286
+ if (!contentContainer) return;
287
+
288
+ contentContainer.innerHTML = '';
289
+
290
+ const { classData, filter } = this.state;
291
+
292
+ if (!classData || !classData.components) {
293
+ const emptyEl = document.createElement('div');
294
+ emptyEl.className = 'jux-blueprint-empty';
295
+ emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
296
+ contentContainer.appendChild(emptyEl);
297
+ return;
298
+ }
299
+
300
+ // Filter components
301
+ const filteredComponents = classData.components.filter((comp: any) => {
302
+ if (!filter) return true;
303
+ return comp.file.toLowerCase().includes(filter.toLowerCase());
304
+ });
305
+
306
+ // Render component cards
307
+ filteredComponents.forEach((component: any) => {
308
+ const card = this._renderComponentCard(component);
309
+ contentContainer.appendChild(card);
310
+ });
311
+
312
+ // Show count
313
+ const countEl = this.container.querySelector('.jux-blueprint-count');
314
+ if (countEl) {
315
+ countEl.textContent = `Showing ${filteredComponents.length} of ${classData.components.length} components`;
316
+ }
316
317
  }
317
- }
318
-
319
- /* ═════════════════════════════════════════════════════════════════
320
- * RENDER
321
- * ═════════════════════════════════════════════════════════════════ */
322
-
323
- render(targetId?: string | HTMLElement | BaseComponent<any>): this {
324
- const container = this._setupContainer(targetId);
325
- const { theme, style, class: className, classData } = this.state;
326
-
327
- // Create wrapper
328
- const wrapper = document.createElement('div');
329
- wrapper.className = 'jux-blueprint';
330
- wrapper.id = this._id;
331
- wrapper.dataset.theme = theme;
332
- if (className) wrapper.className += ` ${className}`;
333
- if (style) wrapper.setAttribute('style', style);
334
-
335
- // Header
336
- const header = document.createElement('div');
337
- header.className = 'jux-blueprint-header';
338
-
339
- const title = document.createElement('h2');
340
- title.className = 'jux-blueprint-title';
341
- title.textContent = 'Component Blueprint';
342
- header.appendChild(title);
343
-
344
- // Stats
345
- if (classData) {
346
- const stats = document.createElement('div');
347
- stats.className = 'jux-blueprint-stats';
348
- stats.innerHTML = `
318
+
319
+ /* ═════════════════════════════════════════════════════════════════
320
+ * RENDER
321
+ * ═════════════════════════════════════════════════════════════════ */
322
+
323
+ render(targetId?: string | HTMLElement | BaseComponent<any>): this {
324
+ const container = this._setupContainer(targetId);
325
+ const { theme, style, class: className, classData } = this.state;
326
+
327
+ // Create wrapper
328
+ const wrapper = document.createElement('div');
329
+ wrapper.className = 'jux-blueprint';
330
+ wrapper.id = this._id;
331
+ wrapper.dataset.theme = theme;
332
+ if (className) wrapper.className += ` ${className}`;
333
+ if (style) wrapper.setAttribute('style', style);
334
+
335
+ // Header
336
+ const header = document.createElement('div');
337
+ header.className = 'jux-blueprint-header';
338
+
339
+ const title = document.createElement('h2');
340
+ title.className = 'jux-blueprint-title';
341
+ title.textContent = 'Component Blueprint';
342
+ header.appendChild(title);
343
+
344
+ // Stats
345
+ if (classData) {
346
+ const stats = document.createElement('div');
347
+ stats.className = 'jux-blueprint-stats';
348
+ stats.innerHTML = `
349
349
  <span class="jux-blueprint-stat">
350
350
  <strong>${classData.totalFiles || 0}</strong> Components
351
351
  </span>
@@ -353,69 +353,69 @@ export class Blueprint extends BaseComponent<BlueprintState> {
353
353
  <strong>${classData.totalClasses || 0}</strong> Total Classes
354
354
  </span>
355
355
  `;
356
- header.appendChild(stats);
357
- }
358
-
359
- wrapper.appendChild(header);
360
-
361
- // Controls
362
- const controls = document.createElement('div');
363
- controls.className = 'jux-blueprint-controls';
364
-
365
- // Filter input
366
- const filterInput = document.createElement('input');
367
- filterInput.type = 'text';
368
- filterInput.className = 'jux-blueprint-filter';
369
- filterInput.placeholder = 'Filter components...';
370
- filterInput.value = this.state.filter;
371
- filterInput.addEventListener('input', (e) => {
372
- this.state.filter = (e.target as HTMLInputElement).value;
373
- });
374
- controls.appendChild(filterInput);
375
-
376
- // Expand All toggle
377
- const expandToggle = document.createElement('button');
378
- expandToggle.className = 'jux-blueprint-button';
379
- expandToggle.textContent = 'Expand All';
380
- expandToggle.addEventListener('click', () => {
381
- this.state.expandAll = !this.state.expandAll;
382
- expandToggle.textContent = this.state.expandAll ? 'Collapse All' : 'Expand All';
383
- });
384
- controls.appendChild(expandToggle);
385
-
386
- wrapper.appendChild(controls);
387
-
388
- // Count
389
- const count = document.createElement('div');
390
- count.className = 'jux-blueprint-count';
391
- count.textContent = classData ? `Showing ${classData.components.length} components` : 'No data loaded';
392
- wrapper.appendChild(count);
393
-
394
- // Content container
395
- const content = document.createElement('div');
396
- content.className = 'jux-blueprint-content';
397
-
398
- if (classData && classData.components) {
399
- classData.components.forEach((component: any) => {
400
- const card = this._renderComponentCard(component);
401
- content.appendChild(card);
402
- });
403
- } else {
404
- const emptyEl = document.createElement('div');
405
- emptyEl.className = 'jux-blueprint-empty';
406
- emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
407
- content.appendChild(emptyEl);
356
+ header.appendChild(stats);
357
+ }
358
+
359
+ wrapper.appendChild(header);
360
+
361
+ // Controls
362
+ const controls = document.createElement('div');
363
+ controls.className = 'jux-blueprint-controls';
364
+
365
+ // Filter input
366
+ const filterInput = document.createElement('input');
367
+ filterInput.type = 'text';
368
+ filterInput.className = 'jux-blueprint-filter';
369
+ filterInput.placeholder = 'Filter components...';
370
+ filterInput.value = this.state.filter;
371
+ filterInput.addEventListener('input', (e) => {
372
+ this.state.filter = (e.target as HTMLInputElement).value;
373
+ });
374
+ controls.appendChild(filterInput);
375
+
376
+ // Expand All toggle
377
+ const expandToggle = document.createElement('button');
378
+ expandToggle.className = 'jux-blueprint-button';
379
+ expandToggle.textContent = 'Expand All';
380
+ expandToggle.addEventListener('click', () => {
381
+ this.state.expandAll = !this.state.expandAll;
382
+ expandToggle.textContent = this.state.expandAll ? 'Collapse All' : 'Expand All';
383
+ });
384
+ controls.appendChild(expandToggle);
385
+
386
+ wrapper.appendChild(controls);
387
+
388
+ // Count
389
+ const count = document.createElement('div');
390
+ count.className = 'jux-blueprint-count';
391
+ count.textContent = classData ? `Showing ${classData.components.length} components` : 'No data loaded';
392
+ wrapper.appendChild(count);
393
+
394
+ // Content container
395
+ const content = document.createElement('div');
396
+ content.className = 'jux-blueprint-content';
397
+
398
+ if (classData && classData.components) {
399
+ classData.components.forEach((component: any) => {
400
+ const card = this._renderComponentCard(component);
401
+ content.appendChild(card);
402
+ });
403
+ } else {
404
+ const emptyEl = document.createElement('div');
405
+ emptyEl.className = 'jux-blueprint-empty';
406
+ emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
407
+ content.appendChild(emptyEl);
408
+ }
409
+
410
+ wrapper.appendChild(content);
411
+
412
+ this._wireStandardEvents(wrapper);
413
+ container.appendChild(wrapper);
414
+
415
+ return this;
408
416
  }
409
-
410
- wrapper.appendChild(content);
411
-
412
- this._wireStandardEvents(wrapper);
413
- container.appendChild(wrapper);
414
-
415
- return this;
416
- }
417
417
  }
418
418
 
419
419
  export function blueprint(id: string, options: BlueprintOptions = {}): Blueprint {
420
- return new Blueprint(id, options);
420
+ return new Blueprint(id, options);
421
421
  }