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.
- package/cdn.js +0 -4
- package/dist/native-document.components.min.js +1410 -172
- package/dist/native-document.dev.js +3207 -2943
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.min.js +1 -1
- package/index.js +11 -7
- package/package.json +1 -1
- package/src/core/data/Observable.js +141 -0
- package/src/core/data/ObservableArray.js +1 -2
- package/src/core/data/ObservableItem.js +2 -0
- package/src/core/data/ObservableObject.js +10 -10
- package/src/core/data/observable-helpers/observable.is-to.js +1 -2
- package/src/core/data/observable-helpers/observable.prototypes.js +1 -2
- package/src/core/data/observable-helpers/array.js +0 -22
- package/src/core/data/observable-helpers/batch.js +0 -22
- package/src/core/data/observable-helpers/computed.js +0 -55
- package/src/core/data/observable-helpers/object.js +0 -48
|
@@ -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
|
-
|
|
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
|
-
*
|
|
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 {
|
|
739
|
-
* @
|
|
740
|
-
* @
|
|
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
|
-
|
|
746
|
-
|
|
747
|
-
|
|
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
|
-
*
|
|
1736
|
+
* Subscribes to changes in the match status (true when observable equals target value).
|
|
753
1737
|
*
|
|
754
|
-
* @param {
|
|
755
|
-
* @returns {
|
|
1738
|
+
* @param {Function} callback - Function called with boolean indicating if values match
|
|
1739
|
+
* @returns {Function} Unsubscribe function
|
|
756
1740
|
* @example
|
|
757
|
-
* const
|
|
758
|
-
* const
|
|
759
|
-
*
|
|
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
|
-
|
|
764
|
-
|
|
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
|
-
*
|
|
1750
|
+
* Returns true if the observable's current value equals the target value.
|
|
772
1751
|
*
|
|
773
|
-
* @returns {boolean}
|
|
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
|
-
|
|
781
|
-
return
|
|
1754
|
+
ObservableWhen.prototype.val = function() {
|
|
1755
|
+
return this.$observer.$currentValue === this.$target;
|
|
782
1756
|
};
|
|
783
1757
|
|
|
784
1758
|
/**
|
|
785
|
-
*
|
|
1759
|
+
* Returns true if the observable's current value equals the target value.
|
|
1760
|
+
* Alias for val().
|
|
786
1761
|
*
|
|
787
|
-
* @
|
|
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
|
-
|
|
793
|
-
this.set(!this.$currentValue);
|
|
794
|
-
};
|
|
1764
|
+
ObservableWhen.prototype.isMatch = ObservableWhen.prototype.val;
|
|
795
1765
|
|
|
796
1766
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
1767
|
+
* Returns true if the observable's current value equals the target value.
|
|
1768
|
+
* Alias for val().
|
|
799
1769
|
*
|
|
800
|
-
* @
|
|
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
|
-
|
|
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
|
-
* @
|
|
1776
|
+
* @param {ObservableItem} $observable
|
|
1777
|
+
* @param {Function} $checker
|
|
1778
|
+
* @class ObservableChecker
|
|
821
1779
|
*/
|
|
822
|
-
|
|
823
|
-
|
|
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
|
-
*
|
|
828
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
|
|
833
|
-
|
|
1911
|
+
|
|
1912
|
+
ObservableItem.prototype.when = function(value) {
|
|
1913
|
+
return new ObservableWhen(this, value);
|
|
834
1914
|
};
|
|
835
1915
|
|
|
836
1916
|
|
|
837
1917
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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
|
|
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
|
-
|
|
852
|
-
|
|
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(
|
|
855
|
-
|
|
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
|
-
|
|
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 () {
|