@angular-wave/angular.ts 0.0.72 → 0.0.73

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 (42) hide show
  1. package/dist/angular-ts.esm.js +2 -2
  2. package/dist/angular-ts.umd.js +2 -2
  3. package/package.json +1 -1
  4. package/src/animations/animate-js.html +5 -2
  5. package/src/animations/animate-queue.js +1 -1
  6. package/src/animations/animate.js +0 -18
  7. package/src/core/compile/attributes.js +8 -1
  8. package/src/core/compile/compile.spec.js +0 -1
  9. package/src/core/controller/controller.js +9 -3
  10. package/src/core/q/q.js +2 -1
  11. package/src/directive/change/change.js +3 -1
  12. package/src/directive/form/form.js +4 -3
  13. package/src/directive/list/list.js +3 -3
  14. package/src/directive/messages/messages.js +177 -172
  15. package/src/directive/model/model.js +261 -471
  16. package/src/directive/switch/switch.js +4 -4
  17. package/src/router/directives/state-directives.js +2 -9
  18. package/src/router/hooks/core-resolvables.js +5 -3
  19. package/src/router/path/path-utils.js +1 -2
  20. package/src/router/resolve/resolve-context.js +14 -29
  21. package/src/router/state/state-queue-manager.js +1 -2
  22. package/src/router/state/state-service.js +2 -3
  23. package/src/router/transition/transition.js +2 -2
  24. package/src/router/view/view.js +2 -8
  25. package/src/shared/common.js +3 -8
  26. package/src/shared/common.spec.js +1 -19
  27. package/src/shared/hof.js +1 -8
  28. package/src/shared/jqlite/jqlite.js +1 -1
  29. package/src/shared/predicates.js +3 -2
  30. package/src/types.js +2 -3
  31. package/types/animations/animate-queue.d.ts +1 -1
  32. package/types/core/compile/attributes.d.ts +10 -1
  33. package/types/core/q/q.d.ts +4 -2
  34. package/types/directive/form/form.d.ts +3 -1
  35. package/types/directive/messages/messages.d.ts +76 -0
  36. package/types/directive/model/model.d.ts +101 -239
  37. package/types/router/resolve/resolve-context.d.ts +0 -2
  38. package/types/router/transition/transition.d.ts +0 -1
  39. package/types/shared/common.d.ts +0 -3
  40. package/types/shared/hof.d.ts +0 -1
  41. package/types/shared/jqlite/jqlite.d.ts +2 -2
  42. package/types/types.d.ts +4 -2
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@angular-wave/angular.ts",
3
3
  "description": "A modern, optimized and typesafe version of AngularJS",
4
4
  "license": "MIT",
5
- "version": "0.0.72",
5
+ "version": "0.0.73",
6
6
  "type": "module",
7
7
  "main": "dist/angular-ts.esm.js",
8
8
  "browser": "dist/angular-ts.umd.js",
@@ -9,7 +9,7 @@
9
9
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", () => {
12
- window.angular.module("test", []).animation(".colorful", [
12
+ window.angular.module("test", []).animation(".movable", [
13
13
  function () {
14
14
  return {
15
15
  addClass: function (element, className, doneFn) {
@@ -34,7 +34,10 @@
34
34
  <style></style>
35
35
  </head>
36
36
  <body ng-app="test">
37
- <div ng-class="location" class="colorful">
37
+ <div ng-class="location" class="movable" animate="true">
38
+ this box is moody {{ location }}
39
+ </div>
40
+ <div ng-class="location" class="movable" data-animate="true">
38
41
  this box is moody {{ location }}
39
42
  </div>
40
43
  <button ng-click="location='0'">Change to red</button>
@@ -151,7 +151,7 @@ export function $$AnimateQueueProvider($animateProvider) {
151
151
  "$templateRequest",
152
152
  /**
153
153
  *
154
- * @param {*} $rootScope
154
+ * @param {import('../core/scope/scope').Scope} $rootScope
155
155
  * @param {*} $injector
156
156
  * @param {*} $$animation
157
157
  * @param {*} $$AnimateRunner
@@ -40,24 +40,6 @@ function extractElementNode(element) {
40
40
  }
41
41
  }
42
42
 
43
- function splitClasses(classes) {
44
- if (isString(classes)) {
45
- classes = classes.split(" ");
46
- }
47
-
48
- // Use Object.create(null) to prevent class assumptions involving property names in
49
- // Object.prototype
50
- const obj = Object.create(null);
51
- forEach(classes, (klass) => {
52
- // sometimes the split leaves empty string values
53
- // incase extra spaces were applied to the options
54
- if (klass.length) {
55
- obj[klass] = true;
56
- }
57
- });
58
- return obj;
59
- }
60
-
61
43
  // if any other type of options value besides an Object value is
62
44
  // passed into the $animate.method() animation then this helper code
63
45
  // will be run which will ignore it. While this patch is not the
@@ -15,9 +15,16 @@ const $compileMinErr = minErr("$compile");
15
15
  const SIMPLE_ATTR_NAME = /^\w/;
16
16
  const specialAttrHolder = window.document.createElement("div");
17
17
 
18
+ /**
19
+ * @typedef {Object} AnyStringKeyObject
20
+ * @property {Record<string, any>} [key]
21
+ */
22
+
23
+ /**
24
+ * @extends {AnyStringKeyObject}
25
+ */
18
26
  export class Attributes {
19
27
  /**
20
- *
21
28
  * @param {import('../scope/scope').Scope} $rootScope
22
29
  * @param {*} $animate
23
30
  * @param {import("../exception-handler").ExceptionHandlerProvider} $exceptionHandler
@@ -17149,7 +17149,6 @@ describe("$compile", () => {
17149
17149
  $rootScope.$digest();
17150
17150
  await wait(100);
17151
17151
  const spans = element.find("span");
17152
- debugger;
17153
17152
  expect(spans.eq(0)[0].classList.contains("ng-hide")).toBeTrue();
17154
17153
  //expect(spans.eq(1)[0].classList.contains("ng-hide")).toBeTrue();
17155
17154
  expect(spans.eq(2)[0].classList.contains("ng-hide")).toBeTrue();
@@ -162,7 +162,9 @@ export function $ControllerProvider() {
162
162
  locals,
163
163
  identifier,
164
164
  instance,
165
- constructor || expression.name,
165
+ constructor ||
166
+ /** @type {import("../../types").Controller} */ (expression)
167
+ .name,
166
168
  );
167
169
  }
168
170
 
@@ -185,7 +187,10 @@ export function $ControllerProvider() {
185
187
  locals,
186
188
  identifier,
187
189
  instance,
188
- constructor || expression.name,
190
+ constructor ||
191
+ /** @type {import("../../types").Controller} */ (
192
+ expression
193
+ ).name,
189
194
  );
190
195
  }
191
196
  }
@@ -209,7 +214,8 @@ export function $ControllerProvider() {
209
214
  locals,
210
215
  identifier,
211
216
  instance,
212
- constructor || expression.name,
217
+ constructor ||
218
+ /** @type {import("../../types").Controller} */ (expression).name,
213
219
  );
214
220
  }
215
221
 
package/src/core/q/q.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  * @property {function(
17
17
  * ((value: T) => (PromiseLike<never>|PromiseLike<T>|T))|null,
18
18
  * ((reason: any) => (PromiseLike<never>|PromiseLike<T>|T))|null,
19
- * ((state: any) => any)
19
+ * ((state: any) => any)=
20
20
  * ): QPromise<T|never>} then - Calls one of the success or error callbacks asynchronously as soon as the result is available.
21
21
  * @property {function(
22
22
  * ((value: T) => (QPromise<never>|QPromise<T>|T))|null,
@@ -25,6 +25,7 @@ import {
25
25
  * ): QPromise<T|never>} then - Calls one of the success or error callbacks asynchronously as soon as the result is available.
26
26
  * @property {function(((reason: any) => (PromiseLike<never>|PromiseLike<T>|T))|null): QPromise<T>|T} catch - Shorthand for promise.then(null, errorCallback).
27
27
  * @property {function(((reason: any) => (QPromise<never>|QPromise<T>|T))|null): QPromise<T>|T} catch - Shorthand for promise.then(null, errorCallback).
28
+ * @property {function(Array.<QPromise<T>>): QPromise<T>} all
28
29
  * @property {function(function(): void): QPromise<T>} finally - Allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value.
29
30
  * @property {number} [$$intervalId] - Internal id set by the $interval service for callback notifications
30
31
  * @property {number} [$$timeoutId] - Timeout id set by the $timeout service for cancelations
@@ -6,7 +6,9 @@ export function ngChangeDirective() {
6
6
  restrict: "A",
7
7
  require: "ngModel",
8
8
  link(scope, _element, attr, ctrl) {
9
- ctrl.$viewChangeListeners.push(() => scope.$eval(attr.ngChange));
9
+ /** @type {import('../../types').NgModelController} */ (
10
+ ctrl
11
+ ).$viewChangeListeners.push(() => scope.$eval(attr.ngChange));
10
12
  },
11
13
  };
12
14
  }
@@ -21,13 +21,14 @@ export const nullFormCtrl = {
21
21
  $getControls: valueFn([]),
22
22
  $$renameControl: nullFormRenameControl,
23
23
  $removeControl: () => {},
24
- $setValidity: () => {},
24
+ /** @type {(...any) => any} */
25
+ $setValidity: function () {},
25
26
  $setDirty: () => {},
26
27
  $setPristine: () => {},
27
28
  $setSubmitted: () => {},
28
29
  $$setSubmitted: () => {},
29
30
  };
30
- const PENDING_CLASS = "ng-pending";
31
+ export const PENDING_CLASS = "ng-pending";
31
32
  const SUBMITTED_CLASS = "ng-submitted";
32
33
 
33
34
  function nullFormRenameControl(control, name) {
@@ -695,7 +696,7 @@ export function addSetValidityMethod(context) {
695
696
  }
696
697
  }
697
698
 
698
- function isObjectEmpty(obj) {
699
+ export function isObjectEmpty(obj) {
699
700
  if (obj) {
700
701
  for (const prop in obj) {
701
702
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
@@ -28,8 +28,8 @@ export function ngListDirective() {
28
28
  return list;
29
29
  };
30
30
 
31
- ctrl.$parsers.push(parse);
32
- ctrl.$formatters.push((value) => {
31
+ ctrl["$parsers"].push(parse);
32
+ ctrl["$formatters"].push((value) => {
33
33
  if (Array.isArray(value)) {
34
34
  return value.join(ngList);
35
35
  }
@@ -38,7 +38,7 @@ export function ngListDirective() {
38
38
  });
39
39
 
40
40
  // Override the standard $isEmpty because an empty array means the input is empty.
41
- ctrl.$isEmpty = function (value) {
41
+ ctrl["$isEmpty"] = function (value) {
42
42
  return !value || !value.length;
43
43
  };
44
44
  },
@@ -1,198 +1,203 @@
1
- import { forEach, isString } from "../../shared/utils";
2
-
3
- ngMessagesDirective.$inject = ["$animate"];
4
- export function ngMessagesDirective($animate) {
5
- const ACTIVE_CLASS = "ng-active";
6
- const INACTIVE_CLASS = "ng-inactive";
7
- return {
8
- require: "ngMessages",
9
- restrict: "AE",
10
- controller: function ($element, $scope, $attrs) {
11
- const ctrl = this;
12
- let latestKey = 0;
13
- let nextAttachId = 0;
14
- const messages = {};
15
- let renderLater;
16
- let cachedCollection;
17
-
18
- this.head = undefined;
19
- this.default = undefined;
20
- this.messages = messages;
21
-
22
- this.getAttachId = function getAttachId() {
23
- return nextAttachId++;
24
- };
1
+ import { isString } from "../../shared/utils";
2
+
3
+ const ACTIVE_CLASS = "ng-active";
4
+ const INACTIVE_CLASS = "ng-inactive";
5
+
6
+ class NgMessageCtrl {
7
+ /**
8
+ * @param {import('../../shared/jqlite/jqlite').JQLite} $element
9
+ * @param {import('../../core/scope/scope').Scope} $scope
10
+ * @param {import('../../core/compile/attributes').Attributes} $attrs
11
+ * @param {*} $animate
12
+ */
13
+ constructor($element, $scope, $attrs, $animate) {
14
+ this.$element = $element;
15
+ this.$scope = $scope;
16
+ this.$attrs = $attrs;
17
+ this.$animate = $animate;
18
+
19
+ this.latestKey = 0;
20
+ this.nextAttachId = 0;
21
+ this.messages = {};
22
+ this.renderLater = false;
23
+ this.cachedCollection = null;
24
+
25
+ this.head = undefined;
26
+ this.default = undefined;
27
+
28
+ this.$scope.$watchCollection(
29
+ this.$attrs["ngMessages"] || this.$attrs["for"],
30
+ this.render.bind(this),
31
+ );
32
+ }
25
33
 
26
- this.render = function (collection) {
27
- collection = collection || {};
28
-
29
- renderLater = false;
30
- cachedCollection = collection;
31
-
32
- // this is true if the attribute is empty or if the attribute value is truthy
33
- const multiple =
34
- isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
35
- isAttrTruthy($scope, $attrs.multiple);
36
-
37
- const unmatchedMessages = [];
38
- const matchedKeys = {};
39
- let truthyKeys = 0;
40
- let messageItem = ctrl.head;
41
- let messageFound = false;
42
- let totalMessages = 0;
43
-
44
- // we use != instead of !== to allow for both undefined and null values
45
- while (messageItem != null) {
46
- totalMessages++;
47
- const messageCtrl = messageItem.message;
48
-
49
- let messageUsed = false;
50
- if (!messageFound) {
51
- forEach(collection, (value, key) => {
52
- if (truthy(value) && !messageUsed) {
53
- truthyKeys++;
54
-
55
- if (messageCtrl.test(key)) {
56
- // this is to prevent the same error name from showing up twice
57
- if (matchedKeys[key]) return;
58
- matchedKeys[key] = true;
59
-
60
- messageUsed = true;
61
- messageCtrl.attach();
62
- }
63
- }
64
- });
65
- }
34
+ getAttachId() {
35
+ return this.nextAttachId++;
36
+ }
66
37
 
67
- if (messageUsed) {
68
- // unless we want to display multiple messages then we should
69
- // set a flag here to avoid displaying the next message in the list
70
- messageFound = !multiple;
71
- } else {
72
- unmatchedMessages.push(messageCtrl);
38
+ render(collection = {}) {
39
+ this.renderLater = false;
40
+ this.cachedCollection = collection;
41
+
42
+ const multiple =
43
+ isAttrTruthy(this.$scope, this.$attrs["ngMessagesMultiple"]) ||
44
+ isAttrTruthy(this.$scope, this.$attrs["multiple"]);
45
+
46
+ const unmatchedMessages = [];
47
+ const matchedKeys = {};
48
+ let truthyKeys = 0;
49
+ let messageItem = this.head;
50
+ let messageFound = false;
51
+ let totalMessages = 0;
52
+
53
+ while (messageItem != null) {
54
+ totalMessages++;
55
+ const messageCtrl = messageItem.message;
56
+ let messageUsed = false;
57
+
58
+ if (!messageFound) {
59
+ Object.entries(collection).forEach(([key, value]) => {
60
+ if (truthy(value) && !messageUsed) {
61
+ truthyKeys++;
62
+
63
+ if (messageCtrl.test(key)) {
64
+ if (matchedKeys[key]) return;
65
+ matchedKeys[key] = true;
66
+
67
+ messageUsed = true;
68
+ messageCtrl.attach();
69
+ }
73
70
  }
74
-
75
- messageItem = messageItem.next;
76
- }
77
-
78
- forEach(unmatchedMessages, (messageCtrl) => {
79
- messageCtrl.detach();
80
71
  });
72
+ }
81
73
 
82
- const messageMatched = unmatchedMessages.length !== totalMessages;
83
- const attachDefault = ctrl.default && !messageMatched && truthyKeys > 0;
74
+ if (messageUsed) {
75
+ messageFound = !multiple;
76
+ } else {
77
+ unmatchedMessages.push(messageCtrl);
78
+ }
84
79
 
85
- if (attachDefault) {
86
- ctrl.default.attach();
87
- } else if (ctrl.default) {
88
- ctrl.default.detach();
89
- }
80
+ messageItem = messageItem.next;
81
+ }
90
82
 
91
- if (messageMatched || attachDefault) {
92
- $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS);
93
- } else {
94
- $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
95
- }
96
- };
83
+ unmatchedMessages.forEach((messageCtrl) => {
84
+ messageCtrl.detach();
85
+ });
97
86
 
98
- $scope.$watchCollection($attrs.ngMessages || $attrs.for, ctrl.render);
87
+ const messageMatched = unmatchedMessages.length !== totalMessages;
88
+ const attachDefault = this.default && !messageMatched && truthyKeys > 0;
99
89
 
100
- this.reRender = function () {
101
- if (!renderLater) {
102
- renderLater = true;
103
- $scope.$evalAsync(() => {
104
- if (renderLater && cachedCollection) {
105
- ctrl.render(cachedCollection);
106
- }
107
- });
108
- }
109
- };
90
+ if (attachDefault) {
91
+ this.default.attach();
92
+ } else if (this.default) {
93
+ this.default.detach();
94
+ }
110
95
 
111
- this.register = function (comment, messageCtrl, isDefault) {
112
- if (isDefault) {
113
- ctrl.default = messageCtrl;
114
- } else {
115
- const nextKey = latestKey.toString();
116
- messages[nextKey] = {
117
- message: messageCtrl,
118
- };
119
- insertMessageNode($element[0], comment, nextKey);
120
- comment.$$ngMessageNode = nextKey;
121
- latestKey++;
96
+ if (messageMatched || attachDefault) {
97
+ this.$animate.setClass(this.$element, ACTIVE_CLASS, INACTIVE_CLASS);
98
+ } else {
99
+ this.$animate.setClass(this.$element, INACTIVE_CLASS, ACTIVE_CLASS);
100
+ }
101
+ }
102
+
103
+ reRender() {
104
+ if (!this.renderLater) {
105
+ this.renderLater = true;
106
+ this.$scope.$evalAsync(() => {
107
+ if (this.renderLater && this.cachedCollection) {
108
+ this.render(this.cachedCollection);
122
109
  }
110
+ });
111
+ }
112
+ }
123
113
 
124
- ctrl.reRender();
114
+ register(comment, messageCtrl, isDefault) {
115
+ if (isDefault) {
116
+ this.default = messageCtrl;
117
+ } else {
118
+ const nextKey = this.latestKey.toString();
119
+ this.messages[nextKey] = {
120
+ message: messageCtrl,
125
121
  };
122
+ this.insertMessageNode(this.$element[0], comment, nextKey);
123
+ comment.$$ngMessageNode = nextKey;
124
+ this.latestKey++;
125
+ }
126
126
 
127
- this.deregister = function (comment, isDefault) {
128
- if (isDefault) {
129
- delete ctrl.default;
130
- } else {
131
- const key = comment.$$ngMessageNode;
132
- delete comment.$$ngMessageNode;
133
- removeMessageNode($element[0], comment, key);
134
- delete messages[key];
135
- }
136
- ctrl.reRender();
137
- };
127
+ this.reRender();
128
+ }
138
129
 
139
- function findPreviousMessage(parent, comment) {
140
- let prevNode = comment;
141
- const parentLookup = [];
130
+ deregister(comment, isDefault) {
131
+ if (isDefault) {
132
+ delete this.default;
133
+ } else {
134
+ const key = comment.$$ngMessageNode;
135
+ delete comment.$$ngMessageNode;
136
+ this.removeMessageNode(this.$element[0], comment, key);
137
+ delete this.messages[key];
138
+ }
139
+ this.reRender();
140
+ }
142
141
 
143
- while (prevNode && prevNode !== parent) {
144
- const prevKey = prevNode.$$ngMessageNode;
145
- if (prevKey && prevKey.length) {
146
- return messages[prevKey];
147
- }
142
+ findPreviousMessage(parent, comment) {
143
+ let prevNode = comment;
144
+ const parentLookup = [];
148
145
 
149
- // dive deeper into the DOM and examine its children for any ngMessage
150
- // comments that may be in an element that appears deeper in the list
151
- if (
152
- prevNode.childNodes.length &&
153
- parentLookup.indexOf(prevNode) === -1
154
- ) {
155
- parentLookup.push(prevNode);
156
- prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
157
- } else if (prevNode.previousSibling) {
158
- prevNode = prevNode.previousSibling;
159
- } else {
160
- prevNode = prevNode.parentNode;
161
- parentLookup.push(prevNode);
162
- }
163
- }
146
+ while (prevNode && prevNode !== parent) {
147
+ const prevKey = prevNode.$$ngMessageNode;
148
+ if (prevKey && prevKey.length) {
149
+ return this.messages[prevKey];
164
150
  }
165
151
 
166
- function insertMessageNode(parent, comment, key) {
167
- const messageNode = messages[key];
168
- if (!ctrl.head) {
169
- ctrl.head = messageNode;
170
- } else {
171
- const match = findPreviousMessage(parent, comment);
172
- if (match) {
173
- messageNode.next = match.next;
174
- match.next = messageNode;
175
- } else {
176
- messageNode.next = ctrl.head;
177
- ctrl.head = messageNode;
178
- }
179
- }
152
+ if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) === -1) {
153
+ parentLookup.push(prevNode);
154
+ prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
155
+ } else if (prevNode.previousSibling) {
156
+ prevNode = prevNode.previousSibling;
157
+ } else {
158
+ prevNode = prevNode.parentNode;
159
+ parentLookup.push(prevNode);
160
+ }
161
+ }
162
+ }
163
+
164
+ insertMessageNode(parent, comment, key) {
165
+ const messageNode = this.messages[key];
166
+ if (!this.head) {
167
+ this.head = messageNode;
168
+ } else {
169
+ const match = this.findPreviousMessage(parent, comment);
170
+ if (match) {
171
+ messageNode.next = match.next;
172
+ match.next = messageNode;
173
+ } else {
174
+ messageNode.next = this.head;
175
+ this.head = messageNode;
180
176
  }
177
+ }
178
+ }
181
179
 
182
- function removeMessageNode(parent, comment, key) {
183
- const messageNode = messages[key];
180
+ removeMessageNode(parent, comment, key) {
181
+ const messageNode = this.messages[key];
184
182
 
185
- // This message node may have already been removed by a call to deregister()
186
- if (!messageNode) return;
183
+ if (!messageNode) return;
187
184
 
188
- const match = findPreviousMessage(parent, comment);
189
- if (match) {
190
- match.next = messageNode.next;
191
- } else {
192
- ctrl.head = messageNode.next;
193
- }
194
- }
195
- },
185
+ const match = this.findPreviousMessage(parent, comment);
186
+ if (match) {
187
+ match.next = messageNode.next;
188
+ } else {
189
+ this.head = messageNode.next;
190
+ }
191
+ }
192
+ }
193
+
194
+ ngMessagesDirective.$inject = ["$animate"];
195
+ export function ngMessagesDirective($animate) {
196
+ return {
197
+ require: "ngMessages",
198
+ restrict: "AE",
199
+ controller: ($element, $scope, $attrs) =>
200
+ new NgMessageCtrl($element, $scope, $attrs, $animate),
196
201
  };
197
202
  }
198
203