diff --git a/lang/en.json b/lang/en.json index 2b355ae0..fa4dc2db 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2312,7 +2312,8 @@ "appliedEvenIfSuccessful": "Applied even if save succeeded", "diceIsRerolled": "The dice has been rerolled (x{times})", "pendingSaves": "Pending Reaction Rolls", - "openSheetSettings": "Open Settings" + "openSheetSettings": "Open Settings", + "compediumBrowser": "Compedium Browser" } } } diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index 82ef5dba..0927a3ba 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -1,4 +1,3 @@ - const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; /** @@ -21,12 +20,13 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { /** @inheritDoc */ static DEFAULT_OPTIONS = { id: 'itemBrowser', - classes: ['dh-style'], + classes: ['daggerheart', 'dh-style', 'dialog', 'compendium-browser'], tag: 'div', // title: 'Item Browser', window: { frame: true, - title: 'Item Browser', + title: 'Compedium Browser', + icon: 'fa-solid fa-book-atlas', positioned: true, resizable: true }, @@ -62,7 +62,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { * @type {foundry.applications.ux.SearchFilter} */ #search = {}; - + #input = {}; /** @@ -84,7 +84,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { /** @inheritDoc */ async _onRender(context, options) { await super._onRender(context, options); - + this._createSearchFilter(); this._createFilterInputs(); this._createDragProcess(); @@ -104,7 +104,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { context.formatChoices = this.formatChoices; context.fieldFilter = this.fieldFilter = this.selectedMenu.data?.filters ? this._createFieldFilter() : []; context.items = this.items; - console.log(this.items) + console.log(this.items); return context; } @@ -115,11 +115,13 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { id: c.id, label: c.label, selected: (!parent || parent.selected) && this.selectedMenu.path[depth] === c.id - } - folder.folders = c.folders ? ItemBrowser.sortBy(this.getCompendiumFolders(c.folders, folder, depth + 2), 'label') : []; + }; + folder.folders = c.folders + ? ItemBrowser.sortBy(this.getCompendiumFolders(c.folders, folder, depth + 2), 'label') + : []; // sortBy(Object.values(c.folders), 'label') - folders.push(folder) - }) + folders.push(folder); + }); // console.log(folders) return folders; @@ -135,12 +137,12 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { this.selectedMenu = { path: folderPath.split('.'), data: folderData - } - + }; + let items = []; - for(const key of folderData.keys) { + for (const key of folderData.keys) { const comp = game.packs.get(`${compendium}.${key}`); - if(!comp) return; + if (!comp) return; items = items.concat(await comp.getDocuments({ type__in: folderData.type })); } @@ -150,37 +152,37 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { static expandContent(_, target) { const parent = target.parentElement; - parent.classList.toggle("expanded"); + parent.classList.toggle('expanded'); } static sortBy(data, property) { - return data.sort((a, b) => a[property] > b[property] ? 1 : -1) + return data.sort((a, b) => (a[property] > b[property] ? 1 : -1)); } formatLabel(item, field) { const property = foundry.utils.getProperty(item, field.key); - if(typeof field.format !== 'function') return property; + if (typeof field.format !== 'function') return property; return field.format(property); } formatChoices(data) { - if(!data.field.choices) return null; + if (!data.field.choices) return null; const config = { choices: data.field.choices }; foundry.data.fields.StringField._prepareChoiceConfig(config); - return config.options.filter(c => data.filtered.includes(c.value) || data.filtered.includes(c.label.toLowerCase())); + return config.options.filter( + c => data.filtered.includes(c.value) || data.filtered.includes(c.label.toLowerCase()) + ); } _createFieldFilter() { const filters = []; this.selectedMenu.data.filters.forEach(f => { - if(typeof f.field === 'string') - f.field = foundry.utils.getProperty(game, f.field); - else if(typeof f.choices === 'function') - f.choices = f.choices(); - filters.push(f) - }) + if (typeof f.field === 'string') f.field = foundry.utils.getProperty(game, f.field); + else if (typeof f.choices === 'function') f.choices = f.choices(); + filters.push(f); + }); return filters; } @@ -201,7 +203,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { const filters = [ { key: 'browser', - input: 'input[type="search"].search-browser', + input: 'input[type="search"].search-input', content: '[data-application-part="list"] .item-list', callback: this._onSearchFilterBrowser.bind(this) } @@ -217,7 +219,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { this.#search[key] = filter; } } - + /* -------------------------------------------- */ /* Filter Inputs */ /* -------------------------------------------- */ @@ -228,7 +230,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { key: 'browser', container: '[data-application-part="list"] .filter-content .wrapper', content: '[data-application-part="list"] .item-list', - callback: this._onInputFilterBrowser.bind(this), + callback: this._onInputFilterBrowser.bind(this) // target: '.filter-button', // filters: FilterMenu.invetoryFilters } @@ -236,16 +238,16 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { inputs.forEach(m => { const container = this.element.querySelector(m.container); - if(!container) return this.#input[m.key] = {}; + if (!container) return (this.#input[m.key] = {}); const inputs = container.querySelectorAll('input, select'); inputs.forEach(input => { - input.addEventListener('change', this._onInputFilterBrowser.bind(this)) + input.addEventListener('change', this._onInputFilterBrowser.bind(this)); }); this.#filteredItems[m.key].input = new Set(this.items.map(i => i.id)); this.#input[m.key] = inputs; }); } - + /** * Handle invetory items search and filtering. * @param {KeyboardEvent} event The keyboard input event. @@ -267,7 +269,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { // li.hidden = !(matchesSearch); } } - + /** * Callback when filters change * @param {PointerEvent} event @@ -276,7 +278,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { async _onInputFilterBrowser(event) { this.#filteredItems.browser.input.clear(); - console.log(event.target.name) + console.log(event.target.name); this.fieldFilter.find(f => f.key === event.target.name).value = event.target.value; @@ -287,8 +289,12 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { item = this.items.find(i => i.uuid === itemUUID); const matchesMenu = - this.fieldFilter.length === 0 || this.fieldFilter.every(f => { - return (!f.value && f.value !== false) || foundry.applications.ux.SearchFilter.evaluateFilter(item, this.createFilterData(f)) + this.fieldFilter.length === 0 || + this.fieldFilter.every(f => { + return ( + (!f.value && f.value !== false) || + foundry.applications.ux.SearchFilter.evaluateFilter(item, this.createFilterData(f)) + ); }); if (matchesMenu) this.#filteredItems.browser.input.add(item.id); @@ -301,10 +307,14 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { createFilterData(filter) { return { field: filter.key, - value: isNaN(filter.value) ? (["true", "false"].includes(filter.value) ? filter.value === "true" : filter.value) : Number(filter.value), + value: isNaN(filter.value) + ? ['true', 'false'].includes(filter.value) + ? filter.value === 'true' + : filter.value + : Number(filter.value), operator: filter.operator, negate: filter.negate - } + }; } static resetFilters() { @@ -324,15 +334,15 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { _createDragProcess() { new foundry.applications.ux.DragDrop.implementation({ - dragSelector: ".item-container", + dragSelector: '.item-container', // dropSelector: ".directory-list", permissions: { - dragstart: this._canDragStart.bind(this), + dragstart: this._canDragStart.bind(this) // drop: this._canDragDrop.bind(this) }, callbacks: { // dragover: this._onDragOver.bind(this), - dragstart: this._onDragStart.bind(this), + dragstart: this._onDragStart.bind(this) // drop: this._onDrop.bind(this) } }).bind(this.element); @@ -349,10 +359,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { const dragData = foundry.utils.fromUuidSync(itemUuid).toDragData(); // console.log(dragData) // const dragData = { UUID: itemUuid }; - event.dataTransfer.setData("text/plain", JSON.stringify(dragData)); + event.dataTransfer.setData('text/plain', JSON.stringify(dragData)); } _canDragStart() { return true; } -} \ No newline at end of file +} diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less index eb9b761e..9b84f2ec 100644 --- a/styles/less/ui/item-browser/item-browser.less +++ b/styles/less/ui/item-browser/item-browser.less @@ -1,10 +1,12 @@ -@scrollbar-width: 20px; -#itemBrowser { +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; + +.application.daggerheart.dh-style.compendium-browser { border: initial; .window-content { display: flex; flex-direction: row; - gap: 50px; + padding: 0px; > div { overflow: hidden; @@ -13,80 +15,104 @@ gap: 20px; } - div[data-application-part="list"] { + div[data-application-part='list'] { flex: 1; gap: 10px; } - .compendium-container { - summary { - font-family: 'Montserrat', sans-serif; - font-weight: bold; - padding: 2px 12px; - border-radius: 3px; - background-color: light-dark(#18162e, #f3c267); - color: light-dark(#efe6d8, #18162e); - list-style: none; + .compedium-sidebar { + position: relative; + width: 200px; + padding: 16px; - &::marker, /* Latest Chrome, Edge, Firefox */ - &::-webkit-details-marker /* Safari */ { - display: none; - } + &::before { + content: ''; + position: absolute; + right: 0; + background: @golden; + mask-image: linear-gradient(180deg, transparent 0%, black 50%, transparent 100%); + width: 1px; + height: 100%; } - > .folder-list { - padding: 10px; - gap: 0; + .compendium-container { + summary { + display: flex; + flex-direction: column; + align-items: center; + gap: 5px; + font-family: @font-subtitle; + font-weight: bold; + padding: 2px 12px; + color: light-dark(@dark, @beige); + list-style: none; + cursor: pointer; - > div { - &.folder-list { - > div { - margin-top: 5px; - } + &::marker, // Latest Chrome, Edge, Firefox + &::-webkit-details-marker // Safari + { + display: none; } + } - &:not(.folder-list) { - margin-top: 10px; + > .folder-list { + padding: 10px; + gap: 0; + + > div { + &.folder-list { + > div { + margin-top: 5px; + } + } } } } } - .menu-path, option, select { + .compedium-results { + padding: 16px; + } + + .menu-path, + option, + select { text-transform: capitalize; } .menu-path > :first-child { - text-transform: uppercase; + font-weight: bold; } .menu-path { display: flex; align-items: center; - > span { - font-family: 'Montserrat', sans-serif; - font-weight: bold; - padding: 2px 12px; - border-radius: 3px; - background-color: light-dark(#18162e, #f3c267); - color: light-dark(#efe6d8, #18162e); + gap: 10px; + + .item-path { + font-family: @font-body; + color: light-dark(@dark, @beige); &.path-link { - padding: 0 5px; - background-color: light-dark(#f3c267, #18162e); - color: light-dark(#18162e, #efe6d8); + color: light-dark(@dark, @beige); } } } - .folder-list, .item-list-header, .item-header > div { + .folder-list, + .item-list-header, + .item-header > div { gap: 10px; cursor: pointer; } .item-filter { + display: flex; + align-items: center; + flex-direction: column; - .wrapper, .form-group { + .wrapper, + .form-group { display: flex; align-items: center; gap: 10px; @@ -100,6 +126,47 @@ display: flex; align-items: center; gap: 10px; + width: 100%; + + .search-bar { + position: relative; + color: light-dark(@dark-blue-50, @beige-50); + width: 100%; + + input { + border-radius: 50px; + font-family: @font-body; + background: light-dark(@dark-blue-10, @golden-10); + border: none; + outline: 2px solid transparent; + transition: all 0.3s ease; + padding: 0 20px; + width: 100%; + + &:hover { + outline: 2px solid light-dark(@dark, @golden); + } + + &:placeholder { + color: light-dark(@dark-blue-50, @beige-50); + } + + &::-webkit-search-cancel-button { + -webkit-appearance: none; + display: none; + } + } + + .icon { + align-content: center; + height: 32px; + position: absolute; + right: 20px; + font-size: 16px; + z-index: 1; + color: light-dark(@dark-blue-50, @beige-50); + } + } } } @@ -107,25 +174,36 @@ display: flex; flex-direction: column; [data-folder-id] { - padding: 2px 12px; + padding: 5px 10px; border: 1px solid transparent; + font-family: @font-body; + transition: all 0.1s ease; } - .is-selected, > [data-folder-id]:hover { + .is-selected, + [data-folder-id]:hover { font-weight: bold; border-radius: 3px; - background-color: light-dark(transparent, #18162e); - color: light-dark(#18162e, #f3c267); - border-color: light-dark(#18162e, #f3c267); + background-color: light-dark(@dark-blue-40, @golden-40); + color: light-dark(@dark-blue, @golden); } .subfolder-list { - margin: 0 10px; + margin: 5px 0; gap: 0; + + .is-selected, + [data-folder-id]:hover { + font-weight: bold; + border-radius: 3px; + background-color: light-dark(@dark-blue-10, @golden-10); + color: light-dark(@dark-blue, @golden); + } } } - .item-list-header, .item-header > div { + .item-list-header, + .item-header > div { display: grid; grid-template-columns: 40px 400px repeat(auto-fit, minmax(100px, 1fr)); align-items: center; @@ -133,9 +211,12 @@ // gap: 10px; } - .item-list-header, .item-list { + .item-list-header, + .item-list { overflow-y: auto; scrollbar-gutter: stable; + scrollbar-width: thin; + scrollbar-color: light-dark(@dark-blue, @golden) transparent; } .item-list-header { @@ -153,7 +234,7 @@ .item-container { &:hover { - background: rgba(255, 255, 255, .1); + background: rgba(255, 255, 255, 0.1); } } @@ -167,10 +248,11 @@ } .filter-content { - padding: 0 10px; + padding: 0px; } - .filter-content, .item-desc { + .filter-content, + .item-desc { display: grid; grid-template-rows: 0fr; transition: all 0.3s ease-in-out; @@ -178,13 +260,20 @@ overflow: hidden; display: grid; grid-template-columns: repeat(4, 1fr); + padding: 0; .form-group { label { flex: 1; + font-family: @font-body; } .form-fields { flex: 2; + + input[type='number'] { + text-align: center; + color: light-dark(@dark, @beige); + } } } } @@ -197,8 +286,20 @@ .welcome-message { display: flex; + flex-direction: column; + gap: 5px; align-items: center; justify-content: center; + height: -webkit-fill-available; + margin: 0; + + .title { + font-family: @font-subtitle; + margin: 0; + } + .hint { + font-family: @font-body; + } } } -} \ No newline at end of file +} diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index 33efe829..9550bb81 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -10,6 +10,9 @@ + + +