Skip to content

Commit a305395

Browse files
authored
feat: make fields and icons optionally clickable in flyouts (#7672)
* feat: add ability to click fields in flyouts * feat: control if icons are clickable in flyouts * fix: make default icons not clickable in flyout * fix: use booleans like a real programmer
1 parent 76a1ab2 commit a305395

7 files changed

Lines changed: 60 additions & 8 deletions

File tree

core/field.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,20 @@ export abstract class Field<T = any>
581581
);
582582
}
583583

584+
/**
585+
* Check whether the field should be clickable while the block is in a flyout.
586+
* The default is that fields are clickable in always-open flyouts such as the
587+
* simple toolbox, but not in autoclosing flyouts such as the category toolbox.
588+
* Subclasses may override this function to change this behavior. Note that
589+
* `isClickable` must also return true for this to have any effect.
590+
*
591+
* @param autoClosingFlyout true if the containing flyout is an auto-closing one.
592+
* @returns Whether the field should be clickable while the block is in a flyout.
593+
*/
594+
isClickableInFlyout(autoClosingFlyout: boolean): boolean {
595+
return !autoClosingFlyout;
596+
}
597+
584598
/**
585599
* Check whether this field is currently editable. Some fields are never
586600
* EDITABLE (e.g. text labels). Other fields may be EDITABLE but may exist on

core/gesture.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,25 +1157,29 @@ export class Gesture {
11571157
}
11581158

11591159
/**
1160-
* Whether this gesture is a click on a field. This should only be called
1160+
* Whether this gesture is a click on a field that should be handled. This should only be called
11611161
* when ending a gesture (pointerup).
11621162
*
11631163
* @returns Whether this gesture was a click on a field.
11641164
*/
11651165
private isFieldClick(): boolean {
1166-
const fieldClickable = this.startField
1167-
? this.startField.isClickable()
1168-
: false;
1166+
if (!this.startField) return false;
11691167
return (
1170-
fieldClickable &&
1168+
this.startField.isClickable() &&
11711169
!this.hasExceededDragRadius &&
1172-
(!this.flyout || !this.flyout.autoClose)
1170+
(!this.flyout ||
1171+
this.startField.isClickableInFlyout(this.flyout.autoClose))
11731172
);
11741173
}
11751174

1176-
/** @returns Whether this gesture is a click on an icon. */
1175+
/** @returns Whether this gesture is a click on an icon that should be handled. */
11771176
private isIconClick(): boolean {
1178-
return !!this.startIcon && !this.hasExceededDragRadius;
1177+
if (!this.startIcon) return false;
1178+
const handleInFlyout =
1179+
!this.flyout ||
1180+
!this.startIcon.isClickableInFlyout ||
1181+
this.startIcon.isClickableInFlyout(this.flyout.autoClose);
1182+
return !this.hasExceededDragRadius && handleInFlyout;
11791183
}
11801184

11811185
/**

core/icons/comment_icon.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable {
223223
this.setBubbleVisible(!this.bubbleIsVisible());
224224
}
225225

226+
override isClickableInFlyout(): boolean {
227+
return false;
228+
}
229+
226230
/**
227231
* Updates the text of this comment in response to changes in the text of
228232
* the input bubble.

core/icons/icon.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ export abstract class Icon implements IIcon {
133133

134134
onClick(): void {}
135135

136+
/**
137+
* Check whether the icon should be clickable while the block is in a flyout.
138+
* The default is that icons are clickable in all flyouts (auto-closing or not).
139+
* Subclasses may override this function to change this behavior.
140+
*
141+
* @param autoClosingFlyout true if the containing flyout is an auto-closing one.
142+
* @returns Whether the icon should be clickable while the block is in a flyout.
143+
*/
144+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
145+
isClickableInFlyout(autoClosingFlyout: boolean): boolean {
146+
return true;
147+
}
148+
136149
/**
137150
* Sets the visibility of the icon's bubble if one exists.
138151
*

core/icons/mutator_icon.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ export class MutatorIcon extends Icon implements IHasBubble {
157157
}
158158
}
159159

160+
override isClickableInFlyout(): boolean {
161+
return false;
162+
}
163+
160164
bubbleIsVisible(): boolean {
161165
return !!this.miniWorkspaceBubble;
162166
}

core/icons/warning_icon.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ export class WarningIcon extends Icon implements IHasBubble {
160160
this.setBubbleVisible(!this.bubbleIsVisible());
161161
}
162162

163+
override isClickableInFlyout(): boolean {
164+
return false;
165+
}
166+
163167
bubbleIsVisible(): boolean {
164168
return !!this.textBubble;
165169
}

core/interfaces/i_icon.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ export interface IIcon {
8383
* Notifies the icon that it has been clicked.
8484
*/
8585
onClick(): void;
86+
87+
/**
88+
* Check whether the icon should be clickable while the block is in a flyout.
89+
* If this function is not defined, the icon will be clickable in all flyouts.
90+
*
91+
* @param autoClosingFlyout true if the containing flyout is an auto-closing one.
92+
* @returns Whether the icon should be clickable while the block is in a flyout.
93+
*/
94+
isClickableInFlyout?(autoClosingFlyout: boolean): boolean;
8695
}
8796

8897
/** Type guard that checks whether the given object is an IIcon. */

0 commit comments

Comments
 (0)