/** * Disabled-state, aria-state, and toolbar-state helpers used by * {@link ImageEditor}'s `init` and operation handlers. These * helpers share the same `idMap`-driven element-resolution * vocabulary as `dom-bindings.ts` so the orchestrator can speak * one language when wiring or refreshing UI state. * * ## Owned contracts * * - Bound DOM controls live in the orchestrator's * bindings registry and are addressed by logical {@link ElementKey}. * These helpers consume the same key vocabulary so toolbar-state updates * stay aligned with what `dom-bindings.ts` originally bound. * - Toolbar-state mutation must remain a no-op when * the editor is disposed or when a logical key is unmapped. Each helper * short-circuits on a missing element ID or missing DOM node so * post-`dispose` `updateUi`-style calls cannot throw or surprise the * host page. * * ## Why this lives in its own module * * Splitting low-level DOM state out keeps `image-editor.ts` focused on * toolbar policy while helpers here own native DOM writes such as setting * `disabled` by logical key. * * Like `dom-bindings.ts` and `visibility-state.ts`, this module is imported * by `image-editor.ts` only and is intentionally NOT re-exported from * `src/index.ts`. * * @module */ import type { ElementIdMap } from '../core/public-types.js'; /** * Logical element-name keys understood by the editor's `idMap`. Matches the * `ElementKey` alias exported from `dom-bindings.ts` so the orchestrator's * registry and the toolbar-state helpers can be driven from the same * lookup function without crossing the public-types boundary. */ export type ElementKey = keyof Required; /** * Callback used by every helper in this module to translate a logical * {@link ElementKey} to the resolved DOM element ID supplied by the host * page through `idMap`. Returning a falsy value (`null`, `undefined`, or * empty string) means the host omitted that key — helpers MUST treat that * as a no-op rather than a bug. */ export type ElementIdResolver = (key: ElementKey) => string | null | undefined; /** * Set the native `disabled` IDL property on a button-like control resolved * from `key`. Used by the orchestrator's `updateUi` policy: each toolbar * button maps to one logical key, and the policy decides whether the * button is currently usable. * * Behaviour: * * - If `resolveElementId(key)` returns a falsy value, the helper returns * without touching the DOM (the integrator chose not to wire that * control). * - If `document.getElementById(id)` returns `null`, the helper returns * without throwing. A missing node is a partial-DOM scenario, not a * fatal error. * - Otherwise the resolved element's `disabled` property is set to the * requested boolean. Using the IDL property (not `setAttribute`) * keeps the keyboard/click behaviour the * browser provides "for free" on real `