Merge pull request #30 from Oliver-Akins/GH-19
Ask Application Block Improvements
This commit is contained in:
commit
ab14729e91
16 changed files with 182 additions and 35 deletions
|
|
@ -2,6 +2,15 @@ import { __ID__, filePath } from "../consts.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
const validInputTypes = [
|
||||||
|
`checkbox`,
|
||||||
|
`details`,
|
||||||
|
`divider`,
|
||||||
|
`error`,
|
||||||
|
`input`,
|
||||||
|
`select`,
|
||||||
|
];
|
||||||
|
|
||||||
export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
tag: `dialog`,
|
tag: `dialog`,
|
||||||
|
|
@ -32,11 +41,7 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
inputs: {
|
inputs: {
|
||||||
template: filePath(`templates/Ask/inputs.hbs`),
|
template: filePath(`templates/Ask/inputs.hbs`),
|
||||||
templates: [
|
templates: validInputTypes.map(type => filePath(`templates/Ask/inputs/${type}.hbs`)),
|
||||||
filePath(`templates/Ask/inputs/checkbox.hbs`),
|
|
||||||
filePath(`templates/Ask/inputs/details.hbs`),
|
|
||||||
filePath(`templates/Ask/inputs/input.hbs`),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
controls: {
|
controls: {
|
||||||
template: filePath(`templates/Ask/controls.hbs`),
|
template: filePath(`templates/Ask/controls.hbs`),
|
||||||
|
|
@ -69,6 +74,14 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
} = {}) {
|
} = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
this.alwaysUseAnswerObject = alwaysUseAnswerObject;
|
this.alwaysUseAnswerObject = alwaysUseAnswerObject;
|
||||||
|
|
||||||
|
for (const input of inputs) {
|
||||||
|
if (!validInputTypes.includes(input.type)) {
|
||||||
|
input.details = `Invalid input type provided: ${input.type}`;
|
||||||
|
input.type = `error`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
this._inputs = inputs;
|
this._inputs = inputs;
|
||||||
this._description = description;
|
this._description = description;
|
||||||
this._userOnCancel = onCancel;
|
this._userOnCancel = onCancel;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { filePath } from "../consts.mjs";
|
import { filePath } from "../consts.mjs";
|
||||||
|
import { options } from "./options.mjs";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
systemFilePath: filePath,
|
systemFilePath: filePath,
|
||||||
|
"taf-options": options,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
34
module/handlebarsHelpers/options.mjs
Normal file
34
module/handlebarsHelpers/options.mjs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* @typedef {object} Option
|
||||||
|
* @property {string} [label]
|
||||||
|
* @property {string|number} value
|
||||||
|
* @property {boolean} [disabled]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string | number} selected The selected value
|
||||||
|
* @param {Array<Option | string>} opts The options that are valid
|
||||||
|
* @param {any} meta The Handlebars meta processing
|
||||||
|
*/
|
||||||
|
export function options(selected, opts, meta) {
|
||||||
|
const { localize = false } = meta.hash;
|
||||||
|
selected = Handlebars.escapeExpression(selected);
|
||||||
|
const htmlOptions = [];
|
||||||
|
|
||||||
|
for (let opt of opts) {
|
||||||
|
if (typeof opt === `string`) {
|
||||||
|
opt = { label: opt, value: opt };
|
||||||
|
};
|
||||||
|
opt.value = Handlebars.escapeExpression(opt.value);
|
||||||
|
htmlOptions.push(
|
||||||
|
`<option
|
||||||
|
value="${opt.value}"
|
||||||
|
${selected === opt.value ? `selected` : ``}
|
||||||
|
${opt.disabled ? `disabled` : ``}
|
||||||
|
>
|
||||||
|
${localize ? game.i18n.format(opt.label) : opt.label}
|
||||||
|
</option>`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return new Handlebars.SafeString(htmlOptions.join(`\n`));
|
||||||
|
};
|
||||||
|
|
@ -36,8 +36,19 @@
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
grid-column: 1 / -1;
|
|
||||||
text-indent: 1em;
|
text-indent: 1em;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding: 6px 8px;
|
||||||
|
box-shadow: 0 0 10px var(--color-shadow-dark);
|
||||||
|
color: var(--color-text-light-1);
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--color-level-error-bg);
|
||||||
|
border: 1px solid var(--color-level-error);
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
|
|
|
||||||
7
styles/elements/hr.css
Normal file
7
styles/elements/hr.css
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
.taf > .window-content hr {
|
||||||
|
height: 1px;
|
||||||
|
background: rebeccapurple;
|
||||||
|
border-radius: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
@ -3,4 +3,54 @@
|
||||||
--input-height: 2.5rem;
|
--input-height: 2.5rem;
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[type="checkbox"] {
|
||||||
|
--checkbox-checked-color: var(--color-warm-1);
|
||||||
|
width: var(--checkbox-size);
|
||||||
|
height: var(--checkbox-size);
|
||||||
|
background: var(--input-background-color);
|
||||||
|
border: 2px solid var(--color-cool-3);
|
||||||
|
position: relative;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::before, &::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--checkbox-checked-color);
|
||||||
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked::after {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
inset: 4px;
|
||||||
|
z-index: 1;
|
||||||
|
content: "";
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--checkbox-checked-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
content: "";
|
||||||
|
background: var(--color-level-error-bg);
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
@layer resets, themes, elements, components, partials, apps, exceptions;
|
@layer resets, themes, elements, components, partials, apps, exceptions;
|
||||||
|
|
||||||
|
/* Resets */
|
||||||
|
@import url("./resets/hr.css") layer(resets);
|
||||||
|
@import url("./resets/inputs.css") layer(resets);
|
||||||
|
|
||||||
/* Themes */
|
/* Themes */
|
||||||
@import url("./themes/dark.css") layer(themes);
|
@import url("./themes/dark.css") layer(themes);
|
||||||
@import url("./themes/light.css") layer(themes);
|
@import url("./themes/light.css") layer(themes);
|
||||||
|
|
||||||
/* Elements */
|
/* Elements */
|
||||||
@import url("./elements/headers.css") layer(elements);
|
@import url("./elements/headers.css") layer(elements);
|
||||||
|
@import url("./elements/hr.css") layer(elements);
|
||||||
@import url("./elements/input.css") layer(elements);
|
@import url("./elements/input.css") layer(elements);
|
||||||
@import url("./elements/p.css") layer(elements);
|
@import url("./elements/p.css") layer(elements);
|
||||||
@import url("./elements/prose-mirror.css") layer(elements);
|
@import url("./elements/prose-mirror.css") layer(elements);
|
||||||
|
|
|
||||||
3
styles/resets/hr.css
Normal file
3
styles/resets/hr.css
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
.taf > .window-content hr {
|
||||||
|
all: initial;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
.taf > .window-content {
|
.taf > .window-content {
|
||||||
button, input {
|
input[type="checkbox"] {
|
||||||
all: initial;
|
all: initial;
|
||||||
|
&::after, &::before {
|
||||||
|
all: initial;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
</p>
|
</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#each inputs as | i |}}
|
{{#each inputs as | i |}}
|
||||||
<div class="prompt">
|
{{> (concat (systemFilePath "templates/Ask/inputs/" ) i.type ".hbs") i}}
|
||||||
{{> (concat (systemFilePath "templates/Ask/inputs/" ) i.type ".hbs") i}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<label
|
<div class="prompt">
|
||||||
for="{{id}}"
|
<label
|
||||||
>
|
for="{{id}}"
|
||||||
{{ label }}
|
>
|
||||||
</label>
|
{{ label }}
|
||||||
<input
|
</label>
|
||||||
type="checkbox"
|
<input
|
||||||
id="{{ id }}"
|
type="checkbox"
|
||||||
name="{{ key }}"
|
id="{{ id }}"
|
||||||
{{ checked defaultValue }}
|
name="{{ key }}"
|
||||||
{{#if autofocus}}autofocus{{/if}}
|
{{ checked defaultValue }}
|
||||||
>
|
{{#if autofocus}}autofocus{{/if}}
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<p class="prompt__details">
|
<p>
|
||||||
{{{ details }}}
|
{{{ details }}}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
1
templates/Ask/inputs/divider.hbs
Normal file
1
templates/Ask/inputs/divider.hbs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<hr>
|
||||||
3
templates/Ask/inputs/error.hbs
Normal file
3
templates/Ask/inputs/error.hbs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<p class="error">
|
||||||
|
{{ details }}
|
||||||
|
</p>
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<label
|
<div class="prompt">
|
||||||
for="{{id}}"
|
<label
|
||||||
>
|
for="{{id}}"
|
||||||
{{ label }}
|
>
|
||||||
</label>
|
{{ label }}
|
||||||
<input
|
</label>
|
||||||
type="{{ inputType }}"
|
<input
|
||||||
id="{{ id }}"
|
type="{{ inputType }}"
|
||||||
name="{{ key }}"
|
id="{{ id }}"
|
||||||
{{ valueAttribute }}="{{ defaultValue }}"
|
name="{{ key }}"
|
||||||
{{#if autofocus}}autofocus{{/if}}
|
{{ valueAttribute }}="{{ defaultValue }}"
|
||||||
>
|
{{#if autofocus}}autofocus{{/if}}
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
13
templates/Ask/inputs/select.hbs
Normal file
13
templates/Ask/inputs/select.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="prompt">
|
||||||
|
<label
|
||||||
|
for="{{id}}"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="{{ id }}"
|
||||||
|
name="{{ key }}"
|
||||||
|
>
|
||||||
|
{{ taf-options defaultValue options }}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue