@@ -200,6 +200,25 @@ const script = ` const vscode = acquireVsCodeApi();
200200 function convert(from, to) {
201201 return exports[from + 'To' + to.charAt(0).toUpperCase() + to.slice(1)];
202202 }
203+ /**
204+ * One inlined merge of a saved value with whatever is staged, by the kind
205+ * of control asking, or undefined when the library could not be read.
206+ *
207+ * Assembled like {@link convert} and for the same reason: the panel
208+ * script never spells the name, so finding it in the document is proof
209+ * the library was really inlined.
210+ */
211+ function display(kind) {
212+ return exports['display' + kind.charAt(0).toUpperCase() + kind.slice(1)];
213+ }
214+ /**
215+ * What one row should show now, falling back to the saved value alone
216+ * when the merge could not be inlined.
217+ */
218+ function shown(kind, saved, key, pending) {
219+ const merge = display(kind);
220+ return merge ? merge(saved, key, pending || {}) : { value: saved, pending: false };
221+ }
203222 function sliders(key) {
204223 return document.querySelectorAll('input[data-slider-for="' + key + '"]');
205224 }
@@ -457,34 +476,39 @@ const script = ` const vscode = acquireVsCodeApi();
457476 if (!message || message.type !== 'state') {
458477 return;
459478 }
479+ const pending = message.pending || {};
460480 (message.toggles || []).forEach((toggle) => {
481+ const entry = shown('toggle', toggle.value, toggle.key, pending);
461482 const box = switchOf(toggle.key);
462483 if (box) {
463- box.checked = toggle .value;
484+ box.checked = entry .value;
464485 }
465- markPending(toggle.key, false );
486+ markPending(toggle.key, entry.pending );
466487 });
467488 (message.selects || []).forEach((select) => {
468- markSelected(select.key, select.value);
469- markPending(select.key, false);
489+ const entry = shown('value', select.value, select.key, pending);
490+ markSelected(select.key, entry.value);
491+ markPending(select.key, entry.pending);
470492 });
471493 message.rows.forEach((row) => {
472- markPending(row.key, false);
494+ const entry = shown('value', row.savedColor, row.key, pending);
495+ const color = entry.value;
496+ markPending(row.key, entry.pending);
473497 const swatch = document.querySelector('[data-swatch="' + row.key + '"]');
474498 if (swatch) {
475- swatch.style.background = row.savedColor ;
476- swatch.title = row.savedColor ;
499+ swatch.style.background = color ;
500+ swatch.title = color ;
477501 }
478502 const input = document.querySelector('input[type="color"][data-key="' + row.key + '"]');
479- if (input && /^#[0-9a-fA-F]{6}$/.test(row.savedColor )) {
480- input.value = row.savedColor ;
503+ if (input && /^#[0-9a-fA-F]{6}$/.test(color )) {
504+ input.value = color ;
481505 }
482- showOnSliders(row.key, /^#[0-9a-fA-F]{6}$/.test(row.savedColor ) ? row.savedColor : '#000000');
483- // The saved value wins over whatever is being typed: a reset has to
484- // reach a field the reader still has the caret in.
506+ showOnSliders(row.key, /^#[0-9a-fA-F]{6}$/.test(color ) ? color : '#000000');
507+ // The displayed value wins over whatever is being typed: a reset has
508+ // to reach a field the reader still has the caret in.
485509 const field = document.querySelector('[data-hex-for="' + row.key + '"]');
486510 if (field) {
487- field.value = row.savedColor ;
511+ field.value = color ;
488512 field.classList.remove('invalid');
489513 }
490514 });
@@ -558,15 +582,18 @@ const style = ` body { font-family: var(--vscode-font-family); font-size: v
558582 *
559583 * Flipping a switch or dragging a picker only previews; a row marks itself
560584 * pending until a state message says its value was saved. The footer button
561- * commits every pending row at once.
585+ * commits every pending row at once. A state message names what is saved and
586+ * what is staged separately, and every control shows the staged value over the
587+ * saved one, so a resync arriving mid-edit cannot undo a choice.
562588 *
563589 * The select rows sit between the two: they are settings of the editor rather
564590 * than of this extension, and choosing one stages it without any local
565591 * rendering, because VS Code draws those numbers itself.
566592 *
567- * @param inlineLib compiled color conversions, pasted verbatim into the nonced
568- * script behind an exports shim so the sliders convert with the very code the
569- * unit tests cover; an empty string leaves the row usable through its picker
593+ * @param inlineLib the compiled color conversions and pending merge, pasted
594+ * verbatim into the nonced script behind an exports shim so the panel runs
595+ * the very code the unit tests cover; an empty string leaves the row usable
596+ * through its picker
570597 */
571598export function renderPanelHtml (
572599 toggles : PanelToggle [ ] ,
0 commit comments