ultra_settings 2.7.0 → 2.8.1

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.
data/app/application.css CHANGED
@@ -2,22 +2,22 @@
2
2
  margin-bottom: 1rem;
3
3
  }
4
4
 
5
- .ultra-settings-nav form {
6
- margin: 0;
7
- }
8
-
9
- .ultra-settings-config-file {
5
+ .ultra-settings-description-container {
10
6
  margin-bottom: 1.5rem;
11
- padding: 1rem;
12
- background-color: var(--config-file-bg-color);
7
+ line-height: 1.5;
13
8
  border: 1px solid var(--config-file-border-color);
14
9
  border-radius: 0.375rem;
10
+ padding: 1rem 1rem 0 1rem;
11
+ }
12
+
13
+ .ultra-settings-description {
14
+ margin-bottom: 1rem;
15
+ color: var(--description-color);
15
16
  }
16
17
 
17
18
  .ultra-settings-config-file-label {
18
- font-weight: 600;
19
- color: var(--text-color);
20
- margin-right: 0.5rem;
19
+ font-weight: 500;
20
+ color: var(--description-color);
21
21
  }
22
22
 
23
23
  .ultra-settings-config-file-path {
@@ -132,6 +132,10 @@ code.ultra-settings-field-data-value {
132
132
  gap: 0.5rem;
133
133
  }
134
134
 
135
+ .ultra-settings-field-description svg {
136
+ margin-top: 0.125rem;
137
+ }
138
+
135
139
  .ultra-settings-description-text {
136
140
  flex: 1;
137
141
  }
@@ -166,13 +170,19 @@ code.ultra-settings-field-data-value {
166
170
  min-width: 120px;
167
171
  }
168
172
 
173
+ .ultra-settings-source-value-container {
174
+ display: flex;
175
+ align-items: center;
176
+ gap: 0.5rem;
177
+ flex: 1;
178
+ margin: 0 0.75rem;
179
+ }
180
+
169
181
  .ultra-settings-source-value {
170
182
  font-family: monospace;
171
183
  font-size: 0.875rem;
172
184
  color: var(--source-value-color);
173
185
  font-weight: 550;
174
- flex: 1;
175
- margin: 0 0.75rem;
176
186
  word-break: break-all;
177
187
  }
178
188
 
@@ -184,24 +194,100 @@ code.ultra-settings-field-data-value {
184
194
  letter-spacing: 0.025em;
185
195
  }
186
196
 
187
- .ultra-settings-source-value-dfn {
188
- display: inline-block;
189
- margin-left: 0.25rem;
197
+ .ultra-settings-source-indicator::before {
198
+ content: "● ";
199
+ font-size: 1rem;
200
+ }
201
+
202
+ .ultra-settings-source-overridden {
203
+ background-color: var(--source-overridden-bg-color);
204
+ border-color: var(--source-overridden-border-color);
205
+ }
206
+
207
+ .ultra-settings-source-overridden .ultra-settings-source-type {
208
+ color: var(--source-overridden-type-color);
209
+ }
210
+
211
+ .ultra-settings-source-overridden .ultra-settings-source-value-container .ultra-settings-source-value {
212
+ color: var(--source-overridden-value-color);
213
+ }
214
+
215
+ .ultra-settings-source-override {
216
+ font-size: 0.75rem;
217
+ font-weight: 600;
218
+ color: var(--source-overridden-warning-color);
219
+ display: flex;
220
+ align-items: center;
221
+ gap: 0.25rem;
222
+ }
223
+
224
+ .ultra-settings-source-override svg {
225
+ flex-shrink: 0;
226
+ }
227
+
228
+ .ultra-settings-source-override-text {
229
+ text-transform: uppercase;
230
+ letter-spacing: 0.025em;
190
231
  }
191
232
 
192
233
  .ultra-settings-icon-info {
193
234
  color: var(--info-color);
194
235
  cursor: pointer;
236
+ padding: 0.25rem;
237
+ border-radius: 0.25rem;
238
+ transition: all 0.15s ease;
239
+ display: inline-flex;
240
+ align-items: center;
241
+ justify-content: center;
242
+ }
243
+
244
+ .ultra-settings-icon-info:hover {
245
+ background-color: var(--source-bg-color);
246
+ transform: scale(1.15);
247
+ }
248
+
249
+ .ultra-settings-icon-info:active {
250
+ transform: scale(1.05);
195
251
  }
196
252
 
197
253
  .ultra-settings-icon-not-set {
198
254
  color: var(--warning-color);
199
255
  cursor: pointer;
256
+ padding: 0.25rem;
257
+ border-radius: 0.25rem;
258
+ transition: all 0.15s ease;
259
+ display: inline-flex;
260
+ align-items: center;
261
+ justify-content: center;
262
+ }
263
+
264
+ .ultra-settings-icon-not-set:hover {
265
+ background-color: var(--source-bg-color);
266
+ transform: scale(1.15);
267
+ }
268
+
269
+ .ultra-settings-icon-not-set:active {
270
+ transform: scale(1.05);
200
271
  }
201
272
 
202
273
  .ultra-settings-icon-secret {
203
274
  color: var(--disabled-color);
204
275
  cursor: pointer;
276
+ padding: 0.25rem;
277
+ border-radius: 0.25rem;
278
+ transition: all 0.15s ease;
279
+ display: inline-flex;
280
+ align-items: center;
281
+ justify-content: center;
282
+ }
283
+
284
+ .ultra-settings-icon-secret:hover {
285
+ background-color: var(--source-bg-color);
286
+ transform: scale(1.15);
287
+ }
288
+
289
+ .ultra-settings-icon-secret:active {
290
+ transform: scale(1.05);
205
291
  }
206
292
 
207
293
  .ultra-settings-edit-link {
@@ -218,47 +304,55 @@ code.ultra-settings-field-data-value {
218
304
  opacity: 1;
219
305
  }
220
306
 
221
- .ultra-settings-select {
222
- display: inline-block;
223
- padding: .375rem 2.25rem .375rem .75rem;
224
- -moz-padding-start: calc(0.75rem - 3px);
225
- font-size: 1rem;
226
- font-weight: 400;
227
- line-height: 1.5;
228
- color: var(--form-control-color);
229
- background-color: var(--form-control-bg-color);
230
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
231
- background-repeat: no-repeat;
232
- background-position: right .75rem center;
233
- background-size: 16px 12px;
234
- border: 1px solid var(--form-control-border-color);
235
- border-radius: .25rem;
236
- transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
237
- -webkit-appearance: none;
238
- -moz-appearance: none;
239
- appearance: none;
240
- }
241
-
242
307
  .ultra-settings-dialog {
243
- min-width: 20rem;
308
+ min-width: 24rem;
309
+ max-width: 90vw;
244
310
  padding: 0;
245
- border: 1px solid var(--field-border-color);
246
- border-radius: 0.375rem;
311
+ border: none;
312
+ border-radius: 0.5rem;
313
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
314
+ animation: ultra-settings-dialog-show 0.2s ease-out;
315
+ }
316
+
317
+ .ultra-settings-dialog::backdrop {
318
+ background-color: rgba(0, 0, 0, 0.5);
319
+ animation: ultra-settings-backdrop-show 0.2s ease-out;
320
+ }
321
+
322
+ @keyframes ultra-settings-dialog-show {
323
+ from {
324
+ opacity: 0;
325
+ transform: scale(0.95) translateY(-10px);
326
+ }
327
+ to {
328
+ opacity: 1;
329
+ transform: scale(1) translateY(0);
330
+ }
331
+ }
332
+
333
+ @keyframes ultra-settings-backdrop-show {
334
+ from {
335
+ opacity: 0;
336
+ }
337
+ to {
338
+ opacity: 1;
339
+ }
247
340
  }
248
341
 
249
342
  .ultra-settings-dialog-header {
250
- padding: 0.5rem;
343
+ padding: 1rem 1.25rem;
251
344
  background-color: var(--field-header-bg-color);
252
345
  color: var(--field-header-text-color);
253
346
  font-size: 1rem;
254
347
  display: flex;
255
- align-items: top;
348
+ align-items: center;
349
+ border-bottom: 1px solid var(--field-border-color);
256
350
  }
257
351
 
258
352
  .ultra-settings-dialog-title {
259
353
  flex: 1;
260
- text-align: center;
261
- font-weight: 550;
354
+ font-weight: 600;
355
+ font-size: 1.125rem;
262
356
  }
263
357
 
264
358
  .ultra-settings-dialog-close {
@@ -267,10 +361,194 @@ code.ultra-settings-field-data-value {
267
361
  color: var(--field-header-text-color);
268
362
  cursor: pointer;
269
363
  padding: 0.25rem;
364
+ border-radius: 0.25rem;
365
+ display: flex;
366
+ align-items: center;
367
+ justify-content: center;
368
+ transition: background-color 0.15s ease;
369
+ margin-left: 0.5rem;
370
+ }
371
+
372
+ .ultra-settings-dialog-close:hover {
373
+ background-color: var(--source-bg-color);
374
+ }
375
+
376
+ .ultra-settings-dialog-close:active {
377
+ transform: scale(0.95);
270
378
  }
271
379
 
272
380
  .ultra-settings-dialog-body {
273
- padding: 1rem;
381
+ padding: 1.5rem;
274
382
  background-color: var(--background-color);
275
383
  color: var(--text-color);
384
+ max-height: 60vh;
385
+ overflow-y: auto;
386
+ }
387
+
388
+ .ultra-settings-dialog-body .ultra-settings-field-data-value {
389
+ display: block;
390
+ word-break: break-all;
391
+ white-space: pre-wrap;
392
+ font-size: 0.9375rem;
393
+ line-height: 1.6;
394
+ padding: 0.75rem 1rem;
395
+ }
396
+
397
+ /* Dropdown Styles */
398
+ .ultra-settings-dropdown {
399
+ position: relative;
400
+ display: inline-block;
401
+ width: 100%;
402
+ max-width: 400px;
403
+ }
404
+
405
+ .ultra-settings-dropdown-button {
406
+ width: 100%;
407
+ text-align: left;
408
+ padding: 0.5rem 1rem;
409
+ font-size: 1.25rem;
410
+ font-weight: 500;
411
+ background-color: var(--form-control-bg-color);
412
+ color: var(--form-control-color);
413
+ border: 1px solid var(--form-control-border-color);
414
+ border-radius: 0.375rem;
415
+ cursor: pointer;
416
+ display: flex;
417
+ justify-content: space-between;
418
+ align-items: center;
419
+ }
420
+
421
+ .ultra-settings-dropdown-button::after {
422
+ content: "";
423
+ display: inline-block;
424
+ width: 0;
425
+ height: 0;
426
+ margin-left: 0.5rem;
427
+ vertical-align: middle;
428
+ border-top: 4px solid;
429
+ border-right: 4px solid transparent;
430
+ border-left: 4px solid transparent;
431
+ }
432
+
433
+ .ultra-settings-dropdown-menu {
434
+ position: absolute;
435
+ top: 100%;
436
+ left: 0;
437
+ z-index: 1000;
438
+ display: none;
439
+ min-width: 100%;
440
+ padding: 0.5rem 0;
441
+ margin: 0.125rem 0 0;
442
+ font-size: 1rem;
443
+ color: var(--text-color);
444
+ text-align: left;
445
+ list-style: none;
446
+ background-color: var(--form-control-bg-color);
447
+ background-clip: padding-box;
448
+ border: 1px solid var(--form-control-border-color);
449
+ border-radius: 0.375rem;
450
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
451
+ }
452
+
453
+ .ultra-settings-search-container {
454
+ padding: 0.5rem 1rem;
455
+ border-bottom: 1px solid var(--form-control-border-color);
456
+ }
457
+
458
+ #config-search {
459
+ width: 100%;
460
+ padding: 0.375rem 0.75rem;
461
+ font-size: 0.875rem;
462
+ line-height: 1.5;
463
+ color: var(--form-control-color);
464
+ background-color: var(--value-bg-color);
465
+ background-clip: padding-box;
466
+ border: 1px solid var(--form-control-border-color);
467
+ border-radius: 0.25rem;
468
+ box-sizing: border-box;
469
+ }
470
+
471
+ .ultra-settings-dropdown-list {
472
+ list-style: none;
473
+ padding: 0;
474
+ margin: 0;
475
+ max-height: 300px;
476
+ overflow-y: auto;
477
+ }
478
+
479
+ .ultra-settings-dropdown-item {
480
+ display: flex;
481
+ align-items: center;
482
+ padding: 0.5rem 1rem;
483
+ clear: both;
484
+ font-weight: 400;
485
+ color: var(--form-control-color);
486
+ text-align: inherit;
487
+ white-space: nowrap;
488
+ background-color: transparent;
489
+ border: 0;
490
+ cursor: pointer;
491
+ }
492
+
493
+ .ultra-settings-dropdown-item:hover {
494
+ background-color: var(--field-header-bg-color);
495
+ }
496
+
497
+ .ultra-settings-check-icon {
498
+ width: 1.5rem;
499
+ display: inline-block;
500
+ text-align: center;
501
+ font-weight: bold;
502
+ }
503
+
504
+ .ultra-settings-dropdown-item.selected .ultra-settings-check-icon::before {
505
+ content: "✓";
506
+ }
507
+
508
+ .ultra-settings-title {
509
+ margin: 0;
510
+ font-size: 1.25rem;
511
+ font-weight: 500;
512
+ color: var(--text-color);
513
+ }
514
+
515
+ /* Configuration List Styles */
516
+ .ultra-settings-configuration-list {
517
+ display: grid;
518
+ grid-template-columns: repeat(auto-fill, minmax(max(300px, 30%), 1fr));
519
+ gap: 1.5rem;
520
+ margin-top: 1.5rem;
521
+ }
522
+
523
+ .ultra-settings-configuration-summary {
524
+ background-color: var(--field-bg-color);
525
+ border: 1px solid var(--field-border-color);
526
+ border-radius: 0.5rem;
527
+ padding: 1.5rem;
528
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
529
+ overflow: hidden;
530
+ }
531
+
532
+ .ultra-settings-configuration-summary:hover {
533
+ transform: translateY(-2px);
534
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
535
+ }
536
+
537
+ .ultra-settings-configuration-title {
538
+ display: block;
539
+ font-size: 1.25rem;
540
+ font-weight: 600;
541
+ color: var(--description-color);
542
+ text-decoration: none;
543
+ margin-bottom: 0.75rem;
544
+ }
545
+
546
+ .ultra-settings-configuration-title:hover {
547
+ text-decoration: underline;
548
+ }
549
+
550
+ .ultra-settings-configuration-summary p {
551
+ margin: 0;
552
+ color: var(--description-color);
553
+ line-height: 1.5;
276
554
  }
data/app/application.js CHANGED
@@ -1,41 +1,124 @@
1
1
  document.addEventListener("DOMContentLoaded", () => {
2
- const menu = document.getElementById("config-selector");
2
+ const dropdown = document.getElementById("config-dropdown");
3
+ const button = document.getElementById("config-dropdown-button");
4
+ const menu = document.getElementById("config-dropdown-menu");
5
+ const searchInput = document.getElementById("config-search");
6
+ const items = document.querySelectorAll(".ultra-settings-dropdown-item");
7
+ const configurations = document.querySelectorAll(".ultra-settings-configuration");
8
+ const configList = document.querySelector(".ultra-settings-configuration-list");
3
9
 
4
- showCurrentConfiguration = () => {
5
- const selectedId = menu.options[menu.selectedIndex].value;
6
- const hash = selectedId.replace(/^config-/, "");
10
+ // If no dropdown, we might be in single config mode or no configs.
11
+ if (!dropdown) {
12
+ // If there is exactly one configuration, show it.
13
+ if (configurations.length === 1) {
14
+ configurations[0].style.display = "block";
15
+ }
16
+ return;
17
+ }
7
18
 
8
- document.querySelectorAll(".ultra-settings-configuration").forEach((configuration) => {
9
- if (configuration.id === selectedId) {
10
- configuration.style.display = "block";
11
- window.location.hash = hash;
19
+ const toggleMenu = () => {
20
+ const isVisible = menu.style.display === "block";
21
+ menu.style.display = isVisible ? "none" : "block";
22
+ if (!isVisible) {
23
+ searchInput.value = "";
24
+ filterItems("");
25
+ searchInput.focus();
26
+ }
27
+ };
28
+
29
+ const closeMenu = () => {
30
+ menu.style.display = "none";
31
+ };
32
+
33
+ const filterItems = (query) => {
34
+ const lowerQuery = query.toLowerCase();
35
+ items.forEach(item => {
36
+ const label = item.getAttribute("data-search").toLowerCase();
37
+ if (label.includes(lowerQuery)) {
38
+ item.style.display = "flex";
12
39
  } else {
13
- configuration.style.display = "none";
40
+ item.style.display = "none";
14
41
  }
15
42
  });
16
- }
43
+ };
17
44
 
18
- menu.addEventListener("change", showCurrentConfiguration);
45
+ const showConfigList = () => {
46
+ if (configList) configList.style.display = "grid";
47
+ configurations.forEach(config => config.style.display = "none");
48
+ items.forEach(item => item.classList.remove("selected"));
49
+ button.textContent = "Select Configuration";
50
+ closeMenu();
51
+ };
19
52
 
20
- const setCurrentSelection = () => {
21
- const hash = window.location.hash.replace(/^#/, "");
22
- const selectedId = `config-${hash}`;
23
- for (const option of menu.options) {
24
- if (option.value === selectedId) {
25
- option.selected = true;
26
- break;
53
+ const showConfig = (configId) => {
54
+ if (configList) configList.style.display = "none";
55
+
56
+ configurations.forEach(config => {
57
+ config.style.display = config.id === configId ? "block" : "none";
58
+ });
59
+
60
+ items.forEach(item => {
61
+ if (item.getAttribute("data-value") === configId) {
62
+ item.classList.add("selected");
63
+ button.textContent = item.getAttribute("data-label");
64
+ } else {
65
+ item.classList.remove("selected");
27
66
  }
67
+ });
68
+
69
+ closeMenu();
70
+ };
71
+
72
+ // Event Listeners
73
+ button.addEventListener("click", (e) => {
74
+ e.stopPropagation();
75
+ toggleMenu();
76
+ });
77
+
78
+ document.addEventListener("click", (e) => {
79
+ if (!dropdown.contains(e.target)) {
80
+ closeMenu();
28
81
  }
82
+ });
29
83
 
30
- showCurrentConfiguration();
31
- }
84
+ searchInput.addEventListener("input", (e) => {
85
+ filterItems(e.target.value);
86
+ });
32
87
 
33
- window.addEventListener('hashchange', setCurrentSelection);
88
+ items.forEach(item => {
89
+ item.addEventListener("click", () => {
90
+ const configId = item.getAttribute("data-value");
91
+ const hash = configId.replace(/^config-/, "");
34
92
 
93
+ if (item.classList.contains("selected")) {
94
+ // Toggle off: clear hash
95
+ history.pushState("", document.title, window.location.pathname + window.location.search);
96
+ handleHashChange();
97
+ } else {
98
+ window.location.hash = hash;
99
+ }
100
+ });
101
+ });
35
102
 
36
- if (window.location.hash) {
37
- setCurrentSelection()
38
- }
103
+ // Initial Load & Hash Change
104
+ const handleHashChange = () => {
105
+ const hash = window.location.hash.replace(/^#/, "");
106
+ if (hash) {
107
+ const configId = `config-${hash}`;
108
+ // Check if config exists
109
+ const exists = Array.from(items).some(item => item.getAttribute("data-value") === configId);
110
+ if (exists) {
111
+ showConfig(configId);
112
+ } else {
113
+ showConfigList();
114
+ }
115
+ } else {
116
+ showConfigList();
117
+ }
118
+ };
119
+
120
+ window.addEventListener("hashchange", handleHashChange);
39
121
 
40
- showCurrentConfiguration();
122
+ // Run once on load
123
+ handleHashChange();
41
124
  });
@@ -28,6 +28,11 @@
28
28
  --source-border-color: #e9ecef;
29
29
  --source-active-bg-color: #e7f3ff;
30
30
  --source-active-border-color: #0d6efd;
31
+ --source-overridden-bg-color: #fff3cd;
32
+ --source-overridden-border-color: #ffc107;
33
+ --source-overridden-type-color: #4d4d4d;
34
+ --source-overridden-value-color: #2b2b2b;
35
+ --source-overridden-warning-color: #996900;
31
36
  --source-type-color: #666666;
32
37
  --source-value-color: #444444;
33
38
  --source-indicator-color: #0d6efd;
@@ -77,6 +82,11 @@
77
82
  --source-border-color: #444444;
78
83
  --source-active-bg-color: #1a3a52;
79
84
  --source-active-border-color: #0d6efd;
85
+ --source-overridden-bg-color: #3d3416;
86
+ --source-overridden-border-color: #997404;
87
+ --source-overridden-type-color: #d4d4d4;
88
+ --source-overridden-value-color: #e8e8e8;
89
+ --source-overridden-warning-color: #ffb84d;
80
90
  --source-type-color: #adb5bd;
81
91
  --source-value-color: #ced4da;
82
92
  --source-indicator-color: #6ea8fe;