juxscript 1.1.65 → 1.1.67

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.
@@ -1,45 +1,38 @@
1
1
  import { BaseComponent, BaseState } from './base/BaseComponent.js';
2
2
  export interface BlueprintOptions {
3
- componentId?: string;
4
- showClasses?: boolean;
5
- showIds?: boolean;
6
- showTags?: boolean;
3
+ structureData?: any;
4
+ classData?: any;
5
+ filter?: string;
6
+ showMethods?: boolean;
7
7
  expandAll?: boolean;
8
8
  theme?: 'light' | 'dark' | 'auto';
9
- interactive?: boolean;
10
9
  style?: string;
11
10
  class?: string;
12
11
  }
13
12
  interface BlueprintState extends BaseState {
14
- componentId: string;
15
- showClasses: boolean;
16
- showIds: boolean;
17
- showTags: boolean;
13
+ structureData: any;
14
+ classData: any;
15
+ filter: string;
16
+ showMethods: boolean;
18
17
  expandAll: boolean;
19
18
  theme: string;
20
- interactive: boolean;
21
- selectedNode: string | null;
22
- hoveredNode: string | null;
19
+ expandedComponents: Set<string>;
23
20
  }
24
21
  export declare class Blueprint extends BaseComponent<BlueprintState> {
25
- private _domStructure;
26
22
  constructor(id: string, options?: BlueprintOptions);
27
23
  protected getTriggerEvents(): readonly string[];
28
24
  protected getCallbackEvents(): readonly string[];
29
- componentId(value: string): this;
30
- showClasses(value: boolean): this;
31
- showIds(value: boolean): this;
32
- showTags(value: boolean): this;
25
+ structureData(data: any): this;
26
+ classData(data: any): this;
27
+ filter(value: string): this;
28
+ showMethods(value: boolean): this;
33
29
  expandAll(value: boolean): this;
34
30
  theme(value: 'light' | 'dark' | 'auto'): this;
35
- interactive(value: boolean): this;
36
- selectNode(path: string): this;
37
- private _analyzeDOMStructure;
38
- private _renderNode;
39
- private _renderTree;
31
+ toggleComponent(componentFile: string): this;
32
+ private _renderHierarchy;
33
+ private _renderComponentCard;
40
34
  update(prop: string, value: any): void;
41
- private _rebuildTree;
42
- private _updateNodeStates;
35
+ private _rebuildContent;
43
36
  render(targetId?: string | HTMLElement | BaseComponent<any>): this;
44
37
  }
45
38
  export declare function blueprint(id: string, options?: BlueprintOptions): Blueprint;
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAOnE,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,cAAe,SAAQ,SAAS;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAWD,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,CAAC;IACxD,OAAO,CAAC,aAAa,CAAiB;gBAE1B,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAgBtD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKhC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKjC,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK7B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK9B,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK/B,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAK7C,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKjC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU9B,OAAO,CAAC,oBAAoB;IAmC5B,OAAO,CAAC,WAAW;IAyFnB,OAAO,CAAC,WAAW;IAwBnB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAiCtC,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,iBAAiB;IAiBzB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI;CA8FrE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAE/E"}
1
+ {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMnE,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAe,SAAQ,SAAS;IACxC,aAAa,EAAE,GAAG,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AASD,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,CAAC;gBAC9C,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IActD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAQhD,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAK9B,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAK1B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK3B,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKjC,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK/B,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAK7C,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAc5C,OAAO,CAAC,gBAAgB;IA2DxB,OAAO,CAAC,oBAAoB;IA6F5B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAwBtC,OAAO,CAAC,eAAe;IAyCvB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI;CA8FnE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAE/E"}
@@ -1,24 +1,20 @@
1
1
  import { BaseComponent } from './base/BaseComponent.js';
2
- import { registry } from './registry.js';
3
2
  // Event definitions
4
3
  const TRIGGER_EVENTS = [];
5
- const CALLBACK_EVENTS = ['select', 'hover'];
4
+ const CALLBACK_EVENTS = ['select', 'expand'];
6
5
  export class Blueprint extends BaseComponent {
7
6
  constructor(id, options = {}) {
8
7
  super(id, {
9
- componentId: options.componentId ?? '',
10
- showClasses: options.showClasses ?? true,
11
- showIds: options.showIds ?? true,
12
- showTags: options.showTags ?? true,
13
- expandAll: options.expandAll ?? true,
8
+ structureData: options.structureData ?? null,
9
+ classData: options.classData ?? null,
10
+ filter: options.filter ?? '',
11
+ showMethods: options.showMethods ?? true,
12
+ expandAll: options.expandAll ?? false,
14
13
  theme: options.theme ?? 'auto',
15
- interactive: options.interactive ?? true,
16
- selectedNode: null,
17
- hoveredNode: null,
14
+ expandedComponents: new Set(),
18
15
  style: options.style ?? '',
19
16
  class: options.class ?? ''
20
17
  });
21
- this._domStructure = [];
22
18
  }
23
19
  getTriggerEvents() {
24
20
  return TRIGGER_EVENTS;
@@ -29,20 +25,20 @@ export class Blueprint extends BaseComponent {
29
25
  /* ═════════════════════════════════════════════════════════════════
30
26
  * FLUENT API
31
27
  * ═════════════════════════════════════════════════════════════════ */
32
- componentId(value) {
33
- this.state.componentId = value;
28
+ structureData(data) {
29
+ this.state.structureData = data;
34
30
  return this;
35
31
  }
36
- showClasses(value) {
37
- this.state.showClasses = value;
32
+ classData(data) {
33
+ this.state.classData = data;
38
34
  return this;
39
35
  }
40
- showIds(value) {
41
- this.state.showIds = value;
36
+ filter(value) {
37
+ this.state.filter = value;
42
38
  return this;
43
39
  }
44
- showTags(value) {
45
- this.state.showTags = value;
40
+ showMethods(value) {
41
+ this.state.showMethods = value;
46
42
  return this;
47
43
  }
48
44
  expandAll(value) {
@@ -53,132 +49,136 @@ export class Blueprint extends BaseComponent {
53
49
  this.state.theme = value;
54
50
  return this;
55
51
  }
56
- interactive(value) {
57
- this.state.interactive = value;
58
- return this;
59
- }
60
- selectNode(path) {
61
- this.state.selectedNode = path;
62
- this._triggerCallback('select', path);
63
- return this;
64
- }
65
- /* ═════════════════════════════════════════════════════════════════
66
- * DOM ANALYSIS
67
- * ═════════════════════════════════════════════════════════════════ */
68
- _analyzeDOMStructure(componentId) {
69
- const component = registry.get(componentId);
70
- if (!component || !component.container) {
71
- return [];
52
+ toggleComponent(componentFile) {
53
+ if (this.state.expandedComponents.has(componentFile)) {
54
+ this.state.expandedComponents.delete(componentFile);
72
55
  }
73
- const rootElement = component.container.querySelector(`#${componentId}`);
74
- if (!rootElement) {
75
- return [];
56
+ else {
57
+ this.state.expandedComponents.add(componentFile);
76
58
  }
77
- const extractNode = (element, depth = 0, path = '0') => {
78
- const node = {
79
- tag: element.tagName.toLowerCase(),
80
- classes: Array.from(element.classList),
81
- id: element.id || null,
82
- depth,
83
- path,
84
- children: []
85
- };
86
- Array.from(element.children).forEach((child, index) => {
87
- node.children.push(extractNode(child, depth + 1, `${path}.${index}`));
88
- });
89
- return node;
90
- };
91
- return [extractNode(rootElement)];
59
+ this._triggerCallback('expand', componentFile);
60
+ return this;
92
61
  }
93
62
  /* ═════════════════════════════════════════════════════════════════
94
- * RENDER NODE
63
+ * RENDER HELPERS
95
64
  * ═════════════════════════════════════════════════════════════════ */
96
- _renderNode(node, isLast = false, prefix = '') {
97
- const { showClasses, showIds, showTags, interactive, selectedNode, hoveredNode } = this.state;
98
- const nodeEl = document.createElement('div');
99
- nodeEl.className = 'jux-blueprint-node';
100
- nodeEl.dataset.path = node.path;
101
- if (selectedNode === node.path) {
102
- nodeEl.classList.add('jux-blueprint-node-selected');
103
- }
104
- if (hoveredNode === node.path) {
105
- nodeEl.classList.add('jux-blueprint-node-hovered');
106
- }
107
- // Tree line
108
- const lineEl = document.createElement('span');
109
- lineEl.className = 'jux-blueprint-line';
110
- const connector = isLast ? '└─' : '├─';
111
- const indent = prefix + connector;
112
- lineEl.textContent = indent;
113
- nodeEl.appendChild(lineEl);
114
- // Node content
115
- const contentEl = document.createElement('span');
116
- contentEl.className = 'jux-blueprint-content';
117
- // Tag
118
- if (showTags) {
65
+ _renderHierarchy(hierarchy, depth = 0) {
66
+ const container = document.createElement('div');
67
+ container.className = 'jux-blueprint-hierarchy';
68
+ hierarchy.forEach((node, index) => {
69
+ const nodeEl = document.createElement('div');
70
+ nodeEl.className = 'jux-blueprint-node';
71
+ nodeEl.style.paddingLeft = `${depth * 20}px`;
72
+ const isLast = index === hierarchy.length - 1;
73
+ const connector = isLast ? '└─' : '├─';
74
+ // Tree line
75
+ const lineEl = document.createElement('span');
76
+ lineEl.className = 'jux-blueprint-line';
77
+ lineEl.textContent = connector + ' ';
78
+ nodeEl.appendChild(lineEl);
79
+ // Tag
119
80
  const tagEl = document.createElement('span');
120
81
  tagEl.className = 'jux-blueprint-tag';
121
82
  tagEl.textContent = `<${node.tag}>`;
122
- contentEl.appendChild(tagEl);
123
- }
124
- // ID
125
- if (showIds && node.id) {
126
- const idEl = document.createElement('span');
127
- idEl.className = 'jux-blueprint-id';
128
- idEl.textContent = `#${node.id}`;
129
- contentEl.appendChild(idEl);
130
- }
131
- // Classes
132
- if (showClasses && node.classes.length > 0) {
133
- const classesEl = document.createElement('span');
134
- classesEl.className = 'jux-blueprint-classes';
135
- node.classes.forEach((cls, index) => {
136
- const classEl = document.createElement('span');
137
- classEl.className = 'jux-blueprint-class';
138
- classEl.textContent = `.${cls}`;
139
- classesEl.appendChild(classEl);
140
- if (index < node.classes.length - 1) {
83
+ nodeEl.appendChild(tagEl);
84
+ // ID
85
+ if (node.id) {
86
+ const idEl = document.createElement('span');
87
+ idEl.className = 'jux-blueprint-id';
88
+ idEl.textContent = ` #${node.id}`;
89
+ nodeEl.appendChild(idEl);
90
+ }
91
+ // Classes
92
+ if (node.classes && node.classes.length > 0) {
93
+ const classesEl = document.createElement('span');
94
+ classesEl.className = 'jux-blueprint-classes';
95
+ node.classes.forEach(cls => {
96
+ const classEl = document.createElement('span');
97
+ classEl.className = 'jux-blueprint-class';
98
+ classEl.textContent = `.${cls}`;
99
+ classesEl.appendChild(classEl);
141
100
  classesEl.appendChild(document.createTextNode(' '));
142
- }
143
- });
144
- contentEl.appendChild(classesEl);
145
- }
146
- nodeEl.appendChild(contentEl);
147
- // Interactive behavior
148
- if (interactive) {
149
- nodeEl.style.cursor = 'pointer';
150
- nodeEl.addEventListener('click', (e) => {
151
- e.stopPropagation();
152
- this.state.selectedNode = node.path;
153
- this._triggerCallback('select', node);
154
- });
155
- nodeEl.addEventListener('mouseenter', () => {
156
- this.state.hoveredNode = node.path;
157
- this._triggerCallback('hover', node);
158
- });
159
- nodeEl.addEventListener('mouseleave', () => {
160
- if (this.state.hoveredNode === node.path) {
161
- this.state.hoveredNode = null;
162
- }
163
- });
164
- }
165
- return nodeEl;
166
- }
167
- _renderTree(nodes, prefix = '') {
168
- const treeEl = document.createElement('div');
169
- treeEl.className = 'jux-blueprint-tree';
170
- nodes.forEach((node, index) => {
171
- const isLast = index === nodes.length - 1;
172
- const nodeEl = this._renderNode(node, isLast, prefix);
173
- treeEl.appendChild(nodeEl);
174
- // Render children
175
- if (node.children.length > 0) {
176
- const childPrefix = prefix + (isLast ? ' ' : '│ ');
177
- const childrenEl = this._renderTree(node.children, childPrefix);
178
- treeEl.appendChild(childrenEl);
101
+ });
102
+ nodeEl.appendChild(classesEl);
103
+ }
104
+ container.appendChild(nodeEl);
105
+ // Render children recursively
106
+ if (node.children && node.children.length > 0) {
107
+ container.appendChild(this._renderHierarchy(node.children, depth + 1));
179
108
  }
180
109
  });
181
- return treeEl;
110
+ return container;
111
+ }
112
+ _renderComponentCard(component) {
113
+ const { showMethods, expandAll, expandedComponents } = this.state;
114
+ const isExpanded = expandAll || expandedComponents.has(component.file);
115
+ const card = document.createElement('div');
116
+ card.className = 'jux-blueprint-card';
117
+ if (isExpanded)
118
+ card.classList.add('jux-blueprint-card-expanded');
119
+ // Header
120
+ const header = document.createElement('div');
121
+ header.className = 'jux-blueprint-card-header';
122
+ header.addEventListener('click', () => {
123
+ this.toggleComponent(component.file);
124
+ this.update('expandedComponents', this.state.expandedComponents);
125
+ });
126
+ const title = document.createElement('h4');
127
+ title.className = 'jux-blueprint-card-title';
128
+ title.textContent = component.file;
129
+ header.appendChild(title);
130
+ const badge = document.createElement('span');
131
+ badge.className = 'jux-blueprint-badge';
132
+ badge.textContent = `${component.classCount} classes`;
133
+ header.appendChild(badge);
134
+ const toggle = document.createElement('span');
135
+ toggle.className = 'jux-blueprint-toggle-icon';
136
+ toggle.textContent = isExpanded ? '▼' : '▶';
137
+ header.appendChild(toggle);
138
+ card.appendChild(header);
139
+ // Body (collapsed by default)
140
+ if (isExpanded) {
141
+ const body = document.createElement('div');
142
+ body.className = 'jux-blueprint-card-body';
143
+ // Class list
144
+ if (component.allClasses && component.allClasses.length > 0) {
145
+ const classSection = document.createElement('div');
146
+ classSection.className = 'jux-blueprint-section';
147
+ const classTitle = document.createElement('h5');
148
+ classTitle.className = 'jux-blueprint-section-title';
149
+ classTitle.textContent = 'CSS Classes';
150
+ classSection.appendChild(classTitle);
151
+ const classList = document.createElement('div');
152
+ classList.className = 'jux-blueprint-class-list';
153
+ component.allClasses.forEach((cls) => {
154
+ const classTag = document.createElement('span');
155
+ classTag.className = 'jux-blueprint-class-tag';
156
+ classTag.textContent = `.${cls}`;
157
+ classList.appendChild(classTag);
158
+ });
159
+ classSection.appendChild(classList);
160
+ body.appendChild(classSection);
161
+ }
162
+ // DOM Structures
163
+ if (component.domStructures && component.domStructures.length > 0) {
164
+ component.domStructures.forEach((structure) => {
165
+ const structSection = document.createElement('div');
166
+ structSection.className = 'jux-blueprint-section';
167
+ const methodTitle = document.createElement('h5');
168
+ methodTitle.className = 'jux-blueprint-section-title';
169
+ methodTitle.textContent = `Method: ${structure.method}()`;
170
+ structSection.appendChild(methodTitle);
171
+ // Render hierarchy if available
172
+ if (structure.hierarchy && structure.hierarchy.length > 0) {
173
+ const hierarchyEl = this._renderHierarchy(structure.hierarchy);
174
+ structSection.appendChild(hierarchyEl);
175
+ }
176
+ body.appendChild(structSection);
177
+ });
178
+ }
179
+ card.appendChild(body);
180
+ }
181
+ return card;
182
182
  }
183
183
  /* ═════════════════════════════════════════════════════════════════
184
184
  * REACTIVE UPDATE
@@ -191,65 +191,57 @@ export class Blueprint extends BaseComponent {
191
191
  if (!blueprint)
192
192
  return;
193
193
  switch (prop) {
194
- case 'componentId':
195
- this._domStructure = this._analyzeDOMStructure(value);
196
- this._rebuildTree();
197
- break;
198
- case 'showClasses':
199
- case 'showIds':
200
- case 'showTags':
194
+ case 'structureData':
195
+ case 'classData':
196
+ case 'filter':
197
+ case 'showMethods':
201
198
  case 'expandAll':
202
- case 'interactive':
203
- this._rebuildTree();
199
+ case 'expandedComponents':
200
+ this._rebuildContent();
204
201
  break;
205
202
  case 'theme':
206
203
  blueprint.dataset.theme = value;
207
204
  break;
208
- case 'selectedNode':
209
- case 'hoveredNode':
210
- this._updateNodeStates();
211
- break;
212
205
  }
213
206
  }
214
- _rebuildTree() {
207
+ _rebuildContent() {
215
208
  if (!this.container)
216
209
  return;
217
- const treeContainer = this.container.querySelector('.jux-blueprint-tree-container');
218
- if (!treeContainer)
210
+ const contentContainer = this.container.querySelector('.jux-blueprint-content');
211
+ if (!contentContainer)
219
212
  return;
220
- treeContainer.innerHTML = '';
221
- if (this._domStructure.length > 0) {
222
- const treeEl = this._renderTree(this._domStructure);
223
- treeContainer.appendChild(treeEl);
224
- }
225
- else {
213
+ contentContainer.innerHTML = '';
214
+ const { classData, filter } = this.state;
215
+ if (!classData || !classData.components) {
226
216
  const emptyEl = document.createElement('div');
227
217
  emptyEl.className = 'jux-blueprint-empty';
228
- emptyEl.textContent = 'No component selected or component not found';
229
- treeContainer.appendChild(emptyEl);
230
- }
231
- }
232
- _updateNodeStates() {
233
- if (!this.container)
218
+ emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
219
+ contentContainer.appendChild(emptyEl);
234
220
  return;
235
- const nodes = this.container.querySelectorAll('.jux-blueprint-node');
236
- nodes.forEach(node => {
237
- const el = node;
238
- const path = el.dataset.path;
239
- el.classList.toggle('jux-blueprint-node-selected', path === this.state.selectedNode);
240
- el.classList.toggle('jux-blueprint-node-hovered', path === this.state.hoveredNode);
221
+ }
222
+ // Filter components
223
+ const filteredComponents = classData.components.filter((comp) => {
224
+ if (!filter)
225
+ return true;
226
+ return comp.file.toLowerCase().includes(filter.toLowerCase());
227
+ });
228
+ // Render component cards
229
+ filteredComponents.forEach((component) => {
230
+ const card = this._renderComponentCard(component);
231
+ contentContainer.appendChild(card);
241
232
  });
233
+ // Show count
234
+ const countEl = this.container.querySelector('.jux-blueprint-count');
235
+ if (countEl) {
236
+ countEl.textContent = `Showing ${filteredComponents.length} of ${classData.components.length} components`;
237
+ }
242
238
  }
243
239
  /* ═════════════════════════════════════════════════════════════════
244
240
  * RENDER
245
241
  * ═════════════════════════════════════════════════════════════════ */
246
242
  render(targetId) {
247
243
  const container = this._setupContainer(targetId);
248
- const { componentId, theme, style, class: className } = this.state;
249
- // Analyze structure if componentId is provided
250
- if (componentId) {
251
- this._domStructure = this._analyzeDOMStructure(componentId);
252
- }
244
+ const { theme, style, class: className, classData } = this.state;
253
245
  // Create wrapper
254
246
  const wrapper = document.createElement('div');
255
247
  wrapper.className = 'jux-blueprint';
@@ -262,64 +254,69 @@ export class Blueprint extends BaseComponent {
262
254
  // Header
263
255
  const header = document.createElement('div');
264
256
  header.className = 'jux-blueprint-header';
265
- const title = document.createElement('h3');
257
+ const title = document.createElement('h2');
266
258
  title.className = 'jux-blueprint-title';
267
- title.textContent = componentId ? `Blueprint: ${componentId}` : 'Component Blueprint';
259
+ title.textContent = 'Component Blueprint';
268
260
  header.appendChild(title);
261
+ // Stats
262
+ if (classData) {
263
+ const stats = document.createElement('div');
264
+ stats.className = 'jux-blueprint-stats';
265
+ stats.innerHTML = `
266
+ <span class="jux-blueprint-stat">
267
+ <strong>${classData.totalFiles || 0}</strong> Components
268
+ </span>
269
+ <span class="jux-blueprint-stat">
270
+ <strong>${classData.totalClasses || 0}</strong> Total Classes
271
+ </span>
272
+ `;
273
+ header.appendChild(stats);
274
+ }
275
+ wrapper.appendChild(header);
269
276
  // Controls
270
277
  const controls = document.createElement('div');
271
278
  controls.className = 'jux-blueprint-controls';
272
- const toggles = [
273
- { prop: 'showTags', label: 'Tags' },
274
- { prop: 'showIds', label: 'IDs' },
275
- { prop: 'showClasses', label: 'Classes' }
276
- ];
277
- toggles.forEach(({ prop, label }) => {
278
- const toggleEl = document.createElement('label');
279
- toggleEl.className = 'jux-blueprint-toggle';
280
- const checkbox = document.createElement('input');
281
- checkbox.type = 'checkbox';
282
- checkbox.checked = this.state[prop];
283
- checkbox.addEventListener('change', () => {
284
- this.state[prop] = checkbox.checked;
285
- });
286
- toggleEl.appendChild(checkbox);
287
- toggleEl.appendChild(document.createTextNode(` ${label}`));
288
- controls.appendChild(toggleEl);
279
+ // Filter input
280
+ const filterInput = document.createElement('input');
281
+ filterInput.type = 'text';
282
+ filterInput.className = 'jux-blueprint-filter';
283
+ filterInput.placeholder = 'Filter components...';
284
+ filterInput.value = this.state.filter;
285
+ filterInput.addEventListener('input', (e) => {
286
+ this.state.filter = e.target.value;
289
287
  });
290
- header.appendChild(controls);
291
- wrapper.appendChild(header);
292
- // Tree container
293
- const treeContainer = document.createElement('div');
294
- treeContainer.className = 'jux-blueprint-tree-container';
295
- if (this._domStructure.length > 0) {
296
- const treeEl = this._renderTree(this._domStructure);
297
- treeContainer.appendChild(treeEl);
288
+ controls.appendChild(filterInput);
289
+ // Expand All toggle
290
+ const expandToggle = document.createElement('button');
291
+ expandToggle.className = 'jux-blueprint-button';
292
+ expandToggle.textContent = 'Expand All';
293
+ expandToggle.addEventListener('click', () => {
294
+ this.state.expandAll = !this.state.expandAll;
295
+ expandToggle.textContent = this.state.expandAll ? 'Collapse All' : 'Expand All';
296
+ });
297
+ controls.appendChild(expandToggle);
298
+ wrapper.appendChild(controls);
299
+ // Count
300
+ const count = document.createElement('div');
301
+ count.className = 'jux-blueprint-count';
302
+ count.textContent = classData ? `Showing ${classData.components.length} components` : 'No data loaded';
303
+ wrapper.appendChild(count);
304
+ // Content container
305
+ const content = document.createElement('div');
306
+ content.className = 'jux-blueprint-content';
307
+ if (classData && classData.components) {
308
+ classData.components.forEach((component) => {
309
+ const card = this._renderComponentCard(component);
310
+ content.appendChild(card);
311
+ });
298
312
  }
299
313
  else {
300
314
  const emptyEl = document.createElement('div');
301
315
  emptyEl.className = 'jux-blueprint-empty';
302
- emptyEl.textContent = componentId
303
- ? `Component "${componentId}" not found or not rendered`
304
- : 'Set componentId to analyze a component';
305
- treeContainer.appendChild(emptyEl);
316
+ emptyEl.textContent = 'No component data loaded. Use .structureData() and .classData() to load JSON files.';
317
+ content.appendChild(emptyEl);
306
318
  }
307
- wrapper.appendChild(treeContainer);
308
- // Legend
309
- const legend = document.createElement('div');
310
- legend.className = 'jux-blueprint-legend';
311
- legend.innerHTML = `
312
- <span class="jux-blueprint-legend-item">
313
- <span class="jux-blueprint-tag">&lt;tag&gt;</span> HTML Element
314
- </span>
315
- <span class="jux-blueprint-legend-item">
316
- <span class="jux-blueprint-id">#id</span> Element ID
317
- </span>
318
- <span class="jux-blueprint-legend-item">
319
- <span class="jux-blueprint-class">.class</span> CSS Class
320
- </span>
321
- `;
322
- wrapper.appendChild(legend);
319
+ wrapper.appendChild(content);
323
320
  this._wireStandardEvents(wrapper);
324
321
  container.appendChild(wrapper);
325
322
  return this;