@wavemaker/app-ng-runtime 11.14.1-3.6306 → 11.14.1-32.647748

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.
Files changed (67) hide show
  1. package/components/base/bundles/index.umd.js +6 -22
  2. package/components/base/esm2022/pipes/custom-pipes.mjs +1 -1
  3. package/components/base/esm2022/widgets/common/base/base.component.mjs +8 -24
  4. package/components/base/fesm2022/index.mjs +7 -23
  5. package/components/base/fesm2022/index.mjs.map +1 -1
  6. package/components/chart/bundles/index.umd.js +2 -2
  7. package/components/chart/esm2022/chart.utils.mjs +3 -3
  8. package/components/chart/fesm2022/index.mjs +2 -2
  9. package/components/chart/fesm2022/index.mjs.map +1 -1
  10. package/components/containers/wizard/bundles/index.umd.js +21 -2
  11. package/components/containers/wizard/esm2022/wizard-step/wizard-step.component.mjs +3 -1
  12. package/components/containers/wizard/esm2022/wizard.component.mjs +20 -3
  13. package/components/containers/wizard/fesm2022/index.mjs +21 -2
  14. package/components/containers/wizard/fesm2022/index.mjs.map +1 -1
  15. package/components/containers/wizard/wizard-step/wizard-step.component.d.ts +2 -0
  16. package/components/data/pagination/bundles/index.umd.js +6 -1
  17. package/components/data/pagination/esm2022/pagination.component.mjs +7 -2
  18. package/components/data/pagination/fesm2022/index.mjs +6 -1
  19. package/components/data/pagination/fesm2022/index.mjs.map +1 -1
  20. package/components/data/table/bundles/index.umd.js +331 -23
  21. package/components/data/table/esm2022/table-action/table-action.directive.mjs +8 -1
  22. package/components/data/table/esm2022/table-column/table-column.directive.mjs +108 -4
  23. package/components/data/table/esm2022/table-column-group/table-column-group.directive.mjs +9 -1
  24. package/components/data/table/esm2022/table-cud.directive.mjs +22 -5
  25. package/components/data/table/esm2022/table-filter.directive.mjs +43 -4
  26. package/components/data/table/esm2022/table-row/table-row.directive.mjs +8 -1
  27. package/components/data/table/esm2022/table-row-action/table-row-action.directive.mjs +8 -1
  28. package/components/data/table/esm2022/table.component.mjs +134 -15
  29. package/components/data/table/fesm2022/index.mjs +333 -25
  30. package/components/data/table/fesm2022/index.mjs.map +1 -1
  31. package/components/data/table/table-action/table-action.directive.d.ts +3 -2
  32. package/components/data/table/table-column/table-column.directive.d.ts +3 -2
  33. package/components/data/table/table-column-group/table-column-group.directive.d.ts +3 -2
  34. package/components/data/table/table-cud.directive.d.ts +3 -1
  35. package/components/data/table/table-filter.directive.d.ts +3 -1
  36. package/components/data/table/table-row/table-row.directive.d.ts +3 -2
  37. package/components/data/table/table-row-action/table-row-action.directive.d.ts +3 -2
  38. package/components/data/table/table.component.d.ts +10 -0
  39. package/components/page/default/bundles/index.umd.js +1 -0
  40. package/components/page/default/esm2022/page.directive.mjs +2 -1
  41. package/components/page/default/fesm2022/index.mjs +1 -0
  42. package/components/page/default/fesm2022/index.mjs.map +1 -1
  43. package/core/bundles/index.umd.js +185 -330
  44. package/core/esm2022/public_api.mjs +2 -2
  45. package/core/esm2022/utils/watcher.mjs +189 -328
  46. package/core/fesm2022/index.mjs +192 -330
  47. package/core/fesm2022/index.mjs.map +1 -1
  48. package/core/public_api.d.ts +1 -1
  49. package/core/utils/watcher.d.ts +5 -26
  50. package/locales/moment-timezone/moment-timezone-with-data.js +179 -27
  51. package/npm-shrinkwrap.json +2 -2
  52. package/package-lock.json +2 -2
  53. package/package.json +1 -1
  54. package/runtime/base/bundles/index.umd.js +20 -46
  55. package/runtime/base/components/base-prefab.component.d.ts +6 -4
  56. package/runtime/base/esm2022/components/app-component/app.component.mjs +2 -7
  57. package/runtime/base/esm2022/components/base-page.component.mjs +2 -8
  58. package/runtime/base/esm2022/components/base-partial.component.mjs +3 -11
  59. package/runtime/base/esm2022/components/base-prefab.component.mjs +21 -21
  60. package/runtime/base/esm2022/components/base-spa-page.component.mjs +2 -9
  61. package/runtime/base/fesm2022/index.mjs +21 -47
  62. package/runtime/base/fesm2022/index.mjs.map +1 -1
  63. package/runtime/dynamic/bundles/index.umd.js +4 -0
  64. package/runtime/dynamic/esm2022/app/app.config.mjs +6 -2
  65. package/runtime/dynamic/fesm2022/index.mjs +5 -1
  66. package/runtime/dynamic/fesm2022/index.mjs.map +1 -1
  67. package/scripts/datatable/datatable.js +336 -33
@@ -1,5 +1,5 @@
1
1
  import { Attribute, ImplicitReceiver, PropertyRead, LiteralPrimitive, LiteralArray, LiteralMap, PropertyWrite, KeyedRead, PrefixNot, Unary, Binary, Conditional, Call, Chain, BindingPipe, Parser, Lexer } from '@angular/compiler';
2
- import { isArray, startsWith, includes, get, flatten, isEqual, clone, isObject as isObject$1, camelCase, split, map, attempt, isError, isFunction, isDate, isString, cloneDeep, identity, intersection, omit, keys, toLower, replace as replace$1, forEach, trim, isEqualWith, every, indexOf, isNumber, filter, isUndefined, isNull, noop as noop$2, toUpper, assign, merge, isEmpty, debounce as debounce$1, isNil } from 'lodash-es';
2
+ import { isArray, startsWith, includes, get, camelCase, split, map, attempt, isError, isFunction, isDate, isString, cloneDeep, identity, intersection, omit, isEqual, keys, toLower, replace as replace$1, forEach, trim, isEqualWith, every, indexOf, isNumber, filter, isUndefined, isNull, noop as noop$2, toUpper, assign, clone, isObject as isObject$1, merge, isEmpty, debounce as debounce$1, isNil } from 'lodash-es';
3
3
  import { Subject } from 'rxjs';
4
4
  import X2JS from 'x2js';
5
5
  import * as momentLib from 'moment-timezone/moment-timezone';
@@ -1432,11 +1432,11 @@ const CURRENCY_INFO = {
1432
1432
  }
1433
1433
  };
1434
1434
 
1435
- const $RAF = window.requestAnimationFrame;
1435
+ const $RAF$1 = window.requestAnimationFrame;
1436
1436
  const $RAFQueue = [];
1437
1437
  const invokeLater = fn => {
1438
1438
  if (!$RAFQueue.length) {
1439
- $RAF(() => {
1439
+ $RAF$1(() => {
1440
1440
  $RAFQueue.forEach(f => f());
1441
1441
  $RAFQueue.length = 0;
1442
1442
  });
@@ -2173,25 +2173,14 @@ const getFnForEventExpr = (expr) => {
2173
2173
  return fnExecutor(expr, ExpressionType.Action);
2174
2174
  };
2175
2175
 
2176
- // Constants
2177
- const WIDGET_ID_REGEX = /^(widget-[^_]+)/;
2178
- const WIDGET_PROPERTY_REGEX = /^widget-[^_]+_(.+)$/;
2179
- const ARRAY_INDEX_PLACEHOLDER = '[$i]';
2180
- const ARRAY_INDEX_ZERO = '[0]';
2181
- const DEBOUNCE_WAIT = 100;
2182
- const MAX_WATCH_CYCLES = 5;
2183
2176
  const registry = new Map();
2184
2177
  const watchIdGenerator = new IDGenerator('watch-id-');
2185
- const FIRST_TIME_WATCH = Object.freeze({});
2186
- // State
2178
+ const FIRST_TIME_WATCH = {};
2179
+ Object.freeze(FIRST_TIME_WATCH);
2180
+ const isFirstTimeChange = v => v === FIRST_TIME_WATCH;
2187
2181
  let muted = false;
2188
- let changedByWatch = false;
2189
- let skipWatchers = false;
2190
- let ngZone;
2191
2182
  let appRef;
2192
- // Utility functions
2193
- const isFirstTimeChange = (v) => v === FIRST_TIME_WATCH;
2194
- const debounce = (fn, wait = DEBOUNCE_WAIT) => {
2183
+ const debounce = (fn, wait = 50) => {
2195
2184
  let timeout;
2196
2185
  return (...args) => {
2197
2186
  window['__zone_symbol__clearTimeout'](timeout);
@@ -2203,362 +2192,230 @@ const muteWatchers = () => {
2203
2192
  };
2204
2193
  const unMuteWatchers = () => {
2205
2194
  muted = false;
2206
- triggerWatchers();
2207
- };
2208
- /**
2209
- * Extracts widget ID from identifier (e.g., "widget-id23_eventsource" -> "widget-id23")
2210
- */
2211
- const getWidgetId = (identifier) => {
2212
- if (!identifier || typeof identifier !== 'string') {
2213
- return null;
2214
- }
2215
- const match = identifier.match(WIDGET_ID_REGEX);
2216
- return match ? match[1] : null;
2217
- };
2218
- /**
2219
- * Extracts property name from identifier (e.g., "widget-id23_eventsource" -> "eventsource")
2220
- */
2221
- const getPropertyName = (identifier) => {
2222
- if (!identifier || typeof identifier !== 'string') {
2223
- return identifier;
2224
- }
2225
- const match = identifier.match(WIDGET_PROPERTY_REGEX);
2226
- return match ? match[1] : identifier;
2195
+ $invokeWatchers(true);
2227
2196
  };
2228
- /**
2229
- * Array consumer wrapper for array-based expressions
2230
- */
2231
2197
  const arrayConsumer = (listenerFn, restExpr, newVal, oldVal) => {
2232
- if (!isArray(newVal)) {
2233
- return;
2234
- }
2235
- let formattedData = newVal.map(datum => findValueOf(datum, restExpr));
2236
- // Flatten if result is array of arrays
2237
- if (isArray(formattedData[0])) {
2238
- formattedData = flatten(formattedData);
2198
+ let data = newVal, formattedData;
2199
+ if (_.isArray(data)) {
2200
+ formattedData = data.map(function (datum) {
2201
+ return findValueOf(datum, restExpr);
2202
+ });
2203
+ // If resulting structure is an array of array, flatten it
2204
+ if (_.isArray(formattedData[0])) {
2205
+ formattedData = _.flatten(formattedData);
2206
+ }
2207
+ listenerFn(formattedData, oldVal);
2239
2208
  }
2240
- listenerFn(formattedData, oldVal);
2241
2209
  };
2242
- /**
2243
- * Updates watch info for array expressions
2244
- */
2245
- const getUpdatedWatchInfo = (expr, acceptsArray, listener) => {
2246
- const regex = /\[\$i\]/g;
2210
+ const getUpdatedWatcInfo = (expr, acceptsArray, listener) => {
2211
+ // listener doesn't accept array
2212
+ // replace all `[$i]` with `[0]` and return the expression
2213
+ let regex = /\[\$i\]/g, $I = '[$i]', $0 = '[0]';
2247
2214
  if (!acceptsArray) {
2248
2215
  return {
2249
- expr: expr.replace(regex, ARRAY_INDEX_ZERO),
2250
- listener
2216
+ 'expr': expr.replace(regex, $0),
2217
+ 'listener': listener
2251
2218
  };
2252
2219
  }
2253
- const lastIndex = expr.lastIndexOf(ARRAY_INDEX_PLACEHOLDER);
2254
- const baseExpr = expr.substring(0, lastIndex).replace(ARRAY_INDEX_PLACEHOLDER, ARRAY_INDEX_ZERO);
2255
- const restExpr = expr.substring(lastIndex + ARRAY_INDEX_PLACEHOLDER.length);
2256
- const arrayConsumerFn = restExpr
2257
- ? arrayConsumer.bind(undefined, listener, restExpr)
2258
- : listener;
2220
+ // listener accepts array
2221
+ // replace all except the last `[$i]` with `[0]` and return the expression.
2222
+ var index = expr.lastIndexOf($I), _expr = expr.substr(0, index).replace($I, $0), restExpr = expr.substr(index + 5), arrayConsumerFn = listener;
2223
+ if (restExpr) {
2224
+ arrayConsumerFn = arrayConsumer.bind(undefined, listener, restExpr);
2225
+ }
2259
2226
  return {
2260
- expr: baseExpr,
2261
- listener: arrayConsumerFn
2227
+ 'expr': _expr,
2228
+ 'listener': arrayConsumerFn
2262
2229
  };
2263
2230
  };
2264
- /**
2265
- * Determines if an expression is static (doesn't need to be watched)
2266
- */
2267
- const STATIC_EXPRESSION_NAMES = [
2268
- "row.getProperty('investment')",
2269
- "row.getProperty('factsheetLink')",
2270
- "row.getProperty('isRebalanceEligible')"
2271
- ];
2272
- const isStaticExpression = (expr) => {
2273
- if (typeof expr !== 'string') {
2274
- return false;
2275
- }
2276
- const trimmedExpr = expr.trim();
2277
- // Expressions that always evaluate to localization strings
2278
- if (trimmedExpr.includes('appLocale')) {
2279
- return true;
2280
- }
2281
- // Hard-coded static expression names
2282
- if (STATIC_EXPRESSION_NAMES.includes(trimmedExpr)) {
2283
- return true;
2284
- }
2285
- return false;
2286
- };
2287
- /**
2288
- * Gets the scope type from the scope object
2289
- */
2290
- const getScopeType = ($scope) => {
2291
- if (!$scope) {
2292
- return null;
2293
- }
2294
- if ($scope.pageName)
2295
- return 'Page';
2296
- if ($scope.prefabName)
2297
- return 'Prefab';
2298
- if ($scope.partialName)
2299
- return 'Partial';
2300
- // Check for App scope
2301
- if ($scope.Variables !== undefined &&
2302
- $scope.Actions !== undefined &&
2303
- !$scope.pageName &&
2304
- !$scope.prefabName &&
2305
- !$scope.partialName) {
2306
- return 'App';
2307
- }
2308
- if ($scope.constructor?.name === 'AppRef') {
2309
- return 'App';
2310
- }
2311
- return null;
2312
- };
2313
- /**
2314
- * Gets scope name based on scope type
2315
- */
2316
- const getScopeName = ($scope, scopeType) => {
2317
- if (!scopeType || !$scope) {
2318
- return null;
2319
- }
2320
- switch (scopeType) {
2321
- case 'Prefab': return $scope.prefabName || null;
2322
- case 'Partial': return $scope.partialName || null;
2323
- case 'Page': return $scope.pageName || null;
2324
- default: return null;
2325
- }
2326
- };
2327
- /**
2328
- * Main watch function
2329
- */
2330
2231
  const $watch = (expr, $scope, $locals, listener, identifier = watchIdGenerator.nextUid(), doNotClone = false, config = {}, isMuted) => {
2331
- // Handle array expressions
2332
- if (expr.includes(ARRAY_INDEX_PLACEHOLDER)) {
2333
- const watchInfo = getUpdatedWatchInfo(expr, config.arrayType || config.isList || false, listener);
2232
+ if (expr.indexOf('[$i]') !== -1) {
2233
+ let watchInfo = getUpdatedWatcInfo(expr, config && (config.arrayType || config.isList), listener);
2334
2234
  expr = watchInfo.expr;
2335
2235
  listener = watchInfo.listener;
2336
2236
  }
2337
- // Handle static expressions
2338
- if (isStaticExpression(expr)) {
2339
- try {
2340
- const fn = $parseExpr(expr);
2341
- const staticValue = fn($scope, $locals);
2342
- listener(staticValue, FIRST_TIME_WATCH);
2343
- }
2344
- catch (e) {
2345
- console.warn(`Error evaluating static expression '${expr}':`, e);
2346
- listener(undefined, FIRST_TIME_WATCH);
2347
- }
2348
- return () => { }; // No-op unsubscribe
2349
- }
2350
2237
  const fn = $parseExpr(expr);
2351
- const scopeType = getScopeType($scope);
2352
- const scopeName = getScopeName($scope, scopeType);
2353
- const watchInfo = {
2354
- fn: fn.bind(null, $scope, $locals),
2238
+ registry.set(identifier, {
2239
+ fn: fn.bind(expr, $scope, $locals),
2355
2240
  listener,
2356
2241
  expr,
2357
2242
  last: FIRST_TIME_WATCH,
2358
2243
  doNotClone,
2359
- isMuted,
2360
- scopeType,
2361
- scopeName
2362
- };
2363
- // Store in registry
2364
- const widgetId = getWidgetId(identifier);
2365
- if (widgetId) {
2366
- const propertyName = getPropertyName(identifier);
2367
- if (!registry.has(widgetId)) {
2368
- registry.set(widgetId, {});
2369
- }
2370
- const widgetGroup = registry.get(widgetId);
2371
- widgetGroup[propertyName] = watchInfo;
2372
- }
2373
- else {
2374
- registry.set(identifier, watchInfo);
2375
- }
2376
- return () => $unwatch(identifier);
2377
- };
2378
- /**
2379
- * Unwatches a single identifier
2380
- */
2381
- const $unwatch = (identifier) => {
2382
- const widgetId = getWidgetId(identifier);
2383
- if (widgetId) {
2384
- const propertyName = getPropertyName(identifier);
2385
- const widgetGroup = registry.get(widgetId);
2386
- if (widgetGroup && typeof widgetGroup === 'object' && !widgetGroup.fn) {
2387
- const watchInfo = widgetGroup[propertyName];
2388
- if (watchInfo) {
2389
- delete widgetGroup[propertyName];
2390
- // Clean up empty widget groups
2391
- if (Object.keys(widgetGroup).length === 0) {
2392
- registry.delete(widgetId);
2393
- }
2394
- return true;
2395
- }
2396
- }
2397
- }
2398
- // Fallback to direct lookup
2399
- if (registry.has(identifier)) {
2400
- registry.delete(identifier);
2401
- return true;
2402
- }
2403
- return false;
2404
- };
2405
- /**
2406
- * Unwatches all watchers for a specific widget ID
2407
- */
2408
- const $unwatchAll = (widgetId) => {
2409
- if (!widgetId || typeof widgetId !== 'string') {
2410
- return 0;
2411
- }
2412
- const widgetGroup = registry.get(widgetId);
2413
- if (widgetGroup && typeof widgetGroup === 'object' && !widgetGroup.fn) {
2414
- const count = Object.keys(widgetGroup).length;
2415
- registry.delete(widgetId);
2416
- return count;
2417
- }
2418
- // Fallback: find all identifiers starting with this widget ID
2419
- let removedCount = 0;
2420
- const identifiersToRemove = [];
2421
- registry.forEach((_, key) => {
2422
- if (key.startsWith(widgetId + '_')) {
2423
- identifiersToRemove.push(key);
2424
- }
2425
- });
2426
- identifiersToRemove.forEach(identifier => {
2427
- if ($unwatch(identifier)) {
2428
- removedCount++;
2429
- }
2244
+ isMuted: isMuted
2430
2245
  });
2431
- return removedCount;
2432
- };
2433
- /**
2434
- * Unwatches all watchers for a specific scope (Page, Prefab, Partial, or App)
2435
- * Now works directly with the main registry instead of separate scoped registries
2436
- */
2437
- const $unwatchAllByScope = (scopeType, scopeName) => {
2438
- if (!scopeType) {
2439
- return 0;
2440
- }
2441
- let removedCount = 0;
2442
- const identifiersToRemove = [];
2443
- registry.forEach((value, key) => {
2444
- // Handle grouped structure (widget groups)
2445
- if (value && typeof value === 'object' && !value.fn) {
2446
- Object.entries(value).forEach(([propertyName, watchInfo]) => {
2447
- if (watchInfo?.scopeType === scopeType &&
2448
- (!scopeName || watchInfo.scopeName === scopeName)) {
2449
- identifiersToRemove.push(`${key}_${propertyName}`);
2450
- }
2451
- });
2452
- }
2453
- else {
2454
- // Direct watchInfo
2455
- const watchInfo = value;
2456
- if (watchInfo?.scopeType === scopeType &&
2457
- (!scopeName || watchInfo.scopeName === scopeName)) {
2458
- identifiersToRemove.push(key);
2459
- }
2460
- }
2461
- });
2462
- // Unwatch all collected identifiers
2463
- identifiersToRemove.forEach(identifier => {
2464
- if ($unwatch(identifier)) {
2465
- removedCount++;
2466
- }
2467
- });
2468
- return removedCount;
2469
- };
2470
- /**
2471
- * Processes a single watch info during trigger cycle
2472
- */
2473
- const processWatchInfo = (watchInfo) => {
2474
- if (!watchInfo?.fn || (watchInfo.isMuted?.() ?? false)) {
2475
- return false;
2476
- }
2477
- let newValue;
2478
- try {
2479
- newValue = watchInfo.fn();
2480
- }
2481
- catch (e) {
2482
- console.warn(`Error executing expression: '${watchInfo.expr}'`, e);
2483
- return false;
2484
- }
2485
- if (isEqual(newValue, watchInfo.last)) {
2486
- return false;
2487
- }
2488
- // Change detected
2489
- changedByWatch = true;
2490
- watchInfo.last = isObject$1(newValue) && !watchInfo.doNotClone
2491
- ? clone(newValue)
2492
- : newValue;
2493
- watchInfo.listener(newValue, watchInfo.last === newValue ? FIRST_TIME_WATCH : watchInfo.last);
2494
- changedByWatch = false;
2495
- return true;
2246
+ return () => $unwatch(identifier);
2496
2247
  };
2497
- /**
2498
- * Triggers all watchers
2499
- */
2500
- const triggerWatchers = (ignoreMuted = false) => {
2248
+ const $unwatch = identifier => registry.delete(identifier);
2249
+ let changedByWatch = false;
2250
+ const $RAF = window.requestAnimationFrame;
2251
+ let ngZone;
2252
+ const triggerWatchers = (ignoreMuted) => {
2501
2253
  if (muted && !ignoreMuted) {
2502
2254
  return;
2503
2255
  }
2256
+ log(".......................triggerWatchers.................................");
2257
+ const limit = 5;
2504
2258
  let pass = 1;
2505
2259
  let changeDetected;
2506
2260
  do {
2507
2261
  changeDetected = false;
2508
- registry.forEach((value) => {
2509
- // Handle grouped structure
2510
- if (value && typeof value === 'object' && !value.fn) {
2511
- Object.values(value).forEach((watchInfo) => {
2512
- if (processWatchInfo(watchInfo)) {
2513
- changeDetected = true;
2514
- }
2515
- });
2262
+ registry.forEach(watchInfo => {
2263
+ if (watchInfo.isMuted && watchInfo.isMuted()) {
2264
+ return;
2516
2265
  }
2517
- else {
2518
- // Direct watchInfo
2519
- if (processWatchInfo(value)) {
2520
- changeDetected = true;
2266
+ const fn = watchInfo.fn;
2267
+ const listener = watchInfo.listener;
2268
+ const ov = watchInfo.last;
2269
+ let nv;
2270
+ try {
2271
+ nv = fn();
2272
+ }
2273
+ catch (e) {
2274
+ console.warn(`error in executing expression: '${watchInfo.expr}'`);
2275
+ }
2276
+ if (!_.isEqual(nv, ov)) {
2277
+ changeDetected = true;
2278
+ changedByWatch = true;
2279
+ watchInfo.last = nv;
2280
+ if (_.isObject(nv) && !watchInfo.doNotClone && nv.__cloneable__ !== false) {
2281
+ watchInfo.last = _.clone(nv);
2521
2282
  }
2283
+ listener(nv, ov);
2284
+ resetChangeFromWatch();
2522
2285
  }
2523
2286
  });
2524
2287
  pass++;
2525
- } while (changeDetected && pass < MAX_WATCH_CYCLES);
2526
- if (changeDetected && pass === MAX_WATCH_CYCLES) {
2527
- console.warn(`Watch cycles exceeded limit of ${MAX_WATCH_CYCLES}`);
2288
+ } while (changeDetected && pass < limit);
2289
+ if (changeDetected && pass === limit) {
2290
+ console.warn(`Number of watch cycles gone above set limit of: ${limit} `);
2528
2291
  }
2529
2292
  };
2530
- // Angular zone integration
2531
- const setNgZone = (zone) => {
2532
- ngZone = zone;
2533
- };
2534
- const setAppRef = (ref) => {
2293
+ const setNgZone = zone => ngZone = zone;
2294
+ const setAppRef = ref => {
2535
2295
  appRef = ref;
2536
2296
  };
2537
2297
  const isChangeFromWatch = () => changedByWatch;
2538
- const resetChangeFromWatch = () => {
2539
- changedByWatch = false;
2540
- };
2541
- // Debounced trigger
2542
- const debouncedTriggerWatchers = debounce(() => {
2543
- skipWatchers = true;
2544
- ngZone.run(() => triggerWatchers());
2545
- }, DEBOUNCE_WAIT);
2298
+ const resetChangeFromWatch = () => changedByWatch = false;
2299
+ window.watchRegistry = registry;
2300
+ let skipWatchers;
2301
+ let scheduled = false, rerunRequested = false, isRunning = false, consecutiveReruns = 0;
2302
+ const MAX_PASSES = 5, DEBOUNCE_TIME = 200, MAX_CONSECUTIVE_RERUNS = 3;
2303
+ window.__WM_DEBUG_WATCHERS__ = false;
2546
2304
  const $invokeWatchers = (force = false, ignoreMuted = false) => {
2547
2305
  if (force) {
2548
2306
  triggerWatchers(ignoreMuted);
2549
2307
  }
2550
2308
  else {
2309
+ scheduleExecution(ignoreMuted);
2310
+ }
2311
+ };
2312
+ function scheduleExecution(ignoreMuted) {
2313
+ if (scheduled) {
2314
+ rerunRequested = true;
2315
+ return;
2316
+ }
2317
+ scheduled = true;
2318
+ // Reset consecutive rerun counter when scheduling from outside
2319
+ // (not from within executeWatchers rerun logic)
2320
+ if (!isRunning) {
2321
+ consecutiveReruns = 0;
2322
+ }
2323
+ debouncedExecute(ignoreMuted);
2324
+ }
2325
+ const debouncedExecute = debounce((ignoreMuted) => {
2326
+ scheduled = false;
2327
+ executeWatchers(ignoreMuted);
2328
+ }, DEBOUNCE_TIME);
2329
+ function executeWatchers(ignoreMuted) {
2330
+ if (isRunning) {
2331
+ rerunRequested = true;
2332
+ return;
2333
+ }
2334
+ isRunning = true;
2335
+ let actuallyChanged = false;
2336
+ ngZone.runOutsideAngular(() => {
2337
+ let pass = 1;
2338
+ let changeDetected;
2339
+ do {
2340
+ changeDetected = false;
2341
+ log(`-------executeWatchers (run #${consecutiveReruns + 1})--------- `);
2342
+ registry.forEach(watchInfo => {
2343
+ if (watchInfo.isMuted && watchInfo.isMuted()) {
2344
+ return;
2345
+ }
2346
+ const fn = watchInfo.fn;
2347
+ const listener = watchInfo.listener;
2348
+ const ov = watchInfo.last;
2349
+ let nv;
2350
+ try {
2351
+ nv = fn();
2352
+ }
2353
+ catch (e) {
2354
+ console.warn(`error in executing expression: '${watchInfo.expr}'`);
2355
+ }
2356
+ if (!_.isEqual(nv, ov)) {
2357
+ changeDetected = true;
2358
+ actuallyChanged = true;
2359
+ changedByWatch = true;
2360
+ watchInfo.last = nv;
2361
+ if (_.isObject(nv) && !watchInfo.doNotClone && nv.__cloneable__ !== false) {
2362
+ watchInfo.last = _.clone(nv);
2363
+ }
2364
+ listener(nv, ov);
2365
+ resetChangeFromWatch();
2366
+ }
2367
+ });
2368
+ pass++;
2369
+ } while (changeDetected && pass < MAX_PASSES);
2370
+ });
2371
+ isRunning = false;
2372
+ // Trigger Angular change detection if watchers actually changed values
2373
+ if (actuallyChanged) {
2374
+ ngZone.run(() => {
2375
+ log(`-------DONE (changes detected)--------- `);
2376
+ });
2377
+ }
2378
+ else {
2379
+ log(`-------DONE (no changes)--------- `);
2380
+ }
2381
+ // 🔥 collapse ALL mid-run triggers into ONE rerun
2382
+ // BUT limit consecutive reruns to prevent infinite loops
2383
+ if (rerunRequested) {
2384
+ rerunRequested = false;
2385
+ if (consecutiveReruns < MAX_CONSECUTIVE_RERUNS) {
2386
+ consecutiveReruns++;
2387
+ log(`[Watcher] Scheduling rerun #${consecutiveReruns} (requested during execution)`);
2388
+ scheduleExecution(ignoreMuted);
2389
+ }
2390
+ else {
2391
+ consecutiveReruns = 0;
2392
+ log(`[Watcher] ⚠️ Stopped infinite loop! Max consecutive reruns (${MAX_CONSECUTIVE_RERUNS}) reached. This usually means watcher listeners are triggering more change detection.`);
2393
+ }
2394
+ }
2395
+ else {
2396
+ // No rerun requested - reset counter
2397
+ consecutiveReruns = 0;
2398
+ }
2399
+ }
2400
+ const debouncedTriggerWatchers = debounce(() => {
2401
+ skipWatchers = true;
2402
+ ngZone.runOutsideAngular(() => triggerWatchers());
2403
+ }, 100);
2404
+ /*export const $invokeWatchers = (force?: boolean, ignoreMuted?: boolean) => {
2405
+ if (force) {
2406
+ triggerWatchers(ignoreMuted);
2407
+ } else {
2408
+
2551
2409
  if (skipWatchers) {
2552
2410
  skipWatchers = false;
2553
2411
  return;
2554
2412
  }
2555
2413
  debouncedTriggerWatchers();
2556
2414
  }
2557
- };
2415
+ };*/
2558
2416
  const $appDigest = (() => {
2559
2417
  let queued = false;
2560
- const $RAF = window.requestAnimationFrame;
2561
- return (force = false) => {
2418
+ return (force) => {
2562
2419
  if (!appRef) {
2563
2420
  return;
2564
2421
  }
@@ -2570,16 +2427,21 @@ const $appDigest = (() => {
2570
2427
  if (queued) {
2571
2428
  return;
2572
2429
  }
2573
- queued = true;
2574
- $RAF(() => {
2575
- ngZone.run(() => appRef.tick());
2576
- queued = false;
2577
- });
2430
+ else {
2431
+ queued = true;
2432
+ $RAF(() => {
2433
+ ngZone.run(() => appRef.tick());
2434
+ queued = false;
2435
+ });
2436
+ }
2578
2437
  }
2579
2438
  };
2580
2439
  })();
2581
- // Export registry for debugging
2582
- // (window as any).watchRegistry = registry;
2440
+ function log(message) {
2441
+ if (window.__WM_DEBUG_WATCHERS__) {
2442
+ console.log(message);
2443
+ }
2444
+ }
2583
2445
 
2584
2446
  var ComponentType;
2585
2447
  (function (ComponentType) {
@@ -5424,5 +5286,5 @@ class LRUCache {
5424
5286
  * Generated bundle index. Do not edit.
5425
5287
  */
5426
5288
 
5427
- export { $appDigest, $invokeWatchers, $parseEvent, $parseExpr, $unwatch, $unwatchAll, $unwatchAllByScope, $watch, AbstractDialogService, AbstractHttpService, AbstractI18nService, AbstractNavigationService, AbstractSpinnerService, AbstractToasterService, App, AppConstants, AppDefaults, CURRENCY_INFO, ComponentType, ConstantService, CustomIconsLoaderService, CustomPipeManager, CustomWidgetRefProvider, DEFAULT_FORMATS, DataSource, DataType, DynamicComponentRefProvider, EventNotifier, FIRST_TIME_WATCH, FieldTypeService, FieldWidgetService, FormWidgetType, IDGenerator, IDataSource, LRUCache, MatchMode, PaginationService, PartialRefProvider, ScriptLoaderService, ScriptStore, StatePersistence, UserDefinedExecutionContext, UtilsService, VALIDATOR, Viewport, _WM_APP_PROJECT, addClass, addEventListenerOnElement, addForIdAttributes, adjustContainerPosition, adjustContainerRightEdges, appendNode, appendScriptToHead, checkIsCustomPipeExpression, closePopover, convertToBlob, createCSSRule, createElement, deHyphenate, debounce, defer, detectChanges, encodeUrl, encodeUrlParams, executePromiseChain, extendProto, extractCurrentItemExpr, extractType, fetchContent, findParent, findRootContainer, findValueOf, generateGUId, getAbortableDefer, getAndroidVersion, getAppSetting, getBlob, getClonedObject, getDatasourceFromExpr, getDateObj, getDisplayDateTimeFormat, getEvaluatedExprValue, getFiles, getFnByExpr, getFnForBindExpr, getFnForEventExpr, getFormWidgetTemplate, getFormattedDate, getMomentLocaleObject, getNativeDateObject, getNavClass, getNgModelAttr, getPreviewProperties, getRequiredFormWidget, getResourceURL, getRouteNameFromLink, getRowActionAttrs, getSessionStorageItem, getSheetPositionClass, getUrlParams, getValidDateObject, getValidJSON, getWebkitTraslationMatrix, getWmProjectProperties, hasOffsetStr, initCaps, insertAfter, insertBefore, isAndroid, isAndroidTablet, isAppleProduct, isAudioFile, isChangeFromWatch, isDataSourceEqual, isDateTimeType, isDefined, isElementInViewport, isEmptyObject, isEqualWithFields, isFirstTimeChange, isIE, isImageFile, isInsecureContentRequest, isIos, isIpad, isIphone, isIpod, isKitkatDevice, isLargeTabletLandscape, isLargeTabletPortrait, isMobile, isNumberType, isObject, isPageable, isSafari, isValidImageUrl, isValidWebURL, isVideoFile, loadScript, loadScripts, loadStyleSheet, loadStyleSheets, muteWatchers, noop, openLink, periodSeparate, prettifyLabel, prettifyLabels, processFilterExpBindNode, registerFnByExpr, removeAttr, removeClass, removeExtraSlashes, removeNode, replace, replaceAt, resetChangeFromWatch, retryIfFails, scrollToElement, setAppRef, setAttr, setCSS, setCSSFromObj, setHtml, setListClass, setNgZone, setPipeProvider, setPreviewProperties, setProperty, setSessionStorageItem, setTranslation3dPosition, setWmProjectProperties, spaceSeparate, stringStartsWith, switchClass, toBoolean, toDimension, toPromise, toggleClass, transformFileURI, triggerFn, triggerItemAction, unMuteWatchers, updateTemplateAttrs, validateAccessRoles, validateDataSourceCtx, xmlToJson };
5289
+ export { $appDigest, $invokeWatchers, $parseEvent, $parseExpr, $unwatch, $watch, AbstractDialogService, AbstractHttpService, AbstractI18nService, AbstractNavigationService, AbstractSpinnerService, AbstractToasterService, App, AppConstants, AppDefaults, CURRENCY_INFO, ComponentType, ConstantService, CustomIconsLoaderService, CustomPipeManager, CustomWidgetRefProvider, DEFAULT_FORMATS, DataSource, DataType, DynamicComponentRefProvider, EventNotifier, FIRST_TIME_WATCH, FieldTypeService, FieldWidgetService, FormWidgetType, IDGenerator, IDataSource, LRUCache, MatchMode, PaginationService, PartialRefProvider, ScriptLoaderService, ScriptStore, StatePersistence, UserDefinedExecutionContext, UtilsService, VALIDATOR, Viewport, _WM_APP_PROJECT, addClass, addEventListenerOnElement, addForIdAttributes, adjustContainerPosition, adjustContainerRightEdges, appendNode, appendScriptToHead, checkIsCustomPipeExpression, closePopover, convertToBlob, createCSSRule, createElement, deHyphenate, debounce, defer, detectChanges, encodeUrl, encodeUrlParams, executePromiseChain, extendProto, extractCurrentItemExpr, extractType, fetchContent, findParent, findRootContainer, findValueOf, generateGUId, getAbortableDefer, getAndroidVersion, getAppSetting, getBlob, getClonedObject, getDatasourceFromExpr, getDateObj, getDisplayDateTimeFormat, getEvaluatedExprValue, getFiles, getFnByExpr, getFnForBindExpr, getFnForEventExpr, getFormWidgetTemplate, getFormattedDate, getMomentLocaleObject, getNativeDateObject, getNavClass, getNgModelAttr, getPreviewProperties, getRequiredFormWidget, getResourceURL, getRouteNameFromLink, getRowActionAttrs, getSessionStorageItem, getSheetPositionClass, getUrlParams, getValidDateObject, getValidJSON, getWebkitTraslationMatrix, getWmProjectProperties, hasOffsetStr, initCaps, insertAfter, insertBefore, isAndroid, isAndroidTablet, isAppleProduct, isAudioFile, isChangeFromWatch, isDataSourceEqual, isDateTimeType, isDefined, isElementInViewport, isEmptyObject, isEqualWithFields, isFirstTimeChange, isIE, isImageFile, isInsecureContentRequest, isIos, isIpad, isIphone, isIpod, isKitkatDevice, isLargeTabletLandscape, isLargeTabletPortrait, isMobile, isNumberType, isObject, isPageable, isSafari, isValidImageUrl, isValidWebURL, isVideoFile, loadScript, loadScripts, loadStyleSheet, loadStyleSheets, muteWatchers, noop, openLink, periodSeparate, prettifyLabel, prettifyLabels, processFilterExpBindNode, registerFnByExpr, removeAttr, removeClass, removeExtraSlashes, removeNode, replace, replaceAt, resetChangeFromWatch, retryIfFails, scrollToElement, setAppRef, setAttr, setCSS, setCSSFromObj, setHtml, setListClass, setNgZone, setPipeProvider, setPreviewProperties, setProperty, setSessionStorageItem, setTranslation3dPosition, setWmProjectProperties, spaceSeparate, stringStartsWith, switchClass, toBoolean, toDimension, toPromise, toggleClass, transformFileURI, triggerFn, triggerItemAction, unMuteWatchers, updateTemplateAttrs, validateAccessRoles, validateDataSourceCtx, xmlToJson };
5428
5290
  //# sourceMappingURL=index.mjs.map