@angular-wave/angular.ts 0.0.69 → 0.0.70

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.
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.69",
5
+ "version": "0.0.70",
6
6
  "type": "module",
7
7
  "main": "dist/angular-ts.esm.js",
8
8
  "browser": "dist/angular-ts.umd.js",
@@ -512,7 +512,6 @@ export function $CompileProvider($provide, $$sanitizeUriProvider) {
512
512
 
513
513
  /**
514
514
  * The security context of DOM Properties.
515
- * @private
516
515
  */
517
516
  const PROP_CONTEXTS = Object.create(null);
518
517
 
@@ -7753,7 +7753,7 @@ describe("$compile", () => {
7753
7753
  expect(
7754
7754
  element[0].outerHTML.replace(' selected="selected"', ""),
7755
7755
  ).toEqual(
7756
- '<select ng-model="x" class="ng-pristine ng-untouched ng-valid ng-empty">' +
7756
+ '<select ng-model="x" class="ng-pristine ng-untouched ng-valid ng-empty" aria-invalid="false">' +
7757
7757
  '<option value="">Greet !</option>' +
7758
7758
  "</select>",
7759
7759
  );
@@ -7762,7 +7762,7 @@ describe("$compile", () => {
7762
7762
  expect(
7763
7763
  element[0].outerHTML.replace(' selected="selected"', ""),
7764
7764
  ).toEqual(
7765
- '<select ng-model="x" class="ng-pristine ng-untouched ng-valid ng-empty">' +
7765
+ '<select ng-model="x" class="ng-pristine ng-untouched ng-valid ng-empty" aria-invalid="false">' +
7766
7766
  '<option value="">Greet Misko!</option>' +
7767
7767
  "</select>",
7768
7768
  );
@@ -905,7 +905,6 @@ export class Scope {
905
905
  }
906
906
 
907
907
  /**
908
- * @private
909
908
  * @param {ScopePhase} phase
910
909
  */
911
910
  beginPhase(phase) {
@@ -10,7 +10,7 @@
10
10
  <script src="/jasmine/jasmine-5.1.2/jasmine-html.js"></script>
11
11
  <script src="/jasmine/jasmine-5.1.2/boot0.js"></script>
12
12
  <script src="/jasmine/jasmine-5.1.2/boot1.js"></script>
13
- <script type="module" src="/src/exts/aria/aria.spec.js"></script>
13
+ <script type="module" src="/src/directive/aria/aria.spec.js"></script>
14
14
  </head>
15
15
  <body>
16
16
  <div id="dummy"></div>
@@ -0,0 +1,382 @@
1
+ import { extend } from "../../shared/utils";
2
+
3
+ const ARIA_DISABLE_ATTR = "ngAriaDisable";
4
+
5
+ /**
6
+ * Internal Utilities
7
+ */
8
+ const nativeAriaNodeNames = [
9
+ "BUTTON",
10
+ "A",
11
+ "INPUT",
12
+ "TEXTAREA",
13
+ "SELECT",
14
+ "DETAILS",
15
+ "SUMMARY",
16
+ ];
17
+
18
+ const isNodeOneOf = function (elem, nodeTypeArray) {
19
+ if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
20
+ return true;
21
+ }
22
+ };
23
+ /**
24
+ * @ngdoc provider
25
+ * @name $ariaProvider
26
+ *
27
+ *
28
+ * @description
29
+ *
30
+ * Used for configuring the ARIA attributes injected and managed by ngAria.
31
+ *
32
+ * ```js
33
+ * angular.module('myApp', ['ngAria'], function config($ariaProvider) {
34
+ * $ariaProvider.config({
35
+ * ariaValue: true,
36
+ * tabindex: false
37
+ * });
38
+ * });
39
+ *```
40
+ *
41
+ * ## Dependencies
42
+ * Requires the {@link ngAria} module to be installed.
43
+ *
44
+ */
45
+ export function AriaProvider() {
46
+ let config = {
47
+ ariaHidden: true,
48
+ ariaChecked: true,
49
+ ariaReadonly: true,
50
+ ariaDisabled: true,
51
+ ariaRequired: true,
52
+ ariaInvalid: true,
53
+ ariaValue: true,
54
+ tabindex: true,
55
+ bindKeydown: true,
56
+ bindRoleForClick: true,
57
+ };
58
+
59
+ this.config = function (newConfig) {
60
+ config = extend(config, newConfig);
61
+ };
62
+
63
+ function watchExpr(attrName, ariaAttr, nativeAriaNodeNames, negate) {
64
+ return function (scope, elem, attr) {
65
+ if (Object.prototype.hasOwnProperty.call(attr, ARIA_DISABLE_ATTR)) return;
66
+
67
+ const ariaCamelName = attr.$normalize(ariaAttr);
68
+ if (
69
+ config[ariaCamelName] &&
70
+ !isNodeOneOf(elem, nativeAriaNodeNames) &&
71
+ !attr[ariaCamelName]
72
+ ) {
73
+ scope.$watch(attr[attrName], (boolVal) => {
74
+ // ensure boolean value
75
+ boolVal = negate ? !boolVal : !!boolVal;
76
+ elem.attr(ariaAttr, boolVal);
77
+ });
78
+ }
79
+ };
80
+ }
81
+
82
+ this.$get = function () {
83
+ return {
84
+ config(key) {
85
+ return config[key];
86
+ },
87
+ $$watchExpr: watchExpr,
88
+ };
89
+ };
90
+ }
91
+
92
+ ngDisabledAriaDirective.$inject = ["$aria"];
93
+ export function ngDisabledAriaDirective($aria) {
94
+ return $aria.$$watchExpr(
95
+ "ngDisabled",
96
+ "aria-disabled",
97
+ nativeAriaNodeNames,
98
+ false,
99
+ );
100
+ }
101
+
102
+ ngShowAriaDirective.$inject = ["$aria"];
103
+ export function ngShowAriaDirective($aria) {
104
+ return $aria.$$watchExpr("ngShow", "aria-hidden", [], true);
105
+ }
106
+
107
+ export function ngMessagesAriaDirective() {
108
+ return {
109
+ restrict: "A",
110
+ require: "?ngMessages",
111
+ link(_scope, elem, attr) {
112
+ if (Object.prototype.hasOwnProperty.call(attr, ARIA_DISABLE_ATTR)) return;
113
+
114
+ if (!elem.attr("aria-live")) {
115
+ elem.attr("aria-live", "assertive");
116
+ }
117
+ },
118
+ };
119
+ }
120
+
121
+ ngClickAriaDirective.$inject = ["$aria", "$parse"];
122
+ export function ngClickAriaDirective($aria, $parse) {
123
+ return {
124
+ restrict: "A",
125
+ compile(elem, attr) {
126
+ if (Object.prototype.hasOwnProperty.call(attr, ARIA_DISABLE_ATTR)) return;
127
+
128
+ const fn = $parse(attr.ngClick);
129
+ return function (scope, elem, attr) {
130
+ if (!isNodeOneOf(elem, nativeAriaNodeNames)) {
131
+ if ($aria.config("bindRoleForClick") && !elem.attr("role")) {
132
+ elem.attr("role", "button");
133
+ }
134
+
135
+ if ($aria.config("tabindex") && !elem.attr("tabindex")) {
136
+ elem.attr("tabindex", 0);
137
+ }
138
+
139
+ if (
140
+ $aria.config("bindKeydown") &&
141
+ !attr.ngKeydown &&
142
+ !attr.ngKeypress &&
143
+ !attr.ngKeyup
144
+ ) {
145
+ elem.on("keydown", (event) => {
146
+ const keyCode = event.which || event.keyCode;
147
+
148
+ if (keyCode === 13 || keyCode === 32) {
149
+ // If the event is triggered on a non-interactive element ...
150
+ if (
151
+ nativeAriaNodeNames.indexOf(event.target.nodeName) === -1 &&
152
+ !event.target.isContentEditable
153
+ ) {
154
+ // ... prevent the default browser behavior (e.g. scrolling when pressing spacebar)
155
+ // See https://github.com/angular/angular.js/issues/16664
156
+ event.preventDefault();
157
+ }
158
+ scope.$apply(callback);
159
+ }
160
+
161
+ function callback() {
162
+ fn(scope, { $event: event });
163
+ }
164
+ });
165
+ }
166
+ }
167
+ };
168
+ },
169
+ };
170
+ }
171
+
172
+ ngRequiredAriaDirective.$inject = ["$aria"];
173
+ export function ngRequiredAriaDirective($aria) {
174
+ return $aria.$$watchExpr(
175
+ "ngRequired",
176
+ "aria-required",
177
+ nativeAriaNodeNames,
178
+ false,
179
+ );
180
+ }
181
+
182
+ ngCheckedAriaDirective.$inject = ["$aria"];
183
+ export function ngCheckedAriaDirective($aria) {
184
+ return $aria.$$watchExpr(
185
+ "ngChecked",
186
+ "aria-checked",
187
+ nativeAriaNodeNames,
188
+ false,
189
+ );
190
+ }
191
+
192
+ ngValueAriaDirective.$inject = ["$aria"];
193
+ export function ngValueAriaDirective($aria) {
194
+ return $aria.$$watchExpr(
195
+ "ngValue",
196
+ "aria-checked",
197
+ nativeAriaNodeNames,
198
+ false,
199
+ );
200
+ }
201
+
202
+ ngHideAriaDirective.$inject = ["$aria"];
203
+ export function ngHideAriaDirective($aria) {
204
+ return $aria.$$watchExpr("ngHide", "aria-hidden", [], false);
205
+ }
206
+
207
+ ngReadonlyAriaDirective.$inject = ["$aria"];
208
+ export function ngReadonlyAriaDirective($aria) {
209
+ return $aria.$$watchExpr(
210
+ "ngReadonly",
211
+ "aria-readonly",
212
+ nativeAriaNodeNames,
213
+ false,
214
+ );
215
+ }
216
+
217
+ ngModelAriaDirective.$inject = ["$aria"];
218
+ export function ngModelAriaDirective($aria) {
219
+ function shouldAttachAttr(attr, normalizedAttr, elem, allowNonAriaNodes) {
220
+ return (
221
+ $aria.config(normalizedAttr) &&
222
+ !elem.attr(attr) &&
223
+ (allowNonAriaNodes || !isNodeOneOf(elem, nativeAriaNodeNames)) &&
224
+ (elem.attr("type") !== "hidden" || elem[0].nodeName !== "INPUT")
225
+ );
226
+ }
227
+
228
+ function shouldAttachRole(role, elem) {
229
+ // if element does not have role attribute
230
+ // AND element type is equal to role (if custom element has a type equaling shape) <-- remove?
231
+ // AND element is not in nativeAriaNodeNames
232
+ return (
233
+ !elem.attr("role") &&
234
+ elem.attr("type") === role &&
235
+ !isNodeOneOf(elem, nativeAriaNodeNames)
236
+ );
237
+ }
238
+
239
+ function getShape(attr) {
240
+ const { type } = attr;
241
+ const { role } = attr;
242
+
243
+ return (type || role) === "checkbox" || role === "menuitemcheckbox"
244
+ ? "checkbox"
245
+ : (type || role) === "radio" || role === "menuitemradio"
246
+ ? "radio"
247
+ : type === "range" || role === "progressbar" || role === "slider"
248
+ ? "range"
249
+ : "";
250
+ }
251
+
252
+ return {
253
+ restrict: "A",
254
+ require: "ngModel",
255
+ priority: 200, // Make sure watches are fired after any other directives that affect the ngModel value
256
+ compile(elem, attr) {
257
+ if (Object.prototype.hasOwnProperty.call(attr, ARIA_DISABLE_ATTR)) return;
258
+
259
+ const shape = getShape(attr);
260
+
261
+ return {
262
+ post(scope, elem, attr, ngModel) {
263
+ const needsTabIndex = shouldAttachAttr(
264
+ "tabindex",
265
+ "tabindex",
266
+ elem,
267
+ false,
268
+ );
269
+
270
+ function ngAriaWatchModelValue() {
271
+ return ngModel.$modelValue;
272
+ }
273
+
274
+ function getRadioReaction() {
275
+ // Strict comparison would cause a BC
276
+ elem[0].setAttribute(
277
+ "aria-checked",
278
+ (attr.value == ngModel.$viewValue).toString(),
279
+ );
280
+ }
281
+
282
+ function getCheckboxReaction() {
283
+ elem.attr(
284
+ "aria-checked",
285
+ (!ngModel.$isEmpty(ngModel.$viewValue)).toString(),
286
+ );
287
+ }
288
+
289
+ switch (shape) {
290
+ case "radio":
291
+ case "checkbox":
292
+ if (shouldAttachRole(shape, elem)) {
293
+ elem.attr("role", shape);
294
+ }
295
+ if (
296
+ shouldAttachAttr("aria-checked", "ariaChecked", elem, false)
297
+ ) {
298
+ scope.$watch(
299
+ ngAriaWatchModelValue,
300
+ shape === "radio" ? getRadioReaction : getCheckboxReaction,
301
+ );
302
+ }
303
+ if (needsTabIndex) {
304
+ elem.attr("tabindex", 0);
305
+ }
306
+ break;
307
+ case "range":
308
+ if (shouldAttachRole(shape, elem)) {
309
+ elem.attr("role", "slider");
310
+ }
311
+ if ($aria.config("ariaValue")) {
312
+ const needsAriaValuemin =
313
+ !elem.attr("aria-valuemin") &&
314
+ (Object.prototype.hasOwnProperty.call(attr, "min") ||
315
+ Object.prototype.hasOwnProperty.call(attr, "ngMin"));
316
+ const needsAriaValuemax =
317
+ !elem.attr("aria-valuemax") &&
318
+ (Object.prototype.hasOwnProperty.call(attr, "max") ||
319
+ Object.prototype.hasOwnProperty.call(attr, "ngMax"));
320
+ const needsAriaValuenow = !elem.attr("aria-valuenow");
321
+
322
+ if (needsAriaValuemin) {
323
+ attr.$observe("min", (newVal) => {
324
+ elem.attr("aria-valuemin", newVal);
325
+ });
326
+ }
327
+ if (needsAriaValuemax) {
328
+ attr.$observe("max", (newVal) => {
329
+ elem.attr("aria-valuemax", newVal);
330
+ });
331
+ }
332
+ if (needsAriaValuenow) {
333
+ scope.$watch(ngAriaWatchModelValue, (newVal) => {
334
+ elem.attr("aria-valuenow", newVal);
335
+ });
336
+ }
337
+ }
338
+ if (needsTabIndex) {
339
+ elem.attr("tabindex", 0);
340
+ }
341
+ break;
342
+ }
343
+
344
+ if (
345
+ !Object.prototype.hasOwnProperty.call(attr, "ngRequired") &&
346
+ ngModel.$validators.required &&
347
+ shouldAttachAttr("aria-required", "ariaRequired", elem, false)
348
+ ) {
349
+ // ngModel.$error.required is undefined on custom controls
350
+ attr.$observe("required", () => {
351
+ elem.attr("aria-required", (!!attr.required).toString());
352
+ });
353
+ }
354
+
355
+ if (shouldAttachAttr("aria-invalid", "ariaInvalid", elem, true)) {
356
+ scope.$watch(
357
+ () => ngModel.$invalid,
358
+ (newVal) => {
359
+ elem.attr("aria-invalid", (!!newVal).toString());
360
+ },
361
+ );
362
+ }
363
+ },
364
+ };
365
+ },
366
+ };
367
+ }
368
+
369
+ ngDblclickAriaDirective.$inject = ["$aria"];
370
+ export function ngDblclickAriaDirective($aria) {
371
+ return function (scope, elem, attr) {
372
+ if (Object.prototype.hasOwnProperty.call(attr, ARIA_DISABLE_ATTR)) return;
373
+
374
+ if (
375
+ $aria.config("tabindex") &&
376
+ !elem.attr("tabindex") &&
377
+ !isNodeOneOf(elem, nativeAriaNodeNames)
378
+ ) {
379
+ elem.attr("tabindex", 0);
380
+ }
381
+ };
382
+ }
@@ -9,7 +9,7 @@ describe("$aria", () => {
9
9
 
10
10
  beforeEach(() => {
11
11
  window.angular = new Angular();
12
- window.angular.module("test", ["ngAria"]);
12
+ window.angular.module("test", ["ng"]);
13
13
  let injector = createInjector(["test"]);
14
14
  scope = injector.get("$rootScope");
15
15
  $compile = injector.get("$compile");
@@ -340,7 +340,7 @@ describe("$aria", () => {
340
340
  describe("aria-hidden when disabled", () => {
341
341
  beforeEach(() => {
342
342
  window.angular.module("test", [
343
- "ngAria",
343
+ "ng",
344
344
  ($ariaProvider) => {
345
345
  $ariaProvider.config({
346
346
  ariaHidden: false,
@@ -611,7 +611,7 @@ describe("$aria", () => {
611
611
  describe("aria-checked when disabled", () => {
612
612
  beforeEach(() => {
613
613
  window.angular.module("test", [
614
- "ngAria",
614
+ "ng",
615
615
  ($ariaProvider) => {
616
616
  $ariaProvider.config({
617
617
  ariaChecked: false,
@@ -701,7 +701,7 @@ describe("$aria", () => {
701
701
  describe("aria-disabled when disabled", () => {
702
702
  beforeEach(() => {
703
703
  window.angular.module("test", [
704
- "ngAria",
704
+ "ng",
705
705
  ($ariaProvider) => {
706
706
  $ariaProvider.config({
707
707
  ariaDisabled: false,
@@ -772,7 +772,7 @@ describe("$aria", () => {
772
772
  describe("aria-invalid when disabled", () => {
773
773
  beforeEach(() => {
774
774
  window.angular.module("test", [
775
- "ngAria",
775
+ "ng",
776
776
  ($ariaProvider) => {
777
777
  $ariaProvider.config({
778
778
  ariaInvalid: false,
@@ -843,7 +843,7 @@ describe("$aria", () => {
843
843
  describe("aria-readonly when disabled", () => {
844
844
  beforeEach(() => {
845
845
  window.angular.module("test", [
846
- "ngAria",
846
+ "ng",
847
847
  ($ariaProvider) => {
848
848
  $ariaProvider.config({
849
849
  ariaReadonly: false,
@@ -908,7 +908,7 @@ describe("$aria", () => {
908
908
  describe("aria-required when disabled", () => {
909
909
  beforeEach(() => {
910
910
  window.angular.module("test", [
911
- "ngAria",
911
+ "ng",
912
912
  ($ariaProvider) => {
913
913
  $ariaProvider.config({
914
914
  ariaRequired: false,
@@ -1019,7 +1019,7 @@ describe("$aria", () => {
1019
1019
  describe("aria-value when disabled", () => {
1020
1020
  beforeEach(() => {
1021
1021
  window.angular.module("test", [
1022
- "ngAria",
1022
+ "ng",
1023
1023
  ($ariaProvider) => {
1024
1024
  $ariaProvider.config({
1025
1025
  ariaValue: false,
@@ -1126,7 +1126,7 @@ describe("$aria", () => {
1126
1126
  describe("actions when bindRoleForClick is set to false", () => {
1127
1127
  beforeEach(() => {
1128
1128
  window.angular.module("test", [
1129
- "ngAria",
1129
+ "ng",
1130
1130
  ($ariaProvider) => {
1131
1131
  $ariaProvider.config({
1132
1132
  bindRoleForClick: false,
@@ -1149,7 +1149,7 @@ describe("$aria", () => {
1149
1149
  describe("actions when bindKeydown is set to false", () => {
1150
1150
  beforeEach(() => {
1151
1151
  window.angular.module("test", [
1152
- "ngAria",
1152
+ "ng",
1153
1153
  ($ariaProvider) => {
1154
1154
  $ariaProvider.config({
1155
1155
  bindKeydown: false,
@@ -1186,7 +1186,7 @@ describe("$aria", () => {
1186
1186
  describe("tabindex when disabled", () => {
1187
1187
  beforeEach(() => {
1188
1188
  window.angular.module("test", [
1189
- "ngAria",
1189
+ "ng",
1190
1190
  ($ariaProvider) => {
1191
1191
  $ariaProvider.config({
1192
1192
  tabindex: false,
@@ -1216,7 +1216,7 @@ describe("$aria", () => {
1216
1216
  describe("ngModel", () => {
1217
1217
  it("should not break when manually compiling", () => {
1218
1218
  window.angular.module("test", [
1219
- "ngAria",
1219
+ "ng",
1220
1220
  ($compileProvider) => {
1221
1221
  $compileProvider.directive("foo", () => ({
1222
1222
  priority: 10,
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from "@playwright/test";
2
2
 
3
- const TEST_URL = "src/exts/aria/aria.html";
3
+ const TEST_URL = "src/directive/aria/aria.html";
4
4
 
5
5
  test("unit tests contain no errors", async ({ page }) => {
6
6
  await page.goto(TEST_URL);