ripcrypt/module/Apps/mixins/LaidOutAppMixin.mjs

56 lines
1.9 KiB
JavaScript

/**
* 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>} 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;
};