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
This commit is contained in:
Joaquin Pereyra 2025-07-17 19:22:15 -03:00
parent aee8753f63
commit 5ac67a8714
6 changed files with 274 additions and 134 deletions

View file

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

View file

@ -12,39 +12,55 @@
}
}
.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%;
&:hover {
.inventory-item-header .img-portait {
.roll-img {
opacity: 1;
}
.item-img {
height: 40px;
width: 40px;
border-radius: 3px;
border: none;
opacity: 0;
}
}
}
.inventory-item-header {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
object-fit: cover;
&.actor-img {
border-radius: 50%;
}
.img-portait {
flex: 0 0 40px;
height: 40px;
cursor: pointer;
position: relative;
.item-img,
.roll-img {
position: absolute;
transition: opacity 300ms ease-in;
}
.item-label-wrapper {
display: grid;
grid-template-columns: 1fr 60px;
.roll-img {
opacity: 0;
}
}
.item-label {
flex: 1;
font-family: @font-body;
align-self: center;
&.fullWidth {
grid-column: span 2;
}
.item-name {
font-size: 14px;
}
@ -54,45 +70,93 @@
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;
}
.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;
}
}
a {
text-align: center;
.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;
&.unequipped {
opacity: 0.4;
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 {

View file

@ -85,6 +85,7 @@
hideDescription=true
hideTooltip=true
hideResources=true
noExtensible=true
}}
</ul>
</div>

View file

@ -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}}

View file

@ -1,4 +1,4 @@
<li class="card-item" data-item-id="{{item.id}}">
<li class="card-item" data-item-uuid="{{item.uuid}}">
<img src="{{item.img}}" data-action="useItem" class="card-img" />
<div class="card-label">
<div

View file

@ -5,6 +5,7 @@ Parameters:
- type {string} : The type of items in the list
- isActor {boolean} : Passed through to inventory-item partials.
- categoryAdversary {string} : Category adversary id.
- noExtensible {boolean} : If true, the inventory-item-content would be collapsable/extendible else it always be showed
- hideLabels {boolean} : If true, hide label-tags else show label-tags.
- hideTags {boolean} : If true, hide simple-tags else show simple-tags.
- hideTooltip {boolean} : If true, disables the tooltip on the item image.
@ -16,12 +17,15 @@ Parameters:
<li class="inventory-item" {{#if (eq type 'action' )}}data-action-id="{{item.id}}" {{/if}}
data-item-uuid="{{item.uuid}}" data-type="{{type}}" draggable="true">
<div class="inventory-item-header" {{#unless noExtensible}}data-action="toggleExtended" {{/unless}}>
{{!-- Image --}}
<div class="img-portait">
<img src="{{item.img}}" class="item-img {{#if isActor}}actor-img{{/if}}"
data-action='{{ifThen (hasProperty item "use") "useItem" (ifThen (hasProperty item "toChat") "toChat" "editDoc") }}'
{{#unless hideTooltip}}data-tooltip="#item#{{item.uuid}}" {{/unless}} />
<img class="roll-img" src="systems/daggerheart/assets/icons/dice/default/d20.svg" alt="">
</div>
<div class="item-label-wrapper">
{{!-- Name & Tags --}}
<div class="item-label {{#if hideResources}}fullWidth{{/if}}">
@ -155,6 +159,8 @@ Parameters:
{{/if}}
{{!-- Action Block End --}}
</div>
{{!-- Simple Resource --}}
{{#if (and (not hideResources) (eq item.system.resource.type 'simple'))}}
{{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}}
{{/if}}
@ -163,7 +169,6 @@ Parameters:
<input type="number" class="inventory-item-quantity" value="{{item.system.quantity}}" step="1" />
</div>
{{/if}}
</div>
{{!-- Controls --}}
{{#unless hideControls}}
@ -209,19 +214,18 @@ Parameters:
</a>
{{/if}}
</div>
{{else}}
<span></span>
{{/unless}}
</div>
<div class="inventory-item-content{{#unless noExtensible}} extensible{{/unless}}">
{{!-- Description --}}
{{#unless hideDescription}}
<div class="item-description">
{{{item.system.description}}}
</div>
<div class="invetory-description"></div>
{{/unless}}
{{!-- Dice Resource --}}
{{#if (and (not hideResources) (eq item.system.resource.type 'diceValue'))}}
{{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}}
{{/if}}
{{!-- Actions Buttons --}}
{{#if (and showActions (eq item.type 'feature'))}}
<div class="item-buttons">
{{#each item.system.actions as | action |}}
@ -231,4 +235,5 @@ Parameters:
{{/each}}
</div>
{{/if}}
</div>
</li>