FEAT: create isNPC geeter and add the prop on metada on actors

FEAT: create common method for documents sheets
FEAT: create BaseActorSheet and implementation
This commit is contained in:
Joaquin Pereyra 2025-07-06 12:49:08 -03:00
parent 608920c193
commit 98fee6096d
11 changed files with 302 additions and 418 deletions

View file

@ -1,3 +1,4 @@
export { default as DHApplicationMixin } from './application-mixin.mjs';
export { default as DHBaseItemSheet } from './base-item.mjs';
export { default as DHHeritageSheet } from './heritage-sheet.mjs';
export { default as DHBaseActorSheet } from "./base-actor.mjs";

View file

@ -5,6 +5,14 @@ import { tagifyElement } from '../../../helpers/utils.mjs';
* @typedef {object} DragDropConfig
* @property {string} [dragSelector] - A CSS selector that identifies draggable elements.
* @property {string} [dropSelector] - A CSS selector that identifies drop targets.
*
* @typedef {object} ContextMenuConfig
* @property {() => ContextMenuEntry[]} handler - A handler function that provides initial context options
* @property {string} selector - A CSS selector to which the ContextMenu will be bound
* @property {object} [options] - Additional options which affect ContextMenu construction
* @property {HTMLElement} [options.container] - A parent HTMLElement which contains the selector target
* @property {string} [options.hookName] - The hook name
* @property {boolean} [options.parentClassHooks=true] - Whether to call hooks for the parent classes in the inheritance chain.
*
* @typedef {Object} TagOption
* @property {string} label
@ -24,11 +32,21 @@ import { tagifyElement } from '../../../helpers/utils.mjs';
*
* @typedef {Object} TagifyOptions
* @property {number} [maxTags] - Maximum number of allowed tags
*
* @typedef {import("@client/applications/api/handlebars-application.mjs").HandlebarsRenderOptions} HandlebarsRenderOptions
* @typedef {foundry.applications.types.ApplicationConfiguration & HandlebarsRenderOptions & { dragDrop?: DragDropConfig[], tagifyConfigs?: TagifyConfig[] }} DHSheetV2Configuration
*/
/**
* @typedef {import("@client/applications/api/handlebars-application.mjs").HandlebarsRenderOptions} HandlebarsRenderOptions
* @typedef {foundry.applications.types.ApplicationConfiguration} FoundryAppConfig
*
* @typedef {FoundryAppConfig & HandlebarsRenderOptions & {
* dragDrop?: DragDropConfig[],
* tagifyConfigs?: TagifyConfig[],
* contextMenus?: ContextMenuConfig[],
* }} DHSheetV2Configuration
*/
/**
* @template {Constructor<foundry.applications.api.DocumentSheet>} BaseDocumentSheet
* @param {BaseDocumentSheet} Base - The base class to extend.
@ -54,15 +72,12 @@ export default function DHApplicationMixin(Base) {
*/
static DEFAULT_OPTIONS = {
classes: ['daggerheart', 'sheet', 'dh-style'],
position: {
width: 480,
height: 'auto'
},
actions: {
addEffect: DHSheetV2.#addEffect,
editEffect: DHSheetV2.#editEffect,
removeEffect: DHSheetV2.#removeEffect
createDoc: DHSheetV2.#createDoc,
editDoc: DHSheetV2.#editDoc,
deleteDoc: DHSheetV2.#deleteDoc
},
contextMenus: [],
dragDrop: [],
tagifyConfigs: []
};
@ -74,6 +89,11 @@ export default function DHApplicationMixin(Base) {
super._attachPartListeners(partId, htmlElement, options);
this._dragDrop.forEach(d => d.bind(htmlElement));
}
/**@inheritdoc */
async _onFirstRender(context, options) {
await super._onFirstRender(context, options);
if (!!this.options.contextMenus.length) this._createContextMenus();
}
/**@inheritdoc */
async _onRender(context, options) {
@ -81,6 +101,10 @@ export default function DHApplicationMixin(Base) {
this._createTagifyElements(this.options.tagifyConfigs);
}
/* -------------------------------------------- */
/* Tags */
/* -------------------------------------------- */
/**
* Creates Tagify elements from configuration objects
* @param {TagifyConfig[]} tagConfigs - Array of Tagify configuration objects
@ -140,32 +164,50 @@ export default function DHApplicationMixin(Base) {
* @param {DragEvent} event
* @protected
*/
_onDragStart(event) {}
_onDragStart(event) { }
/**
* Handle drop event.
* @param {DragEvent} event
* @protected
*/
_onDrop(event) {}
_onDrop(event) { }
/* -------------------------------------------- */
/* Context Menu */
/* -------------------------------------------- */
_createContextMenus() {
for (const config of this.options.contextMenus) {
const { handler, selector, options } = config;
this._createContextMenu(handler.bind(this), selector, options);
}
}
/* -------------------------------------------- */
/**
* Get the set of ContextMenu options which should be used for journal entry pages in the sidebar.
* @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]}
* @protected
*/
_getEntryContextOptions() {
return [];
}
/* -------------------------------------------- */
/* Prepare Context */
/* -------------------------------------------- */
/**
* Prepare the template context.
* @param {object} options
* @param {string} [objectPath='document']
* @returns {Promise<object>}
* @inheritdoc
*/
async _prepareContext(options, objectPath = 'document') {
/**@inheritdoc*/
async _prepareContext(options) {
const context = await super._prepareContext(options);
context.config = CONFIG.DH;
context.source = this[objectPath];
context.fields = this[objectPath].schema.fields;
context.systemFields = this[objectPath].system ? this[objectPath].system.schema.fields : {};
context.source = this.document;
context.fields = this.document.schema.fields;
context.systemFields = this.document.system.schema.fields;
return context;
}
@ -174,38 +216,44 @@ export default function DHApplicationMixin(Base) {
/* -------------------------------------------- */
/**
* Renders an ActiveEffect's sheet sheet.
* Create an embedded document.
* @param {PointerEvent} event - The originating click event
* @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeAction"]
*/
static async #addEffect() {
const cls = foundry.documents.ActiveEffect;
await cls.create(
{
name: game.i18n.format('DOCUMENT.New', { type: game.i18n.localize(cls.metadata.label) })
},
{ parent: this.document }
);
static async #createDoc(event, button) {
const { type } = button.dataset;
const operation = {
parent: this.document,
pack: this.document.pack,
renderSheet: !event.shiftKey,
}
const cls = getDocumentClass(type);
return await cls.createDocuments([{
name: cls.defaultName(operation)
}], operation);
}
/**
* Renders an ActiveEffect's sheet sheet.
* Renders an embedded document.
* @param {PointerEvent} event - The originating click event
* @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeAction"]
*/
static async #editEffect(_event, button) {
const effect = this.document.effects.get(button.dataset.effect);
effect.sheet.render({ force: true });
static #editDoc(_event, button) {
const { type, docId } = button.dataset;
this.document.getEmbeddedDocument(type, docId, { strict: true }).sheet.render({ force: true });
}
/**
* Delete an ActiveEffect from the item.
* Delete an embedded document.
* @param {PointerEvent} _event - The originating click event
* @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeAction"]
*/
static async #removeEffect(_event, button) {
await this.document.effects.get(button.dataset.effect).delete();
static async #deleteDoc(_event, button) {
const { type, docId } = button.dataset;
await this.document.getEmbeddedDocument(type, docId, { strict: true }).delete();
}
}
return DHSheetV2;

View file

@ -0,0 +1,30 @@
import DHApplicationMixin from './application-mixin.mjs';
const { ActorSheetV2 } = foundry.applications.sheets;
/**
* A base actor sheet extending {@link ActorSheetV2} via {@link DHApplicationMixin}
* @extends ActorSheetV2
* @mixes DHSheetV2
*/
export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
/** @inheritDoc */
static DEFAULT_OPTIONS = {
classes: ['actor'],
position: {
width: 480,
},
form: {
submitOnChange: true
},
actions: {},
dragDrop: []
};
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.isNPC = this.document.isNPC;
return context;
}
}