sygnal 2.6.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +231 -129
- package/dist/index.esm.js +231 -129
- package/dist/sygnal.min.js +1 -1
- package/package.json +4 -1
package/dist/index.cjs.js
CHANGED
|
@@ -351,6 +351,16 @@ var hasSymbols$2 = function hasNativeSymbols() {
|
|
|
351
351
|
return hasSymbolSham();
|
|
352
352
|
};
|
|
353
353
|
|
|
354
|
+
var test = {
|
|
355
|
+
foo: {}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
var $Object = Object;
|
|
359
|
+
|
|
360
|
+
var hasProto$1 = function hasProto() {
|
|
361
|
+
return { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);
|
|
362
|
+
};
|
|
363
|
+
|
|
354
364
|
/* eslint no-invalid-this: 1 */
|
|
355
365
|
|
|
356
366
|
var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
|
|
@@ -453,18 +463,23 @@ var ThrowTypeError = $gOPD
|
|
|
453
463
|
: throwTypeError;
|
|
454
464
|
|
|
455
465
|
var hasSymbols$1 = hasSymbols$2();
|
|
466
|
+
var hasProto = hasProto$1();
|
|
456
467
|
|
|
457
|
-
var getProto = Object.getPrototypeOf ||
|
|
468
|
+
var getProto = Object.getPrototypeOf || (
|
|
469
|
+
hasProto
|
|
470
|
+
? function (x) { return x.__proto__; } // eslint-disable-line no-proto
|
|
471
|
+
: null
|
|
472
|
+
);
|
|
458
473
|
|
|
459
474
|
var needsEval = {};
|
|
460
475
|
|
|
461
|
-
var TypedArray = typeof Uint8Array === 'undefined' ? undefined$1 : getProto(Uint8Array);
|
|
476
|
+
var TypedArray = typeof Uint8Array === 'undefined' || !getProto ? undefined$1 : getProto(Uint8Array);
|
|
462
477
|
|
|
463
478
|
var INTRINSICS = {
|
|
464
479
|
'%AggregateError%': typeof AggregateError === 'undefined' ? undefined$1 : AggregateError,
|
|
465
480
|
'%Array%': Array,
|
|
466
481
|
'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined$1 : ArrayBuffer,
|
|
467
|
-
'%ArrayIteratorPrototype%': hasSymbols$1 ? getProto([][Symbol.iterator]()) : undefined$1,
|
|
482
|
+
'%ArrayIteratorPrototype%': hasSymbols$1 && getProto ? getProto([][Symbol.iterator]()) : undefined$1,
|
|
468
483
|
'%AsyncFromSyncIteratorPrototype%': undefined$1,
|
|
469
484
|
'%AsyncFunction%': needsEval,
|
|
470
485
|
'%AsyncGenerator%': needsEval,
|
|
@@ -472,6 +487,8 @@ var INTRINSICS = {
|
|
|
472
487
|
'%AsyncIteratorPrototype%': needsEval,
|
|
473
488
|
'%Atomics%': typeof Atomics === 'undefined' ? undefined$1 : Atomics,
|
|
474
489
|
'%BigInt%': typeof BigInt === 'undefined' ? undefined$1 : BigInt,
|
|
490
|
+
'%BigInt64Array%': typeof BigInt64Array === 'undefined' ? undefined$1 : BigInt64Array,
|
|
491
|
+
'%BigUint64Array%': typeof BigUint64Array === 'undefined' ? undefined$1 : BigUint64Array,
|
|
475
492
|
'%Boolean%': Boolean,
|
|
476
493
|
'%DataView%': typeof DataView === 'undefined' ? undefined$1 : DataView,
|
|
477
494
|
'%Date%': Date,
|
|
@@ -492,10 +509,10 @@ var INTRINSICS = {
|
|
|
492
509
|
'%Int32Array%': typeof Int32Array === 'undefined' ? undefined$1 : Int32Array,
|
|
493
510
|
'%isFinite%': isFinite,
|
|
494
511
|
'%isNaN%': isNaN,
|
|
495
|
-
'%IteratorPrototype%': hasSymbols$1 ? getProto(getProto([][Symbol.iterator]())) : undefined$1,
|
|
512
|
+
'%IteratorPrototype%': hasSymbols$1 && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined$1,
|
|
496
513
|
'%JSON%': typeof JSON === 'object' ? JSON : undefined$1,
|
|
497
514
|
'%Map%': typeof Map === 'undefined' ? undefined$1 : Map,
|
|
498
|
-
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols$1 ? undefined$1 : getProto(new Map()[Symbol.iterator]()),
|
|
515
|
+
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols$1 || !getProto ? undefined$1 : getProto(new Map()[Symbol.iterator]()),
|
|
499
516
|
'%Math%': Math,
|
|
500
517
|
'%Number%': Number,
|
|
501
518
|
'%Object%': Object,
|
|
@@ -508,10 +525,10 @@ var INTRINSICS = {
|
|
|
508
525
|
'%Reflect%': typeof Reflect === 'undefined' ? undefined$1 : Reflect,
|
|
509
526
|
'%RegExp%': RegExp,
|
|
510
527
|
'%Set%': typeof Set === 'undefined' ? undefined$1 : Set,
|
|
511
|
-
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols$1 ? undefined$1 : getProto(new Set()[Symbol.iterator]()),
|
|
528
|
+
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols$1 || !getProto ? undefined$1 : getProto(new Set()[Symbol.iterator]()),
|
|
512
529
|
'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined$1 : SharedArrayBuffer,
|
|
513
530
|
'%String%': String,
|
|
514
|
-
'%StringIteratorPrototype%': hasSymbols$1 ? getProto(''[Symbol.iterator]()) : undefined$1,
|
|
531
|
+
'%StringIteratorPrototype%': hasSymbols$1 && getProto ? getProto(''[Symbol.iterator]()) : undefined$1,
|
|
515
532
|
'%Symbol%': hasSymbols$1 ? Symbol : undefined$1,
|
|
516
533
|
'%SyntaxError%': $SyntaxError,
|
|
517
534
|
'%ThrowTypeError%': ThrowTypeError,
|
|
@@ -527,6 +544,16 @@ var INTRINSICS = {
|
|
|
527
544
|
'%WeakSet%': typeof WeakSet === 'undefined' ? undefined$1 : WeakSet
|
|
528
545
|
};
|
|
529
546
|
|
|
547
|
+
if (getProto) {
|
|
548
|
+
try {
|
|
549
|
+
null.error; // eslint-disable-line no-unused-expressions
|
|
550
|
+
} catch (e) {
|
|
551
|
+
// https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
|
|
552
|
+
var errorProto = getProto(getProto(e));
|
|
553
|
+
INTRINSICS['%Error.prototype%'] = errorProto;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
530
557
|
var doEval = function doEval(name) {
|
|
531
558
|
var value;
|
|
532
559
|
if (name === '%AsyncFunction%') {
|
|
@@ -542,7 +569,7 @@ var doEval = function doEval(name) {
|
|
|
542
569
|
}
|
|
543
570
|
} else if (name === '%AsyncIteratorPrototype%') {
|
|
544
571
|
var gen = doEval('%AsyncGenerator%');
|
|
545
|
-
if (gen) {
|
|
572
|
+
if (gen && getProto) {
|
|
546
573
|
value = getProto(gen.prototype);
|
|
547
574
|
}
|
|
548
575
|
}
|
|
@@ -612,6 +639,7 @@ var $concat = bind.call(Function.call, Array.prototype.concat);
|
|
|
612
639
|
var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
|
|
613
640
|
var $replace = bind.call(Function.call, String.prototype.replace);
|
|
614
641
|
var $strSlice = bind.call(Function.call, String.prototype.slice);
|
|
642
|
+
var $exec = bind.call(Function.call, RegExp.prototype.exec);
|
|
615
643
|
|
|
616
644
|
/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */
|
|
617
645
|
var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
|
|
@@ -667,6 +695,9 @@ var getIntrinsic = function GetIntrinsic(name, allowMissing) {
|
|
|
667
695
|
throw new $TypeError('"allowMissing" argument must be a boolean');
|
|
668
696
|
}
|
|
669
697
|
|
|
698
|
+
if ($exec(/^%?[^%]*%?$/, name) === null) {
|
|
699
|
+
throw new $SyntaxError('`%` may not be present anywhere but at the beginning and end of the intrinsic name');
|
|
700
|
+
}
|
|
670
701
|
var parts = stringToPath(name);
|
|
671
702
|
var intrinsicBaseName = parts.length > 0 ? parts[0] : '';
|
|
672
703
|
|
|
@@ -787,8 +818,14 @@ var hasPropertyDescriptors = hasPropertyDescriptors_1();
|
|
|
787
818
|
var supportsDescriptors = origDefineProperty && hasPropertyDescriptors;
|
|
788
819
|
|
|
789
820
|
var defineProperty = function (object, name, value, predicate) {
|
|
790
|
-
if (name in object
|
|
791
|
-
|
|
821
|
+
if (name in object) {
|
|
822
|
+
if (predicate === true) {
|
|
823
|
+
if (object[name] === value) {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
} else if (!isFunction(predicate) || !predicate()) {
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
792
829
|
}
|
|
793
830
|
if (supportsDescriptors) {
|
|
794
831
|
origDefineProperty(object, name, {
|
|
@@ -3663,7 +3700,7 @@ class Component {
|
|
|
3663
3700
|
}
|
|
3664
3701
|
|
|
3665
3702
|
addCalculated(state) {
|
|
3666
|
-
if (!this.calculated || typeof state !== 'object') return state
|
|
3703
|
+
if (!this.calculated || typeof state !== 'object' || state instanceof Array) return state
|
|
3667
3704
|
if (typeof this.calculated !== 'object') throw new Error(`'calculated' parameter must be an object mapping calculated state field named to functions`)
|
|
3668
3705
|
const entries = Object.entries(this.calculated);
|
|
3669
3706
|
const calculated = entries.reduce((acc, [field, fn]) => {
|
|
@@ -3678,11 +3715,13 @@ class Component {
|
|
|
3678
3715
|
return { ...state, ...calculated }
|
|
3679
3716
|
}
|
|
3680
3717
|
|
|
3681
|
-
cleanupCalculated(
|
|
3682
|
-
if (
|
|
3683
|
-
|
|
3718
|
+
cleanupCalculated(incomingState) {
|
|
3719
|
+
if (!incomingState || typeof incomingState !== 'object' || incomingState instanceof Array) return incomingState
|
|
3720
|
+
const state = this.storeCalculatedInState ? this.addCalculated(incomingState) : incomingState;
|
|
3721
|
+
const { __props, __children, ...sanitized } = state;
|
|
3722
|
+
const copy = { ...sanitized };
|
|
3723
|
+
if (!this.calculated) return copy
|
|
3684
3724
|
const keys = Object.keys(this.calculated);
|
|
3685
|
-
const copy = { ...state };
|
|
3686
3725
|
keys.forEach(key => {
|
|
3687
3726
|
if (this.initialState && typeof this.initialState[key] !== 'undefined') {
|
|
3688
3727
|
copy[key] = this.initialState[key];
|
|
@@ -3704,11 +3743,11 @@ class Component {
|
|
|
3704
3743
|
renderParams[this.stateSourceName] = stateStream;
|
|
3705
3744
|
|
|
3706
3745
|
if (this.sources.props$) {
|
|
3707
|
-
renderParams.
|
|
3746
|
+
renderParams.__props = this.sources.props$;
|
|
3708
3747
|
}
|
|
3709
3748
|
|
|
3710
3749
|
if (this.sources.children$) {
|
|
3711
|
-
renderParams.
|
|
3750
|
+
renderParams.__children = this.sources.children$;
|
|
3712
3751
|
}
|
|
3713
3752
|
|
|
3714
3753
|
const names = [];
|
|
@@ -3774,17 +3813,9 @@ class Component {
|
|
|
3774
3813
|
instantiator = this.instantiateCustomComponent.bind(this);
|
|
3775
3814
|
}
|
|
3776
3815
|
|
|
3777
|
-
const
|
|
3778
|
-
|
|
3779
|
-
if (preventStateUpdates) {
|
|
3780
|
-
const originalStateSink = sink$[this.stateSourceName];
|
|
3781
|
-
sink$[this.stateSourceName] = originalStateSink.filter(state => {
|
|
3782
|
-
console.warn('State update attempt from component with inderect link to state: Components with state set through HTML properties/attributes cannot update application state directly');
|
|
3783
|
-
return false
|
|
3784
|
-
});
|
|
3785
|
-
}
|
|
3816
|
+
const sink$ = instantiator(el, props$, children$);
|
|
3786
3817
|
|
|
3787
|
-
sink$[this.DOMSourceName] = this.makeCoordinatedSubComponentDomSink(sink$[this.DOMSourceName]);
|
|
3818
|
+
sink$[this.DOMSourceName] = sink$[this.DOMSourceName] ? this.makeCoordinatedSubComponentDomSink(sink$[this.DOMSourceName]) : xs__default["default"].never();
|
|
3788
3819
|
|
|
3789
3820
|
acc[id] = { sink$, props$, children$ };
|
|
3790
3821
|
|
|
@@ -3827,115 +3858,160 @@ class Component {
|
|
|
3827
3858
|
const data = el.data;
|
|
3828
3859
|
const props = data.props || {};
|
|
3829
3860
|
el.children || [];
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3861
|
+
|
|
3862
|
+
const combined$ = xs__default["default"].combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
3863
|
+
.map(([state, __props, __children]) => {
|
|
3864
|
+
return typeof state === 'object' ? { ...this.addCalculated(state), __props, __children } : { value: state, __props, __children }
|
|
3865
|
+
});
|
|
3866
|
+
|
|
3867
|
+
const stateSource = new state.StateSource(combined$);
|
|
3868
|
+
const stateField = props.from;
|
|
3869
|
+
let lense;
|
|
3870
|
+
|
|
3871
|
+
const factory = typeof props.of === 'function' ? props.of : this.components[props.of];
|
|
3872
|
+
|
|
3873
|
+
const sanitizeItems = item => {
|
|
3874
|
+
if (typeof item === 'object') {
|
|
3875
|
+
const { __props, __children, ...sanitized } = item;
|
|
3876
|
+
return sanitized
|
|
3877
|
+
} else {
|
|
3878
|
+
return item
|
|
3879
|
+
}
|
|
3880
|
+
};
|
|
3881
|
+
|
|
3882
|
+
const fieldLense = {
|
|
3883
|
+
get: state => {
|
|
3884
|
+
const { __props, __children } = state;
|
|
3885
|
+
if (!Array.isArray(state[stateField])) return []
|
|
3886
|
+
return state[stateField].map(item => {
|
|
3887
|
+
return typeof item === 'object' ? { ...item, __props, __children } : { value: item, __props, __children }
|
|
3888
|
+
})
|
|
3889
|
+
},
|
|
3890
|
+
set: (oldState, newState) => {
|
|
3891
|
+
if (this.calculated && stateField in this.calculated) {
|
|
3892
|
+
console.warn(`Collection sub-component of ${ this.name } attempted to update state on a calculated field '${ stateField }': Update ignored`);
|
|
3893
|
+
return oldState
|
|
3894
|
+
}
|
|
3895
|
+
return { ...oldState, [stateField]: newState.map(sanitizeItems) }
|
|
3842
3896
|
}
|
|
3843
|
-
return arr
|
|
3844
3897
|
};
|
|
3845
3898
|
|
|
3846
|
-
if (
|
|
3899
|
+
if (stateField === undefined) {
|
|
3847
3900
|
lense = {
|
|
3848
3901
|
get: state => {
|
|
3849
|
-
if (!Array.
|
|
3850
|
-
console.warn(`Collection sub-component of ${ this.name } has no 'for' attribute and the parent state is not an array: Provide a 'for' attribute with either an array or the name of a state property containing an array`);
|
|
3851
|
-
return []
|
|
3852
|
-
}
|
|
3902
|
+
if (!(state instanceof Array) && state.value && state.value instanceof Array) return state.value
|
|
3853
3903
|
return state
|
|
3854
3904
|
},
|
|
3855
|
-
set: (oldState, newState) =>
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
field = props.for;
|
|
3859
|
-
lense = {
|
|
3860
|
-
get: stateGetter,
|
|
3861
|
-
set: (state, arr) => {
|
|
3862
|
-
if (this.calculated && field in this.calculated) {
|
|
3863
|
-
console.warn(`Collection sub-component of ${ this.name } attempted to update state on a calculated field '${ field }': Update ignored`);
|
|
3864
|
-
return state
|
|
3865
|
-
}
|
|
3866
|
-
return { ...state, [field]: arr }
|
|
3905
|
+
set: (oldState, newState) => {
|
|
3906
|
+
console.log('COLL SET', newState);
|
|
3907
|
+
return newState
|
|
3867
3908
|
}
|
|
3868
3909
|
};
|
|
3910
|
+
} else if (typeof stateField === 'string') {
|
|
3911
|
+
if (typeof this.currentState === 'object') {
|
|
3912
|
+
if(!(stateField in this.currentState)) {
|
|
3913
|
+
console.error(`Collection component in ${ this.name } is attempting to use non-existent state property '${ stateField }': To fix this error, specify a valid array property on the state. Attempting to use parent component state.`);
|
|
3914
|
+
lense = undefined;
|
|
3915
|
+
} else if (!Array.isArray(this.currentState[stateField])) {
|
|
3916
|
+
console.warn(`State property '${ stateField }' in collection comopnent of ${ this.name } is not an array: No components will be instantiated in the collection.`);
|
|
3917
|
+
lense = fieldLense;
|
|
3918
|
+
} else {
|
|
3919
|
+
lense = fieldLense;
|
|
3920
|
+
}
|
|
3921
|
+
} else {
|
|
3922
|
+
if (!Array.isArray(this.currentState[stateField])) {
|
|
3923
|
+
console.warn(`State property '${ stateField }' in collection comopnent of ${ this.name } is not an array: No components will be instantiated in the collection.`);
|
|
3924
|
+
lense = fieldLense;
|
|
3925
|
+
} else {
|
|
3926
|
+
lense = fieldLense;
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
} else if (typeof stateField === 'object') {
|
|
3930
|
+
if (typeof stateField.get !== 'function') {
|
|
3931
|
+
console.error(`Collection component in ${ this.name } has an invalid 'from' field: Expecting 'undefined', a string indicating an array property in the state, or an object with 'get' and 'set' functions for retrieving and setting child state from the current state. Attempting to use parent component state.`);
|
|
3932
|
+
lense = undefined;
|
|
3933
|
+
} else {
|
|
3934
|
+
lense = { get: stateField.get, set: stateField.set };
|
|
3935
|
+
}
|
|
3869
3936
|
} else {
|
|
3870
|
-
field
|
|
3871
|
-
|
|
3872
|
-
lense = {
|
|
3873
|
-
get: stateGetter,
|
|
3874
|
-
set: (state, arr) => state
|
|
3875
|
-
};
|
|
3876
|
-
preventStateUpdates = true;
|
|
3937
|
+
console.error(`Collection component in ${ this.name } has an invalid 'from' field: Expecting 'undefined', a string indicating an array property in the state, or an object with 'get' and 'set' functions for retrieving and setting child state from the current state. Attempting to use parent component state.`);
|
|
3938
|
+
lense = undefined;
|
|
3877
3939
|
}
|
|
3878
|
-
|
|
3879
|
-
const
|
|
3880
|
-
sink$
|
|
3940
|
+
|
|
3941
|
+
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$ };
|
|
3942
|
+
const sink$ = collection(factory, lense, { container: null })(sources);
|
|
3881
3943
|
if (typeof sink$ !== 'object') {
|
|
3882
3944
|
throw new Error('Invalid sinks returned from component factory of collection element')
|
|
3883
3945
|
}
|
|
3884
|
-
return
|
|
3946
|
+
return sink$
|
|
3885
3947
|
}
|
|
3886
3948
|
|
|
3887
3949
|
instantiateSwitchable(el, props$, children$) {
|
|
3888
3950
|
const data = el.data;
|
|
3889
3951
|
const props = data.props || {};
|
|
3890
3952
|
el.children || [];
|
|
3891
|
-
let stateSource = new state.StateSource(this.sources[this.stateSourceName].stream.startWith(this.currentState));
|
|
3892
3953
|
|
|
3893
|
-
const
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3954
|
+
const combined$ = xs__default["default"].combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
3955
|
+
.map(([state, __props, __children]) => {
|
|
3956
|
+
return typeof state === 'object' ? { ...this.addCalculated(state), __props, __children } : { value: state, __props, __children }
|
|
3957
|
+
});
|
|
3897
3958
|
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3959
|
+
const stateSource = new state.StateSource(combined$);
|
|
3960
|
+
const stateField = props.state;
|
|
3961
|
+
let lense;
|
|
3962
|
+
|
|
3963
|
+
const fieldLense = {
|
|
3964
|
+
get: state => {
|
|
3965
|
+
const { __props, __children } = state;
|
|
3966
|
+
return (typeof state[stateField] === 'object' && !(state[stateField] instanceof Array)) ? { ...state[stateField], __props, __children } : { value: state[stateField], __props, __children }
|
|
3967
|
+
},
|
|
3968
|
+
set: (oldState, newState) => {
|
|
3969
|
+
if (this.calculated && stateField in this.calculated) {
|
|
3970
|
+
console.warn(`Switchable sub-component of ${ this.name } attempted to update state on a calculated field '${ stateField }': Update ignored`);
|
|
3971
|
+
return oldState
|
|
3910
3972
|
}
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3973
|
+
console.log('SWITCH SET', newState);
|
|
3974
|
+
if (typeof newState !== 'object' || newState instanceof Array) return { ...oldState, [stateField]: newState }
|
|
3975
|
+
const { __props, __children, ...sanitized } = newState;
|
|
3976
|
+
return { ...oldState, [stateField]: sanitized }
|
|
3977
|
+
}
|
|
3978
|
+
};
|
|
3979
|
+
|
|
3980
|
+
const baseLense = {
|
|
3981
|
+
get: state => state,
|
|
3982
|
+
set: (oldState, newState) => {
|
|
3983
|
+
if (typeof newState !== 'object' || newState instanceof Array) return newState
|
|
3984
|
+
const { __props, __children, ...sanitized } = newState;
|
|
3985
|
+
return sanitized
|
|
3986
|
+
}
|
|
3987
|
+
};
|
|
3988
|
+
|
|
3989
|
+
if (typeof stateField === 'undefined') {
|
|
3990
|
+
lense = baseLense;
|
|
3991
|
+
} else if (typeof stateField === 'string') {
|
|
3992
|
+
lense = fieldLense;
|
|
3920
3993
|
} else if (typeof stateField === 'object') {
|
|
3921
|
-
|
|
3994
|
+
if (typeof stateField.get !== 'function') {
|
|
3995
|
+
console.error(`Switchable component in ${ this.name } has an invalid 'state' field: Expecting 'undefined', a string indicating an array property in the state, or an object with 'get' and 'set' functions for retrieving and setting sub-component state from the current state. Attempting to use parent component state.`);
|
|
3996
|
+
lense = baseLense;
|
|
3997
|
+
} else {
|
|
3998
|
+
lense = { get: stateField.get, set: stateField.set };
|
|
3999
|
+
}
|
|
3922
4000
|
} else {
|
|
3923
|
-
|
|
4001
|
+
console.error(`Invalid state provided to switchable sub-component of ${ this.name }: Expecting string, object, or undefined, but found ${ typeof stateField }. Attempting to use parent component state.`);
|
|
4002
|
+
lense = baseLense;
|
|
3924
4003
|
}
|
|
3925
4004
|
|
|
3926
|
-
const switchableComponents =
|
|
4005
|
+
const switchableComponents = props.of;
|
|
3927
4006
|
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$ };
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
} else {
|
|
3931
|
-
sink$ = switchable(switchableComponents, props$.map(props => props.current))(sources);
|
|
3932
|
-
}
|
|
4007
|
+
|
|
4008
|
+
const sink$ = isolate__default["default"](switchable(switchableComponents, props$.map(props => props.current)), { [this.stateSourceName]: lense })(sources);
|
|
3933
4009
|
|
|
3934
4010
|
if (typeof sink$ !== 'object') {
|
|
3935
4011
|
throw new Error('Invalid sinks returned from component factory of switchable element')
|
|
3936
4012
|
}
|
|
3937
4013
|
|
|
3938
|
-
return
|
|
4014
|
+
return sink$
|
|
3939
4015
|
}
|
|
3940
4016
|
|
|
3941
4017
|
instantiateCustomComponent(el, props$, children$) {
|
|
@@ -3943,43 +4019,71 @@ class Component {
|
|
|
3943
4019
|
const data = el.data;
|
|
3944
4020
|
const props = data.props || {};
|
|
3945
4021
|
el.children || [];
|
|
3946
|
-
|
|
4022
|
+
|
|
4023
|
+
const combined$ = xs__default["default"].combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
4024
|
+
.map(([state, __props, __children]) => {
|
|
4025
|
+
return typeof state === 'object' ? { ...this.addCalculated(state), __props, __children } : { value: state, __props, __children }
|
|
4026
|
+
});
|
|
4027
|
+
|
|
4028
|
+
const stateSource = new state.StateSource(combined$);
|
|
4029
|
+
const stateField = props.state;
|
|
3947
4030
|
|
|
3948
4031
|
const factory = componentName === 'sygnal-factory' ? props.sygnalFactory : (this.components[componentName] || props.sygnalFactory);
|
|
3949
|
-
if (!factory
|
|
4032
|
+
if (!factory) {
|
|
3950
4033
|
if (componentName === 'sygnal-factory') throw new Error(`Component not found on element with Capitalized selector and nameless function: JSX transpilation replaces selectors starting with upper case letters with functions in-scope with the same name, Sygnal cannot see the name of the resulting component.`)
|
|
3951
4034
|
throw new Error(`Component not found: ${ componentName }`)
|
|
3952
4035
|
}
|
|
3953
4036
|
|
|
3954
|
-
let
|
|
3955
|
-
let sink$;
|
|
4037
|
+
let lense;
|
|
3956
4038
|
|
|
3957
|
-
const
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
4039
|
+
const fieldLense = {
|
|
4040
|
+
get: state => {
|
|
4041
|
+
const { __props, __children } = state;
|
|
4042
|
+
return typeof state[stateField] === 'object' ? { ...state[stateField], __props, __children } : { value: state[stateField], __props, __children }
|
|
4043
|
+
},
|
|
4044
|
+
set: (oldState, newState) => {
|
|
4045
|
+
if (this.calculated && stateField in this.calculated) {
|
|
4046
|
+
console.warn(`Sub-component of ${ this.name } attempted to update state on a calculated field '${ stateField }': Update ignored`);
|
|
4047
|
+
return oldState
|
|
4048
|
+
}
|
|
4049
|
+
return { ...oldState, [stateField]: newState }
|
|
4050
|
+
}
|
|
4051
|
+
};
|
|
4052
|
+
|
|
4053
|
+
const baseLense = {
|
|
4054
|
+
get: state => state,
|
|
4055
|
+
set: (oldState, newState) => {
|
|
4056
|
+
if (typeof newState !== 'object' || newState instanceof Array) return newState
|
|
4057
|
+
const { __props, __children, ...sanitized } = newState;
|
|
4058
|
+
return sanitized
|
|
4059
|
+
}
|
|
4060
|
+
};
|
|
4061
|
+
|
|
4062
|
+
if (typeof stateField === 'undefined') {
|
|
4063
|
+
lense = baseLense;
|
|
4064
|
+
} else if (typeof stateField === 'string') {
|
|
4065
|
+
lense = fieldLense;
|
|
4066
|
+
} else if (typeof stateField === 'object') {
|
|
4067
|
+
if (typeof stateField.get !== 'function') {
|
|
4068
|
+
console.error(`Sub-component in ${ this.name } has an invalid 'state' field: Expecting 'undefined', a string indicating an array property in the state, or an object with 'get' and 'set' functions for retrieving and setting sub-component state from the current state. Attempting to use parent component state.`);
|
|
4069
|
+
lense = baseLense;
|
|
4070
|
+
} else {
|
|
4071
|
+
lense = { get: stateField.get, set: stateField.set };
|
|
4072
|
+
}
|
|
3962
4073
|
} else {
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
if (typeof state === 'undefined') return props
|
|
3966
|
-
if (typeof state !== 'object') return state
|
|
3967
|
-
|
|
3968
|
-
const copy = { ...props };
|
|
3969
|
-
delete copy.state;
|
|
3970
|
-
return { ...copy, ...state }
|
|
3971
|
-
};
|
|
3972
|
-
stateSource = new state.StateSource(props$.map(lense));
|
|
3973
|
-
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$ };
|
|
3974
|
-
sink$ = factory(sources);
|
|
4074
|
+
console.error(`Invalid state provided to sub-component of ${ this.name }: Expecting string, object, or undefined, but found ${ typeof stateField }. Attempting to use parent component state.`);
|
|
4075
|
+
lense = baseLense;
|
|
3975
4076
|
}
|
|
3976
4077
|
|
|
4078
|
+
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$ };
|
|
4079
|
+
const sink$ = isolate__default["default"](factory, { [this.stateSourceName]: lense })(sources);
|
|
4080
|
+
|
|
3977
4081
|
if (typeof sink$ !== 'object') {
|
|
3978
4082
|
const name = componentName === 'sygnal-factory' ? 'custom element' : componentName;
|
|
3979
4083
|
throw new Error('Invalid sinks returned from component factory:', name)
|
|
3980
4084
|
}
|
|
3981
4085
|
|
|
3982
|
-
return
|
|
4086
|
+
return sink$
|
|
3983
4087
|
}
|
|
3984
4088
|
|
|
3985
4089
|
renderVdom(componentInstances$) {
|
|
@@ -4068,7 +4172,7 @@ function getComponents(currentElement, componentNames, depth=0, index=0) {
|
|
|
4068
4172
|
const isSwitchable = sel && sel.toLowerCase() === 'switchable';
|
|
4069
4173
|
const isComponent = sel && (['collection', 'switchable', 'sygnal-factory', ...componentNames].includes(currentElement.sel)) || typeof currentElement.data?.props?.sygnalFactory === 'function';
|
|
4070
4174
|
const props = (currentElement.data && currentElement.data.props) || {};
|
|
4071
|
-
|
|
4175
|
+
(currentElement.data && currentElement.data.attrs) || {};
|
|
4072
4176
|
const children = currentElement.children || [];
|
|
4073
4177
|
|
|
4074
4178
|
let found = {};
|
|
@@ -4079,11 +4183,9 @@ function getComponents(currentElement, componentNames, depth=0, index=0) {
|
|
|
4079
4183
|
if (!props.of) throw new Error(`Collection element missing required 'component' property`)
|
|
4080
4184
|
if (typeof props.of !== 'string' && typeof props.of !== 'function') throw new Error(`Invalid 'component' property of collection element: found ${ typeof props.of } requires string or component factory function`)
|
|
4081
4185
|
if (typeof props.of !== 'function' && !componentNames.includes(props.of)) throw new Error(`Specified component for collection not found: ${ props.of }`)
|
|
4082
|
-
if (typeof
|
|
4186
|
+
if (typeof props.from !== 'undefined' && !(typeof props.from === 'string' || Array.isArray(props.from))) console.warn(`No valid array found in the 'value' property of collection ${ typeof props.of === 'string' ? props.of : 'function component' }: no collection components will be created`);
|
|
4083
4187
|
currentElement.data.isCollection = true;
|
|
4084
4188
|
currentElement.data.props ||= {};
|
|
4085
|
-
currentElement.data.props.for = attrs.for;
|
|
4086
|
-
currentElement.data.attrs = undefined;
|
|
4087
4189
|
} else if (isSwitchable) {
|
|
4088
4190
|
if (!props.of) throw new Error(`Switchable element missing required 'of' property`)
|
|
4089
4191
|
if (typeof props.of !== 'object') throw new Error(`Invalid 'components' property of switchable element: found ${ typeof props.of } requires object mapping names to component factories`)
|