@wukong-kit/extension 0.1.0

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.
@@ -0,0 +1,770 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.methods = exports.$ = exports.style = exports.template = void 0;
4
+ exports.ready = ready;
5
+ const PACKAGE_NAME = 'wukong';
6
+ exports.template = `
7
+ <div class="wukong-panel">
8
+ <header class="topbar">
9
+ <div>
10
+ <h2>Wukong Kit</h2>
11
+ <p>2D MVC workflow tools</p>
12
+ </div>
13
+ <ui-button id="refresh">Refresh</ui-button>
14
+ </header>
15
+
16
+ <nav class="tabs">
17
+ <ui-button id="moduleTab" class="tab active">Modules</ui-button>
18
+ <ui-button id="managerTab" class="tab">Managers</ui-button>
19
+ <ui-button id="librariesTab" class="tab">Libraries</ui-button>
20
+ <ui-button id="diagnosticsTab" class="tab">Diagnostics</ui-button>
21
+ </nav>
22
+
23
+ <section id="modulePage" class="page active">
24
+ <aside class="module-list">
25
+ <ui-button id="newModule" class="new-module">+ New Module</ui-button>
26
+ <div id="projectModules"></div>
27
+ </aside>
28
+
29
+ <main class="module-detail">
30
+ <section id="createModulePanel" class="surface">
31
+ <div class="section-head">
32
+ <div>
33
+ <h3>Create Module</h3>
34
+ <p>Create a logic module, optionally with an initial View.</p>
35
+ </div>
36
+ </div>
37
+ <div class="form-row">
38
+ <label>Module Name</label>
39
+ <ui-input id="moduleName" placeholder="battle"></ui-input>
40
+ </div>
41
+ <div class="form-row">
42
+ <label>Init Order</label>
43
+ <ui-input id="moduleOrder" placeholder="100" value="100"></ui-input>
44
+ </div>
45
+ <label class="check-row">
46
+ <input id="withView" type="checkbox" />
47
+ <span>Create initial View</span>
48
+ </label>
49
+ <ui-button id="create">Create Module</ui-button>
50
+ <p id="status"></p>
51
+ </section>
52
+
53
+ <section id="moduleInfoPanel" class="surface hidden">
54
+ <div class="section-head">
55
+ <div>
56
+ <h3 id="selectedTitle">Module</h3>
57
+ <p id="selectedPath"></p>
58
+ </div>
59
+ </div>
60
+ <div class="order-editor">
61
+ <div class="form-row">
62
+ <label>Init Order</label>
63
+ <ui-input id="selectedOrder" placeholder="100"></ui-input>
64
+ </div>
65
+ <ui-button id="saveOrder">Save Order</ui-button>
66
+ </div>
67
+ <div id="moduleFiles" class="file-list"></div>
68
+
69
+ <div class="subhead">
70
+ <h3>Views</h3>
71
+ </div>
72
+ <div id="moduleViews" class="view-list"></div>
73
+
74
+ <div class="add-view">
75
+ <div class="form-row">
76
+ <label>View Name</label>
77
+ <ui-input id="viewName" placeholder="Panel"></ui-input>
78
+ </div>
79
+ <div class="form-grid">
80
+ <div class="form-row">
81
+ <label>Layer</label>
82
+ <select id="viewLayer">
83
+ <option value="UI">UI</option>
84
+ <option value="Popup">Popup</option>
85
+ <option value="Tip">Tip</option>
86
+ <option value="Game">Game</option>
87
+ <option value="Scene">Scene</option>
88
+ </select>
89
+ </div>
90
+ <label class="check-row">
91
+ <input id="viewCache" type="checkbox" checked />
92
+ <span>Cache View</span>
93
+ </label>
94
+ </div>
95
+ <ui-button id="addView">Add View</ui-button>
96
+ </div>
97
+ </section>
98
+ </main>
99
+ </section>
100
+
101
+ <section id="managerPage" class="page manager-page">
102
+ <section class="surface manager-card">
103
+ <div class="section-head">
104
+ <div>
105
+ <h3>Create Manager</h3>
106
+ <p>Generate a singleton manager under scripts/core/managers.</p>
107
+ </div>
108
+ </div>
109
+ <div class="form-row">
110
+ <label>Manager Name</label>
111
+ <ui-input id="managerName" placeholder="audio"></ui-input>
112
+ </div>
113
+ <ui-button id="createManager">Create Manager</ui-button>
114
+ <p id="managerStatus"></p>
115
+ </section>
116
+ </section>
117
+
118
+ <section id="librariesPage" class="page">
119
+ <div class="section-head">
120
+ <div>
121
+ <h3>Libraries</h3>
122
+ <p>Optional npm modules supported by this project.</p>
123
+ </div>
124
+ </div>
125
+ <div id="modules"></div>
126
+ </section>
127
+
128
+ <section id="diagnosticsPage" class="page diagnostics-page">
129
+ <section class="surface">
130
+ <div class="section-head">
131
+ <div>
132
+ <h3>Project Diagnostics</h3>
133
+ <p>Check Wukong modules, views, prefabs, and optional libraries.</p>
134
+ </div>
135
+ <ui-button id="runDiagnostics">Run Check</ui-button>
136
+ </div>
137
+ <div id="diagnostics"></div>
138
+ </section>
139
+ </section>
140
+ </div>
141
+ `;
142
+ exports.style = `
143
+ .wukong-panel {
144
+ box-sizing: border-box;
145
+ height: 100%;
146
+ padding: 14px;
147
+ color: var(--color-normal-contrast);
148
+ background: var(--color-normal-fill);
149
+ display: flex;
150
+ flex-direction: column;
151
+ min-height: 0;
152
+ }
153
+ .topbar {
154
+ flex: 0 0 auto;
155
+ display: flex;
156
+ justify-content: space-between;
157
+ align-items: center;
158
+ gap: 12px;
159
+ padding-bottom: 12px;
160
+ border-bottom: 1px solid var(--color-normal-border);
161
+ }
162
+ .tabs {
163
+ flex: 0 0 auto;
164
+ display: flex;
165
+ gap: 8px;
166
+ margin-top: 14px;
167
+ padding: 4px;
168
+ border: 1px solid var(--color-normal-border);
169
+ border-radius: 6px;
170
+ background: var(--color-normal-fill-emphasis);
171
+ }
172
+ .tab {
173
+ flex: 1;
174
+ }
175
+ .tab.active {
176
+ border-color: var(--color-primary-fill);
177
+ }
178
+ h2, h3, p {
179
+ margin: 0;
180
+ }
181
+ h2 {
182
+ font-size: 16px;
183
+ font-weight: 600;
184
+ }
185
+ h3 {
186
+ font-size: 13px;
187
+ font-weight: 600;
188
+ }
189
+ .topbar p,
190
+ .section-head p,
191
+ #status,
192
+ .muted,
193
+ .module p {
194
+ color: var(--color-normal-contrast-weaker);
195
+ }
196
+ .topbar p,
197
+ .section-head p {
198
+ margin-top: 4px;
199
+ font-size: 12px;
200
+ }
201
+ .page {
202
+ display: none;
203
+ flex: 1 1 auto;
204
+ min-height: 0;
205
+ margin-top: 14px;
206
+ }
207
+ .page.active {
208
+ display: flex;
209
+ overflow-y: auto;
210
+ overflow-x: hidden;
211
+ }
212
+ .manager-page.active {
213
+ display: block;
214
+ }
215
+ .diagnostics-page.active {
216
+ display: block;
217
+ }
218
+ #librariesPage.active {
219
+ display: block;
220
+ padding: 12px;
221
+ border: 1px solid var(--color-normal-border);
222
+ border-radius: 6px;
223
+ background: var(--color-normal-fill-emphasis);
224
+ }
225
+ .module-list {
226
+ flex: 0 0 220px;
227
+ min-width: 0;
228
+ padding: 10px;
229
+ border: 1px solid var(--color-normal-border);
230
+ border-radius: 6px;
231
+ background: var(--color-normal-fill-emphasis);
232
+ overflow-y: auto;
233
+ }
234
+ .new-module {
235
+ width: 100%;
236
+ margin-bottom: 10px;
237
+ }
238
+ .module-item {
239
+ display: block;
240
+ width: 100%;
241
+ margin-top: 8px;
242
+ padding: 9px;
243
+ border: 1px solid var(--color-normal-border);
244
+ border-radius: 6px;
245
+ background: var(--color-normal-fill);
246
+ color: var(--color-normal-contrast);
247
+ text-align: left;
248
+ }
249
+ .module-item.active {
250
+ border-color: var(--color-primary-fill);
251
+ }
252
+ .module-item strong,
253
+ .module-item span {
254
+ display: block;
255
+ }
256
+ .module-item strong {
257
+ overflow: hidden;
258
+ text-overflow: ellipsis;
259
+ white-space: nowrap;
260
+ }
261
+ .module-item span {
262
+ margin-top: 4px;
263
+ font-size: 12px;
264
+ color: var(--color-normal-contrast-weaker);
265
+ }
266
+ .module-meta {
267
+ display: flex;
268
+ justify-content: space-between;
269
+ gap: 8px;
270
+ }
271
+ .module-detail {
272
+ flex: 1 1 auto;
273
+ min-width: 0;
274
+ margin-left: 12px;
275
+ overflow-y: auto;
276
+ }
277
+ .surface {
278
+ padding: 12px;
279
+ border: 1px solid var(--color-normal-border);
280
+ border-radius: 6px;
281
+ background: var(--color-normal-fill-emphasis);
282
+ }
283
+ .hidden {
284
+ display: none;
285
+ }
286
+ .section-head {
287
+ display: flex;
288
+ justify-content: space-between;
289
+ align-items: flex-start;
290
+ gap: 12px;
291
+ margin-bottom: 12px;
292
+ }
293
+ .form-row {
294
+ display: flex;
295
+ flex-direction: column;
296
+ gap: 6px;
297
+ margin-bottom: 10px;
298
+ }
299
+ .form-row label,
300
+ .check-row {
301
+ font-size: 12px;
302
+ color: var(--color-normal-contrast-weaker);
303
+ }
304
+ .check-row {
305
+ display: flex;
306
+ align-items: center;
307
+ gap: 8px;
308
+ margin: 8px 0 12px;
309
+ }
310
+ .form-grid {
311
+ display: grid;
312
+ grid-template-columns: 1fr 140px;
313
+ gap: 10px;
314
+ align-items: end;
315
+ }
316
+ .order-editor {
317
+ display: grid;
318
+ grid-template-columns: minmax(120px, 180px) auto;
319
+ gap: 10px;
320
+ align-items: end;
321
+ margin-bottom: 12px;
322
+ }
323
+ select {
324
+ height: 24px;
325
+ color: var(--color-normal-contrast);
326
+ background: var(--color-normal-fill);
327
+ border: 1px solid var(--color-normal-border);
328
+ border-radius: 4px;
329
+ }
330
+ #status {
331
+ min-height: 18px;
332
+ margin-top: 8px;
333
+ font-size: 12px;
334
+ }
335
+ #managerStatus {
336
+ min-height: 18px;
337
+ margin-top: 8px;
338
+ font-size: 12px;
339
+ color: var(--color-normal-contrast-weaker);
340
+ }
341
+ .manager-card {
342
+ max-width: 520px;
343
+ }
344
+ .file-list,
345
+ .view-list {
346
+ display: grid;
347
+ gap: 8px;
348
+ }
349
+ .file-pill,
350
+ .view-pill {
351
+ padding: 8px;
352
+ border: 1px solid var(--color-normal-border);
353
+ border-radius: 6px;
354
+ background: var(--color-normal-fill);
355
+ }
356
+ .view-row {
357
+ display: flex;
358
+ justify-content: space-between;
359
+ align-items: center;
360
+ gap: 10px;
361
+ }
362
+ .view-row .muted {
363
+ display: inline-block;
364
+ max-width: 360px;
365
+ overflow: hidden;
366
+ text-overflow: ellipsis;
367
+ white-space: nowrap;
368
+ }
369
+ .subhead {
370
+ margin: 16px 0 8px;
371
+ }
372
+ .add-view {
373
+ margin-top: 16px;
374
+ padding-top: 12px;
375
+ border-top: 1px solid var(--color-normal-border);
376
+ }
377
+ #modules {
378
+ display: block;
379
+ min-height: 0;
380
+ }
381
+ .module {
382
+ border: 1px solid var(--color-normal-border);
383
+ border-radius: 6px;
384
+ padding: 10px;
385
+ margin-top: 8px;
386
+ background: var(--color-normal-fill);
387
+ }
388
+ .module-title {
389
+ display: flex;
390
+ justify-content: space-between;
391
+ gap: 8px;
392
+ align-items: center;
393
+ margin-bottom: 8px;
394
+ }
395
+ .module-title span {
396
+ font-size: 12px;
397
+ color: var(--color-normal-contrast-weaker);
398
+ }
399
+ .module p {
400
+ margin-bottom: 10px;
401
+ line-height: 1.4;
402
+ }
403
+ .module-actions,
404
+ .lib-meta {
405
+ display: flex;
406
+ align-items: center;
407
+ flex-wrap: wrap;
408
+ gap: 8px;
409
+ }
410
+ .lib-settings {
411
+ display: grid;
412
+ grid-template-columns: minmax(100px, 1fr) 90px auto;
413
+ gap: 8px;
414
+ align-items: center;
415
+ margin-bottom: 10px;
416
+ }
417
+ .lib-settings label {
418
+ display: flex;
419
+ align-items: center;
420
+ gap: 6px;
421
+ }
422
+ .lib-meta {
423
+ margin-bottom: 10px;
424
+ color: var(--color-normal-contrast-weaker);
425
+ font-size: 12px;
426
+ }
427
+ .empty {
428
+ margin-top: 8px;
429
+ color: var(--color-normal-contrast-weaker);
430
+ }
431
+ .diagnostic {
432
+ padding: 10px;
433
+ margin-top: 8px;
434
+ border: 1px solid var(--color-normal-border);
435
+ border-radius: 6px;
436
+ background: var(--color-normal-fill);
437
+ }
438
+ .diagnostic strong {
439
+ display: block;
440
+ margin-bottom: 4px;
441
+ }
442
+ .diagnostic.error {
443
+ border-color: var(--color-danger-fill);
444
+ }
445
+ .diagnostic.warn {
446
+ border-color: var(--color-warn-fill);
447
+ }
448
+ .diagnostic.info {
449
+ border-color: var(--color-success-fill);
450
+ }
451
+ `;
452
+ exports.$ = {
453
+ refresh: '#refresh',
454
+ moduleTab: '#moduleTab',
455
+ managerTab: '#managerTab',
456
+ librariesTab: '#librariesTab',
457
+ diagnosticsTab: '#diagnosticsTab',
458
+ modulePage: '#modulePage',
459
+ managerPage: '#managerPage',
460
+ librariesPage: '#librariesPage',
461
+ diagnosticsPage: '#diagnosticsPage',
462
+ newModule: '#newModule',
463
+ createModulePanel: '#createModulePanel',
464
+ moduleInfoPanel: '#moduleInfoPanel',
465
+ projectModules: '#projectModules',
466
+ selectedTitle: '#selectedTitle',
467
+ selectedPath: '#selectedPath',
468
+ moduleFiles: '#moduleFiles',
469
+ moduleViews: '#moduleViews',
470
+ create: '#create',
471
+ moduleName: '#moduleName',
472
+ moduleOrder: '#moduleOrder',
473
+ withView: '#withView',
474
+ status: '#status',
475
+ selectedOrder: '#selectedOrder',
476
+ saveOrder: '#saveOrder',
477
+ viewName: '#viewName',
478
+ viewLayer: '#viewLayer',
479
+ viewCache: '#viewCache',
480
+ addView: '#addView',
481
+ managerName: '#managerName',
482
+ createManager: '#createManager',
483
+ managerStatus: '#managerStatus',
484
+ modules: '#modules',
485
+ runDiagnostics: '#runDiagnostics',
486
+ diagnostics: '#diagnostics',
487
+ };
488
+ function ready() {
489
+ this.projectModules = [];
490
+ this.selectedModuleName = null;
491
+ this.$.refresh.addEventListener('confirm', async () => {
492
+ if (this.$.librariesPage.classList.contains('active')) {
493
+ await this.renderModules();
494
+ return;
495
+ }
496
+ await this.renderProjectModules();
497
+ });
498
+ this.$.moduleTab.addEventListener('confirm', async () => {
499
+ this.showTab('module');
500
+ await this.renderProjectModules();
501
+ });
502
+ this.$.librariesTab.addEventListener('confirm', async () => {
503
+ this.showTab('libraries');
504
+ await this.renderModules();
505
+ });
506
+ this.$.diagnosticsTab.addEventListener('confirm', async () => {
507
+ this.showTab('diagnostics');
508
+ await this.renderDiagnostics();
509
+ });
510
+ this.$.runDiagnostics.addEventListener('confirm', async () => {
511
+ await this.renderDiagnostics();
512
+ });
513
+ this.$.managerTab.addEventListener('confirm', () => {
514
+ this.showTab('manager');
515
+ });
516
+ this.$.newModule.addEventListener('confirm', () => {
517
+ this.selectedModuleName = null;
518
+ this.renderModuleDetail(null);
519
+ });
520
+ this.$.create.addEventListener('confirm', async () => {
521
+ const name = this.$.moduleName.value || 'NewModule';
522
+ const order = Number(this.$.moduleOrder.value || 100);
523
+ this.$.status.innerText = 'Creating module...';
524
+ try {
525
+ const result = (await Editor.Message.request(PACKAGE_NAME, 'create-module', {
526
+ name,
527
+ order,
528
+ withView: Boolean(this.$.withView.checked),
529
+ }));
530
+ this.$.status.innerText = `Created ${result.moduleName}.`;
531
+ this.$.moduleName.value = '';
532
+ this.$.moduleOrder.value = '100';
533
+ this.$.withView.checked = false;
534
+ await this.renderProjectModules();
535
+ }
536
+ catch (error) {
537
+ this.$.status.innerText = error instanceof Error ? error.message : String(error);
538
+ }
539
+ });
540
+ this.$.saveOrder.addEventListener('confirm', async () => {
541
+ if (!this.selectedModuleName)
542
+ return;
543
+ const order = Number(this.$.selectedOrder.value || 100);
544
+ try {
545
+ await Editor.Message.request(PACKAGE_NAME, 'update-module-order', {
546
+ moduleName: this.selectedModuleName,
547
+ order,
548
+ });
549
+ this.$.status.innerText = `Updated ${this.selectedModuleName} order to ${order}.`;
550
+ await this.renderProjectModules();
551
+ }
552
+ catch (error) {
553
+ this.$.status.innerText = error instanceof Error ? error.message : String(error);
554
+ }
555
+ });
556
+ this.$.addView.addEventListener('confirm', async () => {
557
+ if (!this.selectedModuleName)
558
+ return;
559
+ const viewName = this.$.viewName.value || 'Panel';
560
+ try {
561
+ await Editor.Message.request(PACKAGE_NAME, 'create-view', {
562
+ moduleName: this.selectedModuleName,
563
+ viewName,
564
+ layer: this.$.viewLayer.value || 'UI',
565
+ cache: Boolean(this.$.viewCache.checked),
566
+ });
567
+ this.$.viewName.value = '';
568
+ await this.renderProjectModules();
569
+ }
570
+ catch (error) {
571
+ this.$.status.innerText = error instanceof Error ? error.message : String(error);
572
+ }
573
+ });
574
+ this.$.createManager.addEventListener('confirm', async () => {
575
+ const name = this.$.managerName.value || 'NewManager';
576
+ this.$.managerStatus.innerText = 'Creating manager...';
577
+ try {
578
+ const result = (await Editor.Message.request(PACKAGE_NAME, 'create-manager', { name }));
579
+ this.$.managerStatus.innerText = `Created ${result.moduleName}.`;
580
+ this.$.managerName.value = '';
581
+ }
582
+ catch (error) {
583
+ this.$.managerStatus.innerText = error instanceof Error ? error.message : String(error);
584
+ }
585
+ });
586
+ this.showTab('module');
587
+ void this.renderProjectModules();
588
+ }
589
+ exports.methods = {
590
+ showTab(tab) {
591
+ const showModule = tab === 'module';
592
+ const showManager = tab === 'manager';
593
+ this.$.moduleTab.classList.toggle('active', showModule);
594
+ this.$.managerTab.classList.toggle('active', showManager);
595
+ this.$.librariesTab.classList.toggle('active', tab === 'libraries');
596
+ this.$.diagnosticsTab.classList.toggle('active', tab === 'diagnostics');
597
+ this.$.modulePage.classList.toggle('active', showModule);
598
+ this.$.managerPage.classList.toggle('active', showManager);
599
+ this.$.librariesPage.classList.toggle('active', tab === 'libraries');
600
+ this.$.diagnosticsPage.classList.toggle('active', tab === 'diagnostics');
601
+ },
602
+ async renderProjectModules() {
603
+ this.projectModules = (await Editor.Message.request(PACKAGE_NAME, 'list-project-modules'));
604
+ if (this.projectModules.length === 0) {
605
+ this.$.projectModules.innerHTML = '<p class="empty">No modules yet.</p>';
606
+ this.renderModuleDetail(null);
607
+ return;
608
+ }
609
+ this.$.projectModules.innerHTML = this.projectModules
610
+ .map((module) => `
611
+ <button class="module-item ${module.name === this.selectedModuleName ? 'active' : ''}" data-module="${module.name}">
612
+ <strong>${module.className}</strong>
613
+ <span class="module-meta">
614
+ <span>Order ${module.order}</span>
615
+ <span>${module.views.length > 0 ? `${module.views.length} Views` : 'Logic Module'}</span>
616
+ </span>
617
+ </button>
618
+ `)
619
+ .join('');
620
+ this.$.projectModules.querySelectorAll('.module-item').forEach((button) => {
621
+ button.addEventListener('click', () => {
622
+ this.selectedModuleName = button.getAttribute('data-module');
623
+ this.renderModuleDetail(this.projectModules.find((item) => item.name === this.selectedModuleName) ?? null);
624
+ });
625
+ });
626
+ const selected = this.projectModules.find((item) => item.name === this.selectedModuleName) ?? this.projectModules[0];
627
+ this.selectedModuleName = selected.name;
628
+ this.renderModuleDetail(selected);
629
+ },
630
+ renderModuleDetail(module) {
631
+ this.$.createModulePanel.classList.toggle('hidden', Boolean(module));
632
+ this.$.moduleInfoPanel.classList.toggle('hidden', !module);
633
+ if (!module)
634
+ return;
635
+ this.$.selectedTitle.innerText = `${module.className} Module`;
636
+ this.$.selectedPath.innerText = module.displayPath;
637
+ this.$.selectedPath.setAttribute('title', module.folderPath);
638
+ this.$.selectedOrder.value = String(module.order);
639
+ this.$.moduleFiles.innerHTML = module.displayFiles
640
+ .map((file) => `<div class="file-pill" title="${this.escapeHtml(file)}">${this.escapeHtml(file)}</div>`)
641
+ .join('');
642
+ this.$.moduleViews.innerHTML =
643
+ module.views.length > 0
644
+ ? module.views
645
+ .map((view) => `
646
+ <div class="view-pill">
647
+ <div class="view-row">
648
+ <div>
649
+ <strong>${view.className}</strong><br>
650
+ <span class="muted" title="${this.escapeHtml(view.scriptPath)}">${this.escapeHtml(view.displayPath)}</span>
651
+ </div>
652
+ <ui-button class="delete-view" data-view="${view.className}">Delete</ui-button>
653
+ </div>
654
+ </div>
655
+ `)
656
+ .join('')
657
+ : '<p class="empty">No views. Add one when this module needs presentation.</p>';
658
+ this.$.moduleViews.querySelectorAll('.delete-view').forEach((button) => {
659
+ button.addEventListener('confirm', async () => {
660
+ const className = button.getAttribute('data-view');
661
+ if (!className || !this.selectedModuleName)
662
+ return;
663
+ await Editor.Message.request(PACKAGE_NAME, 'delete-view', {
664
+ moduleName: this.selectedModuleName,
665
+ className,
666
+ });
667
+ await this.renderProjectModules();
668
+ });
669
+ });
670
+ },
671
+ escapeHtml(text) {
672
+ return text.replace(/[&<>"']/g, (char) => {
673
+ const map = {
674
+ '&': '&amp;',
675
+ '<': '&lt;',
676
+ '>': '&gt;',
677
+ '"': '&quot;',
678
+ "'": '&#39;',
679
+ };
680
+ return map[char] ?? char;
681
+ });
682
+ },
683
+ async renderDiagnostics() {
684
+ const issues = (await Editor.Message.request(PACKAGE_NAME, 'diagnose-project'));
685
+ this.$.diagnostics.innerHTML = issues
686
+ .map((issue) => `
687
+ <div class="diagnostic ${issue.level}">
688
+ <strong>${issue.level.toUpperCase()} · ${this.escapeHtml(issue.code)}</strong>
689
+ <p>${this.escapeHtml(issue.message)}</p>
690
+ ${issue.target ? `<p class="muted" title="${this.escapeHtml(issue.target)}">${this.escapeHtml(issue.target)}</p>` : ''}
691
+ </div>
692
+ `)
693
+ .join('');
694
+ },
695
+ async renderModules() {
696
+ const modules = (await Editor.Message.request(PACKAGE_NAME, 'list-modules'));
697
+ if (modules.length === 0) {
698
+ this.$.modules.innerHTML = '<p class="empty">No optional libraries configured.</p>';
699
+ return;
700
+ }
701
+ this.$.modules.innerHTML = modules
702
+ .map((module) => `
703
+ <div class="module">
704
+ <div class="module-title">
705
+ <strong>${module.displayName}</strong>
706
+ <span>${module.installed ? module.installedVersion : 'Not installed'}</span>
707
+ </div>
708
+ <p>${module.description}</p>
709
+ <div class="lib-meta">
710
+ <span>Init: ${module.initMode}</span>
711
+ <span>Order: ${module.order}</span>
712
+ <span>${module.enabled ? 'Enabled' : 'Disabled'}</span>
713
+ </div>
714
+ ${module.installed
715
+ ? `<div class="lib-settings">
716
+ <label>
717
+ <ui-checkbox class="lib-enabled" data-id="${module.id}" ${module.enabled ? 'checked' : ''}></ui-checkbox>
718
+ Enabled
719
+ </label>
720
+ <ui-num-input class="lib-order" data-id="${module.id}" value="${module.order}"></ui-num-input>
721
+ <ui-button class="save-lib-state" data-id="${module.id}">Save</ui-button>
722
+ </div>`
723
+ : ''}
724
+ <div class="module-actions">
725
+ <ui-button class="install" data-package="${module.installPackage || module.npmPackage}">
726
+ ${module.installed ? (module.updateAvailable ? 'Update' : 'Reinstall') : 'Install'}
727
+ </ui-button>
728
+ ${module.installed
729
+ ? `<ui-button class="uninstall" data-package="${module.npmPackage}">Uninstall</ui-button>`
730
+ : ''}
731
+ </div>
732
+ </div>
733
+ `)
734
+ .join('');
735
+ this.$.modules.querySelectorAll('.install').forEach((button) => {
736
+ button.addEventListener('confirm', async () => {
737
+ const npmPackage = button.getAttribute('data-package');
738
+ if (!npmPackage)
739
+ return;
740
+ await Editor.Message.request(PACKAGE_NAME, 'install-module', npmPackage);
741
+ await this.renderModules();
742
+ });
743
+ });
744
+ this.$.modules.querySelectorAll('.uninstall').forEach((button) => {
745
+ button.addEventListener('confirm', async () => {
746
+ const npmPackage = button.getAttribute('data-package');
747
+ if (!npmPackage)
748
+ return;
749
+ await Editor.Message.request(PACKAGE_NAME, 'uninstall-module', npmPackage);
750
+ await this.renderModules();
751
+ });
752
+ });
753
+ this.$.modules.querySelectorAll('.save-lib-state').forEach((button) => {
754
+ button.addEventListener('confirm', async () => {
755
+ const id = button.getAttribute('data-id');
756
+ if (!id)
757
+ return;
758
+ const enabled = this.$.modules.querySelector(`.lib-enabled[data-id="${id}"]`);
759
+ const order = this.$.modules.querySelector(`.lib-order[data-id="${id}"]`);
760
+ await Editor.Message.request(PACKAGE_NAME, 'update-library-state', {
761
+ id,
762
+ enabled: Boolean(enabled?.checked),
763
+ order: Number(order?.value || 100),
764
+ });
765
+ await this.renderModules();
766
+ });
767
+ });
768
+ },
769
+ };
770
+ //# sourceMappingURL=index.js.map