sygnal 5.1.4 → 5.2.0
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/README.md +8 -7
- package/dist/astro/client.cjs.js +25 -10
- package/dist/astro/client.mjs +25 -10
- package/dist/index.cjs.js +32 -10
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +32 -10
- package/dist/sygnal.min.js +1 -1
- package/package.json +1 -1
- package/src/component.ts +18 -11
- package/src/extra/run.ts +4 -0
- package/src/extra/testing.ts +4 -0
- package/src/index.d.ts +2 -1
package/package.json
CHANGED
package/src/component.ts
CHANGED
|
@@ -26,6 +26,7 @@ const ENVIRONMENT: any =
|
|
|
26
26
|
const BOOTSTRAP_ACTION = 'BOOTSTRAP';
|
|
27
27
|
const INITIALIZE_ACTION = 'INITIALIZE';
|
|
28
28
|
const HYDRATE_ACTION = 'HYDRATE';
|
|
29
|
+
const DISPOSE_ACTION = 'DISPOSE';
|
|
29
30
|
const PARENT_SINK_NAME = 'PARENT';
|
|
30
31
|
const CHILD_SOURCE_NAME = 'CHILD';
|
|
31
32
|
const READY_SINK_NAME = 'READY';
|
|
@@ -446,8 +447,14 @@ class Component {
|
|
|
446
447
|
}
|
|
447
448
|
|
|
448
449
|
dispose(): void {
|
|
449
|
-
//
|
|
450
|
-
|
|
450
|
+
// Fire the DISPOSE built-in action so model handlers can run cleanup logic
|
|
451
|
+
const hasDispose = this.model && (this.model[DISPOSE_ACTION] || Object.keys(this.model).some(k => k.includes('|') && k.split('|')[0].trim() === DISPOSE_ACTION))
|
|
452
|
+
if (hasDispose && this.action$ && typeof this.action$.shamefullySendNext === 'function') {
|
|
453
|
+
try {
|
|
454
|
+
this.action$.shamefullySendNext({ type: DISPOSE_ACTION })
|
|
455
|
+
} catch (_) {}
|
|
456
|
+
}
|
|
457
|
+
// Signal disposal to the component via dispose$ stream (for advanced use cases)
|
|
451
458
|
if (this._disposeListener) {
|
|
452
459
|
try {
|
|
453
460
|
this._disposeListener.next(true)
|
|
@@ -455,7 +462,7 @@ class Component {
|
|
|
455
462
|
} catch (_) {}
|
|
456
463
|
this._disposeListener = null
|
|
457
464
|
}
|
|
458
|
-
// Tear down streams on next microtask to allow
|
|
465
|
+
// Tear down streams on next microtask to allow DISPOSE/cleanup actions to process
|
|
459
466
|
setTimeout(() => {
|
|
460
467
|
// Complete the action$ stream to stop the entire component cycle
|
|
461
468
|
if (this.action$ && typeof this.action$.shamefullySendComplete === 'function') {
|
|
@@ -1598,7 +1605,7 @@ class Component {
|
|
|
1598
1605
|
if (vdom$.length === 0) return xs.of(root)
|
|
1599
1606
|
|
|
1600
1607
|
// Track READY state on the component instance (persists across folds)
|
|
1601
|
-
for (const [id, val] of entries) {
|
|
1608
|
+
for (const [id, val] of entries as [string, any]) {
|
|
1602
1609
|
if (this._childReadyState[id] !== undefined) continue // already tracking
|
|
1603
1610
|
const readySink = val.sink$[READY_SINK_NAME]
|
|
1604
1611
|
if (readySink) {
|
|
@@ -2117,11 +2124,11 @@ function __sortFunctionFromObj(item: Record<string, any>): ((a: any, b: any) =>
|
|
|
2117
2124
|
}
|
|
2118
2125
|
let ascending = true
|
|
2119
2126
|
if (typeof directionRaw === 'string') {
|
|
2120
|
-
if (!['asc', '
|
|
2121
|
-
console.error('Sort object string values must be asc or
|
|
2127
|
+
if (!['asc', 'desc'].includes(directionRaw.toLowerCase())) {
|
|
2128
|
+
console.error('Sort object string values must be asc or desc:', item)
|
|
2122
2129
|
return undefined
|
|
2123
2130
|
}
|
|
2124
|
-
ascending = directionRaw.toLowerCase()
|
|
2131
|
+
ascending = directionRaw.toLowerCase() !== 'desc'
|
|
2125
2132
|
}
|
|
2126
2133
|
if (typeof directionRaw === 'number') {
|
|
2127
2134
|
if (directionRaw !== 1 && directionRaw !== -1) {
|
|
@@ -2139,9 +2146,9 @@ function sortFunctionFromProp(sortProp: any): ((a: any, b: any) => number) | und
|
|
|
2139
2146
|
// if function do nothing
|
|
2140
2147
|
if (propType === 'function') return sortProp
|
|
2141
2148
|
if (propType === 'string') {
|
|
2142
|
-
// if passed either 'asc' or '
|
|
2143
|
-
if (sortProp.toLowerCase() === 'asc' || sortProp.toLowerCase() === '
|
|
2144
|
-
const ascending = sortProp.toLowerCase()
|
|
2149
|
+
// if passed either 'asc' or 'desc' sort on the entire item
|
|
2150
|
+
if (sortProp.toLowerCase() === 'asc' || sortProp.toLowerCase() === 'desc') {
|
|
2151
|
+
const ascending = sortProp.toLowerCase() !== 'desc'
|
|
2145
2152
|
return (a, b) => __baseSort(a, b, ascending)
|
|
2146
2153
|
}
|
|
2147
2154
|
// assume it's a field/property name, and sort it ascending
|
|
@@ -2150,7 +2157,7 @@ function sortFunctionFromProp(sortProp: any): ((a: any, b: any) => number) | und
|
|
|
2150
2157
|
} else if (Array.isArray(sortProp)) {
|
|
2151
2158
|
const sorters = sortProp.map(item => {
|
|
2152
2159
|
if (typeof item === 'function') return item
|
|
2153
|
-
if (typeof item === 'string' && !['asc', '
|
|
2160
|
+
if (typeof item === 'string' && !['asc', 'desc'].includes(item.toLowerCase())) return (a: any, b: any) => __baseSort(a[item], b[item], true)
|
|
2154
2161
|
if (isObj(item)) {
|
|
2155
2162
|
return __sortFunctionFromObj(item)
|
|
2156
2163
|
}
|
package/src/extra/run.ts
CHANGED
|
@@ -118,6 +118,10 @@ export default function run(
|
|
|
118
118
|
(sources as any).STATE.stream.removeListener(persistListener);
|
|
119
119
|
persistListener = null;
|
|
120
120
|
}
|
|
121
|
+
// Trigger the component's dispose() which fires the DISPOSE action and dispose$ stream
|
|
122
|
+
if (typeof (sinks as any).__dispose === 'function') {
|
|
123
|
+
try { (sinks as any).__dispose(); } catch (_) {}
|
|
124
|
+
}
|
|
121
125
|
rawDispose();
|
|
122
126
|
};
|
|
123
127
|
|
package/src/extra/testing.ts
CHANGED
|
@@ -249,6 +249,10 @@ export function renderComponent(
|
|
|
249
249
|
} catch (_) {}
|
|
250
250
|
stateListener = null;
|
|
251
251
|
}
|
|
252
|
+
// Trigger the component's dispose() which fires the DISPOSE action and dispose$ stream
|
|
253
|
+
if (typeof (sinks as any).__dispose === 'function') {
|
|
254
|
+
try { (sinks as any).__dispose(); } catch (_) {}
|
|
255
|
+
}
|
|
252
256
|
rawDispose();
|
|
253
257
|
};
|
|
254
258
|
|
package/src/index.d.ts
CHANGED
|
@@ -117,6 +117,7 @@ type WithDefaultActions<STATE, ACTIONS> = ACTIONS & {
|
|
|
117
117
|
BOOTSTRAP?: never;
|
|
118
118
|
INITIALIZE?: STATE;
|
|
119
119
|
HYDRATE?: any;
|
|
120
|
+
DISPOSE?: never;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
type ComponentModel<STATE, PROPS, DRIVERS, ACTIONS, CALCULATED, SINK_RETURNS extends NonStateSinkReturns = {}> = keyof ACTIONS extends never
|
|
@@ -239,7 +240,7 @@ export type Filter<ITEM = any> = (item: ITEM) => boolean
|
|
|
239
240
|
export type SortFunction<ITEM = any> = (a: ITEM, b: ITEM) => number
|
|
240
241
|
|
|
241
242
|
export type SortObject<ITEM = any> = {
|
|
242
|
-
[field: string]: 'asc' | '
|
|
243
|
+
[field: string]: 'asc' | 'desc' | SortFunction<ITEM>
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
/**
|