@angular-wave/angular.ts 0.9.8 → 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 (53) 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 +6 -63
  10. package/@types/core/compile/inteface.d.ts +82 -0
  11. package/@types/core/controller/controller.d.ts +1 -1
  12. package/@types/core/di/ng-module.d.ts +14 -14
  13. package/@types/core/scope/interface.d.ts +18 -0
  14. package/@types/core/scope/scope.d.ts +16 -97
  15. package/@types/directive/aria/aria.d.ts +11 -13
  16. package/@types/directive/attrs/attrs.d.ts +2 -2
  17. package/@types/directive/channel/channel.d.ts +3 -5
  18. package/@types/directive/cloak/cloak.d.ts +2 -2
  19. package/@types/directive/events/events.d.ts +16 -0
  20. package/@types/directive/http/http.d.ts +4 -22
  21. package/@types/directive/if/if.d.ts +2 -4
  22. package/@types/directive/include/include.d.ts +4 -4
  23. package/@types/directive/messages/messages.d.ts +3 -3
  24. package/@types/directive/observe/observe.d.ts +2 -5
  25. package/@types/directive/options/options.d.ts +2 -2
  26. package/@types/directive/transclude/transclude.d.ts +4 -4
  27. package/@types/directive/viewport/viewport.d.ts +4 -0
  28. package/@types/directive/worker/worker.d.ts +15 -0
  29. package/@types/interface.d.ts +6 -5
  30. package/@types/namespace.d.ts +69 -40
  31. package/@types/router/directives/view-directive.d.ts +2 -2
  32. package/@types/router/path/path-utils.d.ts +2 -2
  33. package/@types/router/state/state-object.d.ts +6 -6
  34. package/@types/router/state/state-service.d.ts +3 -3
  35. package/@types/router/template-factory.d.ts +1 -1
  36. package/@types/router/transition/hook-builder.d.ts +1 -1
  37. package/@types/router/transition/interface.d.ts +1 -12
  38. package/@types/router/transition/transition-hook.d.ts +31 -0
  39. package/@types/router/transition/transition-service.d.ts +1 -1
  40. package/@types/router/transition/transition.d.ts +2 -2
  41. package/@types/services/pubsub/pubsub.d.ts +2 -2
  42. package/@types/services/sse/interface.d.ts +27 -1
  43. package/@types/services/sse/sse.d.ts +4 -3
  44. package/@types/services/worker/interface.d.ts +12 -0
  45. package/@types/services/worker/worker.d.ts +31 -0
  46. package/@types/shared/url-utils/url-utils.d.ts +14 -14
  47. package/README.md +2 -2
  48. package/dist/angular-ts.esm.js +1462 -1147
  49. package/dist/angular-ts.umd.js +1462 -1147
  50. package/dist/angular-ts.umd.min.js +1 -1
  51. package/dist/angular.css +1 -0
  52. package/package.json +4 -3
  53. package/css/angular.css +0 -16
@@ -1,4 +1,4 @@
1
- /* Version: 0.9.8 - October 26, 2025 19:05:36 */
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).
@@ -4020,10 +4383,11 @@ const ngEventDirectives = {};
4020
4383
  .forEach((eventName) => {
4021
4384
  const directiveName = directiveNormalize(`ng-${eventName}`);
4022
4385
  ngEventDirectives[directiveName] = [
4023
- "$parse",
4024
- "$exceptionHandler",
4386
+ $injectTokens.$parse,
4387
+ $injectTokens.$exceptionHandler,
4388
+
4025
4389
  /**
4026
- * @param {import("../../core/parse/interface.ts").ParseService} $parse
4390
+ * @param {ng.ParseService} $parse
4027
4391
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4028
4392
  * @returns
4029
4393
  */
@@ -4056,14 +4420,58 @@ function createEventDirective(
4056
4420
  restrict: "A",
4057
4421
  compile(_element, attr) {
4058
4422
  const fn = $parse(attr[directiveName]);
4059
- return function ngEventHandler(scope, element) {
4060
- element.addEventListener(eventName, (event) => {
4423
+ return (scope, element) => {
4424
+ const handler = (event) => {
4061
4425
  try {
4062
4426
  fn(scope, { $event: event });
4063
4427
  } catch (error) {
4064
4428
  $exceptionHandler(error);
4065
4429
  }
4066
- });
4430
+ };
4431
+ element.addEventListener(eventName, handler);
4432
+
4433
+ scope.$on("$destroy", () =>
4434
+ element.removeEventListener(eventName, handler),
4435
+ );
4436
+ };
4437
+ },
4438
+ };
4439
+ }
4440
+
4441
+ /**
4442
+ *
4443
+ * @param {ng.ParseService} $parse
4444
+ * @param {ng.ExceptionHandlerService} $exceptionHandler
4445
+ * @param {ng.WindowService} $window
4446
+ * @param {string} directiveName
4447
+ * @param {string} eventName
4448
+ * @returns {ng.Directive}
4449
+ */
4450
+ function createWindowEventDirective(
4451
+ $parse,
4452
+ $exceptionHandler,
4453
+ $window,
4454
+ directiveName,
4455
+ eventName,
4456
+ ) {
4457
+ return {
4458
+ restrict: "A",
4459
+ compile(_element, attr) {
4460
+ const fn = $parse(attr[directiveName]);
4461
+ return (scope) => {
4462
+ const handler = (event) => {
4463
+ try {
4464
+ fn(scope, { $event: event });
4465
+ } catch (error) {
4466
+ $exceptionHandler(error);
4467
+ }
4468
+ };
4469
+
4470
+ $window.addEventListener(eventName, handler);
4471
+
4472
+ scope.$on("$destroy", () =>
4473
+ $window.removeEventListener(eventName, handler),
4474
+ );
4067
4475
  };
4068
4476
  },
4069
4477
  };
@@ -4073,16 +4481,13 @@ const $compileMinErr$1 = minErr("$compile");
4073
4481
  const SIMPLE_ATTR_NAME = /^\w/;
4074
4482
  const specialAttrHolder = document.createElement("div");
4075
4483
 
4076
- /**
4077
- * @implements {Record<string, any>}
4078
- */
4079
4484
  class Attributes {
4080
4485
  static $nonscope = true;
4081
4486
 
4082
4487
  /**
4083
- * @param {import('../scope/scope.js').Scope} $rootScope
4488
+ * @param {ng.Scope} $rootScope
4084
4489
  * @param {*} $animate
4085
- * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
4490
+ * @param {ng.ExceptionHandlerService} $exceptionHandler
4086
4491
  * @param {*} $sce
4087
4492
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
4088
4493
  * @param {Object} [attributesToCopy]
@@ -4395,19 +4800,18 @@ function tokenDifference(str1, str2) {
4395
4800
  /**
4396
4801
  * @param {string} source - the name of the attribute to be observed
4397
4802
  * @param {string} prop - the scope property to be updated with attribute value
4398
- * @returns {import("../../interface.ts").Directive}
4803
+ * @returns {ng.Directive}
4399
4804
  */
4400
4805
  function ngObserveDirective(source, prop) {
4401
4806
  return {
4402
4807
  restrict: "A",
4403
4808
  compile: () => (scope, element) => {
4404
- const targetElement = element;
4405
4809
  if (prop === "") {
4406
4810
  prop = source;
4407
4811
  }
4408
4812
  const normalized = kebabToCamel(prop);
4409
4813
  if (!scope[normalized]) {
4410
- scope[normalized] = targetElement.getAttribute(source);
4814
+ scope[normalized] = element.getAttribute(source);
4411
4815
  }
4412
4816
 
4413
4817
  const observer = new MutationObserver((mutations) => {
@@ -4420,7 +4824,7 @@ function ngObserveDirective(source, prop) {
4420
4824
  }
4421
4825
  });
4422
4826
 
4423
- observer.observe(targetElement, {
4827
+ observer.observe(element, {
4424
4828
  attributes: true,
4425
4829
  attributeFilter: [source],
4426
4830
  });
@@ -4432,91 +4836,6 @@ function ngObserveDirective(source, prop) {
4432
4836
  };
4433
4837
  }
4434
4838
 
4435
- /**
4436
- * A function passed as the fifth argument to a {@type PublicLinkFn} link function.
4437
- * It behaves like a linking function, with the `scope` argument automatically created
4438
- * as a new child of the transcluded parent scope.
4439
- *
4440
- * The function returns the DOM content to be injected (transcluded) into the directive.
4441
- *
4442
- * @callback TranscludeFn
4443
- * @param {Element | Node | ChildNode | NodeList | Node[]} [clone] - The DOM node to be inserted into the transcluded directive.
4444
- * @param {import("../scope/scope.js").Scope} [scope] - The new child scope created from the transcluded parent.
4445
- * @returns void
4446
-
4447
- /**
4448
- * A specialized version of {@link TranscludeFn} with the scope argument already bound.
4449
- * This function requires no parameters and returns the same result as {@link TranscludeFn}.
4450
- *
4451
- * @typedef {() => Element|Node} BoundTranscludeFn
4452
- */
4453
-
4454
- /**
4455
- * @typedef {Object} SimpleChange
4456
- * @property {any} currentValue
4457
- * @property {boolean} firstChange
4458
- */
4459
-
4460
- /**
4461
- * @description A function returned by the '$compile' service that links a compiled template to a scope.
4462
- *
4463
- * @callback PublicLinkFn
4464
- * @param {import('../scope/scope.js').Scope} scope - Scope to link with element
4465
- * @param {TranscludeFn} [cloneConnectFn]
4466
- * @param {*} [options]
4467
- * @return {Element|Node|ChildNode|Node[]} The nodes to be linked.
4468
- */
4469
-
4470
- /**
4471
- * @description Entry point for the '$compile' service.
4472
- *
4473
- * @callback CompileFn
4474
- * @param {string|Element|Node|ChildNode|NodeList} compileNode - The node to be compiled.
4475
- * @param {TranscludeFn} [transcludeFn] - An optional transclusion function to be used during compilation.
4476
- * @param {number} [maxPriority] - An optional maximum priority for directives.
4477
- * @param {string} [ignoreDirective] - An optional directive to ignore during compilation.
4478
- * @param {*} [previousCompileContext] - An optional context from a previous compilation. TODO
4479
- * @returns {PublicLinkFn} A public link function.
4480
- */
4481
-
4482
- /**
4483
- * @typedef {Object} LinkFnMapping
4484
- * @property {number} index
4485
- * @property {NodeLinkFnCtx} [nodeLinkFnCtx]
4486
- * @property {CompositeLinkFn} [childLinkFn]
4487
- */
4488
-
4489
- /**
4490
- * @typedef {function(): CompositeLinkFn} CompileNodesFn
4491
- */
4492
-
4493
- /**
4494
- * @callback NodeLinkFn
4495
- * @returns {Node|Element|NodeList}
4496
- */
4497
-
4498
- /**
4499
- * @typedef {Object} NodeLinkFnCtx
4500
- * @property {NodeLinkFn} nodeLinkFn
4501
- * @property {boolean} terminal
4502
- * @property {TranscludeFn} transclude
4503
- * @property {boolean} transcludeOnThisElement
4504
- * @property {boolean} templateOnThisElement
4505
- * @property {boolean} newScope
4506
- */
4507
-
4508
- /**
4509
- * @typedef {function(): NodeLinkFn} ApplyDirectivesToNodeFn
4510
- */
4511
-
4512
- /**
4513
- * @description Function that aggregates all linking fns for a compilation root (nodeList)
4514
- * @callback CompositeLinkFn
4515
- * @param {import('../scope/scope.js').Scope} scope - The scope to be linked to the template
4516
- * @param {NodeRef} $linkNode - wrapper around a nodeList
4517
- * @param {Function} [parentBoundTranscludeFn]
4518
- */
4519
-
4520
4839
  const $compileMinErr = minErr("$compile");
4521
4840
  const EXCLUDED_DIRECTIVES = ["ngIf", "ngRepeat"];
4522
4841
  const ALL_OR_NOTHING_ATTRS = ["ngSrc", "ngSrcset", "src", "srcset"];
@@ -4531,7 +4850,7 @@ class CompileProvider {
4531
4850
  /* @ignore */ static $inject = [$injectTokens.$provide, $injectTokens.$$sanitizeUriProvider];
4532
4851
 
4533
4852
  /**
4534
- * @param {import('../../interface.js').Provider} $provide
4853
+ * @param {import('../../interface.ts').Provider} $provide
4535
4854
  * @param {import('../sanitize/sanitize-uri.js').SanitizeUriProvider} $$sanitizeUriProvider
4536
4855
  */
4537
4856
  constructor($provide, $$sanitizeUriProvider) {
@@ -4540,7 +4859,6 @@ class CompileProvider {
4540
4859
  const bindingCache = Object.create(null);
4541
4860
 
4542
4861
  /**
4543
- *
4544
4862
  * @param {import("../scope/scope.js").Scope} scope
4545
4863
  * @param {string} directiveName
4546
4864
  * @param {boolean} isController
@@ -4722,7 +5040,7 @@ class CompileProvider {
4722
5040
  /**
4723
5041
  * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
4724
5042
  * or an object map of components where the keys are the names and the values are the component definition objects.
4725
- * @param {import("../../interface.js").Component} options Component definition object (a simplified
5043
+ * @param {import("../../interface.ts").Component} options Component definition object (a simplified
4726
5044
  * {directive definition object}),
4727
5045
  * with the following properties (all optional):
4728
5046
  *
@@ -5053,12 +5371,11 @@ class CompileProvider {
5053
5371
  ? (x) => x
5054
5372
  : (x) => x.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
5055
5373
 
5056
- const NG_PREFIX_BINDING = /^ng(Attr|Prop|On|Observe)([A-Z].*)$/;
5374
+ const NG_PREFIX_BINDING = /^ng(Attr|Prop|On|Observe|Window)([A-Z].*)$/;
5057
5375
  return compile;
5058
5376
 
5059
- //= ===============================
5060
5377
  /**
5061
- * @type {CompileFn}
5378
+ * @type {ng.CompileService}
5062
5379
  */
5063
5380
  function compile(
5064
5381
  element,
@@ -5072,7 +5389,7 @@ class CompileProvider {
5072
5389
  /**
5073
5390
  * The composite link function is a composite of individual node linking functions.
5074
5391
  * It will be invoke by the public link function below.
5075
- * @type {CompositeLinkFn}
5392
+ * @type {ng.CompositeLinkFn}
5076
5393
  */
5077
5394
  let compositeLinkFn = compileNodes(
5078
5395
  nodeRef,
@@ -5085,7 +5402,7 @@ class CompileProvider {
5085
5402
  let namespace = null;
5086
5403
  return publicLinkFn;
5087
5404
 
5088
- /** @type {PublicLinkFn} */
5405
+ /** @type {ng.PublicLinkFn} */
5089
5406
  function publicLinkFn(scope, cloneConnectFn, options) {
5090
5407
  if (!nodeRef) {
5091
5408
  throw $compileMinErr(
@@ -5207,7 +5524,7 @@ class CompileProvider {
5207
5524
  * @param {number=} [maxPriority] Max directive priority.
5208
5525
  * @param {*} [ignoreDirective]
5209
5526
  * @param {*} [previousCompileContext]
5210
- * @returns {CompositeLinkFn} A composite linking function of all of the matched directives or null.
5527
+ * @returns {ng.CompositeLinkFn} A composite linking function of all of the matched directives or null.
5211
5528
  */
5212
5529
  function compileNodes(
5213
5530
  nodeRefList,
@@ -5220,7 +5537,7 @@ class CompileProvider {
5220
5537
  * Aggregates for the composite linking function, where a node in a node list is mapped
5221
5538
  * to a corresponding link function. For single elements, the node should be mapped to
5222
5539
  * a single node link function.
5223
- * @type {LinkFnMapping[]}
5540
+ * @type {ng.LinkFnMapping[]}
5224
5541
  */
5225
5542
  const linkFnsList = []; // An array to hold node indices and their linkFns
5226
5543
  let nodeLinkFnFound;
@@ -5240,7 +5557,7 @@ class CompileProvider {
5240
5557
  ignoreDirective,
5241
5558
  );
5242
5559
 
5243
- /** @type {NodeLinkFnCtx} */
5560
+ /** @type {ng.NodeLinkFnCtx} */
5244
5561
  let nodeLinkFnCtx;
5245
5562
 
5246
5563
  if (directives.length) {
@@ -5387,10 +5704,10 @@ class CompileProvider {
5387
5704
 
5388
5705
  /**
5389
5706
  * Prebinds the transclusion function to a scope
5390
- * @param {import("../scope/scope.js").Scope} scope
5707
+ * @param {ng.Scope} scope
5391
5708
  * @param {*} transcludeFn
5392
5709
  * @param {*} previousBoundTranscludeFn
5393
- * @returns {BoundTranscludeFn}
5710
+ * @returns {ng.BoundTranscludeFn}
5394
5711
  */
5395
5712
  function createBoundTranscludeFn(
5396
5713
  scope,
@@ -5448,7 +5765,7 @@ class CompileProvider {
5448
5765
  */
5449
5766
  function collectDirectives(node, attrs, maxPriority, ignoreDirective) {
5450
5767
  /**
5451
- * @type {import('../../interface.ts').Directive[]}
5768
+ * @type {ng.Directive[]}
5452
5769
  */
5453
5770
  const directives = [];
5454
5771
  const { nodeType } = node;
@@ -5474,6 +5791,7 @@ class CompileProvider {
5474
5791
  let isNgProp = false;
5475
5792
  let isNgEvent = false;
5476
5793
  let isNgObserve = false;
5794
+ let isWindow = false;
5477
5795
 
5478
5796
  let attr = node.attributes[j];
5479
5797
  let name = attr.name;
@@ -5487,6 +5805,7 @@ class CompileProvider {
5487
5805
  isNgProp = ngPrefixMatch[1] === "Prop";
5488
5806
  isNgEvent = ngPrefixMatch[1] === "On";
5489
5807
  isNgObserve = ngPrefixMatch[1] === "Observe";
5808
+ isWindow = ngPrefixMatch[1] === "Window";
5490
5809
 
5491
5810
  // Normalize the non-prefixed name
5492
5811
  name = name
@@ -5496,13 +5815,13 @@ class CompileProvider {
5496
5815
  .replace(/_(.)/g, (match, letter) => letter.toUpperCase());
5497
5816
  }
5498
5817
 
5499
- if (isNgProp || isNgEvent) {
5818
+ if (isNgProp || isNgEvent || isWindow) {
5500
5819
  attrs[nName] = value;
5501
5820
  attrsMap[nName] = attr.name;
5502
5821
 
5503
5822
  if (isNgProp) {
5504
5823
  addPropertyDirective(node, directives, nName, name);
5505
- } else {
5824
+ } else if (isNgEvent) {
5506
5825
  directives.push(
5507
5826
  createEventDirective(
5508
5827
  $parse,
@@ -5511,6 +5830,17 @@ class CompileProvider {
5511
5830
  name,
5512
5831
  ),
5513
5832
  );
5833
+ } else {
5834
+ // isWindow
5835
+ directives.push(
5836
+ createWindowEventDirective(
5837
+ $parse,
5838
+ $exceptionHandler,
5839
+ window,
5840
+ nName,
5841
+ name,
5842
+ ),
5843
+ );
5514
5844
  }
5515
5845
  } else if (isNgObserve) {
5516
5846
  directives.push(ngObserveDirective(name, value));
@@ -5569,7 +5899,7 @@ class CompileProvider {
5569
5899
  * @param maxPriority
5570
5900
  * @param ignoreDirective
5571
5901
  * @param previousCompileContext
5572
- * @returns {PublicLinkFn|TranscludeFn}
5902
+ * @returns {ng.PublicLinkFn|ng.TranscludeFn}
5573
5903
  */
5574
5904
  function compilationGenerator(
5575
5905
  eager,
@@ -5616,14 +5946,14 @@ class CompileProvider {
5616
5946
  * this needs to be pre-sorted by priority order.
5617
5947
  * @param {Node | Element} compileNode DOM node to apply the compile functions to
5618
5948
  * @param {Attributes} templateAttrs The shared attribute function
5619
- * @param {TranscludeFn} transcludeFn
5949
+ * @param {ng.TranscludeFn} transcludeFn
5620
5950
  * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
5621
5951
  * compiling the transclusion.
5622
5952
  * @param {Array.<Function>} [preLinkFns]
5623
5953
  * @param {Array.<Function>} [postLinkFns]
5624
5954
  * @param {Object} [previousCompileContext] Context used for previous compilation of the current
5625
5955
  * node
5626
- * @returns {NodeLinkFnCtx} node link function
5956
+ * @returns {ng.NodeLinkFnCtx} node link function
5627
5957
  */
5628
5958
  function applyDirectivesToNode(
5629
5959
  directives,
@@ -5658,7 +5988,7 @@ class CompileProvider {
5658
5988
  let directiveName;
5659
5989
  let $template;
5660
5990
  let replaceDirective = originalReplaceDirective;
5661
- /** @type {TranscludeFn} */
5991
+ /** @type {ng.TranscludeFn} */
5662
5992
  let childTranscludeFn = transcludeFn;
5663
5993
 
5664
5994
  let didScanForMultipleTransclusion = false;
@@ -5667,7 +5997,7 @@ class CompileProvider {
5667
5997
 
5668
5998
  /**
5669
5999
  * Links all the directives of a single node.
5670
- * @type {NodeLinkFn}
6000
+ * @type {ng.NodeLinkFn}
5671
6001
  */
5672
6002
  // @ts-ignore
5673
6003
  let nodeLinkFn = function (
@@ -6349,7 +6679,7 @@ class CompileProvider {
6349
6679
  ii = directives.length;
6350
6680
  } else if (directive.compile) {
6351
6681
  try {
6352
- /** @type {PublicLinkFn} */
6682
+ /** @type {ng.PublicLinkFn} */
6353
6683
  const linkFn = directive.compile(
6354
6684
  compileNodeRef.getAny(),
6355
6685
  templateAttrs,
@@ -7365,7 +7695,7 @@ class CompileProvider {
7365
7695
  }
7366
7696
 
7367
7697
  /**
7368
- * @type {SimpleChange}
7698
+ * @type {import("./inteface.ts").SimpleChange}
7369
7699
  */
7370
7700
  initialChanges[scopeName] = {
7371
7701
  currentValue: destination[scopeName],
@@ -7491,7 +7821,7 @@ class CompileProvider {
7491
7821
  scope.$handler.watchers
7492
7822
  .get(attrs[attrName])
7493
7823
  ?.forEach((watchFn) => {
7494
- watchFn.listenerFn(val);
7824
+ watchFn.listenerFn(val, scope.$target);
7495
7825
  });
7496
7826
  }
7497
7827
  }
@@ -7518,7 +7848,7 @@ class CompileProvider {
7518
7848
  parentGet = $parse(attrs[attrName]);
7519
7849
 
7520
7850
  destination.$target[scopeName] = parentGet(scope.$target);
7521
- /** @type {SimpleChange} */
7851
+ /** @type {import("./inteface.ts").SimpleChange} */
7522
7852
  initialChanges[scopeName] = {
7523
7853
  currentValue: destination.$target[scopeName],
7524
7854
  firstChange: firstChange,
@@ -7904,8 +8234,14 @@ class FormController {
7904
8234
  * state (ng-dirty class). This method will also propagate to parent forms.
7905
8235
  */
7906
8236
  $setDirty() {
7907
- this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
7908
- 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
+ }
7909
8245
  this.$dirty = true;
7910
8246
  this.$pristine = false;
7911
8247
  this.$$parentForm.$setDirty();
@@ -7924,11 +8260,18 @@ class FormController {
7924
8260
  * saving or resetting it.
7925
8261
  */
7926
8262
  $setPristine() {
7927
- this.$$animate.setClass(
7928
- this.$$element,
7929
- PRISTINE_CLASS,
7930
- `${DIRTY_CLASS} ${SUBMITTED_CLASS}`,
7931
- );
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
+
7932
8275
  this.$dirty = false;
7933
8276
  this.$pristine = true;
7934
8277
  this.$submitted = false;
@@ -7966,7 +8309,11 @@ class FormController {
7966
8309
  }
7967
8310
 
7968
8311
  $$setSubmitted() {
7969
- 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
+ }
7970
8317
  this.$submitted = true;
7971
8318
  this.$$controls.forEach((control) => {
7972
8319
  if (control.$$setSubmitted) {
@@ -11486,7 +11833,7 @@ const ngClassOddDirective = classDirective("Odd", 0);
11486
11833
  const ngClassEvenDirective = classDirective("Even", 1);
11487
11834
 
11488
11835
  /**
11489
- * @returns {import('../../interface.ts').Directive}
11836
+ * @returns {ng.Directive}
11490
11837
  */
11491
11838
  function ngCloakDirective() {
11492
11839
  return {
@@ -11576,7 +11923,7 @@ function ngHideDirective($animate) {
11576
11923
  ngIfDirective.$inject = ["$animate"];
11577
11924
  /**
11578
11925
  * @param {*} $animate
11579
- * @returns {import("../../interface.ts").Directive}
11926
+ * @returns {ng.Directive}
11580
11927
  */
11581
11928
  function ngIfDirective($animate) {
11582
11929
  return {
@@ -11586,10 +11933,10 @@ function ngIfDirective($animate) {
11586
11933
  restrict: "A",
11587
11934
  /**
11588
11935
  *
11589
- * @param {import("../../core/scope/scope.js").Scope} $scope
11936
+ * @param {ng.Scope} $scope
11590
11937
  * @param {Element} $element
11591
- * @param {import("../../core/compile/attributes.js").Attributes} $attr
11592
- * @param {Object} _ctrl
11938
+ * @param {ng.Attributes} $attr
11939
+ * @param {*} _ctrl
11593
11940
  * @param {*} $transclude
11594
11941
  */
11595
11942
  link($scope, $element, $attr, _ctrl, $transclude) {
@@ -11601,7 +11948,7 @@ function ngIfDirective($animate) {
11601
11948
 
11602
11949
  let previousElements;
11603
11950
 
11604
- $scope.$watch($attr["ngIf"], (value) => {
11951
+ $scope.$watch($attr.ngIf, (value) => {
11605
11952
  if (value) {
11606
11953
  if (!childScope) {
11607
11954
  $transclude((clone, newScope) => {
@@ -11656,7 +12003,7 @@ ngIncludeDirective.$inject = [
11656
12003
  * @param {import("../../services/anchor-scroll/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
11657
12004
  * @param {*} $animate
11658
12005
  * @param {import('../../services/exception/interface.ts').ErrorHandler} $exceptionHandler
11659
- * @returns {import('../../interface.js').Directive}
12006
+ * @returns {import('../../interface.ts').Directive}
11660
12007
  */
11661
12008
  function ngIncludeDirective(
11662
12009
  $templateRequest,
@@ -11777,7 +12124,7 @@ function ngIncludeDirective(
11777
12124
  ngIncludeFillContentDirective.$inject = [$injectTokens.$compile];
11778
12125
 
11779
12126
  /**
11780
- * @param {import("../../core/compile/compile.js").CompileFn} $compile
12127
+ * @param {ng.CompileService} $compile
11781
12128
  * @returns {import("../../interface.ts").Directive}
11782
12129
  */
11783
12130
  function ngIncludeFillContentDirective($compile) {
@@ -12408,7 +12755,7 @@ const NG_OPTIONS_REGEXP =
12408
12755
  ngOptionsDirective.$inject = ["$compile", "$parse"];
12409
12756
  /**
12410
12757
  *
12411
- * @param {import("../../core/compile/compile.js").CompileFn} $compile
12758
+ * @param {ng.CompileService} $compile
12412
12759
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
12413
12760
  * @returns {import("../../interface.ts").Directive}
12414
12761
  */
@@ -12935,8 +13282,8 @@ const ngTranscludeMinErr = minErr("ngTransclude");
12935
13282
 
12936
13283
  ngTranscludeDirective.$inject = ["$compile"];
12937
13284
  /**
12938
- * @param {import("../../core/compile/compile.js").CompileFn} $compile
12939
- * @returns {import("../../interface.ts").Directive}
13285
+ * @param {ng.CompileService} $compile
13286
+ * @returns {ng.Directive}
12940
13287
  */
12941
13288
  function ngTranscludeDirective($compile) {
12942
13289
  return {
@@ -12947,9 +13294,9 @@ function ngTranscludeDirective($compile) {
12947
13294
 
12948
13295
  /**
12949
13296
  *
12950
- * @param {import("../../core/scope/scope.js").Scope} $scope
13297
+ * @param {ng.Scope} $scope
12951
13298
  * @param {Element} $element
12952
- * @param {import("../../core/compile/attributes.js").Attributes} $attrs
13299
+ * @param {ng.Attributes} $attrs
12953
13300
  * @param {*} _controller
12954
13301
  * @param {*} $transclude
12955
13302
  */
@@ -13038,7 +13385,7 @@ function ngTranscludeDirective($compile) {
13038
13385
  const REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
13039
13386
 
13040
13387
  /**
13041
- * @type {Record<string, import("../../interface.js").DirectiveFactory>}
13388
+ * @type {Record<string, import("../../interface.ts").DirectiveFactory>}
13042
13389
  */
13043
13390
  const ngAttributeAliasDirectives = {};
13044
13391
 
@@ -13611,364 +13958,6 @@ class AnchorScrollProvider {
13611
13958
  ];
13612
13959
  }
13613
13960
 
13614
- /**
13615
- * @readonly
13616
- * @enum {number}
13617
- */
13618
- const ASTType = {
13619
- Program: 1,
13620
- ExpressionStatement: 2,
13621
- AssignmentExpression: 3,
13622
- ConditionalExpression: 4,
13623
- LogicalExpression: 5,
13624
- BinaryExpression: 6,
13625
- UnaryExpression: 7,
13626
- CallExpression: 8,
13627
- MemberExpression: 9,
13628
- Identifier: 10,
13629
- Literal: 11,
13630
- ArrayExpression: 12,
13631
- Property: 13,
13632
- ObjectExpression: 14,
13633
- ThisExpression: 15,
13634
- LocalsExpression: 16,
13635
- NGValueParameter: 17,
13636
- };
13637
-
13638
- const ADD_CLASS_SUFFIX = "-add";
13639
- const REMOVE_CLASS_SUFFIX = "-remove";
13640
- const EVENT_CLASS_PREFIX = "ng-";
13641
- const ACTIVE_CLASS_SUFFIX = "-active";
13642
- const PREPARE_CLASS_SUFFIX = "-prepare";
13643
-
13644
- const NG_ANIMATE_CLASSNAME = "ng-animate";
13645
- const NG_ANIMATE_CHILDREN_DATA = "$$ngAnimateChildren";
13646
- let TRANSITION_PROP;
13647
- let TRANSITIONEND_EVENT;
13648
- let ANIMATION_PROP;
13649
- let ANIMATIONEND_EVENT;
13650
-
13651
- // If unprefixed events are not supported but webkit-prefixed are, use the latter.
13652
- // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
13653
- // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
13654
- // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
13655
- // Register both events in case `window.onanimationend` is not supported because of that,
13656
- // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
13657
- // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
13658
- // therefore there is no reason to test anymore for other vendor prefixes:
13659
- // http://caniuse.com/#search=transition
13660
- if (
13661
- window.ontransitionend === undefined &&
13662
- window.onwebkittransitionend !== undefined
13663
- ) {
13664
- TRANSITION_PROP = "WebkitTransition";
13665
- TRANSITIONEND_EVENT = "webkitTransitionEnd transitionend";
13666
- } else {
13667
- TRANSITION_PROP = "transition";
13668
- TRANSITIONEND_EVENT = "transitionend";
13669
- }
13670
-
13671
- if (
13672
- window.onanimationend === undefined &&
13673
- window.onwebkitanimationend !== undefined
13674
- ) {
13675
- ANIMATION_PROP = "WebkitAnimation";
13676
- ANIMATIONEND_EVENT = "webkitAnimationEnd animationend";
13677
- } else {
13678
- ANIMATION_PROP = "animation";
13679
- ANIMATIONEND_EVENT = "animationend";
13680
- }
13681
-
13682
- const DURATION_KEY = "Duration";
13683
- const PROPERTY_KEY = ASTType.Property;
13684
- const DELAY_KEY = "Delay";
13685
- const TIMING_KEY = "TimingFunction";
13686
- const ANIMATION_ITERATION_COUNT_KEY = "IterationCount";
13687
- const ANIMATION_PLAYSTATE_KEY = "PlayState";
13688
- const SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
13689
-
13690
- const ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
13691
- const ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
13692
- const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
13693
- const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
13694
-
13695
- const ngMinErr$1 = minErr("ng");
13696
- function assertArg(arg, name, reason) {
13697
- if (!arg) {
13698
- throw ngMinErr$1(
13699
- "areq",
13700
- "Argument '{0}' is {1}",
13701
- name || "?",
13702
- reason,
13703
- );
13704
- }
13705
- return arg;
13706
- }
13707
-
13708
- function packageStyles(options) {
13709
- const styles = {};
13710
- if (options && (options.to || options.from)) {
13711
- styles.to = options.to;
13712
- styles.from = options.from;
13713
- }
13714
- return styles;
13715
- }
13716
-
13717
- function pendClasses(classes, fix, isPrefix) {
13718
- let className = "";
13719
-
13720
- classes = Array.isArray(classes)
13721
- ? classes
13722
- : classes && isString(classes) && classes.length
13723
- ? classes.split(/\s+/)
13724
- : [];
13725
- classes.forEach((klass, i) => {
13726
- if (klass && klass.length > 0) {
13727
- className += i > 0 ? " " : "";
13728
- className += isPrefix ? fix + klass : klass + fix;
13729
- }
13730
- });
13731
- return className;
13732
- }
13733
-
13734
- function removeFromArray(arr, val) {
13735
- const index = arr.indexOf(val);
13736
- if (val >= 0) {
13737
- arr.splice(index, 1);
13738
- }
13739
- }
13740
-
13741
- /**
13742
- *
13743
- * @param {NodeList|Node} element
13744
- * @returns {Node[]|Node|undefined}
13745
- */
13746
- function stripCommentsFromElement(element) {
13747
- if (element instanceof NodeList) {
13748
- return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
13749
- } else if (element.nodeType === Node.ELEMENT_NODE) {
13750
- return /** @type {Node} */ (element);
13751
- } else {
13752
- return undefined;
13753
- }
13754
- }
13755
-
13756
- /**
13757
- * @param {NodeList|Node} element
13758
- * @returns {Node}
13759
- */
13760
- function extractElementNode(element) {
13761
- if (!element) return /** @type {Node} */ (element);
13762
- for (let i = 0; i < /** @type {NodeList} */ (element).length; i++) {
13763
- const elm = element[i];
13764
- if (elm.nodeType === Node.ELEMENT_NODE) {
13765
- return elm;
13766
- }
13767
- }
13768
- }
13769
-
13770
- function applyAnimationClassesFactory() {
13771
- return function (element, options) {
13772
- if (options.addClass) {
13773
- element.classList.add(...options.addClass.trim().split(" "));
13774
- options.addClass = null;
13775
- }
13776
- if (options.removeClass) {
13777
- element.classList.remove(...options.removeClass.trim().split(" "));
13778
- options.removeClass = null;
13779
- }
13780
- };
13781
- }
13782
-
13783
- function prepareAnimationOptions(options) {
13784
- options = options || {};
13785
- if (!options.$$prepared) {
13786
- let domOperation = options.domOperation || (() => {});
13787
- options.domOperation = function () {
13788
- options.$$domOperationFired = true;
13789
- domOperation();
13790
- domOperation = () => {};
13791
- };
13792
- options.$$prepared = true;
13793
- }
13794
- return options;
13795
- }
13796
-
13797
- function applyAnimationStyles(element, options) {
13798
- applyAnimationFromStyles(element, options);
13799
- applyAnimationToStyles(element, options);
13800
- }
13801
-
13802
- function applyAnimationFromStyles(element, options) {
13803
- if (options.from) {
13804
- //element.css(options.from);
13805
- options.from = null;
13806
- }
13807
- }
13808
-
13809
- function applyAnimationToStyles(element, options) {
13810
- if (options.to) {
13811
- //element.css(options.to);
13812
- options.to = null;
13813
- }
13814
- }
13815
-
13816
- function mergeAnimationDetails(element, oldAnimation, newAnimation) {
13817
- const target = oldAnimation.options || {};
13818
- const newOptions = newAnimation.options || {};
13819
-
13820
- const toAdd = `${target.addClass || ""} ${newOptions.addClass || ""}`;
13821
- const toRemove = `${target.removeClass || ""} ${newOptions.removeClass || ""}`;
13822
- const classes = resolveElementClasses(
13823
- element.getAttribute("class"),
13824
- toAdd,
13825
- toRemove,
13826
- );
13827
-
13828
- if (newOptions.preparationClasses) {
13829
- target.preparationClasses = concatWithSpace(
13830
- newOptions.preparationClasses,
13831
- target.preparationClasses,
13832
- );
13833
- delete newOptions.preparationClasses;
13834
- }
13835
-
13836
- extend(target, newOptions);
13837
-
13838
- if (classes.addClass) {
13839
- target.addClass = classes.addClass;
13840
- } else {
13841
- target.addClass = null;
13842
- }
13843
-
13844
- if (classes.removeClass) {
13845
- target.removeClass = classes.removeClass;
13846
- } else {
13847
- target.removeClass = null;
13848
- }
13849
-
13850
- oldAnimation.addClass = target.addClass;
13851
- oldAnimation.removeClass = target.removeClass;
13852
-
13853
- return target;
13854
- }
13855
-
13856
- function resolveElementClasses(existing, toAdd, toRemove) {
13857
- const ADD_CLASS = 1;
13858
- const REMOVE_CLASS = -1;
13859
-
13860
- const flags = {};
13861
- existing = splitClassesToLookup(existing);
13862
-
13863
- toAdd = splitClassesToLookup(toAdd);
13864
- Object.keys(toAdd).forEach((key) => {
13865
- flags[key] = ADD_CLASS;
13866
- });
13867
-
13868
- toRemove = splitClassesToLookup(toRemove);
13869
- Object.keys(toRemove).forEach((key) => {
13870
- flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
13871
- });
13872
-
13873
- const classes = {
13874
- addClass: "",
13875
- removeClass: "",
13876
- };
13877
-
13878
- Object.entries(flags).forEach(([klass, val]) => {
13879
- let prop, allow;
13880
- if (val === ADD_CLASS) {
13881
- prop = "addClass";
13882
- allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
13883
- } else if (val === REMOVE_CLASS) {
13884
- prop = "removeClass";
13885
- allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
13886
- }
13887
- if (allow) {
13888
- if (classes[prop].length) {
13889
- classes[prop] += " ";
13890
- }
13891
- classes[prop] += klass;
13892
- }
13893
- });
13894
-
13895
- function splitClassesToLookup(classes) {
13896
- if (isString(classes)) {
13897
- classes = classes.trim().split(" ");
13898
- }
13899
-
13900
- const obj = {};
13901
- if (classes) {
13902
- classes.forEach((klass) => {
13903
- // sometimes the split leaves empty string values
13904
- // incase extra spaces were applied to the options
13905
- if (klass.length) {
13906
- obj[klass] = true;
13907
- }
13908
- });
13909
- }
13910
- return obj;
13911
- }
13912
-
13913
- return classes;
13914
- }
13915
-
13916
- function applyGeneratedPreparationClasses(element, event, options) {
13917
- let classes = "";
13918
- if (event) {
13919
- classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
13920
- }
13921
- if (options.addClass) {
13922
- classes = concatWithSpace(
13923
- classes,
13924
- pendClasses(options.addClass, ADD_CLASS_SUFFIX),
13925
- );
13926
- }
13927
- if (options.removeClass) {
13928
- classes = concatWithSpace(
13929
- classes,
13930
- pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX),
13931
- );
13932
- }
13933
- if (classes.length) {
13934
- options.preparationClasses = classes;
13935
- element.className += ` ${classes}`;
13936
- }
13937
- }
13938
-
13939
- function clearGeneratedClasses(element, options) {
13940
- if (options.preparationClasses) {
13941
- options.preparationClasses
13942
- .split(" ")
13943
- .forEach((cls) => element.classList.remove(cls));
13944
- options.preparationClasses = null;
13945
- }
13946
- if (options.activeClasses) {
13947
- options.activeClasses
13948
- .split(" ")
13949
- .forEach((cls) => element.classList.remove(cls));
13950
- options.activeClasses = null;
13951
- }
13952
- }
13953
-
13954
- function blockKeyframeAnimations(node, applyBlock) {
13955
- const value = applyBlock ? "paused" : "";
13956
- const key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
13957
- applyInlineStyle(node, [key, value]);
13958
- return [key, value];
13959
- }
13960
-
13961
- function applyInlineStyle(node, styleTuple) {
13962
- const prop = styleTuple[0];
13963
- node.style[prop] = styleTuple[1];
13964
- }
13965
-
13966
- function concatWithSpace(a, b) {
13967
- if (!a) return b;
13968
- if (!b) return a;
13969
- return `${a} ${b}`;
13970
- }
13971
-
13972
13961
  /** @typedef {"enter"|"leave"|"move"|"addClass"|"setClass"|"removeClass"} AnimationMethod */
13973
13962
 
13974
13963
  /**
@@ -14356,7 +14345,7 @@ function AnimateProvider($provide) {
14356
14345
  *
14357
14346
  * @param {Element} element - the element which will be inserted into the DOM
14358
14347
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14359
- * @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
14360
14349
  * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14361
14350
  * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
14362
14351
  */
@@ -17834,7 +17823,7 @@ class InterpolateProvider {
17834
17823
  return concat.join("");
17835
17824
  };
17836
17825
 
17837
- return /**@type {import("./interface.js").InterpolationFunction} */ extend(
17826
+ return /**@type {import("./interface.ts").InterpolationFunction} */ extend(
17838
17827
  (context, cb) => {
17839
17828
  let i = 0;
17840
17829
  const ii = expressions.length;
@@ -19502,7 +19491,7 @@ class LocationProvider {
19502
19491
  /**
19503
19492
  * Registers a callback to be called when the URL changes.
19504
19493
  *
19505
- * @param {import("./interface.js").UrlChangeListener} callback - The callback function to register.
19494
+ * @param {import("./interface.ts").UrlChangeListener} callback - The callback function to register.
19506
19495
  * @returns void
19507
19496
  */
19508
19497
  #onUrlChange(callback) {
@@ -20095,16 +20084,9 @@ function nextId() {
20095
20084
  */
20096
20085
  let $parse;
20097
20086
 
20098
- /**@type {import('../../services/exception/exception-handler.js').ErrorHandler} */
20087
+ /**@type {ng.ExceptionHandlerService} */
20099
20088
  let $exceptionHandler;
20100
20089
 
20101
- /**
20102
- * @typedef {Object} AsyncQueueTask
20103
- * @property {Scope} handler
20104
- * @property {Function} fn
20105
- * @property {Object} locals
20106
- */
20107
-
20108
20090
  const $postUpdateQueue = [];
20109
20091
 
20110
20092
  class RootScopeProvider {
@@ -20113,11 +20095,11 @@ class RootScopeProvider {
20113
20095
  }
20114
20096
 
20115
20097
  $get = [
20116
- "$exceptionHandler",
20117
- "$parse",
20098
+ $injectTokens.$exceptionHandler,
20099
+ $injectTokens.$parse,
20118
20100
  /**
20119
- * @param {import('../../services/exception/exception-handler.js').ErrorHandler} exceptionHandler
20120
- * @param {import('../parse/interface.ts').ParseService} parse
20101
+ * @param {ng.ExceptionHandlerService} exceptionHandler
20102
+ * @param {ng.ParseService} parse
20121
20103
  */
20122
20104
  (exceptionHandler, parse) => {
20123
20105
  $exceptionHandler = exceptionHandler;
@@ -20174,27 +20156,6 @@ function createScope(target = {}, context) {
20174
20156
  }
20175
20157
  }
20176
20158
 
20177
- /**
20178
- * Listener function definition.
20179
- * @typedef {Object} Listener
20180
- * @property {Object} originalTarget - The original target object.
20181
- * @property {ListenerFunction} listenerFn - The function invoked when changes are detected.
20182
- * @property {import("../parse/interface.ts").CompiledExpression} watchFn
20183
- * @property {number} id - Deregistration id
20184
- * @property {number} scopeId - The scope that created the Listener
20185
- * @property {string[]} property
20186
- * @property {string} [watchProp] - The original property to watch if different from observed key
20187
- * @property {Proxy} [foreignListener]
20188
- *
20189
- */
20190
-
20191
- /**
20192
- * Listener function type.
20193
- * @callback ListenerFunction
20194
- * @param {*} newValue - The new value of the changed property.
20195
- * @param {Object} originalTarget - The original target object.
20196
- */
20197
-
20198
20159
  /**
20199
20160
  * Decorator for excluding objects from scope observability
20200
20161
  */
@@ -20220,13 +20181,13 @@ class Scope {
20220
20181
  : context
20221
20182
  : undefined;
20222
20183
 
20223
- /** @type {Map<string, Array<Listener>>} Watch listeners */
20184
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners */
20224
20185
  this.watchers = context ? context.watchers : new Map();
20225
20186
 
20226
20187
  /** @type {Map<String, Function[]>} Event listeners */
20227
20188
  this.$$listeners = new Map();
20228
20189
 
20229
- /** @type {Map<string, Array<Listener>>} Watch listeners from other proxies */
20190
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners from other proxies */
20230
20191
  this.foreignListeners = context ? context.foreignListeners : new Map();
20231
20192
 
20232
20193
  /** @type {Set<ProxyConstructor>} */
@@ -20271,7 +20232,7 @@ class Scope {
20271
20232
  ? null
20272
20233
  : context;
20273
20234
 
20274
- /** @type {AsyncQueueTask[]} */
20235
+ /** @type {import('./interface.ts').AsyncQueueTask[]} */
20275
20236
  this.$$asyncQueue = [];
20276
20237
 
20277
20238
  this.filters = [];
@@ -20280,257 +20241,18 @@ class Scope {
20280
20241
  this.$$destroyed = false;
20281
20242
 
20282
20243
  this.scheduled = [];
20283
- }
20284
-
20285
- /**
20286
- * Intercepts and handles property assignments on the target object. If a new value is
20287
- * an object, it will be recursively proxied.
20288
- *
20289
- * @param {Object} target - The target object.
20290
- * @param {string} property - The name of the property being set.
20291
- * @param {*} value - The new value being assigned to the property.
20292
- * @param {Proxy} proxy - The proxy intercepting property access
20293
- * @returns {boolean} - Returns true to indicate success of the operation.
20294
- */
20295
- set(target, property, value, proxy) {
20296
- if (property === "undefined") {
20297
- throw new Error("Attempting to set undefined property");
20298
- }
20299
- if (
20300
- (target.constructor?.$nonscope &&
20301
- Array.isArray(target.constructor.$nonscope) &&
20302
- target.constructor.$nonscope.includes(property)) ||
20303
- (target.$nonscope &&
20304
- Array.isArray(target.$nonscope) &&
20305
- target.$nonscope.includes(property))
20306
- ) {
20307
- target[property] = value;
20308
- return true;
20309
- }
20310
-
20311
- this.$proxy = proxy;
20312
- this.$target = target;
20313
- const oldValue = target[property];
20314
-
20315
- // Handle NaNs
20316
- if (
20317
- oldValue !== undefined &&
20318
- Number.isNaN(oldValue) &&
20319
- Number.isNaN(value)
20320
- ) {
20321
- return true;
20322
- }
20323
- if (oldValue && oldValue[isProxySymbol]) {
20324
- if (Array.isArray(value)) {
20325
- if (oldValue !== value) {
20326
- const listeners = this.watchers.get(property);
20327
-
20328
- if (listeners) {
20329
- this.#scheduleListener(listeners);
20330
- }
20331
-
20332
- const foreignListeners = this.foreignListeners.get(property);
20333
-
20334
- if (foreignListeners) {
20335
- this.#scheduleListener(foreignListeners);
20336
- }
20337
- }
20338
-
20339
- if (this.objectListeners.get(target[property])) {
20340
- this.objectListeners.delete(target[property]);
20341
- }
20342
- target[property] = createScope(value, this);
20343
- this.objectListeners.set(target[property], [property]);
20344
- return true;
20345
- }
20346
-
20347
- if (isObject(value)) {
20348
- if (hasOwn(target, property)) {
20349
- Object.keys(oldValue)
20350
- .filter((x) => !value[x])
20351
- .forEach((k) => {
20352
- delete oldValue[k];
20353
- });
20354
- }
20355
-
20356
- if (oldValue !== value) {
20357
- const listeners = this.watchers.get(property);
20358
-
20359
- if (listeners) {
20360
- this.#scheduleListener(listeners);
20361
- }
20362
-
20363
- const foreignListeners = this.foreignListeners.get(property);
20364
-
20365
- if (foreignListeners) {
20366
- this.#scheduleListener(foreignListeners);
20367
- }
20368
-
20369
- this.#checkeListenersForAllKeys(value);
20370
- }
20371
- target[property] = createScope(value, this);
20372
- //setDeepValue(target[property], value);
20373
- return true;
20374
- }
20375
-
20376
- if (isUndefined(value)) {
20377
- let called = false;
20378
- Object.keys(oldValue.$target).forEach((k) => {
20379
- if (oldValue.$target[k]?.[isProxySymbol]) {
20380
- called = true;
20381
- }
20382
- delete oldValue[k];
20383
- });
20384
-
20385
- target[property] = undefined;
20386
- if (!called) {
20387
- let listeners = this.watchers.get(property);
20388
-
20389
- if (listeners) {
20390
- this.#scheduleListener(listeners);
20391
- }
20392
- }
20393
-
20394
- return true;
20395
- }
20396
-
20397
- if (isDefined(value)) {
20398
- target[property] = value;
20399
- let listeners = this.watchers.get(property);
20400
-
20401
- if (listeners) {
20402
- this.#scheduleListener(listeners);
20403
- }
20404
-
20405
- if (Array.isArray(target)) {
20406
- if (this.objectListeners.has(proxy) && property !== "length") {
20407
- let keys = this.objectListeners.get(proxy);
20408
- keys.forEach((key) => {
20409
- const listeners = this.watchers.get(key);
20410
- if (listeners) {
20411
- this.#scheduleListener(listeners);
20412
- }
20413
- });
20414
- }
20415
- }
20416
-
20417
- return true;
20418
- }
20419
- return true;
20420
- } else {
20421
- if (isUndefined(target[property]) && isProxy(value)) {
20422
- this.foreignProxies.add(value);
20423
- target[property] = value;
20424
- if (!this.watchers.has(property)) {
20425
- return true;
20426
- }
20427
- }
20428
- if (isUndefined(value)) {
20429
- target[property] = value;
20430
- } else {
20431
- target[property] = createScope(value, this);
20432
- }
20433
-
20434
- if (oldValue !== value) {
20435
- let expectedTarget = this.$target;
20436
- let listeners = [];
20437
- // Handle the case where we need to start observing object after a watcher has been set
20438
- if (isUndefined(oldValue) && isObject(target[property])) {
20439
- if (!this.objectListeners.has(target[property])) {
20440
- this.objectListeners.set(target[property], [property]);
20441
- }
20442
- for (const k of Object.keys(value)) {
20443
- this.watchers.get(k)?.forEach((l) => listeners.push(l));
20444
- // overwhrite the context so we pass the owneship test in filter
20445
- expectedTarget = value;
20446
- }
20447
- }
20448
-
20449
- if (Array.isArray(target)) {
20450
- this.watchers.get("length")?.forEach((l) => listeners.push(l));
20451
- }
20452
-
20453
- this.watchers.get(property)?.forEach((l) => listeners.push(l));
20454
- if (listeners.length > 0) {
20455
- // check if the listener actually appllies to this target
20456
- this.#scheduleListener(listeners, (x) => {
20457
- return x.filter((x) => {
20458
- if (!x.watchProp) return true;
20459
- // Compute the expected target based on `watchProp`
20460
- const wrapperExpr = x.watchProp.split(".").slice(0, -1).join(".");
20461
- const expectedHandler = $parse(wrapperExpr)(
20462
- x.originalTarget,
20463
- )?.$handler;
20464
- return expectedTarget === expectedHandler?.$target;
20465
- });
20466
- });
20467
- }
20468
-
20469
- let foreignListeners = this.foreignListeners.get(property);
20470
-
20471
- if (!foreignListeners && this.$parent?.foreignListeners) {
20472
- foreignListeners = this.$parent.foreignListeners.get(property);
20473
- }
20474
- if (foreignListeners) {
20475
- // filter for repeaters
20476
- if (this.$target.$$hashKey) {
20477
- foreignListeners = foreignListeners.filter((x) =>
20478
- x.originalTarget.$$hashKey
20479
- ? x.originalTarget.$$hashKey == this.$target.$$hashKey
20480
- : false,
20481
- );
20482
- }
20483
-
20484
- this.#scheduleListener(foreignListeners);
20485
- }
20486
- }
20487
-
20488
- if (this.objectListeners.has(proxy) && property !== "length") {
20489
- let keys = this.objectListeners.get(proxy);
20490
- keys.forEach((key) => {
20491
- const listeners = this.watchers.get(key);
20492
- if (listeners) {
20493
- if (this.scheduled !== listeners) {
20494
- this.#scheduleListener(listeners);
20495
- }
20496
- }
20497
- });
20498
- }
20499
-
20500
- return true;
20501
- }
20502
- }
20503
-
20504
- /**
20505
- * Intercepts property access on the target object. It checks for specific
20506
- * properties (`watch` and `sync`) and binds their methods. For other properties,
20507
- * it returns the value directly.
20508
- *
20509
- * @param {Object} target - The target object.
20510
- * @param {string|number|symbol} property - The name of the property being accessed.
20511
- * @param {Proxy} proxy - The proxy object being invoked
20512
- * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20513
- */
20514
- get(target, property, proxy) {
20515
- if (property === "$$watchersCount") return calculateWatcherCount(this);
20516
- if (property === isProxySymbol) return true;
20517
-
20518
- if (target[property] && isProxy(target[property])) {
20519
- this.$proxy = target[property];
20520
- } else {
20521
- this.$proxy = proxy;
20522
- }
20523
20244
 
20245
+ /** @private */
20524
20246
  this.propertyMap = {
20525
20247
  $watch: this.$watch.bind(this),
20526
20248
  $new: this.$new.bind(this),
20527
20249
  $newIsolate: this.$newIsolate.bind(this),
20528
20250
  $destroy: this.$destroy.bind(this),
20251
+ $flushQueue: this.$flushQueue.bind(this),
20529
20252
  $eval: this.$eval.bind(this),
20530
20253
  $apply: this.$apply.bind(this),
20531
20254
  $postUpdate: this.$postUpdate.bind(this),
20532
20255
  $isRoot: this.#isRoot.bind(this),
20533
- $target: target,
20534
20256
  $proxy: this.$proxy,
20535
20257
  $on: this.$on.bind(this),
20536
20258
  $emit: this.$emit.bind(this),
@@ -20544,6 +20266,249 @@ class Scope {
20544
20266
  $merge: this.$merge.bind(this),
20545
20267
  $getById: this.$getById.bind(this),
20546
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;
20547
20512
 
20548
20513
  if (
20549
20514
  Array.isArray(target) &&
@@ -20638,7 +20603,7 @@ class Scope {
20638
20603
  }
20639
20604
 
20640
20605
  /**
20641
- * @param {Listener[]} listeners
20606
+ * @param {import('./interface.ts').Listener[]} listeners
20642
20607
  * @param {Function} filter
20643
20608
  */
20644
20609
  #scheduleListener(listeners, filter = (val) => val) {
@@ -20662,7 +20627,7 @@ class Scope {
20662
20627
  * function is invoked when changes to that property are detected.
20663
20628
  *
20664
20629
  * @param {string} watchProp - An expression to be watched in the context of this model.
20665
- * @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.
20666
20631
  * @param {boolean} [lazy] - A flag to indicate if the listener should be invoked immediately. Defaults to false.
20667
20632
  */
20668
20633
  $watch(watchProp, listenerFn, lazy = false) {
@@ -20684,7 +20649,7 @@ class Scope {
20684
20649
  return () => {};
20685
20650
  }
20686
20651
 
20687
- /** @type {Listener} */
20652
+ /** @type {import('./interface.ts').Listener} */
20688
20653
  const listener = {
20689
20654
  originalTarget: this.$target,
20690
20655
  listenerFn: listenerFn,
@@ -20796,7 +20761,7 @@ class Scope {
20796
20761
 
20797
20762
  let potentialProxy = $parse(
20798
20763
  watchProp.split(".").slice(0, -1).join("."),
20799
- )(listener.originalTarget);
20764
+ )(/** @type {Scope} */ (listener.originalTarget));
20800
20765
  if (potentialProxy && this.foreignProxies.has(potentialProxy)) {
20801
20766
  potentialProxy.$handler.#registerForeignKey(key, listener);
20802
20767
  potentialProxy.$handler.#scheduleListener([listener]);
@@ -20994,21 +20959,21 @@ class Scope {
20994
20959
  return true;
20995
20960
  }
20996
20961
 
20997
- // deregisterForeignKey(key, id) {
20998
- // const listenerList = this.foreignListeners.get(key);
20999
- // if (!listenerList) return false;
20962
+ deregisterForeignKey(key, id) {
20963
+ const listenerList = this.foreignListeners.get(key);
20964
+ if (!listenerList) return false;
21000
20965
 
21001
- // const index = listenerList.findIndex((x) => x.id === id);
21002
- // if (index === -1) return false;
20966
+ const index = listenerList.findIndex((x) => x.id === id);
20967
+ if (index === -1) return false;
21003
20968
 
21004
- // listenerList.splice(index, 1);
21005
- // if (listenerList.length) {
21006
- // this.foreignListeners.set(key, listenerList);
21007
- // } else {
21008
- // this.foreignListeners.delete(key);
21009
- // }
21010
- // return true;
21011
- // }
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
+ }
21012
20977
 
21013
20978
  $eval(expr, locals) {
21014
20979
  const fn = $parse(expr);
@@ -21041,7 +21006,7 @@ class Scope {
21041
21006
  }
21042
21007
 
21043
21008
  /**
21044
- * @param {import('../../interface.js').Expression} expr
21009
+ * @param {import('../../interface.ts').Expression} expr
21045
21010
  * @returns {any}
21046
21011
  */
21047
21012
  $apply(expr) {
@@ -21222,12 +21187,12 @@ class Scope {
21222
21187
 
21223
21188
  /**
21224
21189
  * @internal
21225
- * @param {Listener} listener - The property path that was changed.
21190
+ * @param {import('./interface.ts').Listener} listener - The property path that was changed.
21226
21191
  */
21227
21192
  #notifyListener(listener, target) {
21228
21193
  const { originalTarget, listenerFn, watchFn } = listener;
21229
21194
  try {
21230
- let newVal = watchFn(originalTarget);
21195
+ let newVal = watchFn(/** @type {Scope} */ (originalTarget));
21231
21196
  if (isUndefined(newVal)) {
21232
21197
  newVal = watchFn(target);
21233
21198
  }
@@ -21257,6 +21222,13 @@ class Scope {
21257
21222
  }
21258
21223
  }
21259
21224
 
21225
+ /* @ignore */
21226
+ $flushQueue() {
21227
+ while ($postUpdateQueue.length) {
21228
+ $postUpdateQueue.shift()();
21229
+ }
21230
+ }
21231
+
21260
21232
  /**
21261
21233
  * Searches the scope instance
21262
21234
  *
@@ -21767,7 +21739,7 @@ const ngMessageDefaultDirective = ngMessageDirectiveFactory(true);
21767
21739
 
21768
21740
  /**
21769
21741
  * @param {boolean} isDefault
21770
- * @returns {(any) => import("../../interface.js").Directive}
21742
+ * @returns {(any) => import("../../interface.ts").Directive}
21771
21743
  */
21772
21744
  function ngMessageDirectiveFactory(isDefault) {
21773
21745
  ngMessageDirective.$inject = ["$animate"];
@@ -21974,6 +21946,9 @@ function ngShowAriaDirective($aria) {
21974
21946
  return $aria.$$watchExpr("ngShow", "aria-hidden", [], true);
21975
21947
  }
21976
21948
 
21949
+ /**
21950
+ * @return {ng.Directive}
21951
+ */
21977
21952
  function ngMessagesAriaDirective() {
21978
21953
  return {
21979
21954
  restrict: "A",
@@ -21989,18 +21964,21 @@ function ngMessagesAriaDirective() {
21989
21964
  }
21990
21965
 
21991
21966
  ngClickAriaDirective.$inject = [$injectTokens.$aria, $injectTokens.$parse];
21967
+
21968
+ /**
21969
+ * @param $aria
21970
+ * @param {ng.ParseService} $parse
21971
+ * @return {ng.Directive}
21972
+ */
21992
21973
  function ngClickAriaDirective($aria, $parse) {
21993
21974
  return {
21994
21975
  restrict: "A",
21995
21976
  compile(_elem, attr) {
21996
21977
  if (hasOwn(attr, ARIA_DISABLE_ATTR)) return;
21997
21978
 
21998
- const fn = $parse(attr.ngClick);
21979
+ const fn = $parse(attr["ngClick"]);
21999
21980
 
22000
- /**
22001
- * @param {Element} elem
22002
- */
22003
- return function (scope, elem, attr) {
21981
+ return (scope, elem, attr) => {
22004
21982
  if (!isNodeOneOf(elem, nativeAriaNodeNames)) {
22005
21983
  if ($aria.config("bindRoleForClick") && !elem.hasAttribute("role")) {
22006
21984
  elem.setAttribute("role", "button");
@@ -22037,10 +22015,6 @@ function ngClickAriaDirective($aria, $parse) {
22037
22015
  // See https://github.com/angular/angular.js/issues/16664
22038
22016
  event.preventDefault();
22039
22017
  }
22040
- scope.$apply(callback);
22041
- }
22042
-
22043
- function callback() {
22044
22018
  fn(scope, { $event: event });
22045
22019
  }
22046
22020
  },
@@ -22362,6 +22336,7 @@ function registerRestorableStyles(backup, node, properties) {
22362
22336
  }
22363
22337
 
22364
22338
  function AnimateCssProvider() {
22339
+ let activeClasses;
22365
22340
  this.$get = [
22366
22341
  "$$AnimateRunner",
22367
22342
  "$$animateCache",
@@ -22705,10 +22680,7 @@ function AnimateCssProvider() {
22705
22680
  return closeAndReturnNoopAnimator();
22706
22681
  }
22707
22682
 
22708
- let activeClasses = pendClasses(
22709
- preparationClasses,
22710
- ACTIVE_CLASS_SUFFIX,
22711
- );
22683
+ activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
22712
22684
 
22713
22685
  if (options.delay != null) {
22714
22686
  if (typeof options.delay !== "boolean") {
@@ -22845,7 +22817,9 @@ function AnimateCssProvider() {
22845
22817
 
22846
22818
  if (events && events.length) {
22847
22819
  // Remove the transitionend / animationend listener(s)
22848
- element.off(events.join(" "), onAnimationProgress);
22820
+ events.forEach((i) =>
22821
+ element.removeEventListener(i, onAnimationProgress),
22822
+ );
22849
22823
  }
22850
22824
 
22851
22825
  // Cancel the fallback closing timeout and remove the timer data
@@ -23280,11 +23254,6 @@ function AnimateQueueProvider($animateProvider) {
23280
23254
  ) {
23281
23255
  const activeAnimationsLookup = new Map();
23282
23256
  const disabledElementsLookup = new Map();
23283
- let animationsEnabled = null;
23284
-
23285
- function removeFromDisabledElementsLookup(evt) {
23286
- disabledElementsLookup.delete(evt.target);
23287
- }
23288
23257
 
23289
23258
  function postDigestTaskFactory() {
23290
23259
  let postDigestCalled = false;
@@ -23324,11 +23293,6 @@ function AnimateQueueProvider($animateProvider) {
23324
23293
  // any animations are triggered.
23325
23294
  $rootScope.$postUpdate(() => {
23326
23295
  $rootScope.$postUpdate(() => {
23327
- // we check for null directly in the event that the application already called
23328
- // .enabled() with whatever arguments that it provided it with
23329
- if (animationsEnabled === null) {
23330
- animationsEnabled = true;
23331
- }
23332
23296
  });
23333
23297
  });
23334
23298
  }
@@ -23467,47 +23431,6 @@ function AnimateQueueProvider($animateProvider) {
23467
23431
  options.domOperation = domOperation;
23468
23432
  return queueAnimation(element, event, options);
23469
23433
  },
23470
-
23471
- // this method has four signatures:
23472
- // () - global getter
23473
- // (bool) - global setter
23474
- // (element) - element getter
23475
- // (element, bool) - element setter<F37>
23476
- enabled(element, bool) {
23477
- const argCount = arguments.length;
23478
-
23479
- if (argCount === 0) {
23480
- // () - Global getter
23481
- bool = !!animationsEnabled;
23482
- } else {
23483
- const hasElement = isElement(element);
23484
-
23485
- if (!hasElement) {
23486
- // (bool) - Global setter
23487
- bool = animationsEnabled = !!element;
23488
- } else {
23489
- const node = element;
23490
-
23491
- if (argCount === 1) {
23492
- // (element) - Element getter
23493
- bool = !disabledElementsLookup.get(node);
23494
- } else {
23495
- // (element, bool) - Element setter
23496
- if (!disabledElementsLookup.has(node)) {
23497
- // The element is added to the map for the first time.
23498
- // Create a listener to remove it on `$destroy` (to avoid memory leak).
23499
- element.addEventListener(
23500
- "$destroy",
23501
- removeFromDisabledElementsLookup,
23502
- );
23503
- }
23504
- disabledElementsLookup.set(node, !bool);
23505
- }
23506
- }
23507
- }
23508
-
23509
- return bool;
23510
- },
23511
23434
  };
23512
23435
 
23513
23436
  return $animate;
@@ -23564,6 +23487,7 @@ function AnimateQueueProvider($animateProvider) {
23564
23487
  if (options.to && !isObject(options.to)) {
23565
23488
  options.to = null;
23566
23489
  }
23490
+
23567
23491
  // If animations are hard-disabled for the whole application there is no need to continue.
23568
23492
  // There are also situations where a directive issues an animation for a JQLite wrapper that
23569
23493
  // contains only comment nodes. In this case, there is no way we can perform an animation.
@@ -23576,7 +23500,6 @@ function AnimateQueueProvider($animateProvider) {
23576
23500
  close();
23577
23501
  return runner;
23578
23502
  }
23579
-
23580
23503
  const isStructural = ["enter", "move", "leave"].indexOf(event) >= 0;
23581
23504
 
23582
23505
  // This is a hard disable of all animations the element itself, therefore there is no need to
@@ -23812,6 +23735,8 @@ function AnimateQueueProvider($animateProvider) {
23812
23735
  });
23813
23736
  });
23814
23737
 
23738
+ // Since we don't have digest any more - trigger queue here
23739
+ setTimeout($rootScope.$flushQueue, 0);
23815
23740
  return runner;
23816
23741
 
23817
23742
  function notifyProgress(runner, event, phase, data) {
@@ -23975,14 +23900,14 @@ function AnimateQueueProvider($animateProvider) {
23975
23900
  // TODO: use caching here to speed things up for detection
23976
23901
  // TODO: add documentation
23977
23902
 
23978
- AnimateJsProvider.$inject = ["$animateProvider"];
23903
+ AnimateJsProvider.$inject = [$injectTokens.$animate + "Provider"];
23979
23904
  function AnimateJsProvider($animateProvider) {
23980
23905
  this.$get = [
23981
23906
  $injectTokens.$injector,
23982
23907
  "$$AnimateRunner",
23983
23908
  /**
23984
23909
  *
23985
- * @param {import("../core/di/internal-injector").InjectorService} $injector
23910
+ * @param {ng.InjectorService} $injector
23986
23911
  * @param {*} $$AnimateRunner
23987
23912
  * @returns
23988
23913
  */
@@ -24841,8 +24766,8 @@ function AnimationProvider() {
24841
24766
  }
24842
24767
 
24843
24768
  /**
24844
- * @typedef {import('./interface.js').RafScheduler} RafScheduler
24845
- * @typedef {import('../interface.js').ServiceProvider} ServiceProvider
24769
+ * @typedef {import('./interface.ts').RafScheduler} RafScheduler
24770
+ * @typedef {import('../interface.ts').ServiceProvider} ServiceProvider
24846
24771
  */
24847
24772
 
24848
24773
  /**
@@ -25357,9 +25282,9 @@ function AnimateJsDriverProvider($$animationProvider) {
25357
25282
  ];
25358
25283
  }
25359
25284
 
25360
- ngAnimateSwapDirective.$inject = ["$animate"];
25285
+ ngAnimateSwapDirective.$inject = [$injectTokens.$animate];
25361
25286
  /**
25362
- * @returns {import('../interface.ts').Directive}
25287
+ * @returns {ng.Directive}
25363
25288
  */
25364
25289
  function ngAnimateSwapDirective($animate) {
25365
25290
  return {
@@ -25368,10 +25293,10 @@ function ngAnimateSwapDirective($animate) {
25368
25293
  terminal: true,
25369
25294
  priority: 550, // We use 550 here to ensure that the directive is caught before others,
25370
25295
  // but after `ngIf` (at priority 600).
25371
- link(scope, $element, attrs, ctrl, $transclude) {
25296
+ link(scope, $element, attrs, _ctrl, $transclude) {
25372
25297
  let previousElement;
25373
25298
  let previousScope;
25374
- scope.$watch(attrs["ngAnimateSwap"] || attrs["for"], (value) => {
25299
+ scope.$watch(attrs.ngAnimateSwap || attrs.for, (value) => {
25375
25300
  if (previousElement) {
25376
25301
  $animate.leave(previousElement);
25377
25302
  }
@@ -27598,7 +27523,7 @@ class PathUtils {
27598
27523
  * @param {PathNode[]} fromPath
27599
27524
  * @param {PathNode[]} toPath
27600
27525
  * @param {boolean} [reloadState]
27601
- * @returns {import("../transition/interface.js").TreeChanges}
27526
+ * @returns {import("../transition/interface.ts").TreeChanges}
27602
27527
  */
27603
27528
  static treeChanges(fromPath, toPath, reloadState) {
27604
27529
  const max = Math.min(fromPath.length, toPath.length);
@@ -28333,25 +28258,6 @@ ViewService.matches = (ngViewsByFqn, ngView) => (viewConfig) => {
28333
28258
  return vc.$ngViewContextAnchor === (ngViewContext && ngViewContext.name);
28334
28259
  };
28335
28260
 
28336
- /**
28337
- * An object for Transition Hook Phases
28338
- * @enum {number}
28339
- * @readonly
28340
- */
28341
- const TransitionHookPhase = {
28342
- CREATE: 0,
28343
- BEFORE: 1,
28344
- RUN: 2,
28345
- SUCCESS: 3,
28346
- ERROR: 4,
28347
- };
28348
-
28349
- /** An object for Transition Hook Scopes */
28350
- const TransitionHookScope = {
28351
- TRANSITION: 0,
28352
- STATE: 1,
28353
- };
28354
-
28355
28261
  /**
28356
28262
  * An object for Transition Rejection reasons.
28357
28263
  * @enum {number}
@@ -28471,7 +28377,7 @@ class Rejection {
28471
28377
  }
28472
28378
  }
28473
28379
 
28474
- /** @typedef {import('../../interface.js').ServiceProvider} ServiceProvider
28380
+ /** @typedef {import('../../interface.ts').ServiceProvider} ServiceProvider
28475
28381
 
28476
28382
  /**
28477
28383
  * Configurable provider for an injectable event bus
@@ -28828,6 +28734,31 @@ const defaultOptions = {
28828
28734
  bind: null,
28829
28735
  };
28830
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
+
28831
28762
  class TransitionHook {
28832
28763
  /**
28833
28764
  * Chains together an array of TransitionHooks.
@@ -30646,7 +30577,6 @@ class TransitionProvider {
30646
30577
  }
30647
30578
 
30648
30579
  _defineCoreEvents() {
30649
- const Phase = TransitionHookPhase;
30650
30580
  const TH = TransitionHook;
30651
30581
  const paths = this._criteriaPaths;
30652
30582
  const NORMAL_SORT = false,
@@ -30654,7 +30584,7 @@ class TransitionProvider {
30654
30584
  const SYNCHRONOUS = true;
30655
30585
  this._defineEvent(
30656
30586
  "onCreate",
30657
- Phase.CREATE,
30587
+ TransitionHookPhase.CREATE,
30658
30588
  0,
30659
30589
  paths.to,
30660
30590
  NORMAL_SORT,
@@ -30662,15 +30592,21 @@ class TransitionProvider {
30662
30592
  TH.THROW_ERROR,
30663
30593
  SYNCHRONOUS,
30664
30594
  );
30665
- this._defineEvent("onBefore", Phase.BEFORE, 0, paths.to);
30666
- this._defineEvent("onStart", Phase.RUN, 0, paths.to);
30667
- this._defineEvent("onExit", Phase.RUN, 100, paths.exiting, REVERSE_SORT);
30668
- this._defineEvent("onRetain", Phase.RUN, 200, paths.retained);
30669
- this._defineEvent("onEnter", Phase.RUN, 300, paths.entering);
30670
- 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);
30671
30607
  this._defineEvent(
30672
30608
  "onSuccess",
30673
- Phase.SUCCESS,
30609
+ TransitionHookPhase.SUCCESS,
30674
30610
  0,
30675
30611
  paths.to,
30676
30612
  NORMAL_SORT,
@@ -30680,7 +30616,7 @@ class TransitionProvider {
30680
30616
  );
30681
30617
  this._defineEvent(
30682
30618
  "onError",
30683
- Phase.ERROR,
30619
+ TransitionHookPhase.ERROR,
30684
30620
  0,
30685
30621
  paths.to,
30686
30622
  NORMAL_SORT,
@@ -30946,7 +30882,7 @@ class StateProvider {
30946
30882
 
30947
30883
  /**
30948
30884
  *
30949
- * @param {import("./interface.js").StateDeclaration} definition
30885
+ * @param {import("./interface.ts").StateDeclaration} definition
30950
30886
  */
30951
30887
  state(definition) {
30952
30888
  if (!definition.name) {
@@ -32246,7 +32182,7 @@ function encodeDashes(str) {
32246
32182
  );
32247
32183
  }
32248
32184
 
32249
- /** @typedef {import('./interface.js').StateDeclaration} StateDeclaration */
32185
+ /** @typedef {import('./interface.ts').StateDeclaration} StateDeclaration */
32250
32186
 
32251
32187
  /**
32252
32188
  * Internal representation of a ng-router state.
@@ -32269,7 +32205,7 @@ class StateObject {
32269
32205
  includes = undefined;
32270
32206
 
32271
32207
  /**
32272
- * @param {import('./interface.js').StateDeclaration} config
32208
+ * @param {import('./interface.ts').StateDeclaration} config
32273
32209
  */
32274
32210
  constructor(config) {
32275
32211
  Object.assign(this, config);
@@ -32277,7 +32213,7 @@ class StateObject {
32277
32213
  return this;
32278
32214
  };
32279
32215
  /**
32280
- * @type {import('./interface.js').StateDeclaration}
32216
+ * @type {import('./interface.ts').StateDeclaration}
32281
32217
  */
32282
32218
  this.self = config;
32283
32219
  /**
@@ -34666,7 +34602,7 @@ function $StateRefActiveDirective(
34666
34602
  * ```
34667
34603
  */
34668
34604
 
34669
- /** @type {import("../../interface.js").AnnotatedDirectiveFactory} */
34605
+ /** @type {import("../../interface.ts").AnnotatedDirectiveFactory} */
34670
34606
  let ngView = [
34671
34607
  "$view",
34672
34608
  "$animate",
@@ -34677,7 +34613,7 @@ let ngView = [
34677
34613
  * @param {*} $animate
34678
34614
  * @param {*} $viewScroll
34679
34615
  * @param {*} $interpolate
34680
- * @returns {import("../../interface.js").Directive}
34616
+ * @returns {import("../../interface.ts").Directive}
34681
34617
  */
34682
34618
  function $ViewDirective($view, $animate, $viewScroll, $interpolate) {
34683
34619
  function getRenderer() {
@@ -35018,8 +34954,8 @@ function registerControllerCallbacks(
35018
34954
 
35019
34955
  ngChannelDirective.$inject = [$injectTokens.$eventBus];
35020
34956
  /**
35021
- * @param {import("../../services/pubsub/pubsub.js").PubSub} $eventBus
35022
- * @returns {import("../../interface.ts").Directive}
34957
+ * @param {ng.PubSubService} $eventBus
34958
+ * @returns {ng.Directive}
35023
34959
  */
35024
34960
  function ngChannelDirective($eventBus) {
35025
34961
  return {
@@ -35103,7 +35039,8 @@ function ngSetterDirective($parse, $log) {
35103
35039
  }
35104
35040
 
35105
35041
  /**
35106
- * @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
35107
35044
  * @returns {ng.DirectiveFactory}
35108
35045
  */
35109
35046
  function defineDirective(method, attrOverride) {
@@ -35117,6 +35054,7 @@ function defineDirective(method, attrOverride) {
35117
35054
  $injectTokens.$parse,
35118
35055
  $injectTokens.$state,
35119
35056
  $injectTokens.$sse,
35057
+ $injectTokens.$animate,
35120
35058
  ];
35121
35059
  return directive;
35122
35060
  }
@@ -35136,15 +35074,11 @@ const ngPutDirective = defineDirective("put");
35136
35074
  /** @type {ng.DirectiveFactory} */
35137
35075
  const ngSseDirective = defineDirective("get", "ngSse");
35138
35076
 
35139
- /**
35140
- * @typedef {"click" | "change" | "submit"} EventType
35141
- */
35142
-
35143
35077
  /**
35144
35078
  * Selects DOM event to listen for based on the element type.
35145
35079
  *
35146
35080
  * @param {Element} element - The DOM element to inspect.
35147
- * @returns {EventType} The name of the event to listen for.
35081
+ * @returns {"click" | "change" | "submit"} The name of the event to listen for.
35148
35082
  */
35149
35083
  function getEventNameForElement(element) {
35150
35084
  const tag = element.tagName.toLowerCase();
@@ -35156,89 +35090,6 @@ function getEventNameForElement(element) {
35156
35090
  return "click";
35157
35091
  }
35158
35092
 
35159
- /**
35160
- * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35161
- *
35162
- * @param {string} html - The HTML string returned from the server.
35163
- * @param {import("./interface.ts").SwapModeType} swap
35164
- * @param {Element} target - The target DOM element to apply the swap to.
35165
- * @param {ng.Scope} scope
35166
- * @param {ng.CompileService} $compile
35167
- */
35168
- function handleSwapResponse(html, swap, target, scope, $compile) {
35169
- let nodes = [];
35170
- if (!["textcontent", "delete", "none"].includes(swap)) {
35171
- if (!html) {
35172
- return;
35173
- }
35174
-
35175
- if (isObject(html)) {
35176
- scope.$merge(html);
35177
- return;
35178
- }
35179
-
35180
- const compiled = $compile(html)(scope);
35181
- nodes =
35182
- compiled instanceof DocumentFragment
35183
- ? Array.from(compiled.childNodes)
35184
- : [compiled];
35185
- }
35186
-
35187
- switch (swap) {
35188
- case "innerHTML":
35189
- target.replaceChildren(...nodes);
35190
- break;
35191
-
35192
- case "outerHTML": {
35193
- const parent = target.parentNode;
35194
- if (!parent) return;
35195
- const frag = document.createDocumentFragment();
35196
- nodes.forEach((n) => frag.appendChild(n));
35197
- parent.replaceChild(frag, target);
35198
- break;
35199
- }
35200
-
35201
- case "textContent":
35202
- target.textContent = html;
35203
- break;
35204
-
35205
- case "beforebegin":
35206
- nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35207
- break;
35208
-
35209
- case "afterbegin":
35210
- nodes
35211
- .slice()
35212
- .reverse()
35213
- .forEach((node) => target.insertBefore(node, target.firstChild));
35214
- break;
35215
-
35216
- case "beforeend":
35217
- nodes.forEach((node) => target.appendChild(node));
35218
- break;
35219
-
35220
- case "afterend":
35221
- nodes
35222
- .slice()
35223
- .reverse()
35224
- .forEach((node) =>
35225
- target.parentNode.insertBefore(node, target.nextSibling),
35226
- );
35227
- break;
35228
-
35229
- case "delete":
35230
- target.remove();
35231
- break;
35232
-
35233
- case "none":
35234
- break;
35235
-
35236
- default:
35237
- target.replaceChildren(...nodes);
35238
- break;
35239
- }
35240
- }
35241
-
35242
35093
  /**
35243
35094
  * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
35244
35095
  *
@@ -35247,16 +35098,136 @@ function handleSwapResponse(html, swap, target, scope, $compile) {
35247
35098
  * @returns {ng.DirectiveFactory}
35248
35099
  */
35249
35100
  function createHttpDirective(method, attrName) {
35101
+ let content = undefined;
35102
+
35250
35103
  /**
35251
35104
  * @param {ng.HttpService} $http
35252
35105
  * @param {ng.CompileService} $compile
35253
35106
  * @param {ng.LogService} $log
35254
35107
  * @param {ng.ParseService} $parse
35255
35108
  * @param {ng.StateService} $state
35256
- * @param {Function} $sse
35109
+ * @param {ng.SseService} $sse
35257
35110
  * @returns {ng.Directive}
35258
35111
  */
35259
- 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
+
35260
35231
  /**
35261
35232
  * Collects form data from the element or its associated form.
35262
35233
  *
@@ -35270,15 +35241,12 @@ function createHttpDirective(method, attrName) {
35270
35241
  const tag = element.tagName.toLowerCase();
35271
35242
 
35272
35243
  if (tag === "form") {
35273
- /** @type {HTMLFormElement} */
35274
35244
  form = /** @type {HTMLFormElement} */ (element);
35275
35245
  } else if ("form" in element && element.form) {
35276
- /** @type {HTMLFormElement} */
35277
35246
  form = /** @type {HTMLFormElement} */ (element.form);
35278
35247
  } else if (element.hasAttribute("form")) {
35279
35248
  const formId = element.getAttribute("form");
35280
35249
  if (formId) {
35281
- /** @type {HTMLElement | null} */
35282
35250
  const maybeForm = document.getElementById(formId);
35283
35251
  if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
35284
35252
  form = /** @type {HTMLFormElement} */ (maybeForm);
@@ -35316,13 +35284,10 @@ function createHttpDirective(method, attrName) {
35316
35284
  return {
35317
35285
  restrict: "A",
35318
35286
  link(scope, element, attrs) {
35319
- const eventName =
35320
- attrs["trigger"] ||
35321
- /** @type {EventType} */ getEventNameForElement(element);
35322
-
35287
+ const eventName = attrs.trigger || getEventNameForElement(element);
35323
35288
  const tag = element.tagName.toLowerCase();
35324
35289
 
35325
- if (isDefined(attrs["latch"])) {
35290
+ if (isDefined(attrs.latch)) {
35326
35291
  attrs.$observe(
35327
35292
  "latch",
35328
35293
  callBackAfterFirst(() =>
@@ -35338,24 +35303,14 @@ function createHttpDirective(method, attrName) {
35338
35303
  element.dispatchEvent(new Event(eventName));
35339
35304
  intervalId = setInterval(
35340
35305
  () => element.dispatchEvent(new Event(eventName)),
35341
- parseInt(attrs["interval"]) || 1000,
35306
+ parseInt(attrs.interval) || 1000,
35342
35307
  );
35343
35308
  }
35344
35309
 
35345
35310
  element.addEventListener(eventName, async (event) => {
35346
35311
  if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35347
35312
  if (tag === "form") event.preventDefault();
35348
- const swap = attrs["swap"] || "innerHTML";
35349
- const targetSelector = attrs["target"];
35350
- const target = targetSelector
35351
- ? document.querySelector(targetSelector)
35352
- : element;
35353
-
35354
- if (!target) {
35355
- $log.warn(`${attrName}: target "${targetSelector}" not found`);
35356
- return;
35357
- }
35358
-
35313
+ const swap = attrs.swap || "innerHTML";
35359
35314
  const url = attrs[attrName];
35360
35315
  if (!url) {
35361
35316
  $log.warn(`${attrName}: no URL specified`);
@@ -35363,56 +35318,57 @@ function createHttpDirective(method, attrName) {
35363
35318
  }
35364
35319
 
35365
35320
  const handler = (res) => {
35366
- if (isDefined(attrs["loading"])) {
35321
+ if (isDefined(attrs.loading)) {
35367
35322
  attrs.$set("loading", false);
35368
35323
  }
35369
35324
 
35370
- if (isDefined(attrs["loadingClass"])) {
35371
- attrs.$removeClass(attrs["loadingClass"]);
35325
+ if (isDefined(attrs.loadingClass)) {
35326
+ attrs.$removeClass(attrs.loadingClass);
35372
35327
  }
35373
35328
 
35374
35329
  const html = res.data;
35375
35330
  if (200 <= res.status && res.status <= 299) {
35376
- if (isDefined(attrs["success"])) {
35377
- $parse(attrs["success"])(scope, { $res: html });
35331
+ if (isDefined(attrs.success)) {
35332
+ $parse(attrs.success)(scope, { $res: html });
35378
35333
  }
35379
35334
 
35380
- if (isDefined(attrs["stateSuccess"])) {
35381
- $state.go(attrs["stateSuccess"]);
35335
+ if (isDefined(attrs.stateSuccess)) {
35336
+ $state.go(attrs.stateSuccess);
35382
35337
  }
35383
35338
  } else if (400 <= res.status && res.status <= 599) {
35384
- if (isDefined(attrs["error"])) {
35385
- $parse(attrs["error"])(scope, { $res: html });
35339
+ if (isDefined(attrs.error)) {
35340
+ $parse(attrs.error)(scope, { $res: html });
35386
35341
  }
35387
35342
 
35388
- if (isDefined(attrs["stateError"])) {
35389
- $state.go(attrs["stateError"]);
35343
+ if (isDefined(attrs.stateError)) {
35344
+ $state.go(attrs.stateError);
35390
35345
  }
35391
35346
  }
35392
35347
 
35393
- handleSwapResponse(
35394
- html,
35395
- /** @type {import("./interface.ts").SwapModeType} */ (swap),
35396
- target,
35397
- scope,
35398
- $compile,
35399
- );
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
+ }
35400
35357
  };
35401
- if (isDefined(attrs["delay"])) {
35402
- await wait(parseInt(attrs["delay"]) | 0);
35403
- }
35404
35358
 
35405
- if (throttled) {
35406
- return;
35359
+ if (isDefined(attrs.delay)) {
35360
+ await wait(parseInt(attrs.delay) | 0);
35407
35361
  }
35408
35362
 
35409
- if (isDefined(attrs["throttle"])) {
35363
+ if (throttled) return;
35364
+
35365
+ if (isDefined(attrs.throttle)) {
35410
35366
  throttled = true;
35411
35367
  attrs.$set("throttled", true);
35412
35368
  setTimeout(() => {
35413
35369
  attrs.$set("throttled", false);
35414
35370
  throttled = false;
35415
- }, parseInt(attrs["throttle"]));
35371
+ }, parseInt(attrs.throttle));
35416
35372
  }
35417
35373
 
35418
35374
  if (isDefined(attrs["loading"])) {
@@ -35420,13 +35376,13 @@ function createHttpDirective(method, attrName) {
35420
35376
  }
35421
35377
 
35422
35378
  if (isDefined(attrs["loadingClass"])) {
35423
- attrs.$addClass(attrs["loadingClass"]);
35379
+ attrs.$addClass(attrs.loadingClass);
35424
35380
  }
35425
35381
 
35426
35382
  if (method === "post" || method === "put") {
35427
35383
  let data;
35428
35384
  const config = {};
35429
- if (attrs["enctype"]) {
35385
+ if (attrs.enctype) {
35430
35386
  config.headers = {
35431
35387
  "Content-Type": attrs["enctype"],
35432
35388
  };
@@ -35436,11 +35392,10 @@ function createHttpDirective(method, attrName) {
35436
35392
  }
35437
35393
  $http[method](url, data, config).then(handler).catch(handler);
35438
35394
  } else {
35439
- // If SSE mode is enabled
35440
- if (method === "get" && attrs["ngSse"]) {
35395
+ if (method === "get" && attrs.ngSse) {
35441
35396
  const sseUrl = url;
35442
35397
  const config = {
35443
- withCredentials: attrs["withCredentials"] === "true",
35398
+ withCredentials: attrs.withCredentials === "true",
35444
35399
  transformMessage: (data) => {
35445
35400
  try {
35446
35401
  return JSON.parse(data);
@@ -35450,9 +35405,9 @@ function createHttpDirective(method, attrName) {
35450
35405
  },
35451
35406
  onOpen: () => {
35452
35407
  $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
35453
- if (isDefined(attrs["loading"])) attrs.$set("loading", false);
35454
- if (isDefined(attrs["loadingClass"]))
35455
- attrs.$removeClass(attrs["loadingClass"]);
35408
+ if (isDefined(attrs.loading)) attrs.$set("loading", false);
35409
+ if (isDefined(attrs.loadingClass))
35410
+ attrs.$removeClass(attrs.loadingClass);
35456
35411
  },
35457
35412
  onMessage: (data) => {
35458
35413
  const res = { status: 200, data };
@@ -35463,12 +35418,15 @@ function createHttpDirective(method, attrName) {
35463
35418
  const res = { status: 500, data: err };
35464
35419
  handler(res);
35465
35420
  },
35421
+ onReconnect: (count) => {
35422
+ $log.info(`ngSse: reconnected ${count} time(s)`);
35423
+ if (attrs.onReconnect)
35424
+ $parse(attrs.onReconnect)(scope, { $count: count });
35425
+ },
35466
35426
  };
35467
35427
 
35468
- // Open the SSE connection using the injected service
35469
35428
  const source = $sse(sseUrl, config);
35470
35429
 
35471
- // Cleanup on scope destroy
35472
35430
  scope.$on("$destroy", () => {
35473
35431
  $log.info(`${attrName}: closing SSE connection`);
35474
35432
  source.close();
@@ -35483,7 +35441,6 @@ function createHttpDirective(method, attrName) {
35483
35441
  scope.$on("$destroy", () => clearInterval(intervalId));
35484
35442
  }
35485
35443
 
35486
- // Eagerly execute for 'load' event
35487
35444
  if (eventName == "load") {
35488
35445
  element.dispatchEvent(new Event("load"));
35489
35446
  }
@@ -35564,38 +35521,54 @@ function ngElDirective() {
35564
35521
  * const source = $sse('/events', {
35565
35522
  * onMessage: (data) => console.log(data),
35566
35523
  * onError: (err) => console.error(err),
35567
- * withCredentials: true
35524
+ * retryDelay: 2000,
35525
+ * heartbeatTimeout: 10000,
35568
35526
  * });
35569
35527
  *
35570
- * // later:
35571
35528
  * source.close();
35572
35529
  */
35573
-
35574
35530
  class SseProvider {
35575
35531
  constructor() {
35576
35532
  /**
35577
35533
  * Optional provider-level defaults
35578
35534
  * @type {ng.SseConfig}
35579
35535
  */
35580
- 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
+ };
35581
35548
  }
35582
35549
 
35583
35550
  /**
35584
35551
  * Returns the $sse service function
35585
35552
  * @returns {ng.SseService}
35586
35553
  */
35587
- $get =
35588
- () =>
35589
- (url, config = {}) => {
35590
- const finalUrl = this.#buildUrl(url, config.params);
35591
- return this.#createEventSource(finalUrl, config);
35592
- };
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
+ ];
35593
35566
 
35594
35567
  /**
35595
35568
  * Build URL with query parameters
35596
- * @param {string} url - Base URL
35597
- * @param {Record<string, any>=} params - Query parameters
35598
- * @returns {string} URL with serialized query string
35569
+ * @param {string} url
35570
+ * @param {Record<string, any>=} params
35571
+ * @returns {string}
35599
35572
  */
35600
35573
  #buildUrl(url, params) {
35601
35574
  if (!params) return url;
@@ -35606,37 +35579,376 @@ class SseProvider {
35606
35579
  }
35607
35580
 
35608
35581
  /**
35609
- * Create and manage an EventSource
35610
- * @param {string} url - URL for SSE connection
35611
- * @param {ng.SseConfig} config - Configuration object
35612
- * @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}
35613
35586
  */
35614
- #createEventSource(url, config) {
35615
- const es = new EventSource(url, {
35616
- withCredentials: !!config.withCredentials,
35617
- });
35587
+ #createConnection(url, config) {
35588
+ let es;
35589
+ let retryCount = 0;
35590
+ let closed = false;
35591
+ let heartbeatTimer;
35618
35592
 
35619
- if (config.onOpen) {
35620
- es.addEventListener("open", (e) => config.onOpen(e));
35621
- }
35593
+ const connect = () => {
35594
+ if (closed) return;
35622
35595
 
35623
- es.addEventListener("message", (e) => {
35624
- let data = e.data;
35625
- try {
35626
- data = config.transformMessage
35627
- ? config.transformMessage(data)
35628
- : JSON.parse(data);
35629
- } catch {
35630
- // leave as raw string if not JSON
35596
+ es = new EventSource(url, {
35597
+ withCredentials: !!config.withCredentials,
35598
+ });
35599
+
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
+ });
35616
+
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
+ };
35657
+ }
35658
+ }
35659
+
35660
+ /**
35661
+ * @returns {ng.Directive}
35662
+ */
35663
+ function ngViewportDirective() {
35664
+ return {
35665
+ restrict: "A",
35666
+ link(scope, element, attrs) {
35667
+ const enterExpr = attrs["onEnter"];
35668
+ const leaveExpr = attrs["onLeave"];
35669
+
35670
+ const observer = new IntersectionObserver(
35671
+ (entries) => {
35672
+ entries.forEach((entry) => {
35673
+ if (entry.isIntersecting) {
35674
+ if (enterExpr) scope.$eval(enterExpr);
35675
+ } else {
35676
+ if (leaveExpr) scope.$eval(leaveExpr);
35677
+ }
35678
+ });
35679
+ },
35680
+ {
35681
+ root: null, // viewport
35682
+ threshold: 0.1, // consider "in view" if 10% visible
35683
+ },
35684
+ );
35685
+
35686
+ observer.observe(element);
35687
+
35688
+ // Clean up when the element is removed from DOM
35689
+ const parent = element.parentNode;
35690
+ let mutationObserver;
35691
+ if (parent) {
35692
+ mutationObserver = new MutationObserver((mutations) => {
35693
+ for (const mutation of mutations) {
35694
+ Array.from(mutation.removedNodes).forEach((removedNode) => {
35695
+ if (removedNode === element) {
35696
+ observer.disconnect();
35697
+ mutationObserver.disconnect();
35698
+ }
35699
+ });
35700
+ }
35701
+ });
35702
+ mutationObserver.observe(parent, { childList: true });
35631
35703
  }
35632
- config.onMessage?.(data, e);
35633
- });
35634
35704
 
35635
- if (config.onError) {
35636
- es.addEventListener("error", (e) => config.onError(e));
35705
+ scope.$on("$destroy", () => {
35706
+ observer.disconnect();
35707
+ if (mutationObserver) mutationObserver.disconnect();
35708
+ });
35709
+ },
35710
+ };
35711
+ }
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;
35637
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
+ }
35638
35841
 
35639
- return es;
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
+ };
35640
35952
  }
35641
35953
  }
35642
35954
 
@@ -35652,7 +35964,7 @@ function registerNgModule(angular) {
35652
35964
  [],
35653
35965
  [
35654
35966
  $injectTokens.$provide,
35655
- /** @param {import("./interface.js").Provider} $provide */
35967
+ /** @param {import("./interface.ts").Provider} $provide */
35656
35968
  ($provide) => {
35657
35969
  // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
35658
35970
  $provide.provider({
@@ -35717,6 +36029,8 @@ function registerNgModule(angular) {
35717
36029
  maxlength: maxlengthDirective,
35718
36030
  ngValue: ngValueDirective,
35719
36031
  ngModelOptions: ngModelOptionsDirective,
36032
+ ngViewport: ngViewportDirective,
36033
+ ngWorker: ngWorkerDirective,
35720
36034
  })
35721
36035
  .directive({
35722
36036
  input: hiddenInputBrowserCacheDirective,
@@ -35784,6 +36098,7 @@ function registerNgModule(angular) {
35784
36098
  $url: UrlService,
35785
36099
  $stateRegistry: StateRegistryProvider,
35786
36100
  $eventBus: PubSubProvider,
36101
+ $worker: WorkerProvider,
35787
36102
  });
35788
36103
  },
35789
36104
  ],
@@ -35815,7 +36130,7 @@ class Angular {
35815
36130
  /**
35816
36131
  * @type {string} `version` from `package.json`
35817
36132
  */
35818
- this.version = "0.9.8"; //inserted via rollup plugin
36133
+ this.version = "0.10.0"; //inserted via rollup plugin
35819
36134
 
35820
36135
  /** @type {!Array<string|any>} */
35821
36136
  this.bootsrappedModules = [];
@@ -35908,10 +36223,10 @@ class Angular {
35908
36223
  $injectTokens.$compile,
35909
36224
  $injectTokens.$injector,
35910
36225
  /**
35911
- * @param {import('./core/scope/scope.js').Scope} scope
36226
+ * @param {ng.Scope} scope
35912
36227
  * @param {Element} el
35913
- * @param {import("./core/compile/compile.js").CompileFn} compile
35914
- * @param {import("./core/di/internal-injector.js").InjectorService} $injector
36228
+ * @param {ng.CompileService} compile
36229
+ * @param {ng.InjectorService} $injector
35915
36230
  */
35916
36231
  (scope, el, compile, $injector) => {
35917
36232
  // ng-route deps
@@ -36038,7 +36353,7 @@ class Angular {
36038
36353
  * @param {string} name The name of the module to create or retrieve.
36039
36354
  * @param {Array.<string>} [requires] If specified then new module is being created. If
36040
36355
  * unspecified then the module is being retrieved for further configuration.
36041
- * @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
36042
36357
  * passed to {@link NgModule.config NgModule.config()}.
36043
36358
  * @returns {NgModule} A newly registered module.
36044
36359
  */