sygnal 2.9.3 → 2.9.4
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 +64 -63
- package/dist/index.esm.js +64 -63
- package/dist/sygnal.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -3158,7 +3158,7 @@ const ABORT = '~#~#~ABORT~#~#~';
|
|
|
3158
3158
|
function component (opts) {
|
|
3159
3159
|
const { name, sources, isolateOpts, stateSourceName='STATE' } = opts;
|
|
3160
3160
|
|
|
3161
|
-
if (sources &&
|
|
3161
|
+
if (sources && !isObj(sources)) {
|
|
3162
3162
|
throw new Error('Sources must be a Cycle.js sources object:', name)
|
|
3163
3163
|
}
|
|
3164
3164
|
|
|
@@ -3176,7 +3176,7 @@ function component (opts) {
|
|
|
3176
3176
|
const currySources = typeof sources === 'undefined';
|
|
3177
3177
|
let returnFunction;
|
|
3178
3178
|
|
|
3179
|
-
if (
|
|
3179
|
+
if (isObj(fixedIsolateOpts)) {
|
|
3180
3180
|
const wrapped = (sources) => {
|
|
3181
3181
|
const fixedOpts = { ...opts, sources };
|
|
3182
3182
|
return (new Component(fixedOpts)).sinks
|
|
@@ -3240,7 +3240,7 @@ class Component {
|
|
|
3240
3240
|
// sinks
|
|
3241
3241
|
|
|
3242
3242
|
constructor({ name='NO NAME', sources, intent, request, model, context, response, view, children={}, components={}, initialState, calculated, storeCalculatedInState=true, DOMSourceName='DOM', stateSourceName='STATE', requestSourceName='HTTP', debug=false }) {
|
|
3243
|
-
if (!sources ||
|
|
3243
|
+
if (!sources || !isObj(sources)) throw new Error('Missing or invalid sources')
|
|
3244
3244
|
|
|
3245
3245
|
this.name = name;
|
|
3246
3246
|
this.sources = sources;
|
|
@@ -3320,7 +3320,7 @@ class Component {
|
|
|
3320
3320
|
|
|
3321
3321
|
this.intent$ = this.intent(this.sources);
|
|
3322
3322
|
|
|
3323
|
-
if (!(this.intent$ instanceof xs$1.Stream) && (
|
|
3323
|
+
if (!(this.intent$ instanceof xs$1.Stream) && (!isObj(this.intent$))) {
|
|
3324
3324
|
throw new Error('Intent must return either an action$ stream or map of event streams')
|
|
3325
3325
|
}
|
|
3326
3326
|
}
|
|
@@ -3364,7 +3364,7 @@ class Component {
|
|
|
3364
3364
|
initResponse$() {
|
|
3365
3365
|
if (typeof this.request == 'undefined') {
|
|
3366
3366
|
return
|
|
3367
|
-
} else if (
|
|
3367
|
+
} else if (!isObj(this.request)) {
|
|
3368
3368
|
throw new Error('The request parameter must be an object')
|
|
3369
3369
|
}
|
|
3370
3370
|
|
|
@@ -3469,29 +3469,16 @@ class Component {
|
|
|
3469
3469
|
this.context$ = xs$1.of({});
|
|
3470
3470
|
return
|
|
3471
3471
|
}
|
|
3472
|
-
const repeatChecker = (a, b) => {
|
|
3473
|
-
if (a === b) return true
|
|
3474
|
-
if (typeof a !== 'object' || typeof b !== 'object') {
|
|
3475
|
-
return a === b
|
|
3476
|
-
}
|
|
3477
|
-
const entriesA = Object.entries(a);
|
|
3478
|
-
const entriesB = Object.entries(b);
|
|
3479
|
-
if (entriesA.length === 0 && entriesB.length === 0) return true
|
|
3480
|
-
if (entriesA.length !== entriesB.length) return false
|
|
3481
|
-
return entriesA.every(([name, value]) => {
|
|
3482
|
-
return b[name] === value
|
|
3483
|
-
})
|
|
3484
|
-
};
|
|
3485
3472
|
|
|
3486
|
-
const state$ = this.sources[this.stateSourceName]?.stream.startWith({}).compose(_default$5(
|
|
3487
|
-
const parentContext$ = this.sources.__parentContext$.startWith({}).compose(_default$5(
|
|
3488
|
-
if (this.context &&
|
|
3473
|
+
const state$ = this.sources[this.stateSourceName]?.stream.startWith({}).compose(_default$5(objIsEqual)) || xs$1.never();
|
|
3474
|
+
const parentContext$ = this.sources.__parentContext$.startWith({}).compose(_default$5(objIsEqual)) || xs$1.of({});
|
|
3475
|
+
if (this.context && !isObj(this.context)) {
|
|
3489
3476
|
console.error(`[${this.name}] Context must be an object mapping names to values of functions: ignoring provided ${ typeof this.context }`);
|
|
3490
3477
|
}
|
|
3491
3478
|
this.context$ = xs$1.combine(state$, parentContext$)
|
|
3492
3479
|
.map(([_, parent]) => {
|
|
3493
|
-
const _parent =
|
|
3494
|
-
const context =
|
|
3480
|
+
const _parent = isObj(parent) ? parent : {};
|
|
3481
|
+
const context = isObj(this.context) ? this.context : {};
|
|
3495
3482
|
const state = this.currentState;
|
|
3496
3483
|
const values = Object.entries(context).reduce((acc, current) => {
|
|
3497
3484
|
const [name, value] = current;
|
|
@@ -3514,7 +3501,7 @@ class Component {
|
|
|
3514
3501
|
this.currentContext = newContext;
|
|
3515
3502
|
return newContext
|
|
3516
3503
|
})
|
|
3517
|
-
.compose(_default$5(
|
|
3504
|
+
.compose(_default$5(objIsEqual))
|
|
3518
3505
|
.startWith({});
|
|
3519
3506
|
this.context$.subscribe({ next: _ => _ });
|
|
3520
3507
|
}
|
|
@@ -3548,7 +3535,7 @@ class Component {
|
|
|
3548
3535
|
sinks = { [this.stateSourceName]: sinks };
|
|
3549
3536
|
}
|
|
3550
3537
|
|
|
3551
|
-
if (
|
|
3538
|
+
if (!isObj(sinks)) {
|
|
3552
3539
|
throw new Error(`Entry for each action must be an object: ${ this.name } ${ action }`)
|
|
3553
3540
|
}
|
|
3554
3541
|
|
|
@@ -3614,7 +3601,7 @@ class Component {
|
|
|
3614
3601
|
};
|
|
3615
3602
|
|
|
3616
3603
|
const out = this.response(selectable);
|
|
3617
|
-
if (
|
|
3604
|
+
if (!isObj(out)) {
|
|
3618
3605
|
throw new Error('The response function must return an object')
|
|
3619
3606
|
}
|
|
3620
3607
|
|
|
@@ -3726,7 +3713,7 @@ class Component {
|
|
|
3726
3713
|
const next = (type, data, delay=10) => {
|
|
3727
3714
|
if (typeof delay !== 'number') throw new Error(`[${ this.name } ] Invalid delay value provided to next() function in model action '${ name }'. Must be a number in ms.`)
|
|
3728
3715
|
const _reqId = action._reqId || (action.req && action.req.id);
|
|
3729
|
-
const _data = _reqId ? (
|
|
3716
|
+
const _data = _reqId ? (isObj(data) ? { ...data, _reqId, _action: name } : { data, _reqId, _action: name }) : data;
|
|
3730
3717
|
// put the "next" action request at the end of the event loop so the "current" action completes first
|
|
3731
3718
|
setTimeout(() => {
|
|
3732
3719
|
// push the "next" action request into the action$ stream
|
|
@@ -3751,7 +3738,7 @@ class Component {
|
|
|
3751
3738
|
const type = typeof reduced;
|
|
3752
3739
|
const _reqId = action._reqId || (action.req && action.req.id);
|
|
3753
3740
|
if (['string', 'number', 'boolean', 'function'].includes(type)) return reduced
|
|
3754
|
-
if (
|
|
3741
|
+
if (isObj(reduced)) return { ...reduced, _reqId, _action: name }
|
|
3755
3742
|
if (type == 'undefined') {
|
|
3756
3743
|
console.warn(`'undefined' value sent to ${ name }`);
|
|
3757
3744
|
return reduced
|
|
@@ -3775,11 +3762,11 @@ class Component {
|
|
|
3775
3762
|
let lastResult;
|
|
3776
3763
|
|
|
3777
3764
|
return function(state) {
|
|
3778
|
-
if (!this.calculated ||
|
|
3765
|
+
if (!this.calculated || !isObj(state) || Array.isArray(state)) return state
|
|
3779
3766
|
if (state === lastState) {
|
|
3780
3767
|
return lastResult
|
|
3781
3768
|
}
|
|
3782
|
-
if (
|
|
3769
|
+
if (!isObj(this.calculated)) throw new Error(`'calculated' parameter must be an object mapping calculated state field named to functions`)
|
|
3783
3770
|
const entries = Object.entries(this.calculated);
|
|
3784
3771
|
if (entries.length === 0) {
|
|
3785
3772
|
lastState = state;
|
|
@@ -3806,7 +3793,7 @@ class Component {
|
|
|
3806
3793
|
}
|
|
3807
3794
|
|
|
3808
3795
|
cleanupCalculated(incomingState) {
|
|
3809
|
-
if (!incomingState ||
|
|
3796
|
+
if (!incomingState || !isObj(incomingState) || Array.isArray(incomingState)) return incomingState
|
|
3810
3797
|
const state = this.storeCalculatedInState ? this.addCalculated(incomingState) : incomingState;
|
|
3811
3798
|
const { __props, __children, __context, ...sanitized } = state;
|
|
3812
3799
|
const copy = { ...sanitized };
|
|
@@ -3967,20 +3954,21 @@ class Component {
|
|
|
3967
3954
|
const data = el.data;
|
|
3968
3955
|
const props = data.props || {};
|
|
3969
3956
|
el.children || [];
|
|
3957
|
+
let filter = typeof props.filter === 'function' ? props.filter : _ => true;
|
|
3970
3958
|
|
|
3971
3959
|
const combined$ = xs$1.combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
3972
3960
|
.map(([state, __props, __children]) => {
|
|
3973
|
-
|
|
3961
|
+
if (__props.filter && typeof __props.filter === 'function') {
|
|
3962
|
+
filter = __props.filter;
|
|
3963
|
+
}
|
|
3964
|
+
return isObj(state) ? { ...this.addCalculated(state), __props, __children, __context: this.currentContext } : { value: state, __props, __children, __context: this.currentContext }
|
|
3974
3965
|
});
|
|
3975
3966
|
|
|
3976
|
-
const stateSource
|
|
3977
|
-
const stateField
|
|
3978
|
-
|
|
3979
|
-
if (typeof props.sygnalFactory !== 'function' && typeof props.sygnalOptions === 'object') {
|
|
3980
|
-
props.sygnalFactory = component(props.sygnalOptions);
|
|
3981
|
-
}
|
|
3982
|
-
|
|
3967
|
+
const stateSource = new state.StateSource(combined$);
|
|
3968
|
+
const stateField = props.from;
|
|
3983
3969
|
const collectionOf = props.of;
|
|
3970
|
+
const idField = props.idfield || 'id';
|
|
3971
|
+
|
|
3984
3972
|
let lense;
|
|
3985
3973
|
let factory;
|
|
3986
3974
|
|
|
@@ -4001,7 +3989,7 @@ class Component {
|
|
|
4001
3989
|
}
|
|
4002
3990
|
|
|
4003
3991
|
const sanitizeItems = item => {
|
|
4004
|
-
if (
|
|
3992
|
+
if (isObj(item)) {
|
|
4005
3993
|
const { __props, __children, __context, ...sanitized } = item;
|
|
4006
3994
|
return sanitized
|
|
4007
3995
|
} else {
|
|
@@ -4013,8 +4001,8 @@ class Component {
|
|
|
4013
4001
|
get: state => {
|
|
4014
4002
|
const { __props, __children } = state;
|
|
4015
4003
|
if (!Array.isArray(state[stateField])) return []
|
|
4016
|
-
return state[stateField].map(item => {
|
|
4017
|
-
return
|
|
4004
|
+
return state[stateField].filter(filter).map((item, index) => {
|
|
4005
|
+
return (isObj(item)) ? { ...item, [idField]: item[idField] || index, __props, __children, __context: this.currentContext } : { value: item, [idField]: index, __props, __children, __context: this.currentContext }
|
|
4018
4006
|
})
|
|
4019
4007
|
},
|
|
4020
4008
|
set: (oldState, newState) => {
|
|
@@ -4022,6 +4010,15 @@ class Component {
|
|
|
4022
4010
|
console.warn(`Collection sub-component of ${ this.name } attempted to update state on a calculated field '${ stateField }': Update ignored`);
|
|
4023
4011
|
return oldState
|
|
4024
4012
|
}
|
|
4013
|
+
const updated = [];
|
|
4014
|
+
for (const oldItem of oldState[stateField].map((item, index) => ({ __primitive: true, value: item, [idField]: index }))) {
|
|
4015
|
+
if (!filter(oldItem)) {
|
|
4016
|
+
updated.push(oldItem.__primitive ? oldItem.value : oldItem);
|
|
4017
|
+
} else {
|
|
4018
|
+
const newItem = newState.find(newItem => newItem.id === oldItem.id);
|
|
4019
|
+
if (typeof newItem !== 'undefined') updated.push(oldItem.__primitive ? newItem.value : newItem);
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4025
4022
|
return { ...oldState, [stateField]: newState.map(sanitizeItems) }
|
|
4026
4023
|
}
|
|
4027
4024
|
};
|
|
@@ -4037,7 +4034,7 @@ class Component {
|
|
|
4037
4034
|
}
|
|
4038
4035
|
};
|
|
4039
4036
|
} else if (typeof stateField === 'string') {
|
|
4040
|
-
if (
|
|
4037
|
+
if (isObj(this.currentState)) {
|
|
4041
4038
|
if(!(this.currentState && stateField in this.currentState) && !(this.calculated && stateField in this.calculated)) {
|
|
4042
4039
|
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.`);
|
|
4043
4040
|
lense = undefined;
|
|
@@ -4055,7 +4052,7 @@ class Component {
|
|
|
4055
4052
|
lense = fieldLense;
|
|
4056
4053
|
}
|
|
4057
4054
|
}
|
|
4058
|
-
} else if (
|
|
4055
|
+
} else if (isObj(stateField)) {
|
|
4059
4056
|
if (typeof stateField.get !== 'function') {
|
|
4060
4057
|
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.`);
|
|
4061
4058
|
lense = undefined;
|
|
@@ -4079,7 +4076,7 @@ class Component {
|
|
|
4079
4076
|
|
|
4080
4077
|
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$, __parentContext$: this.context$ };
|
|
4081
4078
|
const sink$ = collection(factory, lense, { container: null })(sources);
|
|
4082
|
-
if (
|
|
4079
|
+
if (!isObj(sink$)) {
|
|
4083
4080
|
throw new Error('Invalid sinks returned from component factory of collection element')
|
|
4084
4081
|
}
|
|
4085
4082
|
return sink$
|
|
@@ -4092,7 +4089,7 @@ class Component {
|
|
|
4092
4089
|
|
|
4093
4090
|
const combined$ = xs$1.combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
4094
4091
|
.map(([state, __props, __children]) => {
|
|
4095
|
-
return
|
|
4092
|
+
return isObj(state) ? { ...this.addCalculated(state), __props, __children, __context: this.currentContext } : { value: state, __props, __children, __context: this.currentContext }
|
|
4096
4093
|
});
|
|
4097
4094
|
|
|
4098
4095
|
const stateSource = new state.StateSource(combined$);
|
|
@@ -4102,14 +4099,14 @@ class Component {
|
|
|
4102
4099
|
const fieldLense = {
|
|
4103
4100
|
get: state => {
|
|
4104
4101
|
const { __props, __children } = state;
|
|
4105
|
-
return (
|
|
4102
|
+
return (isObj(state[stateField])) ? { ...state[stateField], __props, __children, __context: this.currentContext } : { value: state[stateField], __props, __children, __context: this.currentContext }
|
|
4106
4103
|
},
|
|
4107
4104
|
set: (oldState, newState) => {
|
|
4108
4105
|
if (this.calculated && stateField in this.calculated) {
|
|
4109
4106
|
console.warn(`Switchable sub-component of ${ this.name } attempted to update state on a calculated field '${ stateField }': Update ignored`);
|
|
4110
4107
|
return oldState
|
|
4111
4108
|
}
|
|
4112
|
-
if (
|
|
4109
|
+
if (!isObj(newState) || Array.isArray(newState)) return { ...oldState, [stateField]: newState }
|
|
4113
4110
|
const { __props, __children, __context, ...sanitized } = newState;
|
|
4114
4111
|
return { ...oldState, [stateField]: sanitized }
|
|
4115
4112
|
}
|
|
@@ -4118,7 +4115,7 @@ class Component {
|
|
|
4118
4115
|
const baseLense = {
|
|
4119
4116
|
get: state => state,
|
|
4120
4117
|
set: (oldState, newState) => {
|
|
4121
|
-
if (
|
|
4118
|
+
if (!isObj(newState) || Array.isArray(newState)) return newState
|
|
4122
4119
|
const { __props, __children, __context, ...sanitized } = newState;
|
|
4123
4120
|
return sanitized
|
|
4124
4121
|
}
|
|
@@ -4128,7 +4125,7 @@ class Component {
|
|
|
4128
4125
|
lense = baseLense;
|
|
4129
4126
|
} else if (typeof stateField === 'string') {
|
|
4130
4127
|
lense = fieldLense;
|
|
4131
|
-
} else if (
|
|
4128
|
+
} else if (isObj(stateField)) {
|
|
4132
4129
|
if (typeof stateField.get !== 'function') {
|
|
4133
4130
|
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.`);
|
|
4134
4131
|
lense = baseLense;
|
|
@@ -4156,7 +4153,7 @@ class Component {
|
|
|
4156
4153
|
|
|
4157
4154
|
const sink$ = isolate(switchable(switchableComponents, props$.map(props => props.current)), { [this.stateSourceName]: lense })(sources);
|
|
4158
4155
|
|
|
4159
|
-
if (
|
|
4156
|
+
if (!isObj(sink$)) {
|
|
4160
4157
|
throw new Error('Invalid sinks returned from component factory of switchable element')
|
|
4161
4158
|
}
|
|
4162
4159
|
|
|
@@ -4171,13 +4168,13 @@ class Component {
|
|
|
4171
4168
|
|
|
4172
4169
|
const combined$ = xs$1.combine(this.sources[this.stateSourceName].stream.startWith(this.currentState), props$, children$)
|
|
4173
4170
|
.map(([state, __props, __children]) => {
|
|
4174
|
-
return
|
|
4171
|
+
return isObj(state) ? { ...this.addCalculated(state), __props, __children, __context: this.currentContext } : { value: state, __props, __children, __context: this.currentContext }
|
|
4175
4172
|
});
|
|
4176
4173
|
|
|
4177
4174
|
const stateSource = new state.StateSource(combined$);
|
|
4178
4175
|
const stateField = props.state;
|
|
4179
4176
|
|
|
4180
|
-
if (typeof props.sygnalFactory !== 'function' &&
|
|
4177
|
+
if (typeof props.sygnalFactory !== 'function' && isObj(props.sygnalOptions)) {
|
|
4181
4178
|
props.sygnalFactory = component(props.sygnalOptions);
|
|
4182
4179
|
}
|
|
4183
4180
|
|
|
@@ -4192,7 +4189,7 @@ class Component {
|
|
|
4192
4189
|
const fieldLense = {
|
|
4193
4190
|
get: state => {
|
|
4194
4191
|
const { __props, __children } = state;
|
|
4195
|
-
return
|
|
4192
|
+
return isObj(state[stateField]) ? { ...state[stateField], __props, __children, __context: this.currentContext } : { value: state[stateField], __props, __children, __context: this.currentContext }
|
|
4196
4193
|
},
|
|
4197
4194
|
set: (oldState, newState) => {
|
|
4198
4195
|
if (this.calculated && stateField in this.calculated) {
|
|
@@ -4206,7 +4203,7 @@ class Component {
|
|
|
4206
4203
|
const baseLense = {
|
|
4207
4204
|
get: state => state,
|
|
4208
4205
|
set: (oldState, newState) => {
|
|
4209
|
-
if (
|
|
4206
|
+
if (!isObj(newState) || Array.isArray(newState)) return newState
|
|
4210
4207
|
const { __props, __children, __context, ...sanitized } = newState;
|
|
4211
4208
|
return sanitized
|
|
4212
4209
|
}
|
|
@@ -4216,7 +4213,7 @@ class Component {
|
|
|
4216
4213
|
lense = baseLense;
|
|
4217
4214
|
} else if (typeof stateField === 'string') {
|
|
4218
4215
|
lense = fieldLense;
|
|
4219
|
-
} else if (
|
|
4216
|
+
} else if (isObj(stateField)) {
|
|
4220
4217
|
if (typeof stateField.get !== 'function') {
|
|
4221
4218
|
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.`);
|
|
4222
4219
|
lense = baseLense;
|
|
@@ -4231,7 +4228,7 @@ class Component {
|
|
|
4231
4228
|
const sources = { ...this.sources, [this.stateSourceName]: stateSource, props$, children$, __parentContext$: this.context$ };
|
|
4232
4229
|
const sink$ = isolate(factory, { [this.stateSourceName]: lense })(sources);
|
|
4233
4230
|
|
|
4234
|
-
if (
|
|
4231
|
+
if (!isObj(sink$)) {
|
|
4235
4232
|
const name = componentName === 'sygnal-factory' ? 'custom element' : componentName;
|
|
4236
4233
|
throw new Error('Invalid sinks returned from component factory:', name)
|
|
4237
4234
|
}
|
|
@@ -4329,7 +4326,7 @@ function getComponents(currentElement, componentNames, depth=0, index=0, parentI
|
|
|
4329
4326
|
const sel = currentElement.sel;
|
|
4330
4327
|
const isCollection = sel && sel.toLowerCase() === 'collection';
|
|
4331
4328
|
const isSwitchable = sel && sel.toLowerCase() === 'switchable';
|
|
4332
|
-
const isComponent = sel && (['collection', 'switchable', 'sygnal-factory', ...componentNames].includes(sel)) || typeof currentElement.data?.props?.sygnalFactory === 'function' ||
|
|
4329
|
+
const isComponent = sel && (['collection', 'switchable', 'sygnal-factory', ...componentNames].includes(sel)) || typeof currentElement.data?.props?.sygnalFactory === 'function' || isObj(currentElement.data?.props?.sygnalOptions);
|
|
4333
4330
|
const props = (currentElement.data && currentElement.data.props) || {};
|
|
4334
4331
|
(currentElement.data && currentElement.data.attrs) || {};
|
|
4335
4332
|
const children = currentElement.children || [];
|
|
@@ -4340,15 +4337,15 @@ function getComponents(currentElement, componentNames, depth=0, index=0, parentI
|
|
|
4340
4337
|
if (isComponent) {
|
|
4341
4338
|
id = getComponentIdFromElement(currentElement, depth, index, parentId);
|
|
4342
4339
|
if (isCollection) {
|
|
4343
|
-
if (!props.of)
|
|
4340
|
+
if (!props.of) throw new Error(`Collection element missing required 'component' property`)
|
|
4344
4341
|
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`)
|
|
4345
4342
|
if (typeof props.of !== 'function' && !componentNames.includes(props.of)) throw new Error(`Specified component for collection not found: ${ props.of }`)
|
|
4346
4343
|
if (typeof props.from !== 'undefined' && !(typeof props.from === 'string' || Array.isArray(props.from) || typeof props.from.get === 'function')) console.warn(`No valid array found for collection ${ typeof props.of === 'string' ? props.of : 'function component' }: no collection components will be created`, props.from);
|
|
4347
4344
|
currentElement.data.isCollection = true;
|
|
4348
4345
|
currentElement.data.props ||= {};
|
|
4349
4346
|
} else if (isSwitchable) {
|
|
4350
|
-
if (!props.of)
|
|
4351
|
-
if (
|
|
4347
|
+
if (!props.of) throw new Error(`Switchable element missing required 'of' property`)
|
|
4348
|
+
if (!isObj(props.of)) throw new Error(`Invalid 'of' property of switchable element: found ${ typeof props.of } requires object mapping names to component factories`)
|
|
4352
4349
|
const switchableComponents = Object.values(props.of);
|
|
4353
4350
|
if (!switchableComponents.every(comp => typeof comp === 'function')) throw new Error(`One or more components provided to switchable element is not a valid component factory`)
|
|
4354
4351
|
if (!props.current || (typeof props.current !== 'string' && typeof props.current !== 'function')) throw new Error(`Missing or invalid 'current' property for switchable element: found '${ typeof props.current }' requires string or function`)
|
|
@@ -4377,7 +4374,7 @@ function injectComponents(currentElement, components, componentNames, depth=0, i
|
|
|
4377
4374
|
|
|
4378
4375
|
|
|
4379
4376
|
const sel = currentElement.sel || 'NO SELECTOR';
|
|
4380
|
-
const isComponent = ['collection', 'switchable', 'sygnal-factory', ...componentNames].includes(sel) || typeof currentElement.data?.props?.sygnalFactory === 'function' ||
|
|
4377
|
+
const isComponent = ['collection', 'switchable', 'sygnal-factory', ...componentNames].includes(sel) || typeof currentElement.data?.props?.sygnalFactory === 'function' || isObj(currentElement.data?.props?.sygnalOptions);
|
|
4381
4378
|
const isCollection = currentElement?.data?.isCollection;
|
|
4382
4379
|
const isSwitchable = currentElement?.data?.isSwitchable;
|
|
4383
4380
|
(currentElement.data && currentElement.data.props) || {};
|
|
@@ -4475,11 +4472,15 @@ function objIsEqual(objA, objB, maxDepth = 5, depth = 0) {
|
|
|
4475
4472
|
}
|
|
4476
4473
|
|
|
4477
4474
|
function sanitizeObject(obj) {
|
|
4478
|
-
if (
|
|
4475
|
+
if (!isObj(obj)) return obj
|
|
4479
4476
|
const {state, of, from, _reqId, _action, __props, __children, __context, ...sanitized} = obj;
|
|
4480
4477
|
return sanitized
|
|
4481
4478
|
}
|
|
4482
4479
|
|
|
4480
|
+
function isObj(obj) {
|
|
4481
|
+
return typeof obj === 'object' && obj !== null && !Array.isArray(obj)
|
|
4482
|
+
}
|
|
4483
|
+
|
|
4483
4484
|
function driverFromAsync(promiseReturningFunction, opts = {}) {
|
|
4484
4485
|
const {
|
|
4485
4486
|
selector: selectorProperty = 'category',
|