From 5ac67a8714e3d666443e66ea028082c39bd7b2a0 Mon Sep 17 00:00:00 2001 From: Joaquin Pereyra Date: Thu, 17 Jul 2025 19:22:15 -0300 Subject: [PATCH] FEAT: add enritch on inventory-item description FEAT: add extensible behavior on inventory-item-content FEAT: add fade effect on item-img to roll-itmg --- .../sheets/api/application-mixin.mjs | 67 ++++++ styles/less/global/inventory-item.less | 193 ++++++++++++------ templates/sheets/actors/adversary/sidebar.hbs | 1 + templates/sheets/actors/character/sidebar.hbs | 2 + .../global/partials/domain-card-item.hbs | 2 +- .../global/partials/inventory-item-V2.hbs | 143 ++++++------- 6 files changed, 274 insertions(+), 134 deletions(-) diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 3c177241..9aeb9b69 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -84,6 +84,7 @@ export default function DHApplicationMixin(Base) { useItem: DHSheetV2.#useItem, useAction: DHSheetV2.#useAction, toggleEffect: DHSheetV2.#toggleEffect, + toggleExtended: DHSheetV2.#toggleExtended, }, contextMenus: [{ handler: DHSheetV2.#getEffectContextOptions, @@ -124,6 +125,27 @@ export default function DHApplicationMixin(Base) { this._createTagifyElements(this.options.tagifyConfigs); } + /* -------------------------------------------- */ + /* Sync Parts */ + /* -------------------------------------------- */ + + /**@inheritdoc */ + _syncPartState(partId, newElement, priorElement, state) { + super._syncPartState(partId, newElement, priorElement, state); + for (const el of priorElement.querySelectorAll(".extensible.extended")) { + const { actionId, itemUuid } = el.parentElement.dataset; + const selector = `${actionId ? `[data-action-id="${actionId}"]` : `[data-item-uuid="${itemUuid}"]`} .extensible`; + const newExtensible = newElement.querySelector(selector); + + if (!newExtensible) continue; + newExtensible.classList.add("extended"); + const descriptionElement = newExtensible.querySelector('.invetory-description'); + if (descriptionElement) { + this.#prepareInventoryDescription(newExtensible, descriptionElement); + } + } + } + /* -------------------------------------------- */ /* Tags */ /* -------------------------------------------- */ @@ -354,6 +376,37 @@ export default function DHApplicationMixin(Base) { return context; } + /* -------------------------------------------- */ + /* Prepare Descriptions */ + /* -------------------------------------------- */ + + /** + * Prepares and enriches an inventory item or action description for display. + * @param {HTMLElement} extensibleElement - The parent element containing the description. + * @param {HTMLElement} descriptionElement - The element where the enriched description will be rendered. + * @returns {Promise} + */ + async #prepareInventoryDescription(extensibleElement, descriptionElement) { + const parent = extensibleElement.closest('[data-item-uuid], [data-action-id]'); + const { actionId, itemUuid } = parent?.dataset || {}; + if (!actionId && !itemUuid) return; + + const doc = itemUuid + ? getDocFromElement(extensibleElement) + : this.document.system.attack?.id === actionId + ? this.document.system.attack + : this.document.system.actions?.find(a => a.id === actionId); + if (!doc) return; + + const description = doc.system?.description ?? doc.description; + const isAction = !!actionId; + descriptionElement.innerHTML = await foundry.applications.ux.TextEditor.implementation.enrichHTML(description, { + relativeTo: isAction ? doc.parent : doc, + rollData: doc.getRollData(), + secrets: isAction ? doc.parent.isOwner : doc.isOwner + }); + } + /* -------------------------------------------- */ /* Application Clicks Actions */ /* -------------------------------------------- */ @@ -526,6 +579,20 @@ export default function DHApplicationMixin(Base) { return CONFIG.ux.ContextMenu.triggerContextMenu(event); } + /** + * Toggle the 'extended' class on the .extensible element inside inventory-item-content + * @type {ApplicationClickAction} + * @this {DHSheetV2} + */ + static async #toggleExtended(_, target) { + const container = target.closest('.inventory-item'); + const extensible = container?.querySelector('.extensible'); + const t = extensible?.classList.toggle('extended'); + + const descriptionElement = extensible?.querySelector('.invetory-description'); + if (t && !!descriptionElement) this.#prepareInventoryDescription(extensible, descriptionElement); + } + } return DHSheetV2; diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index 30fe920c..1775be24 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -12,87 +12,151 @@ } } +.appTheme({}, { + .inventory-item-header .img-portait .roll-img { + filter: invert(1); + } +}); + .application.daggerheart.dh-style { .inventory-item { - display: grid; - grid-template-columns: 40px 1fr 60px; - gap: 10px; width: 100%; - .item-img { - height: 40px; - width: 40px; - border-radius: 3px; - border: none; - cursor: pointer; - object-fit: cover; - - &.actor-img { - border-radius: 50%; - } - } - - .item-label-wrapper { - display: grid; - grid-template-columns: 1fr 60px; - } - - .item-label { - font-family: @font-body; - align-self: center; - - &.fullWidth { - grid-column: span 2; - } - - .item-name { - font-size: 14px; - } - - .item-tags, - .item-labels { - display: flex; - gap: 10px; - - .tag { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 3px 5px; - font-size: 12px; - - background: light-dark(@dark-15, @beige-15); - border: 1px solid light-dark(@dark, @beige); - border-radius: 3px; + &:hover { + .inventory-item-header .img-portait { + .roll-img { + opacity: 1; } - - .label { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - font-size: 12px; - gap: 4px; + .item-img { + opacity: 0; } } } - .controls { + .inventory-item-header { display: flex; align-items: center; - justify-content: end; - gap: 8px; + gap: 10px; + cursor: pointer; - a { - text-align: center; + .img-portait { + flex: 0 0 40px; + height: 40px; + cursor: pointer; + position: relative; - &.unequipped { - opacity: 0.4; + .item-img, + .roll-img { + position: absolute; + transition: opacity 300ms ease-in; + } + + .roll-img { + opacity: 0; + } + } + + .item-label { + flex: 1; + font-family: @font-body; + align-self: center; + + .item-name { + font-size: 14px; + } + + .item-tags, + .item-labels { + display: flex; + gap: 10px; + + .tag, + .label { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font-size: 12px; + } + + .tag { + padding: 3px 5px; + background: light-dark(@dark-15, @beige-15); + border: 1px solid light-dark(@dark, @beige); + border-radius: 3px; + } + + .label { + gap: 4px; + } + } + } + + .item-resource { + flex: 0 0 60px; + display: flex; + align-items: center; + gap: 4px; + } + .controls { + flex: 0 0 auto; + display: flex; + align-items: center; + justify-content: end; + gap: 8px; + } + } + + .inventory-item-content { + &.extensible { + max-height: 0; + overflow: hidden; + transition: max-height 2s linear; + &.extended { + max-height: 1000px; // Reasonable large value + //maybe need the redo this.... idk, i'm just a little wittle girl, atte: JP. + } + } + .item-resources { + display: flex; + align-items: center; + gap: 4px; + .item-dice-resource { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 26px; + + label, + i { + position: absolute; + z-index: 2; + cursor: pointer; + } + + label { + color: light-dark(white, black); + filter: drop-shadow(0 0 1px light-dark(@dark-blue, @golden)); + font-size: 18px; + } + + img { + filter: brightness(0) saturate(100%) invert(97%) sepia(7%) saturate(580%) hue-rotate(332deg) + brightness(96%) contrast(95%); + } + + i { + text-shadow: 0 0 3px white; + filter: drop-shadow(0 1px white); + color: black; + font-size: 26px; + } } } } } + .card-item { position: relative; height: 120px; @@ -212,6 +276,7 @@ input { flex: 1; + text-align: center; } .item-dice-resource { diff --git a/templates/sheets/actors/adversary/sidebar.hbs b/templates/sheets/actors/adversary/sidebar.hbs index ef13efd4..d1c0467e 100644 --- a/templates/sheets/actors/adversary/sidebar.hbs +++ b/templates/sheets/actors/adversary/sidebar.hbs @@ -85,6 +85,7 @@ hideDescription=true hideTooltip=true hideResources=true + noExtensible=true }} diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index f5109d72..cff3b755 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -89,6 +89,7 @@ hideTags=true hideDescription=true hideResources=true + noExtensible=true }} {{/if}} {{/each}} @@ -108,6 +109,7 @@ hideTags=true hideDescription=true hideResources=true + noExtensible=true }} {{/each}} diff --git a/templates/sheets/global/partials/domain-card-item.hbs b/templates/sheets/global/partials/domain-card-item.hbs index beeb41b8..37d6a0e2 100644 --- a/templates/sheets/global/partials/domain-card-item.hbs +++ b/templates/sheets/global/partials/domain-card-item.hbs @@ -1,4 +1,4 @@ -
  • +
  • - {{!-- Image --}} - +
    + {{!-- Image --}} +
    + + +
    -
    {{!-- Name & Tags --}}
    @@ -155,6 +159,8 @@ Parameters: {{/if}} {{!-- Action Block End --}}
    + + {{!-- Simple Resource --}} {{#if (and (not hideResources) (eq item.system.resource.type 'simple'))}} {{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}} {{/if}} @@ -163,72 +169,71 @@ Parameters:
    {{/if}} -
    - {{!-- Controls --}} - {{#unless hideControls}} -
    - {{#if isActor}} - - - - {{#if (eq type 'adversary')}} - - - + {{!-- Controls --}} + {{#unless hideControls}} +
    + {{#if isActor}} + + + + {{#if (eq type 'adversary')}} + + + + {{/if}} + {{else}} + {{#if (eq type 'weapon')}} + + + + {{else if (eq type 'armor')}} + + + + {{else if (eq type 'domainCard')}} + + + + {{else if (eq type 'effect')}} + + + + {{/if}} + {{#if (hasProperty item "toChat")}} + + + + {{/if}} + + + + {{/if}} +
    + {{/unless}} +
    +
    + {{!-- Description --}} + {{#unless hideDescription}} +
    + {{/unless}} + {{!-- Dice Resource --}} + {{#if (and (not hideResources) (eq item.system.resource.type 'diceValue'))}} + {{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}} {{/if}} - {{else}} - {{#if (eq type 'weapon')}} - - - - {{else if (eq type 'armor')}} - - - - {{else if (eq type 'domainCard')}} - - - - {{else if (eq type 'effect')}} - - - - {{/if}} - {{#if (hasProperty item "toChat")}} - - - - {{/if}} - - - + {{!-- Actions Buttons --}} + {{#if (and showActions (eq item.type 'feature'))}} +
    + {{#each item.system.actions as | action |}} + + {{/each}} +
    {{/if}}
    - {{else}} - - {{/unless}} - - {{!-- Description --}} - {{#unless hideDescription}} -
    - {{{item.system.description}}} -
    - {{/unless}} - {{#if (and (not hideResources) (eq item.system.resource.type 'diceValue'))}} - {{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}} - {{/if}} - {{#if (and showActions (eq item.type 'feature'))}} -
    - {{#each item.system.actions as | action |}} - - {{/each}} -
    - {{/if}}
  • \ No newline at end of file