From f84365b2262e1ad648bf18716042631341b98dd1 Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Wed, 7 May 2025 13:41:51 -0700 Subject: [PATCH] fix: Fix regressions in `Field`. --- core/field.ts | 28 +++++++++++++++++++++++++++- core/field_image.ts | 1 - core/field_input.ts | 20 ++++++++++++++++++++ core/field_variable.ts | 1 - 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/core/field.ts b/core/field.ts index 26fd44df96f..401e6c76eef 100644 --- a/core/field.ts +++ b/core/field.ts @@ -88,6 +88,9 @@ export abstract class Field */ DEFAULT_VALUE: T | null = null; + /** Non-breaking space. */ + static readonly NBSP = '\u00A0'; + /** * A value used to signal when a field's constructor should *not* set the * field's value or run configure_, and should allow a subclass to do that @@ -110,7 +113,28 @@ export abstract class Field * field is not yet initialized. Is *not* guaranteed to be accurate. */ private tooltip: Tooltip.TipInfo | null = null; - protected size_: Size; + + /** This field's dimensions. */ + private size: Size = new Size(0, 0); + + /** + * Gets the size of this field. Because getSize() and updateSize() have side + * effects, this acts as a shim for subclasses which wish to adjust field + * bounds when setting/getting the size without triggering unwanted rendering + * or other side effects. Note that subclasses must override *both* get and + * set if either is overridden; the implementation may just call directly + * through to super, but it must exist per the JS spec. + */ + protected get size_(): Size { + return this.size; + } + + /** + * Sets the size of this field. + */ + protected set size_(newValue: Size) { + this.size = newValue; + } /** The rendered field's SVG group element. */ protected fieldGroup_: SVGGElement | null = null; @@ -973,6 +997,8 @@ export abstract class Field // Truncate displayed string and add an ellipsis ('...'). text = text.substring(0, this.maxDisplayLength - 2) + '…'; } + // Replace whitespace with non-breaking spaces so the text doesn't collapse. + text = text.replace(/\s/g, Field.NBSP); if (this.sourceBlock_ && this.sourceBlock_.RTL) { // The SVG is LTR, force text to be RTL by adding an RLM. text += '\u200F'; diff --git a/core/field_image.ts b/core/field_image.ts index b65b77ae29c..761294a8cde 100644 --- a/core/field_image.ts +++ b/core/field_image.ts @@ -27,7 +27,6 @@ export class FieldImage extends Field { * of the field. */ private static readonly Y_PADDING = 1; - protected override size_: Size; protected readonly imageHeight: number; /** The function to be called when this field is clicked. */ diff --git a/core/field_input.ts b/core/field_input.ts index 2cdd8056553..f329e0991dc 100644 --- a/core/field_input.ts +++ b/core/field_input.ts @@ -100,6 +100,26 @@ export abstract class FieldInput extends Field< */ override SERIALIZABLE = true; + /** + * Sets the size of this field. Although this appears to be a no-op, it must + * exist since the getter is overridden below. + */ + protected override set size_(newValue: Size) { + super.size_ = newValue; + } + + /** + * Returns the size of this field, with a minimum width of 14. + */ + protected override get size_() { + const s = super.size_; + if (s.width < 14) { + s.width = 14; + } + + return s; + } + /** * @param value The initial value of the field. Should cast to a string. * Defaults to an empty string if null or undefined. Also accepts diff --git a/core/field_variable.ts b/core/field_variable.ts index b54b113cd69..aa4fdfe310f 100644 --- a/core/field_variable.ts +++ b/core/field_variable.ts @@ -49,7 +49,6 @@ export class FieldVariable extends FieldDropdown { * dropdown. */ variableTypes: string[] | null = []; - protected override size_: Size; /** The variable model associated with this field. */ private variable: IVariableModel | null = null;