diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 553a1a17..4ffcc64d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -37,6 +37,7 @@ jobs: url: https://github.com/${{github.repository}} manifest: https://raw.githubusercontent.com/${{github.repository}}/v14/system.json download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip + flags.hotReload: false # Create a zip file with all files required by the module to add to the release - run: zip -r ./system.zip system.json README.md LICENSE build/daggerheart.js build/tagify.css styles/daggerheart.css assets/ templates/ packs/ lang/ diff --git a/.gitignore b/.gitignore index 9a22c0ce..e41a67d3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ Build build foundry styles/daggerheart.css +styles/daggerheart.css.map diff --git a/assets/parchments/dh-parchment-button-dark.png b/assets/parchments/dh-parchment-button-dark.png new file mode 100644 index 00000000..39dd76b3 Binary files /dev/null and b/assets/parchments/dh-parchment-button-dark.png differ diff --git a/gulpfile.js b/gulpfile.js index 1a81f5ae..2e873ced 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,9 +1,15 @@ // Less configuration var gulp = require('gulp'); var less = require('gulp-less'); +var sourcemaps = require('gulp-sourcemaps'); gulp.task('less', function (cb) { - gulp.src('styles/daggerheart.less').pipe(less()).on('error', console.error.bind(console)).pipe(gulp.dest('styles')); + gulp.src('styles/daggerheart.less') + .pipe(sourcemaps.init()) + .pipe(less()) + .on('error', console.error.bind(console)) + .pipe(sourcemaps.write('.')) + .pipe(gulp.dest('styles')); cb(); }); diff --git a/lang/en.json b/lang/en.json index 20c66a32..a06c46c2 100755 --- a/lang/en.json +++ b/lang/en.json @@ -406,7 +406,11 @@ "giveSpotlight": "Give The Spotlight", "requestingSpotlight": "Requesting The Spotlight", "requestSpotlight": "Request The Spotlight", - "openCountdowns": "Countdowns" + "openCountdowns": "Countdowns", + "adversaryCategories": { + "friendly": "Friendly", + "adversaries": "Adversaries" + } }, "CompendiumBrowserSettings": { "title": "Enable Compendiums", @@ -774,7 +778,9 @@ "title": "Group Roll" }, "TokenConfig": { - "actorSizeUsed": "Actor size is set, determining the dimensions" + "actorSizeUsed": "Actor size is set, determining the dimensions", + "tokenSize": "Token Size", + "sizeCategory": "Size Category" } }, "CLASS": { @@ -2561,10 +2567,11 @@ "tokenImg": { "label": "Token Image" }, "tokenRingImg": { "label": "Subject Texture" }, "tokenSize": { - "placeholder": "Using character dimensions", - "disabledPlaceholder": "Set by character size", + "placeholder": "Token Size", + "disabledPlaceholder": "Token Size", "height": { "label": "Height" }, "width": { "label": "Width" }, + "depth": { "label": "Depth" }, "scale": { "label": "Token Scale" } }, "evolved": { diff --git a/module/applications/dialogs/CompendiumBrowserSettings.mjs b/module/applications/dialogs/CompendiumBrowserSettings.mjs index bef54a6f..b0d83fb3 100644 --- a/module/applications/dialogs/CompendiumBrowserSettings.mjs +++ b/module/applications/dialogs/CompendiumBrowserSettings.mjs @@ -50,7 +50,7 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi const excludedSourceData = this.browserSettings.excludedSources; const excludedPackData = this.browserSettings.excludedPacks; context.typePackCollections = game.packs.reduce((acc, pack) => { - const { type, label, packageType, packageName: basePackageName, id } = pack.metadata; + const { type, label, packageType, packageName: basePackageName, name, id } = pack.metadata; if (!CompendiumBrowserSettings.#browserPackTypes.includes(type)) return acc; const isWorldPack = packageType === 'world'; @@ -68,13 +68,15 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi if (!acc[type].sources[packageName]) acc[type].sources[packageName] = { label: sourceLabel, checked: sourceChecked, packs: [] }; - const checked = !excludedPackData[id] || !excludedPackData[id].excludedDocumentTypes.includes(type); + const included = + !excludedPackData[packageName] || + !excludedPackData[packageName][name]?.excludedDocumentTypes.includes(type); acc[type].sources[packageName].packs.push({ - pack: id, + name, type, label: id === game.system.id ? game.system.title : game.i18n.localize(label), - checked: checked + checked: included }); return acc; @@ -106,16 +108,16 @@ export default class CompendiumBrowserSettings extends HandlebarsApplicationMixi toggleTypedPack(event) { event.stopPropagation(); - const { type, pack } = event.target.dataset; - const currentlyExcluded = this.browserSettings.excludedPacks[pack] - ? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.includes(type) + const { type, source, packName } = event.target.dataset; + const currentlyExcluded = this.browserSettings.excludedPacks[source]?.[packName] + ? this.browserSettings.excludedPacks[source][packName].excludedDocumentTypes.includes(type) : false; - if (!this.browserSettings.excludedPacks[pack]) - this.browserSettings.excludedPacks[pack] = { excludedDocumentTypes: [] }; - this.browserSettings.excludedPacks[pack].excludedDocumentTypes = currentlyExcluded - ? this.browserSettings.excludedPacks[pack].excludedDocumentTypes.filter(x => x !== type) - : [...(this.browserSettings.excludedPacks[pack]?.excludedDocumentTypes ?? []), type]; + this.browserSettings.excludedPacks[source] ??= {}; + this.browserSettings.excludedPacks[source][packName] ??= { excludedDocumentTypes: [] }; + this.browserSettings.excludedPacks[source][packName].excludedDocumentTypes = currentlyExcluded + ? this.browserSettings.excludedPacks[source][packName].excludedDocumentTypes.filter(x => x !== type) + : [...(this.browserSettings.excludedPacks[source][packName]?.excludedDocumentTypes ?? []), type]; this.render(); } diff --git a/module/applications/dialogs/deathMove.mjs b/module/applications/dialogs/deathMove.mjs index 69ff758e..4a949b99 100644 --- a/module/applications/dialogs/deathMove.mjs +++ b/module/applications/dialogs/deathMove.mjs @@ -57,6 +57,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV let returnMessage = game.i18n.localize('DAGGERHEART.UI.Chat.deathMove.avoidScar'); if (config.roll.fate.value <= this.actor.system.levelData.level.current) { + const maxHope = this.actor.system.resources.hope.max + this.actor.system.scars; const newScarAmount = this.actor.system.scars + 1; await this.actor.update({ system: { @@ -64,7 +65,7 @@ export default class DhDeathMove extends HandlebarsApplicationMixin(ApplicationV } }); - if (newScarAmount >= this.actor.system.resources.hope.max) { + if (newScarAmount >= maxHope) { await this.actor.setDeathMoveDefeated(CONFIG.DH.GENERAL.defeatedConditionChoices.dead.id); return game.i18n.format('DAGGERHEART.UI.Chat.deathMove.journeysEnd', { scars: newScarAmount }); } diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index e06cbe48..ba76831f 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -38,6 +38,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio tag: 'form', classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'tag-team-dialog'], position: { width: 550, height: 'auto' }, + window: { + icon: 'fa-solid fa-user-group' + }, actions: { toggleSelectMember: TagTeamDialog.#toggleSelectMember, startTagTeamRoll: TagTeamDialog.#startTagTeamRoll, diff --git a/module/applications/hud/tokenHUD.mjs b/module/applications/hud/tokenHUD.mjs index 943f3506..671b01a1 100644 --- a/module/applications/hud/tokenHUD.mjs +++ b/module/applications/hud/tokenHUD.mjs @@ -124,7 +124,9 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD { const animationDuration = 500; const scene = game.scenes.get(game.user.viewedScene); /* getDependentTokens returns already removed tokens with id = null. Need to filter that until it's potentially fixed from Foundry */ - const activeTokens = actors.flatMap(member => member.getDependentTokens({ scenes: scene }).filter(x => x._id)); + const activeTokens = actors.flatMap(member => + member.getDependentTokens({ scenes: scene }).filter(x => x._id && !x._destroyed) + ); const { x: actorX, y: actorY } = this.document; if (activeTokens.length > 0) { for (let token of activeTokens) { diff --git a/module/applications/levelup/characterLevelup.mjs b/module/applications/levelup/characterLevelup.mjs index f7ef2ffa..e8d6cf1c 100644 --- a/module/applications/levelup/characterLevelup.mjs +++ b/module/applications/levelup/characterLevelup.mjs @@ -156,6 +156,7 @@ export default class DhCharacterLevelUp extends LevelUpBase { if (multiclasses?.[0]) { const data = multiclasses[0]; const multiclass = data.data.length > 0 ? await foundry.utils.fromUuid(data.data[0]) : {}; + const subclasses = (await multiclass?.system?.fetchSubclasses()) ?? []; context.multiclass = { ...data, @@ -175,13 +176,12 @@ export default class DhCharacterLevelUp extends LevelUpBase { alreadySelected }; }) ?? [], - subclasses: - multiclass?.system?.subclasses.map(subclass => ({ - ...subclass, - uuid: subclass.uuid, - selected: data.secondaryData.subclass === subclass.uuid, - disabled: data.secondaryData.subclass && data.secondaryData.subclass !== subclass.uuid - })) ?? [], + subclasses: subclasses.map(subclass => ({ + ...subclass, + uuid: subclass.uuid, + selected: data.secondaryData.subclass === subclass.uuid, + disabled: data.secondaryData.subclass && data.secondaryData.subclass !== subclass.uuid + })), compendium: 'classes', limit: 1 }; diff --git a/module/applications/settings/homebrewSettings.mjs b/module/applications/settings/homebrewSettings.mjs index 9f0b22c4..40ea0301 100644 --- a/module/applications/settings/homebrewSettings.mjs +++ b/module/applications/settings/homebrewSettings.mjs @@ -1,6 +1,5 @@ import { DhHomebrew } from '../../data/settings/_module.mjs'; import { Resource } from '../../data/settings/Homebrew.mjs'; -import { slugify } from '../../helpers/utils.mjs'; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; @@ -403,12 +402,12 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli const domainName = button.form.elements.domainName.value; if (!domainName) return; - const newSlug = slugify(domainName); + const newSlug = domainName.slugify(); const existingDomains = [ ...Object.values(this.settings.domains), ...Object.values(CONFIG.DH.DOMAIN.domains) ]; - if (existingDomains.find(x => slugify(game.i18n.localize(x.label)) === newSlug)) { + if (existingDomains.find(x => x.id === newSlug)) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.domains.duplicateDomain')); return; } @@ -529,7 +528,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli const identifier = button.form.elements.identifier.value; if (!identifier) return; - const sluggedIdentifier = slugify(identifier); + const sluggedIdentifier = identifier.slugify(); await this.settings.updateSource({ [`resources.${actorType}.resources.${sluggedIdentifier}`]: Resource.getDefaultResourceData(identifier) diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index f40c144a..5f6c854b 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -57,6 +57,14 @@ export default class CharacterSheet extends DHBaseActorSheet { } ], contextMenus: [ + { + handler: CharacterSheet.#getCreationMainContextOptions, + selector: '.character-details [data-action="editDoc"]', + options: { + parentClassHooks: false, + fixed: true + } + }, { handler: CharacterSheet.#getDomainCardContextOptions, selector: '[data-item-uuid][data-type="domainCard"]', @@ -319,6 +327,56 @@ export default class CharacterSheet extends DHBaseActorSheet { /* Context Menu */ /* -------------------------------------------- */ + static #getCreationMainContextOptions() { + /** Returns true if the item is managed by the level up wizard. Such items shouldn't allow things like manual removal */ + function isItemWizardManaged(item) { + const actor = item?.actor; + if (!actor) return false; + + // If levelup automation is off in general or for this character, all items are unmanaged + // This is disabled until we have proper granted feature removal, for now this feature is to correct errors + // const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; + // if (!levelupAuto) return false; + + // Core items aren't part of levelup data. TODO: add some way to flag a specific character as no auto leveling + const classPair = actor.system.class; + const coreItems = [actor.system.ancestry, actor.system.community, classPair?.value, classPair?.subclass]; + if (coreItems.includes(item)) return true; + + const levelups = Object.values(actor.system.levelData?.levelups) ?? []; + const uuid = item.uuid; + const sourceUuid = item._stats.compendiumSource; // on older characters this may be missing + return levelups.some(data => { + if (item.type === 'subclass') { + const selectedSubclasses = data.selections.map(s => s.secondaryData?.subclass).filter(s => !!s); + return sourceUuid + ? selectedSubclasses.includes(sourceUuid) + : selectedSubclasses.length && item.system.isMulticlass; + } + + const matchesCard = data.achievements.domainCards.some(i => i.itemUuid === uuid); + const matchesSelection = data.selections.some(s => s.itemUuid === uuid); + return matchesCard || matchesSelection; + }); + } + + return [ + { + label: 'CONTROLS.CommonDelete', + icon: 'fa-solid fa-trash', + visible: target => { + const doc = getDocFromElementSync(target); + return doc?.isOwner && !isItemWizardManaged(doc); + }, + callback: async (target, event) => { + const doc = await getDocFromElement(target); + if (event.shiftKey) return doc.delete(); + else return doc.deleteDialog(); + } + } + ]; + } + /** * Get the set of ContextMenu options for DomainCards. * @returns {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} - The Array of context options passed to the ContextMenu instance @@ -718,7 +776,7 @@ export default class CharacterSheet extends DHBaseActorSheet { ? { 'system.linkedClass.uuid': { key: 'system.linkedClass.uuid', - value: this.document.system.class.value._stats.compendiumSource + value: this.document.system.class.value?._stats.compendiumSource } } : undefined, diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs index 403960c0..cec1e1f0 100644 --- a/module/applications/sheets/actors/party.mjs +++ b/module/applications/sheets/actors/party.mjs @@ -26,7 +26,6 @@ export default class Party extends DHBaseActorSheet { actions: { openDocument: Party.#openDocument, deletePartyMember: Party.#deletePartyMember, - deleteItem: Party.#deleteItem, toggleHope: Party.#toggleHope, toggleHitPoints: Party.#toggleHitPoints, toggleStress: Party.#toggleStress, @@ -44,7 +43,10 @@ export default class Party extends DHBaseActorSheet { static PARTS = { header: { template: 'systems/daggerheart/templates/sheets/actors/party/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, - partyMembers: { template: 'systems/daggerheart/templates/sheets/actors/party/party-members.hbs' }, + partyMembers: { + template: 'systems/daggerheart/templates/sheets/actors/party/party-members.hbs', + scrollable: [''] + }, /* NOT YET IMPLEMENTED */ // projects: { // template: 'systems/daggerheart/templates/sheets/actors/party/projects.hbs', @@ -506,23 +508,4 @@ export default class Party extends DHBaseActorSheet { const newMembersList = currentMembers.filter(uuid => uuid !== doc.uuid); await this.document.update({ 'system.partyMembers': newMembersList }); } - - static async #deleteItem(event, target) { - const doc = await getDocFromElement(target.closest('.inventory-item')); - if (!event.shiftKey) { - const confirmed = await foundry.applications.api.DialogV2.confirm({ - window: { - title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', { - type: game.i18n.localize('TYPES.Actor.party'), - name: doc.name - }) - }, - content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: doc.name }) - }); - - if (!confirmed) return; - } - - this.document.deleteEmbeddedDocuments('Item', [doc.id]); - } } diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 36477821..c79db99b 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -89,7 +89,7 @@ export default function DHApplicationMixin(Base) { classes: ['daggerheart', 'sheet', 'dh-style'], actions: { triggerContextMenu: DHSheetV2.#triggerContextMenu, - createDoc: DHSheetV2.#createDoc, + createDoc: DHSheetV2.#onCreateDoc, editDoc: DHSheetV2.#editDoc, deleteDoc: DHSheetV2.#deleteDoc, toChat: DHSheetV2.#toChat, @@ -97,8 +97,8 @@ export default function DHApplicationMixin(Base) { viewItem: DHSheetV2.#viewItem, toggleEffect: DHSheetV2.#toggleEffect, toggleExtended: DHSheetV2.#toggleExtended, - addNewItem: DHSheetV2.#addNewItem, - browseItem: DHSheetV2.#browseItem, + addNewItem: DHSheetV2.#onAddNewItem, + browseItem: DHSheetV2.#onBrowseItem, editAttribution: DHSheetV2.#editAttribution }, contextMenus: [ @@ -639,7 +639,7 @@ export default function DHApplicationMixin(Base) { /* Application Clicks Actions */ /* -------------------------------------------- */ - static async #addNewItem(event, target) { + static async #onAddNewItem(event, target) { const createChoice = await foundry.applications.api.DialogV2.wait({ classes: ['dh-style', 'two-big-buttons'], buttons: [ @@ -658,11 +658,11 @@ export default function DHApplicationMixin(Base) { if (!createChoice) return; - if (createChoice === 'browse') return DHSheetV2.#browseItem.call(this, event, target); - else return DHSheetV2.#createDoc.call(this, event, target); + if (createChoice === 'browse') return DHSheetV2.#onBrowseItem.call(this, event, target); + else return DHSheetV2.#onCreateDoc.call(this, event, target); } - static async #browseItem(event, target) { + static async #onBrowseItem(_event, target) { const type = target.dataset.compendium ?? target.dataset.type; const presets = { @@ -713,7 +713,7 @@ export default function DHApplicationMixin(Base) { * Create an embedded document. * @type {ApplicationClickAction} */ - static async #createDoc(event, target) { + static async #onCreateDoc(event, target) { const { documentClass, type, inVault, disabled } = target.dataset; const parentIsItem = this.document.documentName === 'Item'; const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature'; @@ -725,7 +725,7 @@ export default function DHApplicationMixin(Base) { : null : this.document; - let systemData = null; + let systemData = {}; if (featureOnCharacter) { systemData = { originItemType: this.document.type, @@ -738,15 +738,18 @@ export default function DHApplicationMixin(Base) { const data = { name: cls.defaultName({ type, parent }), - type + type, + system: systemData }; - - if (systemData) data.system = systemData; - - if (inVault) data['system.inVault'] = true; if (disabled) data.disabled = true; - if (type === 'domainCard' && parent?.system.domains?.length) { - data.system.domain = parent.system.domains[0]; + + if (type === 'domainCard') { + if (parent?.system.domains?.length) data.system.domain = parent.system.domains[0]; + if (inVault) data.system.inVault = true; + } else if (type === 'weapon') { + // Passing an empty system object to weapon causes validation failure due to attack action initialization + // todo: determine why, fix it at its source, then remove this fallback + delete data.system; } const doc = await cls.create(data, { parent, renderSheet: !event.shiftKey }); diff --git a/module/applications/ui/combatTracker.mjs b/module/applications/ui/combatTracker.mjs index fb19a17e..0989bcb8 100644 --- a/module/applications/ui/combatTracker.mjs +++ b/module/applications/ui/combatTracker.mjs @@ -56,7 +56,9 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C async _prepareTrackerContext(context, options) { await super._prepareTrackerContext(context, options); - const adversaries = context.turns?.filter(x => x.isNPC) ?? []; + const npcs = context.turns?.filter(x => x.isNPC) ?? []; + const adversaries = npcs.filter(x => x.disposition !== CONST.TOKEN_DISPOSITIONS.FRIENDLY); + const friendlies = npcs.filter(x => x.disposition === CONST.TOKEN_DISPOSITIONS.FRIENDLY); const characters = context.turns?.filter(x => !x.isNPC) ?? []; const spotlightQueueEnabled = game.settings.get( CONFIG.DH.id, @@ -75,6 +77,7 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C Object.assign(context, { actionTokens: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).actionTokens, adversaries, + friendlies, allCharacters: characters, characters: characters.filter(x => !spotlightQueueEnabled || x.system.spotlight.requestOrderIndex == 0), spotlightRequests @@ -129,7 +132,8 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C active: index === combat.turn, canPing: combatant.sceneId === canvas.scene?.id && game.user.hasPermission('PING_CANVAS'), type: combatant.actor?.system?.type, - img: await this._getCombatantThumbnail(combatant) + img: await this._getCombatantThumbnail(combatant), + disposition: combatant.token.disposition }; turn.css = [turn.active ? 'active' : null, hidden ? 'hide' : null, isDefeated ? 'defeated' : null].filterJoin( diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 052564cc..76e2b399 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -21,10 +21,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application static DEFAULT_OPTIONS = { id: 'countdowns', tag: 'div', - classes: ['daggerheart', 'dh-style', 'countdowns', 'faded-ui'], + classes: ['daggerheart', 'dh-style', 'countdowns'], window: { icon: 'fa-solid fa-clock-rotate-left', - frame: true, + frame: false, title: 'DAGGERHEART.UI.Countdowns.title', positioned: false, resizable: false, @@ -62,20 +62,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application if (iconOnly) frame.classList.add('icon-only'); else frame.classList.remove('icon-only'); - const header = frame.querySelector('.window-header'); - header.querySelector('button[data-action="close"]').remove(); - header.querySelector('button[data-action="toggleControls"]').remove(); - - if (game.user.isGM) { - const editTooltip = game.i18n.localize('DAGGERHEART.APPLICATIONS.CountdownEdit.editTitle'); - const editButton = ``; - header.insertAdjacentHTML('beforeEnd', editButton); - } - - const minimizeTooltip = game.i18n.localize('DAGGERHEART.UI.Countdowns.toggleIconMode'); - const minimizeButton = ``; - header.insertAdjacentHTML('beforeEnd', minimizeButton); - return frame; } diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index 99b9a23d..d98cf2da 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -109,8 +109,8 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { CONFIG.DH.id, CONFIG.DH.FLAGS[`${this.compendiumBrowserTypeKey}`].position ); - options.position = userPresetPosition ?? ItemBrowser.DEFAULT_OPTIONS.position; + delete options.position.zIndex; if (!userPresetPosition) { const width = noFolder === true || lite === true ? 600 : 850; diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 77c178d6..68e325c2 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -249,9 +249,6 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { /** @inheritDoc */ _drawBar(number, bar, data) { - const val = Number(data.value); - const pct = Math.clamp(val, 0, data.max) / data.max; - // Determine sizing const { width, height } = this.document.getSize(); const s = canvas.dimensions.uiScale; @@ -259,17 +256,19 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { const bh = 8 * (this.document.height >= 2 ? 1.5 : 1) * s; // Determine the color to use - const fillColor = - number === 0 ? foundry.utils.Color.fromRGB([1, 0, 0]) : foundry.utils.Color.fromString('#0032b1'); + const Color = foundry.utils.Color; + const fillColor = number === 0 ? Color.fromRGB([1, 0, 0]) : Color.fromString('#0032b1'); + const emptyColor = Color.fromRGB([0, 0, 0]); - // Draw the bar - const widthUnit = bw / data.max; + // Draw the bar (accounting floating point numbers from bar animations) + const widthUnit = bw / Math.ceil(data.max); bar.clear().lineStyle(s, 0x000000, 1.0); - const sections = [...Array(data.max).keys()]; - for (let mark of sections) { + const sections = [...Array(Math.ceil(data.max)).keys()]; + for (const mark of sections) { const x = mark * widthUnit; - const marked = mark + 1 <= data.value; - const color = marked ? fillColor : foundry.utils.Color.fromRGB([0, 0, 0]); + const marked = mark < Math.ceil(data.value); + const remainder = mark === Math.ceil(data.value) - 1 ? data.value % 1 : 0; + const color = !marked ? emptyColor : remainder ? emptyColor.mix(fillColor, remainder) : fillColor; if (mark === 0 || mark === sections.length - 1) { bar.beginFill(color, marked ? 1.0 : 0.5).drawRect(x, 0, widthUnit, bh, 2 * s); // Would like drawRoundedRect, but it's very troublsome with the corners. Leaving for now. } else { diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 3e40c97b..ae5fa71b 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -70,6 +70,49 @@ export const typeConfig = { } ] }, + environments: { + columns: [ + { + key: 'system.tier', + label: 'DAGGERHEART.GENERAL.Tiers.singular' + }, + { + key: 'system.type', + label: 'DAGGERHEART.GENERAL.type', + format: type => { + if (!type) return '-'; + + return CONFIG.DH.ACTOR.environmentTypes[type].label; + } + } + ], + filters: [ + { + key: 'system.tier', + label: 'DAGGERHEART.GENERAL.Tiers.singular', + field: 'system.api.models.actors.DhEnvironment.schema.fields.tier' + }, + { + key: 'system.type', + label: 'DAGGERHEART.GENERAL.type', + field: 'system.api.models.actors.DhEnvironment.schema.fields.type' + }, + { + key: 'system.difficulty', + name: 'difficulty.min', + label: 'DAGGERHEART.UI.ItemBrowser.difficultyMin', + field: 'system.api.models.actors.DhEnvironment.schema.fields.difficulty', + operator: 'gte' + }, + { + key: 'system.difficulty', + name: 'difficulty.max', + label: 'DAGGERHEART.UI.ItemBrowser.difficultyMax', + field: 'system.api.models.actors.DhEnvironment.schema.fields.difficulty', + operator: 'lte' + } + ] + }, items: { columns: [ { @@ -400,10 +443,12 @@ export const typeConfig = { const list = []; for (const item of items.filter(item => item.system.linkedClass)) { const linkedClass = await foundry.utils.fromUuid(item.system.linkedClass); - list.push({ - value: linkedClass.uuid, - label: linkedClass.name - }); + if (linkedClass) { + list.push({ + value: linkedClass.uuid, + label: linkedClass.name + }); + } } return list.reduce((a, c) => { @@ -559,7 +604,8 @@ export const compendiumConfig = { id: 'environments', keys: ['environments'], label: 'DAGGERHEART.UI.ItemBrowser.folders.environments', - type: ['environment'] + type: ['environment'], + listType: 'environments' }, beastforms: { id: 'beastforms', diff --git a/module/data/activeEffect/beastformEffect.mjs b/module/data/activeEffect/beastformEffect.mjs index 128c0c52..0fbea122 100644 --- a/module/data/activeEffect/beastformEffect.mjs +++ b/module/data/activeEffect/beastformEffect.mjs @@ -35,6 +35,7 @@ export default class BeastformEffect extends BaseEffect { static migrateData(source) { if (!source.characterTokenData.tokenSize.height) source.characterTokenData.tokenSize.height = 1; if (!source.characterTokenData.tokenSize.width) source.characterTokenData.tokenSize.width = 1; + if (!source.characterTokenData.tokenSize.depth) source.characterTokenData.tokenSize.depth = 1; return super.migrateData(source); } @@ -52,7 +53,8 @@ export default class BeastformEffect extends BaseEffect { if (this.parent.parent.type === 'character') { const baseUpdate = { height: this.characterTokenData.tokenSize.height, - width: this.characterTokenData.tokenSize.width + width: this.characterTokenData.tokenSize.width, + depth: this.characterTokenData.tokenSize.depth }; const update = { ...baseUpdate, diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index a1cd13e8..10d53c13 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -577,6 +577,8 @@ export default class DhCharacter extends DhCreature { communityFeatures = [], classFeatures = [], subclassFeatures = [], + multiclassFeatures = [], + multiclassSubclassFeatures = [], companionFeatures = [], features = []; @@ -586,9 +588,9 @@ export default class DhCharacter extends DhCreature { } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.community.id) { communityFeatures.push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.class.id) { - classFeatures.push(item); + (item.system.multiclassOrigin ? multiclassFeatures : classFeatures).push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) { - subclassFeatures.push(item); + (item.system.multiclassOrigin ? multiclassSubclassFeatures : subclassFeatures).push(item); } else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.companion.id) { companionFeatures.push(item); } else if (item.type === 'feature' && !item.system.type) { @@ -617,6 +619,24 @@ export default class DhCharacter extends DhCreature { type: 'subclass', values: subclassFeatures }, + ...(multiclassFeatures.length + ? { + multiclassFeatures: { + title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} - ${this.multiclass.value?.name}`, + type: 'multiclass', + values: multiclassFeatures + } + } + : {}), + ...(multiclassSubclassFeatures.length + ? { + multiclassSubclassFeatures: { + title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} ${game.i18n.localize('TYPES.Item.subclass')} - ${this.multiclass.subclass?.name}`, + type: 'multiclassSubclass', + values: multiclassSubclassFeatures + } + } + : {}), companionFeatures: { title: game.i18n.localize('DAGGERHEART.ACTORS.Character.companionFeatures'), type: 'companion', @@ -840,12 +860,13 @@ export default class DhCharacter extends DhCreature { const newHopeMax = this.resources.hope.max + diff; const newHopeValue = Math.min(newHopeMax, this.resources.hope.value); if (newHopeValue != this.resources.hope.value) { - if (!changes.system.resources.hope) changes.system.resources.hope = { value: 0 }; - - changes.system.resources.hope = { - ...changes.system.resources.hope, - value: changes.system.resources.hope.value + newHopeValue - }; + changes.system = foundry.utils.mergeObject(changes.system ?? {}, { + resources: { + hope: { + value: (changes.system?.resources?.hope?.value ?? 0) + newHopeMax + } + } + }); } } diff --git a/module/data/compendiumBrowserSettings.mjs b/module/data/compendiumBrowserSettings.mjs index ea71c439..ed70c88f 100644 --- a/module/data/compendiumBrowserSettings.mjs +++ b/module/data/compendiumBrowserSettings.mjs @@ -11,11 +11,13 @@ export default class CompendiumBrowserSettings extends foundry.abstract.DataMode }) ), excludedPacks: new fields.TypedObjectField( - new fields.SchemaField({ - excludedDocumentTypes: new fields.ArrayField( - new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES }) - ) - }) + new fields.TypedObjectField( + new fields.SchemaField({ + excludedDocumentTypes: new fields.ArrayField( + new fields.StringField({ required: true, choices: CONST.SYSTEM_SPECIFIC_COMPENDIUM_TYPES }) + ) + }) + ) ) }; } @@ -28,7 +30,7 @@ export default class CompendiumBrowserSettings extends foundry.abstract.DataMode const excludedSourceData = this.excludedSources[packageName]; if (excludedSourceData && excludedSourceData.excludedDocumentTypes.includes(pack.metadata.type)) return true; - const excludedPackData = this.excludedPacks[item.pack]; + const excludedPackData = this.excludedPacks[packageName]?.[pack.metadata.name]; if (excludedPackData && excludedPackData.excludedDocumentTypes.includes(pack.metadata.type)) return true; return false; diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index b0e4847f..21c56f9a 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -141,16 +141,6 @@ export default class DHArmor extends AttachableItem { } } - _onUpdate(a, b, c) { - super._onUpdate(a, b, c); - - if (this.actor?.type === 'character') { - for (const party of this.actor.parties) { - party.render(); - } - } - } - /** @inheritDoc */ static migrateDocumentData(source) { if (!source.system.armor) { diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index d30d6046..ee9d9839 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -51,7 +51,8 @@ export default class DHBeastform extends BaseDataItem { }), scale: new fields.NumberField({ nullable: false, min: 0.2, max: 3, step: 0.05, initial: 1 }), height: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }), - width: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }) + width: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }), + depth: new fields.NumberField({ integer: true, min: 1, initial: null, nullable: true }) }), mainTrait: new fields.StringField({ required: true, @@ -192,7 +193,8 @@ export default class DHBeastform extends BaseDataItem { tokenSize: { scale: this.parent.parent.prototypeToken.texture.scaleX, height: this.parent.parent.prototypeToken.height, - width: this.parent.parent.prototypeToken.width + width: this.parent.parent.prototypeToken.width, + depth: this.parent.parent.prototypeToken.depth } }, advantageOn: this.advantageOn, @@ -211,10 +213,12 @@ export default class DHBeastform extends BaseDataItem { : null; const width = autoTokenSize ?? this.tokenSize.width; const height = autoTokenSize ?? this.tokenSize.height; + const depth = autoTokenSize ?? this.tokenSize.depth; const prototypeTokenUpdate = { height, width, + depth, texture: { src: this.tokenImg, scaleX: this.tokenSize.scale, diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 12d85c1e..ecf72de3 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -56,38 +56,30 @@ export default class DHSubclass extends BaseDataItem { if (allowed === false) return; if (this.actor?.type === 'character') { - const dataUuid = data.uuid ?? data._stats.compendiumSource ?? `Item.${data._id}`; - if (this.actor.system.class.subclass) { - if (this.actor.system.multiclass.subclass) { - ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent')); - return false; - } else { - const multiclass = this.actor.items.find(x => x.type === 'class' && x.system.isMulticlass); - if (!multiclass) { - ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingMulticlass')); - return false; - } + const { value: actorClass, subclass: existingSubclass } = this.actor.system.class; + const { value: multiclass, subclass: existingMultisubclass } = this.actor.system.multiclass; + if (!actorClass && !multiclass) { + ui.notifications.warn('DAGGERHEART.UI.Notifications.missingClass', { localize: true }); + return false; + } + if (existingSubclass && existingMultisubclass) { + ui.notifications.warn('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent', { localize: true }); + return false; + } + if (existingSubclass && !multiclass) { + ui.notifications.warn('DAGGERHEART.UI.Notifications.missingMulticlass', { localize: true }); + return false; + } - if (multiclass.system.subclasses.every(x => x.uuid !== dataUuid)) { - ui.notifications.error( - game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInMulticlass') - ); - return false; - } - - await this.updateSource({ isMulticlass: true }); - } - } else { - const actorClass = this.actor.items.find(x => x.type === 'class' && !x.system.isMulticlass); - if (!actorClass) { - ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass')); - return false; - } - - if ((await actorClass.system.fetchSubclasses()).every(x => x.uuid !== dataUuid)) { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass')); - return false; - } + const match = [multiclass, actorClass].find( + c => c && (c._stats.compendiumSource ?? c.uuid) === this.linkedClass + ); + if (!match) { + const key = multiclass ? 'subclassNotInMulticlass' : 'subclassNotInClass'; + ui.notifications.warn(`DAGGERHEART.UI.Notifications.${key}`, { localize: true }); + return false; + } else if (match.system.isMulticlass) { + await this.updateSource({ isMulticlass: true }); } } } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 5df87b6c..e4c11a5c 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -112,10 +112,22 @@ export default class DhpActor extends Actor { this.updateSource(update); } + /** Perform a render, debounced in order to prevent overloading repeat render requests */ + renderDebounced = foundry.utils.debounce(options => { + return this.render(options); + }, 10); + + _onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId) { + super._onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId); + for (const party of this.parties) { + party.renderDebounced({ parts: ['partyMembers'] }); + } + } + _onUpdate(changes, options, userId) { super._onUpdate(changes, options, userId); for (const party of this.parties) { - party.render({ parts: ['partyMembers'] }); + party.renderDebounced({ parts: ['partyMembers'] }); } } @@ -134,17 +146,20 @@ export default class DhpActor extends Actor { _onDelete(options, userId) { super._onDelete(options, userId); for (const party of this.parties) { - party.render({ parts: ['partyMembers'] }); + party.renderDebounced({ parts: ['partyMembers'] }); } } async updateLevel(newLevel) { if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return; + const tiers = Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers); + const maxLevel = tiers.reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); + const multiclassMinLevel = Math.min( + maxLevel, + ...tiers.filter(t => t.options.multiclass).map(t => t.levels.start) + ); if (newLevel > this.system.levelData.level.current) { - const maxLevel = Object.values( - game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers - ).reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); if (newLevel > maxLevel) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.tooHighLevel')); } @@ -219,18 +234,19 @@ export default class DhpActor extends Actor { this.system.multiclass.subclass.update({ 'system.featureState': subclassFeatureState.multiclass }); } - if (multiclass) { - const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid); - const multiclassFeatures = this.items.filter( - x => x.system.originItemType === 'class' && x.system.multiclassOrigin - ); - const subclassFeatures = this.items.filter( - x => x.system.originItemType === 'subclass' && x.system.multiclassOrigin + // Remove multiclass if we're removing a multiclass feature or if we're below the multiclass minimum level + // Multclasses cannot be manually removed on the sheet, so this allows recovering in the case of errors + if (multiclass || newLevel < multiclassMinLevel) { + const multiclassItems = this.items.filter( + x => + x.uuid === multiclass?.itemUuid || + x.system.isMulticlass || + (['class', 'subclass'].includes(x.system.originItemType) && x.system.multiclassOrigin) ); this.deleteEmbeddedDocuments( 'Item', - [multiclassItem, ...multiclassFeatures, ...subclassFeatures].map(x => x.id) + multiclassItems.map(x => x.id) ); this.update({ @@ -269,6 +285,7 @@ export default class DhpActor extends Actor { async levelUp(levelupData) { const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; + const getStatsWithSource = document => ({ ...(document._stats ?? {}), compendiumSource: document.uuid }); const levelups = {}; for (var levelKey of Object.keys(levelupData)) { @@ -381,8 +398,8 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...multiclassData, - uuid: multiclassItem.uuid, - _stats: multiclassItem._stats, + uuid: multiclassItem.uuid, // todo: replace with setting an id and using keepId + _stats: getStatsWithSource(multiclassItem), system: { ...multiclassData.system, features: multiclassData.system.features.filter(x => x.type !== 'hope'), @@ -395,8 +412,8 @@ export default class DhpActor extends Actor { await this.createEmbeddedDocuments('Item', [ { ...subclassData, - uuid: subclassItem.uuid, - _stats: subclassItem._stats, + uuid: subclassItem.uuid, // todo: replace with setting an id and using keepId + _stats: getStatsWithSource(subclassItem), system: { ...subclassData.system, isMulticlass: true @@ -416,8 +433,8 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...cardData, - uuid: cardItem.uuid, - _stats: cardItem._stats, + uuid: cardItem.uuid, // todo: replace with setting an id and using keepId + _stats: getStatsWithSource(cardItem), system: { ...cardData.system, inVault: true @@ -438,8 +455,7 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...cardData, - uuid: cardItem.uuid, - _stats: cardItem._stats, + _stats: getStatsWithSource(cardItem), system: { ...cardData.system, inVault: true diff --git a/module/documents/scene.mjs b/module/documents/scene.mjs index 59b8091f..bf700610 100644 --- a/module/documents/scene.mjs +++ b/module/documents/scene.mjs @@ -20,7 +20,7 @@ export default class DhScene extends Scene { const prototype = tokenDoc.actor?.prototypeToken ?? tokenDoc; this.#sizeSyncBatch.set(tokenDoc.id, { size: tokenSize, - prototypeSize: { width: prototype.width, height: prototype.height }, + prototypeSize: { width: prototype.width, height: prototype.height, depth: prototype.depth }, position: { x: tokenDoc.x, y: tokenDoc.y, elevation: tokenDoc.elevation } }); this.#processSyncBatch(); @@ -36,11 +36,13 @@ export default class DhScene extends Scene { const tokenSize = tokenSizes[size]; const width = size !== CONFIG.DH.ACTOR.tokenSize.custom.id ? tokenSize : prototypeSize.width; const height = size !== CONFIG.DH.ACTOR.tokenSize.custom.id ? tokenSize : prototypeSize.height; + const depth = size !== CONFIG.DH.ACTOR.tokenSize.custom.id ? tokenSize : prototypeSize.depth; const updatedPosition = DHToken.getSnappedPositionInSquareGrid(this.grid, position, width, height); return { _id, width, height, + depth, ...updatedPosition }; }); diff --git a/module/documents/token.mjs b/module/documents/token.mjs index 4ee7ce05..30862724 100644 --- a/module/documents/token.mjs +++ b/module/documents/token.mjs @@ -66,7 +66,8 @@ export default class DHToken extends CONFIG.Token.documentClass { if (tokenSize && actor.system.size !== CONFIG.DH.ACTOR.tokenSize.custom.id) { document.updateSource({ width: tokenSize, - height: tokenSize + height: tokenSize, + depth: tokenSize }); } } @@ -90,7 +91,7 @@ export default class DHToken extends CONFIG.Token.documentClass { ) { const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; const tokenSize = tokenSizes[update.system.size]; - if (tokenSize !== this.width || tokenSize !== this.height) { + if (tokenSize !== this.width || tokenSize !== this.height || tokenSize !== this.depth) { this.parent?.syncTokenDimensions(this, update.system.size); } } diff --git a/module/documents/tokenManager.mjs b/module/documents/tokenManager.mjs index 3ccff4e2..7678d2c7 100644 --- a/module/documents/tokenManager.mjs +++ b/module/documents/tokenManager.mjs @@ -15,6 +15,7 @@ export default class DhTokenManager { if (tokenSize && actor.system.size !== CONFIG.DH.ACTOR.tokenSize.custom.id) { tokenData.width = tokenSize; tokenData.height = tokenSize; + tokenData.depth = tokenSize; } } diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index e10dc5fa..18c03169 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -350,7 +350,9 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti async getBattlepointHTML(combatId) { const combat = game.combats.get(combatId); const adversaries = - combat.turns?.filter(x => x.actor?.isNPC)?.map(x => ({ ...x.actor, type: x.actor.system.type })) ?? []; + combat.turns + ?.filter(x => x.actor?.isNPC && x.token.disposition === CONST.TOKEN_DISPOSITIONS.HOSTILE) + ?.map(x => ({ ...x.actor, type: x.actor.system.type })) ?? []; const characters = combat.turns?.filter(x => !x.isNPC && x.actor) ?? []; const nrCharacters = characters.length; diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 90937db4..7bc5fa25 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -449,14 +449,9 @@ export async function createEmbeddedItemsWithEffects(actor, baseData) { effects: data.effects?.map(effect => effect.toObject()) }); } - await actor.createEmbeddedDocuments('Item', effectData); } -export const slugify = name => { - return name.toLowerCase().replaceAll(' ', '-').replaceAll('.', ''); -}; - export function shuffleArray(array) { let currentIndex = array.length; while (currentIndex != 0) { diff --git a/package-lock.json b/package-lock.json index 47c5dede..28223032 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "autocompleter": "^9.3.2", "gulp": "^5.0.0", "gulp-less": "^5.0.0", + "gulp-sourcemaps": "^3.0.0", "rollup": "^4.40.0" }, "devDependencies": { @@ -202,6 +203,132 @@ "node": ">17.0.0" } }, + "node_modules/@gulp-sourcemaps/identity-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", + "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", + "license": "MIT", + "dependencies": { + "acorn": "^6.4.1", + "normalize-path": "^3.0.0", + "postcss": "^7.0.16", + "source-map": "^0.6.0", + "through2": "^3.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha512-o/EatdaGt8+x2qpb0vFLC/2Gug/xYPRXb6a+ET1wGYKozKN3krDWC/zZFZAtrzxJHuDL12mwdfEFKcKMNvc55A==", + "license": "MIT", + "dependencies": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/@gulpjs/messages": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", @@ -894,6 +1021,18 @@ "node": ">= 10.13.0" } }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/autocompleter": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/autocompleter/-/autocompleter-9.3.2.tgz", @@ -1482,6 +1621,12 @@ "node": ">= 10.13.0" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1496,6 +1641,17 @@ "node": ">= 8" } }, + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, "node_modules/css-declaration-sorter": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", @@ -1667,6 +1823,19 @@ "node": ">=8.0.0" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -1700,6 +1869,35 @@ } } }, + "node_modules/debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "license": "MIT", + "dependencies": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + } + }, + "node_modules/debug-fabulous/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1741,6 +1939,15 @@ "node": ">=0.10.0" } }, + "node_modules/detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -1905,6 +2112,58 @@ "node": ">= 0.4" } }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2106,6 +2365,21 @@ "node": ">=6" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", @@ -2176,6 +2450,16 @@ "node": ">=0.10.0" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", @@ -2194,6 +2478,15 @@ "node": ">=0.10.0" } }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2820,6 +3113,86 @@ "node": ">=6" } }, + "node_modules/gulp-sourcemaps": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", + "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", + "license": "ISC", + "dependencies": { + "@gulp-sourcemaps/identity-map": "^2.0.1", + "@gulp-sourcemaps/map-sources": "^1.0.0", + "acorn": "^6.4.1", + "convert-source-map": "^1.0.0", + "css": "^3.0.0", + "debug-fabulous": "^1.0.0", + "detect-newline": "^2.0.0", + "graceful-fs": "^4.0.0", + "source-map": "^0.6.0", + "strip-bom-string": "^1.0.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gulp-sourcemaps/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/gulp-sourcemaps/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/gulp-sourcemaps/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gulp-sourcemaps/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/gulp-sourcemaps/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gulp-sourcemaps/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/gulplog": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", @@ -3248,6 +3621,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -3333,6 +3712,12 @@ "node": ">=0.10.0" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3647,6 +4032,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -3692,6 +4086,25 @@ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "dev": true }, + "node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3779,8 +4192,7 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mute-stdout": { "version": "2.0.0", @@ -3846,6 +4258,12 @@ "node": ">= 4.4.x" } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, "node_modules/node-gyp-build": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", @@ -4827,6 +5245,12 @@ "node": ">=6.0.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/promise.series": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", @@ -5376,7 +5800,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -5390,6 +5813,17 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "license": "MIT", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, "node_modules/sparkles": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", @@ -5515,6 +5949,15 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-inject": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", @@ -5650,6 +6093,19 @@ "readable-stream": "3" } }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/tinyexec": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", @@ -5696,6 +6152,12 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5989,6 +6451,15 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 52bb4ce7..73a7fe99 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "autocompleter": "^9.3.2", "gulp": "^5.0.0", "gulp-less": "^5.0.0", + "gulp-sourcemaps": "^3.0.0", "rollup": "^4.40.0" }, "scripts": { diff --git a/styles/less/dialog/character-creation/selections-container.less b/styles/less/dialog/character-creation/selections-container.less index 2bbac484..24217dbf 100644 --- a/styles/less/dialog/character-creation/selections-container.less +++ b/styles/less/dialog/character-creation/selections-container.less @@ -114,9 +114,6 @@ .card-preview-container { flex: 1; - } - - .card-preview-container { border-color: light-dark(@dark-blue, @golden); } diff --git a/styles/less/dialog/group-roll-dialog/_common.less b/styles/less/dialog/group-roll-dialog/_common.less index 41573718..b04f6893 100644 --- a/styles/less/dialog/group-roll-dialog/_common.less +++ b/styles/less/dialog/group-roll-dialog/_common.less @@ -1,9 +1,7 @@ h1 { color: light-dark(@dark-blue, @golden); - font-family: var(--dh-font-subtitle); - font-size: var(--font-size-24); + font: 700 var(--font-size-24) var(--dh-font-subtitle); text-align: center; - font-weight: 700; } header { diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index eb882eeb..11d9635e 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -1,10 +1,5 @@ @import './attribution/sheet.less'; -@import './level-up/navigation-container.less'; -@import './level-up/selections-container.less'; -@import './level-up/sheet.less'; -@import './level-up/summary-container.less'; -@import './level-up/tiers-container.less'; -@import './level-up/footer.less'; +@import './level-up/index.less'; @import './resource-dice/sheet.less'; diff --git a/styles/less/dialog/level-up/index.less b/styles/less/dialog/level-up/index.less new file mode 100644 index 00000000..849a4d36 --- /dev/null +++ b/styles/less/dialog/level-up/index.less @@ -0,0 +1,6 @@ +@import './navigation-container.less'; +@import './selections-container.less'; +@import './summary-container.less'; +@import './tiers-container.less'; +@import './footer.less'; +@import './sheet.less'; diff --git a/styles/less/dialog/level-up/selections-container.less b/styles/less/dialog/level-up/selections-container.less index 6a551865..8c0dbaec 100644 --- a/styles/less/dialog/level-up/selections-container.less +++ b/styles/less/dialog/level-up/selections-container.less @@ -3,12 +3,7 @@ .daggerheart.levelup { .levelup-selections-container { - overflow: auto; padding: 10px 0; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; - max-height: 500px; - mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); .achievement-experience-cards { display: flex; @@ -45,20 +40,22 @@ .levelup-card-selection { display: flex; - flex-wrap: wrap; justify-content: center; gap: 40px; height: 190px; + align-items: stretch; .card-preview-container { - height: 100%; + height: 190px; max-width: 200px; } .levelup-domains-selection-container { - display: flex; - flex-direction: column; - gap: 8px; + display: grid; + grid-auto-flow: column; + grid-template-rows: repeat(2, minmax(0, 1fr)); + height: 100%; + gap: 4px; .levelup-domain-selection-container { display: flex; @@ -66,6 +63,8 @@ align-items: center; position: relative; cursor: pointer; + overflow: hidden; + width: 93px; &.disabled { pointer-events: none; @@ -74,16 +73,20 @@ .levelup-domain-label { position: absolute; + left: 0; + right: 0; + bottom: 0; text-align: center; - top: 4px; background: grey; - padding: 0 12px; - border-radius: 6px; + padding: 2px 12px; z-index: 2; + line-height: 1; } img { - height: 124px; + object-fit: cover; + width: auto; + height: auto; &.svg { filter: @beige-filter; @@ -92,17 +95,18 @@ .levelup-domain-selected { position: absolute; - height: 54px; - width: 54px; + height: 40px; + width: 40px; border-radius: 50%; - border: 2px solid; - font-size: var(--font-size-48); + border: 2px solid @golden; + font-size: var(--font-size-24); display: flex; align-items: center; justify-content: center; - background-image: url(../assets/parchments/dh-parchment-light.png); - color: var(--color-dark-5); - top: calc(50% - 29px); + background: @dark-golden; + color: @golden; + top: 10px; + z-index: 2; i { position: relative; diff --git a/styles/less/dialog/level-up/sheet.less b/styles/less/dialog/level-up/sheet.less index ade7c8a9..c663f304 100644 --- a/styles/less/dialog/level-up/sheet.less +++ b/styles/less/dialog/level-up/sheet.less @@ -11,9 +11,11 @@ }); .daggerheart.levelup { - .window-content { - max-height: 960px; + .tab.active { + flex: 1; overflow: auto; + scrollbar-width: thin; + scrollbar-color: light-dark(@dark-blue, @golden) transparent; } div[data-application-part='form'] { @@ -22,15 +24,13 @@ gap: 8px; } - section { - .section-container { - display: flex; - flex-direction: row; - justify-content: center; - gap: 20px 8px; - margin-top: 8px; - flex-wrap: wrap; - } + .section-container { + display: flex; + flex-direction: row; + justify-content: center; + gap: 20px 8px; + margin-top: 8px; + flex-wrap: wrap; } .levelup-footer { diff --git a/styles/less/dialog/level-up/summary-container.less b/styles/less/dialog/level-up/summary-container.less index d67abff6..97353ba7 100644 --- a/styles/less/dialog/level-up/summary-container.less +++ b/styles/less/dialog/level-up/summary-container.less @@ -17,8 +17,6 @@ .levelup-summary-container { overflow: auto; padding: 10px 0; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; max-height: 700px; mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); diff --git a/styles/less/dialog/tag-team-dialog/initialization.less b/styles/less/dialog/tag-team-dialog/initialization.less index 8557d231..2d015141 100644 --- a/styles/less/dialog/tag-team-dialog/initialization.less +++ b/styles/less/dialog/tag-team-dialog/initialization.less @@ -7,39 +7,85 @@ } .daggerheart.dialog.dh-style.views.tag-team-dialog { - .initialization-container { + .initialization-container.active { + display: flex; + flex-direction: column; + gap: var(--spacer-4); + h2 { text-align: center; } .members-container { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; + display: flex; + flex-wrap: wrap; + justify-content: center; gap: 8px; + // Force 3 columns for 5 -> 6 players + &:has(> :nth-child(5)):not(:has(> :nth-child(7))) { + padding-left: 10%; + padding-right: 10%; + } + .member-container { position: relative; display: flex; + align-items: stretch; justify-content: center; + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @golden); + overflow: hidden; + height: 11.5rem; + width: 122px; &.inactive { - opacity: 0.4; + border-color: light-dark(@dark-blue-40, @golden-40); + img { + opacity: 0.4; + } } .member-name { + --shadow-color: light-dark(white, black); position: absolute; - padding: 0 2px; - border: 1px solid; - border-radius: 6px; - margin-top: 4px; - color: light-dark(@dark, @beige); - background-image: url('../assets/parchments/dh-parchment-dark.png'); + bottom: 0; + left: 0; + right: 0; + + display: flex; + flex-direction: column; + justify-content: flex-end; + min-height: 4rem; + padding: 5rem 4px var(--spacer-8) 4px; text-align: center; + + color: var(--color-text-primary); + text-shadow: 1px 1px 2px var(--shadow-color), 0 0 10px var(--shadow-color); + + // Basic "scrim" gradient + background-image: linear-gradient( + to top, + var(--shadow-color), + rgba(from var(--shadow-color) r g b / 0.834) 10.6%, + rgba(from var(--shadow-color) r g b / 0.541) 34%, + rgba(from var(--shadow-color) r g b / 0.382) 47%, + rgba(from var(--shadow-color) r g b / 0.194) 65%, + transparent 100% + ); } img { - border-radius: 6px; - border: 1px solid light-dark(@dark-blue, @golden); + object-fit: cover; + object-position: top center; + flex: 1; + } + + .leader-mark { + position: absolute; + top: 4px; + right: 4px; + text-shadow: var(--shadow-text-stroke), 0 0 20px black; } } } diff --git a/styles/less/dialog/tag-team-dialog/sheet.less b/styles/less/dialog/tag-team-dialog/sheet.less index dc8f16dc..a8dffbd2 100644 --- a/styles/less/dialog/tag-team-dialog/sheet.less +++ b/styles/less/dialog/tag-team-dialog/sheet.less @@ -1,4 +1,10 @@ -.daggerheart.dialog.dh-style.views.tag-team-dialog { +.daggerheart.dialog.dh-style.views.tag-team-dialog .window-content { + h1 { + color: light-dark(@dark-blue, @golden); + font: 700 var(--font-size-24) var(--dh-font-subtitle); + text-align: center; + } + .team-container { display: flex; gap: 16px; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 05e679b5..9dbf0683 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -7,12 +7,12 @@ input[type='text'], input[type='number'], textarea, + file-picker, .input[contenteditable] { background: light-dark(transparent, transparent); border-radius: 6px; box-shadow: 0 4px 30px @soft-shadow; backdrop-filter: blur(9.5px); - -webkit-backdrop-filter: blur(9.5px); outline: 2px solid transparent; color: light-dark(@dark-blue, @golden); border: 1px solid light-dark(@dark, @beige); @@ -96,20 +96,19 @@ textarea { color: light-dark(@dark, @beige); - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } - button:where(:not(.plain)) { - background: light-dark(transparent, @golden); - border: 1px solid light-dark(@dark-blue, @dark-blue); - color: light-dark(@dark-blue, @dark-blue); + button:where(:not(.plain, color-picker *, file-picker *)) { + background: var(--dh-button-background); + border: 1px solid light-dark(@dark-blue, #efe6d850); + color: light-dark(@dark-blue, #efe6d8); outline: none; box-shadow: none; + border-radius: 0; &:hover { - background: light-dark(@light-black, @dark-blue); - color: light-dark(@dark-blue, @golden); + background-color: @golden-40; + background-blend-mode: lighten; } &.glow { @@ -117,15 +116,8 @@ } &:disabled { - background: light-dark(transparent, @golden); - color: light-dark(@dark-blue, @dark-blue); opacity: 0.6; cursor: not-allowed; - - &:hover { - background: light-dark(transparent, @golden); - color: light-dark(@dark-blue, @dark-blue); - } } &.reverted { @@ -254,6 +246,15 @@ text-shadow: 0 0 1px currentColor, 0 0 1px currentColor, 0 0 8px light-dark(@dark-blue, @golden); } + file-picker, color-picker { + > input[type=text] { + background: transparent; + border: none; + outline: none; + backdrop-filter: unset; + } + } + fieldset { align-items: center; margin-top: 5px; @@ -551,38 +552,31 @@ .item-button { display: flex; - border: 1px solid light-dark(#18162e, #18162e); - color: light-dark(#18162e, #18162e); outline: none; box-shadow: none; - border-radius: 6px; + border-radius: 0; button { - border-radius: 3px 0px 0px 3px; - color: light-dark(@dark-blue, @dark-blue); + --button-size: 2.25em; + font-size: var(--font-size-12); + font-family: @font-body; + font-weight: 500; white-space: nowrap; - border: 0; - &:hover { - color: light-dark(@dark-blue, @golden); + &:not(:last-child) { + border-right-width: 0; } &:not(:first-child) { padding: 6px; - background: light-dark(@dark-blue-10, @golden-secondary); - border-radius: 0px 3px 3px 0px; - color: light-dark(@dark-blue, @dark-golden); - - &:hover { - background: light-dark(@light-black, @dark-blue); - color: light-dark(@dark-blue, @golden-secondary); - } + border-left-width: 0; } } .spacer { - border-right: 1px solid black; + border-right: 1px solid light-dark(#18162e, #efe6d850); content: ''; + margin-left: -1px; } } } @@ -599,59 +593,6 @@ } } -.application.setting.dh-style { - h2, - h3, - h4 { - margin: 8px 0 4px; - text-align: center; - } - - footer { - margin-top: 8px; - display: flex; - gap: 8px; - - button { - flex: 1; - } - } - - .form-group { - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.25rem 0.5rem; - flex-wrap: wrap; - - label { - font-size: var(--font-size-14); - font-weight: normal; - } - - .form-fields { - display: flex; - gap: 4px; - align-items: center; - } - - &.setting-two-values { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 0.25rem 0.5rem; - - .form-group { - justify-content: end; - flex-wrap: nowrap; - } - - .hint { - grid-column: 1 / -1; - } - } - } -} - .system-daggerheart { .tagify { background: light-dark(transparent, transparent); @@ -747,6 +688,8 @@ } .theme-light { + --dh-button-background: transparent; + .application { &.sheet.dh-style { button.glow { @@ -769,6 +712,11 @@ } } +.theme-dark .dh-style, +.theme-dark.dh-style { + --dh-button-background: url('../assets/parchments/dh-parchment-button-dark.png'); +} + .application .component.dh-style.card-preview-container { position: relative; border: 2px solid transparent; @@ -804,6 +752,7 @@ .preview-image-container { width: 100%; + min-height: 0; flex-grow: 1; object-fit: cover; border-radius: 4px 4px 0 0; diff --git a/styles/less/global/feature-section.less b/styles/less/global/feature-section.less index 7d5099e1..2fd4e20f 100644 --- a/styles/less/global/feature-section.less +++ b/styles/less/global/feature-section.less @@ -5,8 +5,6 @@ .tab.features { padding: 0 10px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; .feature-list { display: flex; flex-direction: column; diff --git a/styles/less/global/global.less b/styles/less/global/global.less index b9af67c0..c0e7f3fc 100644 --- a/styles/less/global/global.less +++ b/styles/less/global/global.less @@ -12,6 +12,11 @@ } .daggerheart.dh-style { + * { + scrollbar-width: thin; + scrollbar-color: light-dark(@dark-blue, @golden) transparent; + } + .hint { flex: 0 0 100%; margin: 0; @@ -33,7 +38,7 @@ } &:before { - font-family: 'Font Awesome 6 Pro'; + font-family: var(--font-awesome); content: '\f110'; position: absolute; height: 100%; diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less index 8a663e28..8412235d 100644 --- a/styles/less/global/prose-mirror.less +++ b/styles/less/global/prose-mirror.less @@ -10,8 +10,6 @@ background-color: transparent; } .editor-content { - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; h1 { font-size: var(--font-size-32); } diff --git a/styles/less/global/sheet.less b/styles/less/global/sheet.less index 0c400564..5ccb8788 100755 --- a/styles/less/global/sheet.less +++ b/styles/less/global/sheet.less @@ -4,8 +4,8 @@ // Theme handling .appTheme({ - background: @dark-blue-90; - backdrop-filter: blur(8px); + background: @dark-blue-d0; + backdrop-filter: blur(7px); }, { background: url('../assets/parchments/dh-parchment-light.png') no-repeat center; }); diff --git a/styles/less/sheets-settings/adversary-settings/features.less b/styles/less/sheets-settings/adversary-settings/features.less index 4e0f6a8f..15b1fa18 100644 --- a/styles/less/sheets-settings/adversary-settings/features.less +++ b/styles/less/sheets-settings/adversary-settings/features.less @@ -5,8 +5,6 @@ .tab.features { max-height: 450px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; .add-feature-btn { width: 100%; diff --git a/styles/less/sheets-settings/environment-settings/adversaries.less b/styles/less/sheets-settings/environment-settings/adversaries.less index 1a27eaca..2ce4819a 100644 --- a/styles/less/sheets-settings/environment-settings/adversaries.less +++ b/styles/less/sheets-settings/environment-settings/adversaries.less @@ -5,8 +5,6 @@ .tab.adversaries { max-height: 450px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; .add-action-btn { width: 100%; diff --git a/styles/less/sheets-settings/environment-settings/features.less b/styles/less/sheets-settings/environment-settings/features.less index d907837a..db6b544d 100644 --- a/styles/less/sheets-settings/environment-settings/features.less +++ b/styles/less/sheets-settings/environment-settings/features.less @@ -5,8 +5,6 @@ .tab.features { max-height: 450px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; .add-feature-btn { width: 100%; diff --git a/styles/less/sheets/actors/adversary/actions.less b/styles/less/sheets/actors/adversary/actions.less index 00395ebd..af870d9b 100644 --- a/styles/less/sheets/actors/adversary/actions.less +++ b/styles/less/sheets/actors/adversary/actions.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/adversary/effects.less b/styles/less/sheets/actors/adversary/effects.less index 4afe2454..fbf74249 100644 --- a/styles/less/sheets/actors/adversary/effects.less +++ b/styles/less/sheets/actors/adversary/effects.less @@ -9,9 +9,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/adversary/sidebar.less b/styles/less/sheets/actors/adversary/sidebar.less index 4e7535c1..ef99bc09 100644 --- a/styles/less/sheets/actors/adversary/sidebar.less +++ b/styles/less/sheets/actors/adversary/sidebar.less @@ -287,12 +287,11 @@ padding-top: 10px; padding-bottom: 20px; mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); - scrollbar-width: thin; + scrollbar-gutter: stable; &:hover { overflow-y: auto; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } diff --git a/styles/less/sheets/actors/character/biography.less b/styles/less/sheets/actors/character/biography.less index b7c6ba6e..f8d56735 100644 --- a/styles/less/sheets/actors/character/biography.less +++ b/styles/less/sheets/actors/character/biography.less @@ -13,9 +13,6 @@ padding-top: 8px; padding-bottom: 20px; height: 100%; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } .characteristics-section { diff --git a/styles/less/sheets/actors/character/effects.less b/styles/less/sheets/actors/character/effects.less index ceadd05e..ae49fa2d 100644 --- a/styles/less/sheets/actors/character/effects.less +++ b/styles/less/sheets/actors/character/effects.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less index 6a6438ff..017254a3 100644 --- a/styles/less/sheets/actors/character/features.less +++ b/styles/less/sheets/actors/character/features.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index 12f63753..c8d2b584 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); padding: 20px 0; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index eba55890..127d688a 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -92,9 +92,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 98%, transparent 100%); padding: 20px 0; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index 0e6e3d97..7188faca 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -93,6 +93,17 @@ } } + .status-label { + position: relative; + background: light-dark(@dark-blue, @golden); + h4 { + font-weight: bold; + text-align: center; + line-height: 18px; + color: light-dark(@beige, @dark-blue); + } + } + .resources-section { display: flex; justify-content: space-evenly; @@ -106,19 +117,10 @@ height: 40px; .status-label { - position: relative; top: 40px; height: 22px; width: 79px; clip-path: path('M0 0H79L74 16.5L39 22L4 16.5L0 0Z'); - background: light-dark(@dark-blue, @golden); - - h4 { - font-weight: bold; - text-align: center; - line-height: 18px; - color: light-dark(@beige, @dark-blue); - } } .status-value { @@ -253,12 +255,10 @@ .status-label { padding: 2px 2px; - position: relative; top: 30px; height: 22px; width: 95px; border-radius: 3px; - background: light-dark(@dark-blue, @golden); clip-path: none; display: flex; align-items: center; @@ -268,10 +268,6 @@ transition: all 0.3s ease; h4 { - font-weight: bold; - text-align: center; - line-height: 18px; - color: light-dark(@beige, @dark-blue); font-size: var(--font-size-12); } @@ -494,14 +490,8 @@ padding: 2px 10px; width: 100%; border-radius: 3px; - background: light-dark(@dark-blue, @golden); - h4 { - font-weight: bold; - text-align: center; - line-height: 18px; font-size: var(--font-size-12); - color: light-dark(@beige, @dark-blue); } } } @@ -551,11 +541,9 @@ padding-bottom: 20px; mask-image: linear-gradient(0deg, transparent 0%, black 5%); scrollbar-gutter: stable; - scrollbar-width: thin; - + &:hover { overflow-y: auto; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } diff --git a/styles/less/sheets/actors/companion/effects.less b/styles/less/sheets/actors/companion/effects.less index 12e1d847..6d7fe061 100644 --- a/styles/less/sheets/actors/companion/effects.less +++ b/styles/less/sheets/actors/companion/effects.less @@ -9,9 +9,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/environment/actions.less b/styles/less/sheets/actors/environment/actions.less index 51385322..cc8a345a 100644 --- a/styles/less/sheets/actors/environment/actions.less +++ b/styles/less/sheets/actors/environment/actions.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/environment/potentialAdversaries.less b/styles/less/sheets/actors/environment/potentialAdversaries.less index 274362a5..f3c5776a 100644 --- a/styles/less/sheets/actors/environment/potentialAdversaries.less +++ b/styles/less/sheets/actors/environment/potentialAdversaries.less @@ -9,9 +9,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%); padding-bottom: 20px; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/environment/sheet.less b/styles/less/sheets/actors/environment/sheet.less index 3ea14bc7..a7c9605b 100644 --- a/styles/less/sheets/actors/environment/sheet.less +++ b/styles/less/sheets/actors/environment/sheet.less @@ -20,8 +20,6 @@ .tab { flex: 1; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; &.active { overflow: hidden; diff --git a/styles/less/sheets/actors/party/inventory.less b/styles/less/sheets/actors/party/inventory.less index ac59e1de..8af37a79 100644 --- a/styles/less/sheets/actors/party/inventory.less +++ b/styles/less/sheets/actors/party/inventory.less @@ -10,9 +10,6 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); padding: 20px 0; - - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } } diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index a29f7c88..a3ec90ec 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -2,16 +2,6 @@ @import '../../../utils/fonts.less'; @import '../../../utils/mixin.less'; -body.game:is(.performance-low, .noblur) { - .application.sheet.daggerheart.actor.dh-style.party .tab.resources .actors-list .actor-resources { - background: light-dark(@dark-blue, @dark-golden); - - .actor-name { - background: light-dark(@dark-blue, @dark-golden); - } - } -} - .application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers { overflow: auto; diff --git a/styles/less/sheets/actors/party/sheet.less b/styles/less/sheets/actors/party/sheet.less index 6b51de53..852b6cfc 100644 --- a/styles/less/sheets/actors/party/sheet.less +++ b/styles/less/sheets/actors/party/sheet.less @@ -20,8 +20,6 @@ .tab { flex: 1; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; scrollbar-gutter: stable; &.active { diff --git a/styles/less/sheets/items/domain-card.less b/styles/less/sheets/items/domain-card.less index a784b3a2..54378fd0 100644 --- a/styles/less/sheets/items/domain-card.less +++ b/styles/less/sheets/items/domain-card.less @@ -5,7 +5,5 @@ section.tab { height: 400px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } diff --git a/styles/less/sheets/items/feature.less b/styles/less/sheets/items/feature.less index b7493f15..f3c7cd49 100644 --- a/styles/less/sheets/items/feature.less +++ b/styles/less/sheets/items/feature.less @@ -14,7 +14,5 @@ section.tab { height: 400px; overflow-y: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } } diff --git a/styles/less/ui/chat/sheet.less b/styles/less/ui/chat/sheet.less index 66b539b4..fb8cc104 100644 --- a/styles/less/ui/chat/sheet.less +++ b/styles/less/ui/chat/sheet.less @@ -195,7 +195,7 @@ fieldset.daggerheart.chat { &:before, &:after { content: '\f0d8'; - font-family: 'Font Awesome 6 Pro'; + font-family: var(--font-awesome); } } &.expanded { diff --git a/styles/less/ui/countdown/countdown-edit.less b/styles/less/ui/countdown/countdown-edit.less index d6c4da93..78ad3a06 100644 --- a/styles/less/ui/countdown/countdown-edit.less +++ b/styles/less/ui/countdown/countdown-edit.less @@ -60,8 +60,6 @@ overflow-y: auto; overflow-x: hidden; max-height: 500px; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; .countdown-edit-outer-container { display: flex; diff --git a/styles/less/ui/countdown/countdown.less b/styles/less/ui/countdown/countdown.less index 47f06eb7..380eb454 100644 --- a/styles/less/ui/countdown/countdown.less +++ b/styles/less/ui/countdown/countdown.less @@ -1,28 +1,47 @@ @import '../../utils/colors.less'; @import '../../utils/fonts.less'; -.theme-dark { +#interface.theme-dark { .daggerheart.dh-style.countdowns { - background-image: url(../assets/parchments/dh-parchment-dark.png); - - .window-header { - background-image: url(../assets/parchments/dh-parchment-dark.png); - } + --background: url(../assets/parchments/dh-parchment-dark.png); } } -.daggerheart.dh-style.countdowns { +#interface.theme-light { + .daggerheart.dh-style.countdowns { + --background: url('../assets/parchments/dh-parchment-light.png') no-repeat center; + } +} + +.daggerheart.dh-style.countdowns { position: relative; border: 0; - border-radius: 4px; box-shadow: none; + color: var(--color-text-primary); width: 300px; pointer-events: all; align-self: flex-end; transition: 0.3s right ease-in-out; - .window-title { - font-family: @font-body; + display: flex; + flex-direction: column; + + &::before { + content: ' '; + position: absolute; + inset: 0; + background: var(--background); + border-radius: 4px; + opacity: var(--ui-fade-opacity); + transition: opacity var(--ui-fade-duration); + } + + :not(.performance-low, .noblur) { + backdrop-filter: blur(5px); + } + + &:hover::before { + opacity: 1; } #ui-right:has(#effects-display .effect-container) & { @@ -34,123 +53,136 @@ min-width: 180px; } - .window-header { - cursor: default; - border-bottom: 0; + .countdowns-header, + .countdowns-container { + position: relative; // allow rendering over the background } - .window-content { - padding-top: 4px; - padding-bottom: 16px; + .countdowns-header { + display: flex; + align-items: center; + gap: 0.25rem; + flex: 0 0 36px; + padding: 0 0.5rem; + overflow: hidden; + font-size: var(--font-size-13); + .window-title { + font-family: @font-body; + flex: 1; + } + .header-control + .header-control { + margin-left: 8px; + } + } + + .countdowns-container { + display: flex; + flex-direction: column; + gap: 8px; + padding: 4px var(--spacer-16) var(--spacer-16) var(--spacer-16); overflow: auto; max-height: 312px; - .countdowns-container { + .countdown-container { display: flex; - flex-direction: column; - gap: 8px; + width: 100%; - .countdown-container { - display: flex; - width: 100%; + &.icon-only { + gap: 8px; - &.icon-only { - gap: 8px; + .countdown-main-container { + .countdown-content { + justify-content: center; - .countdown-main-container { - .countdown-content { - justify-content: center; - - .countdown-tools { - gap: 8px; - } + .countdown-tools { + gap: 8px; } } } + } - .countdown-main-container { - width: 100%; + .countdown-main-container { + width: 100%; + display: flex; + align-items: center; + gap: 16px; + + img { + width: 44px; + height: 44px; + border-radius: 6px; + } + + .countdown-content { + flex: 1; display: flex; - align-items: center; - gap: 16px; + flex-direction: column; + justify-content: space-between; - img { - width: 44px; - height: 44px; - border-radius: 6px; - } - - .countdown-content { - flex: 1; + .countdown-tools { display: flex; - flex-direction: column; + align-items: center; justify-content: space-between; - .countdown-tools { + .countdown-tool-controls { display: flex; align-items: center; - justify-content: space-between; + gap: 16px; + } - .countdown-tool-controls { - display: flex; - align-items: center; - gap: 16px; - } + .progress-tag { + border: 1px solid; + border-radius: 4px; + padding: 2px 4px; + background-color: light-dark(@beige, @dark-blue); + } - .progress-tag { - border: 1px solid; - border-radius: 4px; + .countdown-tool-icons { + display: flex; + align-items: center; + gap: 8px; + + .looping-container { + position: relative; + border: 1px solid light-dark(@dark-blue, white); + border-radius: 6px; padding: 2px 4px; - background-color: light-dark(@beige, @dark-blue); - } - .countdown-tool-icons { - display: flex; - align-items: center; - gap: 8px; + &.should-loop { + background: light-dark(@golden, @golden); - .looping-container { - position: relative; - border: 1px solid light-dark(@dark-blue, white); - border-radius: 6px; - padding: 2px 4px; - - &.should-loop { - background: light-dark(@golden, @golden); - - .loop-marker { - color: light-dark(@dark-blue, @dark-blue); - } + .loop-marker { + color: light-dark(@dark-blue, @dark-blue); } + } - .direction-marker { - position: absolute; - font-size: 10px; - filter: drop-shadow(0 0 3px black); - top: -3px; - } + .direction-marker { + position: absolute; + font-size: 10px; + filter: drop-shadow(0 0 3px black); + top: -3px; } } } } } - /* Keep incase we want to reintroduce the player pips */ - // .countdown-access-container { - // display: grid; - // grid-template-columns: 1fr 1fr 1fr; - // grid-auto-rows: min-content; - // width: 38px; - // gap: 4px; - - // .countdown-access { - // height: 10px; - // width: 10px; - // border-radius: 50%; - // border: 1px solid light-dark(@dark-blue, @beige-80); - // content: ''; - // } - // } } + /* Keep incase we want to reintroduce the player pips */ + // .countdown-access-container { + // display: grid; + // grid-template-columns: 1fr 1fr 1fr; + // grid-auto-rows: min-content; + // width: 38px; + // gap: 4px; + + // .countdown-access { + // height: 10px; + // width: 10px; + // border-radius: 50%; + // border: 1px solid light-dark(@dark-blue, @beige-80); + // content: ''; + // } + // } } } } diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less index f558a0ba..066da73b 100644 --- a/styles/less/ui/item-browser/item-browser.less +++ b/styles/less/ui/item-browser/item-browser.less @@ -125,6 +125,7 @@ .form-group { white-space: nowrap; + gap: 0; } .filter-header { @@ -168,6 +169,10 @@ } } } + + .filter-content { + margin-top: 8px; + } } .folder-list { @@ -237,8 +242,6 @@ .compendium-sidebar > .folder-list { overflow-y: auto; scrollbar-gutter: stable; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; } .item-list-header, @@ -274,7 +277,7 @@ div[data-sort-key] { &:after { - font-family: 'Font Awesome 6 Pro'; + font-family: var(--font-awesome); margin-left: 5px; } diff --git a/styles/less/ui/settings/homebrew-settings/domains.less b/styles/less/ui/settings/homebrew-settings/domains.less index da258fcd..406294ac 100644 --- a/styles/less/ui/settings/homebrew-settings/domains.less +++ b/styles/less/ui/settings/homebrew-settings/domains.less @@ -55,8 +55,6 @@ gap: 8px; max-height: 184px; overflow: auto; - scrollbar-width: thin; - scrollbar-color: light-dark(#18162e, #f3c267) transparent; .domain-container { position: relative; diff --git a/styles/less/ui/settings/homebrew-settings/resources.less b/styles/less/ui/settings/homebrew-settings/resources.less index 5333e54d..1184904b 100644 --- a/styles/less/ui/settings/homebrew-settings/resources.less +++ b/styles/less/ui/settings/homebrew-settings/resources.less @@ -24,7 +24,7 @@ .resource-icons-container { display: flex; justify-content: space-between; - gap: 8px; + gap: 10px; width: 100%; .resource-icon-container { diff --git a/styles/less/ui/settings/settings.less b/styles/less/ui/settings/settings.less index 34f17d53..d08f74e6 100644 --- a/styles/less/ui/settings/settings.less +++ b/styles/less/ui/settings/settings.less @@ -1,6 +1,67 @@ @import '../../utils/colors.less'; .daggerheart.dh-style.setting { + --color-form-label: var(--color-text-primary); + + h2, + h3, + h4 { + margin: 8px 0 4px; + text-align: center; + } + + footer { + margin-top: 8px; + display: flex; + gap: 8px; + + button { + flex: 1; + } + } + + .standard-form { + gap: var(--spacer-8); + .form-group .form-fields { + width: unset; + } + } + + .form-group { + display: flex; + justify-content: space-between; + align-items: center; + gap: 0.25rem 0.5rem; + flex-wrap: wrap; + + label { + font-size: var(--font-size-14); + font-weight: normal; + line-height: var(--input-height); + } + + .form-fields { + display: flex; + gap: 4px; + align-items: center; + } + + &.setting-two-values { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0.25rem 0.5rem; + + .form-group { + justify-content: end; + flex-wrap: nowrap; + } + + .hint { + grid-column: 1 / -1; + } + } + } + fieldset { display: flex; flex-direction: column; @@ -19,7 +80,10 @@ &.three-columns { display: grid; grid-template-columns: 1fr 1fr 1fr; - gap: 2px; + gap: 4px; + .form-group label { + line-height: unset; + } } &.six-columns { diff --git a/styles/less/utils/colors.less b/styles/less/utils/colors.less index 18b981ad..80519a5b 100755 --- a/styles/less/utils/colors.less +++ b/styles/less/utils/colors.less @@ -51,6 +51,7 @@ --dark-blue-50: #18162e50; --dark-blue-60: #18162e60; --dark-blue-90: #18162e90; + --dark-blue-d0: #18162ed0; --semi-transparent-dark-blue: rgba(24, 22, 46, 0.33); --dark: #222222; @@ -136,6 +137,7 @@ @dark-blue-50: var(--dark-blue-50, #18162e50); @dark-blue-60: var(--dark-blue-60, #18162e60); @dark-blue-90: var(--dark-blue-90, #18162e90); +@dark-blue-d0: var(--dark-blue-d0, #18162ed0); @semi-transparent-dark-blue: var(--semi-transparent-dark-blue, rgba(24, 22, 46, 0.33)); @dark: var(--dark, #222222); diff --git a/styles/less/ux/autocomplete/autocomplete.less b/styles/less/ux/autocomplete/autocomplete.less index 7f799449..e778f0da 100644 --- a/styles/less/ux/autocomplete/autocomplete.less +++ b/styles/less/ux/autocomplete/autocomplete.less @@ -21,8 +21,6 @@ flex-direction: column; gap: 2px; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; - .group { font-weight: bold; font-size: var(--font-size-14); diff --git a/styles/less/ux/tooltip/sheet.less b/styles/less/ux/tooltip/sheet.less index 59e4e638..ad774fcd 100644 --- a/styles/less/ux/tooltip/sheet.less +++ b/styles/less/ux/tooltip/sheet.less @@ -48,9 +48,6 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip), overflow-y: auto; position: relative; - scrollbar-width: thin; - scrollbar-color: light-dark(@dark-blue, @golden) transparent; - .tooltip-tag { display: flex; gap: 10px; diff --git a/system.json b/system.json index 16a1f74b..bbee2c09 100644 --- a/system.json +++ b/system.json @@ -2,19 +2,24 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.2.4", + "version": "2.2.6", "compatibility": { - "minimum": "14.359", - "verified": "14.361", + "minimum": "14.361", + "verified": "14.363", "maximum": "14" }, "url": "https://github.com/Foundryborne/daggerheart", "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json", - "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.4/system.zip", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.6/system.zip", "authors": [ { "name": "WBHarry" }, + { + "name": "Supe", + "url": "https://github.com/CarlosFdez", + "discord": "supe" + }, { "name": "cptn-cosmo", "url": "https://github.com/cptn-cosmo", @@ -298,5 +303,11 @@ }, "background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png", "primaryTokenAttribute": "resources.hitPoints", - "secondaryTokenAttribute": "resources.stress" + "secondaryTokenAttribute": "resources.stress", + "flags": { + "hotReload": { + "extensions": ["css", "hbs", "json"], + "paths": ["styles/daggerheart.css", "templates", "lang"] + } + } } diff --git a/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs b/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs index dcda8108..ca2739b2 100644 --- a/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs +++ b/templates/dialogs/compendiumBrowserSettingsDialog/packs.hbs @@ -22,7 +22,7 @@