@eclipse-lyra/extension-settings-tree 0.7.57 → 0.7.59

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,829 +0,0 @@
1
- import { css, html } from "lit";
2
- import { LyraPart, subscribe, TOPIC_SETTINGS_CHANGED, appSettings, promptDialog, editorRegistry, commandRegistry, contributionRegistry, TOOLBAR_MAIN_RIGHT } from "@eclipse-lyra/core";
3
- import { property, state, customElement } from "lit/decorators.js";
4
- import { createRef, ref } from "lit/directives/ref.js";
5
- import { repeat } from "lit/directives/repeat.js";
6
- var __defProp = Object.defineProperty;
7
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
- var __decorateClass = (decorators, target, key, kind) => {
9
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
10
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
11
- if (decorator = decorators[i])
12
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
13
- if (kind && result) __defProp(target, key, result);
14
- return result;
15
- };
16
- let LyraSettingsTree = class extends LyraPart {
17
- constructor() {
18
- super(...arguments);
19
- this.settings = {};
20
- this.categoryTree = [];
21
- this.selectedPath = null;
22
- this.detailRows = [];
23
- this.detailTitle = "";
24
- this.searchQuery = "";
25
- this.detailForPath = null;
26
- this.treeRef = createRef();
27
- }
28
- async doInitUI() {
29
- await this.loadSettings();
30
- subscribe(TOPIC_SETTINGS_CHANGED, () => this.loadSettings());
31
- }
32
- async loadSettings() {
33
- if (this.isDirty()) return;
34
- this.settings = await appSettings.getAll() ?? {};
35
- this.buildCategoryTree();
36
- if (this.selectedPath) {
37
- this.updateDetailForPath(this.selectedPath);
38
- }
39
- }
40
- buildCategoryTree() {
41
- const categories = appSettings.getCategories();
42
- const schemaIds = new Set(categories.map((c) => c.id));
43
- const nodes = [];
44
- for (const cat of categories) {
45
- const childSchema = cat.schema?.properties;
46
- const value = this.settings[cat.id];
47
- const children = this.buildChildNodes(`${cat.id}`, childSchema, value);
48
- const label = cat.schema?.title ?? cat.label;
49
- if (this.matchesSearch(label, cat.id)) {
50
- nodes.push({
51
- path: cat.id,
52
- label,
53
- children,
54
- expanded: true
55
- });
56
- }
57
- }
58
- for (const key of Object.keys(this.settings)) {
59
- if (schemaIds.has(key)) continue;
60
- const value = this.settings[key];
61
- const children = this.buildChildNodes(key, void 0, value);
62
- if (this.matchesSearch(key, key)) {
63
- nodes.push({
64
- path: key,
65
- label: key,
66
- children,
67
- expanded: true
68
- });
69
- }
70
- }
71
- this.categoryTree = nodes;
72
- }
73
- buildChildNodes(parentPath, schemaProps, value) {
74
- const children = [];
75
- if (schemaProps) {
76
- for (const [k, s] of Object.entries(schemaProps)) {
77
- const path = `${parentPath}.${k}`;
78
- const label = s?.title ?? k;
79
- const subValue = LyraSettingsTree.isRecord(value) ? value[k] : void 0;
80
- const subChildren = this.buildChildNodes(path, s?.properties, subValue);
81
- if (this.matchesSearch(label, path)) {
82
- children.push({ path, label, children: subChildren, expanded: false });
83
- }
84
- }
85
- }
86
- if (LyraSettingsTree.isRecord(value) && !schemaProps) {
87
- for (const [k, v] of Object.entries(value)) {
88
- const path = `${parentPath}.${k}`;
89
- const subChildren = this.buildChildNodes(path, void 0, v);
90
- if (this.matchesSearch(k, path)) {
91
- children.push({ path, label: k, children: subChildren, expanded: false });
92
- }
93
- }
94
- }
95
- return children;
96
- }
97
- matchesSearch(label, path) {
98
- if (!this.searchQuery.trim()) return true;
99
- const q = this.searchQuery.toLowerCase();
100
- return label.toLowerCase().includes(q) || path.toLowerCase().includes(q);
101
- }
102
- static isRecord(v) {
103
- return v !== null && typeof v === "object" && !Array.isArray(v);
104
- }
105
- refreshAfterEdit() {
106
- this.markDirty(true);
107
- if (this.selectedPath) this.updateDetailForPath(this.selectedPath);
108
- }
109
- getValueAtPath(path) {
110
- const parts = path.split(".").filter(Boolean);
111
- if (parts.length === 0) return this.settings;
112
- let current = this.settings;
113
- for (const part of parts) {
114
- if (current === null || current === void 0 || typeof current !== "object") return void 0;
115
- current = current[part];
116
- }
117
- return current;
118
- }
119
- setAtInMemory(path, value) {
120
- const parts = path.split(".").filter(Boolean);
121
- if (parts.length === 0) return;
122
- this.settings = this.deepSet(this.settings, parts, value);
123
- }
124
- deepSet(obj, pathParts, value) {
125
- if (pathParts.length === 1) {
126
- const key = pathParts[0];
127
- if (Array.isArray(obj)) {
128
- const idx = parseInt(key, 10);
129
- if (isNaN(idx) || idx < 0) return obj;
130
- const arr = [...obj];
131
- arr[idx] = value;
132
- return arr;
133
- }
134
- return { ...obj, [key]: value };
135
- }
136
- const [head, ...rest] = pathParts;
137
- if (Array.isArray(obj)) {
138
- const idx = parseInt(head, 10);
139
- if (isNaN(idx) || idx < 0) return obj;
140
- const arr = [...obj];
141
- const current2 = arr[idx];
142
- const next2 = current2 !== null && typeof current2 === "object" ? current2 : {};
143
- arr[idx] = this.deepSet(next2, rest, value);
144
- return arr;
145
- }
146
- const o = obj;
147
- const current = o[head];
148
- const next = current !== null && typeof current === "object" ? current : {};
149
- return { ...o, [head]: this.deepSet(next, rest, value) };
150
- }
151
- getArrayItemLabel(item, index) {
152
- if (LyraSettingsTree.isRecord(item)) {
153
- if (typeof item.id === "string") return item.id;
154
- if (typeof item.name === "string") return item.name;
155
- }
156
- return `Item ${index}`;
157
- }
158
- async updateDetailForPath(path) {
159
- const containerSchema = appSettings.getSchemaForSettingKey(path);
160
- const containerValue = this.getValueAtPath(path);
161
- const valueObj = LyraSettingsTree.isRecord(containerValue) ? containerValue : null;
162
- const isArray = Array.isArray(containerValue);
163
- let rows;
164
- if (isArray) {
165
- const arr = containerValue;
166
- const flat = [];
167
- arr.forEach((item, index) => {
168
- const subPath = `${path}.${index}`;
169
- const groupLabel = this.getArrayItemLabel(item, index);
170
- if (LyraSettingsTree.isRecord(item)) {
171
- Object.keys(item).forEach((k) => {
172
- flat.push({
173
- key: k,
174
- path: `${subPath}.${k}`,
175
- title: k,
176
- description: "",
177
- schema: void 0,
178
- value: item[k],
179
- parentPath: subPath,
180
- groupLabel
181
- });
182
- });
183
- } else {
184
- flat.push({
185
- key: String(index),
186
- path: subPath,
187
- title: groupLabel,
188
- description: `Array element ${index}.`,
189
- schema: void 0,
190
- value: item,
191
- parentPath: path,
192
- groupLabel
193
- });
194
- }
195
- });
196
- rows = flat;
197
- } else if (valueObj !== null) {
198
- const schemaProps = containerSchema?.properties;
199
- const keys = schemaProps ? Object.keys(schemaProps) : Object.keys(valueObj);
200
- rows = keys.map((key) => {
201
- const subPath = `${path}.${key}`;
202
- const propSchema = schemaProps?.[key];
203
- const value = valueObj[key];
204
- return {
205
- key,
206
- path: subPath,
207
- title: propSchema?.title ?? key,
208
- description: propSchema?.description ?? "",
209
- schema: propSchema,
210
- value,
211
- parentPath: path
212
- };
213
- });
214
- } else if (containerValue !== void 0 && containerValue !== null && typeof containerValue !== "object") {
215
- const segment = path.split(".").pop() ?? path;
216
- rows = [{
217
- key: segment,
218
- path,
219
- title: segment,
220
- description: "Edit value (no schema).",
221
- schema: void 0,
222
- value: containerValue
223
- }];
224
- } else {
225
- rows = [];
226
- }
227
- rows.forEach((r) => {
228
- if (r.title === void 0) r.title = r.key;
229
- });
230
- if (this.selectedPath !== path) return;
231
- const category = appSettings.getCategories().find((c) => c.id === path);
232
- this.detailForPath = path;
233
- this.detailTitle = category?.label ?? containerSchema?.title ?? path;
234
- this.detailRows = rows;
235
- }
236
- selectPath(path) {
237
- this.selectedPath = path;
238
- this.updateDetailForPath(path);
239
- }
240
- updated(changedProperties) {
241
- super.updated?.(changedProperties);
242
- if (changedProperties.has("selectedPath") && this.selectedPath !== this.detailForPath) {
243
- if (this.selectedPath) this.updateDetailForPath(this.selectedPath);
244
- else {
245
- this.detailForPath = null;
246
- this.detailRows = [];
247
- this.detailTitle = "";
248
- }
249
- }
250
- }
251
- setRowValue(row, value) {
252
- this.setAtInMemory(row.path, value);
253
- this.refreshAfterEdit();
254
- }
255
- setRowValueFromJson(row, raw) {
256
- try {
257
- this.setRowValue(row, JSON.parse(raw));
258
- } catch {
259
- this.refreshAfterEdit();
260
- }
261
- }
262
- renameKey(parentPath, oldKey, newKey) {
263
- if (newKey.trim() === "" || newKey === oldKey) return;
264
- const parent = this.getValueAtPath(parentPath);
265
- if (!LyraSettingsTree.isRecord(parent)) return;
266
- const value = parent[oldKey];
267
- const updated = { ...parent };
268
- delete updated[oldKey];
269
- updated[newKey.trim()] = value;
270
- this.setAtInMemory(parentPath, updated);
271
- this.refreshAfterEdit();
272
- }
273
- deleteKey(parentPath, key) {
274
- const parent = this.getValueAtPath(parentPath);
275
- if (!LyraSettingsTree.isRecord(parent)) return;
276
- const updated = { ...parent };
277
- delete updated[key];
278
- this.setAtInMemory(parentPath, updated);
279
- this.refreshAfterEdit();
280
- }
281
- async addKeyToGroup(groupParentPath) {
282
- const key = await promptDialog("New key name:", "");
283
- if (!key?.trim()) return;
284
- this.setAtInMemory(`${groupParentPath}.${key.trim()}`, null);
285
- this.refreshAfterEdit();
286
- }
287
- deleteTopLevelKey(key) {
288
- if (!(key in this.settings)) return;
289
- const updated = { ...this.settings };
290
- delete updated[key];
291
- this.settings = updated;
292
- this.markDirty(true);
293
- if (this.selectedPath === key) {
294
- this.selectedPath = null;
295
- this.detailForPath = null;
296
- this.detailRows = [];
297
- this.detailTitle = "";
298
- }
299
- this.buildCategoryTree();
300
- if (this.selectedPath) this.updateDetailForPath(this.selectedPath);
301
- }
302
- renderDetailControl(row) {
303
- const schema = row.schema;
304
- const type = schema?.type;
305
- const enumValues = schema?.enum;
306
- const current = row.value;
307
- if (enumValues && Array.isArray(enumValues) && enumValues.length > 0) {
308
- const options = enumValues.map((v) => String(v));
309
- const value = current !== void 0 && current !== null ? String(current) : schema?.default !== void 0 ? String(schema.default) : options[0];
310
- return html`
311
- <wa-select
312
- value=${value}
313
- @change=${(e) => this.setRowValue(row, e.target.value)}
314
- size="small">
315
- ${options.map((opt) => html`<wa-option value=${opt}>${opt}</wa-option>`)}
316
- </wa-select>
317
- `;
318
- }
319
- if (type === "boolean") {
320
- const checked = current === true || current === void 0 && schema?.default === true;
321
- return html`
322
- <wa-switch
323
- ?checked=${checked}
324
- @change=${(e) => this.setRowValue(row, e.target.checked)}
325
- size="small">
326
- </wa-switch>
327
- `;
328
- }
329
- if (type === "number") {
330
- const num = typeof current === "number" ? current : typeof schema?.default === "number" ? schema.default : 0;
331
- return html`
332
- <wa-number-input
333
- .value=${String(num)}
334
- @change=${(e) => this.setRowValue(row, Number(e.target.value))}
335
- size="small">
336
- </wa-number-input>
337
- `;
338
- }
339
- const isObjectOrArray = current !== null && typeof current === "object";
340
- if (isObjectOrArray && !schema && LyraSettingsTree.isRecord(current)) {
341
- return this.renderObjectFields(row.path, current, 0);
342
- }
343
- if (isObjectOrArray) {
344
- const str = JSON.stringify(current, null, 2);
345
- return html`
346
- <wa-textarea
347
- .value=${str}
348
- @blur=${(e) => this.setRowValueFromJson(row, e.target.value)}
349
- rows="3">
350
- </wa-textarea>
351
- `;
352
- }
353
- return this.renderPrimitiveControl(row, current);
354
- }
355
- renderPrimitiveControl(row, current) {
356
- const str = current !== void 0 && current !== null ? String(current) : "";
357
- if (typeof current === "boolean") {
358
- return html`
359
- <wa-switch
360
- ?checked=${current}
361
- @change=${(e) => this.setRowValue(row, e.target.checked)}
362
- size="small">
363
- </wa-switch>
364
- `;
365
- }
366
- if (typeof current === "number") {
367
- return html`
368
- <wa-number-input
369
- .value=${String(current)}
370
- @change=${(e) => this.setRowValue(row, Number(e.target.value))}
371
- size="small">
372
- </wa-number-input>
373
- `;
374
- }
375
- return html`
376
- <wa-input
377
- .value=${str}
378
- @input=${(e) => this.setRowValue(row, e.target.value)}
379
- size="small">
380
- </wa-input>
381
- `;
382
- }
383
- renderObjectFields(parentPath, obj, depth) {
384
- const maxDepth = 2;
385
- if (depth >= maxDepth) {
386
- const str = JSON.stringify(obj, null, 2);
387
- const row = { key: "", path: parentPath, title: "", description: "", value: obj };
388
- return html`
389
- <wa-textarea
390
- .value=${str}
391
- @blur=${(e) => this.setRowValueFromJson(row, e.target.value)}
392
- rows="3">
393
- </wa-textarea>
394
- `;
395
- }
396
- const entries = Object.entries(obj);
397
- return html`
398
- <div class="nested-object" >
399
- ${entries.map(([k, v]) => {
400
- const subPath = `${parentPath}.${k}`;
401
- const subRow = { key: k, path: subPath, title: k, description: "", value: v, parentPath };
402
- const isNestedObj = LyraSettingsTree.isRecord(v);
403
- const isArray = Array.isArray(v);
404
- return html`
405
- <div class="nested-row">
406
- <wa-input
407
- .value=${k}
408
- size="small"
409
- style="width: 140px;"
410
- @blur=${(e) => {
411
- const newKey = e.target.value.trim();
412
- if (newKey && newKey !== k) this.renameKey(parentPath, k, newKey);
413
- }}>
414
- </wa-input>
415
- <span class="nested-sep">:</span>
416
- ${isNestedObj ? this.renderObjectFields(subPath, v, depth + 1) : isArray ? html`
417
- <wa-textarea
418
- .value=${JSON.stringify(v, null, 2)}
419
- rows="2"
420
- style="min-width: 200px;"
421
- @blur=${(e) => this.setRowValueFromJson(subRow, e.target.value)}>
422
- </wa-textarea>
423
- ` : this.renderPrimitiveControl(subRow, v)}
424
- </div>
425
- `;
426
- })}
427
- </div>
428
- `;
429
- }
430
- renderDetailPanel() {
431
- if (!this.selectedPath) {
432
- return html`
433
- <div class="detail-placeholder">
434
- <wa-icon name="gear"></wa-icon>
435
- <p>Select a category from the tree</p>
436
- </div>
437
- `;
438
- }
439
- if (this.detailForPath !== this.selectedPath) {
440
- return html`
441
- <div class="detail-panel">
442
- <div class="detail-heading-row">
443
- <h2 class="detail-heading">${this.selectedPath}</h2>
444
- </div>
445
- <div class="detail-placeholder">
446
- <p>Loading…</p>
447
- </div>
448
- </div>
449
- `;
450
- }
451
- const filteredRows = this.detailRows.filter((row) => {
452
- if (!this.searchQuery.trim()) return true;
453
- const q = this.searchQuery.toLowerCase();
454
- return row.title.toLowerCase().includes(q) || row.description.toLowerCase().includes(q);
455
- });
456
- const containerValue = this.selectedPath ? this.getValueAtPath(this.selectedPath) : void 0;
457
- const isObjectContainer = LyraSettingsTree.isRecord(containerValue);
458
- const isTopLevel = this.selectedPath !== null && !this.selectedPath.includes(".");
459
- const canAddToSelection = isObjectContainer || isTopLevel;
460
- return html`
461
- <div class="detail-panel">
462
- <div class="detail-heading-row">
463
- <h2 class="detail-heading">${this.detailTitle}</h2>
464
- ${canAddToSelection ? html`
465
- <lyra-command size="small" icon="plus" title="Add setting" .action=${() => this.addKeyToGroup(this.selectedPath)}>Add</lyra-command>
466
- ` : ""}
467
- ${isTopLevel ? html`
468
- <lyra-command size="small" icon="trash" title="Delete category" .action=${() => this.deleteTopLevelKey(this.selectedPath)}></lyra-command>
469
- ` : ""}
470
- </div>
471
- <wa-scroller class="detail-scroller" orientation="vertical">
472
- ${filteredRows.length === 0 ? html`
473
- <div class="detail-empty">
474
- ${this.detailRows.length === 0 ? html`<p>No settings in this category. Add keys in the JSON file or register a JSON Schema for this path.</p>` : html`<p>No matching settings for the current search.</p>`}
475
- </div>
476
- ` : repeat(
477
- filteredRows,
478
- (row) => row.path,
479
- (row, index) => {
480
- const prev = index > 0 ? filteredRows[index - 1] : null;
481
- const showGroup = row.groupLabel && prev?.groupLabel !== row.groupLabel;
482
- const inGroup = !!row.groupLabel;
483
- return html`
484
- ${showGroup ? html`
485
- <div class="detail-group-header">
486
- <span>${row.groupLabel}</span>
487
- <lyra-command size="small" icon="plus" title="Add setting" .action=${() => this.addKeyToGroup(row.parentPath)}>Add</lyra-command>
488
- </div>
489
- ` : ""}
490
- <div class="setting-row ${inGroup ? "setting-row-in-group" : ""}">
491
- <div class="setting-meta">
492
- ${row.parentPath != null ? html`
493
- <wa-input
494
- .value=${row.key}
495
- size="small"
496
- class="editable-key setting-control-key"
497
- @blur=${(e) => {
498
- const newKey = e.target.value.trim();
499
- if (newKey && newKey !== row.key) this.renameKey(row.parentPath, row.key, newKey);
500
- }}>
501
- </wa-input>
502
- ` : html`<span class="setting-title">${row.title}</span>`}
503
- ${row.description ? html`<p class="setting-description">${row.description}</p>` : ""}
504
- </div>
505
- <div class="setting-control">${this.renderDetailControl(row)}</div>
506
- ${row.parentPath != null ? html`
507
- <lyra-command size="small" icon="trash" title="Delete setting" .action=${() => this.deleteKey(row.parentPath, row.key)}></lyra-command>
508
- ` : ""}
509
- </div>
510
- `;
511
- }
512
- )}
513
- </wa-scroller>
514
- </div>
515
- `;
516
- }
517
- renderCategoryNode(node) {
518
- const hasChildren = node.children.length > 0;
519
- const isSelected = this.selectedPath === node.path;
520
- return html`
521
- <wa-tree-item ?expanded=${node.expanded}>
522
- <div
523
- class="tree-node-content ${isSelected ? "selected" : ""}"
524
- @click=${() => this.selectPath(node.path)}
525
- role="button"
526
- tabindex="0"
527
- @keydown=${(e) => e.key === "Enter" && this.selectPath(node.path)}>
528
- <span class="tree-node-label">${node.label}</span>
529
- </div>
530
- ${hasChildren ? node.children.map((child) => this.renderCategoryNode(child)) : ""}
531
- </wa-tree-item>
532
- `;
533
- }
534
- setAllExpanded(expanded) {
535
- const tree = this.treeRef.value;
536
- if (tree) {
537
- tree.querySelectorAll("wa-tree-item").forEach((item) => {
538
- item.expanded = expanded;
539
- });
540
- }
541
- this.categoryTree = this.categoryTree.map((n) => this.setExpanded(n, expanded));
542
- this.requestUpdate();
543
- }
544
- setExpanded(node, expanded) {
545
- return {
546
- ...node,
547
- expanded,
548
- children: node.children.map((c) => this.setExpanded(c, expanded))
549
- };
550
- }
551
- async addKey() {
552
- const key = await promptDialog("Enter new top-level key name:", "");
553
- if (!key?.trim()) return;
554
- this.setAtInMemory(key.trim(), null);
555
- this.markDirty(true);
556
- this.buildCategoryTree();
557
- }
558
- save() {
559
- appSettings.setAll(this.settings).then(() => {
560
- this.markDirty(false);
561
- }).catch((err) => {
562
- console.error("Failed to save settings:", err);
563
- });
564
- }
565
- renderToolbar() {
566
- return html`
567
- <wa-input
568
- placeholder="Search settings"
569
- .value=${this.searchQuery}
570
- @input=${(e) => {
571
- this.searchQuery = e.target.value;
572
- this.buildCategoryTree();
573
- }}
574
- size="small"
575
- class="toolbar-search">
576
- </wa-input>
577
- <lyra-command size="small" icon="plus" title="Add Key" .action=${() => this.addKey()}>Add Key</lyra-command>
578
- <lyra-command size="small" icon="chevron-down" title="Expand All" .action=${() => this.setAllExpanded(true)}>Expand All</lyra-command>
579
- <lyra-command size="small" icon="chevron-right" title="Collapse All" .action=${() => this.setAllExpanded(false)}>Collapse All</lyra-command>
580
- `;
581
- }
582
- renderContent() {
583
- return html`
584
- <div class="settings-editor-container">
585
- <wa-split-panel position="25" class="split-panel-fill">
586
- <div slot="start" class="left-panel">
587
- <wa-scroller class="tree-scroller" orientation="vertical">
588
- ${this.categoryTree.length === 0 ? html`
589
- <div class="empty-state">
590
- <wa-icon name="gear"></wa-icon>
591
- <p>No settings.</p>
592
- </div>
593
- ` : html`
594
- <wa-tree ${ref(this.treeRef)}>
595
- ${this.categoryTree.map((node) => this.renderCategoryNode(node))}
596
- </wa-tree>
597
- `}
598
- </wa-scroller>
599
- </div>
600
- <div slot="end" class="right-panel">
601
- ${this.renderDetailPanel()}
602
- </div>
603
- </wa-split-panel>
604
- </div>
605
- `;
606
- }
607
- };
608
- LyraSettingsTree.styles = css`
609
- :host {
610
- display: flex;
611
- flex-direction: column;
612
- height: 100%;
613
- }
614
-
615
- .settings-editor-container {
616
- flex: 1;
617
- min-height: 0;
618
- display: flex;
619
- flex-direction: column;
620
- }
621
-
622
- .left-panel, .right-panel {
623
- display: flex;
624
- flex-direction: column;
625
- min-height: 0;
626
- overflow: hidden;
627
- }
628
-
629
- .tree-scroller, .detail-scroller {
630
- flex: 1;
631
- min-height: 0;
632
- }
633
-
634
- .tree-node-content {
635
- cursor: pointer;
636
- user-select: none;
637
- }
638
-
639
- .tree-node-content.selected {
640
- font-weight: 600;
641
- }
642
-
643
- .detail-placeholder {
644
- display: flex;
645
- flex-direction: column;
646
- align-items: center;
647
- justify-content: center;
648
- height: 100%;
649
- text-align: center;
650
- padding: 32px;
651
- }
652
-
653
- .detail-panel {
654
- display: flex;
655
- flex-direction: column;
656
- height: 100%;
657
- overflow: hidden;
658
- }
659
-
660
- .detail-heading-row {
661
- display: flex;
662
- align-items: center;
663
- gap: 8px;
664
- margin-bottom: 16px;
665
- padding: 0 16px;
666
- }
667
-
668
- .detail-heading {
669
- margin: 0;
670
- flex: 1;
671
- }
672
-
673
- .detail-scroller {
674
- padding: 0 16px 16px;
675
- }
676
-
677
- .detail-empty {
678
- padding: 24px 0;
679
- }
680
-
681
- .detail-group-header {
682
- display: flex;
683
- align-items: center;
684
- gap: 8px;
685
- margin-top: 12px;
686
- margin-bottom: 4px;
687
- }
688
-
689
- .detail-group-header:first-child {
690
- margin-top: 0;
691
- }
692
-
693
- .nested-row {
694
- display: flex;
695
- align-items: center;
696
- gap: 8px;
697
- margin-bottom: 6px;
698
- }
699
-
700
- .setting-row {
701
- display: flex;
702
- flex-wrap: wrap;
703
- gap: 12px;
704
- align-items: flex-start;
705
- padding: 12px 0;
706
- }
707
-
708
- .setting-row-in-group {
709
- padding-left: 20px;
710
- }
711
-
712
- .setting-meta {
713
- flex: 0 0 auto;
714
- min-width: 140px;
715
- }
716
-
717
- .setting-title {
718
- font-weight: 600;
719
- display: block;
720
- margin-bottom: 4px;
721
- }
722
-
723
- .setting-control {
724
- flex: 1;
725
- min-width: 0;
726
- display: flex;
727
- }
728
-
729
- .setting-row command {
730
- flex-shrink: 0;
731
- }
732
-
733
- .setting-control wa-input,
734
- .setting-control wa-textarea,
735
- .setting-control wa-number-input,
736
- .setting-control wa-select {
737
- flex: 1;
738
- min-width: 0;
739
- width: 100%;
740
- }
741
-
742
- .setting-meta .setting-control-key {
743
- width: 160px;
744
- }
745
-
746
- .empty-state {
747
- display: flex;
748
- flex-direction: column;
749
- align-items: center;
750
- justify-content: center;
751
- padding: 32px;
752
- text-align: center;
753
- }
754
-
755
- .nested-object {
756
- margin-left: 8px;
757
- padding-left: 8px;
758
- border-left: 2px solid var(--wa-color-neutral-85);
759
- }
760
-
761
- .toolbar-search {
762
- width: 200px;
763
- margin-right: 8px;
764
- }
765
-
766
- .split-panel-fill {
767
- height: 100%;
768
- }
769
- `;
770
- __decorateClass([
771
- property({ attribute: false })
772
- ], LyraSettingsTree.prototype, "input", 2);
773
- __decorateClass([
774
- state()
775
- ], LyraSettingsTree.prototype, "settings", 2);
776
- __decorateClass([
777
- state()
778
- ], LyraSettingsTree.prototype, "categoryTree", 2);
779
- __decorateClass([
780
- state()
781
- ], LyraSettingsTree.prototype, "selectedPath", 2);
782
- __decorateClass([
783
- state()
784
- ], LyraSettingsTree.prototype, "detailRows", 2);
785
- __decorateClass([
786
- state()
787
- ], LyraSettingsTree.prototype, "detailTitle", 2);
788
- __decorateClass([
789
- state()
790
- ], LyraSettingsTree.prototype, "searchQuery", 2);
791
- LyraSettingsTree = __decorateClass([
792
- customElement("lyra-settings-tree")
793
- ], LyraSettingsTree);
794
- const settingsTreeExtension = (_uiContext) => {
795
- editorRegistry.registerEditorInputHandler({
796
- editorId: "system.settings-tree",
797
- label: "Settings",
798
- ranking: 1e3,
799
- canHandle: (input) => input.key === ".system.settings",
800
- handle: async (input) => {
801
- input.component = (id) => html`
802
- <lyra-settings-tree id="${id}" .input=${input}></lyra-settings-tree>
803
- `;
804
- return input;
805
- }
806
- });
807
- commandRegistry.registerHandler("open_settings", {
808
- ranking: 100,
809
- execute: () => {
810
- const editorInput = {
811
- title: "Settings",
812
- data: {},
813
- key: ".system.settings",
814
- icon: "gear",
815
- state: {}
816
- };
817
- editorRegistry.loadEditor(editorInput);
818
- }
819
- });
820
- contributionRegistry.registerContribution(TOOLBAR_MAIN_RIGHT, {
821
- command: "open_settings",
822
- icon: "gear",
823
- label: "Settings"
824
- });
825
- };
826
- export {
827
- settingsTreeExtension as default
828
- };
829
- //# sourceMappingURL=settings-tree-extension-qqh_Ohws.js.map