@angular-wave/angular.ts 0.9.9 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/@types/angular.d.ts +2 -2
  2. package/@types/animations/animate-js.d.ts +1 -1
  3. package/@types/animations/animate-queue.d.ts +0 -1
  4. package/@types/animations/animate-swap.d.ts +2 -4
  5. package/@types/animations/animate.d.ts +2 -2
  6. package/@types/animations/raf-scheduler.d.ts +4 -4
  7. package/@types/animations/shared.d.ts +30 -2
  8. package/@types/core/compile/attributes.d.ts +5 -8
  9. package/@types/core/compile/compile.d.ts +4 -4
  10. package/@types/core/controller/controller.d.ts +1 -1
  11. package/@types/core/di/ng-module.d.ts +14 -14
  12. package/@types/core/scope/interface.d.ts +18 -0
  13. package/@types/core/scope/scope.d.ts +16 -97
  14. package/@types/directive/aria/aria.d.ts +11 -13
  15. package/@types/directive/attrs/attrs.d.ts +2 -2
  16. package/@types/directive/events/events.d.ts +0 -2
  17. package/@types/directive/http/http.d.ts +4 -22
  18. package/@types/directive/if/if.d.ts +2 -4
  19. package/@types/directive/include/include.d.ts +2 -2
  20. package/@types/directive/messages/messages.d.ts +3 -3
  21. package/@types/directive/observe/observe.d.ts +2 -5
  22. package/@types/directive/worker/worker.d.ts +15 -0
  23. package/@types/interface.d.ts +5 -5
  24. package/@types/namespace.d.ts +7 -1
  25. package/@types/router/directives/view-directive.d.ts +2 -2
  26. package/@types/router/path/path-utils.d.ts +2 -2
  27. package/@types/router/state/state-object.d.ts +6 -6
  28. package/@types/router/state/state-service.d.ts +3 -3
  29. package/@types/router/transition/hook-builder.d.ts +1 -1
  30. package/@types/router/transition/interface.d.ts +1 -12
  31. package/@types/router/transition/transition-hook.d.ts +31 -0
  32. package/@types/router/transition/transition-service.d.ts +1 -1
  33. package/@types/router/transition/transition.d.ts +2 -2
  34. package/@types/services/pubsub/pubsub.d.ts +2 -2
  35. package/@types/services/sse/interface.d.ts +27 -1
  36. package/@types/services/sse/sse.d.ts +4 -3
  37. package/@types/services/worker/interface.d.ts +12 -0
  38. package/@types/services/worker/worker.d.ts +31 -0
  39. package/@types/shared/url-utils/url-utils.d.ts +14 -14
  40. package/README.md +1 -1
  41. package/dist/angular-ts.esm.js +1317 -1032
  42. package/dist/angular-ts.umd.js +1317 -1032
  43. package/dist/angular-ts.umd.min.js +1 -1
  44. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /* Version: 0.9.9 - October 28, 2025 22:08:28 */
1
+ /* Version: 0.10.0 - November 8, 2025 10:37:13 */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -912,7 +912,7 @@
912
912
  return arg;
913
913
  }
914
914
 
915
- /** @type {import("./interface.js").ErrorHandlingConfig} */
915
+ /** @type {import("./interface.ts").ErrorHandlingConfig} */
916
916
  const minErrConfig = {
917
917
  objectMaxDepth: 5,
918
918
  urlErrorParamsEnabled: true,
@@ -1204,6 +1204,382 @@
1204
1204
  */
1205
1205
  const Cache = new Map();
1206
1206
 
1207
+ /**
1208
+ * @readonly
1209
+ * @enum {number}
1210
+ */
1211
+ const ASTType = {
1212
+ Program: 1,
1213
+ ExpressionStatement: 2,
1214
+ AssignmentExpression: 3,
1215
+ ConditionalExpression: 4,
1216
+ LogicalExpression: 5,
1217
+ BinaryExpression: 6,
1218
+ UnaryExpression: 7,
1219
+ CallExpression: 8,
1220
+ MemberExpression: 9,
1221
+ Identifier: 10,
1222
+ Literal: 11,
1223
+ ArrayExpression: 12,
1224
+ Property: 13,
1225
+ ObjectExpression: 14,
1226
+ ThisExpression: 15,
1227
+ LocalsExpression: 16,
1228
+ NGValueParameter: 17,
1229
+ };
1230
+
1231
+ const ADD_CLASS_SUFFIX = "-add";
1232
+ const REMOVE_CLASS_SUFFIX = "-remove";
1233
+ const EVENT_CLASS_PREFIX = "ng-";
1234
+ const ACTIVE_CLASS_SUFFIX = "-active";
1235
+ const PREPARE_CLASS_SUFFIX = "-prepare";
1236
+
1237
+ const NG_ANIMATE_CLASSNAME = "ng-animate";
1238
+ const NG_ANIMATE_CHILDREN_DATA = "$$ngAnimateChildren";
1239
+ let TRANSITION_PROP;
1240
+ let TRANSITIONEND_EVENT;
1241
+ let ANIMATION_PROP;
1242
+ let ANIMATIONEND_EVENT;
1243
+
1244
+ // If unprefixed events are not supported but webkit-prefixed are, use the latter.
1245
+ // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
1246
+ // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
1247
+ // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
1248
+ // Register both events in case `window.onanimationend` is not supported because of that,
1249
+ // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
1250
+ // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
1251
+ // therefore there is no reason to test anymore for other vendor prefixes:
1252
+ // http://caniuse.com/#search=transition
1253
+ if (
1254
+ window.ontransitionend === undefined &&
1255
+ window.onwebkittransitionend !== undefined
1256
+ ) {
1257
+ TRANSITION_PROP = "WebkitTransition";
1258
+ TRANSITIONEND_EVENT = "webkitTransitionEnd transitionend";
1259
+ } else {
1260
+ TRANSITION_PROP = "transition";
1261
+ TRANSITIONEND_EVENT = "transitionend";
1262
+ }
1263
+
1264
+ if (
1265
+ window.onanimationend === undefined &&
1266
+ window.onwebkitanimationend !== undefined
1267
+ ) {
1268
+ ANIMATION_PROP = "WebkitAnimation";
1269
+ ANIMATIONEND_EVENT = "webkitAnimationEnd animationend";
1270
+ } else {
1271
+ ANIMATION_PROP = "animation";
1272
+ ANIMATIONEND_EVENT = "animationend";
1273
+ }
1274
+
1275
+ const DURATION_KEY = "Duration";
1276
+ const PROPERTY_KEY = ASTType.Property;
1277
+ const DELAY_KEY = "Delay";
1278
+ const TIMING_KEY = "TimingFunction";
1279
+ const ANIMATION_ITERATION_COUNT_KEY = "IterationCount";
1280
+ const ANIMATION_PLAYSTATE_KEY = "PlayState";
1281
+ const SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
1282
+
1283
+ const ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
1284
+ const ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
1285
+ const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
1286
+ const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
1287
+
1288
+ const ngMinErr$1 = minErr("ng");
1289
+ function assertArg(arg, name, reason) {
1290
+ if (!arg) {
1291
+ throw ngMinErr$1(
1292
+ "areq",
1293
+ "Argument '{0}' is {1}",
1294
+ name || "?",
1295
+ reason,
1296
+ );
1297
+ }
1298
+ return arg;
1299
+ }
1300
+
1301
+ function packageStyles(options) {
1302
+ const styles = {};
1303
+ if (options && (options.to || options.from)) {
1304
+ styles.to = options.to;
1305
+ styles.from = options.from;
1306
+ }
1307
+ return styles;
1308
+ }
1309
+
1310
+ function pendClasses(classes, fix, isPrefix) {
1311
+ let className = "";
1312
+
1313
+ classes = Array.isArray(classes)
1314
+ ? classes
1315
+ : classes && isString(classes) && classes.length
1316
+ ? classes.split(/\s+/)
1317
+ : [];
1318
+ classes.forEach((klass, i) => {
1319
+ if (klass && klass.length > 0) {
1320
+ className += i > 0 ? " " : "";
1321
+ className += isPrefix ? fix + klass : klass + fix;
1322
+ }
1323
+ });
1324
+ return className;
1325
+ }
1326
+
1327
+ function removeFromArray(arr, val) {
1328
+ const index = arr.indexOf(val);
1329
+ if (val >= 0) {
1330
+ arr.splice(index, 1);
1331
+ }
1332
+ }
1333
+
1334
+ /**
1335
+ *
1336
+ * @param {NodeList|Node} element
1337
+ * @returns {Node[]|Node|undefined}
1338
+ */
1339
+ function stripCommentsFromElement(element) {
1340
+ if (element instanceof NodeList) {
1341
+ return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
1342
+ } else if (element.nodeType === Node.ELEMENT_NODE) {
1343
+ return /** @type {Node} */ (element);
1344
+ } else {
1345
+ return undefined;
1346
+ }
1347
+ }
1348
+
1349
+ /**
1350
+ * @param {NodeList|Node} element
1351
+ * @returns {Node}
1352
+ */
1353
+ function extractElementNode(element) {
1354
+ if (!element || !Array.isArray(element)) return /** @type {Node} */ (element);
1355
+ for (let i = 0; i < /** @type {NodeList} */ (element).length; i++) {
1356
+ const elm = element[i];
1357
+ if (elm.nodeType === Node.ELEMENT_NODE) {
1358
+ return elm;
1359
+ }
1360
+ }
1361
+ }
1362
+
1363
+ function applyAnimationClassesFactory() {
1364
+ return function (element, options) {
1365
+ if (options.addClass) {
1366
+ element.classList.add(...options.addClass.trim().split(" "));
1367
+ options.addClass = null;
1368
+ }
1369
+ if (options.removeClass) {
1370
+ element.classList.remove(...options.removeClass.trim().split(" "));
1371
+ options.removeClass = null;
1372
+ }
1373
+ };
1374
+ }
1375
+
1376
+ function prepareAnimationOptions(options) {
1377
+ options = options || {};
1378
+ if (!options.$$prepared) {
1379
+ let domOperation = options.domOperation || (() => {});
1380
+ options.domOperation = function () {
1381
+ options.$$domOperationFired = true;
1382
+ domOperation();
1383
+ domOperation = () => {};
1384
+ };
1385
+ options.$$prepared = true;
1386
+ }
1387
+ return options;
1388
+ }
1389
+
1390
+ function applyAnimationStyles(element, options) {
1391
+ applyAnimationFromStyles(element, options);
1392
+ applyAnimationToStyles(element, options);
1393
+ }
1394
+
1395
+ /**
1396
+ * Applies initial animation styles to a DOM element.
1397
+ *
1398
+ * This function sets the element's inline styles using the properties
1399
+ * defined in `options.from`, then clears the property to prevent reuse.
1400
+ *
1401
+ * @param {HTMLElement} element - The target DOM element to apply styles to.
1402
+ * @param {{ from?: Partial<CSSStyleDeclaration> | null }} options - options containing a `from` object with CSS property–value pairs.
1403
+ */
1404
+ function applyAnimationFromStyles(element, options) {
1405
+ if (options.from) {
1406
+ Object.assign(element.style, options.from);
1407
+ options.from = null;
1408
+ }
1409
+ }
1410
+
1411
+ /**
1412
+ * Applies final animation styles to a DOM element.
1413
+ *
1414
+ * This function sets the element's inline styles using the properties
1415
+ * defined in `options.to`, then clears the property to prevent reuse.
1416
+ *
1417
+ * @param {HTMLElement} element - The target DOM element to apply styles to.
1418
+ * @param {{ to?: Partial<CSSStyleDeclaration> | null }} options - options containing a `from` object with CSS property–value pairs.
1419
+ */
1420
+ function applyAnimationToStyles(element, options) {
1421
+ if (options.to) {
1422
+ Object.assign(element.style, options.to);
1423
+ options.to = null;
1424
+ }
1425
+ }
1426
+
1427
+ function mergeAnimationDetails(element, oldAnimation, newAnimation) {
1428
+ const target = oldAnimation.options || {};
1429
+ const newOptions = newAnimation.options || {};
1430
+
1431
+ const toAdd = `${target.addClass || ""} ${newOptions.addClass || ""}`;
1432
+ const toRemove = `${target.removeClass || ""} ${newOptions.removeClass || ""}`;
1433
+ const classes = resolveElementClasses(
1434
+ element.getAttribute("class"),
1435
+ toAdd,
1436
+ toRemove,
1437
+ );
1438
+
1439
+ if (newOptions.preparationClasses) {
1440
+ target.preparationClasses = concatWithSpace(
1441
+ newOptions.preparationClasses,
1442
+ target.preparationClasses,
1443
+ );
1444
+ delete newOptions.preparationClasses;
1445
+ }
1446
+
1447
+ extend(target, newOptions);
1448
+
1449
+ if (classes.addClass) {
1450
+ target.addClass = classes.addClass;
1451
+ } else {
1452
+ target.addClass = null;
1453
+ }
1454
+
1455
+ if (classes.removeClass) {
1456
+ target.removeClass = classes.removeClass;
1457
+ } else {
1458
+ target.removeClass = null;
1459
+ }
1460
+
1461
+ oldAnimation.addClass = target.addClass;
1462
+ oldAnimation.removeClass = target.removeClass;
1463
+
1464
+ return target;
1465
+ }
1466
+
1467
+ function resolveElementClasses(existing, toAdd, toRemove) {
1468
+ const ADD_CLASS = 1;
1469
+ const REMOVE_CLASS = -1;
1470
+
1471
+ const flags = {};
1472
+ existing = splitClassesToLookup(existing);
1473
+
1474
+ toAdd = splitClassesToLookup(toAdd);
1475
+ Object.keys(toAdd).forEach((key) => {
1476
+ flags[key] = ADD_CLASS;
1477
+ });
1478
+
1479
+ toRemove = splitClassesToLookup(toRemove);
1480
+ Object.keys(toRemove).forEach((key) => {
1481
+ flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
1482
+ });
1483
+
1484
+ const classes = {
1485
+ addClass: "",
1486
+ removeClass: "",
1487
+ };
1488
+
1489
+ Object.entries(flags).forEach(([klass, val]) => {
1490
+ let prop, allow;
1491
+ if (val === ADD_CLASS) {
1492
+ prop = "addClass";
1493
+ allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
1494
+ } else if (val === REMOVE_CLASS) {
1495
+ prop = "removeClass";
1496
+ allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
1497
+ }
1498
+ if (allow) {
1499
+ if (classes[prop].length) {
1500
+ classes[prop] += " ";
1501
+ }
1502
+ classes[prop] += klass;
1503
+ }
1504
+ });
1505
+
1506
+ function splitClassesToLookup(classes) {
1507
+ if (isString(classes)) {
1508
+ classes = classes.trim().split(" ");
1509
+ }
1510
+
1511
+ const obj = {};
1512
+ if (classes) {
1513
+ classes.forEach((klass) => {
1514
+ // sometimes the split leaves empty string values
1515
+ // incase extra spaces were applied to the options
1516
+ if (klass.length) {
1517
+ obj[klass] = true;
1518
+ }
1519
+ });
1520
+ }
1521
+ return obj;
1522
+ }
1523
+
1524
+ return classes;
1525
+ }
1526
+
1527
+ function applyGeneratedPreparationClasses(element, event, options) {
1528
+ let classes = "";
1529
+ if (event) {
1530
+ classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
1531
+ }
1532
+ if (options.addClass) {
1533
+ classes = concatWithSpace(
1534
+ classes,
1535
+ pendClasses(options.addClass, ADD_CLASS_SUFFIX),
1536
+ );
1537
+ }
1538
+ if (options.removeClass) {
1539
+ classes = concatWithSpace(
1540
+ classes,
1541
+ pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX),
1542
+ );
1543
+ }
1544
+ if (classes.length) {
1545
+ options.preparationClasses = classes;
1546
+ element.className += ` ${classes}`;
1547
+ }
1548
+ }
1549
+
1550
+ function clearGeneratedClasses(element, options) {
1551
+ if (options.preparationClasses) {
1552
+ options.preparationClasses
1553
+ .split(" ")
1554
+ .forEach((cls) => element.classList.remove(cls));
1555
+ options.preparationClasses = null;
1556
+ }
1557
+ if (options.activeClasses) {
1558
+ options.activeClasses
1559
+ .split(" ")
1560
+ .forEach((cls) => element.classList.remove(cls));
1561
+ options.activeClasses = null;
1562
+ }
1563
+ }
1564
+
1565
+ function blockKeyframeAnimations(node, applyBlock) {
1566
+ const value = applyBlock ? "paused" : "";
1567
+ const key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
1568
+ applyInlineStyle(node, [key, value]);
1569
+ return [key, value];
1570
+ }
1571
+
1572
+ function applyInlineStyle(node, styleTuple) {
1573
+ const prop = styleTuple[0];
1574
+ node.style[prop] = styleTuple[1];
1575
+ }
1576
+
1577
+ function concatWithSpace(a, b) {
1578
+ if (!a) return b;
1579
+ if (!b) return a;
1580
+ return `${a} ${b}`;
1581
+ }
1582
+
1207
1583
  /** @type {number} */
1208
1584
  let jqId = 1;
1209
1585
 
@@ -1725,12 +2101,8 @@
1725
2101
  // from the dom sometime before this code runs then let's
1726
2102
  // just stick to using the parent element as the anchor
1727
2103
  if (afterElement) {
1728
- const afterNode = extractElementNode$1(afterElement);
1729
- if (
1730
- afterNode &&
1731
- !afterNode.parentNode &&
1732
- !afterNode.previousElementSibling
1733
- ) {
2104
+ const afterNode = extractElementNode(afterElement);
2105
+ if (afterNode && !afterNode.parentNode && !afterNode.previousSibling) {
1734
2106
  afterElement = null;
1735
2107
  }
1736
2108
  }
@@ -1741,16 +2113,6 @@
1741
2113
  }
1742
2114
  }
1743
2115
 
1744
- function extractElementNode$1(element) {
1745
- const { length } = element;
1746
- for (let i = 0; i < length; i++) {
1747
- const elm = element[i];
1748
- if (elm.nodeType === Node.ELEMENT_NODE) {
1749
- return elm;
1750
- }
1751
- }
1752
- }
1753
-
1754
2116
  /**
1755
2117
  * Returns the base href of the document.
1756
2118
  *
@@ -1869,7 +2231,7 @@
1869
2231
  /**
1870
2232
  * @param {string} name - Name of the module
1871
2233
  * @param {Array<string>} requires - List of modules which the injector will load before the current module
1872
- * @param {import("../../interface.js").Injectable<any>} [configFn]
2234
+ * @param {import("../../interface.ts").Injectable<any>} [configFn]
1873
2235
  */
1874
2236
  constructor(name, requires, configFn) {
1875
2237
  assert(isString(name), "name required");
@@ -1895,7 +2257,7 @@
1895
2257
  /** @type {!Array<Array<*>>} */
1896
2258
  this.configBlocks = [];
1897
2259
 
1898
- /** @type {!Array.<import("../../interface.js").Injectable<any>>} */
2260
+ /** @type {!Array.<import("../../interface.ts").Injectable<any>>} */
1899
2261
  this.runBlocks = [];
1900
2262
 
1901
2263
  if (configFn) {
@@ -1999,7 +2361,7 @@
1999
2361
 
2000
2362
  /**
2001
2363
  * @param {string} name
2002
- * @param {import("../../interface.js").Injectable<any>} decorFn
2364
+ * @param {import("../../interface.ts").Injectable<any>} decorFn
2003
2365
  * @returns {NgModule}
2004
2366
  */
2005
2367
  decorator(name, decorFn) {
@@ -2012,7 +2374,7 @@
2012
2374
 
2013
2375
  /**
2014
2376
  * @param {string} name
2015
- * @param {import("../../interface.js").Injectable<any>} directiveFactory
2377
+ * @param {import("../../interface.ts").Injectable<any>} directiveFactory
2016
2378
  * @returns {NgModule}
2017
2379
  */
2018
2380
  directive(name, directiveFactory) {
@@ -2029,7 +2391,7 @@
2029
2391
 
2030
2392
  /**
2031
2393
  * @param {string} name
2032
- * @param {import("../../interface.js").Injectable<any>} animationFactory
2394
+ * @param {import("../../interface.ts").Injectable<any>} animationFactory
2033
2395
  * @returns {NgModule}
2034
2396
  */
2035
2397
  animation(name, animationFactory) {
@@ -2046,7 +2408,7 @@
2046
2408
 
2047
2409
  /**
2048
2410
  * @param {string} name
2049
- * @param {import("../../interface.js").Injectable<any>} filterFn
2411
+ * @param {import("../../interface.ts").Injectable<any>} filterFn
2050
2412
  * @return {NgModule}
2051
2413
  */
2052
2414
  filter(name, filterFn) {
@@ -2059,7 +2421,7 @@
2059
2421
 
2060
2422
  /**
2061
2423
  * @param {string} name
2062
- * @param {import("../../interface.js").Injectable<any>} ctlFn
2424
+ * @param {import("../../interface.ts").Injectable<any>} ctlFn
2063
2425
  * @returns {NgModule}
2064
2426
  */
2065
2427
  controller(name, ctlFn) {
@@ -2444,7 +2806,7 @@
2444
2806
  * Registers a factory.
2445
2807
  * @param {string} name
2446
2808
  * @param {(string|(function(*): *))[]} factoryFn
2447
- * @returns {import('../../interface.js').ServiceProvider}
2809
+ * @returns {import('../../interface.ts').ServiceProvider}
2448
2810
  */
2449
2811
  function factory(name, factoryFn) {
2450
2812
  return provider(name, {
@@ -2466,7 +2828,7 @@
2466
2828
  * Registers a service constructor.
2467
2829
  * @param {string} name
2468
2830
  * @param {Function} constructor
2469
- * @returns {import('../../interface.js').ServiceProvider}
2831
+ * @returns {import('../../interface.ts').ServiceProvider}
2470
2832
  */
2471
2833
  function service(name, constructor) {
2472
2834
  return factory(name, [
@@ -2935,7 +3297,7 @@
2935
3297
 
2936
3298
  /**
2937
3299
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
2938
- * @returns {import("./interface.js").ControllerService} A service function that creates controllers.
3300
+ * @returns {import("./interface.ts").ControllerService} A service function that creates controllers.
2939
3301
  */
2940
3302
  ($injector) => {
2941
3303
  return (expression, locals, later, ident) => {
@@ -3053,18 +3415,19 @@
3053
3415
  );
3054
3416
  }
3055
3417
  locals.$scope[identifier] = instance;
3418
+ locals.$scope["$controllerIdentifier"] = identifier;
3056
3419
  }
3057
3420
  }
3058
3421
 
3059
3422
  const originUrl = urlResolve(window.location.href);
3060
3423
 
3061
3424
  /**
3062
- * @param {import("./interface.js").ResolvableUrl} url
3063
- * @return {import("./interface.js").ParsedUrl}
3425
+ * @param {import("./interface.ts").ResolvableUrl} url
3426
+ * @return {import("./interface.ts").ParsedUrl}
3064
3427
  */
3065
3428
  function urlResolve(url) {
3066
3429
  if (!isString(url))
3067
- return /** @type {import("./interface.js").ParsedUrl} */ (url);
3430
+ return /** @type {import("./interface.ts").ParsedUrl} */ (url);
3068
3431
 
3069
3432
  const urlParsingNode = new URL(
3070
3433
  /** @type {string} */ (url),
@@ -3096,7 +3459,7 @@
3096
3459
  * Parse a request URL and determine whether this is a same-origin request as the application
3097
3460
  * document.
3098
3461
  *
3099
- * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3462
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3100
3463
  * or a parsed URL object.
3101
3464
  * @returns {boolean} Whether the request is for the same origin as the application document.
3102
3465
  */
@@ -3110,7 +3473,7 @@
3110
3473
  * Note: The base URL is usually the same as the document location (`location.href`) but can
3111
3474
  * be overriden by using the `<base>` tag.
3112
3475
  *
3113
- * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3476
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3114
3477
  * or a parsed URL object.
3115
3478
  * @returns {boolean} Whether the URL is same-origin as the document base URL.
3116
3479
  */
@@ -3124,7 +3487,7 @@
3124
3487
  *
3125
3488
  * @param {string[]} trustedOriginUrls - A list of URLs (strings), whose origins are trusted.
3126
3489
  *
3127
- * @returns {(url: import("./interface.js").ResolvableUrl) => boolean } - A function that receives a URL (string or parsed URL object) and returns
3490
+ * @returns {(url: import("./interface.ts").ResolvableUrl) => boolean } - A function that receives a URL (string or parsed URL object) and returns
3128
3491
  * whether it is of an allowed origin.
3129
3492
  */
3130
3493
  function urlIsAllowedOriginFactory(trustedOriginUrls) {
@@ -3137,7 +3500,7 @@
3137
3500
  * based on a list of trusted-origin URLs. The current location's origin is implicitly
3138
3501
  * trusted.
3139
3502
  *
3140
- * @param {import("./interface.js").ResolvableUrl} requestUrl - The URL to be checked (provided as a string that will be
3503
+ * @param {import("./interface.ts").ResolvableUrl} requestUrl - The URL to be checked (provided as a string that will be
3141
3504
  * resolved or a parsed URL object).
3142
3505
  *
3143
3506
  * @returns {boolean} - Whether the specified URL is of an allowed origin.
@@ -3153,9 +3516,9 @@
3153
3516
  /**
3154
3517
  * Determine if two URLs share the same origin.
3155
3518
  *
3156
- * @param {import("./interface.js").ResolvableUrl} url1 - First URL to compare as a string or a normalized URL in the form of
3519
+ * @param {import("./interface.ts").ResolvableUrl} url1 - First URL to compare as a string or a normalized URL in the form of
3157
3520
  * a dictionary object returned by `urlResolve()`.
3158
- * @param {import("./interface.js").ResolvableUrl} url2 - Second URL to compare as a string or a normalized URL in the form
3521
+ * @param {import("./interface.ts").ResolvableUrl} url2 - Second URL to compare as a string or a normalized URL in the form
3159
3522
  * of a dictionary object returned by `urlResolve()`.
3160
3523
  *
3161
3524
  * @returns {boolean} - True if both URLs have the same origin, and false otherwise.
@@ -3789,7 +4152,7 @@
3789
4152
  *
3790
4153
  * @param {string} type The SCE context in which this result will be used.
3791
4154
  * @param {string} expr String expression to compile.
3792
- * @return {import("../../core/parse/interface.js").CompiledExpression} A function which represents the compiled expression:
4155
+ * @return {import("../../core/parse/interface.ts").CompiledExpression} A function which represents the compiled expression:
3793
4156
  *
3794
4157
  * * `context` – `{object}` – an object against which any expressions embedded in the
3795
4158
  * strings are evaluated against (typically a scope object).
@@ -4021,26 +4384,23 @@
4021
4384
  */
4022
4385
  const ngEventDirectives = {};
4023
4386
 
4024
- "click copy cut dblclick focus blur keydown keyup load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove offline online"
4387
+ "click copy cut dblclick focus blur keydown keyup load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove"
4025
4388
  .split(" ")
4026
4389
  .forEach((eventName) => {
4027
4390
  const directiveName = directiveNormalize(`ng-${eventName}`);
4028
4391
  ngEventDirectives[directiveName] = [
4029
4392
  $injectTokens.$parse,
4030
4393
  $injectTokens.$exceptionHandler,
4031
- $injectTokens.$window,
4032
4394
 
4033
4395
  /**
4034
- * @param {import("../../core/parse/interface.ts").ParseService} $parse
4396
+ * @param {ng.ParseService} $parse
4035
4397
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4036
- * @param {ng.WindowService} $window
4037
4398
  * @returns
4038
4399
  */
4039
- ($parse, $exceptionHandler, $window) => {
4400
+ ($parse, $exceptionHandler) => {
4040
4401
  return createEventDirective(
4041
4402
  $parse,
4042
4403
  $exceptionHandler,
4043
- $window,
4044
4404
  directiveName,
4045
4405
  eventName,
4046
4406
  );
@@ -4052,7 +4412,6 @@
4052
4412
  *
4053
4413
  * @param {ng.ParseService} $parse
4054
4414
  * @param {ng.ExceptionHandlerService} $exceptionHandler
4055
- * @param {ng.WindowService} $window
4056
4415
  * @param {string} directiveName
4057
4416
  * @param {string} eventName
4058
4417
  * @returns {ng.Directive}
@@ -4060,7 +4419,6 @@
4060
4419
  function createEventDirective(
4061
4420
  $parse,
4062
4421
  $exceptionHandler,
4063
- $window,
4064
4422
  directiveName,
4065
4423
  eventName,
4066
4424
  ) {
@@ -4129,16 +4487,13 @@
4129
4487
  const SIMPLE_ATTR_NAME = /^\w/;
4130
4488
  const specialAttrHolder = document.createElement("div");
4131
4489
 
4132
- /**
4133
- * @implements {Record<string, any>}
4134
- */
4135
4490
  class Attributes {
4136
4491
  static $nonscope = true;
4137
4492
 
4138
4493
  /**
4139
- * @param {import('../scope/scope.js').Scope} $rootScope
4494
+ * @param {ng.Scope} $rootScope
4140
4495
  * @param {*} $animate
4141
- * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
4496
+ * @param {ng.ExceptionHandlerService} $exceptionHandler
4142
4497
  * @param {*} $sce
4143
4498
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
4144
4499
  * @param {Object} [attributesToCopy]
@@ -4451,19 +4806,18 @@
4451
4806
  /**
4452
4807
  * @param {string} source - the name of the attribute to be observed
4453
4808
  * @param {string} prop - the scope property to be updated with attribute value
4454
- * @returns {import("../../interface.ts").Directive}
4809
+ * @returns {ng.Directive}
4455
4810
  */
4456
4811
  function ngObserveDirective(source, prop) {
4457
4812
  return {
4458
4813
  restrict: "A",
4459
4814
  compile: () => (scope, element) => {
4460
- const targetElement = element;
4461
4815
  if (prop === "") {
4462
4816
  prop = source;
4463
4817
  }
4464
4818
  const normalized = kebabToCamel(prop);
4465
4819
  if (!scope[normalized]) {
4466
- scope[normalized] = targetElement.getAttribute(source);
4820
+ scope[normalized] = element.getAttribute(source);
4467
4821
  }
4468
4822
 
4469
4823
  const observer = new MutationObserver((mutations) => {
@@ -4476,7 +4830,7 @@
4476
4830
  }
4477
4831
  });
4478
4832
 
4479
- observer.observe(targetElement, {
4833
+ observer.observe(element, {
4480
4834
  attributes: true,
4481
4835
  attributeFilter: [source],
4482
4836
  });
@@ -4502,7 +4856,7 @@
4502
4856
  /* @ignore */ static $inject = [$injectTokens.$provide, $injectTokens.$$sanitizeUriProvider];
4503
4857
 
4504
4858
  /**
4505
- * @param {import('../../interface.js').Provider} $provide
4859
+ * @param {import('../../interface.ts').Provider} $provide
4506
4860
  * @param {import('../sanitize/sanitize-uri.js').SanitizeUriProvider} $$sanitizeUriProvider
4507
4861
  */
4508
4862
  constructor($provide, $$sanitizeUriProvider) {
@@ -4692,7 +5046,7 @@
4692
5046
  /**
4693
5047
  * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
4694
5048
  * or an object map of components where the keys are the names and the values are the component definition objects.
4695
- * @param {import("../../interface.js").Component} options Component definition object (a simplified
5049
+ * @param {import("../../interface.ts").Component} options Component definition object (a simplified
4696
5050
  * {directive definition object}),
4697
5051
  * with the following properties (all optional):
4698
5052
  *
@@ -5478,12 +5832,12 @@
5478
5832
  createEventDirective(
5479
5833
  $parse,
5480
5834
  $exceptionHandler,
5481
- window,
5482
5835
  nName,
5483
5836
  name,
5484
5837
  ),
5485
5838
  );
5486
5839
  } else {
5840
+ // isWindow
5487
5841
  directives.push(
5488
5842
  createWindowEventDirective(
5489
5843
  $parse,
@@ -7473,7 +7827,7 @@
7473
7827
  scope.$handler.watchers
7474
7828
  .get(attrs[attrName])
7475
7829
  ?.forEach((watchFn) => {
7476
- watchFn.listenerFn(val);
7830
+ watchFn.listenerFn(val, scope.$target);
7477
7831
  });
7478
7832
  }
7479
7833
  }
@@ -7886,8 +8240,14 @@
7886
8240
  * state (ng-dirty class). This method will also propagate to parent forms.
7887
8241
  */
7888
8242
  $setDirty() {
7889
- this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
7890
- this.$$animate.addClass(this.$$element, DIRTY_CLASS);
8243
+ if (hasAnimate(this.$$element)) {
8244
+ this.$$animate.removeClass(this.$$element, PRISTINE_CLASS);
8245
+ this.$$animate.addClass(this.$$element, DIRTY_CLASS);
8246
+ } else {
8247
+ // Fallback for non-animated environments
8248
+ this.$$element.classList.remove(PRISTINE_CLASS);
8249
+ this.$$element.classList.add(DIRTY_CLASS);
8250
+ }
7891
8251
  this.$dirty = true;
7892
8252
  this.$pristine = false;
7893
8253
  this.$$parentForm.$setDirty();
@@ -7906,11 +8266,18 @@
7906
8266
  * saving or resetting it.
7907
8267
  */
7908
8268
  $setPristine() {
7909
- this.$$animate.setClass(
7910
- this.$$element,
7911
- PRISTINE_CLASS,
7912
- `${DIRTY_CLASS} ${SUBMITTED_CLASS}`,
7913
- );
8269
+ if (hasAnimate(this.$$element)) {
8270
+ this.$$animate.setClass(
8271
+ this.$$element,
8272
+ PRISTINE_CLASS,
8273
+ `${DIRTY_CLASS} ${SUBMITTED_CLASS}`,
8274
+ );
8275
+ } else {
8276
+ // Fallback for non-animated environments
8277
+ this.$$element.classList.remove(DIRTY_CLASS, SUBMITTED_CLASS);
8278
+ this.$$element.classList.add(PRISTINE_CLASS);
8279
+ }
8280
+
7914
8281
  this.$dirty = false;
7915
8282
  this.$pristine = true;
7916
8283
  this.$submitted = false;
@@ -7948,7 +8315,11 @@
7948
8315
  }
7949
8316
 
7950
8317
  $$setSubmitted() {
7951
- this.$$animate.addClass(this.$$element, SUBMITTED_CLASS);
8318
+ if (hasAnimate(this.$$element)) {
8319
+ this.$$animate.addClass(this.$$element, SUBMITTED_CLASS);
8320
+ } else {
8321
+ this.$$element.classList.add(SUBMITTED_CLASS);
8322
+ }
7952
8323
  this.$submitted = true;
7953
8324
  this.$$controls.forEach((control) => {
7954
8325
  if (control.$$setSubmitted) {
@@ -11558,7 +11929,7 @@
11558
11929
  ngIfDirective.$inject = ["$animate"];
11559
11930
  /**
11560
11931
  * @param {*} $animate
11561
- * @returns {import("../../interface.ts").Directive}
11932
+ * @returns {ng.Directive}
11562
11933
  */
11563
11934
  function ngIfDirective($animate) {
11564
11935
  return {
@@ -11568,10 +11939,10 @@
11568
11939
  restrict: "A",
11569
11940
  /**
11570
11941
  *
11571
- * @param {import("../../core/scope/scope.js").Scope} $scope
11942
+ * @param {ng.Scope} $scope
11572
11943
  * @param {Element} $element
11573
- * @param {import("../../core/compile/attributes.js").Attributes} $attr
11574
- * @param {Object} _ctrl
11944
+ * @param {ng.Attributes} $attr
11945
+ * @param {*} _ctrl
11575
11946
  * @param {*} $transclude
11576
11947
  */
11577
11948
  link($scope, $element, $attr, _ctrl, $transclude) {
@@ -11583,7 +11954,7 @@
11583
11954
 
11584
11955
  let previousElements;
11585
11956
 
11586
- $scope.$watch($attr["ngIf"], (value) => {
11957
+ $scope.$watch($attr.ngIf, (value) => {
11587
11958
  if (value) {
11588
11959
  if (!childScope) {
11589
11960
  $transclude((clone, newScope) => {
@@ -11638,7 +12009,7 @@
11638
12009
  * @param {import("../../services/anchor-scroll/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
11639
12010
  * @param {*} $animate
11640
12011
  * @param {import('../../services/exception/interface.ts').ErrorHandler} $exceptionHandler
11641
- * @returns {import('../../interface.js').Directive}
12012
+ * @returns {import('../../interface.ts').Directive}
11642
12013
  */
11643
12014
  function ngIncludeDirective(
11644
12015
  $templateRequest,
@@ -13020,7 +13391,7 @@
13020
13391
  const REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
13021
13392
 
13022
13393
  /**
13023
- * @type {Record<string, import("../../interface.js").DirectiveFactory>}
13394
+ * @type {Record<string, import("../../interface.ts").DirectiveFactory>}
13024
13395
  */
13025
13396
  const ngAttributeAliasDirectives = {};
13026
13397
 
@@ -13593,364 +13964,6 @@
13593
13964
  ];
13594
13965
  }
13595
13966
 
13596
- /**
13597
- * @readonly
13598
- * @enum {number}
13599
- */
13600
- const ASTType = {
13601
- Program: 1,
13602
- ExpressionStatement: 2,
13603
- AssignmentExpression: 3,
13604
- ConditionalExpression: 4,
13605
- LogicalExpression: 5,
13606
- BinaryExpression: 6,
13607
- UnaryExpression: 7,
13608
- CallExpression: 8,
13609
- MemberExpression: 9,
13610
- Identifier: 10,
13611
- Literal: 11,
13612
- ArrayExpression: 12,
13613
- Property: 13,
13614
- ObjectExpression: 14,
13615
- ThisExpression: 15,
13616
- LocalsExpression: 16,
13617
- NGValueParameter: 17,
13618
- };
13619
-
13620
- const ADD_CLASS_SUFFIX = "-add";
13621
- const REMOVE_CLASS_SUFFIX = "-remove";
13622
- const EVENT_CLASS_PREFIX = "ng-";
13623
- const ACTIVE_CLASS_SUFFIX = "-active";
13624
- const PREPARE_CLASS_SUFFIX = "-prepare";
13625
-
13626
- const NG_ANIMATE_CLASSNAME = "ng-animate";
13627
- const NG_ANIMATE_CHILDREN_DATA = "$$ngAnimateChildren";
13628
- let TRANSITION_PROP;
13629
- let TRANSITIONEND_EVENT;
13630
- let ANIMATION_PROP;
13631
- let ANIMATIONEND_EVENT;
13632
-
13633
- // If unprefixed events are not supported but webkit-prefixed are, use the latter.
13634
- // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them.
13635
- // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend`
13636
- // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`.
13637
- // Register both events in case `window.onanimationend` is not supported because of that,
13638
- // do the same for `transitionend` as Safari is likely to exhibit similar behavior.
13639
- // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
13640
- // therefore there is no reason to test anymore for other vendor prefixes:
13641
- // http://caniuse.com/#search=transition
13642
- if (
13643
- window.ontransitionend === undefined &&
13644
- window.onwebkittransitionend !== undefined
13645
- ) {
13646
- TRANSITION_PROP = "WebkitTransition";
13647
- TRANSITIONEND_EVENT = "webkitTransitionEnd transitionend";
13648
- } else {
13649
- TRANSITION_PROP = "transition";
13650
- TRANSITIONEND_EVENT = "transitionend";
13651
- }
13652
-
13653
- if (
13654
- window.onanimationend === undefined &&
13655
- window.onwebkitanimationend !== undefined
13656
- ) {
13657
- ANIMATION_PROP = "WebkitAnimation";
13658
- ANIMATIONEND_EVENT = "webkitAnimationEnd animationend";
13659
- } else {
13660
- ANIMATION_PROP = "animation";
13661
- ANIMATIONEND_EVENT = "animationend";
13662
- }
13663
-
13664
- const DURATION_KEY = "Duration";
13665
- const PROPERTY_KEY = ASTType.Property;
13666
- const DELAY_KEY = "Delay";
13667
- const TIMING_KEY = "TimingFunction";
13668
- const ANIMATION_ITERATION_COUNT_KEY = "IterationCount";
13669
- const ANIMATION_PLAYSTATE_KEY = "PlayState";
13670
- const SAFE_FAST_FORWARD_DURATION_VALUE = 9999;
13671
-
13672
- const ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY;
13673
- const ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY;
13674
- const TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY;
13675
- const TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY;
13676
-
13677
- const ngMinErr$1 = minErr("ng");
13678
- function assertArg(arg, name, reason) {
13679
- if (!arg) {
13680
- throw ngMinErr$1(
13681
- "areq",
13682
- "Argument '{0}' is {1}",
13683
- name || "?",
13684
- reason,
13685
- );
13686
- }
13687
- return arg;
13688
- }
13689
-
13690
- function packageStyles(options) {
13691
- const styles = {};
13692
- if (options && (options.to || options.from)) {
13693
- styles.to = options.to;
13694
- styles.from = options.from;
13695
- }
13696
- return styles;
13697
- }
13698
-
13699
- function pendClasses(classes, fix, isPrefix) {
13700
- let className = "";
13701
-
13702
- classes = Array.isArray(classes)
13703
- ? classes
13704
- : classes && isString(classes) && classes.length
13705
- ? classes.split(/\s+/)
13706
- : [];
13707
- classes.forEach((klass, i) => {
13708
- if (klass && klass.length > 0) {
13709
- className += i > 0 ? " " : "";
13710
- className += isPrefix ? fix + klass : klass + fix;
13711
- }
13712
- });
13713
- return className;
13714
- }
13715
-
13716
- function removeFromArray(arr, val) {
13717
- const index = arr.indexOf(val);
13718
- if (val >= 0) {
13719
- arr.splice(index, 1);
13720
- }
13721
- }
13722
-
13723
- /**
13724
- *
13725
- * @param {NodeList|Node} element
13726
- * @returns {Node[]|Node|undefined}
13727
- */
13728
- function stripCommentsFromElement(element) {
13729
- if (element instanceof NodeList) {
13730
- return Array.from(element).filter((x) => x.nodeType == Node.ELEMENT_NODE);
13731
- } else if (element.nodeType === Node.ELEMENT_NODE) {
13732
- return /** @type {Node} */ (element);
13733
- } else {
13734
- return undefined;
13735
- }
13736
- }
13737
-
13738
- /**
13739
- * @param {NodeList|Node} element
13740
- * @returns {Node}
13741
- */
13742
- function extractElementNode(element) {
13743
- if (!element) return /** @type {Node} */ (element);
13744
- for (let i = 0; i < /** @type {NodeList} */ (element).length; i++) {
13745
- const elm = element[i];
13746
- if (elm.nodeType === Node.ELEMENT_NODE) {
13747
- return elm;
13748
- }
13749
- }
13750
- }
13751
-
13752
- function applyAnimationClassesFactory() {
13753
- return function (element, options) {
13754
- if (options.addClass) {
13755
- element.classList.add(...options.addClass.trim().split(" "));
13756
- options.addClass = null;
13757
- }
13758
- if (options.removeClass) {
13759
- element.classList.remove(...options.removeClass.trim().split(" "));
13760
- options.removeClass = null;
13761
- }
13762
- };
13763
- }
13764
-
13765
- function prepareAnimationOptions(options) {
13766
- options = options || {};
13767
- if (!options.$$prepared) {
13768
- let domOperation = options.domOperation || (() => {});
13769
- options.domOperation = function () {
13770
- options.$$domOperationFired = true;
13771
- domOperation();
13772
- domOperation = () => {};
13773
- };
13774
- options.$$prepared = true;
13775
- }
13776
- return options;
13777
- }
13778
-
13779
- function applyAnimationStyles(element, options) {
13780
- applyAnimationFromStyles(element, options);
13781
- applyAnimationToStyles(element, options);
13782
- }
13783
-
13784
- function applyAnimationFromStyles(element, options) {
13785
- if (options.from) {
13786
- //element.css(options.from);
13787
- options.from = null;
13788
- }
13789
- }
13790
-
13791
- function applyAnimationToStyles(element, options) {
13792
- if (options.to) {
13793
- //element.css(options.to);
13794
- options.to = null;
13795
- }
13796
- }
13797
-
13798
- function mergeAnimationDetails(element, oldAnimation, newAnimation) {
13799
- const target = oldAnimation.options || {};
13800
- const newOptions = newAnimation.options || {};
13801
-
13802
- const toAdd = `${target.addClass || ""} ${newOptions.addClass || ""}`;
13803
- const toRemove = `${target.removeClass || ""} ${newOptions.removeClass || ""}`;
13804
- const classes = resolveElementClasses(
13805
- element.getAttribute("class"),
13806
- toAdd,
13807
- toRemove,
13808
- );
13809
-
13810
- if (newOptions.preparationClasses) {
13811
- target.preparationClasses = concatWithSpace(
13812
- newOptions.preparationClasses,
13813
- target.preparationClasses,
13814
- );
13815
- delete newOptions.preparationClasses;
13816
- }
13817
-
13818
- extend(target, newOptions);
13819
-
13820
- if (classes.addClass) {
13821
- target.addClass = classes.addClass;
13822
- } else {
13823
- target.addClass = null;
13824
- }
13825
-
13826
- if (classes.removeClass) {
13827
- target.removeClass = classes.removeClass;
13828
- } else {
13829
- target.removeClass = null;
13830
- }
13831
-
13832
- oldAnimation.addClass = target.addClass;
13833
- oldAnimation.removeClass = target.removeClass;
13834
-
13835
- return target;
13836
- }
13837
-
13838
- function resolveElementClasses(existing, toAdd, toRemove) {
13839
- const ADD_CLASS = 1;
13840
- const REMOVE_CLASS = -1;
13841
-
13842
- const flags = {};
13843
- existing = splitClassesToLookup(existing);
13844
-
13845
- toAdd = splitClassesToLookup(toAdd);
13846
- Object.keys(toAdd).forEach((key) => {
13847
- flags[key] = ADD_CLASS;
13848
- });
13849
-
13850
- toRemove = splitClassesToLookup(toRemove);
13851
- Object.keys(toRemove).forEach((key) => {
13852
- flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS;
13853
- });
13854
-
13855
- const classes = {
13856
- addClass: "",
13857
- removeClass: "",
13858
- };
13859
-
13860
- Object.entries(flags).forEach(([klass, val]) => {
13861
- let prop, allow;
13862
- if (val === ADD_CLASS) {
13863
- prop = "addClass";
13864
- allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX];
13865
- } else if (val === REMOVE_CLASS) {
13866
- prop = "removeClass";
13867
- allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX];
13868
- }
13869
- if (allow) {
13870
- if (classes[prop].length) {
13871
- classes[prop] += " ";
13872
- }
13873
- classes[prop] += klass;
13874
- }
13875
- });
13876
-
13877
- function splitClassesToLookup(classes) {
13878
- if (isString(classes)) {
13879
- classes = classes.trim().split(" ");
13880
- }
13881
-
13882
- const obj = {};
13883
- if (classes) {
13884
- classes.forEach((klass) => {
13885
- // sometimes the split leaves empty string values
13886
- // incase extra spaces were applied to the options
13887
- if (klass.length) {
13888
- obj[klass] = true;
13889
- }
13890
- });
13891
- }
13892
- return obj;
13893
- }
13894
-
13895
- return classes;
13896
- }
13897
-
13898
- function applyGeneratedPreparationClasses(element, event, options) {
13899
- let classes = "";
13900
- if (event) {
13901
- classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
13902
- }
13903
- if (options.addClass) {
13904
- classes = concatWithSpace(
13905
- classes,
13906
- pendClasses(options.addClass, ADD_CLASS_SUFFIX),
13907
- );
13908
- }
13909
- if (options.removeClass) {
13910
- classes = concatWithSpace(
13911
- classes,
13912
- pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX),
13913
- );
13914
- }
13915
- if (classes.length) {
13916
- options.preparationClasses = classes;
13917
- element.className += ` ${classes}`;
13918
- }
13919
- }
13920
-
13921
- function clearGeneratedClasses(element, options) {
13922
- if (options.preparationClasses) {
13923
- options.preparationClasses
13924
- .split(" ")
13925
- .forEach((cls) => element.classList.remove(cls));
13926
- options.preparationClasses = null;
13927
- }
13928
- if (options.activeClasses) {
13929
- options.activeClasses
13930
- .split(" ")
13931
- .forEach((cls) => element.classList.remove(cls));
13932
- options.activeClasses = null;
13933
- }
13934
- }
13935
-
13936
- function blockKeyframeAnimations(node, applyBlock) {
13937
- const value = applyBlock ? "paused" : "";
13938
- const key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
13939
- applyInlineStyle(node, [key, value]);
13940
- return [key, value];
13941
- }
13942
-
13943
- function applyInlineStyle(node, styleTuple) {
13944
- const prop = styleTuple[0];
13945
- node.style[prop] = styleTuple[1];
13946
- }
13947
-
13948
- function concatWithSpace(a, b) {
13949
- if (!a) return b;
13950
- if (!b) return a;
13951
- return `${a} ${b}`;
13952
- }
13953
-
13954
13967
  /** @typedef {"enter"|"leave"|"move"|"addClass"|"setClass"|"removeClass"} AnimationMethod */
13955
13968
 
13956
13969
  /**
@@ -14338,7 +14351,7 @@
14338
14351
  *
14339
14352
  * @param {Element} element - the element which will be inserted into the DOM
14340
14353
  * @param {Element} parent - the parent element which will append the element as a child (so long as the after element is not present)
14341
- * @param {Element} after - after the sibling element after which the element will be appended
14354
+ * @param {Element} [after] - after the sibling element after which the element will be appended
14342
14355
  * @param {AnimationOptions} [options] - an optional collection of options/styles that will be applied to the element.
14343
14356
  * @returns {import('./animate-runner.js').AnimateRunner} the animation runner
14344
14357
  */
@@ -17816,7 +17829,7 @@
17816
17829
  return concat.join("");
17817
17830
  };
17818
17831
 
17819
- return /**@type {import("./interface.js").InterpolationFunction} */ extend(
17832
+ return /**@type {import("./interface.ts").InterpolationFunction} */ extend(
17820
17833
  (context, cb) => {
17821
17834
  let i = 0;
17822
17835
  const ii = expressions.length;
@@ -19484,7 +19497,7 @@
19484
19497
  /**
19485
19498
  * Registers a callback to be called when the URL changes.
19486
19499
  *
19487
- * @param {import("./interface.js").UrlChangeListener} callback - The callback function to register.
19500
+ * @param {import("./interface.ts").UrlChangeListener} callback - The callback function to register.
19488
19501
  * @returns void
19489
19502
  */
19490
19503
  #onUrlChange(callback) {
@@ -20077,16 +20090,9 @@
20077
20090
  */
20078
20091
  let $parse;
20079
20092
 
20080
- /**@type {import('../../services/exception/exception-handler.js').ErrorHandler} */
20093
+ /**@type {ng.ExceptionHandlerService} */
20081
20094
  let $exceptionHandler;
20082
20095
 
20083
- /**
20084
- * @typedef {Object} AsyncQueueTask
20085
- * @property {Scope} handler
20086
- * @property {Function} fn
20087
- * @property {Object} locals
20088
- */
20089
-
20090
20096
  const $postUpdateQueue = [];
20091
20097
 
20092
20098
  class RootScopeProvider {
@@ -20095,11 +20101,11 @@
20095
20101
  }
20096
20102
 
20097
20103
  $get = [
20098
- "$exceptionHandler",
20099
- "$parse",
20104
+ $injectTokens.$exceptionHandler,
20105
+ $injectTokens.$parse,
20100
20106
  /**
20101
- * @param {import('../../services/exception/exception-handler.js').ErrorHandler} exceptionHandler
20102
- * @param {import('../parse/interface.ts').ParseService} parse
20107
+ * @param {ng.ExceptionHandlerService} exceptionHandler
20108
+ * @param {ng.ParseService} parse
20103
20109
  */
20104
20110
  (exceptionHandler, parse) => {
20105
20111
  $exceptionHandler = exceptionHandler;
@@ -20156,27 +20162,6 @@
20156
20162
  }
20157
20163
  }
20158
20164
 
20159
- /**
20160
- * Listener function definition.
20161
- * @typedef {Object} Listener
20162
- * @property {Object} originalTarget - The original target object.
20163
- * @property {ListenerFunction} listenerFn - The function invoked when changes are detected.
20164
- * @property {import("../parse/interface.ts").CompiledExpression} watchFn
20165
- * @property {number} id - Deregistration id
20166
- * @property {number} scopeId - The scope that created the Listener
20167
- * @property {string[]} property
20168
- * @property {string} [watchProp] - The original property to watch if different from observed key
20169
- * @property {Proxy} [foreignListener]
20170
- *
20171
- */
20172
-
20173
- /**
20174
- * Listener function type.
20175
- * @callback ListenerFunction
20176
- * @param {*} newValue - The new value of the changed property.
20177
- * @param {Object} originalTarget - The original target object.
20178
- */
20179
-
20180
20165
  /**
20181
20166
  * Decorator for excluding objects from scope observability
20182
20167
  */
@@ -20202,13 +20187,13 @@
20202
20187
  : context
20203
20188
  : undefined;
20204
20189
 
20205
- /** @type {Map<string, Array<Listener>>} Watch listeners */
20190
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners */
20206
20191
  this.watchers = context ? context.watchers : new Map();
20207
20192
 
20208
20193
  /** @type {Map<String, Function[]>} Event listeners */
20209
20194
  this.$$listeners = new Map();
20210
20195
 
20211
- /** @type {Map<string, Array<Listener>>} Watch listeners from other proxies */
20196
+ /** @type {Map<string, Array<import('./interface.ts').Listener>>} Watch listeners from other proxies */
20212
20197
  this.foreignListeners = context ? context.foreignListeners : new Map();
20213
20198
 
20214
20199
  /** @type {Set<ProxyConstructor>} */
@@ -20253,7 +20238,7 @@
20253
20238
  ? null
20254
20239
  : context;
20255
20240
 
20256
- /** @type {AsyncQueueTask[]} */
20241
+ /** @type {import('./interface.ts').AsyncQueueTask[]} */
20257
20242
  this.$$asyncQueue = [];
20258
20243
 
20259
20244
  this.filters = [];
@@ -20262,257 +20247,18 @@
20262
20247
  this.$$destroyed = false;
20263
20248
 
20264
20249
  this.scheduled = [];
20265
- }
20266
-
20267
- /**
20268
- * Intercepts and handles property assignments on the target object. If a new value is
20269
- * an object, it will be recursively proxied.
20270
- *
20271
- * @param {Object} target - The target object.
20272
- * @param {string} property - The name of the property being set.
20273
- * @param {*} value - The new value being assigned to the property.
20274
- * @param {Proxy} proxy - The proxy intercepting property access
20275
- * @returns {boolean} - Returns true to indicate success of the operation.
20276
- */
20277
- set(target, property, value, proxy) {
20278
- if (property === "undefined") {
20279
- throw new Error("Attempting to set undefined property");
20280
- }
20281
- if (
20282
- (target.constructor?.$nonscope &&
20283
- Array.isArray(target.constructor.$nonscope) &&
20284
- target.constructor.$nonscope.includes(property)) ||
20285
- (target.$nonscope &&
20286
- Array.isArray(target.$nonscope) &&
20287
- target.$nonscope.includes(property))
20288
- ) {
20289
- target[property] = value;
20290
- return true;
20291
- }
20292
-
20293
- this.$proxy = proxy;
20294
- this.$target = target;
20295
- const oldValue = target[property];
20296
-
20297
- // Handle NaNs
20298
- if (
20299
- oldValue !== undefined &&
20300
- Number.isNaN(oldValue) &&
20301
- Number.isNaN(value)
20302
- ) {
20303
- return true;
20304
- }
20305
- if (oldValue && oldValue[isProxySymbol]) {
20306
- if (Array.isArray(value)) {
20307
- if (oldValue !== value) {
20308
- const listeners = this.watchers.get(property);
20309
-
20310
- if (listeners) {
20311
- this.#scheduleListener(listeners);
20312
- }
20313
-
20314
- const foreignListeners = this.foreignListeners.get(property);
20315
-
20316
- if (foreignListeners) {
20317
- this.#scheduleListener(foreignListeners);
20318
- }
20319
- }
20320
-
20321
- if (this.objectListeners.get(target[property])) {
20322
- this.objectListeners.delete(target[property]);
20323
- }
20324
- target[property] = createScope(value, this);
20325
- this.objectListeners.set(target[property], [property]);
20326
- return true;
20327
- }
20328
-
20329
- if (isObject(value)) {
20330
- if (hasOwn(target, property)) {
20331
- Object.keys(oldValue)
20332
- .filter((x) => !value[x])
20333
- .forEach((k) => {
20334
- delete oldValue[k];
20335
- });
20336
- }
20337
-
20338
- if (oldValue !== value) {
20339
- const listeners = this.watchers.get(property);
20340
-
20341
- if (listeners) {
20342
- this.#scheduleListener(listeners);
20343
- }
20344
-
20345
- const foreignListeners = this.foreignListeners.get(property);
20346
-
20347
- if (foreignListeners) {
20348
- this.#scheduleListener(foreignListeners);
20349
- }
20350
-
20351
- this.#checkeListenersForAllKeys(value);
20352
- }
20353
- target[property] = createScope(value, this);
20354
- //setDeepValue(target[property], value);
20355
- return true;
20356
- }
20357
-
20358
- if (isUndefined(value)) {
20359
- let called = false;
20360
- Object.keys(oldValue.$target).forEach((k) => {
20361
- if (oldValue.$target[k]?.[isProxySymbol]) {
20362
- called = true;
20363
- }
20364
- delete oldValue[k];
20365
- });
20366
-
20367
- target[property] = undefined;
20368
- if (!called) {
20369
- let listeners = this.watchers.get(property);
20370
-
20371
- if (listeners) {
20372
- this.#scheduleListener(listeners);
20373
- }
20374
- }
20375
-
20376
- return true;
20377
- }
20378
-
20379
- if (isDefined(value)) {
20380
- target[property] = value;
20381
- let listeners = this.watchers.get(property);
20382
-
20383
- if (listeners) {
20384
- this.#scheduleListener(listeners);
20385
- }
20386
-
20387
- if (Array.isArray(target)) {
20388
- if (this.objectListeners.has(proxy) && property !== "length") {
20389
- let keys = this.objectListeners.get(proxy);
20390
- keys.forEach((key) => {
20391
- const listeners = this.watchers.get(key);
20392
- if (listeners) {
20393
- this.#scheduleListener(listeners);
20394
- }
20395
- });
20396
- }
20397
- }
20398
-
20399
- return true;
20400
- }
20401
- return true;
20402
- } else {
20403
- if (isUndefined(target[property]) && isProxy(value)) {
20404
- this.foreignProxies.add(value);
20405
- target[property] = value;
20406
- if (!this.watchers.has(property)) {
20407
- return true;
20408
- }
20409
- }
20410
- if (isUndefined(value)) {
20411
- target[property] = value;
20412
- } else {
20413
- target[property] = createScope(value, this);
20414
- }
20415
-
20416
- if (oldValue !== value) {
20417
- let expectedTarget = this.$target;
20418
- let listeners = [];
20419
- // Handle the case where we need to start observing object after a watcher has been set
20420
- if (isUndefined(oldValue) && isObject(target[property])) {
20421
- if (!this.objectListeners.has(target[property])) {
20422
- this.objectListeners.set(target[property], [property]);
20423
- }
20424
- for (const k of Object.keys(value)) {
20425
- this.watchers.get(k)?.forEach((l) => listeners.push(l));
20426
- // overwhrite the context so we pass the owneship test in filter
20427
- expectedTarget = value;
20428
- }
20429
- }
20430
-
20431
- if (Array.isArray(target)) {
20432
- this.watchers.get("length")?.forEach((l) => listeners.push(l));
20433
- }
20434
-
20435
- this.watchers.get(property)?.forEach((l) => listeners.push(l));
20436
- if (listeners.length > 0) {
20437
- // check if the listener actually appllies to this target
20438
- this.#scheduleListener(listeners, (x) => {
20439
- return x.filter((x) => {
20440
- if (!x.watchProp) return true;
20441
- // Compute the expected target based on `watchProp`
20442
- const wrapperExpr = x.watchProp.split(".").slice(0, -1).join(".");
20443
- const expectedHandler = $parse(wrapperExpr)(
20444
- x.originalTarget,
20445
- )?.$handler;
20446
- return expectedTarget === expectedHandler?.$target;
20447
- });
20448
- });
20449
- }
20450
-
20451
- let foreignListeners = this.foreignListeners.get(property);
20452
-
20453
- if (!foreignListeners && this.$parent?.foreignListeners) {
20454
- foreignListeners = this.$parent.foreignListeners.get(property);
20455
- }
20456
- if (foreignListeners) {
20457
- // filter for repeaters
20458
- if (this.$target.$$hashKey) {
20459
- foreignListeners = foreignListeners.filter((x) =>
20460
- x.originalTarget.$$hashKey
20461
- ? x.originalTarget.$$hashKey == this.$target.$$hashKey
20462
- : false,
20463
- );
20464
- }
20465
-
20466
- this.#scheduleListener(foreignListeners);
20467
- }
20468
- }
20469
-
20470
- if (this.objectListeners.has(proxy) && property !== "length") {
20471
- let keys = this.objectListeners.get(proxy);
20472
- keys.forEach((key) => {
20473
- const listeners = this.watchers.get(key);
20474
- if (listeners) {
20475
- if (this.scheduled !== listeners) {
20476
- this.#scheduleListener(listeners);
20477
- }
20478
- }
20479
- });
20480
- }
20481
-
20482
- return true;
20483
- }
20484
- }
20485
-
20486
- /**
20487
- * Intercepts property access on the target object. It checks for specific
20488
- * properties (`watch` and `sync`) and binds their methods. For other properties,
20489
- * it returns the value directly.
20490
- *
20491
- * @param {Object} target - The target object.
20492
- * @param {string|number|symbol} property - The name of the property being accessed.
20493
- * @param {Proxy} proxy - The proxy object being invoked
20494
- * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20495
- */
20496
- get(target, property, proxy) {
20497
- if (property === "$$watchersCount") return calculateWatcherCount(this);
20498
- if (property === isProxySymbol) return true;
20499
-
20500
- if (target[property] && isProxy(target[property])) {
20501
- this.$proxy = target[property];
20502
- } else {
20503
- this.$proxy = proxy;
20504
- }
20505
20250
 
20251
+ /** @private */
20506
20252
  this.propertyMap = {
20507
20253
  $watch: this.$watch.bind(this),
20508
20254
  $new: this.$new.bind(this),
20509
20255
  $newIsolate: this.$newIsolate.bind(this),
20510
20256
  $destroy: this.$destroy.bind(this),
20257
+ $flushQueue: this.$flushQueue.bind(this),
20511
20258
  $eval: this.$eval.bind(this),
20512
20259
  $apply: this.$apply.bind(this),
20513
20260
  $postUpdate: this.$postUpdate.bind(this),
20514
20261
  $isRoot: this.#isRoot.bind(this),
20515
- $target: target,
20516
20262
  $proxy: this.$proxy,
20517
20263
  $on: this.$on.bind(this),
20518
20264
  $emit: this.$emit.bind(this),
@@ -20526,6 +20272,249 @@
20526
20272
  $merge: this.$merge.bind(this),
20527
20273
  $getById: this.$getById.bind(this),
20528
20274
  };
20275
+ }
20276
+
20277
+ /**
20278
+ * Intercepts and handles property assignments on the target object. If a new value is
20279
+ * an object, it will be recursively proxied.
20280
+ *
20281
+ * @param {Object} target - The target object.
20282
+ * @param {string} property - The name of the property being set.
20283
+ * @param {*} value - The new value being assigned to the property.
20284
+ * @param {Proxy} proxy - The proxy intercepting property access
20285
+ * @returns {boolean} - Returns true to indicate success of the operation.
20286
+ */
20287
+ set(target, property, value, proxy) {
20288
+ if (property === "undefined") {
20289
+ throw new Error("Attempting to set undefined property");
20290
+ }
20291
+ if (
20292
+ (target.constructor?.$nonscope &&
20293
+ Array.isArray(target.constructor.$nonscope) &&
20294
+ target.constructor.$nonscope.includes(property)) ||
20295
+ (target.$nonscope &&
20296
+ Array.isArray(target.$nonscope) &&
20297
+ target.$nonscope.includes(property))
20298
+ ) {
20299
+ target[property] = value;
20300
+ return true;
20301
+ }
20302
+
20303
+ this.$proxy = proxy;
20304
+ this.$target = target;
20305
+ const oldValue = target[property];
20306
+
20307
+ // Handle NaNs
20308
+ if (
20309
+ oldValue !== undefined &&
20310
+ Number.isNaN(oldValue) &&
20311
+ Number.isNaN(value)
20312
+ ) {
20313
+ return true;
20314
+ }
20315
+ if (oldValue && oldValue[isProxySymbol]) {
20316
+ if (Array.isArray(value)) {
20317
+ if (oldValue !== value) {
20318
+ const listeners = this.watchers.get(property);
20319
+
20320
+ if (listeners) {
20321
+ this.#scheduleListener(listeners);
20322
+ }
20323
+
20324
+ const foreignListeners = this.foreignListeners.get(property);
20325
+
20326
+ if (foreignListeners) {
20327
+ this.#scheduleListener(foreignListeners);
20328
+ }
20329
+ }
20330
+
20331
+ if (this.objectListeners.get(target[property])) {
20332
+ this.objectListeners.delete(target[property]);
20333
+ }
20334
+ target[property] = createScope(value, this);
20335
+ this.objectListeners.set(target[property], [property]);
20336
+ return true;
20337
+ }
20338
+
20339
+ if (isObject(value)) {
20340
+ if (hasOwn(target, property)) {
20341
+ Object.keys(oldValue)
20342
+ .filter((x) => !value[x])
20343
+ .forEach((k) => {
20344
+ delete oldValue[k];
20345
+ });
20346
+ }
20347
+
20348
+ if (oldValue !== value) {
20349
+ const listeners = this.watchers.get(property);
20350
+
20351
+ if (listeners) {
20352
+ this.#scheduleListener(listeners);
20353
+ }
20354
+
20355
+ const foreignListeners = this.foreignListeners.get(property);
20356
+
20357
+ if (foreignListeners) {
20358
+ this.#scheduleListener(foreignListeners);
20359
+ }
20360
+
20361
+ this.#checkeListenersForAllKeys(value);
20362
+ }
20363
+ target[property] = createScope(value, this);
20364
+ //setDeepValue(target[property], value);
20365
+ return true;
20366
+ }
20367
+
20368
+ if (isUndefined(value)) {
20369
+ let called = false;
20370
+ Object.keys(oldValue.$target).forEach((k) => {
20371
+ if (oldValue.$target[k]?.[isProxySymbol]) {
20372
+ called = true;
20373
+ }
20374
+ delete oldValue[k];
20375
+ });
20376
+
20377
+ target[property] = undefined;
20378
+ if (!called) {
20379
+ let listeners = this.watchers.get(property);
20380
+
20381
+ if (listeners) {
20382
+ this.#scheduleListener(listeners);
20383
+ }
20384
+ }
20385
+
20386
+ return true;
20387
+ }
20388
+
20389
+ if (isDefined(value)) {
20390
+ target[property] = value;
20391
+ let listeners = this.watchers.get(property);
20392
+
20393
+ if (listeners) {
20394
+ this.#scheduleListener(listeners);
20395
+ }
20396
+
20397
+ if (Array.isArray(target)) {
20398
+ if (this.objectListeners.has(proxy) && property !== "length") {
20399
+ let keys = this.objectListeners.get(proxy);
20400
+ keys.forEach((key) => {
20401
+ const listeners = this.watchers.get(key);
20402
+ if (listeners) {
20403
+ this.#scheduleListener(listeners);
20404
+ }
20405
+ });
20406
+ }
20407
+ }
20408
+
20409
+ return true;
20410
+ }
20411
+ return true;
20412
+ } else {
20413
+ if (isUndefined(target[property]) && isProxy(value)) {
20414
+ this.foreignProxies.add(value);
20415
+ target[property] = value;
20416
+ if (!this.watchers.has(property)) {
20417
+ return true;
20418
+ }
20419
+ }
20420
+ if (isUndefined(value)) {
20421
+ target[property] = value;
20422
+ } else {
20423
+ target[property] = createScope(value, this);
20424
+ }
20425
+
20426
+ if (oldValue !== value) {
20427
+ let expectedTarget = this.$target;
20428
+ let listeners = [];
20429
+ // Handle the case where we need to start observing object after a watcher has been set
20430
+ if (isUndefined(oldValue) && isObject(target[property])) {
20431
+ if (!this.objectListeners.has(target[property])) {
20432
+ this.objectListeners.set(target[property], [property]);
20433
+ }
20434
+ for (const k of Object.keys(value)) {
20435
+ this.watchers.get(k)?.forEach((l) => listeners.push(l));
20436
+ // overwhrite the context so we pass the owneship test in filter
20437
+ expectedTarget = value;
20438
+ }
20439
+ }
20440
+
20441
+ if (Array.isArray(target)) {
20442
+ this.watchers.get("length")?.forEach((l) => listeners.push(l));
20443
+ }
20444
+
20445
+ this.watchers.get(property)?.forEach((l) => listeners.push(l));
20446
+ if (listeners.length > 0) {
20447
+ // check if the listener actually appllies to this target
20448
+ this.#scheduleListener(listeners, (x) => {
20449
+ return x.filter((x) => {
20450
+ if (!x.watchProp) return true;
20451
+ // Compute the expected target based on `watchProp`
20452
+ const wrapperExpr = x.watchProp.split(".").slice(0, -1).join(".");
20453
+ const expectedHandler = $parse(wrapperExpr)(
20454
+ x.originalTarget,
20455
+ )?.$handler;
20456
+ return expectedTarget === expectedHandler?.$target;
20457
+ });
20458
+ });
20459
+ }
20460
+
20461
+ let foreignListeners = this.foreignListeners.get(property);
20462
+
20463
+ if (!foreignListeners && this.$parent?.foreignListeners) {
20464
+ foreignListeners = this.$parent.foreignListeners.get(property);
20465
+ }
20466
+ if (foreignListeners) {
20467
+ // filter for repeaters
20468
+ if (this.$target.$$hashKey) {
20469
+ foreignListeners = foreignListeners.filter((x) =>
20470
+ x.originalTarget["$$hashKey"]
20471
+ ? x.originalTarget["$$hashKey"] === this.$target.$$hashKey
20472
+ : false,
20473
+ );
20474
+ }
20475
+
20476
+ this.#scheduleListener(foreignListeners);
20477
+ }
20478
+ }
20479
+
20480
+ if (this.objectListeners.has(proxy) && property !== "length") {
20481
+ let keys = this.objectListeners.get(proxy);
20482
+ keys.forEach((key) => {
20483
+ const listeners = this.watchers.get(key);
20484
+ if (listeners) {
20485
+ if (this.scheduled !== listeners) {
20486
+ this.#scheduleListener(listeners);
20487
+ }
20488
+ }
20489
+ });
20490
+ }
20491
+
20492
+ return true;
20493
+ }
20494
+ }
20495
+
20496
+ /**
20497
+ * Intercepts property access on the target object. It checks for specific
20498
+ * properties (`watch` and `sync`) and binds their methods. For other properties,
20499
+ * it returns the value directly.
20500
+ *
20501
+ * @param {Object} target - The target object.
20502
+ * @param {string|number|symbol} property - The name of the property being accessed.
20503
+ * @param {Proxy} proxy - The proxy object being invoked
20504
+ * @returns {*} - The value of the property or a method if accessing `watch` or `sync`.
20505
+ */
20506
+ get(target, property, proxy) {
20507
+ if (property === "$$watchersCount") return calculateWatcherCount(this);
20508
+ if (property === isProxySymbol) return true;
20509
+
20510
+ if (target[property] && isProxy(target[property])) {
20511
+ this.$proxy = target[property];
20512
+ } else {
20513
+ this.$proxy = proxy;
20514
+ }
20515
+
20516
+ this.propertyMap.$target = target;
20517
+ this.propertyMap.$proxy = proxy;
20529
20518
 
20530
20519
  if (
20531
20520
  Array.isArray(target) &&
@@ -20620,7 +20609,7 @@
20620
20609
  }
20621
20610
 
20622
20611
  /**
20623
- * @param {Listener[]} listeners
20612
+ * @param {import('./interface.ts').Listener[]} listeners
20624
20613
  * @param {Function} filter
20625
20614
  */
20626
20615
  #scheduleListener(listeners, filter = (val) => val) {
@@ -20644,7 +20633,7 @@
20644
20633
  * function is invoked when changes to that property are detected.
20645
20634
  *
20646
20635
  * @param {string} watchProp - An expression to be watched in the context of this model.
20647
- * @param {ListenerFunction} [listenerFn] - A function to execute when changes are detected on watched context.
20636
+ * @param {import('./interface.ts').ListenerFunction} [listenerFn] - A function to execute when changes are detected on watched context.
20648
20637
  * @param {boolean} [lazy] - A flag to indicate if the listener should be invoked immediately. Defaults to false.
20649
20638
  */
20650
20639
  $watch(watchProp, listenerFn, lazy = false) {
@@ -20666,7 +20655,7 @@
20666
20655
  return () => {};
20667
20656
  }
20668
20657
 
20669
- /** @type {Listener} */
20658
+ /** @type {import('./interface.ts').Listener} */
20670
20659
  const listener = {
20671
20660
  originalTarget: this.$target,
20672
20661
  listenerFn: listenerFn,
@@ -20778,7 +20767,7 @@
20778
20767
 
20779
20768
  let potentialProxy = $parse(
20780
20769
  watchProp.split(".").slice(0, -1).join("."),
20781
- )(listener.originalTarget);
20770
+ )(/** @type {Scope} */ (listener.originalTarget));
20782
20771
  if (potentialProxy && this.foreignProxies.has(potentialProxy)) {
20783
20772
  potentialProxy.$handler.#registerForeignKey(key, listener);
20784
20773
  potentialProxy.$handler.#scheduleListener([listener]);
@@ -20976,21 +20965,21 @@
20976
20965
  return true;
20977
20966
  }
20978
20967
 
20979
- // deregisterForeignKey(key, id) {
20980
- // const listenerList = this.foreignListeners.get(key);
20981
- // if (!listenerList) return false;
20968
+ deregisterForeignKey(key, id) {
20969
+ const listenerList = this.foreignListeners.get(key);
20970
+ if (!listenerList) return false;
20982
20971
 
20983
- // const index = listenerList.findIndex((x) => x.id === id);
20984
- // if (index === -1) return false;
20972
+ const index = listenerList.findIndex((x) => x.id === id);
20973
+ if (index === -1) return false;
20985
20974
 
20986
- // listenerList.splice(index, 1);
20987
- // if (listenerList.length) {
20988
- // this.foreignListeners.set(key, listenerList);
20989
- // } else {
20990
- // this.foreignListeners.delete(key);
20991
- // }
20992
- // return true;
20993
- // }
20975
+ listenerList.splice(index, 1);
20976
+ if (listenerList.length) {
20977
+ this.foreignListeners.set(key, listenerList);
20978
+ } else {
20979
+ this.foreignListeners.delete(key);
20980
+ }
20981
+ return true;
20982
+ }
20994
20983
 
20995
20984
  $eval(expr, locals) {
20996
20985
  const fn = $parse(expr);
@@ -21023,7 +21012,7 @@
21023
21012
  }
21024
21013
 
21025
21014
  /**
21026
- * @param {import('../../interface.js').Expression} expr
21015
+ * @param {import('../../interface.ts').Expression} expr
21027
21016
  * @returns {any}
21028
21017
  */
21029
21018
  $apply(expr) {
@@ -21204,12 +21193,12 @@
21204
21193
 
21205
21194
  /**
21206
21195
  * @internal
21207
- * @param {Listener} listener - The property path that was changed.
21196
+ * @param {import('./interface.ts').Listener} listener - The property path that was changed.
21208
21197
  */
21209
21198
  #notifyListener(listener, target) {
21210
21199
  const { originalTarget, listenerFn, watchFn } = listener;
21211
21200
  try {
21212
- let newVal = watchFn(originalTarget);
21201
+ let newVal = watchFn(/** @type {Scope} */ (originalTarget));
21213
21202
  if (isUndefined(newVal)) {
21214
21203
  newVal = watchFn(target);
21215
21204
  }
@@ -21239,6 +21228,13 @@
21239
21228
  }
21240
21229
  }
21241
21230
 
21231
+ /* @ignore */
21232
+ $flushQueue() {
21233
+ while ($postUpdateQueue.length) {
21234
+ $postUpdateQueue.shift()();
21235
+ }
21236
+ }
21237
+
21242
21238
  /**
21243
21239
  * Searches the scope instance
21244
21240
  *
@@ -21749,7 +21745,7 @@
21749
21745
 
21750
21746
  /**
21751
21747
  * @param {boolean} isDefault
21752
- * @returns {(any) => import("../../interface.js").Directive}
21748
+ * @returns {(any) => import("../../interface.ts").Directive}
21753
21749
  */
21754
21750
  function ngMessageDirectiveFactory(isDefault) {
21755
21751
  ngMessageDirective.$inject = ["$animate"];
@@ -21956,6 +21952,9 @@
21956
21952
  return $aria.$$watchExpr("ngShow", "aria-hidden", [], true);
21957
21953
  }
21958
21954
 
21955
+ /**
21956
+ * @return {ng.Directive}
21957
+ */
21959
21958
  function ngMessagesAriaDirective() {
21960
21959
  return {
21961
21960
  restrict: "A",
@@ -21971,18 +21970,21 @@
21971
21970
  }
21972
21971
 
21973
21972
  ngClickAriaDirective.$inject = [$injectTokens.$aria, $injectTokens.$parse];
21973
+
21974
+ /**
21975
+ * @param $aria
21976
+ * @param {ng.ParseService} $parse
21977
+ * @return {ng.Directive}
21978
+ */
21974
21979
  function ngClickAriaDirective($aria, $parse) {
21975
21980
  return {
21976
21981
  restrict: "A",
21977
21982
  compile(_elem, attr) {
21978
21983
  if (hasOwn(attr, ARIA_DISABLE_ATTR)) return;
21979
21984
 
21980
- const fn = $parse(attr.ngClick);
21985
+ const fn = $parse(attr["ngClick"]);
21981
21986
 
21982
- /**
21983
- * @param {Element} elem
21984
- */
21985
- return function (scope, elem, attr) {
21987
+ return (scope, elem, attr) => {
21986
21988
  if (!isNodeOneOf(elem, nativeAriaNodeNames)) {
21987
21989
  if ($aria.config("bindRoleForClick") && !elem.hasAttribute("role")) {
21988
21990
  elem.setAttribute("role", "button");
@@ -22019,10 +22021,6 @@
22019
22021
  // See https://github.com/angular/angular.js/issues/16664
22020
22022
  event.preventDefault();
22021
22023
  }
22022
- scope.$apply(callback);
22023
- }
22024
-
22025
- function callback() {
22026
22024
  fn(scope, { $event: event });
22027
22025
  }
22028
22026
  },
@@ -22344,6 +22342,7 @@
22344
22342
  }
22345
22343
 
22346
22344
  function AnimateCssProvider() {
22345
+ let activeClasses;
22347
22346
  this.$get = [
22348
22347
  "$$AnimateRunner",
22349
22348
  "$$animateCache",
@@ -22687,10 +22686,7 @@
22687
22686
  return closeAndReturnNoopAnimator();
22688
22687
  }
22689
22688
 
22690
- let activeClasses = pendClasses(
22691
- preparationClasses,
22692
- ACTIVE_CLASS_SUFFIX,
22693
- );
22689
+ activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
22694
22690
 
22695
22691
  if (options.delay != null) {
22696
22692
  if (typeof options.delay !== "boolean") {
@@ -22827,7 +22823,9 @@
22827
22823
 
22828
22824
  if (events && events.length) {
22829
22825
  // Remove the transitionend / animationend listener(s)
22830
- element.off(events.join(" "), onAnimationProgress);
22826
+ events.forEach((i) =>
22827
+ element.removeEventListener(i, onAnimationProgress),
22828
+ );
22831
22829
  }
22832
22830
 
22833
22831
  // Cancel the fallback closing timeout and remove the timer data
@@ -23262,11 +23260,6 @@
23262
23260
  ) {
23263
23261
  const activeAnimationsLookup = new Map();
23264
23262
  const disabledElementsLookup = new Map();
23265
- let animationsEnabled = null;
23266
-
23267
- function removeFromDisabledElementsLookup(evt) {
23268
- disabledElementsLookup.delete(evt.target);
23269
- }
23270
23263
 
23271
23264
  function postDigestTaskFactory() {
23272
23265
  let postDigestCalled = false;
@@ -23306,11 +23299,6 @@
23306
23299
  // any animations are triggered.
23307
23300
  $rootScope.$postUpdate(() => {
23308
23301
  $rootScope.$postUpdate(() => {
23309
- // we check for null directly in the event that the application already called
23310
- // .enabled() with whatever arguments that it provided it with
23311
- if (animationsEnabled === null) {
23312
- animationsEnabled = true;
23313
- }
23314
23302
  });
23315
23303
  });
23316
23304
  }
@@ -23449,47 +23437,6 @@
23449
23437
  options.domOperation = domOperation;
23450
23438
  return queueAnimation(element, event, options);
23451
23439
  },
23452
-
23453
- // this method has four signatures:
23454
- // () - global getter
23455
- // (bool) - global setter
23456
- // (element) - element getter
23457
- // (element, bool) - element setter<F37>
23458
- enabled(element, bool) {
23459
- const argCount = arguments.length;
23460
-
23461
- if (argCount === 0) {
23462
- // () - Global getter
23463
- bool = !!animationsEnabled;
23464
- } else {
23465
- const hasElement = isElement(element);
23466
-
23467
- if (!hasElement) {
23468
- // (bool) - Global setter
23469
- bool = animationsEnabled = !!element;
23470
- } else {
23471
- const node = element;
23472
-
23473
- if (argCount === 1) {
23474
- // (element) - Element getter
23475
- bool = !disabledElementsLookup.get(node);
23476
- } else {
23477
- // (element, bool) - Element setter
23478
- if (!disabledElementsLookup.has(node)) {
23479
- // The element is added to the map for the first time.
23480
- // Create a listener to remove it on `$destroy` (to avoid memory leak).
23481
- element.addEventListener(
23482
- "$destroy",
23483
- removeFromDisabledElementsLookup,
23484
- );
23485
- }
23486
- disabledElementsLookup.set(node, !bool);
23487
- }
23488
- }
23489
- }
23490
-
23491
- return bool;
23492
- },
23493
23440
  };
23494
23441
 
23495
23442
  return $animate;
@@ -23546,6 +23493,7 @@
23546
23493
  if (options.to && !isObject(options.to)) {
23547
23494
  options.to = null;
23548
23495
  }
23496
+
23549
23497
  // If animations are hard-disabled for the whole application there is no need to continue.
23550
23498
  // There are also situations where a directive issues an animation for a JQLite wrapper that
23551
23499
  // contains only comment nodes. In this case, there is no way we can perform an animation.
@@ -23558,7 +23506,6 @@
23558
23506
  close();
23559
23507
  return runner;
23560
23508
  }
23561
-
23562
23509
  const isStructural = ["enter", "move", "leave"].indexOf(event) >= 0;
23563
23510
 
23564
23511
  // This is a hard disable of all animations the element itself, therefore there is no need to
@@ -23794,6 +23741,8 @@
23794
23741
  });
23795
23742
  });
23796
23743
 
23744
+ // Since we don't have digest any more - trigger queue here
23745
+ setTimeout($rootScope.$flushQueue, 0);
23797
23746
  return runner;
23798
23747
 
23799
23748
  function notifyProgress(runner, event, phase, data) {
@@ -23957,14 +23906,14 @@
23957
23906
  // TODO: use caching here to speed things up for detection
23958
23907
  // TODO: add documentation
23959
23908
 
23960
- AnimateJsProvider.$inject = ["$animateProvider"];
23909
+ AnimateJsProvider.$inject = [$injectTokens.$animate + "Provider"];
23961
23910
  function AnimateJsProvider($animateProvider) {
23962
23911
  this.$get = [
23963
23912
  $injectTokens.$injector,
23964
23913
  "$$AnimateRunner",
23965
23914
  /**
23966
23915
  *
23967
- * @param {import("../core/di/internal-injector").InjectorService} $injector
23916
+ * @param {ng.InjectorService} $injector
23968
23917
  * @param {*} $$AnimateRunner
23969
23918
  * @returns
23970
23919
  */
@@ -24823,8 +24772,8 @@
24823
24772
  }
24824
24773
 
24825
24774
  /**
24826
- * @typedef {import('./interface.js').RafScheduler} RafScheduler
24827
- * @typedef {import('../interface.js').ServiceProvider} ServiceProvider
24775
+ * @typedef {import('./interface.ts').RafScheduler} RafScheduler
24776
+ * @typedef {import('../interface.ts').ServiceProvider} ServiceProvider
24828
24777
  */
24829
24778
 
24830
24779
  /**
@@ -25339,9 +25288,9 @@
25339
25288
  ];
25340
25289
  }
25341
25290
 
25342
- ngAnimateSwapDirective.$inject = ["$animate"];
25291
+ ngAnimateSwapDirective.$inject = [$injectTokens.$animate];
25343
25292
  /**
25344
- * @returns {import('../interface.ts').Directive}
25293
+ * @returns {ng.Directive}
25345
25294
  */
25346
25295
  function ngAnimateSwapDirective($animate) {
25347
25296
  return {
@@ -25350,10 +25299,10 @@
25350
25299
  terminal: true,
25351
25300
  priority: 550, // We use 550 here to ensure that the directive is caught before others,
25352
25301
  // but after `ngIf` (at priority 600).
25353
- link(scope, $element, attrs, ctrl, $transclude) {
25302
+ link(scope, $element, attrs, _ctrl, $transclude) {
25354
25303
  let previousElement;
25355
25304
  let previousScope;
25356
- scope.$watch(attrs["ngAnimateSwap"] || attrs["for"], (value) => {
25305
+ scope.$watch(attrs.ngAnimateSwap || attrs.for, (value) => {
25357
25306
  if (previousElement) {
25358
25307
  $animate.leave(previousElement);
25359
25308
  }
@@ -27580,7 +27529,7 @@
27580
27529
  * @param {PathNode[]} fromPath
27581
27530
  * @param {PathNode[]} toPath
27582
27531
  * @param {boolean} [reloadState]
27583
- * @returns {import("../transition/interface.js").TreeChanges}
27532
+ * @returns {import("../transition/interface.ts").TreeChanges}
27584
27533
  */
27585
27534
  static treeChanges(fromPath, toPath, reloadState) {
27586
27535
  const max = Math.min(fromPath.length, toPath.length);
@@ -28315,25 +28264,6 @@
28315
28264
  return vc.$ngViewContextAnchor === (ngViewContext && ngViewContext.name);
28316
28265
  };
28317
28266
 
28318
- /**
28319
- * An object for Transition Hook Phases
28320
- * @enum {number}
28321
- * @readonly
28322
- */
28323
- const TransitionHookPhase = {
28324
- CREATE: 0,
28325
- BEFORE: 1,
28326
- RUN: 2,
28327
- SUCCESS: 3,
28328
- ERROR: 4,
28329
- };
28330
-
28331
- /** An object for Transition Hook Scopes */
28332
- const TransitionHookScope = {
28333
- TRANSITION: 0,
28334
- STATE: 1,
28335
- };
28336
-
28337
28267
  /**
28338
28268
  * An object for Transition Rejection reasons.
28339
28269
  * @enum {number}
@@ -28453,7 +28383,7 @@
28453
28383
  }
28454
28384
  }
28455
28385
 
28456
- /** @typedef {import('../../interface.js').ServiceProvider} ServiceProvider
28386
+ /** @typedef {import('../../interface.ts').ServiceProvider} ServiceProvider
28457
28387
 
28458
28388
  /**
28459
28389
  * Configurable provider for an injectable event bus
@@ -28810,6 +28740,31 @@
28810
28740
  bind: null,
28811
28741
  };
28812
28742
 
28743
+ /**
28744
+ * Enum representing the different phases of a transition hook.
28745
+ *
28746
+ * @readonly
28747
+ * @enum {number}
28748
+ */
28749
+ const TransitionHookPhase = Object.freeze({
28750
+ CREATE: 0,
28751
+ BEFORE: 1,
28752
+ RUN: 2,
28753
+ SUCCESS: 3,
28754
+ ERROR: 4,
28755
+ });
28756
+
28757
+ /**
28758
+ * Enum representing the scope in which a transition hook operates.
28759
+ *
28760
+ * @readonly
28761
+ * @enum {number}
28762
+ */
28763
+ const TransitionHookScope = Object.freeze({
28764
+ TRANSITION: 0,
28765
+ STATE: 1,
28766
+ });
28767
+
28813
28768
  class TransitionHook {
28814
28769
  /**
28815
28770
  * Chains together an array of TransitionHooks.
@@ -30628,7 +30583,6 @@
30628
30583
  }
30629
30584
 
30630
30585
  _defineCoreEvents() {
30631
- const Phase = TransitionHookPhase;
30632
30586
  const TH = TransitionHook;
30633
30587
  const paths = this._criteriaPaths;
30634
30588
  const NORMAL_SORT = false,
@@ -30636,7 +30590,7 @@
30636
30590
  const SYNCHRONOUS = true;
30637
30591
  this._defineEvent(
30638
30592
  "onCreate",
30639
- Phase.CREATE,
30593
+ TransitionHookPhase.CREATE,
30640
30594
  0,
30641
30595
  paths.to,
30642
30596
  NORMAL_SORT,
@@ -30644,15 +30598,21 @@
30644
30598
  TH.THROW_ERROR,
30645
30599
  SYNCHRONOUS,
30646
30600
  );
30647
- this._defineEvent("onBefore", Phase.BEFORE, 0, paths.to);
30648
- this._defineEvent("onStart", Phase.RUN, 0, paths.to);
30649
- this._defineEvent("onExit", Phase.RUN, 100, paths.exiting, REVERSE_SORT);
30650
- this._defineEvent("onRetain", Phase.RUN, 200, paths.retained);
30651
- this._defineEvent("onEnter", Phase.RUN, 300, paths.entering);
30652
- this._defineEvent("onFinish", Phase.RUN, 400, paths.to);
30601
+ this._defineEvent("onBefore", TransitionHookPhase.BEFORE, 0, paths.to);
30602
+ this._defineEvent("onStart", TransitionHookPhase.RUN, 0, paths.to);
30603
+ this._defineEvent(
30604
+ "onExit",
30605
+ TransitionHookPhase.RUN,
30606
+ 100,
30607
+ paths.exiting,
30608
+ REVERSE_SORT,
30609
+ );
30610
+ this._defineEvent("onRetain", TransitionHookPhase.RUN, 200, paths.retained);
30611
+ this._defineEvent("onEnter", TransitionHookPhase.RUN, 300, paths.entering);
30612
+ this._defineEvent("onFinish", TransitionHookPhase.RUN, 400, paths.to);
30653
30613
  this._defineEvent(
30654
30614
  "onSuccess",
30655
- Phase.SUCCESS,
30615
+ TransitionHookPhase.SUCCESS,
30656
30616
  0,
30657
30617
  paths.to,
30658
30618
  NORMAL_SORT,
@@ -30662,7 +30622,7 @@
30662
30622
  );
30663
30623
  this._defineEvent(
30664
30624
  "onError",
30665
- Phase.ERROR,
30625
+ TransitionHookPhase.ERROR,
30666
30626
  0,
30667
30627
  paths.to,
30668
30628
  NORMAL_SORT,
@@ -30928,7 +30888,7 @@
30928
30888
 
30929
30889
  /**
30930
30890
  *
30931
- * @param {import("./interface.js").StateDeclaration} definition
30891
+ * @param {import("./interface.ts").StateDeclaration} definition
30932
30892
  */
30933
30893
  state(definition) {
30934
30894
  if (!definition.name) {
@@ -32228,7 +32188,7 @@
32228
32188
  );
32229
32189
  }
32230
32190
 
32231
- /** @typedef {import('./interface.js').StateDeclaration} StateDeclaration */
32191
+ /** @typedef {import('./interface.ts').StateDeclaration} StateDeclaration */
32232
32192
 
32233
32193
  /**
32234
32194
  * Internal representation of a ng-router state.
@@ -32251,7 +32211,7 @@
32251
32211
  includes = undefined;
32252
32212
 
32253
32213
  /**
32254
- * @param {import('./interface.js').StateDeclaration} config
32214
+ * @param {import('./interface.ts').StateDeclaration} config
32255
32215
  */
32256
32216
  constructor(config) {
32257
32217
  Object.assign(this, config);
@@ -32259,7 +32219,7 @@
32259
32219
  return this;
32260
32220
  };
32261
32221
  /**
32262
- * @type {import('./interface.js').StateDeclaration}
32222
+ * @type {import('./interface.ts').StateDeclaration}
32263
32223
  */
32264
32224
  this.self = config;
32265
32225
  /**
@@ -34648,7 +34608,7 @@
34648
34608
  * ```
34649
34609
  */
34650
34610
 
34651
- /** @type {import("../../interface.js").AnnotatedDirectiveFactory} */
34611
+ /** @type {import("../../interface.ts").AnnotatedDirectiveFactory} */
34652
34612
  let ngView = [
34653
34613
  "$view",
34654
34614
  "$animate",
@@ -34659,7 +34619,7 @@
34659
34619
  * @param {*} $animate
34660
34620
  * @param {*} $viewScroll
34661
34621
  * @param {*} $interpolate
34662
- * @returns {import("../../interface.js").Directive}
34622
+ * @returns {import("../../interface.ts").Directive}
34663
34623
  */
34664
34624
  function $ViewDirective($view, $animate, $viewScroll, $interpolate) {
34665
34625
  function getRenderer() {
@@ -35085,7 +35045,8 @@
35085
35045
  }
35086
35046
 
35087
35047
  /**
35088
- * @param {"get" | "delete" | "post" | "put"} method
35048
+ * @param {"get" | "delete" | "post" | "put"} method - HTTP method applied to request
35049
+ * @param {string} [attrOverride] - Custom name to use for the attribute
35089
35050
  * @returns {ng.DirectiveFactory}
35090
35051
  */
35091
35052
  function defineDirective(method, attrOverride) {
@@ -35099,6 +35060,7 @@
35099
35060
  $injectTokens.$parse,
35100
35061
  $injectTokens.$state,
35101
35062
  $injectTokens.$sse,
35063
+ $injectTokens.$animate,
35102
35064
  ];
35103
35065
  return directive;
35104
35066
  }
@@ -35118,15 +35080,11 @@
35118
35080
  /** @type {ng.DirectiveFactory} */
35119
35081
  const ngSseDirective = defineDirective("get", "ngSse");
35120
35082
 
35121
- /**
35122
- * @typedef {"click" | "change" | "submit"} EventType
35123
- */
35124
-
35125
35083
  /**
35126
35084
  * Selects DOM event to listen for based on the element type.
35127
35085
  *
35128
35086
  * @param {Element} element - The DOM element to inspect.
35129
- * @returns {EventType} The name of the event to listen for.
35087
+ * @returns {"click" | "change" | "submit"} The name of the event to listen for.
35130
35088
  */
35131
35089
  function getEventNameForElement(element) {
35132
35090
  const tag = element.tagName.toLowerCase();
@@ -35138,89 +35096,6 @@
35138
35096
  return "click";
35139
35097
  }
35140
35098
 
35141
- /**
35142
- * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35143
- *
35144
- * @param {string} html - The HTML string returned from the server.
35145
- * @param {import("./interface.ts").SwapModeType} swap
35146
- * @param {Element} target - The target DOM element to apply the swap to.
35147
- * @param {ng.Scope} scope
35148
- * @param {ng.CompileService} $compile
35149
- */
35150
- function handleSwapResponse(html, swap, target, scope, $compile) {
35151
- let nodes = [];
35152
- if (!["textcontent", "delete", "none"].includes(swap)) {
35153
- if (!html) {
35154
- return;
35155
- }
35156
-
35157
- if (isObject(html)) {
35158
- scope.$merge(html);
35159
- return;
35160
- }
35161
-
35162
- const compiled = $compile(html)(scope);
35163
- nodes =
35164
- compiled instanceof DocumentFragment
35165
- ? Array.from(compiled.childNodes)
35166
- : [compiled];
35167
- }
35168
-
35169
- switch (swap) {
35170
- case "innerHTML":
35171
- target.replaceChildren(...nodes);
35172
- break;
35173
-
35174
- case "outerHTML": {
35175
- const parent = target.parentNode;
35176
- if (!parent) return;
35177
- const frag = document.createDocumentFragment();
35178
- nodes.forEach((n) => frag.appendChild(n));
35179
- parent.replaceChild(frag, target);
35180
- break;
35181
- }
35182
-
35183
- case "textContent":
35184
- target.textContent = html;
35185
- break;
35186
-
35187
- case "beforebegin":
35188
- nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35189
- break;
35190
-
35191
- case "afterbegin":
35192
- nodes
35193
- .slice()
35194
- .reverse()
35195
- .forEach((node) => target.insertBefore(node, target.firstChild));
35196
- break;
35197
-
35198
- case "beforeend":
35199
- nodes.forEach((node) => target.appendChild(node));
35200
- break;
35201
-
35202
- case "afterend":
35203
- nodes
35204
- .slice()
35205
- .reverse()
35206
- .forEach((node) =>
35207
- target.parentNode.insertBefore(node, target.nextSibling),
35208
- );
35209
- break;
35210
-
35211
- case "delete":
35212
- target.remove();
35213
- break;
35214
-
35215
- case "none":
35216
- break;
35217
-
35218
- default:
35219
- target.replaceChildren(...nodes);
35220
- break;
35221
- }
35222
- }
35223
-
35224
35099
  /**
35225
35100
  * Creates an HTTP directive factory that supports GET, DELETE, POST, PUT.
35226
35101
  *
@@ -35229,6 +35104,8 @@
35229
35104
  * @returns {ng.DirectiveFactory}
35230
35105
  */
35231
35106
  function createHttpDirective(method, attrName) {
35107
+ let content = undefined;
35108
+
35232
35109
  /**
35233
35110
  * @param {ng.HttpService} $http
35234
35111
  * @param {ng.CompileService} $compile
@@ -35238,7 +35115,125 @@
35238
35115
  * @param {ng.SseService} $sse
35239
35116
  * @returns {ng.Directive}
35240
35117
  */
35241
- return function ($http, $compile, $log, $parse, $state, $sse) {
35118
+ return function ($http, $compile, $log, $parse, $state, $sse, $animate) {
35119
+ /**
35120
+ * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35121
+ *
35122
+ * @param {string | Object} html - The HTML string or object returned from the server.
35123
+ * @param {import("./interface.ts").SwapModeType} swap
35124
+ * @param {ng.Scope} scope
35125
+ * @param {ng.Attributes} attrs
35126
+ * @param {Element} element
35127
+ */
35128
+ function handleSwapResponse(html, swap, scope, attrs, element) {
35129
+ let animationEnabled = false;
35130
+ if (attrs.animate) {
35131
+ animationEnabled = true;
35132
+ }
35133
+ let nodes = [];
35134
+ if (!["textcontent", "delete", "none"].includes(swap)) {
35135
+ if (!html) return;
35136
+ const compiled = $compile(html)(scope);
35137
+ nodes =
35138
+ compiled instanceof DocumentFragment
35139
+ ? Array.from(compiled.childNodes)
35140
+ : [compiled];
35141
+ }
35142
+
35143
+ const targetSelector = attrs["target"];
35144
+ const target = targetSelector
35145
+ ? document.querySelector(targetSelector)
35146
+ : element;
35147
+
35148
+ if (!target) {
35149
+ $log.warn(`${attrName}: target "${targetSelector}" not found`);
35150
+ return;
35151
+ }
35152
+
35153
+ switch (swap) {
35154
+ case "innerHTML":
35155
+ if (animationEnabled) {
35156
+ if (content) {
35157
+ $animate.leave(content).done(() => {
35158
+ content = nodes[0];
35159
+ $animate.enter(nodes[0], target);
35160
+ scope.$flushQueue();
35161
+ });
35162
+ scope.$flushQueue();
35163
+ } else {
35164
+ content = nodes[0];
35165
+ $animate.enter(nodes[0], target);
35166
+ scope.$flushQueue();
35167
+ }
35168
+ } else {
35169
+ target.replaceChildren(...nodes);
35170
+ }
35171
+ break;
35172
+
35173
+ case "outerHTML": {
35174
+ const parent = target.parentNode;
35175
+ if (!parent) return;
35176
+ const frag = document.createDocumentFragment();
35177
+ nodes.forEach((n) => frag.appendChild(n));
35178
+ if (animationEnabled) {
35179
+ const placeholder = document.createComment("placeholder");
35180
+ target.parentNode.insertBefore(placeholder, target.nextSibling);
35181
+ $animate.leave(target).done(() => {
35182
+ const insertedNodes = Array.from(frag.childNodes);
35183
+ insertedNodes.forEach((n) =>
35184
+ $animate.enter(n, parent, placeholder),
35185
+ );
35186
+ content = insertedNodes;
35187
+ scope.$flushQueue();
35188
+ });
35189
+ scope.$flushQueue();
35190
+ } else {
35191
+ parent.replaceChild(frag, target);
35192
+ }
35193
+ break;
35194
+ }
35195
+
35196
+ case "textContent":
35197
+ target.textContent = html;
35198
+ break;
35199
+
35200
+ case "beforebegin":
35201
+ nodes.forEach((node) => target.parentNode.insertBefore(node, target));
35202
+ break;
35203
+
35204
+ case "afterbegin":
35205
+ nodes
35206
+ .slice()
35207
+ .reverse()
35208
+ .forEach((node) => target.insertBefore(node, target.firstChild));
35209
+ break;
35210
+
35211
+ case "beforeend":
35212
+ nodes.forEach((node) => target.appendChild(node));
35213
+ break;
35214
+
35215
+ case "afterend":
35216
+ nodes
35217
+ .slice()
35218
+ .reverse()
35219
+ .forEach((node) =>
35220
+ target.parentNode.insertBefore(node, target.nextSibling),
35221
+ );
35222
+ break;
35223
+
35224
+ case "delete":
35225
+ target.remove();
35226
+ break;
35227
+
35228
+ case "none":
35229
+ break;
35230
+
35231
+ default:
35232
+ target.replaceChildren(...nodes);
35233
+ break;
35234
+ }
35235
+ }
35236
+
35242
35237
  /**
35243
35238
  * Collects form data from the element or its associated form.
35244
35239
  *
@@ -35252,15 +35247,12 @@
35252
35247
  const tag = element.tagName.toLowerCase();
35253
35248
 
35254
35249
  if (tag === "form") {
35255
- /** @type {HTMLFormElement} */
35256
35250
  form = /** @type {HTMLFormElement} */ (element);
35257
35251
  } else if ("form" in element && element.form) {
35258
- /** @type {HTMLFormElement} */
35259
35252
  form = /** @type {HTMLFormElement} */ (element.form);
35260
35253
  } else if (element.hasAttribute("form")) {
35261
35254
  const formId = element.getAttribute("form");
35262
35255
  if (formId) {
35263
- /** @type {HTMLElement | null} */
35264
35256
  const maybeForm = document.getElementById(formId);
35265
35257
  if (maybeForm && maybeForm.tagName.toLowerCase() === "form") {
35266
35258
  form = /** @type {HTMLFormElement} */ (maybeForm);
@@ -35298,13 +35290,10 @@
35298
35290
  return {
35299
35291
  restrict: "A",
35300
35292
  link(scope, element, attrs) {
35301
- const eventName =
35302
- attrs["trigger"] ||
35303
- /** @type {EventType} */ getEventNameForElement(element);
35304
-
35293
+ const eventName = attrs.trigger || getEventNameForElement(element);
35305
35294
  const tag = element.tagName.toLowerCase();
35306
35295
 
35307
- if (isDefined(attrs["latch"])) {
35296
+ if (isDefined(attrs.latch)) {
35308
35297
  attrs.$observe(
35309
35298
  "latch",
35310
35299
  callBackAfterFirst(() =>
@@ -35320,24 +35309,14 @@
35320
35309
  element.dispatchEvent(new Event(eventName));
35321
35310
  intervalId = setInterval(
35322
35311
  () => element.dispatchEvent(new Event(eventName)),
35323
- parseInt(attrs["interval"]) || 1000,
35312
+ parseInt(attrs.interval) || 1000,
35324
35313
  );
35325
35314
  }
35326
35315
 
35327
35316
  element.addEventListener(eventName, async (event) => {
35328
35317
  if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35329
35318
  if (tag === "form") event.preventDefault();
35330
- const swap = attrs["swap"] || "innerHTML";
35331
- const targetSelector = attrs["target"];
35332
- const target = targetSelector
35333
- ? document.querySelector(targetSelector)
35334
- : element;
35335
-
35336
- if (!target) {
35337
- $log.warn(`${attrName}: target "${targetSelector}" not found`);
35338
- return;
35339
- }
35340
-
35319
+ const swap = attrs.swap || "innerHTML";
35341
35320
  const url = attrs[attrName];
35342
35321
  if (!url) {
35343
35322
  $log.warn(`${attrName}: no URL specified`);
@@ -35345,56 +35324,57 @@
35345
35324
  }
35346
35325
 
35347
35326
  const handler = (res) => {
35348
- if (isDefined(attrs["loading"])) {
35327
+ if (isDefined(attrs.loading)) {
35349
35328
  attrs.$set("loading", false);
35350
35329
  }
35351
35330
 
35352
- if (isDefined(attrs["loadingClass"])) {
35353
- attrs.$removeClass(attrs["loadingClass"]);
35331
+ if (isDefined(attrs.loadingClass)) {
35332
+ attrs.$removeClass(attrs.loadingClass);
35354
35333
  }
35355
35334
 
35356
35335
  const html = res.data;
35357
35336
  if (200 <= res.status && res.status <= 299) {
35358
- if (isDefined(attrs["success"])) {
35359
- $parse(attrs["success"])(scope, { $res: html });
35337
+ if (isDefined(attrs.success)) {
35338
+ $parse(attrs.success)(scope, { $res: html });
35360
35339
  }
35361
35340
 
35362
- if (isDefined(attrs["stateSuccess"])) {
35363
- $state.go(attrs["stateSuccess"]);
35341
+ if (isDefined(attrs.stateSuccess)) {
35342
+ $state.go(attrs.stateSuccess);
35364
35343
  }
35365
35344
  } else if (400 <= res.status && res.status <= 599) {
35366
- if (isDefined(attrs["error"])) {
35367
- $parse(attrs["error"])(scope, { $res: html });
35345
+ if (isDefined(attrs.error)) {
35346
+ $parse(attrs.error)(scope, { $res: html });
35368
35347
  }
35369
35348
 
35370
- if (isDefined(attrs["stateError"])) {
35371
- $state.go(attrs["stateError"]);
35349
+ if (isDefined(attrs.stateError)) {
35350
+ $state.go(attrs.stateError);
35372
35351
  }
35373
35352
  }
35374
35353
 
35375
- handleSwapResponse(
35376
- html,
35377
- /** @type {import("./interface.ts").SwapModeType} */ (swap),
35378
- target,
35379
- scope,
35380
- $compile,
35381
- );
35354
+ if (isObject(html)) {
35355
+ if (attrs.target) {
35356
+ scope.$eval(`${attrs.target} = ${JSON.stringify(html)}`);
35357
+ } else {
35358
+ scope.$merge(html);
35359
+ }
35360
+ } else if (isString(html)) {
35361
+ handleSwapResponse(html, swap, scope, attrs, element);
35362
+ }
35382
35363
  };
35383
- if (isDefined(attrs["delay"])) {
35384
- await wait(parseInt(attrs["delay"]) | 0);
35385
- }
35386
35364
 
35387
- if (throttled) {
35388
- return;
35365
+ if (isDefined(attrs.delay)) {
35366
+ await wait(parseInt(attrs.delay) | 0);
35389
35367
  }
35390
35368
 
35391
- if (isDefined(attrs["throttle"])) {
35369
+ if (throttled) return;
35370
+
35371
+ if (isDefined(attrs.throttle)) {
35392
35372
  throttled = true;
35393
35373
  attrs.$set("throttled", true);
35394
35374
  setTimeout(() => {
35395
35375
  attrs.$set("throttled", false);
35396
35376
  throttled = false;
35397
- }, parseInt(attrs["throttle"]));
35377
+ }, parseInt(attrs.throttle));
35398
35378
  }
35399
35379
 
35400
35380
  if (isDefined(attrs["loading"])) {
@@ -35402,13 +35382,13 @@
35402
35382
  }
35403
35383
 
35404
35384
  if (isDefined(attrs["loadingClass"])) {
35405
- attrs.$addClass(attrs["loadingClass"]);
35385
+ attrs.$addClass(attrs.loadingClass);
35406
35386
  }
35407
35387
 
35408
35388
  if (method === "post" || method === "put") {
35409
35389
  let data;
35410
35390
  const config = {};
35411
- if (attrs["enctype"]) {
35391
+ if (attrs.enctype) {
35412
35392
  config.headers = {
35413
35393
  "Content-Type": attrs["enctype"],
35414
35394
  };
@@ -35418,11 +35398,10 @@
35418
35398
  }
35419
35399
  $http[method](url, data, config).then(handler).catch(handler);
35420
35400
  } else {
35421
- // If SSE mode is enabled
35422
- if (method === "get" && attrs["ngSse"]) {
35401
+ if (method === "get" && attrs.ngSse) {
35423
35402
  const sseUrl = url;
35424
35403
  const config = {
35425
- withCredentials: attrs["withCredentials"] === "true",
35404
+ withCredentials: attrs.withCredentials === "true",
35426
35405
  transformMessage: (data) => {
35427
35406
  try {
35428
35407
  return JSON.parse(data);
@@ -35432,9 +35411,9 @@
35432
35411
  },
35433
35412
  onOpen: () => {
35434
35413
  $log.info(`${attrName}: SSE connection opened to ${sseUrl}`);
35435
- if (isDefined(attrs["loading"])) attrs.$set("loading", false);
35436
- if (isDefined(attrs["loadingClass"]))
35437
- attrs.$removeClass(attrs["loadingClass"]);
35414
+ if (isDefined(attrs.loading)) attrs.$set("loading", false);
35415
+ if (isDefined(attrs.loadingClass))
35416
+ attrs.$removeClass(attrs.loadingClass);
35438
35417
  },
35439
35418
  onMessage: (data) => {
35440
35419
  const res = { status: 200, data };
@@ -35445,12 +35424,15 @@
35445
35424
  const res = { status: 500, data: err };
35446
35425
  handler(res);
35447
35426
  },
35427
+ onReconnect: (count) => {
35428
+ $log.info(`ngSse: reconnected ${count} time(s)`);
35429
+ if (attrs.onReconnect)
35430
+ $parse(attrs.onReconnect)(scope, { $count: count });
35431
+ },
35448
35432
  };
35449
35433
 
35450
- // Open the SSE connection using the injected service
35451
35434
  const source = $sse(sseUrl, config);
35452
35435
 
35453
- // Cleanup on scope destroy
35454
35436
  scope.$on("$destroy", () => {
35455
35437
  $log.info(`${attrName}: closing SSE connection`);
35456
35438
  source.close();
@@ -35465,7 +35447,6 @@
35465
35447
  scope.$on("$destroy", () => clearInterval(intervalId));
35466
35448
  }
35467
35449
 
35468
- // Eagerly execute for 'load' event
35469
35450
  if (eventName == "load") {
35470
35451
  element.dispatchEvent(new Event("load"));
35471
35452
  }
@@ -35546,38 +35527,54 @@
35546
35527
  * const source = $sse('/events', {
35547
35528
  * onMessage: (data) => console.log(data),
35548
35529
  * onError: (err) => console.error(err),
35549
- * withCredentials: true
35530
+ * retryDelay: 2000,
35531
+ * heartbeatTimeout: 10000,
35550
35532
  * });
35551
35533
  *
35552
- * // later:
35553
35534
  * source.close();
35554
35535
  */
35555
-
35556
35536
  class SseProvider {
35557
35537
  constructor() {
35558
35538
  /**
35559
35539
  * Optional provider-level defaults
35560
35540
  * @type {ng.SseConfig}
35561
35541
  */
35562
- this.defaults = {};
35542
+ this.defaults = {
35543
+ retryDelay: 1000,
35544
+ maxRetries: Infinity,
35545
+ heartbeatTimeout: 15000, // 15 seconds
35546
+ transformMessage(data) {
35547
+ try {
35548
+ return JSON.parse(data);
35549
+ } catch {
35550
+ return data;
35551
+ }
35552
+ },
35553
+ };
35563
35554
  }
35564
35555
 
35565
35556
  /**
35566
35557
  * Returns the $sse service function
35567
35558
  * @returns {ng.SseService}
35568
35559
  */
35569
- $get =
35570
- () =>
35571
- (url, config = {}) => {
35572
- const finalUrl = this.#buildUrl(url, config.params);
35573
- return this.#createEventSource(finalUrl, config);
35574
- };
35560
+ $get = [
35561
+ $injectTokens.$log,
35562
+ /** @param {ng.LogService} log */
35563
+ (log) => {
35564
+ this.$log = log;
35565
+ return (url, config = {}) => {
35566
+ const mergedConfig = { ...this.defaults, ...config };
35567
+ const finalUrl = this.#buildUrl(url, mergedConfig.params);
35568
+ return this.#createConnection(finalUrl, mergedConfig);
35569
+ };
35570
+ },
35571
+ ];
35575
35572
 
35576
35573
  /**
35577
35574
  * Build URL with query parameters
35578
- * @param {string} url - Base URL
35579
- * @param {Record<string, any>=} params - Query parameters
35580
- * @returns {string} URL with serialized query string
35575
+ * @param {string} url
35576
+ * @param {Record<string, any>=} params
35577
+ * @returns {string}
35581
35578
  */
35582
35579
  #buildUrl(url, params) {
35583
35580
  if (!params) return url;
@@ -35588,37 +35585,81 @@
35588
35585
  }
35589
35586
 
35590
35587
  /**
35591
- * Create and manage an EventSource
35592
- * @param {string} url - URL for SSE connection
35593
- * @param {ng.SseConfig} config - Configuration object
35594
- * @returns {EventSource} The EventSource instance wrapped as SseService
35588
+ * Creates a managed SSE connection with reconnect and heartbeat
35589
+ * @param {string} url
35590
+ * @param {ng.SseConfig} config
35591
+ * @returns {import("./interface.ts").SseConnection}
35595
35592
  */
35596
- #createEventSource(url, config) {
35597
- const es = new EventSource(url, {
35598
- withCredentials: !!config.withCredentials,
35599
- });
35593
+ #createConnection(url, config) {
35594
+ let es;
35595
+ let retryCount = 0;
35596
+ let closed = false;
35597
+ let heartbeatTimer;
35600
35598
 
35601
- if (config.onOpen) {
35602
- es.addEventListener("open", (e) => config.onOpen(e));
35603
- }
35599
+ const connect = () => {
35600
+ if (closed) return;
35604
35601
 
35605
- es.addEventListener("message", (e) => {
35606
- let data = e.data;
35607
- try {
35608
- data = config.transformMessage
35609
- ? config.transformMessage(data)
35610
- : JSON.parse(data);
35611
- } catch {
35612
- // leave as raw string if not JSON
35613
- }
35614
- config.onMessage?.(data, e);
35615
- });
35602
+ es = new EventSource(url, {
35603
+ withCredentials: !!config.withCredentials,
35604
+ });
35616
35605
 
35617
- if (config.onError) {
35618
- es.addEventListener("error", (e) => config.onError(e));
35619
- }
35606
+ es.addEventListener("open", (e) => {
35607
+ retryCount = 0;
35608
+ config.onOpen?.(e);
35609
+ if (config.heartbeatTimeout) resetHeartbeat();
35610
+ });
35611
+
35612
+ es.addEventListener("message", (e) => {
35613
+ let data = e.data;
35614
+ try {
35615
+ data = config.transformMessage ? config.transformMessage(data) : data;
35616
+ } catch {
35617
+ /* empty */
35618
+ }
35619
+ config.onMessage?.(data, e);
35620
+ if (config.heartbeatTimeout) resetHeartbeat();
35621
+ });
35620
35622
 
35621
- return es;
35623
+ es.addEventListener("error", (err) => {
35624
+ config.onError?.(err);
35625
+ if (closed) return;
35626
+ es.close();
35627
+
35628
+ if (retryCount < config.maxRetries) {
35629
+ retryCount++;
35630
+ config.onReconnect?.(retryCount);
35631
+ setTimeout(connect, config.retryDelay);
35632
+ } else {
35633
+ this.$log.warn("SSE: Max retries reached");
35634
+ }
35635
+ });
35636
+ };
35637
+
35638
+ const resetHeartbeat = () => {
35639
+ clearTimeout(heartbeatTimer);
35640
+ heartbeatTimer = setTimeout(() => {
35641
+ this.$log.warn("SSE: heartbeat timeout, reconnecting...");
35642
+ es.close();
35643
+ config.onReconnect?.(++retryCount);
35644
+ connect();
35645
+ }, config.heartbeatTimeout);
35646
+ };
35647
+
35648
+ connect();
35649
+
35650
+ return {
35651
+ close() {
35652
+ closed = true;
35653
+ clearTimeout(heartbeatTimer);
35654
+ es.close();
35655
+ },
35656
+ connect() {
35657
+ if (closed == false) {
35658
+ close();
35659
+ }
35660
+ connect();
35661
+ },
35662
+ };
35622
35663
  }
35623
35664
  }
35624
35665
 
@@ -35675,6 +35716,248 @@
35675
35716
  };
35676
35717
  }
35677
35718
 
35719
+ ngWorkerDirective.$inject = ["$worker", $injectTokens.$parse, $injectTokens.$log];
35720
+ /**
35721
+ * ngWorker directive factory
35722
+ * Usage: <div ng-worker="workerName" data-params="{{ expression }}" data-on-result="callback($result)"></div>
35723
+ */
35724
+ function ngWorkerDirective($worker, $parse, $log) {
35725
+ return {
35726
+ restrict: "A",
35727
+ link(scope, element, attrs) {
35728
+ const workerName = attrs.ngWorker;
35729
+ if (!workerName) {
35730
+ $log.warn("ngWorker: missing worker name");
35731
+ return;
35732
+ }
35733
+
35734
+ const eventName = attrs.trigger || getEventNameForElement(element);
35735
+
35736
+ let throttled = false;
35737
+ let intervalId;
35738
+
35739
+ if (isDefined(attrs.latch)) {
35740
+ attrs.$observe(
35741
+ "latch",
35742
+ callBackAfterFirst(() => element.dispatchEvent(new Event(eventName))),
35743
+ );
35744
+ }
35745
+
35746
+ if (isDefined(attrs.interval)) {
35747
+ element.dispatchEvent(new Event(eventName));
35748
+ intervalId = setInterval(
35749
+ () => element.dispatchEvent(new Event(eventName)),
35750
+ parseInt(attrs.interval) || 1000,
35751
+ );
35752
+ }
35753
+
35754
+ const worker = $worker(workerName, {
35755
+ onMessage: (result) => {
35756
+ if (isDefined(attrs.dataOnResult)) {
35757
+ $parse(attrs.dataOnResult)(scope, { $result: result });
35758
+ } else {
35759
+ const swap = attrs.swap || "innerHTML";
35760
+ handleSwap(result, swap, element);
35761
+ }
35762
+ },
35763
+ onError: (err) => {
35764
+ $log.error(`[ng-worker:${workerName}]`, err);
35765
+ if (isDefined(attrs.dataOnError)) {
35766
+ $parse(attrs.dataOnError)(scope, { $error: err });
35767
+ } else {
35768
+ element.textContent = "Error";
35769
+ }
35770
+ },
35771
+ });
35772
+
35773
+ element.addEventListener(eventName, async () => {
35774
+ if (element.disabled) return;
35775
+
35776
+ if (isDefined(attrs.delay)) {
35777
+ await wait(parseInt(attrs.delay) || 0);
35778
+ }
35779
+
35780
+ if (throttled) return;
35781
+
35782
+ if (isDefined(attrs.throttle)) {
35783
+ throttled = true;
35784
+ attrs.$set("throttled", true);
35785
+ setTimeout(() => {
35786
+ attrs.$set("throttled", false);
35787
+ throttled = false;
35788
+ }, parseInt(attrs.throttle));
35789
+ }
35790
+
35791
+ let params;
35792
+ try {
35793
+ params = attrs.params ? scope.$eval(attrs.params) : undefined;
35794
+ } catch (err) {
35795
+ $log.error("ngWorker: failed to evaluate data-params", err);
35796
+ params = undefined;
35797
+ }
35798
+
35799
+ worker.post(params);
35800
+ });
35801
+
35802
+ if (intervalId) {
35803
+ scope.$on("$destroy", () => clearInterval(intervalId));
35804
+ }
35805
+
35806
+ if (eventName === "load") {
35807
+ element.dispatchEvent(new Event("load"));
35808
+ }
35809
+ },
35810
+ };
35811
+ }
35812
+
35813
+ /**
35814
+ * Swap result into DOM based on strategy
35815
+ */
35816
+ function handleSwap(result, swap, element) {
35817
+ switch (swap) {
35818
+ case "outerHTML": {
35819
+ const parent = element.parentNode;
35820
+ if (!parent) return;
35821
+ const temp = document.createElement("div");
35822
+ temp.innerHTML = result;
35823
+ parent.replaceChild(temp.firstChild, element);
35824
+ break;
35825
+ }
35826
+ case "textContent":
35827
+ element.textContent = result;
35828
+ break;
35829
+ case "beforebegin":
35830
+ element.insertAdjacentHTML("beforebegin", result);
35831
+ break;
35832
+ case "afterbegin":
35833
+ element.insertAdjacentHTML("afterbegin", result);
35834
+ break;
35835
+ case "beforeend":
35836
+ element.insertAdjacentHTML("beforeend", result);
35837
+ break;
35838
+ case "afterend":
35839
+ element.insertAdjacentHTML("afterend", result);
35840
+ break;
35841
+ case "innerHTML":
35842
+ default:
35843
+ element.innerHTML = result;
35844
+ break;
35845
+ }
35846
+ }
35847
+
35848
+ /**
35849
+ * Worker Provider
35850
+ *
35851
+ * Usage:
35852
+ * const worker = $worker('./math.worker.js', {
35853
+ * onMessage: (data) => console.log('Result:', data),
35854
+ * onError: (err) => console.error('Worker error:', err),
35855
+ * autoTerminate: false,
35856
+ * transformMessage: (d) => d,
35857
+ * });
35858
+ *
35859
+ * worker.post({ action: 'fib', n: 20 });
35860
+ * worker.terminate();
35861
+ */
35862
+ class WorkerProvider {
35863
+ /**
35864
+ * @type {ng.LogService}
35865
+ */
35866
+ $log;
35867
+ constructor() {
35868
+ /**
35869
+ * Optional provider-level defaults
35870
+ * @type {ng.WorkerConfig}
35871
+ */
35872
+ this.defaults = {
35873
+ autoTerminate: false,
35874
+ transformMessage(data) {
35875
+ try {
35876
+ return JSON.parse(data);
35877
+ } catch {
35878
+ return data;
35879
+ }
35880
+ },
35881
+ };
35882
+ }
35883
+
35884
+ /**
35885
+ * Returns the $worker service function
35886
+ * @returns {ng.WorkerService}
35887
+ */
35888
+ $get = [
35889
+ $injectTokens.$log,
35890
+ /** @param {ng.LogService} log */
35891
+ (log) => {
35892
+ this.$log = log;
35893
+ return (scriptPath, config = {}) => {
35894
+ const merged = { ...this.defaults, ...config };
35895
+ return this.#createWorker(scriptPath, merged);
35896
+ };
35897
+ },
35898
+ ];
35899
+
35900
+ /**
35901
+ * Creates a managed Web Worker instance
35902
+ * @param {string | URL} scriptPath
35903
+ * @param {ng.WorkerConfig} config
35904
+ * @returns {import("./interface.ts").WorkerConnection}
35905
+ */
35906
+ #createWorker(scriptPath, config) {
35907
+ if (!scriptPath) throw new Error("Worker script path required");
35908
+
35909
+ let worker = new Worker(scriptPath, { type: "module" });
35910
+ let terminated = false;
35911
+
35912
+ const reconnect = () => {
35913
+ if (terminated) return;
35914
+ this.$log.info("Worker: restarting...");
35915
+ worker.terminate();
35916
+ worker = new Worker(scriptPath, { type: "module" });
35917
+ wire(worker);
35918
+ };
35919
+
35920
+ const wire = (w) => {
35921
+ w.onmessage = (e) => {
35922
+ let data = e.data;
35923
+ try {
35924
+ data = config.transformMessage ? config.transformMessage(data) : data;
35925
+ } catch {
35926
+ /* no-op */
35927
+ }
35928
+ config.onMessage?.(data, e);
35929
+ };
35930
+
35931
+ w.onerror = (err) => {
35932
+ config.onError?.(err);
35933
+ if (config.autoRestart) reconnect();
35934
+ };
35935
+ };
35936
+
35937
+ wire(worker);
35938
+ let that = this;
35939
+ return {
35940
+ post(data) {
35941
+ if (terminated) return that.$log.warn("Worker already terminated");
35942
+ try {
35943
+ worker.postMessage(data);
35944
+ } catch (err) {
35945
+ that.$log.error("Worker post failed", err);
35946
+ }
35947
+ },
35948
+ terminate() {
35949
+ terminated = true;
35950
+ worker.terminate();
35951
+ },
35952
+ restart() {
35953
+ if (terminated)
35954
+ return that.$log.warn("Worker cannot restart after terminate");
35955
+ reconnect();
35956
+ },
35957
+ };
35958
+ }
35959
+ }
35960
+
35678
35961
  /**
35679
35962
  * Initializes core `ng` module.
35680
35963
  * @param {import('./angular.js').Angular} angular
@@ -35687,7 +35970,7 @@
35687
35970
  [],
35688
35971
  [
35689
35972
  $injectTokens.$provide,
35690
- /** @param {import("./interface.js").Provider} $provide */
35973
+ /** @param {import("./interface.ts").Provider} $provide */
35691
35974
  ($provide) => {
35692
35975
  // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
35693
35976
  $provide.provider({
@@ -35753,6 +36036,7 @@
35753
36036
  ngValue: ngValueDirective,
35754
36037
  ngModelOptions: ngModelOptionsDirective,
35755
36038
  ngViewport: ngViewportDirective,
36039
+ ngWorker: ngWorkerDirective,
35756
36040
  })
35757
36041
  .directive({
35758
36042
  input: hiddenInputBrowserCacheDirective,
@@ -35820,6 +36104,7 @@
35820
36104
  $url: UrlService,
35821
36105
  $stateRegistry: StateRegistryProvider,
35822
36106
  $eventBus: PubSubProvider,
36107
+ $worker: WorkerProvider,
35823
36108
  });
35824
36109
  },
35825
36110
  ],
@@ -35851,7 +36136,7 @@
35851
36136
  /**
35852
36137
  * @type {string} `version` from `package.json`
35853
36138
  */
35854
- this.version = "0.9.9"; //inserted via rollup plugin
36139
+ this.version = "0.10.0"; //inserted via rollup plugin
35855
36140
 
35856
36141
  /** @type {!Array<string|any>} */
35857
36142
  this.bootsrappedModules = [];
@@ -36074,7 +36359,7 @@
36074
36359
  * @param {string} name The name of the module to create or retrieve.
36075
36360
  * @param {Array.<string>} [requires] If specified then new module is being created. If
36076
36361
  * unspecified then the module is being retrieved for further configuration.
36077
- * @param {import("./interface.js").Injectable<any>} [configFn] Optional configuration function for the module that gets
36362
+ * @param {import("./interface.ts").Injectable<any>} [configFn] Optional configuration function for the module that gets
36078
36363
  * passed to {@link NgModule.config NgModule.config()}.
36079
36364
  * @returns {NgModule} A newly registered module.
36080
36365
  */