Add a RichEditor to make HTMLFields livable

This commit is contained in:
Oliver-Akins 2025-02-09 23:09:18 -07:00
parent f6ff3247e3
commit ced2b5151b
7 changed files with 137 additions and 0 deletions

View file

@ -0,0 +1,93 @@
/*
This Application is used by parts of the system to enable a better experience
while editing enriched text, because a lot of the spaces for text are really
small and are better served by a bigger text editor so that the controls are
more visible and doesn't cause as much overflow chaos.
*/
import { filePath } from "../consts.mjs";
const { HandlebarsApplicationMixin, DocumentSheetV2 } = foundry.applications.api;
const { hasProperty, getProperty } = foundry.utils;
export class RichEditor extends HandlebarsApplicationMixin(DocumentSheetV2) {
// #region Options
static DEFAULT_OPTIONS = {
classes: [
`ripcrypt`,
`ripcrypt--RichEditor`,
],
window: {
title: `Text Editor`,
frame: true,
positioned: true,
resizable: false,
minimizable: true,
},
position: {
width: `auto`,
height: `auto`,
},
actions: {},
form: {
submitOnChange: true,
closeOnSubmit: false,
},
};
static PARTS = {
editor: {
template: filePath(`templates/Apps/RichEditor/content.hbs`),
root: true,
},
};
// #endregion
// #region Instance Data
document;
path;
constructor(opts) {
const {
document,
path,
compact = false,
collaborative = true,
} = opts;
if (!hasProperty(document, path)) {
throw new Error(`Document provided to text editor must have the property specified by the path.`);
};
opts.sheetConfig = false;
super(opts);
this.compact = compact;
this.collaborative = collaborative;
this.document = document;
this.path = path;
};
// #endregion
// #region Lifecycle
async _preparePartContext(partId, ctx, _opts) {
ctx = {
uuid: this.document.uuid,
editable: true, // this.isEditable
collaborative: this.collaborative,
compact: this.compact,
path: this.path,
};
console.log({
doc: this.document,
path: this.path,
value: this.document.system.description,
});
const value = getProperty(this.document, this.path);
ctx.enriched = await TextEditor.enrichHTML(value);
ctx.raw = value;
return ctx;
};
// #endregion
};

View file

@ -3,6 +3,7 @@ import { CombinedHeroSheet } from "./Apps/ActorSheets/CombinedHeroSheet.mjs";
import { DicePool } from "./Apps/DicePool.mjs"; import { DicePool } from "./Apps/DicePool.mjs";
import { HeroSkillsCardV1 } from "./Apps/ActorSheets/HeroSkillsCardV1.mjs"; import { HeroSkillsCardV1 } from "./Apps/ActorSheets/HeroSkillsCardV1.mjs";
import { HeroSummaryCardV1 } from "./Apps/ActorSheets/HeroSummaryCardV1.mjs"; import { HeroSummaryCardV1 } from "./Apps/ActorSheets/HeroSummaryCardV1.mjs";
import { RichEditor } from "./Apps/RichEditor.mjs";
// Util imports // Util imports
import { documentSorter } from "./consts.mjs"; import { documentSorter } from "./consts.mjs";
@ -19,6 +20,7 @@ Object.defineProperty(
CombinedHeroSheet, CombinedHeroSheet,
HeroSummaryCardV1, HeroSummaryCardV1,
HeroSkillsCardV1, HeroSkillsCardV1,
RichEditor,
}, },
utils: { utils: {
documentSorter, documentSorter,

View file

@ -0,0 +1,16 @@
<div>
{{#if editable}}
<prose-mirror
name="{{ path }}"
value="{{ raw }}"
{{ifThen compact "compact" ""}}
{{#if collaborative}}
data-document-uuid="{{ uuid }}"
{{/if}}
>
{{{ enriched }}}
</prose-mirror>
{{else}}
{{{ enriched }}}
{{/if}}
</div>

View file

@ -0,0 +1,19 @@
.ripcrypt--RichEditor {
width: 500px;
height: 600px;
> .window-content {
padding: 4px;
background: var(--base-background);
height: 100%;
}
prose-mirror {
height: 100%;
.editor-content {
color: var(--input-text);
background: var(--input-background);
}
}
}

View file

@ -4,3 +4,4 @@
@import url("./DicePool/style.css"); @import url("./DicePool/style.css");
@import url("./HeroSummaryCardV1/style.css"); @import url("./HeroSummaryCardV1/style.css");
@import url("./HeroSkillsCardV1/style.css"); @import url("./HeroSkillsCardV1/style.css");
@import url("./RichEditor/style.css");

View file

@ -1,9 +1,12 @@
@layer exceptions;
@import url("./vars.css"); @import url("./vars.css");
@import url("./elements/button.css"); @import url("./elements/button.css");
@import url("./elements/input.css"); @import url("./elements/input.css");
@import url("./elements/lists.css"); @import url("./elements/lists.css");
@import url("./elements/pill-bar.css"); @import url("./elements/pill-bar.css");
@import url("./elements/prose-mirror.css") layer(exceptions);
@import url("./elements/select.css"); @import url("./elements/select.css");
@import url("./elements/span.css"); @import url("./elements/span.css");
@import url("./elements/string-tags.css"); @import url("./elements/string-tags.css");

View file

@ -0,0 +1,3 @@
.ripcrypt prose-mirror * {
all: revert-layer !important;
}