Skip to content

Refactor canvas elements: registry-driven controls#7621

Draft
hatton wants to merge 1 commit intomasterfrom
BL-15770RefactorCanvas
Draft

Refactor canvas elements: registry-driven controls#7621
hatton wants to merge 1 commit intomasterfrom
BL-15770RefactorCanvas

Conversation

@hatton
Copy link
Member

@hatton hatton commented Jan 26, 2026

CanvasElementManager had grown too large and UI affordances (context menu + mini toolbar) were being assembled imperatively, which made ordering/section dividers hard to reason about and encouraged cross-bundle imports.

This change introduces a declarative canvas element registry that drives which buttons and menus are available per element type.

It also makes context menu/mini-toolbar composition deterministic: fixed section ordering, exactly one divider/spacer between non-empty sections, and Duplicate/Delete always last.

To reduce runtime import-cycle risk across the edit view + toolbox bundles, DOM selectors/constants move to a dependency-light module (canvasElementConstants) while canvasElementUtils is narrowed to a cross-frame bridge (getCanvasElementManager) with type-only imports.

CanvasElementManager is partially decomposed into focused helper modules (Geometry/Positioning/Alternates) plus public-function wrappers, and related call sites were updated. Misc hardening: safer MUI Menu anchoring, avoid non-null assertions, fix closest() selector typo, and remove duplicate pxToNumber helper.

Follow-ups in this series:

  • Make mini-toolbar + menu more declarative and consistent
    • Make toolbarButtons the sole source of truth for the mini-toolbar (including explicit spacers) and normalize spacer runs.

    • Share menu + toolbar definitions via a single command registry to keep icons/tooltips/click behavior in sync.

    • Replace “Set Up Hyperlink” with the “Set Destination” command in this context, and do not show either on simple image elements.


This change is Reviewable


Open with Devin

CanvasElementManager had grown too large and UI affordances (context menu + mini toolbar) were being assembled imperatively, which made ordering/section dividers hard to reason about and encouraged cross-bundle imports.

This change introduces a declarative canvas element registry that drives which buttons and menus are available per element type.

It also makes context menu/mini-toolbar composition deterministic: fixed section ordering, exactly one divider/spacer between non-empty sections, and Duplicate/Delete always last.

To reduce runtime import-cycle risk across the edit view + toolbox bundles, DOM selectors/constants move to a dependency-light module (canvasElementConstants) while canvasElementUtils is narrowed to a cross-frame bridge (getCanvasElementManager) with type-only imports.

CanvasElementManager is partially decomposed into focused helper modules (Geometry/Positioning/Alternates) plus public-function wrappers, and related call sites were updated. Misc hardening: safer MUI Menu anchoring, avoid non-null assertions, fix closest() selector typo, and remove duplicate pxToNumber helper.

Follow-ups in this series:

- Make mini-toolbar + menu more declarative and consistent
  - Make `toolbarButtons` the sole source of truth for the mini-toolbar (including explicit spacers) and normalize spacer runs.
  - Share menu + toolbar definitions via a single command registry to keep icons/tooltips/click behavior in sync.

  - Replace “Set Up Hyperlink” with the “Set Destination” command in this context, and do not show either on simple image elements.
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View issue and 6 additional flags in Devin Review.

Open in Devin Review

canvasElementLangIn?: string,
): void => {
const canvasElementLang =
canvasElementLangIn ?? GetSettings().languageForNewTextBoxes;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Missing GetSettings() type declaration in CanvasElementAlternates.ts causes TypeScript error

The new file CanvasElementAlternates.ts uses the globally injected GetSettings() function at line 12 but lacks the required triple-slash reference directive to declare it.

Click to expand

Problem

The file calls GetSettings().languageForNewTextBoxes but GetSettings is not declared in scope. This function is injected by C# at runtime, but TypeScript needs the type declaration to compile.

Evidence

Other files in the codebase that use GetSettings() include the reference directive:

  • CanvasElementManager.ts:8: /// <reference path="./collectionSettings.d.ts"/>
  • BloomSourceBubbles.tsx:10: /// <reference path="../js/collectionSettings.d.ts"/>
  • StyleEditor.ts:11: /// <reference path="../js/collectionSettings.d.ts"/>
  • PlaceholderProvider.ts:5: /// <reference path="./collectionSettings.d.ts" />
  • BloomHintBubbles.ts:5: /// <reference path="./collectionSettings.d.ts" />

Impact

This will cause a TypeScript compilation error: Cannot find name 'GetSettings'.

Recommendation: Add the triple-slash reference directive at the top of the file:

/// <reference path="../collectionSettings.d.ts"/>
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant