juxscript 1.1.71 → 1.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +56 -7
- package/css-classes-inventory.json +1 -556
- package/dom-structure-map.json +2 -487
- package/index.d.ts +0 -2
- package/index.d.ts.map +1 -1
- package/index.js +0 -2
- package/juxconfig.example.js +1 -0
- package/lib/styles/modal.css +402 -0
- package/machinery/build3.js +13 -3
- package/machinery/compiler3.js +83 -0
- package/package.json +1 -1
- package/lib/components/blueprint.ts +0 -421
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
import { BaseComponent, BaseState } from './base/BaseComponent.js';
|
|
2
|
-
|
|
3
|
-
// Event definitions
|
|
4
|
-
const TRIGGER_EVENTS = [] as const;
|
|
5
|
-
const CALLBACK_EVENTS = ['select', 'expand'] as const;
|
|
6
|
-
|
|
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;
|
|
16
|
-
}
|
|
17
|
-
|
|
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>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface ComponentHierarchy {
|
|
29
|
-
tag: string;
|
|
30
|
-
classes: string[];
|
|
31
|
-
id: string | null;
|
|
32
|
-
children?: ComponentHierarchy[];
|
|
33
|
-
}
|
|
34
|
-
|
|
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(' '));
|
|
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
|
-
});
|
|
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
|
-
});
|
|
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;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
255
|
-
* REACTIVE UPDATE
|
|
256
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
257
|
-
|
|
258
|
-
update(prop: string, value: any): void {
|
|
259
|
-
super.update(prop, value);
|
|
260
|
-
|
|
261
|
-
if (!this.container) return;
|
|
262
|
-
|
|
263
|
-
const blueprint = this.container.querySelector(`#${this._id}`) as HTMLElement;
|
|
264
|
-
if (!blueprint) return;
|
|
265
|
-
|
|
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;
|
|
275
|
-
|
|
276
|
-
case 'theme':
|
|
277
|
-
blueprint.dataset.theme = value;
|
|
278
|
-
break;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
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
|
-
}
|
|
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 = `
|
|
349
|
-
<span class="jux-blueprint-stat">
|
|
350
|
-
<strong>${classData.totalFiles || 0}</strong> Components
|
|
351
|
-
</span>
|
|
352
|
-
<span class="jux-blueprint-stat">
|
|
353
|
-
<strong>${classData.totalClasses || 0}</strong> Total Classes
|
|
354
|
-
</span>
|
|
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);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
wrapper.appendChild(content);
|
|
411
|
-
|
|
412
|
-
this._wireStandardEvents(wrapper);
|
|
413
|
-
container.appendChild(wrapper);
|
|
414
|
-
|
|
415
|
-
return this;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
export function blueprint(id: string, options: BlueprintOptions = {}): Blueprint {
|
|
420
|
-
return new Blueprint(id, options);
|
|
421
|
-
}
|