@revisium/schema-toolkit-ui 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as mobx from "mobx";
2
- import { action, computed, makeAutoObservable, makeObservable, observable, reaction, runInAction } from "mobx";
3
- import { FIELD_NAME_ERROR_MESSAGE, JsonSchemaTypeName, SystemSchemaIds, createTableModel, fileSchema, generateDefaultValue, isValidFieldName, jsonPointerToSimplePath, rowCreatedAtSchema, rowCreatedIdSchema, rowHashSchema, rowIdSchema, rowPublishedAtSchema, rowSchemaHashSchema, rowUpdatedAtSchema, rowVersionIdSchema, validateFormulaAgainstSchema } from "@revisium/schema-toolkit";
2
+ import { makeAutoObservable, observable, reaction, runInAction } from "mobx";
3
+ import { FIELD_NAME_ERROR_MESSAGE, SystemSchemaIds, createTableModel, fileSchema, generateDefaultValue, isValidFieldName, jsonPointerToSimplePath, rowCreatedAtSchema, rowCreatedIdSchema, rowHashSchema, rowIdSchema, rowPublishedAtSchema, rowSchemaHashSchema, rowUpdatedAtSchema, rowVersionIdSchema, validateFormulaAgainstSchema } from "@revisium/schema-toolkit";
4
4
  import { createMobxProvider, setReactivityProvider } from "@revisium/schema-toolkit/core";
5
5
  import { Badge, Box, Button, Flex, Icon, IconButton, Input, Menu, Popover, Portal, SegmentGroup, Text, Textarea, Tooltip as Tooltip$1, VStack } from "@chakra-ui/react";
6
6
  import { observer } from "mobx-react-lite";
@@ -16,7 +16,8 @@ import { Menu as Menu$1 } from "@chakra-ui/react/menu";
16
16
  import { LuChevronRight } from "react-icons/lu";
17
17
  import { draggable, dropTargetForElements, monitorForElements } from "@atlaskit/drag-and-drop/adapter/element";
18
18
  import { DialogBackdrop, DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogPositioner, DialogRoot, DialogTitle } from "@chakra-ui/react/dialog";
19
- import { evaluateWithContext, parseExpression } from "@revisium/formula";
19
+
20
+ export * from "@revisium/schema-toolkit"
20
21
 
21
22
  //#region src/schema-editor/model/state/TreeState.ts
22
23
  var TreeState = class {
@@ -3191,11 +3192,13 @@ const DescriptionSubmenu = observer(({ accessor, dataTestId }) => {
3191
3192
  onKeyDown: stopPropagation,
3192
3193
  onKeyUp: stopPropagation,
3193
3194
  rows: 3,
3194
- autoFocus: true,
3195
- onFocus: (e) => {
3196
- const len = e.currentTarget.value.length;
3197
- e.currentTarget.setSelectionRange(len, len);
3198
- },
3195
+ ref: useCallback((el) => {
3196
+ if (el) requestAnimationFrame(() => {
3197
+ el.focus({ preventScroll: true });
3198
+ const len = el.value.length;
3199
+ el.setSelectionRange(len, len);
3200
+ });
3201
+ }, []),
3199
3202
  "data-testid": `${dataTestId}-description-input`
3200
3203
  })
3201
3204
  }) }) })]
@@ -3250,11 +3253,13 @@ const FormulaInput = observer(({ accessor, dataTestId }) => {
3250
3253
  onChange: handleChange,
3251
3254
  onKeyDown: stopPropagation,
3252
3255
  onKeyUp: stopPropagation,
3253
- autoFocus: true,
3254
- onFocus: (e) => {
3255
- const len = e.currentTarget.value.length;
3256
- e.currentTarget.setSelectionRange(len, len);
3257
- },
3256
+ ref: useCallback((el) => {
3257
+ if (el) requestAnimationFrame(() => {
3258
+ el.focus({ preventScroll: true });
3259
+ const len = el.value.length;
3260
+ el.setSelectionRange(len, len);
3261
+ });
3262
+ }, []),
3258
3263
  rows: 2,
3259
3264
  borderColor: hasError ? "red.300" : void 0,
3260
3265
  "data-testid": `${dataTestId}-formula-input`
@@ -3381,7 +3386,11 @@ const DefaultValueSubmenu = observer(({ accessor, dataTestId }) => {
3381
3386
  onBlur: handleBlur,
3382
3387
  onKeyDown: stopPropagation,
3383
3388
  onKeyUp: stopPropagation,
3384
- autoFocus: true,
3389
+ ref: useCallback((el) => {
3390
+ if (el) requestAnimationFrame(() => {
3391
+ el.focus({ preventScroll: true });
3392
+ });
3393
+ }, []),
3385
3394
  "data-testid": `${dataTestId}-default-input`
3386
3395
  })
3387
3396
  }) }) })]
@@ -4578,1501 +4587,5 @@ const UpdatingSchemaEditor = observer(({ vm }) => {
4578
4587
  });
4579
4588
 
4580
4589
  //#endregion
4581
- //#region src/value-model/node/BaseValueNode.ts
4582
- let nodeIdCounter = 0;
4583
- function generateNodeId() {
4584
- return `node-${++nodeIdCounter}`;
4585
- }
4586
- var BaseValueNode = class {
4587
- id;
4588
- schema;
4589
- _parent = null;
4590
- _name;
4591
- constructor(id, name, schema) {
4592
- this.id = id ?? generateNodeId();
4593
- this._name = name;
4594
- this.schema = schema;
4595
- }
4596
- get parent() {
4597
- return this._parent;
4598
- }
4599
- set parent(value) {
4600
- this._parent = value;
4601
- }
4602
- get name() {
4603
- return this._name;
4604
- }
4605
- isObject() {
4606
- return false;
4607
- }
4608
- isArray() {
4609
- return false;
4610
- }
4611
- isPrimitive() {
4612
- return false;
4613
- }
4614
- get errors() {
4615
- return [];
4616
- }
4617
- get warnings() {
4618
- return [];
4619
- }
4620
- get isValid() {
4621
- return this.errors.length === 0;
4622
- }
4623
- get hasWarnings() {
4624
- return this.warnings.length > 0;
4625
- }
4626
- };
4627
-
4628
- //#endregion
4629
- //#region src/value-model/node/BasePrimitiveValueNode.ts
4630
- var BasePrimitiveValueNode = class extends BaseValueNode {
4631
- _value;
4632
- _baseValue;
4633
- _formulaWarning = null;
4634
- constructor(id, name, schema, value, defaultValue) {
4635
- super(id, name, schema);
4636
- const initialValue = value ?? schema.default ?? defaultValue;
4637
- this._value = initialValue;
4638
- this._baseValue = initialValue;
4639
- }
4640
- initObservable() {
4641
- makeObservable(this, {
4642
- _value: observable,
4643
- _baseValue: observable,
4644
- _formulaWarning: observable,
4645
- value: computed,
4646
- baseValue: computed,
4647
- isDirty: computed,
4648
- errors: computed,
4649
- warnings: computed,
4650
- setValue: action,
4651
- setFormulaWarning: action,
4652
- commit: action,
4653
- revert: action
4654
- });
4655
- }
4656
- get value() {
4657
- return this._value;
4658
- }
4659
- set value(newValue) {
4660
- if (this.isReadOnly) throw new Error(`Cannot set value on read-only field: ${this.name}`);
4661
- this._value = newValue;
4662
- }
4663
- get baseValue() {
4664
- return this._baseValue;
4665
- }
4666
- get isDirty() {
4667
- return this._value !== this._baseValue;
4668
- }
4669
- get formula() {
4670
- const xFormula = this.schema["x-formula"];
4671
- if (xFormula) return {
4672
- expression: xFormula.expression,
4673
- version: xFormula.version
4674
- };
4675
- }
4676
- get formulaWarning() {
4677
- return this._formulaWarning;
4678
- }
4679
- get isReadOnly() {
4680
- return this.schema.readOnly === true || this.formula !== void 0;
4681
- }
4682
- getPlainValue() {
4683
- return this._value;
4684
- }
4685
- setValue(value, options) {
4686
- if (this.isReadOnly && !options?.internal) throw new Error(`Cannot set value on read-only field: ${this.name}`);
4687
- this._value = this.coerceValue(value);
4688
- }
4689
- setFormulaWarning(warning) {
4690
- this._formulaWarning = warning;
4691
- }
4692
- commit() {
4693
- this._baseValue = this._value;
4694
- }
4695
- revert() {
4696
- this._value = this._baseValue;
4697
- }
4698
- isPrimitive() {
4699
- return true;
4700
- }
4701
- get errors() {
4702
- return this.computeErrors();
4703
- }
4704
- computeErrors() {
4705
- return [];
4706
- }
4707
- get warnings() {
4708
- if (!this._formulaWarning) return [];
4709
- return [{
4710
- severity: "warning",
4711
- type: this._formulaWarning.type,
4712
- message: this._formulaWarning.message,
4713
- path: this.name,
4714
- params: {
4715
- expression: this._formulaWarning.expression,
4716
- computedValue: this._formulaWarning.computedValue
4717
- }
4718
- }];
4719
- }
4720
- };
4721
-
4722
- //#endregion
4723
- //#region src/value-model/core/types.ts
4724
- let ValueType = /* @__PURE__ */ function(ValueType) {
4725
- ValueType["String"] = "string";
4726
- ValueType["Number"] = "number";
4727
- ValueType["Boolean"] = "boolean";
4728
- ValueType["Object"] = "object";
4729
- ValueType["Array"] = "array";
4730
- ValueType["Ref"] = "ref";
4731
- return ValueType;
4732
- }({});
4733
-
4734
- //#endregion
4735
- //#region src/value-model/node/StringValueNode.ts
4736
- var StringValueNode = class extends BasePrimitiveValueNode {
4737
- type = ValueType.String;
4738
- constructor(id, name, schema, value) {
4739
- super(id, name, schema, value, "");
4740
- this.initObservable();
4741
- }
4742
- get defaultValue() {
4743
- return this.schema.default ?? "";
4744
- }
4745
- coerceValue(value) {
4746
- if (typeof value === "string") return value;
4747
- if (value === null || value === void 0) return "";
4748
- return String(value);
4749
- }
4750
- computeErrors() {
4751
- const errors = [];
4752
- this.validateRequired(errors);
4753
- this.validateForeignKey(errors);
4754
- this.validateMinLength(errors);
4755
- this.validateMaxLength(errors);
4756
- this.validatePattern(errors);
4757
- this.validateEnum(errors);
4758
- return errors;
4759
- }
4760
- validateRequired(errors) {
4761
- if (this.schema.required && this._value === "") errors.push({
4762
- severity: "error",
4763
- type: "required",
4764
- message: "Field is required",
4765
- path: this.name
4766
- });
4767
- }
4768
- validateForeignKey(errors) {
4769
- const foreignKey = this.schema.foreignKey;
4770
- if (foreignKey && this._value === "") errors.push({
4771
- severity: "error",
4772
- type: "foreignKey",
4773
- message: `Reference to ${foreignKey} is required`,
4774
- path: this.name,
4775
- params: { table: foreignKey }
4776
- });
4777
- }
4778
- validateMinLength(errors) {
4779
- const minLength = this.schema.minLength;
4780
- if (minLength !== void 0 && this._value.length > 0 && this._value.length < minLength) errors.push({
4781
- severity: "error",
4782
- type: "minLength",
4783
- message: `Minimum length is ${minLength}`,
4784
- path: this.name,
4785
- params: {
4786
- min: minLength,
4787
- actual: this._value.length
4788
- }
4789
- });
4790
- }
4791
- validateMaxLength(errors) {
4792
- const maxLength = this.schema.maxLength;
4793
- if (maxLength !== void 0 && this._value.length > maxLength) errors.push({
4794
- severity: "error",
4795
- type: "maxLength",
4796
- message: `Maximum length is ${maxLength}`,
4797
- path: this.name,
4798
- params: {
4799
- max: maxLength,
4800
- actual: this._value.length
4801
- }
4802
- });
4803
- }
4804
- validatePattern(errors) {
4805
- const pattern = this.schema.pattern;
4806
- if (!pattern || this._value.length === 0) return;
4807
- try {
4808
- if (!new RegExp(pattern).test(this._value)) errors.push({
4809
- severity: "error",
4810
- type: "pattern",
4811
- message: "Value does not match pattern",
4812
- path: this.name,
4813
- params: { pattern }
4814
- });
4815
- } catch {
4816
- errors.push({
4817
- severity: "error",
4818
- type: "invalidPattern",
4819
- message: "Invalid regex pattern in schema",
4820
- path: this.name,
4821
- params: { pattern }
4822
- });
4823
- }
4824
- }
4825
- validateEnum(errors) {
4826
- const enumValues = this.schema.enum;
4827
- if (enumValues && enumValues.length > 0 && !enumValues.includes(this._value)) errors.push({
4828
- severity: "error",
4829
- type: "enum",
4830
- message: "Value is not in allowed list",
4831
- path: this.name,
4832
- params: {
4833
- allowed: enumValues,
4834
- actual: this._value
4835
- }
4836
- });
4837
- }
4838
- };
4839
-
4840
- //#endregion
4841
- //#region src/value-model/node/NumberValueNode.ts
4842
- var NumberValueNode = class extends BasePrimitiveValueNode {
4843
- type = ValueType.Number;
4844
- constructor(id, name, schema, value) {
4845
- super(id, name, schema, value, 0);
4846
- this.initObservable();
4847
- }
4848
- get defaultValue() {
4849
- return this.schema.default ?? 0;
4850
- }
4851
- coerceValue(value) {
4852
- if (typeof value === "number") return value;
4853
- return Number(value) || 0;
4854
- }
4855
- computeErrors() {
4856
- const errors = [];
4857
- const minimum = this.schema.minimum;
4858
- if (minimum !== void 0 && this._value < minimum) errors.push({
4859
- severity: "error",
4860
- type: "min",
4861
- message: `Value must be at least ${minimum}`,
4862
- path: this.name,
4863
- params: {
4864
- min: minimum,
4865
- actual: this._value
4866
- }
4867
- });
4868
- const maximum = this.schema.maximum;
4869
- if (maximum !== void 0 && this._value > maximum) errors.push({
4870
- severity: "error",
4871
- type: "max",
4872
- message: `Value must be at most ${maximum}`,
4873
- path: this.name,
4874
- params: {
4875
- max: maximum,
4876
- actual: this._value
4877
- }
4878
- });
4879
- const enumValues = this.schema.enum;
4880
- if (enumValues && enumValues.length > 0 && !enumValues.includes(this._value)) errors.push({
4881
- severity: "error",
4882
- type: "enum",
4883
- message: "Value is not in allowed list",
4884
- path: this.name,
4885
- params: {
4886
- allowed: enumValues,
4887
- actual: this._value
4888
- }
4889
- });
4890
- return errors;
4891
- }
4892
- };
4893
-
4894
- //#endregion
4895
- //#region src/value-model/node/BooleanValueNode.ts
4896
- var BooleanValueNode = class extends BasePrimitiveValueNode {
4897
- type = ValueType.Boolean;
4898
- constructor(id, name, schema, value) {
4899
- super(id, name, schema, value, false);
4900
- this.initObservable();
4901
- }
4902
- get defaultValue() {
4903
- return this.schema.default ?? false;
4904
- }
4905
- coerceValue(value) {
4906
- if (typeof value === "boolean") return value;
4907
- return Boolean(value);
4908
- }
4909
- };
4910
-
4911
- //#endregion
4912
- //#region src/value-model/node/ObjectValueNode.ts
4913
- var ObjectValueNode = class extends BaseValueNode {
4914
- type = ValueType.Object;
4915
- _children = /* @__PURE__ */ new Map();
4916
- _baseChildren = /* @__PURE__ */ new Map();
4917
- constructor(id, name, schema, children) {
4918
- super(id, name, schema);
4919
- if (children) for (const child of children) {
4920
- this._children.set(child.name, child);
4921
- child.parent = this;
4922
- }
4923
- this._baseChildren = new Map(this._children);
4924
- makeObservable(this, {
4925
- _children: observable,
4926
- _baseChildren: observable,
4927
- value: computed,
4928
- children: computed,
4929
- isDirty: computed,
4930
- errors: computed,
4931
- warnings: computed,
4932
- addChild: action,
4933
- removeChild: action,
4934
- commit: action,
4935
- revert: action
4936
- });
4937
- }
4938
- get value() {
4939
- return Object.fromEntries(this._children);
4940
- }
4941
- get children() {
4942
- return Array.from(this._children.values());
4943
- }
4944
- getPlainValue() {
4945
- const result = {};
4946
- for (const [key, node] of this._children) result[key] = node.getPlainValue();
4947
- return result;
4948
- }
4949
- child(name) {
4950
- return this._children.get(name);
4951
- }
4952
- hasChild(name) {
4953
- return this._children.has(name);
4954
- }
4955
- addChild(node) {
4956
- const existing = this._children.get(node.name);
4957
- if (existing) existing.parent = null;
4958
- node.parent = this;
4959
- this._children.set(node.name, node);
4960
- }
4961
- removeChild(name) {
4962
- const node = this._children.get(name);
4963
- if (node) {
4964
- node.parent = null;
4965
- this._children.delete(name);
4966
- }
4967
- }
4968
- get isDirty() {
4969
- if (this._children.size !== this._baseChildren.size) return true;
4970
- for (const [key, child] of this._children) if (this._baseChildren.get(key) !== child) return true;
4971
- for (const child of this._children.values()) if ("isDirty" in child && child.isDirty) return true;
4972
- return false;
4973
- }
4974
- commit() {
4975
- this._baseChildren = new Map(this._children);
4976
- for (const child of this._children.values()) if ("commit" in child && typeof child.commit === "function") child.commit();
4977
- }
4978
- revert() {
4979
- for (const child of this._children.values()) child.parent = null;
4980
- this._children = new Map(this._baseChildren);
4981
- for (const child of this._children.values()) {
4982
- child.parent = this;
4983
- if ("revert" in child && typeof child.revert === "function") child.revert();
4984
- }
4985
- }
4986
- isObject() {
4987
- return true;
4988
- }
4989
- get errors() {
4990
- const errors = [];
4991
- for (const child of this._children.values()) errors.push(...child.errors);
4992
- return errors;
4993
- }
4994
- get warnings() {
4995
- const warnings = [];
4996
- for (const child of this._children.values()) warnings.push(...child.warnings);
4997
- return warnings;
4998
- }
4999
- };
5000
-
5001
- //#endregion
5002
- //#region src/value-model/node/ArrayValueNode.ts
5003
- var ArrayValueNode = class extends BaseValueNode {
5004
- type = ValueType.Array;
5005
- _items = [];
5006
- _baseItems = [];
5007
- _nodeFactory = null;
5008
- constructor(id, name, schema, items) {
5009
- super(id, name, schema);
5010
- if (items) for (const item of items) {
5011
- item.parent = this;
5012
- this._items.push(item);
5013
- }
5014
- this._baseItems = [...this._items];
5015
- makeObservable(this, {
5016
- _items: observable,
5017
- _baseItems: observable,
5018
- value: computed,
5019
- length: computed,
5020
- isDirty: computed,
5021
- errors: computed,
5022
- warnings: computed,
5023
- push: action,
5024
- insertAt: action,
5025
- removeAt: action,
5026
- move: action,
5027
- replaceAt: action,
5028
- clear: action,
5029
- commit: action,
5030
- revert: action,
5031
- pushValue: action,
5032
- insertValueAt: action
5033
- });
5034
- }
5035
- get value() {
5036
- return this._items;
5037
- }
5038
- get length() {
5039
- return this._items.length;
5040
- }
5041
- getPlainValue() {
5042
- return this._items.map((item) => item.getPlainValue());
5043
- }
5044
- at(index) {
5045
- if (index < 0) return this._items[this._items.length + index];
5046
- return this._items[index];
5047
- }
5048
- push(node) {
5049
- node.parent = this;
5050
- this._items.push(node);
5051
- }
5052
- insertAt(index, node) {
5053
- if (index < 0 || index > this._items.length) throw new Error(`Index out of bounds: ${index}`);
5054
- node.parent = this;
5055
- this._items.splice(index, 0, node);
5056
- }
5057
- removeAt(index) {
5058
- if (index < 0 || index >= this._items.length) throw new Error(`Index out of bounds: ${index}`);
5059
- const removed = this._items.splice(index, 1)[0];
5060
- if (removed) removed.parent = null;
5061
- }
5062
- move(fromIndex, toIndex) {
5063
- if (fromIndex < 0 || fromIndex >= this._items.length) throw new Error(`Source index out of bounds: ${fromIndex}`);
5064
- if (toIndex < 0 || toIndex >= this._items.length) throw new Error(`Target index out of bounds: ${toIndex}`);
5065
- if (fromIndex === toIndex) return;
5066
- const [item] = this._items.splice(fromIndex, 1);
5067
- if (item) this._items.splice(toIndex, 0, item);
5068
- }
5069
- replaceAt(index, node) {
5070
- if (index < 0 || index >= this._items.length) throw new Error(`Index out of bounds: ${index}`);
5071
- const oldNode = this._items[index];
5072
- if (oldNode) oldNode.parent = null;
5073
- node.parent = this;
5074
- this._items[index] = node;
5075
- }
5076
- clear() {
5077
- for (const item of this._items) item.parent = null;
5078
- this._items.length = 0;
5079
- }
5080
- setNodeFactory(factory) {
5081
- this._nodeFactory = factory;
5082
- }
5083
- pushValue(value) {
5084
- const node = this.createItemNode(this._items.length, value);
5085
- this.push(node);
5086
- }
5087
- insertValueAt(index, value) {
5088
- const node = this.createItemNode(index, value);
5089
- this.insertAt(index, node);
5090
- }
5091
- createItemNode(index, value) {
5092
- if (!this._nodeFactory) throw new Error("NodeFactory not set");
5093
- const itemSchema = this.schema.items;
5094
- if (!itemSchema) throw new Error("No items schema");
5095
- const itemValue = value === void 0 ? itemSchema.default : value;
5096
- const node = this._nodeFactory.create(String(index), itemSchema, itemValue);
5097
- this.propagateFactory(node);
5098
- return node;
5099
- }
5100
- propagateFactory(node) {
5101
- if (!this._nodeFactory) return;
5102
- if (node.isArray()) {
5103
- node.setNodeFactory(this._nodeFactory);
5104
- for (const item of node.value) this.propagateFactory(item);
5105
- } else if (node.isObject()) for (const child of node.children) this.propagateFactory(child);
5106
- }
5107
- get isDirty() {
5108
- if (this._items.length !== this._baseItems.length) return true;
5109
- for (let i = 0; i < this._items.length; i++) if (this._items[i] !== this._baseItems[i]) return true;
5110
- for (const item of this._items) if ("isDirty" in item && item.isDirty) return true;
5111
- return false;
5112
- }
5113
- commit() {
5114
- this._baseItems = [...this._items];
5115
- for (const item of this._items) if ("commit" in item && typeof item.commit === "function") item.commit();
5116
- }
5117
- revert() {
5118
- for (const item of this._items) item.parent = null;
5119
- this._items = [...this._baseItems];
5120
- for (const item of this._items) {
5121
- item.parent = this;
5122
- if ("revert" in item && typeof item.revert === "function") item.revert();
5123
- }
5124
- }
5125
- isArray() {
5126
- return true;
5127
- }
5128
- get errors() {
5129
- const errors = [];
5130
- for (const item of this._items) errors.push(...item.errors);
5131
- return errors;
5132
- }
5133
- get warnings() {
5134
- const warnings = [];
5135
- for (const item of this._items) warnings.push(...item.warnings);
5136
- return warnings;
5137
- }
5138
- };
5139
-
5140
- //#endregion
5141
- //#region src/value-model/node/NodeFactory.ts
5142
- var NodeFactoryRegistry = class {
5143
- factories = /* @__PURE__ */ new Map();
5144
- register(schemaType, factory) {
5145
- this.factories.set(schemaType, factory);
5146
- return this;
5147
- }
5148
- get(schemaType) {
5149
- return this.factories.get(schemaType);
5150
- }
5151
- has(schemaType) {
5152
- return this.factories.has(schemaType);
5153
- }
5154
- };
5155
- var NodeFactory = class {
5156
- constructor(registry) {
5157
- this.registry = registry;
5158
- }
5159
- create(name, schema, value, id) {
5160
- const schemaType = schema.type ?? "object";
5161
- const factory = this.registry.get(schemaType);
5162
- if (!factory) throw new Error(`Unknown schema type: ${schemaType}`);
5163
- return factory(name, schema, value, id);
5164
- }
5165
- createTree(schema, value) {
5166
- return this.create("", schema, value);
5167
- }
5168
- };
5169
- const stringFactory = (name, schema, value, id) => {
5170
- return new StringValueNode(id, name, schema, value);
5171
- };
5172
- const numberFactory = (name, schema, value, id) => {
5173
- return new NumberValueNode(id, name, schema, value);
5174
- };
5175
- const booleanFactory = (name, schema, value, id) => {
5176
- return new BooleanValueNode(id, name, schema, value);
5177
- };
5178
- function createObjectFactory(nodeFactory) {
5179
- return (name, schema, value, id) => {
5180
- const objValue = value ?? {};
5181
- const children = [];
5182
- const properties = schema.properties ?? {};
5183
- for (const [propName, propSchema] of Object.entries(properties)) {
5184
- const propValue = objValue[propName];
5185
- const childNode = nodeFactory.create(propName, propSchema, propValue);
5186
- children.push(childNode);
5187
- }
5188
- return new ObjectValueNode(id, name, schema, children);
5189
- };
5190
- }
5191
- function createArrayFactory(nodeFactory) {
5192
- return (name, schema, value, id) => {
5193
- const arrValue = value ?? [];
5194
- const itemSchema = schema.items ?? { type: "string" };
5195
- const items = [];
5196
- for (let i = 0; i < arrValue.length; i++) {
5197
- const itemValue = arrValue[i];
5198
- const itemNode = nodeFactory.create(String(i), itemSchema, itemValue);
5199
- items.push(itemNode);
5200
- }
5201
- return new ArrayValueNode(id, name, schema, items);
5202
- };
5203
- }
5204
- function createDefaultRegistry() {
5205
- const registry = new NodeFactoryRegistry();
5206
- registry.register("string", stringFactory);
5207
- registry.register("number", numberFactory);
5208
- registry.register("boolean", booleanFactory);
5209
- return registry;
5210
- }
5211
- function createNodeFactory() {
5212
- const registry = createDefaultRegistry();
5213
- const factory = new NodeFactory(registry);
5214
- registry.register("object", createObjectFactory(factory));
5215
- registry.register("array", createArrayFactory(factory));
5216
- return factory;
5217
- }
5218
-
5219
- //#endregion
5220
- //#region src/value-model/core/Path.ts
5221
- var Path = class Path {
5222
- constructor(_segments) {
5223
- this._segments = _segments;
5224
- }
5225
- static empty() {
5226
- return new Path([]);
5227
- }
5228
- static INDEX_REGEX = /^\[(\d+)\]/;
5229
- static PROP_REGEX = /^\.?([a-zA-Z_]\w*)/;
5230
- static fromString(path) {
5231
- if (!path || path === "") return Path.empty();
5232
- const segments = [];
5233
- let current = path;
5234
- while (current.length > 0) {
5235
- const indexMatch = Path.INDEX_REGEX.exec(current);
5236
- if (indexMatch?.[1] !== void 0) {
5237
- segments.push({
5238
- type: "index",
5239
- index: Number.parseInt(indexMatch[1], 10)
5240
- });
5241
- current = current.slice(indexMatch[0].length);
5242
- continue;
5243
- }
5244
- if (current.startsWith("[*]")) {
5245
- segments.push({ type: "items" });
5246
- current = current.slice(3);
5247
- continue;
5248
- }
5249
- const propMatch = Path.PROP_REGEX.exec(current);
5250
- if (propMatch?.[1] !== void 0) {
5251
- segments.push({
5252
- type: "property",
5253
- name: propMatch[1]
5254
- });
5255
- current = current.slice(propMatch[0].length);
5256
- continue;
5257
- }
5258
- throw new Error(`Invalid path segment: ${current}`);
5259
- }
5260
- return new Path(segments);
5261
- }
5262
- static fromSegments(segments) {
5263
- return new Path([...segments]);
5264
- }
5265
- segments() {
5266
- return this._segments;
5267
- }
5268
- isEmpty() {
5269
- return this._segments.length === 0;
5270
- }
5271
- length() {
5272
- return this._segments.length;
5273
- }
5274
- first() {
5275
- return this._segments[0];
5276
- }
5277
- last() {
5278
- return this._segments.at(-1);
5279
- }
5280
- parent() {
5281
- if (this._segments.length === 0) return this;
5282
- return new Path(this._segments.slice(0, -1));
5283
- }
5284
- child(name) {
5285
- return new Path([...this._segments, {
5286
- type: "property",
5287
- name
5288
- }]);
5289
- }
5290
- childIndex(index) {
5291
- return new Path([...this._segments, {
5292
- type: "index",
5293
- index
5294
- }]);
5295
- }
5296
- childItems() {
5297
- return new Path([...this._segments, { type: "items" }]);
5298
- }
5299
- isChildOf(parent) {
5300
- if (parent._segments.length >= this._segments.length) return false;
5301
- for (let i = 0; i < parent._segments.length; i++) {
5302
- const parentSeg = parent._segments[i];
5303
- const thisSeg = this._segments[i];
5304
- if (!parentSeg || !thisSeg || !this.segmentEquals(parentSeg, thisSeg)) return false;
5305
- }
5306
- return true;
5307
- }
5308
- equals(other) {
5309
- if (this._segments.length !== other._segments.length) return false;
5310
- for (let i = 0; i < this._segments.length; i++) {
5311
- const thisSeg = this._segments[i];
5312
- const otherSeg = other._segments[i];
5313
- if (!thisSeg || !otherSeg || !this.segmentEquals(thisSeg, otherSeg)) return false;
5314
- }
5315
- return true;
5316
- }
5317
- asSimple() {
5318
- let result = "";
5319
- for (const segment of this._segments) if (segment.type === "property") {
5320
- if (result.length > 0) result += ".";
5321
- result += segment.name;
5322
- } else if (segment.type === "index") result += `[${segment.index}]`;
5323
- else if (segment.type === "items") result += "[*]";
5324
- return result;
5325
- }
5326
- asJsonPointer() {
5327
- if (this._segments.length === 0) return "";
5328
- let result = "";
5329
- for (const segment of this._segments) if (segment.type === "property") result += "/" + segment.name;
5330
- else if (segment.type === "index") result += "/" + segment.index;
5331
- else if (segment.type === "items") result += "/-";
5332
- return result;
5333
- }
5334
- segmentEquals(a, b) {
5335
- if (a.type !== b.type) return false;
5336
- if (a.type === "property" && b.type === "property") return a.name === b.name;
5337
- if (a.type === "index" && b.type === "index") return a.index === b.index;
5338
- return true;
5339
- }
5340
- };
5341
-
5342
- //#endregion
5343
- //#region src/value-model/tree/TreeIndex.ts
5344
- var TreeIndex = class {
5345
- nodesById = /* @__PURE__ */ new Map();
5346
- pathCache = /* @__PURE__ */ new Map();
5347
- constructor(root) {
5348
- this.root = root;
5349
- this.rebuild();
5350
- }
5351
- nodeById(id) {
5352
- const node = this.nodesById.get(id);
5353
- if (node) return node;
5354
- this.rebuild();
5355
- return this.nodesById.get(id);
5356
- }
5357
- pathOf(node) {
5358
- if (this.isInsideArray(node)) return this.computePath(node);
5359
- const cached = this.pathCache.get(node.id);
5360
- if (cached) return cached;
5361
- const path = this.computePath(node);
5362
- this.pathCache.set(node.id, path);
5363
- return path;
5364
- }
5365
- isInsideArray(node) {
5366
- let current = node.parent;
5367
- while (current) {
5368
- if (current.isArray()) return true;
5369
- current = current.parent;
5370
- }
5371
- return false;
5372
- }
5373
- rebuild() {
5374
- this.nodesById.clear();
5375
- this.pathCache.clear();
5376
- this.indexNode(this.root);
5377
- }
5378
- registerNode(node) {
5379
- this.indexNode(node);
5380
- }
5381
- invalidatePathsUnder(node) {
5382
- this.pathCache.delete(node.id);
5383
- this.invalidateChildPaths(node);
5384
- }
5385
- indexNode(node) {
5386
- this.nodesById.set(node.id, node);
5387
- if (node.isObject()) for (const child of node.children) this.indexNode(child);
5388
- else if (node.isArray()) for (const item of node.value) this.indexNode(item);
5389
- }
5390
- computePath(node) {
5391
- const segments = [];
5392
- let current = node;
5393
- while (current?.parent) {
5394
- const parent = current.parent;
5395
- if (parent.isObject()) segments.unshift({
5396
- type: "property",
5397
- name: current.name
5398
- });
5399
- else if (parent.isArray()) {
5400
- const index = parent.value.indexOf(current);
5401
- if (index >= 0) segments.unshift({
5402
- type: "index",
5403
- index
5404
- });
5405
- }
5406
- current = parent;
5407
- }
5408
- return Path.fromSegments(segments);
5409
- }
5410
- invalidateChildPaths(node) {
5411
- if (node.isObject()) for (const child of node.children) {
5412
- this.pathCache.delete(child.id);
5413
- this.invalidateChildPaths(child);
5414
- }
5415
- else if (node.isArray()) for (const item of node.value) {
5416
- this.pathCache.delete(item.id);
5417
- this.invalidateChildPaths(item);
5418
- }
5419
- }
5420
- };
5421
-
5422
- //#endregion
5423
- //#region src/value-model/tree/ChangeTracker.ts
5424
- var ChangeTracker = class {
5425
- _changes = [];
5426
- get changes() {
5427
- return this._changes;
5428
- }
5429
- get hasChanges() {
5430
- return this._changes.length > 0;
5431
- }
5432
- track(change) {
5433
- this._changes.push(change);
5434
- }
5435
- clear() {
5436
- this._changes = [];
5437
- }
5438
- toPatches() {
5439
- const patches = [];
5440
- for (const change of this._changes) {
5441
- const patch = this.changeToPatches(change);
5442
- patches.push(...patch);
5443
- }
5444
- return patches;
5445
- }
5446
- changeToPatches(change) {
5447
- const path = change.path.asJsonPointer();
5448
- switch (change.type) {
5449
- case "setValue": return [{
5450
- op: "replace",
5451
- path,
5452
- value: change.value
5453
- }];
5454
- case "addProperty": return [{
5455
- op: "add",
5456
- path,
5457
- value: change.value
5458
- }];
5459
- case "removeProperty": return [{
5460
- op: "remove",
5461
- path
5462
- }];
5463
- case "arrayPush": return [{
5464
- op: "add",
5465
- path: `${path}/-`,
5466
- value: change.value
5467
- }];
5468
- case "arrayInsert": return [{
5469
- op: "add",
5470
- path: `${path}/${change.index}`,
5471
- value: change.value
5472
- }];
5473
- case "arrayRemove": return [{
5474
- op: "remove",
5475
- path: `${path}/${change.index}`
5476
- }];
5477
- case "arrayMove": {
5478
- const fromIndex = change.fromIndex ?? 0;
5479
- const toIndex = change.toIndex ?? 0;
5480
- return [{
5481
- op: "move",
5482
- from: `${path}/${fromIndex}`,
5483
- path: `${path}/${toIndex}`
5484
- }];
5485
- }
5486
- case "arrayReplace": return [{
5487
- op: "replace",
5488
- path: `${path}/${change.index}`,
5489
- value: change.value
5490
- }];
5491
- case "arrayClear": return [{
5492
- op: "replace",
5493
- path,
5494
- value: []
5495
- }];
5496
- default: return [];
5497
- }
5498
- }
5499
- };
5500
-
5501
- //#endregion
5502
- //#region src/value-model/tree/ValueTree.ts
5503
- var ValueTree = class {
5504
- index;
5505
- changeTracker;
5506
- _formulaEngine = null;
5507
- constructor(_root) {
5508
- this._root = _root;
5509
- this.index = new TreeIndex(_root);
5510
- this.changeTracker = new ChangeTracker();
5511
- makeObservable(this, {
5512
- allErrors: computed,
5513
- allWarnings: computed,
5514
- allDiagnostics: computed,
5515
- isValid: computed,
5516
- hasDiagnostics: computed,
5517
- isDirty: computed,
5518
- commit: action,
5519
- revert: action
5520
- });
5521
- }
5522
- get root() {
5523
- return this._root;
5524
- }
5525
- nodeById(id) {
5526
- return this.index.nodeById(id);
5527
- }
5528
- get(path) {
5529
- return this.getByPath(Path.fromString(path));
5530
- }
5531
- getByPath(path) {
5532
- if (path.isEmpty()) return this._root;
5533
- let current = this._root;
5534
- for (const segment of path.segments()) {
5535
- if (!current) return;
5536
- current = this.resolveSegment(current, segment);
5537
- }
5538
- return current;
5539
- }
5540
- resolveSegment(node, segment) {
5541
- if (segment.type === "property" && node.isObject()) return node.child(segment.name);
5542
- if (segment.type === "index" && node.isArray()) return node.at(segment.index);
5543
- }
5544
- pathOf(nodeOrId) {
5545
- const node = typeof nodeOrId === "string" ? this.nodeById(nodeOrId) : nodeOrId;
5546
- if (!node) return Path.empty();
5547
- return this.index.pathOf(node);
5548
- }
5549
- get allErrors() {
5550
- return this._root.errors;
5551
- }
5552
- get allWarnings() {
5553
- return this._root.warnings;
5554
- }
5555
- get allDiagnostics() {
5556
- return [...this.allErrors, ...this.allWarnings];
5557
- }
5558
- get isValid() {
5559
- return this.allErrors.length === 0;
5560
- }
5561
- get hasDiagnostics() {
5562
- return this.allDiagnostics.length > 0;
5563
- }
5564
- get errorsByPath() {
5565
- const map = /* @__PURE__ */ new Map();
5566
- for (const error of this.allErrors) {
5567
- const list = map.get(error.path) ?? [];
5568
- list.push(error);
5569
- map.set(error.path, list);
5570
- }
5571
- return map;
5572
- }
5573
- getValue(path) {
5574
- return this.get(path)?.getPlainValue();
5575
- }
5576
- setValue(path, value) {
5577
- const parsedPath = Path.fromString(path);
5578
- const node = this.getByPath(parsedPath);
5579
- if (!node) throw new Error(`Path not found: ${path}`);
5580
- if (!node.isPrimitive()) throw new Error(`Cannot set value on non-primitive node: ${path}`);
5581
- const oldValue = node.value;
5582
- node.setValue(value);
5583
- this.changeTracker.track({
5584
- type: "setValue",
5585
- path: parsedPath,
5586
- value,
5587
- oldValue
5588
- });
5589
- }
5590
- getPlainValue() {
5591
- return this._root.getPlainValue();
5592
- }
5593
- get changes() {
5594
- return this.changeTracker.changes;
5595
- }
5596
- get hasChanges() {
5597
- return this.changeTracker.hasChanges;
5598
- }
5599
- clearChanges() {
5600
- this.changeTracker.clear();
5601
- }
5602
- getPatches() {
5603
- return this.changeTracker.toPatches();
5604
- }
5605
- trackChange(change) {
5606
- this.changeTracker.track(change);
5607
- }
5608
- rebuildIndex() {
5609
- this.index.rebuild();
5610
- }
5611
- invalidatePathsUnder(node) {
5612
- this.index.invalidatePathsUnder(node);
5613
- }
5614
- get isDirty() {
5615
- const root = this._root;
5616
- if ("isDirty" in root) return root.isDirty;
5617
- return false;
5618
- }
5619
- commit() {
5620
- const root = this._root;
5621
- if ("commit" in root && typeof root.commit === "function") root.commit();
5622
- this.changeTracker.clear();
5623
- }
5624
- revert() {
5625
- const root = this._root;
5626
- if ("revert" in root && typeof root.revert === "function") root.revert();
5627
- this.changeTracker.clear();
5628
- }
5629
- setFormulaEngine(engine) {
5630
- this._formulaEngine = engine;
5631
- }
5632
- get formulaEngine() {
5633
- return this._formulaEngine;
5634
- }
5635
- dispose() {
5636
- this._formulaEngine?.dispose();
5637
- this._formulaEngine = null;
5638
- }
5639
- };
5640
-
5641
- //#endregion
5642
- //#region src/value-model/formula/FormulaCollector.ts
5643
- const INDEX_REGEX = /^\[(-?\d+)\]/;
5644
- const PROP_REGEX = /^\.?([a-zA-Z_]\w*)/;
5645
- var FormulaCollector = class {
5646
- root = null;
5647
- collect(root) {
5648
- this.root = root;
5649
- const formulas = [];
5650
- this.traverse(root, {
5651
- parent: null,
5652
- arrayLevels: []
5653
- }, formulas);
5654
- return formulas;
5655
- }
5656
- traverse(node, context, formulas) {
5657
- if (node.isPrimitive()) this.collectPrimitive(node, context, formulas);
5658
- else if (node.isObject()) for (const child of node.children) this.traverse(child, {
5659
- ...context,
5660
- parent: node
5661
- }, formulas);
5662
- else if (node.isArray()) for (let i = 0; i < node.length; i++) {
5663
- const item = node.at(i);
5664
- if (item) this.traverse(item, {
5665
- ...context,
5666
- arrayLevels: [...context.arrayLevels, {
5667
- array: node,
5668
- index: i
5669
- }]
5670
- }, formulas);
5671
- }
5672
- }
5673
- collectPrimitive(node, context, formulas) {
5674
- const formula = node.formula;
5675
- if (!formula) return;
5676
- const rawDependencies = this.extractDependencies(formula.expression);
5677
- const dependencyNodes = this.resolveDependencies(rawDependencies, node, context);
5678
- formulas.push({
5679
- node,
5680
- expression: formula.expression,
5681
- parent: context.parent,
5682
- dependencyNodes,
5683
- arrayLevels: context.arrayLevels
5684
- });
5685
- }
5686
- extractDependencies(expression) {
5687
- try {
5688
- return parseExpression(expression).dependencies;
5689
- } catch {
5690
- return [];
5691
- }
5692
- }
5693
- resolveDependencies(rawDeps, formulaNode, context) {
5694
- const nodes = [];
5695
- for (const dep of rawDeps) {
5696
- const node = this.resolveOneDependency(dep, formulaNode, context);
5697
- if (node) this.collectPrimitiveNodes(node, nodes);
5698
- }
5699
- return nodes;
5700
- }
5701
- collectPrimitiveNodes(node, result) {
5702
- if (node.isPrimitive()) result.push(node);
5703
- else if (node.isArray()) for (let i = 0; i < node.length; i++) {
5704
- const item = node.at(i);
5705
- if (item) this.collectPrimitiveNodes(item, result);
5706
- }
5707
- else if (node.isObject()) for (const child of node.children) this.collectPrimitiveNodes(child, result);
5708
- }
5709
- resolveOneDependency(dep, _formulaNode, context) {
5710
- if (dep.startsWith("/")) return this.resolveFromRoot(dep.slice(1));
5711
- if (dep.startsWith("../")) return this.resolveRelative(dep, context);
5712
- if (context.parent) return this.resolveFromNode(context.parent, dep);
5713
- return this.resolveFromRoot(dep);
5714
- }
5715
- resolveFromRoot(pathStr) {
5716
- if (!this.root) return null;
5717
- return this.resolveFromNode(this.root, pathStr);
5718
- }
5719
- resolveFromNode(startNode, pathStr) {
5720
- const segments = this.parsePathSegments(pathStr);
5721
- let current = startNode;
5722
- for (const segment of segments) {
5723
- if (!current) return null;
5724
- if (segment.type === "property") if (current.isObject()) current = current.children.find((c) => c.name === segment.name) ?? null;
5725
- else return null;
5726
- else if (segment.type === "index") if (current.isArray()) current = current.at(segment.index) ?? null;
5727
- else return null;
5728
- }
5729
- return current;
5730
- }
5731
- resolveRelative(dep, context) {
5732
- let upLevels = 0;
5733
- let remaining = dep;
5734
- while (remaining.startsWith("../")) {
5735
- upLevels++;
5736
- remaining = remaining.slice(3);
5737
- }
5738
- let current = context.parent;
5739
- for (let i = 0; i < upLevels && current; i++) {
5740
- current = this.findParent(current);
5741
- if (current?.isArray()) current = this.findParent(current);
5742
- }
5743
- if (!current) return null;
5744
- if (remaining) return this.resolveFromNode(current, remaining);
5745
- return current;
5746
- }
5747
- findParent(node) {
5748
- if (!this.root || node === this.root) return null;
5749
- return this.findParentRecursive(this.root, node);
5750
- }
5751
- findParentRecursive(current, target) {
5752
- const children = this.getChildNodes(current);
5753
- for (const child of children) {
5754
- if (child === target) return current;
5755
- const found = this.findParentRecursive(child, target);
5756
- if (found) return found;
5757
- }
5758
- return null;
5759
- }
5760
- getChildNodes(node) {
5761
- if (node.isObject()) return [...node.children];
5762
- if (node.isArray()) {
5763
- const items = [];
5764
- for (let i = 0; i < node.length; i++) {
5765
- const item = node.at(i);
5766
- if (item) items.push(item);
5767
- }
5768
- return items;
5769
- }
5770
- return [];
5771
- }
5772
- parsePathSegments(pathStr) {
5773
- const segments = [];
5774
- let current = pathStr;
5775
- while (current.length > 0) {
5776
- const indexMatch = INDEX_REGEX.exec(current);
5777
- if (indexMatch?.[1]) {
5778
- segments.push({
5779
- type: "index",
5780
- index: Number.parseInt(indexMatch[1], 10)
5781
- });
5782
- current = current.slice(indexMatch[0].length);
5783
- continue;
5784
- }
5785
- const propMatch = PROP_REGEX.exec(current);
5786
- if (propMatch?.[1]) {
5787
- segments.push({
5788
- type: "property",
5789
- name: propMatch[1]
5790
- });
5791
- current = current.slice(propMatch[0].length);
5792
- continue;
5793
- }
5794
- break;
5795
- }
5796
- return segments;
5797
- }
5798
- };
5799
-
5800
- //#endregion
5801
- //#region src/value-model/formula/DependencyGraph.ts
5802
- var DependencyGraph = class {
5803
- buildDependencyMap(formulas) {
5804
- const map = /* @__PURE__ */ new Map();
5805
- for (const field of formulas) for (const depNode of field.dependencyNodes) {
5806
- let depSet = map.get(depNode);
5807
- if (!depSet) {
5808
- depSet = /* @__PURE__ */ new Set();
5809
- map.set(depNode, depSet);
5810
- }
5811
- depSet.add(field);
5812
- }
5813
- return map;
5814
- }
5815
- buildEvaluationOrder(formulas) {
5816
- const formulaNodes = new Set(formulas.map((f) => f.node));
5817
- const visited = /* @__PURE__ */ new Set();
5818
- const order = [];
5819
- const formulaByNode = /* @__PURE__ */ new Map();
5820
- for (const field of formulas) formulaByNode.set(field.node, field);
5821
- const visit = (field, stack) => {
5822
- if (visited.has(field.node)) return;
5823
- if (stack.has(field.node)) return;
5824
- stack.add(field.node);
5825
- for (const depNode of field.dependencyNodes) if (formulaNodes.has(depNode)) {
5826
- const depFormula = formulaByNode.get(depNode);
5827
- if (depFormula) visit(depFormula, stack);
5828
- }
5829
- stack.delete(field.node);
5830
- visited.add(field.node);
5831
- order.push(field);
5832
- };
5833
- for (const field of formulas) visit(field, /* @__PURE__ */ new Set());
5834
- return order;
5835
- }
5836
- getAffectedFormulas(changedNode, dependencyMap, evaluationOrder) {
5837
- const affected = /* @__PURE__ */ new Set();
5838
- const queue = [changedNode];
5839
- while (queue.length > 0) {
5840
- const current = queue.shift();
5841
- if (!current) continue;
5842
- const dependents = dependencyMap.get(current);
5843
- if (dependents) {
5844
- for (const field of dependents) if (!affected.has(field)) {
5845
- affected.add(field);
5846
- queue.push(field.node);
5847
- }
5848
- }
5849
- }
5850
- return evaluationOrder.filter((field) => affected.has(field));
5851
- }
5852
- };
5853
-
5854
- //#endregion
5855
- //#region src/value-model/formula/FormulaEvaluator.ts
5856
- var FormulaEvaluator = class {
5857
- constructor(tree, options = {}) {
5858
- this.tree = tree;
5859
- this.options = options;
5860
- }
5861
- evaluate(field) {
5862
- try {
5863
- const context = this.buildContext(field);
5864
- const result = evaluateWithContext(field.expression, context);
5865
- this.setNodeValue(field, result);
5866
- this.checkForWarnings(field, result);
5867
- } catch (error) {
5868
- this.handleError(field, error);
5869
- }
5870
- }
5871
- evaluateAll(fields) {
5872
- for (const field of fields) this.evaluate(field);
5873
- }
5874
- buildContext(field) {
5875
- const context = { rootData: this.tree.getPlainValue() };
5876
- if (field.parent) {
5877
- const itemData = this.getPlainObjectValue(field.parent);
5878
- if (itemData) context.itemData = itemData;
5879
- }
5880
- if (field.arrayLevels.length > 0) context.arrayContext = { levels: this.buildArrayLevels(field) };
5881
- return context;
5882
- }
5883
- buildArrayLevels(field) {
5884
- const levels = [];
5885
- for (let i = field.arrayLevels.length - 1; i >= 0; i--) {
5886
- const level = field.arrayLevels[i];
5887
- if (!level) continue;
5888
- const { array, index } = level;
5889
- levels.push({
5890
- index,
5891
- length: array.length,
5892
- prev: this.getPrevItemValue(array, index),
5893
- next: this.getNextItemValue(array, index)
5894
- });
5895
- }
5896
- return levels;
5897
- }
5898
- getPrevItemValue(array, index) {
5899
- if (index <= 0) return null;
5900
- const prevItem = array.at(index - 1);
5901
- return prevItem ? this.getPlainNodeValue(prevItem) : null;
5902
- }
5903
- getNextItemValue(array, index) {
5904
- if (index >= array.length - 1) return null;
5905
- const nextItem = array.at(index + 1);
5906
- return nextItem ? this.getPlainNodeValue(nextItem) : null;
5907
- }
5908
- getPlainObjectValue(node) {
5909
- const result = {};
5910
- for (const child of node.children) result[child.name] = this.getPlainNodeValue(child);
5911
- return result;
5912
- }
5913
- getPlainNodeValue(node) {
5914
- if (node.isPrimitive()) return node.value;
5915
- if (node.isObject()) return this.getPlainObjectValue(node);
5916
- if (node.isArray()) {
5917
- const result = [];
5918
- for (let i = 0; i < node.length; i++) {
5919
- const item = node.at(i);
5920
- if (item) result.push(this.getPlainNodeValue(item));
5921
- }
5922
- return result;
5923
- }
5924
- return null;
5925
- }
5926
- setNodeValue(field, result) {
5927
- const { node } = field;
5928
- const defaultValue = node.defaultValue;
5929
- if (result === null || result === void 0) {
5930
- node.setValue(defaultValue, { internal: true });
5931
- return;
5932
- }
5933
- if (typeof result === "number" && (Number.isNaN(result) || !Number.isFinite(result))) {
5934
- node.setValue(defaultValue, { internal: true });
5935
- return;
5936
- }
5937
- node.setValue(result, { internal: true });
5938
- }
5939
- checkForWarnings(field, result) {
5940
- const { node } = field;
5941
- if (typeof result === "number") {
5942
- if (Number.isNaN(result)) {
5943
- node.setFormulaWarning({
5944
- type: "nan",
5945
- message: "Formula result is NaN",
5946
- expression: field.expression,
5947
- computedValue: result
5948
- });
5949
- return;
5950
- }
5951
- if (!Number.isFinite(result)) {
5952
- node.setFormulaWarning({
5953
- type: "infinity",
5954
- message: "Formula result is Infinity",
5955
- expression: field.expression,
5956
- computedValue: result
5957
- });
5958
- return;
5959
- }
5960
- }
5961
- node.setFormulaWarning(null);
5962
- }
5963
- handleError(field, error) {
5964
- const { node } = field;
5965
- node.setValue(node.defaultValue, { internal: true });
5966
- node.setFormulaWarning({
5967
- type: "runtime-error",
5968
- message: error.message,
5969
- expression: field.expression,
5970
- computedValue: void 0
5971
- });
5972
- if (this.options.onError) this.options.onError(node, error);
5973
- }
5974
- };
5975
-
5976
- //#endregion
5977
- //#region src/value-model/formula/FormulaEngine.ts
5978
- var FormulaEngine = class {
5979
- collector;
5980
- graph;
5981
- evaluator;
5982
- formulas = [];
5983
- dependencyMap = /* @__PURE__ */ new Map();
5984
- evaluationOrder = [];
5985
- disposers = [];
5986
- constructor(tree, options = {}) {
5987
- this.tree = tree;
5988
- this.collector = new FormulaCollector();
5989
- this.graph = new DependencyGraph();
5990
- this.evaluator = new FormulaEvaluator(tree, options);
5991
- this.initialize();
5992
- }
5993
- reinitialize() {
5994
- this.disposeReactions();
5995
- this.initialize();
5996
- }
5997
- dispose() {
5998
- this.disposeReactions();
5999
- this.formulas = [];
6000
- this.dependencyMap = /* @__PURE__ */ new Map();
6001
- this.evaluationOrder = [];
6002
- }
6003
- getFormulas() {
6004
- return this.formulas;
6005
- }
6006
- getEvaluationOrder() {
6007
- return this.evaluationOrder;
6008
- }
6009
- initialize() {
6010
- this.formulas = this.collector.collect(this.tree.root);
6011
- this.dependencyMap = this.graph.buildDependencyMap(this.formulas);
6012
- this.evaluationOrder = this.graph.buildEvaluationOrder(this.formulas);
6013
- this.evaluateAll();
6014
- this.setupReactions();
6015
- }
6016
- evaluateAll() {
6017
- runInAction(() => {
6018
- for (const field of this.evaluationOrder) this.evaluator.evaluate(field);
6019
- });
6020
- }
6021
- setupReactions() {
6022
- const watchedNodes = /* @__PURE__ */ new Set();
6023
- for (const [depNode] of this.dependencyMap) {
6024
- if (watchedNodes.has(depNode)) continue;
6025
- watchedNodes.add(depNode);
6026
- const disposer = reaction(() => depNode.value, () => this.handleDependencyChange(depNode));
6027
- this.disposers.push(disposer);
6028
- }
6029
- this.setupArrayReactions(this.tree.root);
6030
- }
6031
- setupArrayReactions(node) {
6032
- if (node.isArray()) {
6033
- const disposer = reaction(() => node.length, () => this.handleStructureChange());
6034
- this.disposers.push(disposer);
6035
- for (const item of node.value) this.setupArrayReactions(item);
6036
- } else if (node.isObject()) for (const child of node.children) this.setupArrayReactions(child);
6037
- }
6038
- handleDependencyChange(changedNode) {
6039
- const affected = this.graph.getAffectedFormulas(changedNode, this.dependencyMap, this.evaluationOrder);
6040
- runInAction(() => {
6041
- for (const field of affected) this.evaluator.evaluate(field);
6042
- });
6043
- }
6044
- handleStructureChange() {
6045
- this.reinitialize();
6046
- }
6047
- disposeReactions() {
6048
- for (const disposer of this.disposers) disposer();
6049
- this.disposers = [];
6050
- }
6051
- };
6052
-
6053
- //#endregion
6054
- //#region src/value-model/factory.ts
6055
- function createValueModel(schema, initialValue, options) {
6056
- const nodeFactory = options?.nodeFactory ?? createNodeFactory();
6057
- const rootNode = nodeFactory.createTree(schema, initialValue);
6058
- propagateFactoryToArrays(rootNode, nodeFactory);
6059
- const tree = new ValueTree(rootNode);
6060
- if (options?.formulaEngine !== false) {
6061
- const engine = new FormulaEngine(tree, typeof options?.formulaEngine === "object" ? options.formulaEngine : {});
6062
- tree.setFormulaEngine(engine);
6063
- }
6064
- return tree;
6065
- }
6066
- function propagateFactoryToArrays(node, factory) {
6067
- if (node.isArray()) {
6068
- node.setNodeFactory(factory);
6069
- for (const item of node.value) propagateFactoryToArrays(item, factory);
6070
- } else if (node.isObject()) for (const child of node.children) propagateFactoryToArrays(child, factory);
6071
- }
6072
- function createEmptyValueModel(schema, options) {
6073
- return createValueModel(schema, void 0, options);
6074
- }
6075
-
6076
- //#endregion
6077
- export { ArrayValueNode, BackButton, BooleanValueNode, CloseButton, ContentEditable, CopyButton, CreateButton, CreatingEditorVM, CreatingSchemaEditor, FormulaEngine, GrayButton, JsonCard, JsonSchemaTypeName, NumberValueNode, ObjectValueNode, SchemaEditorCore, SchemaTypeIds, SettingsButton, StringValueNode, Tooltip, UpdatingEditorVM, UpdatingSchemaEditor, ValueTree, ViewerSwitcher, ViewerSwitcherMode, createEmptyValueModel, createValueModel, getLabelByRef, typeMenuGroups, useContentEditable };
4590
+ export { BackButton, CloseButton, ContentEditable, CopyButton, CreateButton, CreatingEditorVM, CreatingSchemaEditor, GrayButton, JsonCard, SchemaEditorCore, SchemaTypeIds, SettingsButton, Tooltip, UpdatingEditorVM, UpdatingSchemaEditor, ViewerSwitcher, ViewerSwitcherMode, ensureReactivityProvider, getLabelByRef, typeMenuGroups, useContentEditable };
6078
4591
  //# sourceMappingURL=index.mjs.map