jedison 0.3.10 → 0.3.12

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.
@@ -1811,8 +1811,15 @@ class Instance extends EventEmitter {
1811
1811
  }
1812
1812
  /**
1813
1813
  * Sets the instance value
1814
+ * @returns {*} The final value after constraint enforcement
1814
1815
  */
1815
1816
  setValue(newValue, notifyParent = true, initiator = "api") {
1817
+ if (this.value === newValue) {
1818
+ return this.value;
1819
+ }
1820
+ if (typeof this.value !== "object" && typeof newValue !== "object" && this.value === newValue) {
1821
+ return this.value;
1822
+ }
1816
1823
  const enforceConst = getSchemaXOption(this.schema, "enforceConst") ?? this.jedison.options.enforceConst;
1817
1824
  if (isSet(enforceConst) && equal(enforceConst, true)) {
1818
1825
  const schemaConst = getSchemaConst(this.schema);
@@ -1821,14 +1828,18 @@ class Instance extends EventEmitter {
1821
1828
  }
1822
1829
  }
1823
1830
  const valueChanged = different(this.value, newValue);
1831
+ if (!valueChanged) {
1832
+ return this.value;
1833
+ }
1824
1834
  this.value = newValue;
1835
+ this.isDirty = true;
1825
1836
  this.emit("set-value", newValue, initiator);
1826
- if (valueChanged) {
1827
- this.isDirty = true;
1828
- this.emit("change", initiator);
1829
- this.jedison.emit("instance-change", this, initiator);
1837
+ this.emit("change", initiator);
1838
+ this.jedison.emit("instance-change", this, initiator);
1839
+ if (notifyParent) {
1830
1840
  this.emit("notifyParent", initiator);
1831
1841
  }
1842
+ return this.value;
1832
1843
  }
1833
1844
  /**
1834
1845
  * Fires when a child's instance state changes
@@ -1905,6 +1916,8 @@ class Editor {
1905
1916
  this.disabled = false;
1906
1917
  this.readOnly = this.instance.isReadOnly();
1907
1918
  this.showingValidationErrors = false;
1919
+ this.markdownEnabled = false;
1920
+ this.purifyEnabled = false;
1908
1921
  this.title = null;
1909
1922
  this.description = null;
1910
1923
  this.init();
@@ -1931,6 +1944,8 @@ class Editor {
1931
1944
  */
1932
1945
  init() {
1933
1946
  this.theme = this.instance.jedison.theme;
1947
+ this.markdownEnabled = getSchemaXOption(this.instance.schema, "parseMarkdown") ?? this.instance.jedison.options.parseMarkdown;
1948
+ this.purifyEnabled = getSchemaXOption(this.instance.schema, "purifyHtml") ?? this.instance.jedison.options.purifyHtml;
1934
1949
  }
1935
1950
  /**
1936
1951
  * Gets the json path level by counting how many "/" it has
@@ -2068,10 +2083,7 @@ class Editor {
2068
2083
  }
2069
2084
  }
2070
2085
  getHtmlFromMarkdown(content) {
2071
- if (this.instance.jedison.options.parseMarkdown && window.marked) {
2072
- return window.marked.parse(content);
2073
- }
2074
- return content;
2086
+ return window.marked.parse(content);
2075
2087
  }
2076
2088
  getTitle() {
2077
2089
  let titleFromSchema = false;
@@ -2083,11 +2095,11 @@ class Editor {
2083
2095
  }
2084
2096
  if (titleFromSchema) {
2085
2097
  this.title = compileTemplate(this.title, this.instance.getTemplateData());
2086
- this.title = this.getHtmlFromMarkdown(this.title);
2098
+ this.title = this.markdownEnabled ? this.getHtmlFromMarkdown(this.title) : this.title;
2087
2099
  const domPurifyOptions = combineDeep({}, this.instance.jedison.options.domPurifyOptions, {
2088
2100
  FORBID_TAGS: ["p"]
2089
2101
  });
2090
- this.title = this.purifyContent(this.title, domPurifyOptions);
2102
+ this.title = this.purifyEnabled ? this.purifyContent(this.title, domPurifyOptions) : this.title;
2091
2103
  }
2092
2104
  return this.title;
2093
2105
  }
@@ -2095,9 +2107,9 @@ class Editor {
2095
2107
  const schemaDescription = getSchemaDescription(this.instance.schema);
2096
2108
  if (isSet(schemaDescription)) {
2097
2109
  this.description = compileTemplate(schemaDescription, this.instance.getTemplateData());
2098
- this.description = this.getHtmlFromMarkdown(this.description);
2110
+ this.description = this.markdownEnabled ? this.getHtmlFromMarkdown(this.description) : this.description;
2099
2111
  const domPurifyOptions = this.instance.jedison.options.domPurifyOptions;
2100
- this.purifyContent(this.description, domPurifyOptions);
2112
+ this.description = this.purifyEnabled ? this.purifyContent(this.description, domPurifyOptions) : this.description;
2101
2113
  }
2102
2114
  return this.description;
2103
2115
  }
@@ -2109,12 +2121,12 @@ class Editor {
2109
2121
  }
2110
2122
  const domPurifyOptions = this.instance.jedison.options.domPurifyOptions;
2111
2123
  if (isSet(schemaInfo.title)) {
2112
- schemaInfo.title = this.getHtmlFromMarkdown(schemaInfo.title);
2113
- schemaInfo.title = this.purifyContent(schemaInfo.title, domPurifyOptions);
2124
+ schemaInfo.title = this.markdownEnabled ? this.getHtmlFromMarkdown(schemaInfo.title) : schemaInfo.title;
2125
+ schemaInfo.title = this.purifyEnabled ? this.purifyContent(schemaInfo.title, domPurifyOptions) : schemaInfo.title;
2114
2126
  }
2115
2127
  if (isSet(schemaInfo.content)) {
2116
- schemaInfo.content = this.getHtmlFromMarkdown(schemaInfo.content);
2117
- schemaInfo.content = this.purifyContent(schemaInfo.content, domPurifyOptions);
2128
+ schemaInfo.content = this.markdownEnabled ? this.getHtmlFromMarkdown(schemaInfo.content) : schemaInfo.content;
2129
+ schemaInfo.content = this.purifyEnabled ? this.purifyContent(schemaInfo.content, domPurifyOptions) : schemaInfo.content;
2118
2130
  }
2119
2131
  return schemaInfo;
2120
2132
  }
@@ -2257,7 +2269,7 @@ class InstanceIfThenElse extends Instance {
2257
2269
  instance.children.forEach((child) => {
2258
2270
  const shouldUpdateValue = child.isMultiple && hasOwn(value, child.getKey());
2259
2271
  if (shouldUpdateValue) {
2260
- child.setValue(value[child.getKey()], false, "api");
2272
+ child.setValue(value[child.getKey()], true, "api");
2261
2273
  }
2262
2274
  });
2263
2275
  }
@@ -2707,7 +2719,8 @@ class InstanceObject extends Instance {
2707
2719
  const oldValue = child.getValue();
2708
2720
  const newValue = value[child.getKey()];
2709
2721
  if (different(oldValue, newValue)) {
2710
- child.setValue(newValue, false, initiator);
2722
+ const finalValue = child.setValue(newValue, false, initiator);
2723
+ value[child.getKey()] = finalValue;
2711
2724
  }
2712
2725
  } else {
2713
2726
  const schema = this.getPropertySchema(propertyName);
@@ -2726,6 +2739,7 @@ class InstanceObject extends Instance {
2726
2739
  }
2727
2740
  }
2728
2741
  this.sortChildrenByPropertyOrder();
2742
+ this.value = value;
2729
2743
  }
2730
2744
  }
2731
2745
  class InstanceArray extends Instance {
@@ -2815,11 +2829,14 @@ class InstanceArray extends Instance {
2815
2829
  if (!isArray(value)) {
2816
2830
  return;
2817
2831
  }
2832
+ const correctedValues = [];
2818
2833
  value.forEach((itemValue, index2) => {
2819
2834
  const child = this.createItemInstance(index2);
2820
2835
  this.children.push(child);
2821
- child.setValue(itemValue, false);
2836
+ const finalValue = child.setValue(itemValue, false);
2837
+ correctedValues.push(finalValue);
2822
2838
  });
2839
+ this.value = correctedValues;
2823
2840
  }
2824
2841
  }
2825
2842
  class InstanceString extends Instance {
@@ -4630,6 +4647,91 @@ class EditorArrayCheckboxes extends Editor {
4630
4647
  });
4631
4648
  }
4632
4649
  }
4650
+ class EditorNumberRange extends EditorNumber {
4651
+ static resolves(schema) {
4652
+ const schemaType = getSchemaType(schema);
4653
+ const isNumericType = schemaType === "number" || schemaType === "integer";
4654
+ if (!isNumericType) {
4655
+ return false;
4656
+ }
4657
+ if (getSchemaXOption(schema, "format") === "range") {
4658
+ return true;
4659
+ }
4660
+ const hasMin = isSet(schema.minimum) || isSet(schema.exclusiveMinimum);
4661
+ const hasMax = isSet(schema.maximum) || isSet(schema.exclusiveMaximum);
4662
+ return hasMin && hasMax;
4663
+ }
4664
+ build() {
4665
+ let optionMin = 0;
4666
+ let optionMax = 100;
4667
+ if (isSet(this.instance.schema.minimum)) {
4668
+ optionMin = this.instance.schema.minimum;
4669
+ } else if (isSet(this.instance.schema.exclusiveMinimum)) {
4670
+ optionMin = this.instance.schema.exclusiveMinimum + 0.01;
4671
+ }
4672
+ if (isSet(this.instance.schema.maximum)) {
4673
+ optionMax = this.instance.schema.maximum;
4674
+ } else if (isSet(this.instance.schema.exclusiveMaximum)) {
4675
+ optionMax = this.instance.schema.exclusiveMaximum - 0.01;
4676
+ }
4677
+ let optionStep;
4678
+ const schemaType = getSchemaType(this.instance.schema);
4679
+ const multipleOf2 = this.instance.schema.multipleOf;
4680
+ if (isSet(multipleOf2)) {
4681
+ optionStep = multipleOf2;
4682
+ } else if (schemaType === "integer") {
4683
+ optionStep = 1;
4684
+ } else {
4685
+ optionStep = 0.01;
4686
+ }
4687
+ this.control = this.theme.getInputRangeControl({
4688
+ title: this.getTitle(),
4689
+ description: this.getDescription(),
4690
+ type: "range",
4691
+ id: this.getIdFromPath(this.instance.path),
4692
+ titleIconClass: getSchemaXOption(this.instance.schema, "titleIconClass"),
4693
+ titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
4694
+ info: this.getInfo()
4695
+ });
4696
+ this.control.input.setAttribute("min", optionMin);
4697
+ this.control.input.setAttribute("max", optionMax);
4698
+ this.control.input.setAttribute("step", optionStep);
4699
+ const inputAttributes = getSchemaXOption(this.instance.schema, "inputAttributes");
4700
+ if (inputAttributes && typeof inputAttributes === "object") {
4701
+ Object.keys(inputAttributes).forEach((attr) => {
4702
+ this.control.input.setAttribute(attr, inputAttributes[attr]);
4703
+ });
4704
+ }
4705
+ const currentValue = this.instance.getValue();
4706
+ this.control.output.textContent = currentValue !== void 0 ? currentValue : optionMin;
4707
+ }
4708
+ adaptForTable() {
4709
+ this.theme.adaptForTableInputControl(this.control);
4710
+ }
4711
+ addEventListeners() {
4712
+ this.control.input.addEventListener("change", () => {
4713
+ const value = parseFloat(this.control.input.value);
4714
+ this.control.output.textContent = value;
4715
+ this.instance.setValue(value, true, "user");
4716
+ });
4717
+ }
4718
+ sanitize(value) {
4719
+ const schemaType = getSchemaType(this.instance.schema);
4720
+ const numValue = Number(value);
4721
+ if (schemaType === "integer") {
4722
+ return Math.round(numValue);
4723
+ }
4724
+ return numValue;
4725
+ }
4726
+ refreshUI() {
4727
+ super.refreshUI();
4728
+ const currentValue = this.instance.getValue();
4729
+ this.control.input.value = currentValue !== void 0 ? currentValue : 0;
4730
+ if (this.control.output) {
4731
+ this.control.output.textContent = currentValue !== void 0 ? currentValue : 0;
4732
+ }
4733
+ }
4734
+ }
4633
4735
  class UiResolver {
4634
4736
  constructor(options) {
4635
4737
  this.customEditors = options.customEditors ?? [];
@@ -4654,6 +4756,7 @@ class UiResolver {
4654
4756
  EditorStringInput,
4655
4757
  EditorNumberIMask,
4656
4758
  EditorNumberRaty,
4759
+ EditorNumberRange,
4657
4760
  EditorNumberRadios,
4658
4761
  EditorNumberSelect,
4659
4762
  EditorNumberInput,
@@ -5004,7 +5107,7 @@ class Jedison extends EventEmitter {
5004
5107
  }, options);
5005
5108
  this.rootName = "#";
5006
5109
  this.pathSeparator = "/";
5007
- this.instances = {};
5110
+ this.instances = /* @__PURE__ */ new Map();
5008
5111
  this.root = null;
5009
5112
  this.translator = new Translator({
5010
5113
  language: this.options.language,
@@ -5181,14 +5284,13 @@ class Jedison extends EventEmitter {
5181
5284
  * Adds a child instance pointer to the instances list
5182
5285
  */
5183
5286
  register(instance) {
5184
- this.instances[instance.path] = instance;
5287
+ this.instances.set(instance.path, instance);
5185
5288
  }
5186
5289
  /**
5187
5290
  * Deletes a child instance pointer from the instances list
5188
5291
  */
5189
5292
  unregister(instance) {
5190
- this.instances[instance.path] = null;
5191
- delete this.instances[instance.path];
5293
+ this.instances.delete(instance.path);
5192
5294
  }
5193
5295
  logIfEditor(...params) {
5194
5296
  if (this.isEditor) {
@@ -5346,7 +5448,7 @@ class Jedison extends EventEmitter {
5346
5448
  * @return {*}
5347
5449
  */
5348
5450
  getInstance(path) {
5349
- return this.instances[path];
5451
+ return this.instances.get(path);
5350
5452
  }
5351
5453
  /**
5352
5454
  * Disables the root instance and it's children user interfaces
@@ -5367,25 +5469,23 @@ class Jedison extends EventEmitter {
5367
5469
  */
5368
5470
  getErrors(filters = ["error"]) {
5369
5471
  let results = [];
5370
- Object.keys(this.instances).forEach((key) => {
5371
- const instance = this.instances[key];
5472
+ for (const instance of this.instances.values()) {
5372
5473
  results = [...results, ...instance.getErrors()];
5373
- });
5474
+ }
5374
5475
  return results.filter((error) => {
5375
5476
  return filters.includes(error.type.toLowerCase());
5376
5477
  });
5377
5478
  }
5378
5479
  export() {
5379
5480
  const results = [];
5380
- Object.keys(this.instances).forEach((key) => {
5381
- const instance = this.instances[key];
5481
+ for (const instance of this.instances.values()) {
5382
5482
  results.push({
5383
5483
  path: instance.path ?? "-",
5384
5484
  type: instance.schema.type ?? "-",
5385
5485
  title: instance.ui.getTitle() ?? "-",
5386
5486
  value: instance.getValue() ?? "-"
5387
5487
  });
5388
- });
5488
+ }
5389
5489
  return results;
5390
5490
  }
5391
5491
  /**
@@ -5402,10 +5502,9 @@ class Jedison extends EventEmitter {
5402
5502
  return false;
5403
5503
  }
5404
5504
  const errors = errorsList ?? this.getErrors();
5405
- Object.keys(this.instances).forEach((key) => {
5406
- const instance = this.instances[key];
5505
+ for (const instance of this.instances.values()) {
5407
5506
  instance.ui.showValidationErrors(errors, true);
5408
- });
5507
+ }
5409
5508
  }
5410
5509
  watch(path, callback) {
5411
5510
  if (!this.watched[path]) {
@@ -6562,6 +6661,15 @@ class Theme {
6562
6661
  container.appendChild(actions);
6563
6662
  return { container, input, label, info, labelText, description, messages, actions };
6564
6663
  }
6664
+ getInputRangeControl(config) {
6665
+ const control = this.getInputControl(config);
6666
+ const output = document.createElement("output");
6667
+ output.className = "range-output";
6668
+ output.style.marginLeft = "10px";
6669
+ output.style.fontWeight = "bold";
6670
+ control.input.parentNode.insertBefore(output, control.input.nextSibling);
6671
+ return { ...control, output };
6672
+ }
6565
6673
  adaptForTableInputControl(control) {
6566
6674
  this.visuallyHidden(control.label);
6567
6675
  this.visuallyHidden(control.description);
@@ -6929,7 +7037,7 @@ class Theme {
6929
7037
  const arrayActions = document.createElement("span");
6930
7038
  const text = document.createElement("span");
6931
7039
  link.classList.add("jedi-nav-link");
6932
- link.setAttribute("href", "#" + config.id);
7040
+ link.setAttribute("href", "#tab-pane-" + config.id);
6933
7041
  text.classList.add("jedi-nav-text");
6934
7042
  text.textContent = config.hasErrors ? "⚠ " + config.title : config.title;
6935
7043
  link.appendChild(arrayActions);
@@ -6984,7 +7092,7 @@ class Theme {
6984
7092
  * Set tab attributes to make it toggleable
6985
7093
  */
6986
7094
  setTabPaneAttributes(element, active, id) {
6987
- element.setAttribute("id", id);
7095
+ element.setAttribute("id", "tab-pane-" + id);
6988
7096
  element.classList.add("jedi-tab-pane");
6989
7097
  }
6990
7098
  /**
@@ -7139,6 +7247,9 @@ class ThemeBootstrap3 extends Theme {
7139
7247
  }
7140
7248
  return control;
7141
7249
  }
7250
+ getInputRangeControl(config) {
7251
+ return super.getInputRangeControl(config);
7252
+ }
7142
7253
  adaptForTableInputControl(control, td) {
7143
7254
  super.adaptForTableInputControl(control, td);
7144
7255
  control.container.classList.remove("form-group");
@@ -7463,6 +7574,17 @@ class ThemeBootstrap4 extends Theme {
7463
7574
  }
7464
7575
  return control;
7465
7576
  }
7577
+ getInputRangeControl(config) {
7578
+ const control = super.getInputRangeControl(config);
7579
+ const { container, input, label } = control;
7580
+ container.classList.add("form-group");
7581
+ input.classList.add("custom-range");
7582
+ input.classList.remove("form-control");
7583
+ if (config.titleHidden) {
7584
+ this.visuallyHidden(label);
7585
+ }
7586
+ return control;
7587
+ }
7466
7588
  adaptForTableInputControl(control, td) {
7467
7589
  super.adaptForTableInputControl(control, td);
7468
7590
  control.container.classList.remove("form-group");
@@ -7811,6 +7933,17 @@ class ThemeBootstrap5 extends Theme {
7811
7933
  }
7812
7934
  return control;
7813
7935
  }
7936
+ getInputRangeControl(config) {
7937
+ const control = super.getInputRangeControl(config);
7938
+ const { container, input, label } = control;
7939
+ container.classList.add("mb-3");
7940
+ input.classList.add("form-range");
7941
+ input.classList.remove("form-control");
7942
+ if (config.titleHidden) {
7943
+ this.visuallyHidden(label);
7944
+ }
7945
+ return control;
7946
+ }
7814
7947
  adaptForTableInputControl(control, td) {
7815
7948
  super.adaptForTableInputControl(control, td);
7816
7949
  control.container.classList.remove("mb-3");
@@ -8039,6 +8172,7 @@ const index = {
8039
8172
  EditorStringTextarea,
8040
8173
  EditorStringAwesomplete,
8041
8174
  EditorStringInput,
8175
+ EditorNumberRange,
8042
8176
  EditorNumber,
8043
8177
  EditorNumberRadios,
8044
8178
  EditorNumberSelect,