@angular-wave/angular.ts 0.9.9 → 0.10.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.
Files changed (44) hide show
  1. package/@types/angular.d.ts +2 -2
  2. package/@types/animations/animate-js.d.ts +1 -1
  3. package/@types/animations/animate-queue.d.ts +0 -1
  4. package/@types/animations/animate-swap.d.ts +2 -4
  5. package/@types/animations/animate.d.ts +2 -2
  6. package/@types/animations/raf-scheduler.d.ts +4 -4
  7. package/@types/animations/shared.d.ts +30 -2
  8. package/@types/core/compile/attributes.d.ts +5 -8
  9. package/@types/core/compile/compile.d.ts +4 -4
  10. package/@types/core/controller/controller.d.ts +1 -1
  11. package/@types/core/di/ng-module.d.ts +14 -14
  12. package/@types/core/scope/interface.d.ts +18 -0
  13. package/@types/core/scope/scope.d.ts +16 -97
  14. package/@types/directive/aria/aria.d.ts +11 -13
  15. package/@types/directive/attrs/attrs.d.ts +2 -2
  16. package/@types/directive/events/events.d.ts +0 -2
  17. package/@types/directive/http/http.d.ts +4 -22
  18. package/@types/directive/if/if.d.ts +2 -4
  19. package/@types/directive/include/include.d.ts +2 -2
  20. package/@types/directive/messages/messages.d.ts +3 -3
  21. package/@types/directive/observe/observe.d.ts +2 -5
  22. package/@types/directive/worker/worker.d.ts +15 -0
  23. package/@types/interface.d.ts +5 -5
  24. package/@types/namespace.d.ts +7 -1
  25. package/@types/router/directives/view-directive.d.ts +2 -2
  26. package/@types/router/path/path-utils.d.ts +2 -2
  27. package/@types/router/state/state-object.d.ts +6 -6
  28. package/@types/router/state/state-service.d.ts +3 -3
  29. package/@types/router/transition/hook-builder.d.ts +1 -1
  30. package/@types/router/transition/interface.d.ts +1 -12
  31. package/@types/router/transition/transition-hook.d.ts +31 -0
  32. package/@types/router/transition/transition-service.d.ts +1 -1
  33. package/@types/router/transition/transition.d.ts +2 -2
  34. package/@types/services/pubsub/pubsub.d.ts +2 -2
  35. package/@types/services/sse/interface.d.ts +27 -1
  36. package/@types/services/sse/sse.d.ts +4 -3
  37. package/@types/services/worker/interface.d.ts +12 -0
  38. package/@types/services/worker/worker.d.ts +31 -0
  39. package/@types/shared/url-utils/url-utils.d.ts +14 -14
  40. package/README.md +1 -1
  41. package/dist/angular-ts.esm.js +1317 -1032
  42. package/dist/angular-ts.umd.js +1317 -1032
  43. package/dist/angular-ts.umd.min.js +1 -1
  44. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /* Version: 0.9.9 - October 28, 2025 22:08:29 */
1
+ /* Version: 0.10.0 - November 8, 2025 10:37:14 */
2
2
  const VALID_CLASS = "ng-valid";
3
3
  const INVALID_CLASS = "ng-invalid";
4
4
  const PRISTINE_CLASS = "ng-pristine";
@@ -906,7 +906,7 @@ function assertArgFn(arg, name, acceptArrayAnnotation) {
906
906
  return arg;
907
907
  }
908
908
 
909
- /** @type {import("./interface.js").ErrorHandlingConfig} */
909
+ /** @type {import("./interface.ts").ErrorHandlingConfig} */
910
910
  const minErrConfig = {
911
911
  objectMaxDepth: 5,
912
912
  urlErrorParamsEnabled: true,
@@ -1198,6 +1198,382 @@ function startsWith(str, search) {
1198
1198
  */
1199
1199
  const Cache = new Map();
1200
1200
 
1201
+ /**
1202
+ * @readonly
1203
+ * @enum {number}
1204
+ */
1205
+ const ASTType = {
1206
+ Program: 1,
1207
+ ExpressionStatement: 2,
1208
+ AssignmentExpression: 3,
1209
+ ConditionalExpression: 4,
1210
+ LogicalExpression: 5,
1211
+ BinaryExpression: 6,
1212
+ UnaryExpression: 7,
1213
+ CallExpression: 8,
1214
+ MemberExpression: 9,
1215
+ Identifier: 10,
1216
+ Literal: 11,
1217
+ ArrayExpression: 12,
1218
+ Property: 13,
1219
+ ObjectExpression: 14,
1220
+ ThisExpression: 15,
1221
+ LocalsExpression: 16,
1222
+ NGValueParameter: 17,
1223
+ };
1224
+
1225
+ const ADD_CLASS_SUFFIX = "-add";
1226
+ const REMOVE_CLASS_SUFFIX = "-remove";
1227
+ const EVENT_CLASS_PREFIX = "ng-";
1228
+ const ACTIVE_CLASS_SUFFIX = "-active";
1229
+ const PREPARE_CLASS_SUFFIX = "-prepare";
1230
+
1231
+ const NG_ANIMATE_CLASSNAME = "ng-animate";
1232
+ const NG_ANIMATE_CHILDREN_DATA = "$$ngAnimateChildren";
1233
+ let TRANSITION_PROP;
1234
+ let TRANSITIONEND_EVENT;
1235
+ let ANIMATION_PROP;
1236
+ let ANIMATIONEND_EVENT;
1237
+
1238
+ // If unprefixed events are not supported but webkit-prefixed are, use the latter.
1239
+ // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
1240
+ // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
1241
+ // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
1242
+ // Register both events in case `window.onanimationend` is not supported because of that,
1243
+ // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
1244
+ // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
1245
+ // therefore there is no reason to test anymore for other vendor prefixes:
1246
+ // http://caniuse.com/#search=transition
1247
+ if (
1248
+ window.ontransitionend === undefined &&
1249
+ window.onwebkittransitionend !== undefined
1250
+ ) {
1251
+ TRANSITION_PROP = "WebkitTransition";
1252
+ TRANSITIONEND_EVENT = "webkitTransitionEnd transitionend";
1253
+ } else {
1254
+ TRANSITION_PROP = "transition";
1255
+ TRANSITIONEND_EVENT = "transitionend";
1256
+ }
1257
+
1258
+ if (
1259
+ window.onanimationend === undefined &&
1260
+ window.onwebkitanimationend !== undefined
1261
+ ) {
1262
+ ANIMATION_PROP = "WebkitAnimation";
1263
+ ANIMATIONEND_EVENT = "webkitAnimationEnd animationend";
1264
+ } else {
1265
+ ANIMATION_PROP = "animation";
1266
+ ANIMATIONEND_EVENT = "animationend";
1267
+ }
1268
+
1269
+ const DURATION_KEY = "Duration";
1270
+ const PROPERTY_KEY = ASTType.Property;
1271
+ const DELAY_KEY = "Delay";
1272
+ const TIMING_KEY = "TimingFunction";
1273
+ const ANIMATION_ITERATION_COUNT_KEY = "IterationCount";
1274
+ const ANIMATION_PLAYSTATE_KEY = "PlayState";
1275
+ const SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
1276
+
1277
+ const ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
1278
+ const ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
1279
+ const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
1280
+ const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
1281
+
1282
+ const ngMinErr$1 = minErr("ng");
1283
+ function assertArg(arg, name, reason) {
1284
+ if (!arg) {
1285
+ throw ngMinErr$1(
1286
+ "areq",
1287
+ "Argument '{0}' is {1}",
1288
+ name || "?",
1289
+ reason,
1290
+ );
1291
+ }
1292
+ return arg;
1293
+ }
1294
+
1295
+ function packageStyles(options) {
1296
+ const styles = {};
1297
+ if (options && (options.to || options.from)) {
1298
+ styles.to = options.to;
1299
+ styles.from = options.from;
1300
+ }
1301
+ return styles;
1302
+ }
1303
+
1304
+ function pendClasses(classes, fix, isPrefix) {
1305
+ let className = "";
1306
+
1307
+ classes = Array.isArray(classes)
1308
+ ? classes
1309
+ : classes && isString(classes) && classes.length
1310
+ ? classes.split(/\s+/)
1311
+ : [];
1312
+ classes.forEach((klass, i) => {
1313
+ if (klass && klass.length > 0) {
1314
+ className += i > 0 ? " " : "";
1315
+ className += isPrefix ? fix + klass : klass + fix;
1316
+ }
1317
+ });
1318
+ return className;
1319
+ }
1320
+
1321
+ function removeFromArray(arr, val) {
1322
+ const index = arr.indexOf(val);
1323
+ if (val >= 0) {
1324
+ arr.splice(index, 1);
1325
+ }
1326
+ }
1327
+
1328
+ /**
1329
+ *
1330
+ * @param {NodeList|Node} element
1331
+ * @returns {Node[]|Node|undefined}
1332
+ */
1333
+ function stripCommentsFromElement(element) {
1334
+ if (element instanceof NodeList) {
1335
+ return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
1336
+ } else if (element.nodeType === Node.ELEMENT_NODE) {
1337
+ return /** @type {Node} */ (element);
1338
+ } else {
1339
+ return undefined;
1340
+ }
1341
+ }
1342
+
1343
+ /**
1344
+ * @param {NodeList|Node} element
1345
+ * @returns {Node}
1346
+ */
1347
+ function extractElementNode(element) {
1348
+ if (!element || !Array.isArray(element)) return /** @type {Node} */ (element);
1349
+ for (let i = 0; i < /** @type {NodeList} */ (element).length; i++) {
1350
+ const elm = element[i];
1351
+ if (elm.nodeType === Node.ELEMENT_NODE) {
1352
+ return elm;
1353
+ }
1354
+ }
1355
+ }
1356
+
1357
+ function applyAnimationClassesFactory() {
1358
+ return function (element, options) {
1359
+ if (options.addClass) {
1360
+ element.classList.add(...options.addClass.trim().split(" "));
1361
+ options.addClass = null;
1362
+ }
1363
+ if (options.removeClass) {
1364
+ element.classList.remove(...options.removeClass.trim().split(" "));
1365
+ options.removeClass = null;
1366
+ }
1367
+ };
1368
+ }
1369
+
1370
+ function prepareAnimationOptions(options) {
1371
+ options = options || {};
1372
+ if (!options.$$prepared) {
1373
+ let domOperation = options.domOperation || (() => {});
1374
+ options.domOperation = function () {
1375
+ options.$$domOperationFired = true;
1376
+ domOperation();
1377
+ domOperation = () => {};
1378
+ };
1379
+ options.$$prepared = true;
1380
+ }
1381
+ return options;
1382
+ }
1383
+
1384
+ function applyAnimationStyles(element, options) {
1385
+ applyAnimationFromStyles(element, options);
1386
+ applyAnimationToStyles(element, options);
1387
+ }
1388
+
1389
+ /**
1390
+ * Applies initial animation styles to a DOM element.
1391
+ *
1392
+ * This function sets the element's inline styles using the properties
1393
+ * defined in `options.from`, then clears the property to prevent reuse.
1394
+ *
1395
+ * @param {HTMLElement} element - The target DOM element to apply styles to.
1396
+ * @param {{ from?: Partial<CSSStyleDeclaration> | null }} options - options containing a `from` object with CSS property–value pairs.
1397
+ */
1398
+ function applyAnimationFromStyles(element, options) {
1399
+ if (options.from) {
1400
+ Object.assign(element.style, options.from);
1401
+ options.from = null;
1402
+ }
1403
+ }
1404
+
1405
+ /**
1406
+ * Applies final animation styles to a DOM element.
1407
+ *
1408
+ * This function sets the element's inline styles using the properties
1409
+ * defined in `options.to`, then clears the property to prevent reuse.
1410
+ *
1411
+ * @param {HTMLElement} element - The target DOM element to apply styles to.
1412
+ * @param {{ to?: Partial<CSSStyleDeclaration> | null }} options - options containing a `from` object with CSS property–value pairs.
1413
+ */
1414
+ function applyAnimationToStyles(element, options) {
1415
+ if (options.to) {
1416
+ Object.assign(element.style, options.to);
1417
+ options.to = null;
1418
+ }
1419
+ }
1420
+
1421
+ function mergeAnimationDetails(element, oldAnimation, newAnimation) {
1422
+ const target = oldAnimation.options || {};
1423
+ const newOptions = newAnimation.options || {};
1424
+
1425
+ const toAdd = `${target.addClass || ""} ${newOptions.addClass || ""}`;
1426
+ const toRemove = `${target.removeClass || ""} ${newOptions.removeClass || ""}`;
1427
+ const classes = resolveElementClasses(
1428
+ element.getAttribute("class"),
1429
+ toAdd,
1430
+ toRemove,
1431
+ );
1432
+
1433
+ if (newOptions.preparationClasses) {
1434
+ target.preparationClasses = concatWithSpace(
1435
+ newOptions.preparationClasses,
1436
+ target.preparationClasses,
1437
+ );
1438
+ delete newOptions.preparationClasses;
1439
+ }
1440
+
1441
+ extend(target, newOptions);
1442
+
1443
+ if (classes.addClass) {
1444
+ target.addClass = classes.addClass;
1445
+ } else {
1446
+ target.addClass = null;
1447
+ }
1448
+
1449
+ if (classes.removeClass) {
1450
+ target.removeClass = classes.removeClass;
1451
+ } else {
1452
+ target.removeClass = null;
1453
+ }
1454
+
1455
+ oldAnimation.addClass = target.addClass;
1456
+ oldAnimation.removeClass = target.removeClass;
1457
+
1458
+ return target;
1459
+ }
1460
+
1461
+ function resolveElementClasses(existing, toAdd, toRemove) {
1462
+ const ADD_CLASS = 1;
1463
+ const REMOVE_CLASS = -1;
1464
+
1465
+ const flags = {};
1466
+ existing = splitClassesToLookup(existing);
1467
+
1468
+ toAdd = splitClassesToLookup(toAdd);
1469
+ Object.keys(toAdd).forEach((key) => {
1470
+ flags[key] = ADD_CLASS;
1471
+ });
1472
+
1473
+ toRemove = splitClassesToLookup(toRemove);
1474
+ Object.keys(toRemove).forEach((key) => {
1475
+ flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
1476
+ });
1477
+
1478
+ const classes = {
1479
+ addClass: "",
1480
+ removeClass: "",
1481
+ };
1482
+
1483
+ Object.entries(flags).forEach(([klass, val]) => {
1484
+ let prop, allow;
1485
+ if (val === ADD_CLASS) {
1486
+ prop = "addClass";
1487
+ allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
1488
+ } else if (val === REMOVE_CLASS) {
1489
+ prop = "removeClass";
1490
+ allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
1491
+ }
1492
+ if (allow) {
1493
+ if (classes[prop].length) {
1494
+ classes[prop] += " ";
1495
+ }
1496
+ classes[prop] += klass;
1497
+ }
1498
+ });
1499
+
1500
+ function splitClassesToLookup(classes) {
1501
+ if (isString(classes)) {
1502
+ classes = classes.trim().split(" ");
1503
+ }
1504
+
1505
+ const obj = {};
1506
+ if (classes) {
1507
+ classes.forEach((klass) => {
1508
+ // sometimes the split leaves empty string values
1509
+ // incase extra spaces were applied to the options
1510
+ if (klass.length) {
1511
+ obj[klass] = true;
1512
+ }
1513
+ });
1514
+ }
1515
+ return obj;
1516
+ }
1517
+
1518
+ return classes;
1519
+ }
1520
+
1521
+ function applyGeneratedPreparationClasses(element, event, options) {
1522
+ let classes = "";
1523
+ if (event) {
1524
+ classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
1525
+ }
1526
+ if (options.addClass) {
1527
+ classes = concatWithSpace(
1528
+ classes,
1529
+ pendClasses(options.addClass, ADD_CLASS_SUFFIX),
1530
+ );
1531
+ }
1532
+ if (options.removeClass) {
1533
+ classes = concatWithSpace(
1534
+ classes,
1535
+ pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX),
1536
+ );
1537
+ }
1538
+ if (classes.length) {
1539
+ options.preparationClasses = classes;
1540
+ element.className += ` ${classes}`;
1541
+ }
1542
+ }
1543
+
1544
+ function clearGeneratedClasses(element, options) {
1545
+ if (options.preparationClasses) {
1546
+ options.preparationClasses
1547
+ .split(" ")
1548
+ .forEach((cls) => element.classList.remove(cls));
1549
+ options.preparationClasses = null;
1550
+ }
1551
+ if (options.activeClasses) {
1552
+ options.activeClasses
1553
+ .split(" ")
1554
+ .forEach((cls) => element.classList.remove(cls));
1555
+ options.activeClasses = null;
1556
+ }
1557
+ }
1558
+
1559
+ function blockKeyframeAnimations(node, applyBlock) {
1560
+ const value = applyBlock ? "paused" : "";
1561
+ const key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
1562
+ applyInlineStyle(node, [key, value]);
1563
+ return [key, value];
1564
+ }
1565
+
1566
+ function applyInlineStyle(node, styleTuple) {
1567
+ const prop = styleTuple[0];
1568
+ node.style[prop] = styleTuple[1];
1569
+ }
1570
+
1571
+ function concatWithSpace(a, b) {
1572
+ if (!a) return b;
1573
+ if (!b) return a;
1574
+ return `${a} ${b}`;
1575
+ }
1576
+
1201
1577
  /** @type {number} */
1202
1578
  let jqId = 1;
1203
1579
 
@@ -1719,12 +2095,8 @@ function domInsert(element, parentElement, afterElement) {
1719
2095
  // from the dom sometime before this code runs then let's
1720
2096
  // just stick to using the parent element as the anchor
1721
2097
  if (afterElement) {
1722
- const afterNode = extractElementNode$1(afterElement);
1723
- if (
1724
- afterNode &&
1725
- !afterNode.parentNode &&
1726
- !afterNode.previousElementSibling
1727
- ) {
2098
+ const afterNode = extractElementNode(afterElement);
2099
+ if (afterNode && !afterNode.parentNode && !afterNode.previousSibling) {
1728
2100
  afterElement = null;
1729
2101
  }
1730
2102
  }
@@ -1735,16 +2107,6 @@ function domInsert(element, parentElement, afterElement) {
1735
2107
  }
1736
2108
  }
1737
2109
 
1738
- function extractElementNode$1(element) {
1739
- const { length } = element;
1740
- for (let i = 0; i < length; i++) {
1741
- const elm = element[i];
1742
- if (elm.nodeType === Node.ELEMENT_NODE) {
1743
- return elm;
1744
- }
1745
- }
1746
- }
1747
-
1748
2110
  /**
1749
2111
  * Returns the base href of the document.
1750
2112
  *
@@ -1863,7 +2225,7 @@ class NgModule {
1863
2225
  /**
1864
2226
  * @param {string} name - Name of the module
1865
2227
  * @param {Array<string>} requires - List of modules which the injector will load before the current module
1866
- * @param {import("../../interface.js").Injectable<any>} [configFn]
2228
+ * @param {import("../../interface.ts").Injectable<any>} [configFn]
1867
2229
  */
1868
2230
  constructor(name, requires, configFn) {
1869
2231
  assert(isString(name), "name required");
@@ -1889,7 +2251,7 @@ class NgModule {
1889
2251
  /** @type {!Array<Array<*>>} */
1890
2252
  this.configBlocks = [];
1891
2253
 
1892
- /** @type {!Array.<import("../../interface.js").Injectable<any>>} */
2254
+ /** @type {!Array.<import("../../interface.ts").Injectable<any>>} */
1893
2255
  this.runBlocks = [];
1894
2256
 
1895
2257
  if (configFn) {
@@ -1993,7 +2355,7 @@ class NgModule {
1993
2355
 
1994
2356
  /**
1995
2357
  * @param {string} name
1996
- * @param {import("../../interface.js").Injectable<any>} decorFn
2358
+ * @param {import("../../interface.ts").Injectable<any>} decorFn
1997
2359
  * @returns {NgModule}
1998
2360
  */
1999
2361
  decorator(name, decorFn) {
@@ -2006,7 +2368,7 @@ class NgModule {
2006
2368
 
2007
2369
  /**
2008
2370
  * @param {string} name
2009
- * @param {import("../../interface.js").Injectable<any>} directiveFactory
2371
+ * @param {import("../../interface.ts").Injectable<any>} directiveFactory
2010
2372
  * @returns {NgModule}
2011
2373
  */
2012
2374
  directive(name, directiveFactory) {
@@ -2023,7 +2385,7 @@ class NgModule {
2023
2385
 
2024
2386
  /**
2025
2387
  * @param {string} name
2026
- * @param {import("../../interface.js").Injectable<any>} animationFactory
2388
+ * @param {import("../../interface.ts").Injectable<any>} animationFactory
2027
2389
  * @returns {NgModule}
2028
2390
  */
2029
2391
  animation(name, animationFactory) {
@@ -2040,7 +2402,7 @@ class NgModule {
2040
2402
 
2041
2403
  /**
2042
2404
  * @param {string} name
2043
- * @param {import("../../interface.js").Injectable<any>} filterFn
2405
+ * @param {import("../../interface.ts").Injectable<any>} filterFn
2044
2406
  * @return {NgModule}
2045
2407
  */
2046
2408
  filter(name, filterFn) {
@@ -2053,7 +2415,7 @@ class NgModule {
2053
2415
 
2054
2416
  /**
2055
2417
  * @param {string} name
2056
- * @param {import("../../interface.js").Injectable<any>} ctlFn
2418
+ * @param {import("../../interface.ts").Injectable<any>} ctlFn
2057
2419
  * @returns {NgModule}
2058
2420
  */
2059
2421
  controller(name, ctlFn) {
@@ -2438,7 +2800,7 @@ function createInjector(modulesToLoad, strictDi = false) {
2438
2800
  * Registers a factory.
2439
2801
  * @param {string} name
2440
2802
  * @param {(string|(function(*): *))[]} factoryFn
2441
- * @returns {import('../../interface.js').ServiceProvider}
2803
+ * @returns {import('../../interface.ts').ServiceProvider}
2442
2804
  */
2443
2805
  function factory(name, factoryFn) {
2444
2806
  return provider(name, {
@@ -2460,7 +2822,7 @@ function createInjector(modulesToLoad, strictDi = false) {
2460
2822
  * Registers a service constructor.
2461
2823
  * @param {string} name
2462
2824
  * @param {Function} constructor
2463
- * @returns {import('../../interface.js').ServiceProvider}
2825
+ * @returns {import('../../interface.ts').ServiceProvider}
2464
2826
  */
2465
2827
  function service(name, constructor) {
2466
2828
  return factory(name, [
@@ -2929,7 +3291,7 @@ class ControllerProvider {
2929
3291
 
2930
3292
  /**
2931
3293
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
2932
- * @returns {import("./interface.js").ControllerService} A service function that creates controllers.
3294
+ * @returns {import("./interface.ts").ControllerService} A service function that creates controllers.
2933
3295
  */
2934
3296
  ($injector) => {
2935
3297
  return (expression, locals, later, ident) => {
@@ -3047,18 +3409,19 @@ class ControllerProvider {
3047
3409
  );
3048
3410
  }
3049
3411
  locals.$scope[identifier] = instance;
3412
+ locals.$scope["$controllerIdentifier"] = identifier;
3050
3413
  }
3051
3414
  }
3052
3415
 
3053
3416
  const originUrl = urlResolve(window.location.href);
3054
3417
 
3055
3418
  /**
3056
- * @param {import("./interface.js").ResolvableUrl} url
3057
- * @return {import("./interface.js").ParsedUrl}
3419
+ * @param {import("./interface.ts").ResolvableUrl} url
3420
+ * @return {import("./interface.ts").ParsedUrl}
3058
3421
  */
3059
3422
  function urlResolve(url) {
3060
3423
  if (!isString(url))
3061
- return /** @type {import("./interface.js").ParsedUrl} */ (url);
3424
+ return /** @type {import("./interface.ts").ParsedUrl} */ (url);
3062
3425
 
3063
3426
  const urlParsingNode = new URL(
3064
3427
  /** @type {string} */ (url),
@@ -3090,7 +3453,7 @@ function urlResolve(url) {
3090
3453
  * Parse a request URL and determine whether this is a same-origin request as the application
3091
3454
  * document.
3092
3455
  *
3093
- * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3456
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3094
3457
  * or a parsed URL object.
3095
3458
  * @returns {boolean} Whether the request is for the same origin as the application document.
3096
3459
  */
@@ -3104,7 +3467,7 @@ function urlIsSameOrigin(requestUrl) {
3104
3467
  * Note: The base URL is usually the same as the document location (`location.href`) but can
3105
3468
  * be overriden by using the `<base>` tag.
3106
3469
  *
3107
- * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3470
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3108
3471
  * or a parsed URL object.
3109
3472
  * @returns {boolean} Whether the URL is same-origin as the document base URL.
3110
3473
  */
@@ -3118,7 +3481,7 @@ function urlIsSameOriginAsBaseUrl(requestUrl) {
3118
3481
  *
3119
3482
  * @param {string[]} trustedOriginUrls - A list of URLs (strings), whose origins are trusted.
3120
3483
  *
3121
- * @returns {(url: import("./interface.js").ResolvableUrl) => boolean } - A function that receives a URL (string or parsed URL object) and returns
3484
+ * @returns {(url: import("./interface.ts").ResolvableUrl) => boolean } - A function that receives a URL (string or parsed URL object) and returns
3122
3485
  * whether it is of an allowed origin.
3123
3486
  */
3124
3487
  function urlIsAllowedOriginFactory(trustedOriginUrls) {
@@ -3131,7 +3494,7 @@ function urlIsAllowedOriginFactory(trustedOriginUrls) {
3131
3494
  * based on a list of trusted-origin URLs. The current location's origin is implicitly
3132
3495
  * trusted.
3133
3496
  *
3134
- * @param {import("./interface.js").ResolvableUrl} requestUrl - The URL to be checked (provided as a string that will be
3497
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl - The URL to be checked (provided as a string that will be
3135
3498
  * resolved or a parsed URL object).
3136
3499
  *
3137
3500
  * @returns {boolean} - Whether the specified URL is of an allowed origin.
@@ -3147,9 +3510,9 @@ function urlIsAllowedOriginFactory(trustedOriginUrls) {
3147
3510
  /**
3148
3511
  * Determine if two URLs share the same origin.
3149
3512
  *
3150
- * @param {import("./interface.js").ResolvableUrl} url1 - First URL to compare as a string or a normalized URL in the form of
3513
+ * @param {import("./interface.ts").ResolvableUrl} url1 - First URL to compare as a string or a normalized URL in the form of
3151
3514
  * a dictionary object returned by `urlResolve()`.
3152
- * @param {import("./interface.js").ResolvableUrl} url2 - Second URL to compare as a string or a normalized URL in the form
3515
+ * @param {import("./interface.ts").ResolvableUrl} url2 - Second URL to compare as a string or a normalized URL in the form
3153
3516
  * of a dictionary object returned by `urlResolve()`.
3154
3517
  *
3155
3518
  * @returns {boolean} - True if both URLs have the same origin, and false otherwise.
@@ -3783,7 +4146,7 @@ function SceProvider() {
3783
4146
  *
3784
4147
  * @param {string} type The SCE context in which this result will be used.
3785
4148
  * @param {string} expr String expression to compile.
3786
- * @return {import("../../core/parse/interface.js").CompiledExpression} A function which represents the compiled expression:
4149
+ * @return {import("../../core/parse/interface.ts").CompiledExpression} A function which represents the compiled expression:
3787
4150
  *
3788
4151
  * * `context` – `{object}` – an object against which any expressions embedded in the
3789
4152
  * strings are evaluated against (typically a scope object).
@@ -4015,26 +4378,23 @@ function SceProvider() {
4015
4378
  */
4016
4379
  const ngEventDirectives = {};
4017
4380
 
4018
- "click copy cut dblclick focus blur keydown keyup load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove offline online"
4381
+ "click copy cut dblclick focus blur keydown keyup load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove"
4019
4382
  .split(" ")
4020
4383
  .forEach((eventName) => {
4021
4384
  const directiveName = directiveNormalize(`ng-${eventName}`);
4022
4385
  ngEventDirectives[directiveName] = [
4023
4386
  $injectTokens.$parse,
4024
4387
  $injectTokens.$exceptionHandler,
4025
- $injectTokens.$window,
4026
4388
 
4027
4389
  /**
4028
- * @param {import("../../core/parse/interface.ts").ParseService} $parse
4390
+ * @param {ng.ParseService} $parse
4029
4391
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4030
- * @param {ng.WindowService} $window
4031
4392
  * @returns
4032
4393
  */
4033
- ($parse, $exceptionHandler, $window) => {
4394
+ ($parse, $exceptionHandler) => {
4034
4395
  return createEventDirective(
4035
4396
  $parse,
4036
4397
  $exceptionHandler,
4037
- $window,
4038
4398
  directiveName,
4039
4399
  eventName,
4040
4400
  );
@@ -4046,7 +4406,6 @@ const ngEventDirectives = {};
4046
4406
  *
4047
4407
  * @param {ng.ParseService} $parse
4048
4408
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4049
- * @param {ng.WindowService} $window
4050
4409
  * @param {string} directiveName
4051
4410
  * @param {string} eventName
4052
4411
  * @returns {ng.Directive}
@@ -4054,7 +4413,6 @@ const ngEventDirectives = {};
4054
4413
  function createEventDirective(
4055
4414
  $parse,
4056
4415
  $exceptionHandler,
4057
- $window,
4058
4416
  directiveName,
4059
4417
  eventName,
4060
4418
  ) {
@@ -4123,16 +4481,13 @@ const $compileMinErr$1 = minErr("$compile");
4123
4481
  const SIMPLE_ATTR_NAME = /^\w/;
4124
4482
  const specialAttrHolder = document.createElement("div");
4125
4483
 
4126
- /**
4127
- * @implements {Record<string, any>}
4128
- */
4129
4484
  class Attributes {
4130
4485
  static $nonscope = true;
4131
4486
 
4132
4487
  /**
4133
- * @param {import('../scope/scope.js').Scope} $rootScope
4488
+ * @param {ng.Scope} $rootScope
4134
4489
  * @param {*} $animate
4135
- * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
4490
+ * @param {ng.ExceptionHandlerService} $exceptionHandler
4136
4491
  * @param {*} $sce
4137
4492
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
4138
4493
  * @param {Object} [attributesToCopy]
@@ -4445,19 +4800,18 @@ function tokenDifference(str1, str2) {
4445
4800
  /**
4446
4801
  * @param {string} source - the name of the attribute to be observed
4447
4802
  * @param {string} prop - the scope property to be updated with attribute value
4448
- * @returns {import("../../interface.ts").Directive}
4803
+ * @returns {ng.Directive}
4449
4804
  */
4450
4805
  function ngObserveDirective(source, prop) {
4451
4806
  return {
4452
4807
  restrict: "A",
4453
4808
  compile: () => (scope, element) => {
4454
- const targetElement = element;
4455
4809
  if (prop === "") {
4456
4810
  prop = source;
4457
4811
  }
4458
4812
  const normalized = kebabToCamel(prop);
4459
4813
  if (!scope[normalized]) {
4460
- scope[normalized] = targetElement.getAttribute(source);
4814
+ scope[normalized] = element.getAttribute(source);
4461
4815
  }
4462
4816
 
4463
4817
  const observer = new MutationObserver((mutations) => {
@@ -4470,7 +4824,7 @@ function ngObserveDirective(source, prop) {
4470
4824
  }
4471
4825
  });
4472
4826
 
4473
- observer.observe(targetElement, {
4827
+ observer.observe(element, {
4474
4828
  attributes: true,
4475
4829
  attributeFilter: [source],
4476
4830
  });
@@ -4496,7 +4850,7 @@ class CompileProvider {
4496
4850
  /* @ignore */ static $inject = [$injectTokens.$provide, $injectTokens.$$sanitizeUriProvider];
4497
4851
 
4498
4852
  /**
4499
- * @param {import('../../interface.js').Provider} $provide
4853
+ * @param {import('../../interface.ts').Provider} $provide
4500
4854
  * @param {import('../sanitize/sanitize-uri.js').SanitizeUriProvider} $$sanitizeUriProvider
4501
4855
  */
4502
4856
  constructor($provide, $$sanitizeUriProvider) {
@@ -4686,7 +5040,7 @@ class CompileProvider {
4686
5040
  /**
4687
5041
  * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
4688
5042
  * or an object map of components where the keys are the names and the values are the component definition objects.
4689
- * @param {import("../../interface.js").Component} options Component definition object (a simplified
5043
+ * @param {import("../../interface.ts").Component} options Component definition object (a simplified
4690
5044
  * {directive definition object}),
4691
5045
  * with the following properties (all optional):
4692
5046
  *
@@ -5472,12 +5826,12 @@ class CompileProvider {
5472
5826
  createEventDirective(
5473
5827
  $parse,
5474
5828
  $exceptionHandler,
5475
- window,
5476
5829
  nName,
5477
5830
  name,
5478
5831
  ),
5479
5832
  );
5480
5833
  } else {
5834
+ // isWindow
5481
5835
  directives.push(
5482
5836
  createWindowEventDirective(
5483
5837
  $parse,
@@ -7467,7 +7821,7 @@ class CompileProvider {
7467
7821
  scope.$handler.watchers
7468
7822
  .get(attrs[attrName])
7469
7823
  ?.forEach((watchFn) => {
7470
- watchFn.listenerFn(val);
7824
+ watchFn.listenerFn(val, scope.$target);
7471
7825
  });
7472
7826
  }
7473
7827
  }
@@ -7880,8 +8234,14 @@ class FormController {
7880
8234
  * state (ng-dirty class). This method will also propagate to parent forms.
7881
8235
  */
7882
8236
  $setDirty() {
7883
- this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
7884
- this.$$animate.addClass(this.$$element, DIRTY_CLASS);
8237
+ if (hasAnimate(this.$$element)) {
8238
+ this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
8239
+ this.$$animate.addClass(this.$$element, DIRTY_CLASS);
8240
+ } else {
8241
+ // Fallback for non-animated environments
8242
+ this.$$element.classList.remove(PRISTINE_CLASS);
8243
+ this.$$element.classList.add(DIRTY_CLASS);
8244
+ }
7885
8245
  this.$dirty = true;
7886
8246
  this.$pristine = false;
7887
8247
  this.$$parentForm.$setDirty();
@@ -7900,11 +8260,18 @@ class FormController {
7900
8260
  * saving or resetting it.
7901
8261
  */
7902
8262
  $setPristine() {
7903
- this.$$animate.setClass(
7904
- this.$$element,
7905
- PRISTINE_CLASS,
7906
- `${DIRTY_CLASS} ${SUBMITTED_CLASS}`,
7907
- );
8263
+ if (hasAnimate(this.$$element)) {
8264
+ this.$$animate.setClass(
8265
+ this.$$element,
8266
+ PRISTINE_CLASS,
8267
+ `${DIRTY_CLASS} ${SUBMITTED_CLASS}`,
8268
+ );
8269
+ } else {
8270
+ // Fallback for non-animated environments
8271
+ this.$$element.classList.remove(DIRTY_CLASS, SUBMITTED_CLASS);
8272
+ this.$$element.classList.add(PRISTINE_CLASS);
8273
+ }
8274
+
7908
8275
  this.$dirty = false;
7909
8276
  this.$pristine = true;
7910
8277
  this.$submitted = false;
@@ -7942,7 +8309,11 @@ class FormController {
7942
8309
  }
7943
8310
 
7944
8311
  $$setSubmitted() {
7945
- this.$$animate.addClass(this.$$element, SUBMITTED_CLASS);
8312
+ if (hasAnimate(this.$$element)) {
8313
+ this.$$animate.addClass(this.$$element, SUBMITTED_CLASS);
8314
+ } else {
8315
+ this.$$element.classList.add(SUBMITTED_CLASS);
8316
+ }
7946
8317
  this.$submitted = true;
7947
8318
  this.$$controls.forEach((control) => {
7948
8319
  if (control.$$setSubmitted) {
@@ -11552,7 +11923,7 @@ function ngHideDirective($animate) {
11552
11923
  ngIfDirective.$inject = ["$animate"];
11553
11924
  /**
11554
11925
  * @param {*} $animate
11555
- * @returns {import("../../interface.ts").Directive}
11926
+ * @returns {ng.Directive}
11556
11927
  */
11557
11928
  function ngIfDirective($animate) {
11558
11929
  return {
@@ -11562,10 +11933,10 @@ function ngIfDirective($animate) {
11562
11933
  restrict: "A",
11563
11934
  /**
11564
11935
  *
11565
- * @param {import("../../core/scope/scope.js").Scope} $scope
11936
+ * @param {ng.Scope} $scope
11566
11937
  * @param {Element} $element
11567
- * @param {import("../../core/compile/attributes.js").Attributes} $attr
11568
- * @param {Object} _ctrl
11938
+ * @param {ng.Attributes} $attr
11939
+ * @param {*} _ctrl
11569
11940
  * @param {*} $transclude
11570
11941
  */
11571
11942
  link($scope, $element, $attr, _ctrl, $transclude) {
@@ -11577,7 +11948,7 @@ function ngIfDirective($animate) {
11577
11948
 
11578
11949
  let previousElements;
11579
11950
 
11580
- $scope.$watch($attr["ngIf"], (value) => {
11951
+ $scope.$watch($attr.ngIf, (value) => {
11581
11952
  if (value) {
11582
11953
  if (!childScope) {
11583
11954
  $transclude((clone, newScope) => {
@@ -11632,7 +12003,7 @@ ngIncludeDirective.$inject = [
11632
12003
  * @param {import("../../services/anchor-scroll/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
11633
12004
  * @param {*} $animate
11634
12005
  * @param {import('../../services/exception/interface.ts').ErrorHandler} $exceptionHandler
11635
- * @returns {import('../../interface.js').Directive}
12006
+ * @returns {import('../../interface.ts').Directive}
11636
12007
  */
11637
12008
  function ngIncludeDirective(
11638
12009
  $templateRequest,
@@ -13014,7 +13385,7 @@ function ngTranscludeDirective($compile) {
13014
13385
  const REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
13015
13386
 
13016
13387
  /**
13017
- * @type {Record<string, import("../../interface.js").DirectiveFactory>}
13388
+ * @type {Record<string, import("../../interface.ts").DirectiveFactory>}
13018
13389
  */
13019
13390
  const ngAttributeAliasDirectives = {};
13020
13391
 
@@ -13587,364 +13958,6 @@ class AnchorScrollProvider {
13587
13958
  ];
13588
13959
  }
13589
13960
 
13590
- /**
13591
- * @readonly
13592
- * @enum {number}
13593
- */
13594
- const ASTType = {
13595
- Program: 1,
13596
- ExpressionStatement: 2,
13597
- AssignmentExpression: 3,
13598
- ConditionalExpression: 4,
13599
- LogicalExpression: 5,
13600
- BinaryExpression: 6,
13601
- UnaryExpression: 7,
13602
- CallExpression: 8,
13603
- MemberExpression: 9,
13604
- Identifier: 10,
13605
- Literal: 11,
13606
- ArrayExpression: 12,
13607
- Property: 13,
13608
- ObjectExpression: 14,
13609
- ThisExpression: 15,
13610
- LocalsExpression: 16,
13611
- NGValueParameter: 17,
13612
- };
13613
-
13614
- const ADD_CLASS_SUFFIX = "-add";
13615
- const REMOVE_CLASS_SUFFIX = "-remove";
13616
- const EVENT_CLASS_PREFIX = "ng-";
13617
- const ACTIVE_CLASS_SUFFIX = "-active";
13618
- const PREPARE_CLASS_SUFFIX = "-prepare";
13619
-
13620
- const NG_ANIMATE_CLASSNAME = "ng-animate";
13621
- const NG_ANIMATE_CHILDREN_DATA = "$$ngAnimateChildren";
13622
- let TRANSITION_PROP;
13623
- let TRANSITIONEND_EVENT;
13624
- let ANIMATION_PROP;
13625
- let ANIMATIONEND_EVENT;
13626
-
13627
- // If unprefixed events are not supported but webkit-prefixed are, use the latter.
13628
- // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
13629
- // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
13630
- // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
13631
- // Register both events in case `window.onanimationend` is not supported because of that,
13632
- // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
13633
- // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
13634
- // therefore there is no reason to test anymore for other vendor prefixes:
13635
- // http://caniuse.com/#search=transition
13636
- if (
13637
- window.ontransitionend === undefined &&
13638
- window.onwebkittransitionend !== undefined
13639
- ) {
13640
- TRANSITION_PROP = "WebkitTransition";
13641
- TRANSITIONEND_EVENT = "webkitTransitionEnd transitionend";
13642
- } else {
13643
- TRANSITION_PROP = "transition";
13644
- TRANSITIONEND_EVENT = "transitionend";
13645
- }
13646
-
13647
- if (
13648
- window.onanimationend === undefined &&
13649
- window.onwebkitanimationend !== undefined
13650
- ) {
13651
- ANIMATION_PROP = "WebkitAnimation";
13652
- ANIMATIONEND_EVENT = "webkitAnimationEnd animationend";
13653
- } else {
13654
- ANIMATION_PROP = "animation";
13655
- ANIMATIONEND_EVENT = "animationend";
13656
- }
13657
-
13658
- const DURATION_KEY = "Duration";
13659
- const PROPERTY_KEY = ASTType.Property;
13660
- const DELAY_KEY = "Delay";
13661
- const TIMING_KEY = "TimingFunction";
13662
- const ANIMATION_ITERATION_COUNT_KEY = "IterationCount";
13663
- const ANIMATION_PLAYSTATE_KEY = "PlayState";
13664
- const SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
13665
-
13666
- const ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
13667
- const ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
13668
- const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
13669
- const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
13670
-
13671
- const ngMinErr$1 = minErr("ng");
13672
- function assertArg(arg, name, reason) {
13673
- if (!arg) {
13674
- throw ngMinErr$1(
13675
- "areq",
13676
- "Argument '{0}' is {1}",
13677
- name || "?",
13678
- reason,
13679
- );
13680
- }
13681
- return arg;
13682
- }
13683
-
13684
- function packageStyles(options) {
13685
- const styles = {};
13686
- if (options && (options.to || options.from)) {
13687
- styles.to = options.to;
13688
- styles.from = options.from;
13689
- }
13690
- return styles;
13691
- }
13692
-
13693
- function pendClasses(classes, fix, isPrefix) {
13694
- let className = "";
13695
-
13696
- classes = Array.isArray(classes)
13697
- ? classes
13698
- : classes && isString(classes) && classes.length
13699
- ? classes.split(/\s+/)
13700
- : [];
13701
- classes.forEach((klass, i) => {
13702
- if (klass && klass.length > 0) {
13703
- className += i > 0 ? " " : "";
13704
- className += isPrefix ? fix + klass : klass + fix;
13705
- }
13706
- });
13707
- return className;
13708
- }
13709
-
13710
- function removeFromArray(arr, val) {
13711
- const index = arr.indexOf(val);
13712
- if (val >= 0) {
13713
- arr.splice(index, 1);
13714
- }
13715
- }
13716
-
13717
- /**
13718
- *
13719
- * @param {NodeList|Node} element
13720
- * @returns {Node[]|Node|undefined}
13721
- */
13722
- function stripCommentsFromElement(element) {
13723
- if (element instanceof NodeList) {
13724
- return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
13725
- } else if (element.nodeType === Node.ELEMENT_NODE) {
13726
- return /** @type {Node} */ (element);
13727
- } else {
13728
- return undefined;
13729
- }
13730
- }
13731
-
13732
- /**
13733
- * @param {NodeList|Node} element
13734
- * @returns {Node}
13735
- */
13736
- function extractElementNode(element) {
13737
- if (!element) return /** @type {Node} */ (element);
13738
- for (let i = 0; i < /** @type {NodeList} */ (element).length; i++) {
13739
- const elm = element[i];
13740
- if (elm.nodeType === Node.ELEMENT_NODE) {
13741
- return elm;
13742
- }
13743
- }
13744
- }
13745
-
13746
- function applyAnimationClassesFactory() {
13747
- return function (element, options) {
13748
- if (options.addClass) {
13749
- element.classList.add(...options.addClass.trim().split(" "));
13750
- options.addClass = null;
13751
- }
13752
- if (options.removeClass) {
13753
- element.classList.remove(...options.removeClass.trim().split(" "));
13754
- options.removeClass = null;
13755
- }
13756
- };
13757
- }
13758
-
13759
- function prepareAnimationOptions(options) {
13760
- options = options || {};
13761
- if (!options.$$prepared) {
13762
- let domOperation = options.domOperation || (() => {});
13763
- options.domOperation = function () {
13764
- options.$$domOperationFired = true;
13765
- domOperation();
13766
- domOperation = () => {};
13767
- };
13768
- options.$$prepared = true;
13769
- }
13770
- return options;
13771
- }
13772
-
13773
- function applyAnimationStyles(element, options) {
13774
- applyAnimationFromStyles(element, options);
13775
- applyAnimationToStyles(element, options);
13776
- }
13777
-
13778
- function applyAnimationFromStyles(element, options) {
13779
- if (options.from) {
13780
- //element.css(options.from);
13781
- options.from = null;
13782
- }
13783
- }
13784
-
13785
- function applyAnimationToStyles(element, options) {
13786
- if (options.to) {
13787
- //element.css(options.to);
13788
- options.to = null;
13789
- }
13790
- }
13791
-
13792
- function mergeAnimationDetails(element, oldAnimation, newAnimation) {
13793
- const target = oldAnimation.options || {};
13794
- const newOptions = newAnimation.options || {};
13795
-
13796
- const toAdd = `${target.addClass || ""} ${newOptions.addClass || ""}`;
13797
- const toRemove = `${target.removeClass || ""} ${newOptions.removeClass || ""}`;
13798
- const classes = resolveElementClasses(
13799
- element.getAttribute("class"),
13800
- toAdd,
13801
- toRemove,
13802
- );
13803
-
13804
- if (newOptions.preparationClasses) {
13805
- target.preparationClasses = concatWithSpace(
13806
- newOptions.preparationClasses,
13807
- target.preparationClasses,
13808
- );
13809
- delete newOptions.preparationClasses;
13810
- }
13811
-
13812
- extend(target, newOptions);
13813
-
13814
- if (classes.addClass) {
13815
- target.addClass = classes.addClass;
13816
- } else {
13817
- target.addClass = null;
13818
- }
13819
-
13820
- if (classes.removeClass) {
13821
- target.removeClass = classes.removeClass;
13822
- } else {
13823
- target.removeClass = null;
13824
- }
13825
-
13826
- oldAnimation.addClass = target.addClass;
13827
- oldAnimation.removeClass = target.removeClass;
13828
-
13829
- return target;
13830
- }
13831
-
13832
- function resolveElementClasses(existing, toAdd, toRemove) {
13833
- const ADD_CLASS = 1;
13834
- const REMOVE_CLASS = -1;
13835
-
13836
- const flags = {};
13837
- existing = splitClassesToLookup(existing);
13838
-
13839
- toAdd = splitClassesToLookup(toAdd);
13840
- Object.keys(toAdd).forEach((key) => {
13841
- flags[key] = ADD_CLASS;
13842
- });
13843
-
13844
- toRemove = splitClassesToLookup(toRemove);
13845
- Object.keys(toRemove).forEach((key) => {
13846
- flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
13847
- });
13848
-
13849
- const classes = {
13850
- addClass: "",
13851
- removeClass: "",
13852
- };
13853
-
13854
- Object.entries(flags).forEach(([klass, val]) => {
13855
- let prop, allow;
13856
- if (val === ADD_CLASS) {
13857
- prop = "addClass";
13858
- allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
13859
- } else if (val === REMOVE_CLASS) {
13860
- prop = "removeClass";
13861
- allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
13862
- }
13863
- if (allow) {
13864
- if (classes[prop].length) {
13865
- classes[prop] += " ";
13866
- }
13867
- classes[prop] += klass;
13868
- }
13869
- });
13870
-
13871
- function splitClassesToLookup(classes) {
13872
- if (isString(classes)) {
13873
- classes = classes.trim().split(" ");
13874
- }
13875
-
13876
- const obj = {};
13877
- if (classes) {
13878
- classes.forEach((klass) => {
13879
- // sometimes the split leaves empty string values
13880
- // incase extra spaces were applied to the options
13881
- if (klass.length) {
13882
- obj[klass] = true;
13883
- }
13884
- });
13885
- }
13886
- return obj;
13887
- }
13888
-
13889
- return classes;
13890
- }
13891
-
13892
- function applyGeneratedPreparationClasses(element, event, options) {
13893
- let classes = "";
13894
- if (event) {
13895
- classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
13896
- }
13897
- if (options.addClass) {
13898
- classes = concatWithSpace(
13899
- classes,
13900
- pendClasses(options.addClass, ADD_CLASS_SUFFIX),
13901
- );
13902
- }
13903
- if (options.removeClass) {
13904
- classes = concatWithSpace(
13905
- classes,
13906
- pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX),
13907
- );
13908
- }
13909
- if (classes.length) {
13910
- options.preparationClasses = classes;
13911
- element.className += ` ${classes}`;
13912
- }
13913
- }
13914
-
13915
- function clearGeneratedClasses(element, options) {
13916
- if (options.preparationClasses) {
13917
- options.preparationClasses
13918
- .split(" ")
13919
- .forEach((cls) => element.classList.remove(cls));
13920
- options.preparationClasses = null;
13921
- }
13922
- if (options.activeClasses) {
13923
- options.activeClasses
13924
- .split(" ")
13925
- .forEach((cls) => element.classList.remove(cls));
13926
- options.activeClasses = null;
13927
- }
13928
- }
13929
-
13930
- function blockKeyframeAnimations(node, applyBlock) {
13931
- const value = applyBlock ? "paused" : "";
13932
- const key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
13933
- applyInlineStyle(node, [key, value]);
13934
- return [key, value];
13935
- }
13936
-
13937
- function applyInlineStyle(node, styleTuple) {
13938
- const prop = styleTuple[0];
13939
- node.style[prop] = styleTuple[1];
13940
- }
13941
-
13942
- function concatWithSpace(a, b) {
13943
- if (!a) return b;
13944
- if (!b) return a;
13945
- return `${a} ${b}`;
13946
- }
13947
-
13948
13961
  /** @typedef {"enter"|"leave"|"move"|"addClass"|"setClass"|"removeClass"} AnimationMethod */
13949
13962
 
13950
13963
  /**
@@ -14332,7 +14345,7 @@ function AnimateProvider($provide) {
14332
14345
  *
14333
14346
  * @param {Element} element - the element which will be inserted into the DOM
14334
14347
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14335
- * @param {Element} after - after the sibling element after which the element will be appended
14348
+ * @param {Element} [after] - after the sibling element after which the element will be appended
14336
14349
  * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14337
14350
  * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
14338
14351
  */
@@ -17810,7 +17823,7 @@ class InterpolateProvider {
17810
17823
  return concat.join("");
17811
17824
  };
17812
17825
 
17813
- return /**@type {import("./interface.js").InterpolationFunction} */ extend(
17826
+ return /**@type {import("./interface.ts").InterpolationFunction} */ extend(
17814
17827
  (context, cb) => {
17815
17828
  let i = 0;
17816
17829
  const ii = expressions.length;
@@ -19478,7 +19491,7 @@ class LocationProvider {
19478
19491
  /**
19479
19492
  * Registers a callback to be called when the URL changes.
19480
19493
  *
19481
- * @param {import("./interface.js").UrlChangeListener} callback - The callback function to register.
19494
+ * @param {import("./interface.ts").UrlChangeListener} callback - The callback function to register.
19482
19495
  * @returns void
19483
19496
  */
19484
19497
  #onUrlChange(callback) {
@@ -20071,16 +20084,9 @@ function nextId() {
20071
20084
  */
20072
20085
  let $parse;
20073
20086
 
20074
- /**@type {import('../../services/exception/exception-handler.js').ErrorHandler} */
20087
+ /**@type {ng.ExceptionHandlerService} */
20075
20088
  let $exceptionHandler;
20076
20089
 
20077
- /**
20078
- * @typedef {Object} AsyncQueueTask
20079
- * @property {Scope} handler
20080
- * @property {Function} fn
20081
- * @property {Object} locals
20082
- */
20083
-
20084
20090
  const $postUpdateQueue = [];
20085
20091
 
20086
20092
  class RootScopeProvider {
@@ -20089,11 +20095,11 @@ class RootScopeProvider {
20089
20095
  }
20090
20096
 
20091
20097
  $get = [
20092
- "$exceptionHandler",
20093
- "$parse",
20098
+ $injectTokens.$exceptionHandler,
20099
+ $injectTokens.$parse,
20094
20100
  /**
20095
- * @param {import('../../services/exception/exception-handler.js').ErrorHandler} exceptionHandler
20096
- * @param {import('../parse/interface.ts').ParseService} parse
20101
+ * @param {ng.ExceptionHandlerService} exceptionHandler
20102
+ * @param {ng.ParseService} parse
20097
20103
  */
20098
20104
  (exceptionHandler, parse) => {
20099
20105
  $exceptionHandler = exceptionHandler;
@@ -20150,27 +20156,6 @@ function createScope(target = {}, context) {
20150
20156
  }
20151
20157
  }
20152
20158
 
20153
- /**
20154
- * Listener function definition.
20155
- * @typedef {Object} Listener
20156
- * @property {Object} originalTarget - The original target object.
20157
- * @property {ListenerFunction} listenerFn - The function invoked when changes are detected.
20158
- * @property {import("../parse/interface.ts").CompiledExpression} watchFn
20159
- * @property {number} id - Deregistration id
20160
- * @property {number} scopeId - The scope that created the Listener
20161
- * @property {string[]} property
20162
- * @property {string} [watchProp] - The original property to watch if different from observed key
20163
- * @property {Proxy} [foreignListener]
20164
- *
20165
- */
20166
-
20167
- /**
20168
- * Listener function type.
20169
- * @callback ListenerFunction
20170
- * @param {*} newValue - The new value of the changed property.
20171
- * @param {Object} originalTarget - The original target object.
20172
- */
20173
-
20174
20159
  /**
20175
20160
  * Decorator for excluding objects from scope observability
20176
20161
  */
@@ -20196,13 +20181,13 @@ class Scope {
20196
20181
  : context
20197
20182
  : undefined;
20198
20183
 
20199
- /** @type {Map<string, Array<Listener>>} Watch listeners */
20184
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners */
20200
20185
  this.watchers = context ? context.watchers : new Map();
20201
20186
 
20202
20187
  /** @type {Map<String, Function[]>} Event listeners */
20203
20188
  this.$$listeners = new Map();
20204
20189
 
20205
- /** @type {Map<string, Array<Listener>>} Watch listeners from other proxies */
20190
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners from other proxies */
20206
20191
  this.foreignListeners = context ? context.foreignListeners : new Map();
20207
20192
 
20208
20193
  /** @type {Set<ProxyConstructor>} */
@@ -20247,7 +20232,7 @@ class Scope {
20247
20232
  ? null
20248
20233
  : context;
20249
20234
 
20250
- /** @type {AsyncQueueTask[]} */
20235
+ /** @type {import('./interface.ts').AsyncQueueTask[]} */
20251
20236
  this.$$asyncQueue = [];
20252
20237
 
20253
20238
  this.filters = [];
@@ -20256,257 +20241,18 @@ class Scope {
20256
20241
  this.$$destroyed = false;
20257
20242
 
20258
20243
  this.scheduled = [];
20259
- }
20260
-
20261
- /**
20262
- * Intercepts and handles property assignments on the target object. If a new value is
20263
- * an object, it will be recursively proxied.
20264
- *
20265
- * @param {Object} target - The target object.
20266
- * @param {string} property - The name of the property being set.
20267
- * @param {*} value - The new value being assigned to the property.
20268
- * @param {Proxy} proxy - The proxy intercepting property access
20269
- * @returns {boolean} - Returns true to indicate success of the operation.
20270
- */
20271
- set(target, property, value, proxy) {
20272
- if (property === "undefined") {
20273
- throw new Error("Attempting to set undefined property");
20274
- }
20275
- if (
20276
- (target.constructor?.$nonscope &&
20277
- Array.isArray(target.constructor.$nonscope) &&
20278
- target.constructor.$nonscope.includes(property)) ||
20279
- (target.$nonscope &&
20280
- Array.isArray(target.$nonscope) &&
20281
- target.$nonscope.includes(property))
20282
- ) {
20283
- target[property] = value;
20284
- return true;
20285
- }
20286
-
20287
- this.$proxy = proxy;
20288
- this.$target = target;
20289
- const oldValue = target[property];
20290
-
20291
- // Handle NaNs
20292
- if (
20293
- oldValue !== undefined &&
20294
- Number.isNaN(oldValue) &&
20295
- Number.isNaN(value)
20296
- ) {
20297
- return true;
20298
- }
20299
- if (oldValue && oldValue[isProxySymbol]) {
20300
- if (Array.isArray(value)) {
20301
- if (oldValue !== value) {
20302
- const listeners = this.watchers.get(property);
20303
-
20304
- if (listeners) {
20305
- this.#scheduleListener(listeners);
20306
- }
20307
-
20308
- const foreignListeners = this.foreignListeners.get(property);
20309
-
20310
- if (foreignListeners) {
20311
- this.#scheduleListener(foreignListeners);
20312
- }
20313
- }
20314
-
20315
- if (this.objectListeners.get(target[property])) {
20316
- this.objectListeners.delete(target[property]);
20317
- }
20318
- target[property] = createScope(value, this);
20319
- this.objectListeners.set(target[property], [property]);
20320
- return true;
20321
- }
20322
-
20323
- if (isObject(value)) {
20324
- if (hasOwn(target, property)) {
20325
- Object.keys(oldValue)
20326
- .filter((x) => !value[x])
20327
- .forEach((k) => {
20328
- delete oldValue[k];
20329
- });
20330
- }
20331
-
20332
- if (oldValue !== value) {
20333
- const listeners = this.watchers.get(property);
20334
-
20335
- if (listeners) {
20336
- this.#scheduleListener(listeners);
20337
- }
20338
-
20339
- const foreignListeners = this.foreignListeners.get(property);
20340
-
20341
- if (foreignListeners) {
20342
- this.#scheduleListener(foreignListeners);
20343
- }
20344
-
20345
- this.#checkeListenersForAllKeys(value);
20346
- }
20347
- target[property] = createScope(value, this);
20348
- //setDeepValue(target[property], value);
20349
- return true;
20350
- }
20351
-
20352
- if (isUndefined(value)) {
20353
- let called = false;
20354
- Object.keys(oldValue.$target).forEach((k) => {
20355
- if (oldValue.$target[k]?.[isProxySymbol]) {
20356
- called = true;
20357
- }
20358
- delete oldValue[k];
20359
- });
20360
-
20361
- target[property] = undefined;
20362
- if (!called) {
20363
- let listeners = this.watchers.get(property);
20364
-
20365
- if (listeners) {
20366
- this.#scheduleListener(listeners);
20367
- }
20368
- }
20369
-
20370
- return true;
20371
- }
20372
-
20373
- if (isDefined(value)) {
20374
- target[property] = value;
20375
- let listeners = this.watchers.get(property);
20376
-
20377
- if (listeners) {
20378
- this.#scheduleListener(listeners);
20379
- }
20380
-
20381
- if (Array.isArray(target)) {
20382
- if (this.objectListeners.has(proxy) && property !== "length") {
20383
- let keys = this.objectListeners.get(proxy);
20384
- keys.forEach((key) => {
20385
- const listeners = this.watchers.get(key);
20386
- if (listeners) {
20387
- this.#scheduleListener(listeners);
20388
- }
20389
- });
20390
- }
20391
- }
20392
-
20393
- return true;
20394
- }
20395
- return true;
20396
- } else {
20397
- if (isUndefined(target[property]) && isProxy(value)) {
20398
- this.foreignProxies.add(value);
20399
- target[property] = value;
20400
- if (!this.watchers.has(property)) {
20401
- return true;
20402
- }
20403
- }
20404
- if (isUndefined(value)) {
20405
- target[property] = value;
20406
- } else {
20407
- target[property] = createScope(value, this);
20408
- }
20409
-
20410
- if (oldValue !== value) {
20411
- let expectedTarget = this.$target;
20412
- let listeners = [];
20413
- // Handle the case where we need to start observing object after a watcher has been set
20414
- if (isUndefined(oldValue) && isObject(target[property])) {
20415
- if (!this.objectListeners.has(target[property])) {
20416
- this.objectListeners.set(target[property], [property]);
20417
- }
20418
- for (const k of Object.keys(value)) {
20419
- this.watchers.get(k)?.forEach((l) => listeners.push(l));
20420
- // overwhrite the context so we pass the owneship test in filter
20421
- expectedTarget = value;
20422
- }
20423
- }
20424
-
20425
- if (Array.isArray(target)) {
20426
- this.watchers.get("length")?.forEach((l) => listeners.push(l));
20427
- }
20428
-
20429
- this.watchers.get(property)?.forEach((l) => listeners.push(l));
20430
- if (listeners.length > 0) {
20431
- // check if the listener actually appllies to this target
20432
- this.#scheduleListener(listeners, (x) => {
20433
- return x.filter((x) => {
20434
- if (!x.watchProp) return true;
20435
- // Compute the expected target based on `watchProp`
20436
- const wrapperExpr = x.watchProp.split(".").slice(0, -1).join(".");
20437
- const expectedHandler = $parse(wrapperExpr)(
20438
- x.originalTarget,
20439
- )?.$handler;
20440
- return expectedTarget === expectedHandler?.$target;
20441
- });
20442
- });
20443
- }
20444
-
20445
- let foreignListeners = this.foreignListeners.get(property);
20446
-
20447
- if (!foreignListeners && this.$parent?.foreignListeners) {
20448
- foreignListeners = this.$parent.foreignListeners.get(property);
20449
- }
20450
- if (foreignListeners) {
20451
- // filter for repeaters
20452
- if (this.$target.$$hashKey) {
20453
- foreignListeners = foreignListeners.filter((x) =>
20454
- x.originalTarget.$$hashKey
20455
- ? x.originalTarget.$$hashKey == this.$target.$$hashKey
20456
- : false,
20457
- );
20458
- }
20459
-
20460
- this.#scheduleListener(foreignListeners);
20461
- }
20462
- }
20463
-
20464
- if (this.objectListeners.has(proxy) && property !== "length") {
20465
- let keys = this.objectListeners.get(proxy);
20466
- keys.forEach((key) => {
20467
- const listeners = this.watchers.get(key);
20468
- if (listeners) {
20469
- if (this.scheduled !== listeners) {
20470
- this.#scheduleListener(listeners);
20471
- }
20472
- }
20473
- });
20474
- }
20475
-
20476
- return true;
20477
- }
20478
- }
20479
-
20480
- /**
20481
- * Intercepts property access on the target object. It checks for specific
20482
- * properties (`watch` and `sync`) and binds their methods. For other properties,
20483
- * it returns the value directly.
20484
- *
20485
- * @param {Object} target - The target object.
20486
- * @param {string|number|symbol} property - The name of the property being accessed.
20487
- * @param {Proxy} proxy - The proxy object being invoked
20488
- * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20489
- */
20490
- get(target, property, proxy) {
20491
- if (property === "$$watchersCount") return calculateWatcherCount(this);
20492
- if (property === isProxySymbol) return true;
20493
-
20494
- if (target[property] && isProxy(target[property])) {
20495
- this.$proxy = target[property];
20496
- } else {
20497
- this.$proxy = proxy;
20498
- }
20499
20244
 
20245
+ /** @private */
20500
20246
  this.propertyMap = {
20501
20247
  $watch: this.$watch.bind(this),
20502
20248
  $new: this.$new.bind(this),
20503
20249
  $newIsolate: this.$newIsolate.bind(this),
20504
20250
  $destroy: this.$destroy.bind(this),
20251
+ $flushQueue: this.$flushQueue.bind(this),
20505
20252
  $eval: this.$eval.bind(this),
20506
20253
  $apply: this.$apply.bind(this),
20507
20254
  $postUpdate: this.$postUpdate.bind(this),
20508
20255
  $isRoot: this.#isRoot.bind(this),
20509
- $target: target,
20510
20256
  $proxy: this.$proxy,
20511
20257
  $on: this.$on.bind(this),
20512
20258
  $emit: this.$emit.bind(this),
@@ -20520,6 +20266,249 @@ class Scope {
20520
20266
  $merge: this.$merge.bind(this),
20521
20267
  $getById: this.$getById.bind(this),
20522
20268
  };
20269
+ }
20270
+
20271
+ /**
20272
+ * Intercepts and handles property assignments on the target object. If a new value is
20273
+ * an object, it will be recursively proxied.
20274
+ *
20275
+ * @param {Object} target - The target object.
20276
+ * @param {string} property - The name of the property being set.
20277
+ * @param {*} value - The new value being assigned to the property.
20278
+ * @param {Proxy} proxy - The proxy intercepting property access
20279
+ * @returns {boolean} - Returns true to indicate success of the operation.
20280
+ */
20281
+ set(target, property, value, proxy) {
20282
+ if (property === "undefined") {
20283
+ throw new Error("Attempting to set undefined property");
20284
+ }
20285
+ if (
20286
+ (target.constructor?.$nonscope &&
20287
+ Array.isArray(target.constructor.$nonscope) &&
20288
+ target.constructor.$nonscope.includes(property)) ||
20289
+ (target.$nonscope &&
20290
+ Array.isArray(target.$nonscope) &&
20291
+ target.$nonscope.includes(property))
20292
+ ) {
20293
+ target[property] = value;
20294
+ return true;
20295
+ }
20296
+
20297
+ this.$proxy = proxy;
20298
+ this.$target = target;
20299
+ const oldValue = target[property];
20300
+
20301
+ // Handle NaNs
20302
+ if (
20303
+ oldValue !== undefined &&
20304
+ Number.isNaN(oldValue) &&
20305
+ Number.isNaN(value)
20306
+ ) {
20307
+ return true;
20308
+ }
20309
+ if (oldValue && oldValue[isProxySymbol]) {
20310
+ if (Array.isArray(value)) {
20311
+ if (oldValue !== value) {
20312
+ const listeners = this.watchers.get(property);
20313
+
20314
+ if (listeners) {
20315
+ this.#scheduleListener(listeners);
20316
+ }
20317
+
20318
+ const foreignListeners = this.foreignListeners.get(property);
20319
+
20320
+ if (foreignListeners) {
20321
+ this.#scheduleListener(foreignListeners);
20322
+ }
20323
+ }
20324
+
20325
+ if (this.objectListeners.get(target[property])) {
20326
+ this.objectListeners.delete(target[property]);
20327
+ }
20328
+ target[property] = createScope(value, this);
20329
+ this.objectListeners.set(target[property], [property]);
20330
+ return true;
20331
+ }
20332
+
20333
+ if (isObject(value)) {
20334
+ if (hasOwn(target, property)) {
20335
+ Object.keys(oldValue)
20336
+ .filter((x) => !value[x])
20337
+ .forEach((k) => {
20338
+ delete oldValue[k];
20339
+ });
20340
+ }
20341
+
20342
+ if (oldValue !== value) {
20343
+ const listeners = this.watchers.get(property);
20344
+
20345
+ if (listeners) {
20346
+ this.#scheduleListener(listeners);
20347
+ }
20348
+
20349
+ const foreignListeners = this.foreignListeners.get(property);
20350
+
20351
+ if (foreignListeners) {
20352
+ this.#scheduleListener(foreignListeners);
20353
+ }
20354
+
20355
+ this.#checkeListenersForAllKeys(value);
20356
+ }
20357
+ target[property] = createScope(value, this);
20358
+ //setDeepValue(target[property], value);
20359
+ return true;
20360
+ }
20361
+
20362
+ if (isUndefined(value)) {
20363
+ let called = false;
20364
+ Object.keys(oldValue.$target).forEach((k) => {
20365
+ if (oldValue.$target[k]?.[isProxySymbol]) {
20366
+ called = true;
20367
+ }
20368
+ delete oldValue[k];
20369
+ });
20370
+
20371
+ target[property] = undefined;
20372
+ if (!called) {
20373
+ let listeners = this.watchers.get(property);
20374
+
20375
+ if (listeners) {
20376
+ this.#scheduleListener(listeners);
20377
+ }
20378
+ }
20379
+
20380
+ return true;
20381
+ }
20382
+
20383
+ if (isDefined(value)) {
20384
+ target[property] = value;
20385
+ let listeners = this.watchers.get(property);
20386
+
20387
+ if (listeners) {
20388
+ this.#scheduleListener(listeners);
20389
+ }
20390
+
20391
+ if (Array.isArray(target)) {
20392
+ if (this.objectListeners.has(proxy) && property !== "length") {
20393
+ let keys = this.objectListeners.get(proxy);
20394
+ keys.forEach((key) => {
20395
+ const listeners = this.watchers.get(key);
20396
+ if (listeners) {
20397
+ this.#scheduleListener(listeners);
20398
+ }
20399
+ });
20400
+ }
20401
+ }
20402
+
20403
+ return true;
20404
+ }
20405
+ return true;
20406
+ } else {
20407
+ if (isUndefined(target[property]) && isProxy(value)) {
20408
+ this.foreignProxies.add(value);
20409
+ target[property] = value;
20410
+ if (!this.watchers.has(property)) {
20411
+ return true;
20412
+ }
20413
+ }
20414
+ if (isUndefined(value)) {
20415
+ target[property] = value;
20416
+ } else {
20417
+ target[property] = createScope(value, this);
20418
+ }
20419
+
20420
+ if (oldValue !== value) {
20421
+ let expectedTarget = this.$target;
20422
+ let listeners = [];
20423
+ // Handle the case where we need to start observing object after a watcher has been set
20424
+ if (isUndefined(oldValue) && isObject(target[property])) {
20425
+ if (!this.objectListeners.has(target[property])) {
20426
+ this.objectListeners.set(target[property], [property]);
20427
+ }
20428
+ for (const k of Object.keys(value)) {
20429
+ this.watchers.get(k)?.forEach((l) => listeners.push(l));
20430
+ // overwhrite the context so we pass the owneship test in filter
20431
+ expectedTarget = value;
20432
+ }
20433
+ }
20434
+
20435
+ if (Array.isArray(target)) {
20436
+ this.watchers.get("length")?.forEach((l) => listeners.push(l));
20437
+ }
20438
+
20439
+ this.watchers.get(property)?.forEach((l) => listeners.push(l));
20440
+ if (listeners.length > 0) {
20441
+ // check if the listener actually appllies to this target
20442
+ this.#scheduleListener(listeners, (x) => {
20443
+ return x.filter((x) => {
20444
+ if (!x.watchProp) return true;
20445
+ // Compute the expected target based on `watchProp`
20446
+ const wrapperExpr = x.watchProp.split(".").slice(0, -1).join(".");
20447
+ const expectedHandler = $parse(wrapperExpr)(
20448
+ x.originalTarget,
20449
+ )?.$handler;
20450
+ return expectedTarget === expectedHandler?.$target;
20451
+ });
20452
+ });
20453
+ }
20454
+
20455
+ let foreignListeners = this.foreignListeners.get(property);
20456
+
20457
+ if (!foreignListeners && this.$parent?.foreignListeners) {
20458
+ foreignListeners = this.$parent.foreignListeners.get(property);
20459
+ }
20460
+ if (foreignListeners) {
20461
+ // filter for repeaters
20462
+ if (this.$target.$$hashKey) {
20463
+ foreignListeners = foreignListeners.filter((x) =>
20464
+ x.originalTarget["$$hashKey"]
20465
+ ? x.originalTarget["$$hashKey"] === this.$target.$$hashKey
20466
+ : false,
20467
+ );
20468
+ }
20469
+
20470
+ this.#scheduleListener(foreignListeners);
20471
+ }
20472
+ }
20473
+
20474
+ if (this.objectListeners.has(proxy) && property !== "length") {
20475
+ let keys = this.objectListeners.get(proxy);
20476
+ keys.forEach((key) => {
20477
+ const listeners = this.watchers.get(key);
20478
+ if (listeners) {
20479
+ if (this.scheduled !== listeners) {
20480
+ this.#scheduleListener(listeners);
20481
+ }
20482
+ }
20483
+ });
20484
+ }
20485
+
20486
+ return true;
20487
+ }
20488
+ }
20489
+
20490
+ /**
20491
+ * Intercepts property access on the target object. It checks for specific
20492
+ * properties (`watch` and `sync`) and binds their methods. For other properties,
20493
+ * it returns the value directly.
20494
+ *
20495
+ * @param {Object} target - The target object.
20496
+ * @param {string|number|symbol} property - The name of the property being accessed.
20497
+ * @param {Proxy} proxy - The proxy object being invoked
20498
+ * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20499
+ */
20500
+ get(target, property, proxy) {
20501
+ if (property === "$$watchersCount") return calculateWatcherCount(this);
20502
+ if (property === isProxySymbol) return true;
20503
+
20504
+ if (target[property] && isProxy(target[property])) {
20505
+ this.$proxy = target[property];
20506
+ } else {
20507
+ this.$proxy = proxy;
20508
+ }
20509
+
20510
+ this.propertyMap.$target = target;
20511
+ this.propertyMap.$proxy = proxy;
20523
20512
 
20524
20513
  if (
20525
20514
  Array.isArray(target) &&
@@ -20614,7 +20603,7 @@ class Scope {
20614
20603
  }
20615
20604
 
20616
20605
  /**
20617
- * @param {Listener[]} listeners
20606
+ * @param {import('./interface.ts').Listener[]} listeners
20618
20607
  * @param {Function} filter
20619
20608
  */
20620
20609
  #scheduleListener(listeners, filter = (val) => val) {
@@ -20638,7 +20627,7 @@ class Scope {
20638
20627
  * function is invoked when changes to that property are detected.
20639
20628
  *
20640
20629
  * @param {string} watchProp - An expression to be watched in the context of this model.
20641
- * @param {ListenerFunction} [listenerFn] - A function to execute when changes are detected on watched context.
20630
+ * @param {import('./interface.ts').ListenerFunction} [listenerFn] - A function to execute when changes are detected on watched context.
20642
20631
  * @param {boolean} [lazy] - A flag to indicate if the listener should be invoked immediately. Defaults to false.
20643
20632
  */
20644
20633
  $watch(watchProp, listenerFn, lazy = false) {
@@ -20660,7 +20649,7 @@ class Scope {
20660
20649
  return () => {};
20661
20650
  }
20662
20651
 
20663
- /** @type {Listener} */
20652
+ /** @type {import('./interface.ts').Listener} */
20664
20653
  const listener = {
20665
20654
  originalTarget: this.$target,
20666
20655
  listenerFn: listenerFn,
@@ -20772,7 +20761,7 @@ class Scope {
20772
20761
 
20773
20762
  let potentialProxy = $parse(
20774
20763
  watchProp.split(".").slice(0, -1).join("."),
20775
- )(listener.originalTarget);
20764
+ )(/** @type {Scope} */ (listener.originalTarget));
20776
20765
  if (potentialProxy && this.foreignProxies.has(potentialProxy)) {
20777
20766
  potentialProxy.$handler.#registerForeignKey(key, listener);
20778
20767
  potentialProxy.$handler.#scheduleListener([listener]);
@@ -20970,21 +20959,21 @@ class Scope {
20970
20959
  return true;
20971
20960
  }
20972
20961
 
20973
- // deregisterForeignKey(key, id) {
20974
- // const listenerList = this.foreignListeners.get(key);
20975
- // if (!listenerList) return false;
20962
+ deregisterForeignKey(key, id) {
20963
+ const listenerList = this.foreignListeners.get(key);
20964
+ if (!listenerList) return false;
20976
20965
 
20977
- // const index = listenerList.findIndex((x) => x.id === id);
20978
- // if (index === -1) return false;
20966
+ const index = listenerList.findIndex((x) => x.id === id);
20967
+ if (index === -1) return false;
20979
20968
 
20980
- // listenerList.splice(index, 1);
20981
- // if (listenerList.length) {
20982
- // this.foreignListeners.set(key, listenerList);
20983
- // } else {
20984
- // this.foreignListeners.delete(key);
20985
- // }
20986
- // return true;
20987
- // }
20969
+ listenerList.splice(index, 1);
20970
+ if (listenerList.length) {
20971
+ this.foreignListeners.set(key, listenerList);
20972
+ } else {
20973
+ this.foreignListeners.delete(key);
20974
+ }
20975
+ return true;
20976
+ }
20988
20977
 
20989
20978
  $eval(expr, locals) {
20990
20979
  const fn = $parse(expr);
@@ -21017,7 +21006,7 @@ class Scope {
21017
21006
  }
21018
21007
 
21019
21008
  /**
21020
- * @param {import('../../interface.js').Expression} expr
21009
+ * @param {import('../../interface.ts').Expression} expr
21021
21010
  * @returns {any}
21022
21011
  */
21023
21012
  $apply(expr) {
@@ -21198,12 +21187,12 @@ class Scope {
21198
21187
 
21199
21188
  /**
21200
21189
  * @internal
21201
- * @param {Listener} listener - The property path that was changed.
21190
+ * @param {import('./interface.ts').Listener} listener - The property path that was changed.
21202
21191
  */
21203
21192
  #notifyListener(listener, target) {
21204
21193
  const { originalTarget, listenerFn, watchFn } = listener;
21205
21194
  try {
21206
- let newVal = watchFn(originalTarget);
21195
+ let newVal = watchFn(/** @type {Scope} */ (originalTarget));
21207
21196
  if (isUndefined(newVal)) {
21208
21197
  newVal = watchFn(target);
21209
21198
  }
@@ -21233,6 +21222,13 @@ class Scope {
21233
21222
  }
21234
21223
  }
21235
21224
 
21225
+ /* @ignore */
21226
+ $flushQueue() {
21227
+ while ($postUpdateQueue.length) {
21228
+ $postUpdateQueue.shift()();
21229
+ }
21230
+ }
21231
+
21236
21232
  /**
21237
21233
  * Searches the scope instance
21238
21234
  *
@@ -21743,7 +21739,7 @@ const ngMessageDefaultDirective = ngMessageDirectiveFactory(true);
21743
21739
 
21744
21740
  /**
21745
21741
  * @param {boolean} isDefault
21746
- * @returns {(any) => import("../../interface.js").Directive}
21742
+ * @returns {(any) => import("../../interface.ts").Directive}
21747
21743
  */
21748
21744
  function ngMessageDirectiveFactory(isDefault) {
21749
21745
  ngMessageDirective.$inject = ["$animate"];
@@ -21950,6 +21946,9 @@ function ngShowAriaDirective($aria) {
21950
21946
  return $aria.$$watchExpr("ngShow", "aria-hidden", [], true);
21951
21947
  }
21952
21948
 
21949
+ /**
21950
+ * @return {ng.Directive}
21951
+ */
21953
21952
  function ngMessagesAriaDirective() {
21954
21953
  return {
21955
21954
  restrict: "A",
@@ -21965,18 +21964,21 @@ function ngMessagesAriaDirective() {
21965
21964
  }
21966
21965
 
21967
21966
  ngClickAriaDirective.$inject = [$injectTokens.$aria, $injectTokens.$parse];
21967
+
21968
+ /**
21969
+ * @param $aria
21970
+ * @param {ng.ParseService} $parse
21971
+ * @return {ng.Directive}
21972
+ */
21968
21973
  function ngClickAriaDirective($aria, $parse) {
21969
21974
  return {
21970
21975
  restrict: "A",
21971
21976
  compile(_elem, attr) {
21972
21977
  if (hasOwn(attr, ARIA_DISABLE_ATTR)) return;
21973
21978
 
21974
- const fn = $parse(attr.ngClick);
21979
+ const fn = $parse(attr["ngClick"]);
21975
21980
 
21976
- /**
21977
- * @param {Element} elem
21978
- */
21979
- return function (scope, elem, attr) {
21981
+ return (scope, elem, attr) => {
21980
21982
  if (!isNodeOneOf(elem, nativeAriaNodeNames)) {
21981
21983
  if ($aria.config("bindRoleForClick") && !elem.hasAttribute("role")) {
21982
21984
  elem.setAttribute("role", "button");
@@ -22013,10 +22015,6 @@ function ngClickAriaDirective($aria, $parse) {
22013
22015
  // See https://github.com/angular/angular.js/issues/16664
22014
22016
  event.preventDefault();
22015
22017
  }
22016
- scope.$apply(callback);
22017
- }
22018
-
22019
- function callback() {
22020
22018
  fn(scope, { $event: event });
22021
22019
  }
22022
22020
  },
@@ -22338,6 +22336,7 @@ function registerRestorableStyles(backup, node, properties) {
22338
22336
  }
22339
22337
 
22340
22338
  function AnimateCssProvider() {
22339
+ let activeClasses;
22341
22340
  this.$get = [
22342
22341
  "$$AnimateRunner",
22343
22342
  "$$animateCache",
@@ -22681,10 +22680,7 @@ function AnimateCssProvider() {
22681
22680
  return closeAndReturnNoopAnimator();
22682
22681
  }
22683
22682
 
22684
- let activeClasses = pendClasses(
22685
- preparationClasses,
22686
- ACTIVE_CLASS_SUFFIX,
22687
- );
22683
+ activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
22688
22684
 
22689
22685
  if (options.delay != null) {
22690
22686
  if (typeof options.delay !== "boolean") {
@@ -22821,7 +22817,9 @@ function AnimateCssProvider() {
22821
22817
 
22822
22818
  if (events && events.length) {
22823
22819
  // Remove the transitionend / animationend listener(s)
22824
- element.off(events.join(" "), onAnimationProgress);
22820
+ events.forEach((i) =>
22821
+ element.removeEventListener(i, onAnimationProgress),
22822
+ );
22825
22823
  }
22826
22824
 
22827
22825
  // Cancel the fallback closing timeout and remove the timer data
@@ -23256,11 +23254,6 @@ function AnimateQueueProvider($animateProvider) {
23256
23254
  ) {
23257
23255
  const activeAnimationsLookup = new Map();
23258
23256
  const disabledElementsLookup = new Map();
23259
- let animationsEnabled = null;
23260
-
23261
- function removeFromDisabledElementsLookup(evt) {
23262
- disabledElementsLookup.delete(evt.target);
23263
- }
23264
23257
 
23265
23258
  function postDigestTaskFactory() {
23266
23259
  let postDigestCalled = false;
@@ -23300,11 +23293,6 @@ function AnimateQueueProvider($animateProvider) {
23300
23293
  // any animations are triggered.
23301
23294
  $rootScope.$postUpdate(() => {
23302
23295
  $rootScope.$postUpdate(() => {
23303
- // we check for null directly in the event that the application already called
23304
- // .enabled() with whatever arguments that it provided it with
23305
- if (animationsEnabled === null) {
23306
- animationsEnabled = true;
23307
- }
23308
23296
  });
23309
23297
  });
23310
23298
  }
@@ -23443,47 +23431,6 @@ function AnimateQueueProvider($animateProvider) {
23443
23431
  options.domOperation = domOperation;
23444
23432
  return queueAnimation(element, event, options);
23445
23433
  },
23446
-
23447
- // this method has four signatures:
23448
- // () - global getter
23449
- // (bool) - global setter
23450
- // (element) - element getter
23451
- // (element, bool) - element setter<F37>
23452
- enabled(element, bool) {
23453
- const argCount = arguments.length;
23454
-
23455
- if (argCount === 0) {
23456
- // () - Global getter
23457
- bool = !!animationsEnabled;
23458
- } else {
23459
- const hasElement = isElement(element);
23460
-
23461
- if (!hasElement) {
23462
- // (bool) - Global setter
23463
- bool = animationsEnabled = !!element;
23464
- } else {
23465
- const node = element;
23466
-
23467
- if (argCount === 1) {
23468
- // (element) - Element getter
23469
- bool = !disabledElementsLookup.get(node);
23470
- } else {
23471
- // (element, bool) - Element setter
23472
- if (!disabledElementsLookup.has(node)) {
23473
- // The element is added to the map for the first time.
23474
- // Create a listener to remove it on `$destroy` (to avoid memory leak).
23475
- element.addEventListener(
23476
- "$destroy",
23477
- removeFromDisabledElementsLookup,
23478
- );
23479
- }
23480
- disabledElementsLookup.set(node, !bool);
23481
- }
23482
- }
23483
- }
23484
-
23485
- return bool;
23486
- },
23487
23434
  };
23488
23435
 
23489
23436
  return $animate;
@@ -23540,6 +23487,7 @@ function AnimateQueueProvider($animateProvider) {
23540
23487
  if (options.to && !isObject(options.to)) {
23541
23488
  options.to = null;
23542
23489
  }
23490
+
23543
23491
  // If animations are hard-disabled for the whole application there is no need to continue.
23544
23492
  // There are also situations where a directive issues an animation for a JQLite wrapper that
23545
23493
  // contains only comment nodes. In this case, there is no way we can perform an animation.
@@ -23552,7 +23500,6 @@ function AnimateQueueProvider($animateProvider) {
23552
23500
  close();
23553
23501
  return runner;
23554
23502
  }
23555
-
23556
23503
  const isStructural = ["enter", "move", "leave"].indexOf(event) >= 0;
23557
23504
 
23558
23505
  // This is a hard disable of all animations the element itself, therefore there is no need to
@@ -23788,6 +23735,8 @@ function AnimateQueueProvider($animateProvider) {
23788
23735
  });
23789
23736
  });
23790
23737
 
23738
+ // Since we don't have digest any more - trigger queue here
23739
+ setTimeout($rootScope.$flushQueue, 0);
23791
23740
  return runner;
23792
23741
 
23793
23742
  function notifyProgress(runner, event, phase, data) {
@@ -23951,14 +23900,14 @@ function AnimateQueueProvider($animateProvider) {
23951
23900
  // TODO: use caching here to speed things up for detection
23952
23901
  // TODO: add documentation
23953
23902
 
23954
- AnimateJsProvider.$inject = ["$animateProvider"];
23903
+ AnimateJsProvider.$inject = [$injectTokens.$animate + "Provider"];
23955
23904
  function AnimateJsProvider($animateProvider) {
23956
23905
  this.$get = [
23957
23906
  $injectTokens.$injector,
23958
23907
  "$$AnimateRunner",
23959
23908
  /**
23960
23909
  *
23961
- * @param {import("../core/di/internal-injector").InjectorService} $injector
23910
+ * @param {ng.InjectorService} $injector
23962
23911
  * @param {*} $$AnimateRunner
23963
23912
  * @returns
23964
23913
  */
@@ -24817,8 +24766,8 @@ function AnimationProvider() {
24817
24766
  }
24818
24767
 
24819
24768
  /**
24820
- * @typedef {import('./interface.js').RafScheduler} RafScheduler
24821
- * @typedef {import('../interface.js').ServiceProvider} ServiceProvider
24769
+ * @typedef {import('./interface.ts').RafScheduler} RafScheduler
24770
+ * @typedef {import('../interface.ts').ServiceProvider} ServiceProvider
24822
24771
  */
24823
24772
 
24824
24773
  /**
@@ -25333,9 +25282,9 @@ function AnimateJsDriverProvider($$animationProvider) {
25333
25282
  ];
25334
25283
  }
25335
25284
 
25336
- ngAnimateSwapDirective.$inject = ["$animate"];
25285
+ ngAnimateSwapDirective.$inject = [$injectTokens.$animate];
25337
25286
  /**
25338
- * @returns {import('../interface.ts').Directive}
25287
+ * @returns {ng.Directive}
25339
25288
  */
25340
25289
  function ngAnimateSwapDirective($animate) {
25341
25290
  return {
@@ -25344,10 +25293,10 @@ function ngAnimateSwapDirective($animate) {
25344
25293
  terminal: true,
25345
25294
  priority: 550, // We use 550 here to ensure that the directive is caught before others,
25346
25295
  // but after `ngIf` (at priority 600).
25347
- link(scope, $element, attrs, ctrl, $transclude) {
25296
+ link(scope, $element, attrs, _ctrl, $transclude) {
25348
25297
  let previousElement;
25349
25298
  let previousScope;
25350
- scope.$watch(attrs["ngAnimateSwap"] || attrs["for"], (value) => {
25299
+ scope.$watch(attrs.ngAnimateSwap || attrs.for, (value) => {
25351
25300
  if (previousElement) {
25352
25301
  $animate.leave(previousElement);
25353
25302
  }
@@ -27574,7 +27523,7 @@ class PathUtils {
27574
27523
  * @param {PathNode[]} fromPath
27575
27524
  * @param {PathNode[]} toPath
27576
27525
  * @param {boolean} [reloadState]
27577
- * @returns {import("../transition/interface.js").TreeChanges}
27526
+ * @returns {import("../transition/interface.ts").TreeChanges}
27578
27527
  */
27579
27528
  static treeChanges(fromPath, toPath, reloadState) {
27580
27529
  const max = Math.min(fromPath.length, toPath.length);
@@ -28309,25 +28258,6 @@ ViewService.matches = (ngViewsByFqn, ngView) => (viewConfig) => {
28309
28258
  return vc.$ngViewContextAnchor === (ngViewContext && ngViewContext.name);
28310
28259
  };
28311
28260
 
28312
- /**
28313
- * An object for Transition Hook Phases
28314
- * @enum {number}
28315
- * @readonly
28316
- */
28317
- const TransitionHookPhase = {
28318
- CREATE: 0,
28319
- BEFORE: 1,
28320
- RUN: 2,
28321
- SUCCESS: 3,
28322
- ERROR: 4,
28323
- };
28324
-
28325
- /** An object for Transition Hook Scopes */
28326
- const TransitionHookScope = {
28327
- TRANSITION: 0,
28328
- STATE: 1,
28329
- };
28330
-
28331
28261
  /**
28332
28262
  * An object for Transition Rejection reasons.
28333
28263
  * @enum {number}
@@ -28447,7 +28377,7 @@ class Rejection {
28447
28377
  }
28448
28378
  }
28449
28379
 
28450
- /** @typedef {import('../../interface.js').ServiceProvider} ServiceProvider
28380
+ /** @typedef {import('../../interface.ts').ServiceProvider} ServiceProvider
28451
28381
 
28452
28382
  /**
28453
28383
  * Configurable provider for an injectable event bus
@@ -28804,6 +28734,31 @@ const defaultOptions = {
28804
28734
  bind: null,
28805
28735
  };
28806
28736
 
28737
+ /**
28738
+ * Enum representing the different phases of a transition hook.
28739
+ *
28740
+ * @readonly
28741
+ * @enum {number}
28742
+ */
28743
+ const TransitionHookPhase = Object.freeze({
28744
+ CREATE: 0,
28745
+ BEFORE: 1,
28746
+ RUN: 2,
28747
+ SUCCESS: 3,
28748
+ ERROR: 4,
28749
+ });
28750
+
28751
+ /**
28752
+ * Enum representing the scope in which a transition hook operates.
28753
+ *
28754
+ * @readonly
28755
+ * @enum {number}
28756
+ */
28757
+ const TransitionHookScope = Object.freeze({
28758
+ TRANSITION: 0,
28759
+ STATE: 1,
28760
+ });
28761
+
28807
28762
  class TransitionHook {
28808
28763
  /**
28809
28764
  * Chains together an array of TransitionHooks.
@@ -30622,7 +30577,6 @@ class TransitionProvider {
30622
30577
  }
30623
30578
 
30624
30579
  _defineCoreEvents() {
30625
- const Phase = TransitionHookPhase;
30626
30580
  const TH = TransitionHook;
30627
30581
  const paths = this._criteriaPaths;
30628
30582
  const NORMAL_SORT = false,
@@ -30630,7 +30584,7 @@ class TransitionProvider {
30630
30584
  const SYNCHRONOUS = true;
30631
30585
  this._defineEvent(
30632
30586
  "onCreate",
30633
- Phase.CREATE,
30587
+ TransitionHookPhase.CREATE,
30634
30588
  0,
30635
30589
  paths.to,
30636
30590
  NORMAL_SORT,
@@ -30638,15 +30592,21 @@ class TransitionProvider {
30638
30592
  TH.THROW_ERROR,
30639
30593
  SYNCHRONOUS,
30640
30594
  );
30641
- this._defineEvent("onBefore", Phase.BEFORE, 0, paths.to);
30642
- this._defineEvent("onStart", Phase.RUN, 0, paths.to);
30643
- this._defineEvent("onExit", Phase.RUN, 100, paths.exiting, REVERSE_SORT);
30644
- this._defineEvent("onRetain", Phase.RUN, 200, paths.retained);
30645
- this._defineEvent("onEnter", Phase.RUN, 300, paths.entering);
30646
- this._defineEvent("onFinish", Phase.RUN, 400, paths.to);
30595
+ this._defineEvent("onBefore", TransitionHookPhase.BEFORE, 0, paths.to);
30596
+ this._defineEvent("onStart", TransitionHookPhase.RUN, 0, paths.to);
30597
+ this._defineEvent(
30598
+ "onExit",
30599
+ TransitionHookPhase.RUN,
30600
+ 100,
30601
+ paths.exiting,
30602
+ REVERSE_SORT,
30603
+ );
30604
+ this._defineEvent("onRetain", TransitionHookPhase.RUN, 200, paths.retained);
30605
+ this._defineEvent("onEnter", TransitionHookPhase.RUN, 300, paths.entering);
30606
+ this._defineEvent("onFinish", TransitionHookPhase.RUN, 400, paths.to);
30647
30607
  this._defineEvent(
30648
30608
  "onSuccess",
30649
- Phase.SUCCESS,
30609
+ TransitionHookPhase.SUCCESS,
30650
30610
  0,
30651
30611
  paths.to,
30652
30612
  NORMAL_SORT,
@@ -30656,7 +30616,7 @@ class TransitionProvider {
30656
30616
  );
30657
30617
  this._defineEvent(
30658
30618
  "onError",
30659
- Phase.ERROR,
30619
+ TransitionHookPhase.ERROR,
30660
30620
  0,
30661
30621
  paths.to,
30662
30622
  NORMAL_SORT,
@@ -30922,7 +30882,7 @@ class StateProvider {
30922
30882
 
30923
30883
  /**
30924
30884
  *
30925
- * @param {import("./interface.js").StateDeclaration} definition
30885
+ * @param {import("./interface.ts").StateDeclaration} definition
30926
30886
  */
30927
30887
  state(definition) {
30928
30888
  if (!definition.name) {
@@ -32222,7 +32182,7 @@ function encodeDashes(str) {
32222
32182
  );
32223
32183
  }
32224
32184
 
32225
- /** @typedef {import('./interface.js').StateDeclaration} StateDeclaration */
32185
+ /** @typedef {import('./interface.ts').StateDeclaration} StateDeclaration */
32226
32186
 
32227
32187
  /**
32228
32188
  * Internal representation of a ng-router state.
@@ -32245,7 +32205,7 @@ class StateObject {
32245
32205
  includes = undefined;
32246
32206
 
32247
32207
  /**
32248
- * @param {import('./interface.js').StateDeclaration} config
32208
+ * @param {import('./interface.ts').StateDeclaration} config
32249
32209
  */
32250
32210
  constructor(config) {
32251
32211
  Object.assign(this, config);
@@ -32253,7 +32213,7 @@ class StateObject {
32253
32213
  return this;
32254
32214
  };
32255
32215
  /**
32256
- * @type {import('./interface.js').StateDeclaration}
32216
+ * @type {import('./interface.ts').StateDeclaration}
32257
32217
  */
32258
32218
  this.self = config;
32259
32219
  /**
@@ -34642,7 +34602,7 @@ function $StateRefActiveDirective(
34642
34602
  * ```
34643
34603
  */
34644
34604
 
34645
- /** @type {import("../../interface.js").AnnotatedDirectiveFactory} */
34605
+ /** @type {import("../../interface.ts").AnnotatedDirectiveFactory} */
34646
34606
  let ngView = [
34647
34607
  "$view",
34648
34608
  "$animate",
@@ -34653,7 +34613,7 @@ let ngView = [
34653
34613
  * @param {*} $animate
34654
34614
  * @param {*} $viewScroll
34655
34615
  * @param {*} $interpolate
34656
- * @returns {import("../../interface.js").Directive}
34616
+ * @returns {import("../../interface.ts").Directive}
34657
34617
  */
34658
34618
  function $ViewDirective($view, $animate, $viewScroll, $interpolate) {
34659
34619
  function getRenderer() {
@@ -35079,7 +35039,8 @@ function ngSetterDirective($parse, $log) {
35079
35039
  }
35080
35040
 
35081
35041
  /**
35082
- * @param {"get" | "delete" | "post" | "put"} method
35042
+ * @param {"get" | "delete" | "post" | "put"} method - HTTP method applied to request
35043
+ * @param {string} [attrOverride] - Custom name to use for the attribute
35083
35044
  * @returns {ng.DirectiveFactory}
35084
35045
  */
35085
35046
  function defineDirective(method, attrOverride) {
@@ -35093,6 +35054,7 @@ function defineDirective(method, attrOverride) {
35093
35054
  $injectTokens.$parse,
35094
35055
  $injectTokens.$state,
35095
35056
  $injectTokens.$sse,
35057
+ $injectTokens.$animate,
35096
35058
  ];
35097
35059
  return directive;
35098
35060
  }
@@ -35112,15 +35074,11 @@ const ngPutDirective = defineDirective("put");
35112
35074
  /** @type {ng.DirectiveFactory} */
35113
35075
  const ngSseDirective = defineDirective("get", "ngSse");
35114
35076
 
35115
- /**
35116
- * @typedef {"click" | "change" | "submit"} EventType
35117
- */
35118
-
35119
35077
  /**
35120
35078
  * Selects DOM event to listen for based on the element type.
35121
35079
  *
35122
35080
  * @param {Element} element - The DOM element to inspect.
35123
- * @returns {EventType} The name of the event to listen for.
35081
+ * @returns {"click" | "change" | "submit"} The name of the event to listen for.
35124
35082
  */
35125
35083
  function getEventNameForElement(element) {
35126
35084
  const tag = element.tagName.toLowerCase();
@@ -35132,89 +35090,6 @@ function getEventNameForElement(element) {
35132
35090
  return "click";
35133
35091
  }
35134
35092
 
35135
- /**
35136
- * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35137
- *
35138
- * @param {string} html - The HTML string returned from the server.
35139
- * @param {import("./interface.ts").SwapModeType} swap
35140
- * @param {Element} target - The target DOM element to apply the swap to.
35141
- * @param {ng.Scope} scope
35142
- * @param {ng.CompileService} $compile
35143
- */
35144
- function handleSwapResponse(html, swap, target, scope, $compile) {
35145
- let nodes = [];
35146
- if (!["textcontent", "delete", "none"].includes(swap)) {
35147
- if (!html) {
35148
- return;
35149
- }
35150
-
35151
- if (isObject(html)) {
35152
- scope.$merge(html);
35153
- return;
35154
- }
35155
-
35156
- const compiled = $compile(html)(scope);
35157
- nodes =
35158
- compiled instanceof DocumentFragment
35159
- ? Array.from(compiled.childNodes)
35160
- : [compiled];
35161
- }
35162
-
35163
- switch (swap) {
35164
- case "innerHTML":
35165
- target.replaceChildren(...nodes);
35166
- break;
35167
-
35168
- case "outerHTML": {
35169
- const parent = target.parentNode;
35170
- if (!parent) return;
35171
- const frag = document.createDocumentFragment();
35172
- nodes.forEach((n) => frag.appendChild(n));
35173
- parent.replaceChild(frag, target);
35174
- break;
35175
- }
35176
-
35177
- case "textContent":
35178
- target.textContent = html;
35179
- break;
35180
-
35181
- case "beforebegin":
35182
- nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35183
- break;
35184
-
35185
- case "afterbegin":
35186
- nodes
35187
- .slice()
35188
- .reverse()
35189
- .forEach((node) => target.insertBefore(node, target.firstChild));
35190
- break;
35191
-
35192
- case "beforeend":
35193
- nodes.forEach((node) => target.appendChild(node));
35194
- break;
35195
-
35196
- case "afterend":
35197
- nodes
35198
- .slice()
35199
- .reverse()
35200
- .forEach((node) =>
35201
- target.parentNode.insertBefore(node, target.nextSibling),
35202
- );
35203
- break;
35204
-
35205
- case "delete":
35206
- target.remove();
35207
- break;
35208
-
35209
- case "none":
35210
- break;
35211
-
35212
- default:
35213
- target.replaceChildren(...nodes);
35214
- break;
35215
- }
35216
- }
35217
-
35218
35093
  /**
35219
35094
  * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
35220
35095
  *
@@ -35223,6 +35098,8 @@ function handleSwapResponse(html, swap, target, scope, $compile) {
35223
35098
  * @returns {ng.DirectiveFactory}
35224
35099
  */
35225
35100
  function createHttpDirective(method, attrName) {
35101
+ let content = undefined;
35102
+
35226
35103
  /**
35227
35104
  * @param {ng.HttpService} $http
35228
35105
  * @param {ng.CompileService} $compile
@@ -35232,7 +35109,125 @@ function createHttpDirective(method, attrName) {
35232
35109
  * @param {ng.SseService} $sse
35233
35110
  * @returns {ng.Directive}
35234
35111
  */
35235
- return function ($http, $compile, $log, $parse, $state, $sse) {
35112
+ return function ($http, $compile, $log, $parse, $state, $sse, $animate) {
35113
+ /**
35114
+ * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35115
+ *
35116
+ * @param {string | Object} html - The HTML string or object returned from the server.
35117
+ * @param {import("./interface.ts").SwapModeType} swap
35118
+ * @param {ng.Scope} scope
35119
+ * @param {ng.Attributes} attrs
35120
+ * @param {Element} element
35121
+ */
35122
+ function handleSwapResponse(html, swap, scope, attrs, element) {
35123
+ let animationEnabled = false;
35124
+ if (attrs.animate) {
35125
+ animationEnabled = true;
35126
+ }
35127
+ let nodes = [];
35128
+ if (!["textcontent", "delete", "none"].includes(swap)) {
35129
+ if (!html) return;
35130
+ const compiled = $compile(html)(scope);
35131
+ nodes =
35132
+ compiled instanceof DocumentFragment
35133
+ ? Array.from(compiled.childNodes)
35134
+ : [compiled];
35135
+ }
35136
+
35137
+ const targetSelector = attrs["target"];
35138
+ const target = targetSelector
35139
+ ? document.querySelector(targetSelector)
35140
+ : element;
35141
+
35142
+ if (!target) {
35143
+ $log.warn(`${attrName}: target "${targetSelector}" not found`);
35144
+ return;
35145
+ }
35146
+
35147
+ switch (swap) {
35148
+ case "innerHTML":
35149
+ if (animationEnabled) {
35150
+ if (content) {
35151
+ $animate.leave(content).done(() => {
35152
+ content = nodes[0];
35153
+ $animate.enter(nodes[0], target);
35154
+ scope.$flushQueue();
35155
+ });
35156
+ scope.$flushQueue();
35157
+ } else {
35158
+ content = nodes[0];
35159
+ $animate.enter(nodes[0], target);
35160
+ scope.$flushQueue();
35161
+ }
35162
+ } else {
35163
+ target.replaceChildren(...nodes);
35164
+ }
35165
+ break;
35166
+
35167
+ case "outerHTML": {
35168
+ const parent = target.parentNode;
35169
+ if (!parent) return;
35170
+ const frag = document.createDocumentFragment();
35171
+ nodes.forEach((n) => frag.appendChild(n));
35172
+ if (animationEnabled) {
35173
+ const placeholder = document.createComment("placeholder");
35174
+ target.parentNode.insertBefore(placeholder, target.nextSibling);
35175
+ $animate.leave(target).done(() => {
35176
+ const insertedNodes = Array.from(frag.childNodes);
35177
+ insertedNodes.forEach((n) =>
35178
+ $animate.enter(n, parent, placeholder),
35179
+ );
35180
+ content = insertedNodes;
35181
+ scope.$flushQueue();
35182
+ });
35183
+ scope.$flushQueue();
35184
+ } else {
35185
+ parent.replaceChild(frag, target);
35186
+ }
35187
+ break;
35188
+ }
35189
+
35190
+ case "textContent":
35191
+ target.textContent = html;
35192
+ break;
35193
+
35194
+ case "beforebegin":
35195
+ nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35196
+ break;
35197
+
35198
+ case "afterbegin":
35199
+ nodes
35200
+ .slice()
35201
+ .reverse()
35202
+ .forEach((node) => target.insertBefore(node, target.firstChild));
35203
+ break;
35204
+
35205
+ case "beforeend":
35206
+ nodes.forEach((node) => target.appendChild(node));
35207
+ break;
35208
+
35209
+ case "afterend":
35210
+ nodes
35211
+ .slice()
35212
+ .reverse()
35213
+ .forEach((node) =>
35214
+ target.parentNode.insertBefore(node, target.nextSibling),
35215
+ );
35216
+ break;
35217
+
35218
+ case "delete":
35219
+ target.remove();
35220
+ break;
35221
+
35222
+ case "none":
35223
+ break;
35224
+
35225
+ default:
35226
+ target.replaceChildren(...nodes);
35227
+ break;
35228
+ }
35229
+ }
35230
+
35236
35231
  /**
35237
35232
  * Collects form data from the element or its associated form.
35238
35233
  *
@@ -35246,15 +35241,12 @@ function createHttpDirective(method, attrName) {
35246
35241
  const tag = element.tagName.toLowerCase();
35247
35242
 
35248
35243
  if (tag === "form") {
35249
- /** @type {HTMLFormElement} */
35250
35244
  form = /** @type {HTMLFormElement} */ (element);
35251
35245
  } else if ("form" in element && element.form) {
35252
- /** @type {HTMLFormElement} */
35253
35246
  form = /** @type {HTMLFormElement} */ (element.form);
35254
35247
  } else if (element.hasAttribute("form")) {
35255
35248
  const formId = element.getAttribute("form");
35256
35249
  if (formId) {
35257
- /** @type {HTMLElement | null} */
35258
35250
  const maybeForm = document.getElementById(formId);
35259
35251
  if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
35260
35252
  form = /** @type {HTMLFormElement} */ (maybeForm);
@@ -35292,13 +35284,10 @@ function createHttpDirective(method, attrName) {
35292
35284
  return {
35293
35285
  restrict: "A",
35294
35286
  link(scope, element, attrs) {
35295
- const eventName =
35296
- attrs["trigger"] ||
35297
- /** @type {EventType} */ getEventNameForElement(element);
35298
-
35287
+ const eventName = attrs.trigger || getEventNameForElement(element);
35299
35288
  const tag = element.tagName.toLowerCase();
35300
35289
 
35301
- if (isDefined(attrs["latch"])) {
35290
+ if (isDefined(attrs.latch)) {
35302
35291
  attrs.$observe(
35303
35292
  "latch",
35304
35293
  callBackAfterFirst(() =>
@@ -35314,24 +35303,14 @@ function createHttpDirective(method, attrName) {
35314
35303
  element.dispatchEvent(new Event(eventName));
35315
35304
  intervalId = setInterval(
35316
35305
  () => element.dispatchEvent(new Event(eventName)),
35317
- parseInt(attrs["interval"]) || 1000,
35306
+ parseInt(attrs.interval) || 1000,
35318
35307
  );
35319
35308
  }
35320
35309
 
35321
35310
  element.addEventListener(eventName, async (event) => {
35322
35311
  if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35323
35312
  if (tag === "form") event.preventDefault();
35324
- const swap = attrs["swap"] || "innerHTML";
35325
- const targetSelector = attrs["target"];
35326
- const target = targetSelector
35327
- ? document.querySelector(targetSelector)
35328
- : element;
35329
-
35330
- if (!target) {
35331
- $log.warn(`${attrName}: target "${targetSelector}" not found`);
35332
- return;
35333
- }
35334
-
35313
+ const swap = attrs.swap || "innerHTML";
35335
35314
  const url = attrs[attrName];
35336
35315
  if (!url) {
35337
35316
  $log.warn(`${attrName}: no URL specified`);
@@ -35339,56 +35318,57 @@ function createHttpDirective(method, attrName) {
35339
35318
  }
35340
35319
 
35341
35320
  const handler = (res) => {
35342
- if (isDefined(attrs["loading"])) {
35321
+ if (isDefined(attrs.loading)) {
35343
35322
  attrs.$set("loading", false);
35344
35323
  }
35345
35324
 
35346
- if (isDefined(attrs["loadingClass"])) {
35347
- attrs.$removeClass(attrs["loadingClass"]);
35325
+ if (isDefined(attrs.loadingClass)) {
35326
+ attrs.$removeClass(attrs.loadingClass);
35348
35327
  }
35349
35328
 
35350
35329
  const html = res.data;
35351
35330
  if (200 <= res.status && res.status <= 299) {
35352
- if (isDefined(attrs["success"])) {
35353
- $parse(attrs["success"])(scope, { $res: html });
35331
+ if (isDefined(attrs.success)) {
35332
+ $parse(attrs.success)(scope, { $res: html });
35354
35333
  }
35355
35334
 
35356
- if (isDefined(attrs["stateSuccess"])) {
35357
- $state.go(attrs["stateSuccess"]);
35335
+ if (isDefined(attrs.stateSuccess)) {
35336
+ $state.go(attrs.stateSuccess);
35358
35337
  }
35359
35338
  } else if (400 <= res.status && res.status <= 599) {
35360
- if (isDefined(attrs["error"])) {
35361
- $parse(attrs["error"])(scope, { $res: html });
35339
+ if (isDefined(attrs.error)) {
35340
+ $parse(attrs.error)(scope, { $res: html });
35362
35341
  }
35363
35342
 
35364
- if (isDefined(attrs["stateError"])) {
35365
- $state.go(attrs["stateError"]);
35343
+ if (isDefined(attrs.stateError)) {
35344
+ $state.go(attrs.stateError);
35366
35345
  }
35367
35346
  }
35368
35347
 
35369
- handleSwapResponse(
35370
- html,
35371
- /** @type {import("./interface.ts").SwapModeType} */ (swap),
35372
- target,
35373
- scope,
35374
- $compile,
35375
- );
35348
+ if (isObject(html)) {
35349
+ if (attrs.target) {
35350
+ scope.$eval(`${attrs.target} = ${JSON.stringify(html)}`);
35351
+ } else {
35352
+ scope.$merge(html);
35353
+ }
35354
+ } else if (isString(html)) {
35355
+ handleSwapResponse(html, swap, scope, attrs, element);
35356
+ }
35376
35357
  };
35377
- if (isDefined(attrs["delay"])) {
35378
- await wait(parseInt(attrs["delay"]) | 0);
35379
- }
35380
35358
 
35381
- if (throttled) {
35382
- return;
35359
+ if (isDefined(attrs.delay)) {
35360
+ await wait(parseInt(attrs.delay) | 0);
35383
35361
  }
35384
35362
 
35385
- if (isDefined(attrs["throttle"])) {
35363
+ if (throttled) return;
35364
+
35365
+ if (isDefined(attrs.throttle)) {
35386
35366
  throttled = true;
35387
35367
  attrs.$set("throttled", true);
35388
35368
  setTimeout(() => {
35389
35369
  attrs.$set("throttled", false);
35390
35370
  throttled = false;
35391
- }, parseInt(attrs["throttle"]));
35371
+ }, parseInt(attrs.throttle));
35392
35372
  }
35393
35373
 
35394
35374
  if (isDefined(attrs["loading"])) {
@@ -35396,13 +35376,13 @@ function createHttpDirective(method, attrName) {
35396
35376
  }
35397
35377
 
35398
35378
  if (isDefined(attrs["loadingClass"])) {
35399
- attrs.$addClass(attrs["loadingClass"]);
35379
+ attrs.$addClass(attrs.loadingClass);
35400
35380
  }
35401
35381
 
35402
35382
  if (method === "post" || method === "put") {
35403
35383
  let data;
35404
35384
  const config = {};
35405
- if (attrs["enctype"]) {
35385
+ if (attrs.enctype) {
35406
35386
  config.headers = {
35407
35387
  "Content-Type": attrs["enctype"],
35408
35388
  };
@@ -35412,11 +35392,10 @@ function createHttpDirective(method, attrName) {
35412
35392
  }
35413
35393
  $http[method](url, data, config).then(handler).catch(handler);
35414
35394
  } else {
35415
- // If SSE mode is enabled
35416
- if (method === "get" && attrs["ngSse"]) {
35395
+ if (method === "get" && attrs.ngSse) {
35417
35396
  const sseUrl = url;
35418
35397
  const config = {
35419
- withCredentials: attrs["withCredentials"] === "true",
35398
+ withCredentials: attrs.withCredentials === "true",
35420
35399
  transformMessage: (data) => {
35421
35400
  try {
35422
35401
  return JSON.parse(data);
@@ -35426,9 +35405,9 @@ function createHttpDirective(method, attrName) {
35426
35405
  },
35427
35406
  onOpen: () => {
35428
35407
  $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
35429
- if (isDefined(attrs["loading"])) attrs.$set("loading", false);
35430
- if (isDefined(attrs["loadingClass"]))
35431
- attrs.$removeClass(attrs["loadingClass"]);
35408
+ if (isDefined(attrs.loading)) attrs.$set("loading", false);
35409
+ if (isDefined(attrs.loadingClass))
35410
+ attrs.$removeClass(attrs.loadingClass);
35432
35411
  },
35433
35412
  onMessage: (data) => {
35434
35413
  const res = { status: 200, data };
@@ -35439,12 +35418,15 @@ function createHttpDirective(method, attrName) {
35439
35418
  const res = { status: 500, data: err };
35440
35419
  handler(res);
35441
35420
  },
35421
+ onReconnect: (count) => {
35422
+ $log.info(`ngSse: reconnected ${count} time(s)`);
35423
+ if (attrs.onReconnect)
35424
+ $parse(attrs.onReconnect)(scope, { $count: count });
35425
+ },
35442
35426
  };
35443
35427
 
35444
- // Open the SSE connection using the injected service
35445
35428
  const source = $sse(sseUrl, config);
35446
35429
 
35447
- // Cleanup on scope destroy
35448
35430
  scope.$on("$destroy", () => {
35449
35431
  $log.info(`${attrName}: closing SSE connection`);
35450
35432
  source.close();
@@ -35459,7 +35441,6 @@ function createHttpDirective(method, attrName) {
35459
35441
  scope.$on("$destroy", () => clearInterval(intervalId));
35460
35442
  }
35461
35443
 
35462
- // Eagerly execute for 'load' event
35463
35444
  if (eventName == "load") {
35464
35445
  element.dispatchEvent(new Event("load"));
35465
35446
  }
@@ -35540,38 +35521,54 @@ function ngElDirective() {
35540
35521
  * const source = $sse('/events', {
35541
35522
  * onMessage: (data) => console.log(data),
35542
35523
  * onError: (err) => console.error(err),
35543
- * withCredentials: true
35524
+ * retryDelay: 2000,
35525
+ * heartbeatTimeout: 10000,
35544
35526
  * });
35545
35527
  *
35546
- * // later:
35547
35528
  * source.close();
35548
35529
  */
35549
-
35550
35530
  class SseProvider {
35551
35531
  constructor() {
35552
35532
  /**
35553
35533
  * Optional provider-level defaults
35554
35534
  * @type {ng.SseConfig}
35555
35535
  */
35556
- this.defaults = {};
35536
+ this.defaults = {
35537
+ retryDelay: 1000,
35538
+ maxRetries: Infinity,
35539
+ heartbeatTimeout: 15000, // 15 seconds
35540
+ transformMessage(data) {
35541
+ try {
35542
+ return JSON.parse(data);
35543
+ } catch {
35544
+ return data;
35545
+ }
35546
+ },
35547
+ };
35557
35548
  }
35558
35549
 
35559
35550
  /**
35560
35551
  * Returns the $sse service function
35561
35552
  * @returns {ng.SseService}
35562
35553
  */
35563
- $get =
35564
- () =>
35565
- (url, config = {}) => {
35566
- const finalUrl = this.#buildUrl(url, config.params);
35567
- return this.#createEventSource(finalUrl, config);
35568
- };
35554
+ $get = [
35555
+ $injectTokens.$log,
35556
+ /** @param {ng.LogService} log */
35557
+ (log) => {
35558
+ this.$log = log;
35559
+ return (url, config = {}) => {
35560
+ const mergedConfig = { ...this.defaults, ...config };
35561
+ const finalUrl = this.#buildUrl(url, mergedConfig.params);
35562
+ return this.#createConnection(finalUrl, mergedConfig);
35563
+ };
35564
+ },
35565
+ ];
35569
35566
 
35570
35567
  /**
35571
35568
  * Build URL with query parameters
35572
- * @param {string} url - Base URL
35573
- * @param {Record<string, any>=} params - Query parameters
35574
- * @returns {string} URL with serialized query string
35569
+ * @param {string} url
35570
+ * @param {Record<string, any>=} params
35571
+ * @returns {string}
35575
35572
  */
35576
35573
  #buildUrl(url, params) {
35577
35574
  if (!params) return url;
@@ -35582,37 +35579,81 @@ class SseProvider {
35582
35579
  }
35583
35580
 
35584
35581
  /**
35585
- * Create and manage an EventSource
35586
- * @param {string} url - URL for SSE connection
35587
- * @param {ng.SseConfig} config - Configuration object
35588
- * @returns {EventSource} The EventSource instance wrapped as SseService
35582
+ * Creates a managed SSE connection with reconnect and heartbeat
35583
+ * @param {string} url
35584
+ * @param {ng.SseConfig} config
35585
+ * @returns {import("./interface.ts").SseConnection}
35589
35586
  */
35590
- #createEventSource(url, config) {
35591
- const es = new EventSource(url, {
35592
- withCredentials: !!config.withCredentials,
35593
- });
35587
+ #createConnection(url, config) {
35588
+ let es;
35589
+ let retryCount = 0;
35590
+ let closed = false;
35591
+ let heartbeatTimer;
35594
35592
 
35595
- if (config.onOpen) {
35596
- es.addEventListener("open", (e) => config.onOpen(e));
35597
- }
35593
+ const connect = () => {
35594
+ if (closed) return;
35598
35595
 
35599
- es.addEventListener("message", (e) => {
35600
- let data = e.data;
35601
- try {
35602
- data = config.transformMessage
35603
- ? config.transformMessage(data)
35604
- : JSON.parse(data);
35605
- } catch {
35606
- // leave as raw string if not JSON
35607
- }
35608
- config.onMessage?.(data, e);
35609
- });
35596
+ es = new EventSource(url, {
35597
+ withCredentials: !!config.withCredentials,
35598
+ });
35610
35599
 
35611
- if (config.onError) {
35612
- es.addEventListener("error", (e) => config.onError(e));
35613
- }
35600
+ es.addEventListener("open", (e) => {
35601
+ retryCount = 0;
35602
+ config.onOpen?.(e);
35603
+ if (config.heartbeatTimeout) resetHeartbeat();
35604
+ });
35605
+
35606
+ es.addEventListener("message", (e) => {
35607
+ let data = e.data;
35608
+ try {
35609
+ data = config.transformMessage ? config.transformMessage(data) : data;
35610
+ } catch {
35611
+ /* empty */
35612
+ }
35613
+ config.onMessage?.(data, e);
35614
+ if (config.heartbeatTimeout) resetHeartbeat();
35615
+ });
35614
35616
 
35615
- return es;
35617
+ es.addEventListener("error", (err) => {
35618
+ config.onError?.(err);
35619
+ if (closed) return;
35620
+ es.close();
35621
+
35622
+ if (retryCount < config.maxRetries) {
35623
+ retryCount++;
35624
+ config.onReconnect?.(retryCount);
35625
+ setTimeout(connect, config.retryDelay);
35626
+ } else {
35627
+ this.$log.warn("SSE: Max retries reached");
35628
+ }
35629
+ });
35630
+ };
35631
+
35632
+ const resetHeartbeat = () => {
35633
+ clearTimeout(heartbeatTimer);
35634
+ heartbeatTimer = setTimeout(() => {
35635
+ this.$log.warn("SSE: heartbeat timeout, reconnecting...");
35636
+ es.close();
35637
+ config.onReconnect?.(++retryCount);
35638
+ connect();
35639
+ }, config.heartbeatTimeout);
35640
+ };
35641
+
35642
+ connect();
35643
+
35644
+ return {
35645
+ close() {
35646
+ closed = true;
35647
+ clearTimeout(heartbeatTimer);
35648
+ es.close();
35649
+ },
35650
+ connect() {
35651
+ if (closed == false) {
35652
+ close();
35653
+ }
35654
+ connect();
35655
+ },
35656
+ };
35616
35657
  }
35617
35658
  }
35618
35659
 
@@ -35669,6 +35710,248 @@ function ngViewportDirective() {
35669
35710
  };
35670
35711
  }
35671
35712
 
35713
+ ngWorkerDirective.$inject = ["$worker", $injectTokens.$parse, $injectTokens.$log];
35714
+ /**
35715
+ * ngWorker directive factory
35716
+ * Usage: <div ng-worker="workerName" data-params="{{ expression }}" data-on-result="callback($result)"></div>
35717
+ */
35718
+ function ngWorkerDirective($worker, $parse, $log) {
35719
+ return {
35720
+ restrict: "A",
35721
+ link(scope, element, attrs) {
35722
+ const workerName = attrs.ngWorker;
35723
+ if (!workerName) {
35724
+ $log.warn("ngWorker: missing worker name");
35725
+ return;
35726
+ }
35727
+
35728
+ const eventName = attrs.trigger || getEventNameForElement(element);
35729
+
35730
+ let throttled = false;
35731
+ let intervalId;
35732
+
35733
+ if (isDefined(attrs.latch)) {
35734
+ attrs.$observe(
35735
+ "latch",
35736
+ callBackAfterFirst(() => element.dispatchEvent(new Event(eventName))),
35737
+ );
35738
+ }
35739
+
35740
+ if (isDefined(attrs.interval)) {
35741
+ element.dispatchEvent(new Event(eventName));
35742
+ intervalId = setInterval(
35743
+ () => element.dispatchEvent(new Event(eventName)),
35744
+ parseInt(attrs.interval) || 1000,
35745
+ );
35746
+ }
35747
+
35748
+ const worker = $worker(workerName, {
35749
+ onMessage: (result) => {
35750
+ if (isDefined(attrs.dataOnResult)) {
35751
+ $parse(attrs.dataOnResult)(scope, { $result: result });
35752
+ } else {
35753
+ const swap = attrs.swap || "innerHTML";
35754
+ handleSwap(result, swap, element);
35755
+ }
35756
+ },
35757
+ onError: (err) => {
35758
+ $log.error(`[ng-worker:${workerName}]`, err);
35759
+ if (isDefined(attrs.dataOnError)) {
35760
+ $parse(attrs.dataOnError)(scope, { $error: err });
35761
+ } else {
35762
+ element.textContent = "Error";
35763
+ }
35764
+ },
35765
+ });
35766
+
35767
+ element.addEventListener(eventName, async () => {
35768
+ if (element.disabled) return;
35769
+
35770
+ if (isDefined(attrs.delay)) {
35771
+ await wait(parseInt(attrs.delay) || 0);
35772
+ }
35773
+
35774
+ if (throttled) return;
35775
+
35776
+ if (isDefined(attrs.throttle)) {
35777
+ throttled = true;
35778
+ attrs.$set("throttled", true);
35779
+ setTimeout(() => {
35780
+ attrs.$set("throttled", false);
35781
+ throttled = false;
35782
+ }, parseInt(attrs.throttle));
35783
+ }
35784
+
35785
+ let params;
35786
+ try {
35787
+ params = attrs.params ? scope.$eval(attrs.params) : undefined;
35788
+ } catch (err) {
35789
+ $log.error("ngWorker: failed to evaluate data-params", err);
35790
+ params = undefined;
35791
+ }
35792
+
35793
+ worker.post(params);
35794
+ });
35795
+
35796
+ if (intervalId) {
35797
+ scope.$on("$destroy", () => clearInterval(intervalId));
35798
+ }
35799
+
35800
+ if (eventName === "load") {
35801
+ element.dispatchEvent(new Event("load"));
35802
+ }
35803
+ },
35804
+ };
35805
+ }
35806
+
35807
+ /**
35808
+ * Swap result into DOM based on strategy
35809
+ */
35810
+ function handleSwap(result, swap, element) {
35811
+ switch (swap) {
35812
+ case "outerHTML": {
35813
+ const parent = element.parentNode;
35814
+ if (!parent) return;
35815
+ const temp = document.createElement("div");
35816
+ temp.innerHTML = result;
35817
+ parent.replaceChild(temp.firstChild, element);
35818
+ break;
35819
+ }
35820
+ case "textContent":
35821
+ element.textContent = result;
35822
+ break;
35823
+ case "beforebegin":
35824
+ element.insertAdjacentHTML("beforebegin", result);
35825
+ break;
35826
+ case "afterbegin":
35827
+ element.insertAdjacentHTML("afterbegin", result);
35828
+ break;
35829
+ case "beforeend":
35830
+ element.insertAdjacentHTML("beforeend", result);
35831
+ break;
35832
+ case "afterend":
35833
+ element.insertAdjacentHTML("afterend", result);
35834
+ break;
35835
+ case "innerHTML":
35836
+ default:
35837
+ element.innerHTML = result;
35838
+ break;
35839
+ }
35840
+ }
35841
+
35842
+ /**
35843
+ * Worker Provider
35844
+ *
35845
+ * Usage:
35846
+ * const worker = $worker('./math.worker.js', {
35847
+ * onMessage: (data) => console.log('Result:', data),
35848
+ * onError: (err) => console.error('Worker error:', err),
35849
+ * autoTerminate: false,
35850
+ * transformMessage: (d) => d,
35851
+ * });
35852
+ *
35853
+ * worker.post({ action: 'fib', n: 20 });
35854
+ * worker.terminate();
35855
+ */
35856
+ class WorkerProvider {
35857
+ /**
35858
+ * @type {ng.LogService}
35859
+ */
35860
+ $log;
35861
+ constructor() {
35862
+ /**
35863
+ * Optional provider-level defaults
35864
+ * @type {ng.WorkerConfig}
35865
+ */
35866
+ this.defaults = {
35867
+ autoTerminate: false,
35868
+ transformMessage(data) {
35869
+ try {
35870
+ return JSON.parse(data);
35871
+ } catch {
35872
+ return data;
35873
+ }
35874
+ },
35875
+ };
35876
+ }
35877
+
35878
+ /**
35879
+ * Returns the $worker service function
35880
+ * @returns {ng.WorkerService}
35881
+ */
35882
+ $get = [
35883
+ $injectTokens.$log,
35884
+ /** @param {ng.LogService} log */
35885
+ (log) => {
35886
+ this.$log = log;
35887
+ return (scriptPath, config = {}) => {
35888
+ const merged = { ...this.defaults, ...config };
35889
+ return this.#createWorker(scriptPath, merged);
35890
+ };
35891
+ },
35892
+ ];
35893
+
35894
+ /**
35895
+ * Creates a managed Web Worker instance
35896
+ * @param {string | URL} scriptPath
35897
+ * @param {ng.WorkerConfig} config
35898
+ * @returns {import("./interface.ts").WorkerConnection}
35899
+ */
35900
+ #createWorker(scriptPath, config) {
35901
+ if (!scriptPath) throw new Error("Worker script path required");
35902
+
35903
+ let worker = new Worker(scriptPath, { type: "module" });
35904
+ let terminated = false;
35905
+
35906
+ const reconnect = () => {
35907
+ if (terminated) return;
35908
+ this.$log.info("Worker: restarting...");
35909
+ worker.terminate();
35910
+ worker = new Worker(scriptPath, { type: "module" });
35911
+ wire(worker);
35912
+ };
35913
+
35914
+ const wire = (w) => {
35915
+ w.onmessage = (e) => {
35916
+ let data = e.data;
35917
+ try {
35918
+ data = config.transformMessage ? config.transformMessage(data) : data;
35919
+ } catch {
35920
+ /* no-op */
35921
+ }
35922
+ config.onMessage?.(data, e);
35923
+ };
35924
+
35925
+ w.onerror = (err) => {
35926
+ config.onError?.(err);
35927
+ if (config.autoRestart) reconnect();
35928
+ };
35929
+ };
35930
+
35931
+ wire(worker);
35932
+ let that = this;
35933
+ return {
35934
+ post(data) {
35935
+ if (terminated) return that.$log.warn("Worker already terminated");
35936
+ try {
35937
+ worker.postMessage(data);
35938
+ } catch (err) {
35939
+ that.$log.error("Worker post failed", err);
35940
+ }
35941
+ },
35942
+ terminate() {
35943
+ terminated = true;
35944
+ worker.terminate();
35945
+ },
35946
+ restart() {
35947
+ if (terminated)
35948
+ return that.$log.warn("Worker cannot restart after terminate");
35949
+ reconnect();
35950
+ },
35951
+ };
35952
+ }
35953
+ }
35954
+
35672
35955
  /**
35673
35956
  * Initializes core `ng` module.
35674
35957
  * @param {import('./angular.js').Angular} angular
@@ -35681,7 +35964,7 @@ function registerNgModule(angular) {
35681
35964
  [],
35682
35965
  [
35683
35966
  $injectTokens.$provide,
35684
- /** @param {import("./interface.js").Provider} $provide */
35967
+ /** @param {import("./interface.ts").Provider} $provide */
35685
35968
  ($provide) => {
35686
35969
  // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
35687
35970
  $provide.provider({
@@ -35747,6 +36030,7 @@ function registerNgModule(angular) {
35747
36030
  ngValue: ngValueDirective,
35748
36031
  ngModelOptions: ngModelOptionsDirective,
35749
36032
  ngViewport: ngViewportDirective,
36033
+ ngWorker: ngWorkerDirective,
35750
36034
  })
35751
36035
  .directive({
35752
36036
  input: hiddenInputBrowserCacheDirective,
@@ -35814,6 +36098,7 @@ function registerNgModule(angular) {
35814
36098
  $url: UrlService,
35815
36099
  $stateRegistry: StateRegistryProvider,
35816
36100
  $eventBus: PubSubProvider,
36101
+ $worker: WorkerProvider,
35817
36102
  });
35818
36103
  },
35819
36104
  ],
@@ -35845,7 +36130,7 @@ class Angular {
35845
36130
  /**
35846
36131
  * @type {string} `version` from `package.json`
35847
36132
  */
35848
- this.version = "0.9.9"; //inserted via rollup plugin
36133
+ this.version = "0.10.0"; //inserted via rollup plugin
35849
36134
 
35850
36135
  /** @type {!Array<string|any>} */
35851
36136
  this.bootsrappedModules = [];
@@ -36068,7 +36353,7 @@ class Angular {
36068
36353
  * @param {string} name The name of the module to create or retrieve.
36069
36354
  * @param {Array.<string>} [requires] If specified then new module is being created. If
36070
36355
  * unspecified then the module is being retrieved for further configuration.
36071
- * @param {import("./interface.js").Injectable<any>} [configFn] Optional configuration function for the module that gets
36356
+ * @param {import("./interface.ts").Injectable<any>} [configFn] Optional configuration function for the module that gets
36072
36357
  * passed to {@link NgModule.config NgModule.config()}.
36073
36358
  * @returns {NgModule} A newly registered module.
36074
36359
  */