diff --git a/src/app/app.ts b/src/app/app.ts index 29871aeb..e83d98f4 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -8,6 +8,7 @@ import { SourceView } from '../view/SourceView' import { ListNode } from '../nodes/ListNode' import { BooleanNode } from '../nodes/BooleanNode' import { MapNode } from '../nodes/MapNode' +import { NumberNode } from '../nodes/NumberNode' const EntityCollection = ['sheep', 'pig'] @@ -15,6 +16,7 @@ const predicateTree = new RootNode('predicate', { condition: new EnumNode(['foo', 'bar'], { transform: (s: string) => (s === 'foo') ? {test: 'baz'} : s }), + number: new NumberNode({integer: false, min: 0}), predicate: new ObjectNode({ type: new EnumNode(EntityCollection), nbt: new StringNode(), diff --git a/src/model/DataModel.ts b/src/model/DataModel.ts index 7373db96..4e6b2b03 100644 --- a/src/model/DataModel.ts +++ b/src/model/DataModel.ts @@ -21,6 +21,7 @@ export class DataModel { } invalidate() { + console.log(this.data) this.listeners.forEach(listener => listener.invalidated(this)) } @@ -35,7 +36,7 @@ export class DataModel { console.log('Set', path.toString(), JSON.stringify(value)) - if (value === undefined) { + if (value === undefined || (typeof value === 'number' && isNaN(value))) { if (typeof path.last() === 'number') { node.splice(path.last(), 1) } else { diff --git a/src/nodes/AbstractNode.ts b/src/nodes/AbstractNode.ts index f00fce17..7fc4f55d 100644 --- a/src/nodes/AbstractNode.ts +++ b/src/nodes/AbstractNode.ts @@ -4,7 +4,7 @@ import { TreeView } from "../view/TreeView" export interface INode { setParent: (parent: INode) => void - default: () => T | null + default: () => T transform: (value: T) => any render: (path: Path, value: T, view: TreeView, options?: RenderOptions) => string renderRaw: (path: Path, value: T, view: TreeView, options?: RenderOptions) => string @@ -30,11 +30,11 @@ export interface NodeMods { export abstract class AbstractNode implements INode { parent?: INode - defaultMod: () => T | null + defaultMod: () => T transformMod: (v: T) => T - constructor(mods?: NodeMods, def?: () => T | null) { - this.defaultMod = mods?.default ? mods.default : def ? def : () => null + constructor(def: () => T, mods?: NodeMods) { + this.defaultMod = mods?.default ? mods.default : def this.transformMod = mods?.transform ? mods.transform : (v: T) => v } @@ -51,7 +51,7 @@ export abstract class AbstractNode implements INode { updateModel(el: Element, path: Path, model: DataModel) {} - default(): T | null { + default(): T { return this.defaultMod() } diff --git a/src/nodes/BooleanNode.ts b/src/nodes/BooleanNode.ts index c966f437..e74e9316 100644 --- a/src/nodes/BooleanNode.ts +++ b/src/nodes/BooleanNode.ts @@ -10,7 +10,7 @@ export class BooleanNode extends AbstractNode { force: boolean constructor(mods?: BooleanNodeMods) { - super(mods, () => false) + super(() => false, mods) this.force = (mods?.force === true) } diff --git a/src/nodes/EnumNode.ts b/src/nodes/EnumNode.ts index 47740fe6..68be30be 100644 --- a/src/nodes/EnumNode.ts +++ b/src/nodes/EnumNode.ts @@ -7,7 +7,7 @@ export class EnumNode extends AbstractNode implements StateNode protected options: string[] constructor(options: string[], mods?: NodeMods) { - super(mods, () => '') + super(() => '', mods) this.options = options } diff --git a/src/nodes/ListNode.ts b/src/nodes/ListNode.ts index b3551396..5bd6ef1d 100644 --- a/src/nodes/ListNode.ts +++ b/src/nodes/ListNode.ts @@ -8,7 +8,7 @@ export class ListNode extends AbstractNode { protected children: INode constructor(values: INode, mods?: NodeMods) { - super(mods, () => []) + super(() => [], mods) this.children = values } diff --git a/src/nodes/MapNode.ts b/src/nodes/MapNode.ts index 62f6989b..48a1b2b4 100644 --- a/src/nodes/MapNode.ts +++ b/src/nodes/MapNode.ts @@ -13,7 +13,7 @@ export class MapNode extends AbstractNode { protected values: INode constructor(keys: StateNode, values: INode, mods?: NodeMods) { - super(mods, () => ({})) + super(() => ({}), mods) this.keys = keys this.values = values } diff --git a/src/nodes/NumberNode.ts b/src/nodes/NumberNode.ts new file mode 100644 index 00000000..c11647ad --- /dev/null +++ b/src/nodes/NumberNode.ts @@ -0,0 +1,42 @@ +import { AbstractNode, NodeMods, RenderOptions, StateNode } from './AbstractNode' +import { Path } from '../model/Path' +import { DataModel } from '../model/DataModel' +import { TreeView } from '../view/TreeView' + +export interface NumberNodeMods extends NodeMods { + integer?: boolean + min?: number + max?: number +} + +export class NumberNode extends AbstractNode implements StateNode { + integer: boolean + min: number + max: number + + constructor(mods?: NumberNodeMods) { + super(() => 0, mods) + console.log(mods) + this.integer = mods?.integer ? mods.integer : false + this.min = mods?.min !== undefined ? mods.min : -Infinity + this.max = mods?.max !== undefined ? mods.max : Infinity + } + + getState(el: Element) { + const value = el.querySelector('input')!.value + const parsed = this.integer ? parseInt(value) : parseFloat(value) + console.log(this.min) + if (parsed < this.min) return this.min + if (parsed > this.max) return this.max + return parsed + } + + updateModel(el: Element, path: Path, model: DataModel) { + model.set(path, this.getState(el)) + } + + renderRaw(path: Path, value: number, view: TreeView, options?: RenderOptions) { + return `${options?.hideLabel ? `` : ``} + ` + } +} diff --git a/src/nodes/ObjectNode.ts b/src/nodes/ObjectNode.ts index 0a61ee1a..aed59487 100644 --- a/src/nodes/ObjectNode.ts +++ b/src/nodes/ObjectNode.ts @@ -10,7 +10,7 @@ export class ObjectNode extends AbstractNode { protected fields: NodeChildren constructor(fields: NodeChildren, mods?: NodeMods) { - super(mods, () => ({})) + super(() => ({}), mods) this.fields = fields Object.values(fields).forEach(child => { child.setParent(this) diff --git a/src/nodes/StringNode.ts b/src/nodes/StringNode.ts index b364f0e6..bdf85101 100644 --- a/src/nodes/StringNode.ts +++ b/src/nodes/StringNode.ts @@ -5,7 +5,7 @@ import { TreeView } from '../view/TreeView' export class StringNode extends AbstractNode implements StateNode { constructor(mods?: NodeMods) { - super(mods, () => '') + super(() => '', mods) } getState(el: Element) {