Fix breaklines in character-config and fix DOM reactivity with children updates.
This commit is contained in:
parent
97578132bb
commit
1b0b9ca7f4
File diff suppressed because one or more lines are too long
|
|
@ -1757,8 +1757,8 @@ export class CharacterSheet
|
||||||
return [
|
return [
|
||||||
div('flex flex-col gap-2', [
|
div('flex flex-col gap-2', [
|
||||||
div('flex flex-row justify-end items-center gap-8', [
|
div('flex flex-row justify-end items-center gap-8', [
|
||||||
dom('span', { class: () => ['italic text-sm', { 'text-light-red dark:text-dark-red': weight > character.itempower }], text: () => `Poids total: ${weight}/${character.itempower}` }),
|
dom('span', { class: ['italic text-sm', () => ({ 'text-light-red dark:text-dark-red': weight > character.itempower })], text: () => `Poids total: ${weight}/${character.itempower}` }),
|
||||||
dom('span', { class: () => ['italic text-sm', { 'text-light-red dark:text-dark-red': power > (character.capacity === false ? 0 : character.capacity) }], text: () => `Puissance magique: ${power}/${character.capacity}` }),
|
dom('span', { class: ['italic text-sm', () => ({ 'text-light-red dark:text-dark-red': power > (character.capacity === false ? 0 : character.capacity) })], text: () => `Puissance magique: ${power}/${character.capacity}` }),
|
||||||
button(text('Modifier'), () => this.itemsPanel(character), 'py-1 px-4'),
|
button(text('Modifier'), () => this.itemsPanel(character), 'py-1 px-4'),
|
||||||
]),
|
]),
|
||||||
div('flex flex-col flex-1 divide-y divide-light-35 dark:divide-dark-35', { list: character.variables.items, redraw: true, render: e => {
|
div('flex flex-col flex-1 divide-y divide-light-35 dark:divide-dark-35', { list: character.variables.items, redraw: true, render: e => {
|
||||||
|
|
@ -1768,21 +1768,31 @@ export class CharacterSheet
|
||||||
|
|
||||||
const price = div(() => ['flex flex-row min-w-16 gap-2 justify-between items-center px-2', { 'cursor-help': e.amount > 1 && !!item.price }], [ icon('ph:coin', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span(() => ({ 'underline decoration-1 decoration-dotted underline-offset-2': e.amount > 1 && !!item.price }), () => item.price ? `${item.price * e.amount}` : '-') ]);
|
const price = div(() => ['flex flex-row min-w-16 gap-2 justify-between items-center px-2', { 'cursor-help': e.amount > 1 && !!item.price }], [ icon('ph:coin', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span(() => ({ 'underline decoration-1 decoration-dotted underline-offset-2': e.amount > 1 && !!item.price }), () => item.price ? `${item.price * e.amount}` : '-') ]);
|
||||||
const weight = div(() => ['flex flex-row min-w-16 gap-2 justify-between items-center px-2', { 'cursor-help': e.amount > 1 && !!item.weight }], [ icon('mdi:weight', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span(() => ({ 'underline decoration-1 decoration-dotted underline-offset-2': e.amount > 1 && !!item.weight }), () => item.weight ? `${item.weight * e.amount}` : '-') ]);
|
const weight = div(() => ['flex flex-row min-w-16 gap-2 justify-between items-center px-2', { 'cursor-help': e.amount > 1 && !!item.weight }], [ icon('mdi:weight', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span(() => ({ 'underline decoration-1 decoration-dotted underline-offset-2': e.amount > 1 && !!item.weight }), () => item.weight ? `${item.weight * e.amount}` : '-') ]);
|
||||||
return foldable(() => [
|
return foldable(() => [
|
||||||
markdown(getText(item.description)),
|
markdown(getText(item.description)),
|
||||||
div('flex flex-row justify-center', [
|
div('flex flex-row justify-center gap-1', [
|
||||||
this.character?.character.campaign ? button(text('Partager'), () => {
|
this.character?.character.campaign ? button(text('Partager'), () => {
|
||||||
|
|
||||||
}, 'p-1') : undefined,
|
}, 'px-2 text-sm h-5 box-content') : undefined,
|
||||||
button(icon('radix-icons:trash'), () => {
|
button(icon('radix-icons:minus', { width: 12, height: 12 }), () => {
|
||||||
const idx = items.findIndex(_e => _e === e);
|
const idx = items.findIndex(_e => _e === e);
|
||||||
if(idx === -1) return;
|
if(idx === -1) return;
|
||||||
|
|
||||||
items[idx]!.amount--;
|
items[idx]!.amount--;
|
||||||
if(items[idx]!.amount >= 0) items.splice(idx, 1);
|
if(items[idx]!.amount <= 0) items.splice(idx, 1);
|
||||||
|
else (items as DOMList<ItemState>)?.render();
|
||||||
|
|
||||||
this.character!.variable('items', items);
|
this.character!.variable('items', items);
|
||||||
}, 'p-1'),
|
}, 'p-1'),
|
||||||
|
button(icon('radix-icons:plus', { width: 12, height: 12 }), () => {
|
||||||
|
const idx = items.findIndex(_e => _e === e);
|
||||||
|
if(idx === -1) return;
|
||||||
|
|
||||||
|
if(item.equippable) items.push({ id: item.id, amount: 1, charges: item.charge, enchantments: [], equipped: false });
|
||||||
|
else if(items.find(_e => _e === e)) { items.find(_e => _e === e)!.amount++; (items as DOMList<ItemState>)?.render(); }
|
||||||
|
else items.push({ id: item.id, amount: 1, charges: item.charge, enchantments: [] });
|
||||||
|
this.character!.variable('items', items);
|
||||||
|
}, 'p-1'),
|
||||||
]) ], [div('flex flex-row justify-between', [
|
]) ], [div('flex flex-row justify-between', [
|
||||||
div('flex flex-row items-center gap-4', [
|
div('flex flex-row items-center gap-4', [
|
||||||
item.equippable ? checkbox({ defaultValue: e.equipped, change: v => {
|
item.equippable ? checkbox({ defaultValue: e.equipped, change: v => {
|
||||||
|
|
@ -1794,10 +1804,10 @@ export class CharacterSheet
|
||||||
]),
|
]),
|
||||||
div('flex flex-row items-center divide-x divide-light-50 dark:divide-dark-50 divide-dashed px-2', [
|
div('flex flex-row items-center divide-x divide-light-50 dark:divide-dark-50 divide-dashed px-2', [
|
||||||
e.amount > 1 && !!item.price ? tooltip(price, `Prix unitaire: ${item.price}`, 'bottom') : price,
|
e.amount > 1 && !!item.price ? tooltip(price, `Prix unitaire: ${item.price}`, 'bottom') : price,
|
||||||
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('radix-icons:cross-2', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', e.amount?.toString() ?? '-') ]),
|
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('radix-icons:cross-2', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', () => e.amount?.toString() ?? '-') ]),
|
||||||
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:bolt-drop', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', item.powercost || item.capacity ? `${item.powercost ?? 0}/${item.capacity ?? 0}` : '-') ]),
|
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:bolt-drop', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', () => item.powercost || item.capacity ? `${item.powercost ?? 0}/${item.capacity ?? 0}` : '-') ]),
|
||||||
e.amount > 1 && !!item.weight ? tooltip(weight, `Poids unitaire: ${item.weight}`, 'bottom') : weight,
|
e.amount > 1 && !!item.weight ? tooltip(weight, `Poids unitaire: ${item.weight}`, 'bottom') : weight,
|
||||||
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:battery-pack', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', item.charge ? `${item.charge}` : '-') ]),
|
div('flex flex-row min-w-16 gap-2 justify-between items-center px-2', [ icon('game-icons:battery-pack', { width: 16, height: 16, class: 'text-light-70 dark:text-dark-70' }), span('', () => item.charge ? `${item.charge}` : '-') ]),
|
||||||
]),
|
]),
|
||||||
])], { open: false, class: { icon: 'px-2', container: 'p-1 gap-2', content: 'px-4 pb-1 flex flex-col' } })
|
])], { open: false, class: { icon: 'px-2', container: 'p-1 gap-2', content: 'px-4 pb-1 flex flex-col' } })
|
||||||
}})
|
}})
|
||||||
|
|
|
||||||
|
|
@ -446,7 +446,7 @@ export function foldable(content: NodeChildren | (() => NodeChildren), title: No
|
||||||
}
|
}
|
||||||
const contentContainer = div(['hidden group-data-[active]:flex', settings?.class?.content]);
|
const contentContainer = div(['hidden group-data-[active]:flex', settings?.class?.content]);
|
||||||
const fold = div(['group flex w-full flex-col', settings?.class?.container], [
|
const fold = div(['group flex w-full flex-col', settings?.class?.container], [
|
||||||
div('flex', [ dom('div', { listeners: { click: () => { display(fold.toggleAttribute('data-active')) } }, class: ['flex justify-center items-center', settings?.class?.icon] }, [ icon('radix-icons:caret-right', { class: 'group-data-[active]:rotate-90 origin-center', noobserver: true }) ]), div(['flex-1', settings?.class?.title], title) ]),
|
div('flex', [ dom('div', { listeners: { click: () => { display(fold.toggleAttribute('data-active')) } }, class: ['flex justify-center items-center', settings?.class?.icon] }, [ icon('radix-icons:caret-right', { class: 'group-data-[active]:rotate-90 origin-center' }) ]), div(['flex-1', settings?.class?.title], title) ]),
|
||||||
contentContainer
|
contentContainer
|
||||||
]);
|
]);
|
||||||
display(settings?.open ?? true);
|
display(settings?.open ?? true);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { iconLoaded, loadIcon } from 'iconify-icon';
|
import { iconLoaded, loadIcon } from 'iconify-icon';
|
||||||
|
|
||||||
export type RedrawableHTML<T extends keyof HTMLElementTagNameMap> = HTMLElementTagNameMap[T] & { update: (recursive: boolean) => void }
|
export type RedrawableHTML<T extends keyof HTMLElementTagNameMap> = HTMLElementTagNameMap[T] & { update: (recursive: boolean) => void }
|
||||||
export type Node = RedrawableHTML<any> & { update: (recursive: boolean) => void } | SVGElement | Text | undefined;
|
export type Node<T extends keyof HTMLElementTagNameMap = any> = RedrawableHTML<T> & { update: (recursive: boolean) => void } | SVGElement | Text | undefined;
|
||||||
export type NodeChildren = Array<Node> | undefined;
|
export type NodeChildren = Array<Node> | undefined;
|
||||||
|
|
||||||
export type Class = Reactive<string | Array<Class> | Record<string, boolean> | undefined>;
|
export type Class = Reactive<string | Array<Class> | Record<string, boolean> | undefined>;
|
||||||
|
|
@ -26,6 +26,21 @@ export interface NodeProperties
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let defered = false, _set = new Set<() => void>();
|
||||||
|
const _defer = (fn: () => void) => {
|
||||||
|
if(!defered)
|
||||||
|
{
|
||||||
|
defered = true;
|
||||||
|
queueMicrotask(() => {
|
||||||
|
_set.forEach(e => e());
|
||||||
|
_set.clear();
|
||||||
|
defered = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_set.add(fn);
|
||||||
|
}
|
||||||
|
|
||||||
export const cancelPropagation = (e: Event) => e.stopImmediatePropagation();
|
export const cancelPropagation = (e: Event) => e.stopImmediatePropagation();
|
||||||
export function dom<T extends keyof HTMLElementTagNameMap>(tag: T, properties?: NodeProperties, children?: NodeChildren): RedrawableHTML<T>;
|
export function dom<T extends keyof HTMLElementTagNameMap>(tag: T, properties?: NodeProperties, children?: NodeChildren): RedrawableHTML<T>;
|
||||||
export function dom<T extends keyof HTMLElementTagNameMap, U extends any>(tag: T, properties?: NodeProperties, children?: { render: (data: U) => Node, list?: Array<U>, redraw?: boolean }): RedrawableHTML<T> & { array?: DOMList<U> };
|
export function dom<T extends keyof HTMLElementTagNameMap, U extends any>(tag: T, properties?: NodeProperties, children?: { render: (data: U) => Node, list?: Array<U>, redraw?: boolean }): RedrawableHTML<T> & { array?: DOMList<U> };
|
||||||
|
|
@ -41,7 +56,6 @@ export function dom<T extends keyof HTMLElementTagNameMap, U extends any>(tag: T
|
||||||
|
|
||||||
if(children !== undefined && (setup || recursive))
|
if(children !== undefined && (setup || recursive))
|
||||||
{
|
{
|
||||||
element.replaceChildren();
|
|
||||||
if(Array.isArray(children))
|
if(Array.isArray(children))
|
||||||
{
|
{
|
||||||
for(const c of children)
|
for(const c of children)
|
||||||
|
|
@ -49,43 +63,40 @@ export function dom<T extends keyof HTMLElementTagNameMap, U extends any>(tag: T
|
||||||
if(c !== undefined)
|
if(c !== undefined)
|
||||||
{
|
{
|
||||||
element.appendChild(c);
|
element.appendChild(c);
|
||||||
recursive && 'update' in c && c.update(true);
|
recursive && 'update' in c && _defer(() => c.update(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(children.list !== undefined)
|
else if(children.list !== undefined)
|
||||||
{
|
{
|
||||||
if(setup || recursive)
|
|
||||||
{
|
|
||||||
_cache.clear();
|
|
||||||
children.list.forEach(e => _cache.set(e, children.render(e)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(setup)
|
if(setup)
|
||||||
{
|
{
|
||||||
|
children.list.forEach(e => _cache.set(e, children.render(e)));
|
||||||
|
|
||||||
const _push = children.list.push;
|
const _push = children.list.push;
|
||||||
children.list.push = (...items: U[]) => {
|
children.list.push = (...items: U[]) => {
|
||||||
items.forEach(e => {
|
items.forEach(e => {
|
||||||
const dom = children.render(e);
|
if(!_cache.has(e)) _cache.set(e, element.appendChild(children.render(e)));
|
||||||
_cache.set(e, dom);
|
else element.appendChild(_cache.get(e));
|
||||||
dom && element.appendChild(dom);
|
|
||||||
});
|
});
|
||||||
if(children.redraw) update(false);
|
if(children.redraw) _defer(() => update(false));
|
||||||
return _push.bind(children.list)(...items);
|
return _push.bind(children.list)(...items);
|
||||||
};
|
};
|
||||||
const _splice = children.list.splice;
|
const _splice = children.list.splice;
|
||||||
children.list.splice = (start: number, deleteCount: number, ...items: U[]) => {
|
children.list.splice = (start: number, deleteCount: number, ...items: U[]) => {
|
||||||
const list = _splice.bind(children.list)(start, deleteCount, ...items);
|
const list = _splice.bind(children.list)(start, deleteCount, ...items);
|
||||||
list.forEach(e => _cache.get(e)?.remove() || _cache.delete(e));
|
list.forEach(e => { if(!children.list!.find(_e => _e === e)) _cache.delete(e); });
|
||||||
if(children.redraw) update(false);
|
element.array!.render();
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if(recursive)
|
||||||
|
_cache.forEach((v, k) => v && 'update' in v && v.update(true));
|
||||||
|
|
||||||
element.array = children.list as DOMList<U>;
|
element.array = children.list as DOMList<U>;
|
||||||
element.array.render = (redraw?: boolean) => {
|
element.array.render = (redraw?: boolean) => {
|
||||||
element.replaceChildren(...children.list?.map(e => _cache.get(e)).filter(e => !!e) ?? []);
|
element.replaceChildren(...children.list?.map(e => _cache.get(e)).filter(e => !!e) ?? []);
|
||||||
if((redraw !== undefined || children.redraw !== undefined) && !updating) update(redraw ?? children.redraw!);
|
if((redraw !== undefined || children.redraw !== undefined) && !updating) _defer(() => update(redraw ?? children.redraw!));
|
||||||
}
|
}
|
||||||
|
|
||||||
element.array.render();
|
element.array.render();
|
||||||
|
|
@ -113,7 +124,7 @@ export function dom<T extends keyof HTMLElementTagNameMap, U extends any>(tag: T
|
||||||
element.appendChild(text as Text);
|
element.appendChild(text as Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(properties?.listeners)
|
if(properties?.listeners && setup)
|
||||||
{
|
{
|
||||||
for(let [k, v] of Object.entries(properties.listeners))
|
for(let [k, v] of Object.entries(properties.listeners))
|
||||||
{
|
{
|
||||||
|
|
@ -264,7 +275,7 @@ export function text(data: any, _txt?: Reactive<string>): Text
|
||||||
}
|
}
|
||||||
else return document.createTextNode('');
|
else return document.createTextNode('');
|
||||||
}
|
}
|
||||||
export function styling(element: SVGElement | RedrawableHTML<any>, properties: {
|
export function styling(element: SVGElement | RedrawableHTML<keyof HTMLElementTagNameMap>, properties: {
|
||||||
class?: Class;
|
class?: Class;
|
||||||
style?: Reactive<Record<string, string | undefined | boolean | number> | string>;
|
style?: Reactive<Record<string, string | undefined | boolean | number> | string>;
|
||||||
}): SVGElement | HTMLElement
|
}): SVGElement | HTMLElement
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue