native-document 1.0.153 → 1.0.154

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.
@@ -34,7 +34,7 @@ var NativeComponents = (function (exports) {
34
34
  VALID_TYPES[COMMON_NODE_TYPES.DOCUMENT_FRAGMENT] = true;
35
35
  VALID_TYPES[COMMON_NODE_TYPES.COMMENT] = true;
36
36
 
37
- const Validator = {
37
+ const Validator$1 = {
38
38
  isObservable(value) {
39
39
  return value && (value.__$isObservable || value.__$Observable);
40
40
  },
@@ -51,7 +51,7 @@ var NativeComponents = (function (exports) {
51
51
  return value?.__isProxy__
52
52
  },
53
53
  isObservableOrProxy(value) {
54
- return Validator.isObservable(value) || Validator.isProxy(value);
54
+ return Validator$1.isObservable(value) || Validator$1.isProxy(value);
55
55
  },
56
56
  isAnchor(value) {
57
57
  return value?.__Anchor__
@@ -134,8 +134,8 @@ var NativeComponents = (function (exports) {
134
134
  if(!data) {
135
135
  return false;
136
136
  }
137
- return Validator.isObject(data)
138
- && Object.values(data).some(value => Validator.isObservable(value));
137
+ return Validator$1.isObject(data)
138
+ && Object.values(data).some(value => Validator$1.isObservable(value));
139
139
  },
140
140
  /**
141
141
  * Check if the data contains an observable reference.
@@ -158,7 +158,7 @@ var NativeComponents = (function (exports) {
158
158
  };
159
159
 
160
160
  const cssPropertyAccumulator = function(initialValue = {}) {
161
- let data = Validator.isString(initialValue) ? initialValue.split(';').filter(Boolean) : initialValue;
161
+ let data = Validator$1.isString(initialValue) ? initialValue.split(';').filter(Boolean) : initialValue;
162
162
 
163
163
  return {
164
164
  add(key, value) {
@@ -166,7 +166,7 @@ var NativeComponents = (function (exports) {
166
166
  data.push(key+': '+value);
167
167
  return;
168
168
  }
169
- if(Validator.isObject(key)) {
169
+ if(Validator$1.isObject(key)) {
170
170
  value = key;
171
171
  for(const property in value) {
172
172
  data[property] = value[property];
@@ -185,11 +185,11 @@ var NativeComponents = (function (exports) {
185
185
  };
186
186
 
187
187
  const classPropertyAccumulator = function(initialValue = []) {
188
- let data = Validator.isString(initialValue) ? initialValue.split(" ").filter(Boolean) : initialValue;
188
+ let data = Validator$1.isString(initialValue) ? initialValue.split(" ").filter(Boolean) : initialValue;
189
189
 
190
190
  return {
191
191
  add(key, value = true) {
192
- if(Validator.isJson(key)) {
192
+ if(Validator$1.isJson(key)) {
193
193
  for(const property in key) {
194
194
  if(key[property]) {
195
195
  data[property] = key[property];
@@ -312,6 +312,19 @@ var NativeComponents = (function (exports) {
312
312
  }
313
313
  };
314
314
 
315
+ const nextTick = function(fn) {
316
+ let pending = false;
317
+ return function(...args) {
318
+ if (pending) return;
319
+ pending = true;
320
+
321
+ Promise.resolve().then(() => {
322
+ fn.apply(this, args);
323
+ pending = false;
324
+ });
325
+ };
326
+ };
327
+
315
328
  const deepClone = (value, onObservableFound) => {
316
329
  try {
317
330
  if(window.structuredClone !== undefined) {
@@ -334,7 +347,7 @@ var NativeComponents = (function (exports) {
334
347
  }
335
348
 
336
349
  // Observables - keep the référence
337
- if (Validator.isObservable(value)) {
350
+ if (Validator$1.isObservable(value)) {
338
351
  onObservableFound && onObservableFound(value);
339
352
  return value;
340
353
  }
@@ -412,7 +425,7 @@ var NativeComponents = (function (exports) {
412
425
  * @class ObservableItem
413
426
  */
414
427
  function ObservableItem(value, configs = null) {
415
- value = Validator.isObservable(value) ? value.val() : value;
428
+ value = Validator$1.isObservable(value) ? value.val() : value;
416
429
 
417
430
  this.$previousValue = null;
418
431
  this.$currentValue = value;
@@ -426,7 +439,7 @@ var NativeComponents = (function (exports) {
426
439
  if(configs) {
427
440
  this.configs = configs;
428
441
  if(configs.reset) {
429
- this.$initialValue = Validator.isObject(value) ? deepClone(value) : value;
442
+ this.$initialValue = Validator$1.isObject(value) ? deepClone(value) : value;
430
443
  }
431
444
  }
432
445
  }
@@ -443,6 +456,7 @@ var NativeComponents = (function (exports) {
443
456
 
444
457
  ObservableItem.prototype.__$Observable = true;
445
458
  ObservableItem.prototype.__$isObservable = true;
459
+ ObservableItem.computed = () => {};
446
460
  const noneTrigger = function() {};
447
461
 
448
462
  /**
@@ -643,7 +657,7 @@ var NativeComponents = (function (exports) {
643
657
  if(!watchValueList) {
644
658
  watchValueList = callback;
645
659
  this.$watchers.set(value, callback);
646
- } else if(!Validator.isArray(watchValueList.list)) {
660
+ } else if(!Validator$1.isArray(watchValueList.list)) {
647
661
  watchValueList = [watchValueList, callback];
648
662
  callback = (value) => {
649
663
  for(let i = 0, length = watchValueList.length; i < length; i++) {
@@ -715,151 +729,1277 @@ var NativeComponents = (function (exports) {
715
729
  this.subscribe(handler);
716
730
  };
717
731
 
718
- /**
719
- * Unsubscribe from an observable.
720
- * @param {Function} callback
721
- */
722
- ObservableItem.prototype.unsubscribe = function(callback) {
723
- if(!this.$listeners) return;
724
- const index = this.$listeners.indexOf(callback);
725
- if (index > -1) {
726
- this.$listeners.splice(index, 1);
732
+ /**
733
+ * Unsubscribe from an observable.
734
+ * @param {Function} callback
735
+ */
736
+ ObservableItem.prototype.unsubscribe = function(callback) {
737
+ if(!this.$listeners) return;
738
+ const index = this.$listeners.indexOf(callback);
739
+ if (index > -1) {
740
+ this.$listeners.splice(index, 1);
741
+ }
742
+ this.assocTrigger();
743
+ };
744
+
745
+
746
+
747
+
748
+ /**
749
+ * Gets a property value from the observable's current value.
750
+ * If the property is an observable, returns its value.
751
+ *
752
+ * @param {string|number} key - Property key to retrieve
753
+ * @returns {*} The value of the property, unwrapped if it's an observable
754
+ * @example
755
+ * const user = Observable({ name: 'John', age: Observable(25) });
756
+ * user.get('name'); // 'John'
757
+ * user.get('age'); // 25 (unwrapped from observable)
758
+ */
759
+ ObservableItem.prototype.get = function(key) {
760
+ const item = this.$currentValue[key];
761
+ return Validator$1.isObservable(item) ? item.val() : item;
762
+ };
763
+
764
+
765
+ /**
766
+ * Compares the observable's current value with another value or observable.
767
+ *
768
+ * @param {*|ObservableItem} other - Value or observable to compare against
769
+ * @returns {boolean} True if values are equal
770
+ * @example
771
+ * const a = Observable(5);
772
+ * const b = Observable(5);
773
+ * a.equals(5); // true
774
+ * a.equals(b); // true
775
+ * a.equals(10); // false
776
+ */
777
+ ObservableItem.prototype.equals = function(other) {
778
+ if(Validator$1.isObservable(other)) {
779
+ return this.$currentValue === other.$currentValue;
780
+ }
781
+ return this.$currentValue === other;
782
+ };
783
+
784
+ /**
785
+ * Converts the observable's current value to a boolean.
786
+ *
787
+ * @returns {boolean} The boolean representation of the current value
788
+ * @example
789
+ * const count = Observable(0);
790
+ * count.toBool(); // false
791
+ * count.set(5);
792
+ * count.toBool(); // true
793
+ */
794
+ ObservableItem.prototype.toBool = function() {
795
+ return !!this.$currentValue;
796
+ };
797
+
798
+ /**
799
+ * Toggles the boolean value of the observable (false becomes true, true becomes false).
800
+ *
801
+ * @example
802
+ * const isOpen = Observable(false);
803
+ * isOpen.toggle(); // Now true
804
+ * isOpen.toggle(); // Now false
805
+ */
806
+ ObservableItem.prototype.toggle = function() {
807
+ this.set(!this.$currentValue);
808
+ };
809
+
810
+ /**
811
+ * Resets the observable to its initial value.
812
+ * Only works if the observable was created with { reset: true } config.
813
+ *
814
+ * @example
815
+ * const count = Observable(0, { reset: true });
816
+ * count.set(10);
817
+ * count.reset(); // Back to 0
818
+ */
819
+ ObservableItem.prototype.reset = function() {
820
+ if(!this.configs?.reset) {
821
+ return;
822
+ }
823
+ const resetValue = (Validator$1.isObject(this.$initialValue))
824
+ ? deepClone(this.$initialValue, (observable) => {
825
+ observable.reset();
826
+ })
827
+ : this.$initialValue;
828
+ this.set(resetValue);
829
+ };
830
+
831
+ /**
832
+ * Returns a string representation of the observable's current value.
833
+ *
834
+ * @returns {string} String representation of the current value
835
+ */
836
+ ObservableItem.prototype.toString = function() {
837
+ return String(this.$currentValue);
838
+ };
839
+
840
+ /**
841
+ * Returns the primitive value of the observable (its current value).
842
+ * Called automatically in type coercion contexts.
843
+ *
844
+ * @returns {*} The current value of the observable
845
+ */
846
+ ObservableItem.prototype.valueOf = function() {
847
+ return this.$currentValue;
848
+ };
849
+
850
+
851
+
852
+ ObservableItem.prototype.persist = function(key, options = {}) {
853
+ let value = $getFromStorage(key, this.$currentValue);
854
+ if(options.get) {
855
+ value = options.get(value);
856
+ }
857
+ this.set(value);
858
+ const saver = $saveToStorage(this.$currentValue);
859
+ this.subscribe((newValue) => {
860
+ saver(key, options.set ? options.set(newValue) : newValue);
861
+ });
862
+ return this;
863
+ };
864
+
865
+ ObservableItem.prototype.clone = function() {
866
+ let clonedValue = this.$currentValue;
867
+
868
+ if(clonedValue && typeof clonedValue === 'object') {
869
+ if(typeof clonedValue.clone === 'function') {
870
+ clonedValue = clonedValue.clone();
871
+ } else {
872
+ clonedValue = structuredClone(clonedValue);
873
+ }
874
+ }
875
+
876
+ return new ObservableItem(clonedValue);
877
+ };
878
+
879
+ function createMultiSourceFilter(sources, callbackFn){
880
+ const observables = sources.filter(Validator$1.isObservable);
881
+
882
+ const getValues = () => sources.map(src =>
883
+ Validator$1.isObservable(src) ? src.val() : src
884
+ );
885
+
886
+ return {
887
+ dependencies: observables.length > 0 ? observables : null,
888
+ callback: (value) => callbackFn(value, getValues())
889
+ };
890
+ }
891
+
892
+ function match(patternObservableOrValue, asRegexObservableOrValue = true, flagsObservableOrValue = ''){
893
+ return createMultiSourceFilter(
894
+ [patternObservableOrValue, asRegexObservableOrValue, flagsObservableOrValue],
895
+ (value, [pattern, asRegex, flags]) => {
896
+ if (!pattern) return true;
897
+
898
+ if (asRegex){
899
+ try {
900
+ const regex = new RegExp(pattern, flags);
901
+ return regex.test(String(value));
902
+ } catch (error){
903
+ DebugManager$1.warn('Invalid regex pattern:', pattern, error);
904
+ return false;
905
+ }
906
+ }
907
+
908
+ if (!flags || flags === ''){
909
+ return String(value).toLowerCase().includes(String(pattern).toLowerCase());
910
+ }
911
+ return String(value).includes(String(pattern));
912
+ }
913
+ );
914
+ }
915
+
916
+ const mutationMethods = ['push', 'pop', 'shift', 'unshift', 'reverse', 'sort', 'splice'];
917
+ const noMutationMethods = ['map', 'forEach', 'filter', 'reduce', 'some', 'every', 'find', 'findIndex', 'concat', 'includes', 'indexOf'];
918
+
919
+ /**
920
+ *
921
+ * @param target
922
+ * @param {{propagation: boolean, deep: boolean, reset: boolean}|null} configs
923
+ * @constructor
924
+ */
925
+ const ObservableArray = function (target, configs = null) {
926
+ if(!Array.isArray(target)) {
927
+ throw new NativeDocumentError('Observable.array : target must be an array');
928
+ }
929
+
930
+ ObservableItem.call(this, target, configs);
931
+ };
932
+
933
+ ObservableArray.prototype = Object.create(ObservableItem.prototype);
934
+ ObservableArray.prototype.constructor = ObservableArray;
935
+ ObservableArray.prototype.__$isObservableArray = true;
936
+
937
+
938
+ Object.defineProperty(ObservableArray.prototype, 'length', {
939
+ get() {
940
+ return this.$currentValue.length;
941
+ }
942
+ });
943
+
944
+
945
+ ObservableArray.prototype.$mutate = function(action, args, mutateFn) {
946
+ if(this.$mutationInterceptor) {
947
+ const value = this.$mutationInterceptor(args, { action });
948
+ if(args !== undefined) {
949
+ args = value;
950
+ }
951
+ }
952
+ mutateFn(args);
953
+ };
954
+
955
+ mutationMethods.forEach((method) => {
956
+ ObservableArray.prototype[method] = function(...values) {
957
+ return this.$mutate(method, values, (argsToUse) => {
958
+ const result = this.$currentValue[method].apply(this.$currentValue, argsToUse);
959
+ this.trigger({ action: method, args: argsToUse, result });
960
+ return result;
961
+ })
962
+ };
963
+ });
964
+
965
+ noMutationMethods.forEach((method) => {
966
+ ObservableArray.prototype[method] = function(...values) {
967
+ return this.$currentValue[method].apply(this.$currentValue, values);
968
+ };
969
+ });
970
+
971
+
972
+ const $clearEvent = { action: 'clear' };
973
+
974
+ /**
975
+ * Removes all items from the array and triggers an update.
976
+ *
977
+ * @returns {boolean} True if array was cleared, false if it was already empty
978
+ * @example
979
+ * const items = Observable.array([1, 2, 3]);
980
+ * items.clear(); // []
981
+ */
982
+ ObservableArray.prototype.clear = function() {
983
+ if(this.$currentValue.length === 0) {
984
+ return;
985
+ }
986
+ this.$mutate('clear', [], () => {
987
+ this.$currentValue.length = 0;
988
+ this.trigger($clearEvent);
989
+ });
990
+ return true;
991
+ };
992
+
993
+ /**
994
+ * Returns the element at the specified index in the array.
995
+ *
996
+ * @param {number} index - Zero-based index of the element to retrieve
997
+ * @returns {*} The element at the specified index
998
+ * @example
999
+ * const items = Observable.array(['a', 'b', 'c']);
1000
+ * items.at(1); // 'b'
1001
+ */
1002
+ ObservableArray.prototype.at = function(index) {
1003
+ return this.$currentValue[index];
1004
+ };
1005
+
1006
+
1007
+ /**
1008
+ * Merges multiple values into the array and triggers an update.
1009
+ * Similar to push but with a different operation name.
1010
+ *
1011
+ * @param {Array} values - Array of values to merge
1012
+ * @example
1013
+ * const items = Observable.array([1, 2]);
1014
+ * items.merge([3, 4]); // [1, 2, 3, 4]
1015
+ */
1016
+ ObservableArray.prototype.merge = function(values) {
1017
+ this.$mutate('merge', values, (valuesToMerge) => {
1018
+ this.$currentValue.push.apply(this.$currentValue, valuesToMerge);
1019
+ this.trigger({ action: 'merge', args: valuesToMerge });
1020
+ });
1021
+ };
1022
+
1023
+ /**
1024
+ * Counts the number of elements that satisfy the provided condition.
1025
+ *
1026
+ * @param {(value: *, index: number) => Boolean} condition - Function that tests each element (item, index) => boolean
1027
+ * @returns {number} The count of elements that satisfy the condition
1028
+ * @example
1029
+ * const numbers = Observable.array([1, 2, 3, 4, 5]);
1030
+ * numbers.count(n => n > 3); // 2
1031
+ */
1032
+ ObservableArray.prototype.count = function(condition) {
1033
+ let count = 0;
1034
+ this.$currentValue.forEach((item, index) => {
1035
+ if(condition(item, index)) {
1036
+ count++;
1037
+ }
1038
+ });
1039
+ return count;
1040
+ };
1041
+
1042
+ /**
1043
+ * Swaps two elements at the specified indices and triggers an update.
1044
+ *
1045
+ * @param {number} indexA - Index of the first element
1046
+ * @param {number} indexB - Index of the second element
1047
+ * @returns {boolean} True if swap was successful, false if indices are out of bounds
1048
+ * @example
1049
+ * const items = Observable.array(['a', 'b', 'c']);
1050
+ * items.swap(0, 2); // ['c', 'b', 'a']
1051
+ */
1052
+ ObservableArray.prototype.swap = function(indexA, indexB) {
1053
+ this.$mutate('swap', [indexA, indexB], ([indexA, indexB]) => {
1054
+ const value = this.$currentValue;
1055
+ const length = value.length;
1056
+ if(indexB < indexA) {
1057
+ const temp = indexA;
1058
+ indexA = indexB;
1059
+ indexB = temp;
1060
+ }
1061
+ if(length < indexA || length < indexB) {
1062
+ return false;
1063
+ }
1064
+ const elementA = value[indexA];
1065
+ const elementB = value[indexB];
1066
+
1067
+ value[indexA] = elementB;
1068
+ value[indexB] = elementA;
1069
+ this.trigger({ action: 'swap', args: [indexA, indexB], result: [elementA, elementB] });
1070
+ });
1071
+ return true;
1072
+ };
1073
+
1074
+ ObservableArray.prototype.swapItems = function(itemA, itemB) {
1075
+ const indexA = this.$currentValue.indexOf(itemA);
1076
+ const indexB = this.$currentValue.indexOf(itemB);
1077
+
1078
+ return this.swap(indexA, indexB);
1079
+ };
1080
+
1081
+ ObservableArray.prototype.insertAfter = function(data, target) {
1082
+ const targetIndex = this.$currentValue.indexOf(target);
1083
+ return this.splice(targetIndex + 1, 0, data);
1084
+ };
1085
+
1086
+ /**
1087
+ * Removes the element at the specified index and triggers an update.
1088
+ *
1089
+ * @param {number} index - Index of the element to remove
1090
+ * @returns {Array} Array containing the removed element, or empty array if index is invalid
1091
+ * @example
1092
+ * const items = Observable.array(['a', 'b', 'c']);
1093
+ * items.remove(1); // ['b'] - Array is now ['a', 'c']
1094
+ */
1095
+ ObservableArray.prototype.remove = function(index) {
1096
+ let deleted = [];
1097
+ this.$mutate('remove', [index], ([idx]) => {
1098
+ deleted = this.$currentValue.splice(idx, 1);
1099
+ if(deleted.length === 0) {
1100
+ return;
1101
+ }
1102
+ this.trigger({action: 'remove', args: [idx], result: deleted[0]});
1103
+ });
1104
+ return deleted;
1105
+ };
1106
+
1107
+ /**
1108
+ * Removes the first occurrence of the specified item from the array.
1109
+ *
1110
+ * @param {*} item - The item to remove
1111
+ * @returns {Array} Array containing the removed element, or empty array if item not found
1112
+ * @example
1113
+ * const items = Observable.array(['a', 'b', 'c']);
1114
+ * items.removeItem('b'); // ['b'] - Array is now ['a', 'c']
1115
+ */
1116
+ ObservableArray.prototype.removeItem = function(item) {
1117
+ const indexOfItem = this.$currentValue.indexOf(item);
1118
+ if(indexOfItem === -1) {
1119
+ return [];
1120
+ }
1121
+ return this.remove(indexOfItem);
1122
+ };
1123
+
1124
+ /**
1125
+ * Checks if the array is empty.
1126
+ *
1127
+ * @returns {boolean} True if array has no elements
1128
+ * @example
1129
+ * const items = Observable.array([]);
1130
+ * items.isEmpty(); // true
1131
+ */
1132
+ ObservableArray.prototype.empty = function() {
1133
+ return this.$currentValue.length === 0;
1134
+ };
1135
+
1136
+ /**
1137
+ * Triggers a populate operation with the current array, iteration count, and callback.
1138
+ * Used internally for rendering optimizations.
1139
+ *
1140
+ * @param {number} iteration - Iteration count for rendering
1141
+ * @param {Function} callback - Callback function for rendering items
1142
+ */
1143
+ ObservableArray.prototype.populateAndRender = function(iteration, callback) {
1144
+ this.trigger({ action: 'populate', args: [this.$currentValue, iteration, callback] });
1145
+ };
1146
+
1147
+
1148
+ /**
1149
+ * Creates a filtered view of the array based on predicates.
1150
+ * The filtered array updates automatically when source data or predicates change.
1151
+ *
1152
+ * @param {Object} predicates - Object mapping property names to filter conditions or functions
1153
+ * @returns {ObservableArray} A new observable array containing filtered items
1154
+ * @example
1155
+ * const users = Observable.array([
1156
+ * { name: 'John', age: 25 },
1157
+ * { name: 'Jane', age: 30 }
1158
+ * ]);
1159
+ *
1160
+ * const adults = users.where({ age: (val) => val >= 18 });
1161
+ */
1162
+ ObservableArray.prototype.where = function(predicates) {
1163
+ if(typeof predicates === 'function') {
1164
+ predicates = { _: predicates };
1165
+ }
1166
+ const sourceArray = this;
1167
+ const observableDependencies = [sourceArray];
1168
+ const filterCallbacks = {};
1169
+
1170
+ for (const [key, rawPredicate] of Object.entries(predicates)) {
1171
+ const predicate = Validator$1.isObservable(rawPredicate) ? match(rawPredicate, false) : rawPredicate;
1172
+ if (predicate && typeof predicate === 'object' && 'callback' in predicate) {
1173
+ filterCallbacks[key] = predicate.callback;
1174
+
1175
+ if (predicate.dependencies) {
1176
+ const deps = Array.isArray(predicate.dependencies)
1177
+ ? predicate.dependencies
1178
+ : [predicate.dependencies];
1179
+ observableDependencies.push.apply(observableDependencies, deps);
1180
+ }
1181
+ } else if(typeof predicate === 'function') {
1182
+ filterCallbacks[key] = predicate;
1183
+ } else {
1184
+ filterCallbacks[key] = (value) => value === predicate;
1185
+ }
1186
+ }
1187
+
1188
+ const viewArray = new ObservableArray([]);
1189
+
1190
+ const filters = Object.entries(filterCallbacks);
1191
+ const updateView = () => {
1192
+ const filtered = sourceArray.val().filter(item => {
1193
+ for (const [key, callback] of filters) {
1194
+ if(key === '_') {
1195
+ if (!callback(item)) return false;
1196
+ } else {
1197
+ if (!callback(item[key])) return false;
1198
+ }
1199
+ }
1200
+ return true;
1201
+ });
1202
+
1203
+ viewArray.set(filtered);
1204
+ };
1205
+
1206
+ observableDependencies.forEach(dep => dep.subscribe(updateView));
1207
+
1208
+ updateView();
1209
+
1210
+ return viewArray;
1211
+ };
1212
+
1213
+ /**
1214
+ * Creates a filtered view where at least one of the specified fields matches the filter.
1215
+ *
1216
+ * @param {Array<string>} fields - Array of field names to check
1217
+ * @param {FilterResult} filter - Filter condition with callback and dependencies
1218
+ * @returns {ObservableArray} A new observable array containing filtered items
1219
+ * @example
1220
+ * const products = Observable.array([
1221
+ * { name: 'Apple', category: 'Fruit' },
1222
+ * { name: 'Carrot', category: 'Vegetable' }
1223
+ * ]);
1224
+ * const searchTerm = Observable('App');
1225
+ * const filtered = products.whereSome(['name', 'category'], match(searchTerm));
1226
+ */
1227
+ ObservableArray.prototype.whereSome = function(fields, filter) {
1228
+ return this.where({
1229
+ _: {
1230
+ dependencies: filter.dependencies,
1231
+ callback: (item) => fields.some(field => filter.callback(item[field]))
1232
+ }
1233
+ });
1234
+ };
1235
+
1236
+ /**
1237
+ * Creates a filtered view where all specified fields match the filter.
1238
+ *
1239
+ * @param {Array<string>} fields - Array of field names to check
1240
+ * @param {FilterResult} filter - Filter condition with callback and dependencies
1241
+ * @returns {ObservableArray} A new observable array containing filtered items
1242
+ * @example
1243
+ * const items = Observable.array([
1244
+ * { status: 'active', verified: true },
1245
+ * { status: 'active', verified: false }
1246
+ * ]);
1247
+ * const activeFilter = equals('active');
1248
+ * const filtered = items.whereEvery(['status', 'verified'], activeFilter);
1249
+ */
1250
+ ObservableArray.prototype.whereEvery = function(fields, filter) {
1251
+ return this.where({
1252
+ _: {
1253
+ dependencies: filter.dependencies,
1254
+ callback: (item) => fields.every(field => filter.callback(item[field]))
1255
+ }
1256
+ });
1257
+ };
1258
+
1259
+ ObservableArray.prototype.deepSubscribe = function(callback) {
1260
+ const updatedValue = nextTick(() => callback(this.val()));
1261
+ const $listeners = new WeakMap();
1262
+
1263
+ const bindItem = (item) => {
1264
+ if ($listeners.has(item)) {
1265
+ return;
1266
+ }
1267
+ if (item?.__$isObservableArray) {
1268
+ $listeners.set(item, item.deepSubscribe(updatedValue));
1269
+ return;
1270
+ }
1271
+ if (item?.__$isObservable) {
1272
+ item.subscribe(updatedValue);
1273
+ $listeners.set(item, () => item.unsubscribe(updatedValue));
1274
+ }
1275
+ };
1276
+
1277
+ const unbindItem = (item) => {
1278
+ const unsub = $listeners.get(item);
1279
+ if (unsub) {
1280
+ unsub();
1281
+ $listeners.delete(item);
1282
+ }
1283
+ };
1284
+
1285
+ this.$currentValue.forEach(bindItem);
1286
+ this.subscribe(updatedValue);
1287
+
1288
+ this.subscribe((items, _, operations) => {
1289
+ switch (operations?.action) {
1290
+ case 'push':
1291
+ case 'unshift':
1292
+ operations.args.forEach(bindItem);
1293
+ break;
1294
+
1295
+ case 'splice': {
1296
+ const [start, deleteCount, ...newItems] = operations.args;
1297
+ operations.result?.forEach(unbindItem);
1298
+ newItems.forEach(bindItem);
1299
+ break;
1300
+ }
1301
+
1302
+ case 'remove':
1303
+ unbindItem(operations.result);
1304
+ break;
1305
+
1306
+ case 'merge':
1307
+ operations.args.forEach(bindItem);
1308
+ break;
1309
+
1310
+ case 'clear':
1311
+ this.$currentValue.forEach(unbindItem);
1312
+ break;
1313
+ }
1314
+ });
1315
+
1316
+ return () => {
1317
+ this.$currentValue.forEach(unbindItem);
1318
+ };
1319
+ };
1320
+
1321
+
1322
+ ObservableArray.prototype.sync = function(targetObservable) {
1323
+ if (!targetObservable || !targetObservable.__$isObservableArray) {
1324
+ throw new NativeDocumentError('ObservableArray.sync : target must be an ObservableArray');
1325
+ }
1326
+
1327
+ targetObservable.set([...this.$currentValue]);
1328
+
1329
+ const sync = (currentValue, _, operations) => {
1330
+ if (!operations) {
1331
+ targetObservable.set([...currentValue]);
1332
+ return;
1333
+ }
1334
+
1335
+ const { action, args } = operations;
1336
+ targetObservable[action].apply(targetObservable, args);
1337
+ };
1338
+ this.subscribe(sync);
1339
+
1340
+ return () => this.unsubscribe(sync);
1341
+ };
1342
+
1343
+ ObservableArray.prototype.clone = function() {
1344
+ return new ObservableArray(this.resolve());
1345
+ };
1346
+
1347
+ const ObservableObject = function(target, configs) {
1348
+ ObservableItem.call(this, target);
1349
+ this.$observables = {};
1350
+ this.configs = configs;
1351
+
1352
+ this.$load(target);
1353
+
1354
+ for(const name in target) {
1355
+ if(!Object.hasOwn(this, name)) {
1356
+ Object.defineProperty(this, name, {
1357
+ get: () => this.$observables[name],
1358
+ set: (value) => this.$observables[name].set(value)
1359
+ });
1360
+ }
1361
+ }
1362
+
1363
+ };
1364
+
1365
+ ObservableObject.prototype = Object.create(ObservableItem.prototype);
1366
+
1367
+ Object.defineProperty(ObservableObject, '$value', {
1368
+ get() {
1369
+ return this.val();
1370
+ },
1371
+ set(value) {
1372
+ this.set(value);
1373
+ }
1374
+ });
1375
+
1376
+ ObservableObject.prototype.__$isObservableObject = true;
1377
+ ObservableObject.prototype.__isProxy__ = true;
1378
+
1379
+ ObservableObject.prototype.$load = function(initialValue) {
1380
+ const configs = this.configs;
1381
+ for(const key in initialValue) {
1382
+ const itemValue = initialValue[key];
1383
+ if(Array.isArray(itemValue)) {
1384
+ if(configs?.deep !== false) {
1385
+ const mappedItemValue = itemValue.map(item => {
1386
+ if(Validator$1.isJson(item)) {
1387
+ return new ObservableObject(item, configs);
1388
+ }
1389
+ if(Validator$1.isArray(item)) {
1390
+ return new ObservableArray(item, configs);
1391
+ }
1392
+ return new ObservableItem(item, configs);
1393
+ });
1394
+ this.$observables[key] = new ObservableArray(mappedItemValue, configs);
1395
+ continue;
1396
+ }
1397
+ this.$observables[key] = new ObservableArray(itemValue, configs);
1398
+ continue;
1399
+ }
1400
+ if(Validator$1.isObservable(itemValue) || Validator$1.isProxy(itemValue)) {
1401
+ this.$observables[key] = itemValue;
1402
+ continue;
1403
+ }
1404
+ this.$observables[key] = (typeof itemValue === 'object') ? new ObservableObject(itemValue, configs) : new ObservableItem(itemValue, configs);
1405
+ }
1406
+ };
1407
+
1408
+ ObservableObject.prototype.val = function() {
1409
+ const result = {};
1410
+ for(const key in this.$observables) {
1411
+ const dataItem = this.$observables[key];
1412
+ if(Validator$1.isObservable(dataItem)) {
1413
+ let value = dataItem.val();
1414
+ if(Array.isArray(value)) {
1415
+ value = value.map(item => {
1416
+ if(Validator$1.isObservable(item)) {
1417
+ return item.val();
1418
+ }
1419
+ if(Validator$1.isProxy(item)) {
1420
+ return item.$value;
1421
+ }
1422
+ return item;
1423
+ });
1424
+ }
1425
+ result[key] = value;
1426
+ } else if(Validator$1.isProxy(dataItem)) {
1427
+ result[key] = dataItem.$value;
1428
+ } else {
1429
+ result[key] = dataItem;
1430
+ }
1431
+ }
1432
+ return result;
1433
+ };
1434
+ ObservableObject.prototype.$val = ObservableObject.prototype.val;
1435
+
1436
+ ObservableObject.prototype.get = function(property) {
1437
+ const item = this.$observables[property];
1438
+ if(Validator$1.isObservable(item)) {
1439
+ return item.val();
1440
+ }
1441
+ if(Validator$1.isProxy(item)) {
1442
+ return item.$value;
1443
+ }
1444
+ return item;
1445
+ };
1446
+ ObservableObject.prototype.$get = ObservableObject.prototype.get;
1447
+
1448
+ ObservableObject.prototype.set = function(newData) {
1449
+ const data = Validator$1.isProxy(newData) ? newData.$value : newData;
1450
+ const configs = this.configs;
1451
+
1452
+ for(const key in data) {
1453
+ const targetItem = this.$observables[key];
1454
+ const newValueOrigin = newData[key];
1455
+ const newValue = data[key];
1456
+
1457
+ if(Validator$1.isObservable(targetItem)) {
1458
+ if(!Validator$1.isArray(newValue)) {
1459
+ targetItem.set(newValue);
1460
+ continue;
1461
+ }
1462
+ const firstElementFromOriginalValue = newValueOrigin.at(0);
1463
+ if(Validator$1.isObservable(firstElementFromOriginalValue) || Validator$1.isProxy(firstElementFromOriginalValue)) {
1464
+ const newValues = newValue.map(item => {
1465
+ if(Validator$1.isProxy(firstElementFromOriginalValue)) {
1466
+ return new ObservableObject(item, configs);
1467
+ }
1468
+ return ObservableItem(item, configs);
1469
+ });
1470
+ targetItem.set(newValues);
1471
+ continue;
1472
+ }
1473
+ targetItem.set([...newValue]);
1474
+ continue;
1475
+ }
1476
+ if(Validator$1.isProxy(targetItem)) {
1477
+ targetItem.update(newValue);
1478
+ continue;
1479
+ }
1480
+ this[key] = newValue;
1481
+ }
1482
+ };
1483
+ ObservableObject.prototype.$set = ObservableObject.prototype.set;
1484
+ ObservableObject.prototype.$updateWith = ObservableObject.prototype.set;
1485
+
1486
+ ObservableObject.prototype.observables = function() {
1487
+ return Object.values(this.$observables);
1488
+ };
1489
+ ObservableObject.prototype.$observables = ObservableObject.prototype.observables;
1490
+
1491
+ ObservableObject.prototype.keys = function() {
1492
+ return Object.keys(this.$observables);
1493
+ };
1494
+ ObservableObject.prototype.$keys = ObservableObject.prototype.keys;
1495
+ ObservableObject.prototype.clone = function() {
1496
+ return new ObservableObject(this.val(), this.configs);
1497
+ };
1498
+ ObservableObject.prototype.$clone = ObservableObject.prototype.clone;
1499
+ ObservableObject.prototype.reset = function() {
1500
+ for(const key in this.$observables) {
1501
+ this.$observables[key].reset();
1502
+ }
1503
+ };
1504
+ ObservableObject.prototype.originalSubscribe = ObservableObject.prototype.subscribe;
1505
+ ObservableObject.prototype.subscribe = function(callback) {
1506
+ const observables = this.observables();
1507
+ const updatedValue = nextTick(() => this.trigger());
1508
+
1509
+ this.originalSubscribe(callback);
1510
+
1511
+ for (let i = 0, length = observables.length; i < length; i++) {
1512
+ const observable = observables[i];
1513
+ if (observable.__$isObservableArray) {
1514
+ observable.deepSubscribe(updatedValue);
1515
+ continue
1516
+ }
1517
+ observable.subscribe(updatedValue);
1518
+ }
1519
+ };
1520
+ ObservableObject.prototype.configs = function() {
1521
+ return this.configs;
1522
+ };
1523
+
1524
+ ObservableObject.prototype.update = ObservableObject.prototype.set;
1525
+
1526
+ const $computed = (fn, dependencies) => ObservableItem.computed(fn, dependencies);
1527
+ const $checker = (obs, fn) => obs.transform(fn);
1528
+
1529
+ //
1530
+ // is... -> ObservableChecker<boolean>
1531
+ //
1532
+
1533
+ ObservableItem.prototype.isEqualTo = function (value) {
1534
+ if (value?.__$Observable) {
1535
+ return $computed((a, b) => a === b, [this, value]);
1536
+ }
1537
+ return $checker(this, x => x === value);
1538
+ };
1539
+
1540
+ ObservableItem.prototype.isNotEqualTo = function (value) {
1541
+ if (value?.__$Observable) {
1542
+ return $computed((a, b) => a !== b, [this, value]);
1543
+ }
1544
+ return $checker(this, x => x !== value);
1545
+ };
1546
+
1547
+ ObservableItem.prototype.isGreaterThan = function (value) {
1548
+ if (value?.__$Observable) {
1549
+ return $computed((a, b) => a > b, [this, value]);
1550
+ }
1551
+ return $checker(this, x => x > value);
1552
+ };
1553
+
1554
+ ObservableItem.prototype.isGreaterThanOrEqualTo = function (value) {
1555
+ if (value?.__$Observable) {
1556
+ return $computed((a, b) => a >= b, [this, value]);
1557
+ }
1558
+ return $checker(this, x => x >= value);
1559
+ };
1560
+
1561
+ ObservableItem.prototype.isLessThan = function (value) {
1562
+ if (value?.__$Observable) {
1563
+ return $computed((a, b) => a < b, [this, value]);
1564
+ }
1565
+ return $checker(this, x => x < value);
1566
+ };
1567
+
1568
+ ObservableItem.prototype.isLessThanOrEqualTo = function (value) {
1569
+ if (value?.__$Observable) {
1570
+ return $computed((a, b) => a <= b, [this, value]);
1571
+ }
1572
+ return $checker(this, x => x <= value);
1573
+ };
1574
+
1575
+ ObservableItem.prototype.isBetween = function (min, max) {
1576
+ if (min.__$Observable && max.__$Observable) {
1577
+ return $computed((x, a, b) => x >= a && x <= b, [this, min, max]);
1578
+ }
1579
+ if (min.__$Observable) {
1580
+ return $computed((x, a) => x >= a && x <= max, [this, min]);
1581
+ }
1582
+ if (max.__$Observable) {
1583
+ return $computed((x, b) => x >= min && x <= b, [this, max]);
1584
+ }
1585
+ return $checker(this, x => x >= min && x <= max);
1586
+ };
1587
+
1588
+ ObservableItem.prototype.isNull = function () {
1589
+ return $checker(this, x => x == null);
1590
+ };
1591
+
1592
+ ObservableItem.prototype.isTruthy = function () {
1593
+ return $checker(this, x => !!x);
1594
+ };
1595
+
1596
+ ObservableItem.prototype.isFalsy = function () {
1597
+ return $checker(this, x => !x);
1598
+ };
1599
+
1600
+ ObservableItem.prototype.isStartingWith = function (str) {
1601
+ if (str?.__$Observable) {
1602
+ return $computed((a, b) => String(a).startsWith(b), [this, str]);
1603
+ }
1604
+ return $checker(this, x => String(x).startsWith(str));
1605
+ };
1606
+
1607
+ ObservableItem.prototype.isEndingWith = function (str) {
1608
+ if (str?.__$Observable) {
1609
+ return $computed((a, b) => String(a).endsWith(b), [this, str]);
1610
+ }
1611
+ return $checker(this, x => String(x).endsWith(str));
1612
+ };
1613
+
1614
+ ObservableItem.prototype.isMatchingPattern = function (regex) {
1615
+ if (regex?.__$Observable) {
1616
+ return $computed((a, b) => new RegExp(b).test(String(a)), [this, regex]);
1617
+ }
1618
+ return $checker(this, x => regex.test(String(x)));
1619
+ };
1620
+
1621
+ ObservableItem.prototype.isEmpty = function () {
1622
+ return $checker(this, x => x == null || x === '' || (Array.isArray(x) && x.length === 0));
1623
+ };
1624
+
1625
+ ObservableItem.prototype.isNotEmpty = function () {
1626
+ return $checker(this, x => x == null || x === '' || (Array.isArray(x) && x.length !== 0));
1627
+ };
1628
+
1629
+ ObservableItem.prototype.isIncludes = function (value) {
1630
+ if (value?.__$Observable) {
1631
+ return $computed((a, b) => {
1632
+ if (Array.isArray(a)) return a.includes(b);
1633
+ return String(a).includes(String(b));
1634
+ }, [this, value]);
1635
+ }
1636
+ return $checker(this, x => {
1637
+ if (Array.isArray(x)) return x.includes(value);
1638
+ return String(x).includes(String(value));
1639
+ });
1640
+ };
1641
+
1642
+ ObservableItem.prototype.isIncludedIn = function (array) {
1643
+ if (array?.__$Observable) {
1644
+ return $computed((a, b) => b.includes(a), [this, array]);
1645
+ }
1646
+ return $checker(this, x => array.includes(x));
1647
+ };
1648
+
1649
+ ObservableItem.prototype.isOneOf = ObservableItem.prototype.isIncludedIn;
1650
+
1651
+ ObservableItem.prototype.isHaving = function (key) {
1652
+ if (key?.__$Observable) {
1653
+ return $computed((a, b) => b in Object(a), [this, key]);
1654
+ }
1655
+ return $checker(this, x => key in Object(x));
1656
+ };
1657
+
1658
+ //
1659
+ // to... -> ObservableChecker<any>
1660
+ //
1661
+
1662
+ ObservableItem.prototype.toUpperCase = function () {
1663
+ return $checker(this, x => String(x).toUpperCase());
1664
+ };
1665
+
1666
+ ObservableItem.prototype.toLowerCase = function () {
1667
+ return $checker(this, x => String(x).toLowerCase());
1668
+ };
1669
+
1670
+ ObservableItem.prototype.toTrimmed = function () {
1671
+ return $checker(this, x => String(x).trim());
1672
+ };
1673
+
1674
+ ObservableItem.prototype.toBoolean = function () {
1675
+ return $checker(this, x => !!x);
1676
+ };
1677
+
1678
+ ObservableItem.prototype.toLiteral = function (template, placeholder = '${v}') {
1679
+ return $checker(this, x => template.replace(placeholder, x));
1680
+ };
1681
+
1682
+ ObservableItem.prototype.toFormatted = ObservableItem.prototype.toLiteral;
1683
+
1684
+ ObservableItem.prototype.toProperty = function (key) {
1685
+ const keys = key.split('.');
1686
+ return $checker(this, x => {
1687
+ let value = x;
1688
+ for (const k of keys) {
1689
+ if (value == null) return undefined;
1690
+ value = value[k];
1691
+ }
1692
+ return value;
1693
+ });
1694
+ };
1695
+
1696
+ ObservableItem.prototype.toLength = function () {
1697
+ return $checker(this, x => (x == null ? 0 : x.length));
1698
+ };
1699
+
1700
+ ObservableItem.prototype.toClamped = function (min, max) {
1701
+ if (min.__$Observable && max.__$Observable) {
1702
+ return $computed((x, a, b) => Math.min(Math.max(x, a), b), [this, min, max]);
727
1703
  }
728
- this.assocTrigger();
1704
+ if (min.__$Observable) {
1705
+ return $computed((x, a) => Math.min(Math.max(x, a), max), [this, min]);
1706
+ }
1707
+ if (max.__$Observable) {
1708
+ return $computed((x, b) => Math.min(Math.max(x, min), b), [this, max]);
1709
+ }
1710
+ return $checker(this, x => Math.min(Math.max(x, min), max));
729
1711
  };
730
1712
 
731
-
732
-
1713
+ ObservableItem.prototype.toPercent = function (total) {
1714
+ if (total?.__$Observable) {
1715
+ return $computed((a, b) => (b === 0 ? 0 : (a / b) * 100), [this, total]);
1716
+ }
1717
+ return $checker(this, x => (total === 0 ? 0 : (x / total) * 100));
1718
+ };
733
1719
 
734
1720
  /**
735
- * Gets a property value from the observable's current value.
736
- * If the property is an observable, returns its value.
1721
+ * Creates an ObservableWhen that tracks whether an observable equals a specific value.
737
1722
  *
738
- * @param {string|number} key - Property key to retrieve
739
- * @returns {*} The value of the property, unwrapped if it's an observable
740
- * @example
741
- * const user = Observable({ name: 'John', age: Observable(25) });
742
- * user.get('name'); // 'John'
743
- * user.get('age'); // 25 (unwrapped from observable)
1723
+ * @param {ObservableItem} observer - The observable to watch
1724
+ * @param {*} value - The value to compare against
1725
+ * @class ObservableWhen
744
1726
  */
745
- ObservableItem.prototype.get = function(key) {
746
- const item = this.$currentValue[key];
747
- return Validator.isObservable(item) ? item.val() : item;
1727
+ const ObservableWhen = function(observer, value) {
1728
+ this.$target = value;
1729
+ this.$observer = observer;
748
1730
  };
749
1731
 
1732
+ ObservableWhen.prototype.__$Observable = true;
1733
+ ObservableWhen.prototype.__$isObservableWhen = true;
750
1734
 
751
1735
  /**
752
- * Compares the observable's current value with another value or observable.
1736
+ * Subscribes to changes in the match status (true when observable equals target value).
753
1737
  *
754
- * @param {*|ObservableItem} other - Value or observable to compare against
755
- * @returns {boolean} True if values are equal
1738
+ * @param {Function} callback - Function called with boolean indicating if values match
1739
+ * @returns {Function} Unsubscribe function
756
1740
  * @example
757
- * const a = Observable(5);
758
- * const b = Observable(5);
759
- * a.equals(5); // true
760
- * a.equals(b); // true
761
- * a.equals(10); // false
1741
+ * const status = Observable('idle');
1742
+ * const isLoading = status.when('loading');
1743
+ * isLoading.subscribe(active => console.log('Loading:', active));
762
1744
  */
763
- ObservableItem.prototype.equals = function(other) {
764
- if(Validator.isObservable(other)) {
765
- return this.$currentValue === other.$currentValue;
766
- }
767
- return this.$currentValue === other;
1745
+ ObservableWhen.prototype.subscribe = function(callback) {
1746
+ return this.$observer.on(this.$target, callback);
768
1747
  };
769
1748
 
770
1749
  /**
771
- * Converts the observable's current value to a boolean.
1750
+ * Returns true if the observable's current value equals the target value.
772
1751
  *
773
- * @returns {boolean} The boolean representation of the current value
774
- * @example
775
- * const count = Observable(0);
776
- * count.toBool(); // false
777
- * count.set(5);
778
- * count.toBool(); // true
1752
+ * @returns {boolean} True if observable value matches target value
779
1753
  */
780
- ObservableItem.prototype.toBool = function() {
781
- return !!this.$currentValue;
1754
+ ObservableWhen.prototype.val = function() {
1755
+ return this.$observer.$currentValue === this.$target;
782
1756
  };
783
1757
 
784
1758
  /**
785
- * Toggles the boolean value of the observable (false becomes true, true becomes false).
1759
+ * Returns true if the observable's current value equals the target value.
1760
+ * Alias for val().
786
1761
  *
787
- * @example
788
- * const isOpen = Observable(false);
789
- * isOpen.toggle(); // Now true
790
- * isOpen.toggle(); // Now false
1762
+ * @returns {boolean} True if observable value matches target value
791
1763
  */
792
- ObservableItem.prototype.toggle = function() {
793
- this.set(!this.$currentValue);
794
- };
1764
+ ObservableWhen.prototype.isMatch = ObservableWhen.prototype.val;
795
1765
 
796
1766
  /**
797
- * Resets the observable to its initial value.
798
- * Only works if the observable was created with { reset: true } config.
1767
+ * Returns true if the observable's current value equals the target value.
1768
+ * Alias for val().
799
1769
  *
800
- * @example
801
- * const count = Observable(0, { reset: true });
802
- * count.set(10);
803
- * count.reset(); // Back to 0
1770
+ * @returns {boolean} True if observable value matches target value
804
1771
  */
805
- ObservableItem.prototype.reset = function() {
806
- if(!this.configs?.reset) {
807
- return;
808
- }
809
- const resetValue = (Validator.isObject(this.$initialValue))
810
- ? deepClone(this.$initialValue, (observable) => {
811
- observable.reset();
812
- })
813
- : this.$initialValue;
814
- this.set(resetValue);
815
- };
1772
+ ObservableWhen.prototype.isActive = ObservableWhen.prototype.val;
816
1773
 
817
1774
  /**
818
- * Returns a string representation of the observable's current value.
819
1775
  *
820
- * @returns {string} String representation of the current value
1776
+ * @param {ObservableItem} $observable
1777
+ * @param {Function} $checker
1778
+ * @class ObservableChecker
821
1779
  */
822
- ObservableItem.prototype.toString = function() {
823
- return String(this.$currentValue);
1780
+ function ObservableChecker($observable, $checker) {
1781
+ this.observable = $observable;
1782
+
1783
+ ObservableItem.call(this);
1784
+
1785
+ this.$mutation = $checker;
1786
+
1787
+ $observable.subscribe((newValue) => {
1788
+ this.$updateWithMutation(newValue);
1789
+ });
1790
+
1791
+ this.$updateWithMutation($observable.val());
1792
+ }
1793
+
1794
+ ObservableChecker.prototype = Object.create(ObservableItem.prototype);
1795
+ ObservableChecker.prototype.constructor = ObservableChecker;
1796
+ ObservableChecker.prototype.__$Observable = true;
1797
+ ObservableChecker.prototype.__$isObservableChecker = true;
1798
+
1799
+
1800
+ const ObservablePipe = ObservableChecker;
1801
+ ObservablePipe.prototype.constructor = ObservablePipe;
1802
+
1803
+ ObservableChecker.prototype.$updateWithMutation = function(newValue) {
1804
+ newValue = this.$mutation(newValue);
1805
+ return this.set(newValue);
1806
+ };
1807
+
1808
+ const $parseDateParts = (value, locale) => {
1809
+ const d = new Date(value);
1810
+ return {
1811
+ d,
1812
+ parts: new Intl.DateTimeFormat(locale, {
1813
+ year: 'numeric',
1814
+ month: 'long',
1815
+ day: '2-digit',
1816
+ hour: '2-digit',
1817
+ minute: '2-digit',
1818
+ second: '2-digit',
1819
+ }).formatToParts(d).reduce((acc, { type, value }) => {
1820
+ acc[type] = value;
1821
+ return acc;
1822
+ }, {})
1823
+ };
1824
+ };
1825
+
1826
+ const $applyDatePattern = (pattern, d, parts) => {
1827
+ const pad = n => String(n).padStart(2, '0');
1828
+ return pattern
1829
+ .replace('YYYY', parts.year)
1830
+ .replace('YY', parts.year.slice(-2))
1831
+ .replace('MMMM', parts.month)
1832
+ .replace('MMM', parts.month.slice(0, 3))
1833
+ .replace('MM', pad(d.getMonth() + 1))
1834
+ .replace('DD', pad(d.getDate()))
1835
+ .replace('D', d.getDate())
1836
+ .replace('HH', parts.hour)
1837
+ .replace('mm', parts.minute)
1838
+ .replace('ss', parts.second);
1839
+ };
1840
+
1841
+ const Formatters = {
1842
+ currency: (value, locale, { currency = 'XOF', notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
1843
+ new Intl.NumberFormat(locale, {
1844
+ style: 'currency',
1845
+ currency,
1846
+ notation,
1847
+ minimumFractionDigits,
1848
+ maximumFractionDigits
1849
+ }).format(value),
1850
+
1851
+ number: (value, locale, { notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
1852
+ new Intl.NumberFormat(locale, {
1853
+ notation,
1854
+ minimumFractionDigits,
1855
+ maximumFractionDigits
1856
+ }).format(value),
1857
+
1858
+ percent: (value, locale, { decimals = 1 } = {}) =>
1859
+ new Intl.NumberFormat(locale, {
1860
+ style: 'percent',
1861
+ maximumFractionDigits: decimals
1862
+ }).format(value),
1863
+
1864
+ date: (value, locale, { format, dateStyle = 'long' } = {}) => {
1865
+ if (format) {
1866
+ const { d, parts } = $parseDateParts(value, locale);
1867
+ return $applyDatePattern(format, d, parts);
1868
+ }
1869
+ return new Intl.DateTimeFormat(locale, { dateStyle }).format(new Date(value));
1870
+ },
1871
+
1872
+ time: (value, locale, { format, hour = '2-digit', minute = '2-digit', second } = {}) => {
1873
+ if (format) {
1874
+ const { d, parts } = $parseDateParts(value, locale);
1875
+ return $applyDatePattern(format, d, parts);
1876
+ }
1877
+ return new Intl.DateTimeFormat(locale, { hour, minute, second }).format(new Date(value));
1878
+ },
1879
+
1880
+ datetime: (value, locale, { format, dateStyle = 'long', hour = '2-digit', minute = '2-digit', second } = {}) => {
1881
+ if (format) {
1882
+ const { d, parts } = $parseDateParts(value, locale);
1883
+ return $applyDatePattern(format, d, parts);
1884
+ }
1885
+ return new Intl.DateTimeFormat(locale, { dateStyle, hour, minute, second }).format(new Date(value));
1886
+ },
1887
+
1888
+ relative: (value, locale, { unit = 'day', numeric = 'auto' } = {}) => {
1889
+ const diff = Math.round((value - Date.now()) / (1000 * 60 * 60 * 24));
1890
+ return new Intl.RelativeTimeFormat(locale, { numeric }).format(diff, unit);
1891
+ },
1892
+
1893
+ plural: (value, locale, { singular, plural } = {}) => {
1894
+ const rule = new Intl.PluralRules(locale).select(value);
1895
+ return `${value} ${rule === 'one' ? singular : plural}`;
1896
+ },
824
1897
  };
825
1898
 
826
1899
  /**
827
- * Returns the primitive value of the observable (its current value).
828
- * Called automatically in type coercion contexts.
1900
+ * Creates an ObservableWhen that represents whether the observable equals a specific value.
1901
+ * Returns an object that can be subscribed to and will emit true/false.
829
1902
  *
830
- * @returns {*} The current value of the observable
1903
+ * @param {*} value - The value to compare against
1904
+ * @returns {ObservableWhen} An ObservableWhen instance that tracks when the observable equals the value
1905
+ * @example
1906
+ * const status = Observable('idle');
1907
+ * const isLoading = status.when('loading');
1908
+ * isLoading.subscribe(active => console.log('Loading:', active));
1909
+ * status.set('loading'); // Logs: "Loading: true"
831
1910
  */
832
- ObservableItem.prototype.valueOf = function() {
833
- return this.$currentValue;
1911
+
1912
+ ObservableItem.prototype.when = function(value) {
1913
+ return new ObservableWhen(this, value);
834
1914
  };
835
1915
 
836
1916
 
837
1917
 
838
- ObservableItem.prototype.persist = function(key, options = {}) {
839
- let value = $getFromStorage(key, this.$currentValue);
840
- if(options.get) {
841
- value = options.get(value);
1918
+ /**
1919
+ * Create an Observable checker instance
1920
+ * @param callback
1921
+ * @returns {ObservableChecker}
1922
+ */
1923
+ ObservableItem.prototype.check = function(callback) {
1924
+ return new ObservableChecker(this, callback)
1925
+ };
1926
+
1927
+ ObservableItem.prototype.transform = ObservableItem.prototype.check;
1928
+ ObservableItem.prototype.pluck = function(property) {
1929
+ return new ObservableChecker(this, (value) => value[property]);
1930
+ };
1931
+ ObservableItem.prototype.is = function(callbackOrValue) {
1932
+ if(typeof callbackOrValue === 'function') {
1933
+ return new ObservableChecker(this, callbackOrValue);
842
1934
  }
843
- this.set(value);
844
- const saver = $saveToStorage(this.$currentValue);
845
- this.subscribe((newValue) => {
846
- saver(key, options.set ? options.set(newValue) : newValue);
847
- });
848
- return this;
1935
+ return new ObservableChecker(this, (value) => value === callbackOrValue);
849
1936
  };
1937
+ ObservableItem.prototype.select = ObservableItem.prototype.check;
850
1938
 
851
- ObservableItem.prototype.clone = function() {
852
- let clonedValue = this.$currentValue;
1939
+ /**
1940
+ * Creates a derived observable that formats the current value using Intl.
1941
+ * Automatically reacts to both value changes and locale changes (Store.__nd.locale).
1942
+ *
1943
+ * @param {string | Function} type - Format type or custom formatter function
1944
+ * @param {Object} [options={}] - Options passed to the formatter
1945
+ * @returns {ObservableItem<string>}
1946
+ *
1947
+ * @example
1948
+ * // Currency
1949
+ * price.format('currency') // "15 000 FCFA"
1950
+ * price.format('currency', { currency: 'EUR' }) // "15 000,00 €"
1951
+ * price.format('currency', { notation: 'compact' }) // "15 K FCFA"
1952
+ *
1953
+ * // Number
1954
+ * count.format('number') // "15 000"
1955
+ *
1956
+ * // Percent
1957
+ * rate.format('percent') // "15,0 %"
1958
+ * rate.format('percent', { decimals: 2 }) // "15,00 %"
1959
+ *
1960
+ * // Date
1961
+ * date.format('date') // "3 mars 2026"
1962
+ * date.format('date', { dateStyle: 'full' }) // "mardi 3 mars 2026"
1963
+ * date.format('date', { format: 'DD/MM/YYYY' }) // "03/03/2026"
1964
+ * date.format('date', { format: 'DD MMM YYYY' }) // "03 mar 2026"
1965
+ * date.format('date', { format: 'DD MMMM YYYY' }) // "03 mars 2026"
1966
+ *
1967
+ * // Time
1968
+ * date.format('time') // "20:30"
1969
+ * date.format('time', { second: '2-digit' }) // "20:30:00"
1970
+ * date.format('time', { format: 'HH:mm:ss' }) // "20:30:00"
1971
+ *
1972
+ * // Datetime
1973
+ * date.format('datetime') // "3 mars 2026, 20:30"
1974
+ * date.format('datetime', { dateStyle: 'full' }) // "mardi 3 mars 2026, 20:30"
1975
+ * date.format('datetime', { format: 'DD/MM/YYYY HH:mm' }) // "03/03/2026 20:30"
1976
+ *
1977
+ * // Relative
1978
+ * date.format('relative') // "dans 11 jours"
1979
+ * date.format('relative', { unit: 'month' }) // "dans 1 mois"
1980
+ *
1981
+ * // Plural
1982
+ * count.format('plural', { singular: 'billet', plural: 'billets' }) // "3 billets"
1983
+ *
1984
+ * // Custom formatter
1985
+ * price.format(value => `${value.toLocaleString()} FCFA`)
1986
+ *
1987
+ * // Reacts to locale changes automatically
1988
+ * Store.setLocale('en-US');
1989
+ */
1990
+ ObservableItem.prototype.format = function(type, options = {}) {
1991
+ const self = this;
853
1992
 
854
- if(clonedValue && typeof clonedValue === 'object') {
855
- if(typeof clonedValue.clone === 'function') {
856
- clonedValue = clonedValue.clone();
857
- } else {
858
- clonedValue = structuredClone(clonedValue);
859
- }
1993
+ if (typeof type === 'function') {
1994
+ return new ObservableChecker(self, type);
860
1995
  }
861
1996
 
862
- return new ObservableItem(clonedValue);
1997
+ const formatter = Formatters[type];
1998
+ const localeObservable = Formatters.locale;
1999
+
2000
+ return ObservableItem.computed(() => formatter(self.val(), localeObservable.val(), options),
2001
+ [self, localeObservable]
2002
+ );
863
2003
  };
864
2004
 
865
2005
  /**
@@ -931,6 +2071,138 @@ var NativeComponents = (function (exports) {
931
2071
  setInterval(() => MemoryManager.cleanObservables(threshold), interval);
932
2072
  };
933
2073
 
2074
+
2075
+ /**
2076
+ * Creates an observable array with reactive array methods.
2077
+ * All mutations trigger updates automatically.
2078
+ *
2079
+ * @param {Array} [target=[]] - Initial array value
2080
+ * @param {Object|null} [configs=null] - Configuration options
2081
+ * // @param {boolean} [configs.propagation=true] - Whether to propagate changes to parent observables
2082
+ * // @param {boolean} [configs.deep=false] - Whether to make nested objects observable
2083
+ * @param {boolean} [configs.reset=false] - Whether to store initial value for reset()
2084
+ * @returns {ObservableArray} An observable array with reactive methods
2085
+ * @example
2086
+ * const items = Observable.array([1, 2, 3]);
2087
+ * items.push(4); // Triggers update
2088
+ * items.subscribe((arr) => console.log(arr));
2089
+ */
2090
+ Observable.array = function(target = [], configs = null) {
2091
+ return new ObservableArray(target, configs);
2092
+ };
2093
+
2094
+ /**
2095
+ *
2096
+ * @param {Function} callback
2097
+ * @returns {Function}
2098
+ */
2099
+ Observable.batch = function(callback) {
2100
+ const $observer = Observable(0);
2101
+ const batch = function() {
2102
+ if(Validator$1.isAsyncFunction(callback)) {
2103
+ return (callback(...arguments)).then(() => {
2104
+ $observer.trigger();
2105
+ }).catch(error => { throw error; });
2106
+ }
2107
+ callback(...arguments);
2108
+ $observer.trigger();
2109
+ };
2110
+ batch.$observer = $observer;
2111
+ return batch;
2112
+ };
2113
+
2114
+
2115
+ /**
2116
+ * Creates a computed observable that automatically updates when its dependencies change.
2117
+ * The callback is re-executed whenever any dependency observable changes.
2118
+ *
2119
+ * @param {Function} callback - Function that returns the computed value
2120
+ * @param {Array<ObservableItem|ObservableChecker|ObservableProxy>|Function} [dependencies=[]] - Array of observables to watch, or batch function
2121
+ * @returns {ObservableItem} A new observable that updates automatically
2122
+ * @example
2123
+ * const firstName = Observable('John');
2124
+ * const lastName = Observable('Doe');
2125
+ * const fullName = Observable.computed(
2126
+ * () => `${firstName.val()} ${lastName.val()}`,
2127
+ * [firstName, lastName]
2128
+ * );
2129
+ *
2130
+ * // With batch function
2131
+ * const batch = Observable.batch(() => { ... });
2132
+ * const computed = Observable.computed(() => { ... }, batch);
2133
+ */
2134
+ Observable.computed = function(callback, dependencies = []) {
2135
+ const initialValue = callback();
2136
+ const observable = new ObservableItem(initialValue);
2137
+ const getValues = () => dependencies.map((item) => item.val());
2138
+ const updatedValue = nextTick(() => observable.set(callback(...getValues())));
2139
+
2140
+ if(Validator$1.isFunction(dependencies)) {
2141
+ if(!Validator$1.isObservable(dependencies.$observer)) {
2142
+ throw new NativeDocumentError('Observable.computed : dependencies must be valid batch function');
2143
+ }
2144
+ dependencies.$observer.subscribe(updatedValue);
2145
+ return observable;
2146
+ }
2147
+
2148
+ dependencies.forEach(dependency => {
2149
+ if(Validator$1.isProxy(dependency)) {
2150
+ dependency.$observables.forEach((observable) => {
2151
+ observable.subscribe(updatedValue);
2152
+ });
2153
+ return;
2154
+ }
2155
+ dependency.subscribe(updatedValue);
2156
+ });
2157
+
2158
+ return observable;
2159
+ };
2160
+ ObservableItem.computed = Observable.computed;
2161
+
2162
+
2163
+ Observable.init = function(initialValue, configs = null) {
2164
+ return new ObservableObject(initialValue, configs)
2165
+ };
2166
+
2167
+ /**
2168
+ *
2169
+ * @param {any[]} data
2170
+ * @return Proxy[]
2171
+ */
2172
+ Observable.arrayOfObject = function(data) {
2173
+ return data.map(item => Observable.object(item));
2174
+ };
2175
+
2176
+ /**
2177
+ * Get the value of an observable or an object of observables.
2178
+ * @param {ObservableItem|Object<ObservableItem>} data
2179
+ * @returns {{}|*|null}
2180
+ */
2181
+ Observable.value = function(data) {
2182
+ if(data?.__$isObservableArray) {
2183
+ const result = [];
2184
+ for(let i = 0, length = data.length; i < length; i++) {
2185
+ const item = data.at(i);
2186
+ result.push(Observable.value(item));
2187
+ }
2188
+ return result;
2189
+ }
2190
+ if(data?.__$Observable) {
2191
+ return data.val();
2192
+ }
2193
+ if(Validator$1.isProxy(data)) {
2194
+ return data.$value;
2195
+ }
2196
+ return data;
2197
+ };
2198
+
2199
+ ObservableItem.prototype.resolve = function () {
2200
+ return Observable.value(this);
2201
+ };
2202
+
2203
+ Observable.object = Observable.init;
2204
+ Observable.json = Observable.init;
2205
+
934
2206
  const BOOLEAN_ATTRIBUTES = new Set([
935
2207
  'checked',
936
2208
  'selected',
@@ -1048,7 +2320,7 @@ var NativeComponents = (function (exports) {
1048
2320
  const bindBooleanAttribute = (element, attributeName, value) => {
1049
2321
  const isObservable = value.__$isObservable;
1050
2322
  const defaultValue = isObservable? value.val() : value;
1051
- if(Validator.isBoolean(defaultValue)) {
2323
+ if(Validator$1.isBoolean(defaultValue)) {
1052
2324
  element[attributeName] = defaultValue;
1053
2325
  }
1054
2326
  else {
@@ -1212,7 +2484,7 @@ var NativeComponents = (function (exports) {
1212
2484
  if(child.toNdElement) {
1213
2485
  do {
1214
2486
  child = child.toNdElement();
1215
- if(Validator.isElement(child)) {
2487
+ if(Validator$1.isElement(child)) {
1216
2488
  return child;
1217
2489
  }
1218
2490
  } while (child.toNdElement);
@@ -1291,7 +2563,7 @@ var NativeComponents = (function (exports) {
1291
2563
  anchor.getParent = () => parent;
1292
2564
 
1293
2565
  anchor.appendChild = (child) => {
1294
- child = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2566
+ child = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1295
2567
  parent.appendChild(child);
1296
2568
  };
1297
2569
 
@@ -1300,7 +2572,7 @@ var NativeComponents = (function (exports) {
1300
2572
  anchor.appendRaw = anchor.appendChildRaw;
1301
2573
 
1302
2574
  anchor.insertAtStart = (child) => {
1303
- child = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2575
+ child = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1304
2576
  parent.firstChild ? parent.insertBefore(child, parent.firstChild) : parent.appendChild(child);
1305
2577
  };
1306
2578
  anchor.insertAtStartRaw = (child) => {
@@ -1314,7 +2586,7 @@ var NativeComponents = (function (exports) {
1314
2586
  };
1315
2587
 
1316
2588
  anchor.replaceContent = function(content) {
1317
- const child = Validator.isElement(content) ? content : ElementCreator.getChild(content);
2589
+ const child = Validator$1.isElement(content) ? content : ElementCreator.getChild(content);
1318
2590
  parent.replaceChildren(child);
1319
2591
  };
1320
2592
 
@@ -1324,7 +2596,7 @@ var NativeComponents = (function (exports) {
1324
2596
  anchor.setContent = anchor.replaceContent;
1325
2597
 
1326
2598
  anchor.insertBefore = (child, anchor) => {
1327
- child = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2599
+ child = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1328
2600
  parent.insertBefore(child, anchor);
1329
2601
  };
1330
2602
  anchor.insertBeforeRaw = (child, anchor) => {
@@ -1368,7 +2640,7 @@ var NativeComponents = (function (exports) {
1368
2640
  ? () => true: (parent) => (parent.firstChild === anchorStart && parent.lastChild === anchorEnd);
1369
2641
 
1370
2642
  const insertBefore = (parent, child, target) => {
1371
- const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2643
+ const childElement = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1372
2644
  insertBeforeRaw(parent, childElement, target);
1373
2645
  };
1374
2646
 
@@ -1418,7 +2690,7 @@ var NativeComponents = (function (exports) {
1418
2690
  anchorFragment.appendRaw = anchorFragment.appendChildRaw;
1419
2691
 
1420
2692
  anchorFragment.insertAtStart = function(child) {
1421
- child = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2693
+ child = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1422
2694
  anchorFragment.insertAtStartRaw(child);
1423
2695
  };
1424
2696
 
@@ -1475,7 +2747,7 @@ var NativeComponents = (function (exports) {
1475
2747
  anchorFragment.delete = anchorFragment.removeWithAnchors;
1476
2748
 
1477
2749
  anchorFragment.replaceContent = function(child) {
1478
- const childElement = Validator.isElement(child) ? child : ElementCreator.getChild(child);
2750
+ const childElement = Validator$1.isElement(child) ? child : ElementCreator.getChild(child);
1479
2751
  anchorFragment.replaceContentRaw(childElement);
1480
2752
  };
1481
2753
 
@@ -1543,7 +2815,7 @@ var NativeComponents = (function (exports) {
1543
2815
  * ShowIf(isVisible, Div({}, 'Hello World'));
1544
2816
  */
1545
2817
  const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
1546
- if(!Validator.isObservable(condition)) {
2818
+ if(!Validator$1.isObservable(condition)) {
1547
2819
  if(typeof condition === "boolean") {
1548
2820
  return condition ? ElementCreator.getChild(child) : null;
1549
2821
  }
@@ -1558,7 +2830,7 @@ var NativeComponents = (function (exports) {
1558
2830
  return childElement;
1559
2831
  }
1560
2832
  childElement = ElementCreator.getChild(child);
1561
- if(Validator.isFragment(childElement)) {
2833
+ if(Validator$1.isFragment(childElement)) {
1562
2834
  childElement = Array.from(childElement.childNodes);
1563
2835
  }
1564
2836
  return childElement;
@@ -5813,7 +7085,7 @@ var NativeComponents = (function (exports) {
5813
7085
  }
5814
7086
  else if (typeof condition === 'function') {
5815
7087
  isRequired = condition(allValues);
5816
- } else if (Validator.isObservable(condition)) {
7088
+ } else if (Validator$1.isObservable(condition)) {
5817
7089
  isRequired = condition.val();
5818
7090
  } else {
5819
7091
  isRequired = !!condition;
@@ -6006,7 +7278,7 @@ var NativeComponents = (function (exports) {
6006
7278
 
6007
7279
  Field.prototype.model = function(observable) {
6008
7280
  this.$description.value = observable;
6009
- this.$description.initialValue = Validator.isObservable(observable)
7281
+ this.$description.initialValue = Validator$1.isObservable(observable)
6010
7282
  ? observable.val()
6011
7283
  : observable;
6012
7284
  return this;
@@ -6015,7 +7287,7 @@ var NativeComponents = (function (exports) {
6015
7287
  Field.prototype.bind = Field.prototype.model;
6016
7288
 
6017
7289
  Field.prototype.errors = function(errors) {
6018
- if(!Validator.isObservable(errors)) {
7290
+ if(!Validator$1.isObservable(errors)) {
6019
7291
  throw new Error('Errors must be an observable');
6020
7292
  }
6021
7293
  this.$description.errors = errors;
@@ -6064,12 +7336,12 @@ var NativeComponents = (function (exports) {
6064
7336
 
6065
7337
  Field.prototype.value = function() {
6066
7338
  const value = this.$model();
6067
- return Validator.isObservable(value) ? value.val() : value;
7339
+ return Validator$1.isObservable(value) ? value.val() : value;
6068
7340
  };
6069
7341
 
6070
7342
  Field.prototype.setValue = function(newValue) {
6071
7343
  const value = this.$model();
6072
- if(Validator.isObservable(value)) {
7344
+ if(Validator$1.isObservable(value)) {
6073
7345
  value.set(newValue);
6074
7346
  return this;
6075
7347
  }
@@ -6139,7 +7411,7 @@ var NativeComponents = (function (exports) {
6139
7411
 
6140
7412
  Field.prototype.reset = function() {
6141
7413
  const value = this.$model();
6142
- if(Validator.isObservable(value)) {
7414
+ if(Validator$1.isObservable(value)) {
6143
7415
  value.set(this.$description.initialValue ?? this.$description.defaultValue ?? null);
6144
7416
  }
6145
7417
 
@@ -6241,7 +7513,7 @@ var NativeComponents = (function (exports) {
6241
7513
  return;
6242
7514
  }
6243
7515
 
6244
- if(Validator.isObservable(dataSource)) {
7516
+ if(Validator$1.isObservable(dataSource)) {
6245
7517
  field.model(dataSource);
6246
7518
  return;
6247
7519
  }
@@ -6899,7 +8171,7 @@ var NativeComponents = (function (exports) {
6899
8171
 
6900
8172
  CheckboxField.prototype.checked = function() {
6901
8173
  const checked = this.$description.checked;
6902
- if(Validator.isObservable(checked)) {
8174
+ if(Validator$1.isObservable(checked)) {
6903
8175
  return checked.val();
6904
8176
  }
6905
8177
  return checked;
@@ -6945,7 +8217,7 @@ var NativeComponents = (function (exports) {
6945
8217
 
6946
8218
  RadioField.prototype.checked = function() {
6947
8219
  const checked = this.$description.checked;
6948
- if(Validator.isObservable(checked)) {
8220
+ if(Validator$1.isObservable(checked)) {
6949
8221
  return checked.val();
6950
8222
  }
6951
8223
  return checked;
@@ -8030,7 +9302,7 @@ var NativeComponents = (function (exports) {
8030
9302
  };
8031
9303
 
8032
9304
  this.$description.value.interceptMutations((items) =>
8033
- items.map(item => Validator.isObservable(item) ? item : $$1.object(item))
9305
+ items.map(item => Validator$1.isObservable(item) ? item : $$1.object(item))
8034
9306
  );
8035
9307
  }
8036
9308
 
@@ -8076,10 +9348,10 @@ var NativeComponents = (function (exports) {
8076
9348
  };
8077
9349
 
8078
9350
  FieldCollection.prototype.model = function(observable) {
8079
- if(Validator.isObservable(observable)) {
9351
+ if(Validator$1.isObservable(observable)) {
8080
9352
  this.$description.value = observable;
8081
9353
  this.$description.value.interceptMutations((items) =>
8082
- items.map(item => Validator.isObservable(item) ? item : $$1.object(item))
9354
+ items.map(item => Validator$1.isObservable(item) ? item : $$1.object(item))
8083
9355
  );
8084
9356
  return this;
8085
9357
  }
@@ -8094,7 +9366,7 @@ var NativeComponents = (function (exports) {
8094
9366
  const raw = this.$description.defaultItem
8095
9367
  ? this.$description.defaultItem()
8096
9368
  : {};
8097
- const item = Validator.isObservable(raw) ? raw : $$1.object(raw);
9369
+ const item = Validator$1.isObservable(raw) ? raw : $$1.object(raw);
8098
9370
 
8099
9371
  this.$description.value.push(item);
8100
9372
  this.emit('add', item);
@@ -8119,7 +9391,7 @@ var NativeComponents = (function (exports) {
8119
9391
 
8120
9392
  FieldCollection.prototype.value = function() {
8121
9393
  return this.$description.value.map(item =>
8122
- Validator.isObservable(item) ? item.val() : item
9394
+ Validator$1.isObservable(item) ? item.val() : item
8123
9395
  );
8124
9396
  };
8125
9397
 
@@ -8642,7 +9914,7 @@ var NativeComponents = (function (exports) {
8642
9914
 
8643
9915
  ListItem.prototype.selectable = function() {
8644
9916
  this.$description.selectable = true;
8645
- if(Validator.isObservable(this.$description.selected)) {
9917
+ if(Validator$1.isObservable(this.$description.selected)) {
8646
9918
  return this;
8647
9919
  }
8648
9920
  this.$description.selected = $(false);
@@ -8650,7 +9922,7 @@ var NativeComponents = (function (exports) {
8650
9922
  };
8651
9923
 
8652
9924
  ListItem.prototype.selected = function(selected = true) {
8653
- if(Validator.isObservable(this.$description.selected)) {
9925
+ if(Validator$1.isObservable(this.$description.selected)) {
8654
9926
  this.$description.selected.set(selected);
8655
9927
  return this;
8656
9928
  }
@@ -11471,7 +12743,7 @@ var NativeComponents = (function (exports) {
11471
12743
  };
11472
12744
 
11473
12745
  Splitter.prototype.panels = function(panels) {
11474
- if(Validator.isObservable(this.$description.panels)) {
12746
+ if(Validator$1.isObservable(this.$description.panels)) {
11475
12747
  this.$description.panels.clear();
11476
12748
  } else {
11477
12749
  this.$description.panels = [];
@@ -12274,40 +13546,6 @@ var NativeComponents = (function (exports) {
12274
13546
  return this;
12275
13547
  };
12276
13548
 
12277
- /**
12278
- *
12279
- * @param {ObservableItem} $observable
12280
- * @param {Function} $checker
12281
- * @class ObservableChecker
12282
- */
12283
- function ObservableChecker($observable, $checker) {
12284
- this.observable = $observable;
12285
-
12286
- ObservableItem.call(this);
12287
-
12288
- this.$mutation = $checker;
12289
-
12290
- $observable.subscribe((newValue) => {
12291
- this.$updateWithMutation(newValue);
12292
- });
12293
-
12294
- this.$updateWithMutation($observable.val());
12295
- }
12296
-
12297
- ObservableChecker.prototype = Object.create(ObservableItem.prototype);
12298
- ObservableChecker.prototype.constructor = ObservableChecker;
12299
- ObservableChecker.prototype.__$Observable = true;
12300
- ObservableChecker.prototype.__$isObservableChecker = true;
12301
-
12302
-
12303
- const ObservablePipe = ObservableChecker;
12304
- ObservablePipe.prototype.constructor = ObservablePipe;
12305
-
12306
- ObservableChecker.prototype.$updateWithMutation = function(newValue) {
12307
- newValue = this.$mutation(newValue);
12308
- return this.set(newValue);
12309
- };
12310
-
12311
13549
  NDElement.$getChild = ElementCreator.getChild;
12312
13550
 
12313
13551
  String.prototype.toNdElement = function () {