/** * This mixin makes it so that we can provide a specific layout template without * needing to reference each of the inner areas via a partial embedded in the root, * enabling partial re-renders for parts of the sheet without losing advanced * layout capabilities. * * @param {ReturnType} HandlebarsApp The mixin'd class from HAM to further mix */ export function LaidOutAppMixin(HandlebarsApp) { class LaidOutApp extends HandlebarsApp { #partDescriptors; /** * This caches the part descriptors into this class of the heirarchy, because * Foundry doesn't expose the partDescriptors from the HAM directly, so we * inject a heirarchy call so that we can nab the pointer that Foundry has * in the HAM so that we can also read/write it from this class. */ _configureRenderParts(options) { const parts = super._configureRenderParts(options); this.#partDescriptors = parts; return parts; }; /** * @override * This is essentially Foundry's HandlebarsApplicationMixin implementation, * however if an existing part for non-root elements don't get concatenated * into the DOM. */ _replaceHTML(result, content, options) { const partInfo = this.#partDescriptors; for ( const [partId, htmlElement] of Object.entries(result) ) { const part = partInfo[partId]; const priorElement = part.root ? content : content.querySelector(`[data-application-part="${partId}"]`); const state = {}; if ( priorElement ) { this._preSyncPartState(partId, htmlElement, priorElement, state); if ( part.root ) { priorElement.replaceChildren(...htmlElement.children); } else { priorElement.replaceWith(htmlElement); } this._syncPartState(partId, htmlElement, priorElement, state); } else { continue; }; this._attachPartListeners(partId, htmlElement, options); this.parts[partId] = htmlElement; } }; }; return LaidOutApp; };