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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sygnal",
3
- "version": "5.1.4",
3
+ "version": "5.2.0",
4
4
  "description": "An intuitive framework for building fast and small components or applications based on Cycle.js",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
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
- // Signal disposal to the component via dispose$ stream
450
- // This fires FIRST so CLEANUP actions in the model can process
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 CLEANUP actions to process
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', 'dec'].includes(directionRaw.toLowerCase())) {
2121
- console.error('Sort object string values must be asc or dec:', item)
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() === 'asc'
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 'dec' sort on the entire item
2143
- if (sortProp.toLowerCase() === 'asc' || sortProp.toLowerCase() === 'dec') {
2144
- const ascending = sortProp.toLowerCase() === 'asc'
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', 'dec'].includes(item.toLowerCase())) return (a: any, b: any) => __baseSort(a[item], b[item], true)
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
 
@@ -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' | 'dec' | SortFunction<ITEM>
243
+ [field: string]: 'asc' | 'desc' | SortFunction<ITEM>
243
244
  }
244
245
 
245
246
  /**