sygnal 3.1.0 → 4.0.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 +32 -9
- package/dist/index.d.ts +221 -0
- package/dist/index.esm.js +32 -11
- package/dist/jsx-dev-runtime.js +224 -0
- package/dist/jsx-runtime.js +224 -0
- package/dist/jsx.cjs.js +12 -1
- package/dist/jsx.esm.js +12 -1
- package/dist/sygnal.min.js +1 -1
- package/package.json +15 -3
- package/src/collection.js +76 -0
- package/src/component.js +1372 -0
- package/src/extra/classes.js +82 -0
- package/src/extra/driverFactories.js +124 -0
- package/src/extra/eventDriver.js +34 -0
- package/src/extra/logDriver.js +9 -0
- package/src/extra/processForm.js +30 -0
- package/src/extra/run.js +62 -0
- package/src/index.d.ts +221 -0
- package/src/index.js +21 -0
- package/src/jsx.js +2 -0
- package/src/pragma/fn.js +54 -0
- package/src/pragma/index.js +133 -0
- package/src/pragma/is.js +23 -0
- package/src/switchable.js +103 -0
- package/src/sygnal.d.ts +49 -0
package/dist/index.cjs.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var isolate = require('@cycle/isolate');
|
|
4
4
|
var state = require('@cycle/state');
|
|
5
|
+
var dom = require('@cycle/dom');
|
|
5
6
|
var xs$1 = require('xstream');
|
|
6
7
|
var run$1 = require('@cycle/run');
|
|
7
|
-
var dom = require('@cycle/dom');
|
|
8
8
|
|
|
9
9
|
function collection(component, stateLense, opts={}) {
|
|
10
10
|
const {
|
|
@@ -66,6 +66,13 @@ function collection(component, stateLense, opts={}) {
|
|
|
66
66
|
return isolate(state.makeCollection(collectionOpts), isolateOpts)(sources)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
const Collection = (props) => {
|
|
70
|
+
const { children, ...sanitizedProps } = props;
|
|
71
|
+
return dom.h('collection', { props: sanitizedProps }, children)
|
|
72
|
+
};
|
|
73
|
+
Collection.label = 'collection';
|
|
74
|
+
Collection.preventInstantiation = true;
|
|
75
|
+
|
|
69
76
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
70
77
|
|
|
71
78
|
var dropRepeats$1 = {};
|
|
@@ -2845,6 +2852,13 @@ function _switchable (factories, sources, name$, switched=['DOM'], stateSourceNa
|
|
|
2845
2852
|
return switchedSinks
|
|
2846
2853
|
}
|
|
2847
2854
|
|
|
2855
|
+
const Switchable = (props) => {
|
|
2856
|
+
const { children, ...sanitizedProps } = props;
|
|
2857
|
+
return dom.h('switchable', { props: sanitizedProps }, children)
|
|
2858
|
+
};
|
|
2859
|
+
Switchable.label = 'switchable';
|
|
2860
|
+
Switchable.preventInstantiation = true;
|
|
2861
|
+
|
|
2848
2862
|
var delay$1 = {};
|
|
2849
2863
|
|
|
2850
2864
|
Object.defineProperty(delay$1, "__esModule", { value: true });
|
|
@@ -3276,7 +3290,8 @@ class Component {
|
|
|
3276
3290
|
const props$ = sources.props$;
|
|
3277
3291
|
if (props$) {
|
|
3278
3292
|
this.sources.props$ = props$.map(val => {
|
|
3279
|
-
|
|
3293
|
+
const { sygnalFactory, sygnalOptions, ...sanitizedProps } = val;
|
|
3294
|
+
this.currentProps = sanitizedProps;
|
|
3280
3295
|
return val
|
|
3281
3296
|
});
|
|
3282
3297
|
}
|
|
@@ -3420,7 +3435,7 @@ class Component {
|
|
|
3420
3435
|
}
|
|
3421
3436
|
|
|
3422
3437
|
const state$ = this.sources[this.stateSourceName]?.stream.startWith({}).compose(_default$5(objIsEqual)) || xs$1.never();
|
|
3423
|
-
const parentContext$ = this.sources.__parentContext
|
|
3438
|
+
const parentContext$ = this.sources.__parentContext$?.startWith({}).compose(_default$5(objIsEqual)) || xs$1.of({});
|
|
3424
3439
|
if (this.context && !isObj(this.context)) {
|
|
3425
3440
|
console.error(`[${this.name}] Context must be an object mapping names to values of functions: ignoring provided ${ typeof this.context }`);
|
|
3426
3441
|
}
|
|
@@ -3610,7 +3625,11 @@ class Component {
|
|
|
3610
3625
|
const renderParameters$ = this.collectRenderParameters();
|
|
3611
3626
|
|
|
3612
3627
|
this.vdom$ = renderParameters$
|
|
3613
|
-
.map(
|
|
3628
|
+
.map(params => {
|
|
3629
|
+
const { props, state, children, context, ...peers } = params;
|
|
3630
|
+
const { sygnalFactory, sygnalOptions, ...sanitizedProps} = props || {};
|
|
3631
|
+
return this.view({ ...sanitizedProps, state, children, context, peers }, state, context, peers)
|
|
3632
|
+
})
|
|
3614
3633
|
.compose(this.log('View rendered'))
|
|
3615
3634
|
.map(vDom => vDom || { sel: 'div', data: {}, children: [] })
|
|
3616
3635
|
.compose(this.instantiateSubComponents.bind(this))
|
|
@@ -3653,20 +3672,22 @@ class Component {
|
|
|
3653
3672
|
this.log(`<${ name }> Triggered a next() action: <${ type }> ${ delay }ms delay`, true);
|
|
3654
3673
|
};
|
|
3655
3674
|
|
|
3656
|
-
const
|
|
3675
|
+
const props = { ...this.currentProps, children: this.currentChildren, context: this.currentContext };
|
|
3657
3676
|
|
|
3658
3677
|
let data = action.data;
|
|
3659
3678
|
if (isStateSink) {
|
|
3660
3679
|
return (state) => {
|
|
3661
3680
|
const _state = this.isSubComponent ? this.currentState : state;
|
|
3662
3681
|
const enhancedState = this.addCalculated(_state);
|
|
3663
|
-
|
|
3682
|
+
props.state = enhancedState;
|
|
3683
|
+
const newState = reducer(enhancedState, data, next, props);
|
|
3664
3684
|
if (newState == ABORT$1) return _state
|
|
3665
3685
|
return this.cleanupCalculated(newState)
|
|
3666
3686
|
}
|
|
3667
3687
|
} else {
|
|
3668
3688
|
const enhancedState = this.addCalculated(this.currentState);
|
|
3669
|
-
|
|
3689
|
+
props.state = enhancedState;
|
|
3690
|
+
const reduced = reducer(enhancedState, data, next, props);
|
|
3670
3691
|
const type = typeof reduced;
|
|
3671
3692
|
if (isObj(reduced) || ['string', 'number', 'boolean', 'function'].includes(type)) return reduced
|
|
3672
3693
|
if (type == 'undefined') {
|
|
@@ -4760,8 +4781,8 @@ function run(app, drivers={}, options={}) {
|
|
|
4760
4781
|
/**
|
|
4761
4782
|
* return a validated and properly separated string of CSS class names from any number of strings, arrays, and objects
|
|
4762
4783
|
*
|
|
4763
|
-
* @param {...String|Array|Object} args any number of strings or arrays with valid CSS class names, or objects where the keys are valid class names and the values evaluate to true or false
|
|
4764
|
-
* @return {String} list of `active` classes separated by spaces
|
|
4784
|
+
* @param { ...String | Array | Object } args any number of strings or arrays with valid CSS class names, or objects where the keys are valid class names and the values evaluate to true or false
|
|
4785
|
+
* @return { String } list of `active` classes separated by spaces
|
|
4765
4786
|
*
|
|
4766
4787
|
* any `string` or `array` arguments are simply validated and appended to the result
|
|
4767
4788
|
* `objects` will evaluate the values (which can be booleans or functions), and the keys with `thruthy` values will be validated and appended to the result
|
|
@@ -5124,6 +5145,8 @@ var _default = sampleCombine$1.default = sampleCombine;
|
|
|
5124
5145
|
|
|
5125
5146
|
exports.xs = xs$1;
|
|
5126
5147
|
exports.ABORT = ABORT$1;
|
|
5148
|
+
exports.Collection = Collection;
|
|
5149
|
+
exports.Switchable = Switchable;
|
|
5127
5150
|
exports.classes = classes;
|
|
5128
5151
|
exports.collection = collection;
|
|
5129
5152
|
exports.component = component;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/// <reference path="../src/sygnal.d.ts" />
|
|
2
|
+
import { Stream } from 'xstream';
|
|
3
|
+
export { MemoryStream, Stream } from 'xstream';
|
|
4
|
+
import { MainDOMSource } from '@cycle/dom';
|
|
5
|
+
import { StateSource } from '@cycle/state';
|
|
6
|
+
|
|
7
|
+
type ABORT = '~#~#~ABORT~#~#~'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A function that takes component properties and returns a JSX element.
|
|
11
|
+
*
|
|
12
|
+
* @template STATE - State type
|
|
13
|
+
* @template PROPS - Props type
|
|
14
|
+
* @template CONTEXT - Context type
|
|
15
|
+
*
|
|
16
|
+
* @param { PROPS & { state?: STATE, children?: JSX.Element | JSX.Element[], context?: CONTEXT } } props - Component props augmented with the current state, children, context, and any peers
|
|
17
|
+
* @returns { JSX.Element } The JSX element rendered by the component.
|
|
18
|
+
*/
|
|
19
|
+
type ComponentProps<STATE, PROPS, CONTEXT> = (
|
|
20
|
+
props: PROPS & { state?: STATE, children?: JSX.Element | JSX.Element[], context?: CONTEXT },
|
|
21
|
+
state: STATE,
|
|
22
|
+
context: CONTEXT,
|
|
23
|
+
peers: { [peer: string]: JSX.Element | JSX.Element[] }
|
|
24
|
+
) => JSX.Element;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
type NextFunction<ACTIONS=any> = ACTIONS extends object
|
|
28
|
+
? <ACTION_KEY extends keyof ACTIONS>(
|
|
29
|
+
action: ACTION_KEY,
|
|
30
|
+
data?: ACTIONS[ACTION_KEY],
|
|
31
|
+
delay?: number
|
|
32
|
+
) => void
|
|
33
|
+
: (action: string, data?: any, delay?: number) => void;
|
|
34
|
+
|
|
35
|
+
type Reducer<STATE, PROPS, ACTIONS = any, DATA = any, RETURN = any> = (
|
|
36
|
+
state: STATE,
|
|
37
|
+
args: DATA,
|
|
38
|
+
next: NextFunction<ACTIONS>,
|
|
39
|
+
props: PROPS
|
|
40
|
+
) => RETURN | ABORT | undefined;
|
|
41
|
+
|
|
42
|
+
type StateOnlyReducer<STATE, RETURN = any> = (
|
|
43
|
+
state: STATE
|
|
44
|
+
) => RETURN | ABORT;
|
|
45
|
+
|
|
46
|
+
type Event<DATA=any> = { type: string, data: DATA }
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Valid values for a sink
|
|
50
|
+
*
|
|
51
|
+
* - true: Whatever value is received from the intent for this action is passed on as-is.
|
|
52
|
+
* - Function: A reducer
|
|
53
|
+
*/
|
|
54
|
+
type SinkValue<STATE, PROPS, ACTIONS, DATA, RETURN> = true | Reducer<STATE, PROPS, ACTIONS, DATA, RETURN>
|
|
55
|
+
|
|
56
|
+
type DefaultSinks<STATE, PROPS, ACTIONS, DATA> = {
|
|
57
|
+
STATE?: SinkValue<STATE, PROPS, ACTIONS, DATA, STATE>;
|
|
58
|
+
EVENTS?: SinkValue<STATE, PROPS, ACTIONS, DATA, Event>;
|
|
59
|
+
LOG?: SinkValue<STATE, PROPS, ACTIONS, DATA, any>;
|
|
60
|
+
PARENT?: SinkValue<STATE, PROPS, ACTIONS, DATA, any>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
type CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY> = keyof DRIVERS extends never ? {
|
|
64
|
+
[driver: string]: SinkValue<STATE, PROPS, ACTIONS, any, any>;
|
|
65
|
+
} : {
|
|
66
|
+
[DRIVER_KEY in keyof DRIVERS]: SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, DRIVERS[DRIVER_KEY] extends { source: any, sink: any } ? DRIVERS[DRIVER_KEY]["sink"] : any>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
type ModelEntry<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY> = SinkValue<STATE, PROPS, ACTIONS, ACTION_ENTRY, STATE> | Partial<DefaultSinks<STATE, PROPS, ACTIONS, ACTION_ENTRY> & CustomDriverSinks<STATE, PROPS, DRIVERS, ACTIONS, ACTION_ENTRY>>;
|
|
70
|
+
|
|
71
|
+
type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
72
|
+
BOOTSTRAP?: never;
|
|
73
|
+
INITIALIZE?: STATE;
|
|
74
|
+
HYDRATE?: any;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS> = keyof ACTIONS extends never ? {
|
|
78
|
+
[action: string]: ModelEntry<STATE, PROPS, DRIVERS, WithDefaultActions<STATE, { [action: string]: any }>, any>;
|
|
79
|
+
} : {
|
|
80
|
+
[ACTION_KEY in keyof WithDefaultActions<STATE, ACTIONS>]?: ModelEntry<STATE, PROPS, DRIVERS, WithDefaultActions<STATE, ACTIONS>, WithDefaultActions<STATE, ACTIONS>[ACTION_KEY]>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type ChildSource = {
|
|
84
|
+
select: (type: string) => Stream<any>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type DefaultDrivers<STATE, EVENTS=any> = {
|
|
88
|
+
STATE: {
|
|
89
|
+
source: StateSource<STATE>;
|
|
90
|
+
sink: STATE;
|
|
91
|
+
};
|
|
92
|
+
DOM: {
|
|
93
|
+
source: MainDOMSource;
|
|
94
|
+
sink: never;
|
|
95
|
+
};
|
|
96
|
+
EVENTS: {
|
|
97
|
+
source: Stream<Event<EVENTS>>;
|
|
98
|
+
sink: EVENTS;
|
|
99
|
+
};
|
|
100
|
+
LOG: {
|
|
101
|
+
source: never;
|
|
102
|
+
sink: any;
|
|
103
|
+
}
|
|
104
|
+
CHILD: {
|
|
105
|
+
source: ChildSource;
|
|
106
|
+
sink: never;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type Sources<DRIVERS> = {
|
|
111
|
+
[DRIVER_KEY in keyof DRIVERS]: DRIVERS[DRIVER_KEY] extends { source: infer SOURCE } ? SOURCE : never;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
type Actions<ACTIONS> = keyof ACTIONS extends never ? {
|
|
115
|
+
[action: string]: Stream<any>;
|
|
116
|
+
} : {
|
|
117
|
+
[ACTION_KEY in keyof ACTIONS]: Stream<ACTIONS[ACTION_KEY]>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
type CombinedSources<STATE, DRIVERS> = Sources<DefaultDrivers<STATE> & DRIVERS>;
|
|
121
|
+
|
|
122
|
+
interface ComponentIntent<STATE, DRIVERS, ACTIONS> {
|
|
123
|
+
(args: CombinedSources<STATE, DRIVERS>): Partial<Actions<ACTIONS>>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
type Calculated<STATE, CALCULATED> = keyof CALCULATED extends never ? {
|
|
127
|
+
[field: string]: boolean | StateOnlyReducer<STATE, any>;
|
|
128
|
+
} : {
|
|
129
|
+
[CALCULATED_KEY in keyof CALCULATED]: boolean | StateOnlyReducer<STATE, CALCULATED[CALCULATED_KEY]>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
type Context<STATE, CONTEXT> = keyof CONTEXT extends never ? {
|
|
133
|
+
[field: string]: boolean | StateOnlyReducer<STATE, any>;
|
|
134
|
+
} : {
|
|
135
|
+
[CONTEXT_KEY in keyof CONTEXT]: boolean | StateOnlyReducer<STATE, CONTEXT[CONTEXT_KEY]>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type Lense<PARENT_STATE=any, CHILD_STATE=any> = {
|
|
139
|
+
get: (state: PARENT_STATE) => CHILD_STATE;
|
|
140
|
+
set: (state: PARENT_STATE, childState: CHILD_STATE) => PARENT_STATE;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type Filter<ITEM=any> = (item: ITEM) => boolean
|
|
144
|
+
|
|
145
|
+
type SortFunction<ITEM=any> = (a: ITEM, b: ITEM) => number
|
|
146
|
+
type SortObject<ITEM=any> = {
|
|
147
|
+
[field: string]: 'asc' | 'dec' | SortFunction<ITEM>;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
type FixDrivers<DRIVERS> =
|
|
151
|
+
0 extends (1 & DRIVERS)
|
|
152
|
+
? {}
|
|
153
|
+
: DRIVERS extends object
|
|
154
|
+
? DRIVERS
|
|
155
|
+
: {};
|
|
156
|
+
/**
|
|
157
|
+
* Sygnal Component
|
|
158
|
+
* @template STATE - State
|
|
159
|
+
* @template PROPS - Props (from JSX element)
|
|
160
|
+
* @template DRIVERS - Custom Drivers (default drivers are automatically applied)
|
|
161
|
+
* @template ACTIONS - Actions (key = action name; value = type expected for Observable values for that action)
|
|
162
|
+
* @template CALCULATED - Calculated state values (key = calculated variable name; value = type of the calculated variable)
|
|
163
|
+
* @template CONTEXT - Context (key = context variable name; value = type of the context variable)
|
|
164
|
+
*/
|
|
165
|
+
type Component<STATE=any, PROPS={[prop: string]: any}, DRIVERS={}, ACTIONS={}, CALCULATED={}, CONTEXT={}> = ComponentProps<STATE & CALCULATED, PROPS, CONTEXT> & {
|
|
166
|
+
label?: string;
|
|
167
|
+
DOMSourceName?: string;
|
|
168
|
+
stateSourceName?: string;
|
|
169
|
+
requestSourceName?: string;
|
|
170
|
+
model?: ComponentModel<STATE & CALCULATED, PROPS, FixDrivers<DRIVERS>, ACTIONS>;
|
|
171
|
+
intent?: ComponentIntent<STATE & CALCULATED, FixDrivers<DRIVERS>, ACTIONS>;
|
|
172
|
+
initialState?: STATE;
|
|
173
|
+
calculated?: Calculated<STATE, CALCULATED>;
|
|
174
|
+
storeCalculatedInState?: boolean;
|
|
175
|
+
context?: Context<STATE & CALCULATED, CONTEXT>;
|
|
176
|
+
peers?: { [name: string]: Component };
|
|
177
|
+
components?: { [name: string]: Component };
|
|
178
|
+
debug?: boolean;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Sygnal Root Component
|
|
183
|
+
* @template STATE - State
|
|
184
|
+
* @template DRIVERS - Custom Drivers (default drivers are automatically applied)
|
|
185
|
+
* @template ACTIONS - Actions (key = action name; value = type expected for Observable values for that action)
|
|
186
|
+
* @template CALCULATED - Calculated state values (key = calculated variable name; value = type of the calculated variable)
|
|
187
|
+
* @template CONTEXT - Context (key = context variable name; value = type of the context variable)
|
|
188
|
+
*/
|
|
189
|
+
type RootComponent<STATE=any, DRIVERS={}, ACTIONS={}, CALCULATED=any, CONTEXT=any> = Component<STATE, any, DRIVERS, ACTIONS, CALCULATED, CONTEXT>
|
|
190
|
+
|
|
191
|
+
type CollectionProps<PROPS=any> = {
|
|
192
|
+
of: any;
|
|
193
|
+
from: string | Lense;
|
|
194
|
+
filter?: Filter;
|
|
195
|
+
sort?: string | SortFunction | SortObject;
|
|
196
|
+
} & Omit<PROPS, 'of' | 'from' | 'filter' | 'sort'>;
|
|
197
|
+
|
|
198
|
+
type SwitchableProps<PROPS=any> = {
|
|
199
|
+
of: any;
|
|
200
|
+
current: string;
|
|
201
|
+
state?: string | Lense;
|
|
202
|
+
} & Omit<PROPS, 'of' | 'state' | 'current'>;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* JSX Types
|
|
206
|
+
*/
|
|
207
|
+
declare global {
|
|
208
|
+
namespace JSX {
|
|
209
|
+
interface IntrinsicElements {
|
|
210
|
+
[elemName: string]: any;
|
|
211
|
+
collection: CollectionProps<any>;
|
|
212
|
+
switchable: SwitchableProps<any>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
interface Element {
|
|
216
|
+
children?: JSX.Element;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export type { CollectionProps, Component, Event, Filter, Lense, RootComponent, SortFunction, SortObject, SwitchableProps };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import isolate from '@cycle/isolate';
|
|
2
2
|
import { makeCollection, StateSource, withState } from '@cycle/state';
|
|
3
|
+
import { h, makeDOMDriver } from '@cycle/dom';
|
|
4
|
+
export * from '@cycle/dom';
|
|
3
5
|
import xs$1, { Stream as Stream$1 } from 'xstream';
|
|
4
6
|
export { default as xs } from 'xstream';
|
|
5
7
|
import { setup } from '@cycle/run';
|
|
6
|
-
import { makeDOMDriver } from '@cycle/dom';
|
|
7
|
-
export * from '@cycle/dom';
|
|
8
8
|
|
|
9
9
|
function collection(component, stateLense, opts={}) {
|
|
10
10
|
const {
|
|
@@ -66,6 +66,13 @@ function collection(component, stateLense, opts={}) {
|
|
|
66
66
|
return isolate(makeCollection(collectionOpts), isolateOpts)(sources)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
const Collection = (props) => {
|
|
70
|
+
const { children, ...sanitizedProps } = props;
|
|
71
|
+
return h('collection', { props: sanitizedProps }, children)
|
|
72
|
+
};
|
|
73
|
+
Collection.label = 'collection';
|
|
74
|
+
Collection.preventInstantiation = true;
|
|
75
|
+
|
|
69
76
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
70
77
|
|
|
71
78
|
var dropRepeats$1 = {};
|
|
@@ -2845,6 +2852,13 @@ function _switchable (factories, sources, name$, switched=['DOM'], stateSourceNa
|
|
|
2845
2852
|
return switchedSinks
|
|
2846
2853
|
}
|
|
2847
2854
|
|
|
2855
|
+
const Switchable = (props) => {
|
|
2856
|
+
const { children, ...sanitizedProps } = props;
|
|
2857
|
+
return h('switchable', { props: sanitizedProps }, children)
|
|
2858
|
+
};
|
|
2859
|
+
Switchable.label = 'switchable';
|
|
2860
|
+
Switchable.preventInstantiation = true;
|
|
2861
|
+
|
|
2848
2862
|
var delay$1 = {};
|
|
2849
2863
|
|
|
2850
2864
|
Object.defineProperty(delay$1, "__esModule", { value: true });
|
|
@@ -3276,7 +3290,8 @@ class Component {
|
|
|
3276
3290
|
const props$ = sources.props$;
|
|
3277
3291
|
if (props$) {
|
|
3278
3292
|
this.sources.props$ = props$.map(val => {
|
|
3279
|
-
|
|
3293
|
+
const { sygnalFactory, sygnalOptions, ...sanitizedProps } = val;
|
|
3294
|
+
this.currentProps = sanitizedProps;
|
|
3280
3295
|
return val
|
|
3281
3296
|
});
|
|
3282
3297
|
}
|
|
@@ -3420,7 +3435,7 @@ class Component {
|
|
|
3420
3435
|
}
|
|
3421
3436
|
|
|
3422
3437
|
const state$ = this.sources[this.stateSourceName]?.stream.startWith({}).compose(_default$5(objIsEqual)) || xs$1.never();
|
|
3423
|
-
const parentContext$ = this.sources.__parentContext
|
|
3438
|
+
const parentContext$ = this.sources.__parentContext$?.startWith({}).compose(_default$5(objIsEqual)) || xs$1.of({});
|
|
3424
3439
|
if (this.context && !isObj(this.context)) {
|
|
3425
3440
|
console.error(`[${this.name}] Context must be an object mapping names to values of functions: ignoring provided ${ typeof this.context }`);
|
|
3426
3441
|
}
|
|
@@ -3610,7 +3625,11 @@ class Component {
|
|
|
3610
3625
|
const renderParameters$ = this.collectRenderParameters();
|
|
3611
3626
|
|
|
3612
3627
|
this.vdom$ = renderParameters$
|
|
3613
|
-
.map(
|
|
3628
|
+
.map(params => {
|
|
3629
|
+
const { props, state, children, context, ...peers } = params;
|
|
3630
|
+
const { sygnalFactory, sygnalOptions, ...sanitizedProps} = props || {};
|
|
3631
|
+
return this.view({ ...sanitizedProps, state, children, context, peers }, state, context, peers)
|
|
3632
|
+
})
|
|
3614
3633
|
.compose(this.log('View rendered'))
|
|
3615
3634
|
.map(vDom => vDom || { sel: 'div', data: {}, children: [] })
|
|
3616
3635
|
.compose(this.instantiateSubComponents.bind(this))
|
|
@@ -3653,20 +3672,22 @@ class Component {
|
|
|
3653
3672
|
this.log(`<${ name }> Triggered a next() action: <${ type }> ${ delay }ms delay`, true);
|
|
3654
3673
|
};
|
|
3655
3674
|
|
|
3656
|
-
const
|
|
3675
|
+
const props = { ...this.currentProps, children: this.currentChildren, context: this.currentContext };
|
|
3657
3676
|
|
|
3658
3677
|
let data = action.data;
|
|
3659
3678
|
if (isStateSink) {
|
|
3660
3679
|
return (state) => {
|
|
3661
3680
|
const _state = this.isSubComponent ? this.currentState : state;
|
|
3662
3681
|
const enhancedState = this.addCalculated(_state);
|
|
3663
|
-
|
|
3682
|
+
props.state = enhancedState;
|
|
3683
|
+
const newState = reducer(enhancedState, data, next, props);
|
|
3664
3684
|
if (newState == ABORT$1) return _state
|
|
3665
3685
|
return this.cleanupCalculated(newState)
|
|
3666
3686
|
}
|
|
3667
3687
|
} else {
|
|
3668
3688
|
const enhancedState = this.addCalculated(this.currentState);
|
|
3669
|
-
|
|
3689
|
+
props.state = enhancedState;
|
|
3690
|
+
const reduced = reducer(enhancedState, data, next, props);
|
|
3670
3691
|
const type = typeof reduced;
|
|
3671
3692
|
if (isObj(reduced) || ['string', 'number', 'boolean', 'function'].includes(type)) return reduced
|
|
3672
3693
|
if (type == 'undefined') {
|
|
@@ -4760,8 +4781,8 @@ function run(app, drivers={}, options={}) {
|
|
|
4760
4781
|
/**
|
|
4761
4782
|
* return a validated and properly separated string of CSS class names from any number of strings, arrays, and objects
|
|
4762
4783
|
*
|
|
4763
|
-
* @param {...String|Array|Object} args any number of strings or arrays with valid CSS class names, or objects where the keys are valid class names and the values evaluate to true or false
|
|
4764
|
-
* @return {String} list of `active` classes separated by spaces
|
|
4784
|
+
* @param { ...String | Array | Object } args any number of strings or arrays with valid CSS class names, or objects where the keys are valid class names and the values evaluate to true or false
|
|
4785
|
+
* @return { String } list of `active` classes separated by spaces
|
|
4765
4786
|
*
|
|
4766
4787
|
* any `string` or `array` arguments are simply validated and appended to the result
|
|
4767
4788
|
* `objects` will evaluate the values (which can be booleans or functions), and the keys with `thruthy` values will be validated and appended to the result
|
|
@@ -5122,4 +5143,4 @@ sampleCombine = function sampleCombine() {
|
|
|
5122
5143
|
};
|
|
5123
5144
|
var _default = sampleCombine$1.default = sampleCombine;
|
|
5124
5145
|
|
|
5125
|
-
export { ABORT$1 as ABORT, classes, collection, component, _default$2 as debounce, _default$4 as delay, driverFromAsync, _default$5 as dropRepeats, processForm, run, _default as sampleCombine, switchable, _default$1 as throttle };
|
|
5146
|
+
export { ABORT$1 as ABORT, Collection, Switchable, classes, collection, component, _default$2 as debounce, _default$4 as delay, driverFromAsync, _default$5 as dropRepeats, processForm, run, _default as sampleCombine, switchable, _default$1 as throttle };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import _extend from 'extend';
|
|
2
|
+
|
|
3
|
+
const undefinedv = (v) => v === undefined;
|
|
4
|
+
|
|
5
|
+
const number = (v) => typeof v === 'number';
|
|
6
|
+
|
|
7
|
+
const string = (v) => typeof v === 'string';
|
|
8
|
+
|
|
9
|
+
const text = (v) => string(v) || number(v);
|
|
10
|
+
|
|
11
|
+
const array = (v) => Array.isArray(v);
|
|
12
|
+
|
|
13
|
+
const object = (v) => typeof v === 'object' && v !== null;
|
|
14
|
+
|
|
15
|
+
const fun = (v) => typeof v === 'function';
|
|
16
|
+
|
|
17
|
+
const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
|
|
18
|
+
|
|
19
|
+
const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
|
|
20
|
+
polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
|
|
21
|
+
|
|
22
|
+
const svg = (v) => v.sel in svgPropsMap;
|
|
23
|
+
|
|
24
|
+
// TODO: stop using extend here
|
|
25
|
+
|
|
26
|
+
const extend = (...objs) => _extend(true, ...objs);
|
|
27
|
+
|
|
28
|
+
const assign = (...objs) => _extend(false, ...objs);
|
|
29
|
+
|
|
30
|
+
const reduceDeep = (arr, fn, initial) => {
|
|
31
|
+
let result = initial;
|
|
32
|
+
for (let i = 0; i < arr.length; i++) {
|
|
33
|
+
const value = arr[i];
|
|
34
|
+
if (array(value)) {
|
|
35
|
+
result = reduceDeep(value, fn, result);
|
|
36
|
+
} else {
|
|
37
|
+
result = fn(result, value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const mapObject = (obj, fn) => Object.keys(obj).map(
|
|
44
|
+
(key) => fn(key, obj[key])
|
|
45
|
+
).reduce(
|
|
46
|
+
(acc, curr) => extend(acc, curr),
|
|
47
|
+
{}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const deepifyKeys = (obj, modules) => mapObject(obj,
|
|
51
|
+
(key, val) => {
|
|
52
|
+
const dashIndex = key.indexOf('-');
|
|
53
|
+
if (dashIndex > -1 && modules[key.slice(0, dashIndex)] !== undefined) {
|
|
54
|
+
const moduleData = {
|
|
55
|
+
[key.slice(dashIndex + 1)]: val
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
[key.slice(0, dashIndex)]: moduleData
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { [key]: val }
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const omit = (key, obj) => mapObject(obj,
|
|
66
|
+
(mod, data) => mod !== key ? ({ [mod]: data }) : {}
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Const fnName = (...params) => guard ? default : ...
|
|
70
|
+
|
|
71
|
+
const createTextElement = (text$1) => !text(text$1) ? undefined : {
|
|
72
|
+
text: text$1,
|
|
73
|
+
sel: undefined,
|
|
74
|
+
data: undefined,
|
|
75
|
+
children: undefined,
|
|
76
|
+
elm: undefined,
|
|
77
|
+
key: undefined
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const considerSvg = (vnode) => !svg(vnode) ? vnode :
|
|
81
|
+
assign(vnode,
|
|
82
|
+
{ data: omit('props', extend(vnode.data,
|
|
83
|
+
{ ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
|
|
84
|
+
{ class: vnode.data.props ? vnode.data.props.className : undefined }
|
|
85
|
+
)) }
|
|
86
|
+
)) },
|
|
87
|
+
{ children: undefinedv(vnode.children) ? undefined :
|
|
88
|
+
vnode.children.map((child) => considerSvg(child))
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const rewrites = {
|
|
93
|
+
for: 'attrs',
|
|
94
|
+
role: 'attrs',
|
|
95
|
+
tabindex: 'attrs',
|
|
96
|
+
'aria-*': 'attrs',
|
|
97
|
+
key: null
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const rewriteModules = (data, modules) => mapObject(data, (key, val) => {
|
|
101
|
+
const inner = { [key]: val };
|
|
102
|
+
if (rewrites[key] && modules[rewrites[key]] !== undefined) {
|
|
103
|
+
return { [rewrites[key]]: inner }
|
|
104
|
+
}
|
|
105
|
+
if (rewrites[key] === null) {
|
|
106
|
+
return {}
|
|
107
|
+
}
|
|
108
|
+
const keys = Object.keys(rewrites);
|
|
109
|
+
for (let i = 0; i < keys.length; i++) {
|
|
110
|
+
const k = keys[i];
|
|
111
|
+
if (k.charAt(k.length - 1) === '*' && key.indexOf(k.slice(0, -1)) === 0 && modules[rewrites[k]] !== undefined) {
|
|
112
|
+
return { [rewrites[k]]: inner }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (modules[key] !== undefined) {
|
|
116
|
+
return { [modules[key] ? modules[key] : key]: val }
|
|
117
|
+
}
|
|
118
|
+
if (modules.props !== undefined) {
|
|
119
|
+
return { props: inner }
|
|
120
|
+
}
|
|
121
|
+
return inner
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const sanitizeData = (data, modules) => considerSvg(rewriteModules(deepifyKeys(data, modules), modules));
|
|
125
|
+
|
|
126
|
+
const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
|
|
127
|
+
|
|
128
|
+
const sanitizeChildren = (children) => reduceDeep(children, (acc, child) => {
|
|
129
|
+
const vnode = vnode$1(child) ? child : createTextElement(child);
|
|
130
|
+
acc.push(vnode);
|
|
131
|
+
return acc
|
|
132
|
+
}
|
|
133
|
+
, []);
|
|
134
|
+
|
|
135
|
+
const defaultModules = {
|
|
136
|
+
attrs: '',
|
|
137
|
+
props: '',
|
|
138
|
+
class: '',
|
|
139
|
+
data: 'dataset',
|
|
140
|
+
style: '',
|
|
141
|
+
hook: '',
|
|
142
|
+
on: ''
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const createElementWithModules = (modules) => {
|
|
146
|
+
return (sel, data, ...children) => {
|
|
147
|
+
if (typeof sel === 'undefined') {
|
|
148
|
+
sel = 'UNDEFINED';
|
|
149
|
+
console.error('JSX Error: Capitalized HTML element without corresponding factory function. Components with names where the first letter is capital MUST be defined or included at the parent component\'s file scope.');
|
|
150
|
+
}
|
|
151
|
+
if (fun(sel)) {
|
|
152
|
+
if (sel.name === 'Fragment') {
|
|
153
|
+
return sel(data || {}, children)
|
|
154
|
+
}
|
|
155
|
+
data ||= {};
|
|
156
|
+
if (!sel.isSygnalComponent) {
|
|
157
|
+
const name = sel.componentName || sel.label || sel.name || 'FUNCTION_COMPONENT';
|
|
158
|
+
const view = sel;
|
|
159
|
+
const { model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug } = sel;
|
|
160
|
+
const options = { name, view, model, intent, hmrActions, context, peers, components, initialState, calculated, storeCalculatedInState, DOMSourceName, stateSourceName, debug };
|
|
161
|
+
data.sygnalOptions = options;
|
|
162
|
+
sel = name;
|
|
163
|
+
} else {
|
|
164
|
+
const factory = sel;
|
|
165
|
+
sel = sel.componentName || sel.label || sel.name || 'sygnal-factory';
|
|
166
|
+
data.sygnalFactory = factory;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const text = sanitizeText(children);
|
|
170
|
+
return considerSvg({
|
|
171
|
+
sel,
|
|
172
|
+
data: data ? sanitizeData(data, modules) : {},
|
|
173
|
+
children: typeof text !== 'undefined' ? createTextElement(text) : sanitizeChildren(children),
|
|
174
|
+
text,
|
|
175
|
+
elm: undefined,
|
|
176
|
+
key: data ? data.key : undefined
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const createElement = createElementWithModules(defaultModules);
|
|
182
|
+
|
|
183
|
+
function vnode(sel, data, children, text, elm) {
|
|
184
|
+
const key = data === undefined ? undefined : data.key;
|
|
185
|
+
return { sel, data, children, text, elm, key };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* eslint-disable @typescript-eslint/no-namespace, import/export */
|
|
189
|
+
function Fragment(data, ...children) {
|
|
190
|
+
const flatChildren = flattenAndFilter(children, []);
|
|
191
|
+
if (flatChildren.length === 1 &&
|
|
192
|
+
!flatChildren[0].sel &&
|
|
193
|
+
flatChildren[0].text) {
|
|
194
|
+
// only child is a simple text node, pass as text for a simpler vtree
|
|
195
|
+
return vnode(undefined, undefined, undefined, flatChildren[0].text, undefined);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
return vnode(undefined, data !== null && data !== void 0 ? data : {}, flatChildren, undefined, undefined);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function flattenAndFilter(children, flattened) {
|
|
202
|
+
for (const child of children) {
|
|
203
|
+
// filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
|
|
204
|
+
if (child !== undefined &&
|
|
205
|
+
child !== null &&
|
|
206
|
+
child !== false &&
|
|
207
|
+
child !== "") {
|
|
208
|
+
if (Array.isArray(child)) {
|
|
209
|
+
flattenAndFilter(child, flattened);
|
|
210
|
+
}
|
|
211
|
+
else if (typeof child === "string" ||
|
|
212
|
+
typeof child === "number" ||
|
|
213
|
+
typeof child === "boolean") {
|
|
214
|
+
flattened.push(vnode(undefined, undefined, undefined, String(child), undefined));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
flattened.push(child);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return flattened;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export { Fragment, createElement as jsxDEV };
|