Make Data panel scalars selectable inline, denoise float display, and standardize breadcrumb string truncation (#4470)

* Make Data panel scalars selectable inline, denoise float display, and move breadcrumb truncation to Rust

* Code review fixes

* Remove denoising from f32
This commit is contained in:
Keavon Chambers
2026-08-22 01:28:23 -07:00
committed by GitHub
parent 2fa6b743fe
commit c8667edacc
14 changed files with 253 additions and 187 deletions

View File

@@ -12,31 +12,11 @@
export let tooltipShortcut: ActionShortcut | undefined = undefined;
// Callbacks
export let action: (index: number) => void;
function truncate(label: string): string {
let maxLength = 40;
if (label.length <= maxLength) return label;
let truncated = label;
const hasQuotes = label.startsWith(`"`) && label.endsWith(`"`);
if (hasQuotes) {
truncated = label.slice(1, -1);
maxLength -= 2;
}
truncated = truncated.slice(0, maxLength - 1) + "…";
if (hasQuotes) truncated = `"${truncated}"`;
return truncated;
}
</script>
<LayoutRow class="breadcrumb-trail-buttons" {tooltipLabel} {tooltipDescription} {tooltipShortcut}>
{#each labels as label, index}
<TextButton label={truncate(label)} emphasized={index === labels.length - 1} {disabled} action={() => !disabled && index !== labels.length - 1 && action(index)} />
<TextButton {label} emphasized={index === labels.length - 1} {disabled} action={() => !disabled && index !== labels.length - 1 && action(index)} />
{/each}
</LayoutRow>

View File

@@ -205,6 +205,10 @@
textarea {
color: var(--color-8-uppergray);
}
input {
pointer-events: none;
}
}
}
</style>

View File

@@ -19,6 +19,8 @@
export let italic = false;
export let monospace = false;
export let multiline = false;
export let enquote = false;
export let selectable = false;
export let centerAlign = false;
export let tableAlign = false;
// Sizing
@@ -76,6 +78,8 @@
class:italic
class:monospace
class:multiline
class:enquote
class:selectable
class:center-align={centerAlign}
class:table-align={tableAlign}
style:min-width={minWidthCharacters ? `${minWidthCharacters}ch` : minWidth > 0 ? `${minWidth}px` : undefined}
@@ -125,6 +129,17 @@
margin: 4px 0;
}
&.enquote::before,
&.enquote::after {
content: '"';
user-select: none;
}
&.selectable {
user-select: text;
cursor: text;
}
&.center-align {
text-align: center;
}

View File

@@ -128,6 +128,7 @@ export function onPointerMove(e: PointerEvent, editor: EditorWrapper, documentSt
export function onPointerDown(e: PointerEvent, editor: EditorWrapper, dialogStore: DialogStore) {
potentiallyRestoreCanvasFocus(e);
potentiallyClearTextSelection(e);
const inFloatingMenu = e.target instanceof Element && e.target.closest("[data-floating-menu-content]");
const isTargetingCanvas = !inFloatingMenu && e.target instanceof Element && e.target.closest("[data-viewport], [data-viewport-container], [data-node-graph]");
@@ -351,6 +352,20 @@ function targetIsTextField(target: EventTarget | HTMLElement | undefined): boole
);
}
function potentiallyClearTextSelection(e: PointerEvent) {
const target = e.target instanceof Element ? e.target : undefined;
if (target && (targetIsTextField(target) || window.getComputedStyle(target).userSelect !== "none")) return;
// A text control's selection lives in its shadow tree, which the document's `Selection` reports as collapsed and cannot clear, so each control holding one is collapsed through its own API
const controls = window.document.querySelectorAll<HTMLInputElement | HTMLTextAreaElement>("textarea, input[type='text']");
controls.forEach((control) => {
const caret = control.selectionStart;
if (typeof caret === "number" && caret !== control.selectionEnd) control.setSelectionRange(caret, caret);
});
window.getSelection()?.removeAllRanges();
}
function potentiallyRestoreCanvasFocus(e: Event) {
const appElement = window.document.querySelector("[data-app-container]");
const app = appElement instanceof HTMLElement ? appElement : undefined;