diff --git a/module/Apps/mixins/LaidOutAppMixin.mjs b/module/Apps/mixins/LaidOutAppMixin.mjs new file mode 100644 index 0000000..956630b --- /dev/null +++ b/module/Apps/mixins/LaidOutAppMixin.mjs @@ -0,0 +1,56 @@ +/** + * 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; +};