@igo2/utils 1.15.4 → 16.0.0-rc.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 (50) hide show
  1. package/{esm2020 → esm2022}/igo2-utils.mjs +4 -4
  2. package/esm2022/lib/base64.mjs +85 -0
  3. package/esm2022/lib/cache.utils.mjs +10 -0
  4. package/esm2022/lib/change.interface.mjs +7 -0
  5. package/esm2022/lib/change.mjs +87 -0
  6. package/{esm2020 → esm2022}/lib/clipboard.mjs +52 -52
  7. package/esm2022/lib/dom.utils.mjs +16 -0
  8. package/esm2022/lib/file.mjs +28 -0
  9. package/esm2022/lib/index.mjs +16 -0
  10. package/esm2022/lib/number-utils.mjs +7 -0
  11. package/esm2022/lib/object-utils.mjs +248 -0
  12. package/{esm2020 → esm2022}/lib/strenum.mjs +8 -8
  13. package/{esm2020 → esm2022}/lib/string-utils.mjs +113 -105
  14. package/esm2022/lib/theme.utils.mjs +18 -0
  15. package/{esm2020 → esm2022}/lib/user-agent.mjs +3 -3
  16. package/{esm2020 → esm2022}/lib/uuid.mjs +9 -9
  17. package/esm2022/lib/watcher.mjs +40 -0
  18. package/{esm2020 → esm2022}/public_api.mjs +5 -5
  19. package/{fesm2020 → fesm2022}/igo2-utils.mjs +706 -656
  20. package/fesm2022/igo2-utils.mjs.map +1 -0
  21. package/index.d.ts +5 -5
  22. package/lib/base64.d.ts +8 -8
  23. package/lib/cache.utils.d.ts +1 -0
  24. package/lib/change.d.ts +5 -5
  25. package/lib/change.interface.d.ts +24 -24
  26. package/lib/clipboard.d.ts +7 -7
  27. package/lib/dom.utils.d.ts +4 -0
  28. package/lib/file.d.ts +16 -16
  29. package/lib/index.d.ts +15 -12
  30. package/lib/number-utils.d.ts +3 -3
  31. package/lib/object-utils.d.ts +27 -26
  32. package/lib/strenum.d.ts +4 -4
  33. package/lib/string-utils.d.ts +8 -6
  34. package/lib/theme.utils.d.ts +1 -0
  35. package/lib/user-agent.d.ts +5 -5
  36. package/lib/uuid.d.ts +2 -2
  37. package/lib/watcher.d.ts +19 -19
  38. package/package.json +10 -16
  39. package/public_api.d.ts +1 -1
  40. package/esm2020/lib/base64.mjs +0 -85
  41. package/esm2020/lib/change.interface.mjs +0 -7
  42. package/esm2020/lib/change.mjs +0 -87
  43. package/esm2020/lib/file.mjs +0 -28
  44. package/esm2020/lib/index.mjs +0 -13
  45. package/esm2020/lib/number-utils.mjs +0 -7
  46. package/esm2020/lib/object-utils.mjs +0 -248
  47. package/esm2020/lib/watcher.mjs +0 -41
  48. package/fesm2015/igo2-utils.mjs +0 -688
  49. package/fesm2015/igo2-utils.mjs.map +0 -1
  50. package/fesm2020/igo2-utils.mjs.map +0 -1
@@ -1,688 +1,738 @@
1
+ import { HttpParams } from '@angular/common/http';
1
2
  import * as Bowser from 'bowser';
2
3
  import { Subject } from 'rxjs';
3
4
  import { distinctUntilChanged } from 'rxjs/operators';
4
5
 
5
- /* eslint-disable */
6
- const ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
7
- class Base64 {
8
- static getByte(s, i) {
9
- const x = s.charCodeAt(i);
10
- return x;
11
- }
12
- static getByte64(s, i) {
13
- const idx = this.ALPHA.indexOf(s.charAt(i));
14
- return idx;
15
- }
16
- static decode(s) {
17
- let pads = 0, i, b10, imax = s.length, x = [];
18
- s = String(s);
19
- if (imax === 0) {
20
- return s;
21
- }
22
- if (s.charAt(imax - 1) === this.PADCHAR) {
23
- pads = 1;
24
- if (s.charAt(imax - 2) === this.PADCHAR) {
25
- pads = 2;
26
- }
27
- imax -= 4;
28
- }
29
- for (i = 0; i < imax; i += 4) {
30
- b10 =
31
- (this.getByte64(s, i) << 18) |
32
- (this.getByte64(s, i + 1) << 12) |
33
- (this.getByte64(s, i + 2) << 6) |
34
- this.getByte64(s, i + 3);
35
- x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255, b10 & 255));
36
- }
37
- switch (pads) {
38
- case 1:
39
- b10 =
40
- (this.getByte64(s, i) << 18) |
41
- (this.getByte64(s, i + 1) << 12) |
42
- (this.getByte64(s, i + 2) << 6);
43
- x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255));
44
- break;
45
- case 2:
46
- b10 = (this.getByte64(s, i) << 18) | (this.getByte64(s, i + 1) << 12);
47
- x.push(String.fromCharCode(b10 >> 16));
48
- break;
49
- }
50
- return x.join('');
51
- }
52
- static encode(s) {
53
- s = String(s);
54
- let i, b10, x = [], imax = s.length - s.length % 3;
55
- if (s.length === 0) {
56
- return s;
57
- }
58
- for (i = 0; i < imax; i += 3) {
59
- b10 =
60
- (this.getByte(s, i) << 16) |
61
- (this.getByte(s, i + 1) << 8) |
62
- this.getByte(s, i + 2);
63
- x.push(this.ALPHA.charAt(b10 >> 18));
64
- x.push(this.ALPHA.charAt((b10 >> 12) & 63));
65
- x.push(this.ALPHA.charAt((b10 >> 6) & 63));
66
- x.push(this.ALPHA.charAt(b10 & 63));
67
- }
68
- switch (s.length - imax) {
69
- case 1:
70
- b10 = this.getByte(s, i) << 16;
71
- x.push(this.ALPHA.charAt(b10 >> 18) +
72
- this.ALPHA.charAt((b10 >> 12) & 63) +
73
- this.PADCHAR +
74
- this.PADCHAR);
75
- break;
76
- case 2:
77
- b10 = (this.getByte(s, i) << 16) | (this.getByte(s, i + 1) << 8);
78
- x.push(this.ALPHA.charAt(b10 >> 18) +
79
- this.ALPHA.charAt((b10 >> 12) & 63) +
80
- this.ALPHA.charAt((b10 >> 6) & 63) +
81
- this.PADCHAR);
82
- break;
83
- }
84
- return x.join('');
85
- }
86
- }
87
- Base64.PADCHAR = '=';
88
- Base64.ALPHA = ALPHA;
6
+ /* eslint-disable */
7
+ const ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
8
+ class Base64 {
9
+ static PADCHAR = '=';
10
+ static ALPHA = ALPHA;
11
+ static getByte(s, i) {
12
+ const x = s.charCodeAt(i);
13
+ return x;
14
+ }
15
+ static getByte64(s, i) {
16
+ const idx = this.ALPHA.indexOf(s.charAt(i));
17
+ return idx;
18
+ }
19
+ static decode(s) {
20
+ let pads = 0, i, b10, imax = s.length, x = [];
21
+ s = String(s);
22
+ if (imax === 0) {
23
+ return s;
24
+ }
25
+ if (s.charAt(imax - 1) === this.PADCHAR) {
26
+ pads = 1;
27
+ if (s.charAt(imax - 2) === this.PADCHAR) {
28
+ pads = 2;
29
+ }
30
+ imax -= 4;
31
+ }
32
+ for (i = 0; i < imax; i += 4) {
33
+ b10 =
34
+ (this.getByte64(s, i) << 18) |
35
+ (this.getByte64(s, i + 1) << 12) |
36
+ (this.getByte64(s, i + 2) << 6) |
37
+ this.getByte64(s, i + 3);
38
+ x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255, b10 & 255));
39
+ }
40
+ switch (pads) {
41
+ case 1:
42
+ b10 =
43
+ (this.getByte64(s, i) << 18) |
44
+ (this.getByte64(s, i + 1) << 12) |
45
+ (this.getByte64(s, i + 2) << 6);
46
+ x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255));
47
+ break;
48
+ case 2:
49
+ b10 = (this.getByte64(s, i) << 18) | (this.getByte64(s, i + 1) << 12);
50
+ x.push(String.fromCharCode(b10 >> 16));
51
+ break;
52
+ }
53
+ return x.join('');
54
+ }
55
+ static encode(s) {
56
+ s = String(s);
57
+ let i, b10, x = [], imax = s.length - (s.length % 3);
58
+ if (s.length === 0) {
59
+ return s;
60
+ }
61
+ for (i = 0; i < imax; i += 3) {
62
+ b10 =
63
+ (this.getByte(s, i) << 16) |
64
+ (this.getByte(s, i + 1) << 8) |
65
+ this.getByte(s, i + 2);
66
+ x.push(this.ALPHA.charAt(b10 >> 18));
67
+ x.push(this.ALPHA.charAt((b10 >> 12) & 63));
68
+ x.push(this.ALPHA.charAt((b10 >> 6) & 63));
69
+ x.push(this.ALPHA.charAt(b10 & 63));
70
+ }
71
+ switch (s.length - imax) {
72
+ case 1:
73
+ b10 = this.getByte(s, i) << 16;
74
+ x.push(this.ALPHA.charAt(b10 >> 18) +
75
+ this.ALPHA.charAt((b10 >> 12) & 63) +
76
+ this.PADCHAR +
77
+ this.PADCHAR);
78
+ break;
79
+ case 2:
80
+ b10 = (this.getByte(s, i) << 16) | (this.getByte(s, i + 1) << 8);
81
+ x.push(this.ALPHA.charAt(b10 >> 18) +
82
+ this.ALPHA.charAt((b10 >> 12) & 63) +
83
+ this.ALPHA.charAt((b10 >> 6) & 63) +
84
+ this.PADCHAR);
85
+ break;
86
+ }
87
+ return x.join('');
88
+ }
89
+ }
90
+
91
+ function customCacheHasher(parameters) {
92
+ return parameters.map((param) => {
93
+ if (param instanceof HttpParams) {
94
+ return param.toString();
95
+ }
96
+ return param !== undefined ? JSON.parse(JSON.stringify(param)) : param;
97
+ });
98
+ }
89
99
 
90
100
  const userAgent = Bowser.getParser(window.navigator.userAgent);
91
101
 
92
- class Clipboard {
93
- static copy(element) {
94
- let successful = false;
95
- if (typeof element === 'string') {
96
- const textArea = Clipboard.createTextArea(element);
97
- Clipboard.selectText(textArea);
98
- successful = Clipboard.copyTextToClipboard();
99
- Clipboard.destroyTextArea(textArea);
100
- }
101
- else {
102
- Clipboard.selectText(element);
103
- successful = Clipboard.copyTextToClipboard();
104
- }
105
- return successful;
106
- }
107
- static createTextArea(text) {
108
- const textArea = document.createElement('textArea');
109
- textArea.value = text;
110
- document.body.appendChild(textArea);
111
- return textArea;
112
- }
113
- static destroyTextArea(textArea) {
114
- document.body.removeChild(textArea);
115
- }
116
- static selectText(textArea) {
117
- if (userAgent.getOSName() === 'iOS') {
118
- const oldContentEditable = textArea.contentEditable;
119
- const oldReadOnly = textArea.readOnly;
120
- const range = document.createRange();
121
- const selection = window.getSelection();
122
- textArea.contenteditable = true;
123
- textArea.readonly = false;
124
- range.selectNodeContents(textArea);
125
- selection.removeAllRanges();
126
- selection.addRange(range);
127
- textArea.setSelectionRange(0, 999999);
128
- textArea.contentEditable = oldContentEditable;
129
- textArea.readOnly = oldReadOnly;
130
- }
131
- else {
132
- textArea.select();
133
- }
134
- }
135
- static copyTextToClipboard() {
136
- if (!(userAgent.getOSName() === 'iOS' && userAgent.compareVersion('<10'))) {
137
- return document.execCommand('copy');
138
- }
139
- return false;
140
- }
102
+ class Clipboard {
103
+ static copy(element) {
104
+ let successful = false;
105
+ if (typeof element === 'string') {
106
+ const textArea = Clipboard.createTextArea(element);
107
+ Clipboard.selectText(textArea);
108
+ successful = Clipboard.copyTextToClipboard();
109
+ Clipboard.destroyTextArea(textArea);
110
+ }
111
+ else {
112
+ Clipboard.selectText(element);
113
+ successful = Clipboard.copyTextToClipboard();
114
+ }
115
+ return successful;
116
+ }
117
+ static createTextArea(text) {
118
+ const textArea = document.createElement('textArea');
119
+ textArea.value = text;
120
+ document.body.appendChild(textArea);
121
+ return textArea;
122
+ }
123
+ static destroyTextArea(textArea) {
124
+ document.body.removeChild(textArea);
125
+ }
126
+ static selectText(textArea) {
127
+ if (userAgent.getOSName() === 'iOS') {
128
+ const oldContentEditable = textArea.contentEditable;
129
+ const oldReadOnly = textArea.readOnly;
130
+ const range = document.createRange();
131
+ const selection = window.getSelection();
132
+ textArea.contenteditable = true;
133
+ textArea.readonly = false;
134
+ range.selectNodeContents(textArea);
135
+ selection.removeAllRanges();
136
+ selection.addRange(range);
137
+ textArea.setSelectionRange(0, 999999);
138
+ textArea.contentEditable = oldContentEditable;
139
+ textArea.readOnly = oldReadOnly;
140
+ }
141
+ else {
142
+ textArea.select();
143
+ }
144
+ }
145
+ static copyTextToClipboard() {
146
+ if (!(userAgent.getOSName() === 'iOS' && userAgent.compareVersion('<10'))) {
147
+ return document.execCommand('copy');
148
+ }
149
+ return false;
150
+ }
141
151
  }
142
152
 
143
- class StringUtils {
144
- static diff(s1, s2, p = 4) {
145
- if (!s1 && !s2) {
146
- return '';
147
- }
148
- if (!s1) {
149
- return '<span class="inserted">' + s2 + '</span>';
150
- }
151
- if (!s2) {
152
- return '<span class="deleted">' + s1 + '</span>';
153
- }
154
- s1 = s1.toString();
155
- s2 = s2.toString();
156
- const changeData = StringUtils.getChanges(s1, s2, '', p);
157
- const nextS = s2.slice(changeData.mtc.length + changeData.ins.length + changeData.sbs.length); // remaining part of "s"
158
- const nextThis = s1.slice(changeData.mtc.length + changeData.del.length + changeData.sbs.length); // remaining part of "this"
159
- let result = ''; // the glorious result
160
- if (changeData.del.length > 0) {
161
- changeData.del = '<span class="deleted">' + changeData.del + '</span>';
162
- }
163
- if (changeData.ins.length > 0) {
164
- changeData.ins = '<span class="inserted">' + changeData.ins + '</span>';
165
- }
166
- result = changeData.mtc + changeData.del + changeData.ins + changeData.sbs;
167
- result +=
168
- nextThis !== '' || nextS !== ''
169
- ? StringUtils.diff(nextThis, nextS, p)
170
- : '';
171
- return result;
172
- }
173
- static getMatchingSubstring(s, l, m) {
174
- // returns the first matching substring in-between the two strings
175
- let i = 0;
176
- let match = false;
177
- const slen = s.length;
178
- const o = { fis: slen, mtc: m, sbs: '' }; // temporary object used to construct the cd (change data) object
179
- while (i < slen) {
180
- l[i] === s[i]
181
- ? match
182
- ? (o.sbs += s[i]) // o.sbs holds the matching substring itsef
183
- : ((match = true), (o.fis = i), (o.sbs = s[i]))
184
- : match
185
- ? (i = slen) // stop after the first found substring
186
- : (i = i);
187
- ++i;
188
- }
189
- return o;
190
- }
191
- static getChanges(s1, s2, m, p) {
192
- const isThisLonger = s1.length >= s1.length ? true : false;
193
- let [longer, shorter] = isThisLonger ? [s1, s2] : [s2, s1]; // assignment of longer and shorter by es6 destructuring
194
- let bi = 0; // base index designating the index of first mismacthing character in both strings
195
- while (shorter[bi] === longer[bi] && bi < shorter.length) {
196
- ++bi;
197
- } // make bi the index of first mismatching character
198
- longer = longer.split('').slice(bi); // as the longer string will be rotated it is converted into array
199
- shorter = shorter.slice(bi); // shorter and longer now starts from the first mismatching character
200
- const len = longer.length; // length of the longer string
201
- let cd = {
202
- fis: shorter.length,
203
- fil: len,
204
- sbs: '',
205
- mtc: m + s2.slice(0, bi)
206
- }; // if exists mtc holds the matching string at the front
207
- let sub = { sbs: '' }; // returned substring per 1 character rotation of the longer string
208
- if (shorter !== '') {
209
- for (let rc = 0; rc < len && sub.sbs.length < p; rc++) {
210
- // rc -> rotate count, p -> precision factor
211
- sub = StringUtils.getMatchingSubstring(shorter, StringUtils.rotateArray(longer, rc), cd.mtc); // rotate longer string 1 char and get substring
212
- sub.fil =
213
- rc < len - sub.fis
214
- ? sub.fis + rc // mismatch is longer than the mismatch in short
215
- : sub.fis - len + rc; // mismatch is shorter than the mismatch in short
216
- if (sub.sbs.length > cd.sbs.length) {
217
- cd = sub; // only keep the one with the longest substring.
218
- }
219
- }
220
- }
221
- // insert the mismatching delete subsrt and insert substr to the cd object and attach the previous substring
222
- [cd.del, cd.ins] = isThisLonger
223
- ? [longer.slice(0, cd.fil).join(''), shorter.slice(0, cd.fis)]
224
- : [shorter.slice(0, cd.fis), longer.slice(0, cd.fil).join('')];
225
- return cd.del.indexOf(' ') === -1 ||
226
- cd.ins.indexOf(' ') === -1 ||
227
- cd.del === '' ||
228
- cd.ins === '' ||
229
- cd.sbs === ''
230
- ? cd
231
- : StringUtils.getChanges(cd.del, cd.ins, cd.mtc, p);
232
- }
233
- static rotateArray(array, n) {
234
- const len = array.length;
235
- const res = new Array(array.length);
236
- if (n % len === 0) {
237
- return array.slice();
238
- }
239
- else {
240
- for (let i = 0; i < len; i++) {
241
- res[i] = array[(i + (len + (n % len))) % len];
242
- }
243
- }
244
- return res;
245
- }
153
+ class StringUtils {
154
+ static diff(s1, s2, p = 4) {
155
+ if (!s1 && !s2) {
156
+ return '';
157
+ }
158
+ if (!s1) {
159
+ return '<span class="inserted">' + s2 + '</span>';
160
+ }
161
+ if (!s2) {
162
+ return '<span class="deleted">' + s1 + '</span>';
163
+ }
164
+ s1 = s1.toString();
165
+ s2 = s2.toString();
166
+ const changeData = StringUtils.getChanges(s1, s2, '', p);
167
+ const nextS = s2.slice(changeData.mtc.length + changeData.ins.length + changeData.sbs.length); // remaining part of "s"
168
+ const nextThis = s1.slice(changeData.mtc.length + changeData.del.length + changeData.sbs.length); // remaining part of "this"
169
+ let result = ''; // the glorious result
170
+ if (changeData.del.length > 0) {
171
+ changeData.del = '<span class="deleted">' + changeData.del + '</span>';
172
+ }
173
+ if (changeData.ins.length > 0) {
174
+ changeData.ins = '<span class="inserted">' + changeData.ins + '</span>';
175
+ }
176
+ result = changeData.mtc + changeData.del + changeData.ins + changeData.sbs;
177
+ result +=
178
+ nextThis !== '' || nextS !== ''
179
+ ? StringUtils.diff(nextThis, nextS, p)
180
+ : '';
181
+ return result;
182
+ }
183
+ static getMatchingSubstring(s, l, m) {
184
+ // returns the first matching substring in-between the two strings
185
+ let i = 0;
186
+ let match = false;
187
+ const slen = s.length;
188
+ const o = { fis: slen, mtc: m, sbs: '' }; // temporary object used to construct the cd (change data) object
189
+ while (i < slen) {
190
+ l[i] === s[i]
191
+ ? match
192
+ ? (o.sbs += s[i]) // o.sbs holds the matching substring itsef
193
+ : ((match = true), (o.fis = i), (o.sbs = s[i]))
194
+ : match
195
+ ? (i = slen) // stop after the first found substring
196
+ : (i = i);
197
+ ++i;
198
+ }
199
+ return o;
200
+ }
201
+ static getChanges(s1, s2, m, p) {
202
+ const isThisLonger = s1.length >= s1.length ? true : false;
203
+ let [longer, shorter] = isThisLonger ? [s1, s2] : [s2, s1]; // assignment of longer and shorter by es6 destructuring
204
+ let bi = 0; // base index designating the index of first mismacthing character in both strings
205
+ while (shorter[bi] === longer[bi] && bi < shorter.length) {
206
+ ++bi;
207
+ } // make bi the index of first mismatching character
208
+ longer = longer.split('').slice(bi); // as the longer string will be rotated it is converted into array
209
+ shorter = shorter.slice(bi); // shorter and longer now starts from the first mismatching character
210
+ const len = longer.length; // length of the longer string
211
+ let cd = {
212
+ fis: shorter.length,
213
+ fil: len,
214
+ sbs: '',
215
+ mtc: m + s2.slice(0, bi)
216
+ }; // if exists mtc holds the matching string at the front
217
+ let sub = { sbs: '' }; // returned substring per 1 character rotation of the longer string
218
+ if (shorter !== '') {
219
+ for (let rc = 0; rc < len && sub.sbs.length < p; rc++) {
220
+ // rc -> rotate count, p -> precision factor
221
+ sub = StringUtils.getMatchingSubstring(shorter, StringUtils.rotateArray(longer, rc), cd.mtc); // rotate longer string 1 char and get substring
222
+ sub.fil =
223
+ rc < len - sub.fis
224
+ ? sub.fis + rc // mismatch is longer than the mismatch in short
225
+ : sub.fis - len + rc; // mismatch is shorter than the mismatch in short
226
+ if (sub.sbs.length > cd.sbs.length) {
227
+ cd = sub; // only keep the one with the longest substring.
228
+ }
229
+ }
230
+ }
231
+ // insert the mismatching delete subsrt and insert substr to the cd object and attach the previous substring
232
+ [cd.del, cd.ins] = isThisLonger
233
+ ? [longer.slice(0, cd.fil).join(''), shorter.slice(0, cd.fis)]
234
+ : [shorter.slice(0, cd.fis), longer.slice(0, cd.fil).join('')];
235
+ return cd.del.indexOf(' ') === -1 ||
236
+ cd.ins.indexOf(' ') === -1 ||
237
+ cd.del === '' ||
238
+ cd.ins === '' ||
239
+ cd.sbs === ''
240
+ ? cd
241
+ : StringUtils.getChanges(cd.del, cd.ins, cd.mtc, p);
242
+ }
243
+ static rotateArray(array, n) {
244
+ const len = array.length;
245
+ const res = new Array(array.length);
246
+ if (n % len === 0) {
247
+ return array.slice();
248
+ }
249
+ else {
250
+ for (let i = 0; i < len; i++) {
251
+ res[i] = array[(i + (len + (n % len))) % len];
252
+ }
253
+ }
254
+ return res;
255
+ }
256
+ static isValidNumber(value) {
257
+ return !isNaN(Number(value));
258
+ }
259
+ static isOctalNumber(value) {
260
+ return (StringUtils.isValidNumber(value) &&
261
+ value.startsWith('0') &&
262
+ value.length > 1);
263
+ }
246
264
  }
247
265
 
248
- var ChangeType;
249
- (function (ChangeType) {
250
- ChangeType["ADDED"] = "added";
251
- ChangeType["DELETED"] = "deleted";
252
- ChangeType["MODIFIED"] = "modified";
266
+ var ChangeType;
267
+ (function (ChangeType) {
268
+ ChangeType["ADDED"] = "added";
269
+ ChangeType["DELETED"] = "deleted";
270
+ ChangeType["MODIFIED"] = "modified";
253
271
  })(ChangeType || (ChangeType = {}));
254
272
 
255
- class ChangeUtils {
256
- static findChanges(obj1, obj2, ignoreKeys = []) {
257
- const items = {
258
- added: [],
259
- deleted: [],
260
- modified: []
261
- };
262
- if (!obj1 || !obj2) {
263
- return items;
264
- }
265
- const obj1Clone = [...obj1];
266
- const obj2Clone = [...obj2];
267
- for (const fromItem of obj1Clone) {
268
- const index = obj2Clone.findIndex(s => s.id === fromItem.id);
269
- if (index === -1) {
270
- items.deleted.push({
271
- change: { type: ChangeType.DELETED },
272
- value: fromItem
273
- });
274
- continue;
275
- }
276
- const toItem = obj2Clone.splice(index, 1)[0];
277
- const fromItemClone = JSON.parse(JSON.stringify(fromItem));
278
- const toItemClone = JSON.parse(JSON.stringify(toItem));
279
- const keysChanged = ChangeUtils.compareObject(fromItemClone, toItemClone, undefined, ignoreKeys);
280
- if (keysChanged.length) {
281
- items.modified.push({
282
- change: {
283
- type: ChangeType.MODIFIED,
284
- keysChanged
285
- },
286
- value: fromItemClone,
287
- oldValue: fromItem,
288
- newValue: toItem
289
- });
290
- }
291
- }
292
- items.added = obj2Clone.map(itemAdded => {
293
- return {
294
- change: { type: ChangeType.ADDED },
295
- value: itemAdded
296
- };
297
- });
298
- return items;
299
- }
300
- static compareObject(fromItem, toItem, baseKey, ignoreKeys = []) {
301
- const fromItemClone = JSON.parse(JSON.stringify(fromItem));
302
- const toItemClone = JSON.parse(JSON.stringify(toItem));
303
- const keys = new Set([
304
- ...Object.keys(fromItem),
305
- ...Object.keys(toItem)
306
- ]);
307
- let keysChanged = [];
308
- keys.forEach(key => {
309
- const keyString = baseKey ? `${baseKey}.${key}` : key;
310
- if (ignoreKeys.indexOf(keyString) !== -1) {
311
- return;
312
- }
313
- if (Array.isArray(fromItem[key])) {
314
- fromItem[key] = fromItem[key].join(',<br>');
315
- }
316
- if (Array.isArray(toItem[key])) {
317
- toItem[key] = toItem[key].join(',<br>');
318
- }
319
- if (typeof fromItem[key] === 'object' &&
320
- typeof toItem[key] === 'object' &&
321
- fromItem[key] !== null &&
322
- toItem[key] !== null) {
323
- keysChanged = keysChanged.concat(this.compareObject(fromItem[key], toItem[key], keyString));
324
- }
325
- else {
326
- if (fromItem[key] !== toItem[key]) {
327
- keysChanged.push({
328
- key: keyString,
329
- oldValue: fromItemClone[key],
330
- newValue: toItemClone[key]
331
- });
332
- fromItem[key] = StringUtils.diff(fromItem[key], toItem[key]);
333
- }
334
- }
335
- });
336
- return keysChanged;
337
- }
273
+ class ChangeUtils {
274
+ static findChanges(obj1, obj2, ignoreKeys = []) {
275
+ const items = {
276
+ added: [],
277
+ deleted: [],
278
+ modified: []
279
+ };
280
+ if (!obj1 || !obj2) {
281
+ return items;
282
+ }
283
+ const obj1Clone = [...obj1];
284
+ const obj2Clone = [...obj2];
285
+ for (const fromItem of obj1Clone) {
286
+ const index = obj2Clone.findIndex((s) => s.id === fromItem.id);
287
+ if (index === -1) {
288
+ items.deleted.push({
289
+ change: { type: ChangeType.DELETED },
290
+ value: fromItem
291
+ });
292
+ continue;
293
+ }
294
+ const toItem = obj2Clone.splice(index, 1)[0];
295
+ const fromItemClone = JSON.parse(JSON.stringify(fromItem));
296
+ const toItemClone = JSON.parse(JSON.stringify(toItem));
297
+ const keysChanged = ChangeUtils.compareObject(fromItemClone, toItemClone, undefined, ignoreKeys);
298
+ if (keysChanged.length) {
299
+ items.modified.push({
300
+ change: {
301
+ type: ChangeType.MODIFIED,
302
+ keysChanged
303
+ },
304
+ value: fromItemClone,
305
+ oldValue: fromItem,
306
+ newValue: toItem
307
+ });
308
+ }
309
+ }
310
+ items.added = obj2Clone.map((itemAdded) => {
311
+ return {
312
+ change: { type: ChangeType.ADDED },
313
+ value: itemAdded
314
+ };
315
+ });
316
+ return items;
317
+ }
318
+ static compareObject(fromItem, toItem, baseKey, ignoreKeys = []) {
319
+ const fromItemClone = JSON.parse(JSON.stringify(fromItem));
320
+ const toItemClone = JSON.parse(JSON.stringify(toItem));
321
+ const keys = new Set([
322
+ ...Object.keys(fromItem),
323
+ ...Object.keys(toItem)
324
+ ]);
325
+ let keysChanged = [];
326
+ keys.forEach((key) => {
327
+ const keyString = baseKey ? `${baseKey}.${key}` : key;
328
+ if (ignoreKeys.indexOf(keyString) !== -1) {
329
+ return;
330
+ }
331
+ if (Array.isArray(fromItem[key])) {
332
+ fromItem[key] = fromItem[key].join(',<br>');
333
+ }
334
+ if (Array.isArray(toItem[key])) {
335
+ toItem[key] = toItem[key].join(',<br>');
336
+ }
337
+ if (typeof fromItem[key] === 'object' &&
338
+ typeof toItem[key] === 'object' &&
339
+ fromItem[key] !== null &&
340
+ toItem[key] !== null) {
341
+ keysChanged = keysChanged.concat(this.compareObject(fromItem[key], toItem[key], keyString));
342
+ }
343
+ else {
344
+ if (fromItem[key] !== toItem[key]) {
345
+ keysChanged.push({
346
+ key: keyString,
347
+ oldValue: fromItemClone[key],
348
+ newValue: toItemClone[key]
349
+ });
350
+ fromItem[key] = StringUtils.diff(fromItem[key], toItem[key]);
351
+ }
352
+ }
353
+ });
354
+ return keysChanged;
355
+ }
356
+ }
357
+
358
+ class DomUtils {
359
+ static create(doc, tagName, options) {
360
+ const el = doc.createElement(tagName);
361
+ for (const key in options) {
362
+ el[key] = options[key];
363
+ }
364
+ return el;
365
+ }
366
+ static remove(node) {
367
+ if (!node.parentNode) {
368
+ return;
369
+ }
370
+ node.parentNode.removeChild(node);
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Trigger download of a file
376
+ *
377
+ * @param content File content
378
+ * @param mimeType File mime type
379
+ * @param fileName File name
380
+ */
381
+ function downloadContent(content, mimeType, fileName) {
382
+ const uri = `data:${mimeType},${encodeURIComponent(content)}`;
383
+ downloadFromUri(uri, fileName);
384
+ }
385
+ /**
386
+ * Trigger download of a file
387
+ *
388
+ * @param content File content
389
+ * @param mimeType File mime type
390
+ * @param fileName File name
391
+ */
392
+ function downloadFromUri(uri, fileName) {
393
+ const element = document.createElement('a');
394
+ element.setAttribute('href', uri);
395
+ element.setAttribute('download', fileName);
396
+ element.style.display = 'none';
397
+ document.body.appendChild(element);
398
+ element.click();
399
+ document.body.removeChild(element);
338
400
  }
339
401
 
340
- /**
341
- * Trigger download of a file
342
- *
343
- * @param content File content
344
- * @param mimeType File mime type
345
- * @param fileName File name
346
- */
347
- function downloadContent(content, mimeType, fileName) {
348
- const uri = `data:${mimeType},${encodeURIComponent(content)}`;
349
- downloadFromUri(uri, fileName);
350
- }
351
- /**
352
- * Trigger download of a file
353
- *
354
- * @param content File content
355
- * @param mimeType File mime type
356
- * @param fileName File name
357
- */
358
- function downloadFromUri(uri, fileName) {
359
- const element = document.createElement('a');
360
- element.setAttribute('href', uri);
361
- element.setAttribute('download', fileName);
362
- element.style.display = 'none';
363
- document.body.appendChild(element);
364
- element.click();
365
- document.body.removeChild(element);
402
+ class ObjectUtils {
403
+ static resolve(obj, key) {
404
+ const keysArray = key.replace(/\[/g, '.').replace(/\]/g, '').split('.');
405
+ let current = obj;
406
+ while (keysArray.length) {
407
+ if (typeof current !== 'object') {
408
+ return undefined;
409
+ }
410
+ current = current[keysArray.shift()];
411
+ }
412
+ return current;
413
+ }
414
+ static isObject(item) {
415
+ return (item &&
416
+ typeof item === 'object' &&
417
+ !Array.isArray(item) &&
418
+ item !== null &&
419
+ !(item instanceof Date));
420
+ }
421
+ static mergeDeep(target, source, ignoreUndefined = false) {
422
+ const output = Object.assign({}, target);
423
+ if (ObjectUtils.isObject(target) && ObjectUtils.isObject(source)) {
424
+ Object.keys(source)
425
+ .filter((key) => !ignoreUndefined || source[key] !== undefined)
426
+ .forEach((key) => {
427
+ if (ObjectUtils.isObject(source[key])) {
428
+ if (!(key in target)) {
429
+ Object.assign(output, { [key]: source[key] });
430
+ }
431
+ else {
432
+ output[key] = ObjectUtils.mergeDeep(target[key], source[key], ignoreUndefined);
433
+ }
434
+ }
435
+ else {
436
+ Object.assign(output, { [key]: source[key] });
437
+ }
438
+ });
439
+ }
440
+ return output;
441
+ }
442
+ static copyDeep(src) {
443
+ const target = Array.isArray(src) ? [] : {};
444
+ for (const prop in src) {
445
+ if (src.hasOwnProperty(prop)) {
446
+ const value = src[prop];
447
+ if (value && typeof value === 'object') {
448
+ target[prop] = this.copyDeep(value);
449
+ }
450
+ else {
451
+ target[prop] = value;
452
+ }
453
+ }
454
+ }
455
+ return target;
456
+ }
457
+ static removeDuplicateCaseInsensitive(obj) {
458
+ const summaryCapitalizeObject = {};
459
+ const capitalizeObject = {};
460
+ const upperCaseCount = [];
461
+ for (const property in obj) {
462
+ if (obj.hasOwnProperty(property)) {
463
+ const upperCaseProperty = property.toUpperCase();
464
+ if (!summaryCapitalizeObject.hasOwnProperty(upperCaseProperty)) {
465
+ summaryCapitalizeObject[upperCaseProperty] = [
466
+ { [property]: obj[property] }
467
+ ];
468
+ }
469
+ else {
470
+ summaryCapitalizeObject[upperCaseProperty].push({
471
+ [property]: obj[property]
472
+ });
473
+ }
474
+ // counting the number of uppercase lettersMna
475
+ upperCaseCount.push({
476
+ key: property,
477
+ count: property.replace(/[^A-Z]/g, '').length
478
+ });
479
+ }
480
+ }
481
+ for (const capitalizedProperty in summaryCapitalizeObject) {
482
+ if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {
483
+ if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {
484
+ const capitalizedPropertyObject = summaryCapitalizeObject[capitalizedProperty];
485
+ if (capitalizedPropertyObject.length === 1) {
486
+ // for single params (no duplicates)
487
+ const singlePossibility = capitalizedPropertyObject[0];
488
+ capitalizeObject[capitalizedProperty] =
489
+ singlePossibility[Object.keys(singlePossibility)[0]];
490
+ }
491
+ else if (capitalizedPropertyObject.length > 1) {
492
+ // defining the closest to lowercase property
493
+ const paramClosestToLowercase = upperCaseCount
494
+ .filter((f) => f.key.toLowerCase() === capitalizedProperty.toLowerCase())
495
+ .reduce((prev, current) => {
496
+ return prev.y < current.y ? prev : current;
497
+ });
498
+ capitalizeObject[paramClosestToLowercase.key.toUpperCase()] =
499
+ obj[paramClosestToLowercase.key];
500
+ }
501
+ }
502
+ }
503
+ }
504
+ for (const property in obj) {
505
+ if (obj.hasOwnProperty(property)) {
506
+ delete obj[property];
507
+ }
508
+ }
509
+ for (const property in capitalizeObject) {
510
+ if (capitalizeObject.hasOwnProperty(property)) {
511
+ obj[property] = capitalizeObject[property];
512
+ }
513
+ }
514
+ }
515
+ static removeUndefined(obj) {
516
+ const output = {};
517
+ if (ObjectUtils.isObject(obj)) {
518
+ Object.keys(obj)
519
+ .filter((key) => obj[key] !== undefined)
520
+ .forEach((key) => {
521
+ if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {
522
+ output[key] = ObjectUtils.removeUndefined(obj[key]);
523
+ }
524
+ else {
525
+ output[key] = obj[key];
526
+ }
527
+ });
528
+ return output;
529
+ }
530
+ if (Array.isArray(obj)) {
531
+ return obj.map((o) => ObjectUtils.removeUndefined(o));
532
+ }
533
+ return obj;
534
+ }
535
+ static removeNull(obj) {
536
+ const output = {};
537
+ if (ObjectUtils.isObject(obj)) {
538
+ Object.keys(obj)
539
+ .filter((key) => obj[key] !== null)
540
+ .forEach((key) => {
541
+ if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {
542
+ output[key] = ObjectUtils.removeNull(obj[key]);
543
+ }
544
+ else {
545
+ output[key] = obj[key];
546
+ }
547
+ });
548
+ return output;
549
+ }
550
+ if (Array.isArray(obj)) {
551
+ return obj.map((o) => ObjectUtils.removeNull(o));
552
+ }
553
+ return obj;
554
+ }
555
+ static naturalCompare(a, b, direction = 'asc', nullsFirst) {
556
+ if (direction === 'desc') {
557
+ b = [a, (a = b)][0];
558
+ }
559
+ // nullsFirst = undefined : end if direction = 'asc', first if direction = 'desc'
560
+ // nullsFirst = true : always first
561
+ // nullsFirst = false : always end
562
+ if (a === null ||
563
+ a === '' ||
564
+ a === undefined ||
565
+ b === null ||
566
+ b === '' ||
567
+ b === undefined) {
568
+ const nullScore = a === b
569
+ ? 0
570
+ : a === undefined
571
+ ? 3
572
+ : b === undefined
573
+ ? -3
574
+ : a === null
575
+ ? 2
576
+ : b === null
577
+ ? -2
578
+ : a === ''
579
+ ? 1
580
+ : -1;
581
+ if (direction === 'desc') {
582
+ return nullsFirst !== false ? nullScore : nullScore * -1;
583
+ }
584
+ return nullsFirst === true ? nullScore * -1 : nullScore;
585
+ }
586
+ const ax = [];
587
+ const bx = [];
588
+ a = '' + a;
589
+ b = '' + b;
590
+ a.replace(/(\d+)|(\D+)/g, (_, $1, $2) => {
591
+ ax.push([$1 || Infinity, $2 || '']);
592
+ });
593
+ b.replace(/(\d+)|(\D+)/g, (_, $1, $2) => {
594
+ bx.push([$1 || Infinity, $2 || '']);
595
+ });
596
+ while (ax.length && bx.length) {
597
+ const an = ax.shift();
598
+ const bn = bx.shift();
599
+ const nn = an[0] - bn[0] || an[1].localeCompare(bn[1]);
600
+ if (nn) {
601
+ return nn;
602
+ }
603
+ }
604
+ return ax.length - bx.length;
605
+ }
606
+ /**
607
+ * Return true if two object are equivalent.
608
+ * Objects are considered equivalent if they have the same properties and
609
+ * if all of their properties (first-level only) share the same value.
610
+ * @param obj1 First object
611
+ * @param obj2 Second object
612
+ * @returns Whether two objects arer equivalent
613
+ */
614
+ static objectsAreEquivalent(obj1, obj2) {
615
+ if (obj1 === obj2) {
616
+ return true;
617
+ }
618
+ const obj1Props = Object.getOwnPropertyNames(obj1);
619
+ const obj2Props = Object.getOwnPropertyNames(obj2);
620
+ if (obj1Props.length !== obj2Props.length) {
621
+ return false;
622
+ }
623
+ for (const prop of obj1Props) {
624
+ if (obj1[prop] !== obj2[prop]) {
625
+ return false;
626
+ }
627
+ }
628
+ return true;
629
+ }
630
+ /**
631
+ * Return a new object with an array of keys removed
632
+ * @param obj Source object
633
+ * @param keys Keys to remove
634
+ * @returns A new object
635
+ */
636
+ static removeKeys(obj, keys) {
637
+ const newObj = Object.keys(obj)
638
+ .filter((key) => keys.indexOf(key) < 0)
639
+ .reduce((_obj, key) => {
640
+ _obj[key] = obj[key];
641
+ return _obj;
642
+ }, {});
643
+ return newObj;
644
+ }
645
+ static isEmpty(obj) {
646
+ return Object.keys(obj).length === 0;
647
+ }
366
648
  }
367
649
 
368
- class ObjectUtils {
369
- static resolve(obj, key) {
370
- const keysArray = key
371
- .replace(/\[/g, '.')
372
- .replace(/\]/g, '')
373
- .split('.');
374
- let current = obj;
375
- while (keysArray.length) {
376
- if (typeof current !== 'object') {
377
- return undefined;
378
- }
379
- current = current[keysArray.shift()];
380
- }
381
- return current;
382
- }
383
- static isObject(item) {
384
- return (item &&
385
- typeof item === 'object' &&
386
- !Array.isArray(item) &&
387
- item !== null &&
388
- !(item instanceof Date));
389
- }
390
- static mergeDeep(target, source, ignoreUndefined = false) {
391
- const output = Object.assign({}, target);
392
- if (ObjectUtils.isObject(target) && ObjectUtils.isObject(source)) {
393
- Object.keys(source)
394
- .filter(key => !ignoreUndefined || source[key] !== undefined)
395
- .forEach(key => {
396
- if (ObjectUtils.isObject(source[key])) {
397
- if (!(key in target)) {
398
- Object.assign(output, { [key]: source[key] });
399
- }
400
- else {
401
- output[key] = ObjectUtils.mergeDeep(target[key], source[key], ignoreUndefined);
402
- }
403
- }
404
- else {
405
- Object.assign(output, { [key]: source[key] });
406
- }
407
- });
408
- }
409
- return output;
410
- }
411
- static copyDeep(src) {
412
- const target = Array.isArray(src) ? [] : {};
413
- for (const prop in src) {
414
- if (src.hasOwnProperty(prop)) {
415
- const value = src[prop];
416
- if (value && typeof value === 'object') {
417
- target[prop] = this.copyDeep(value);
418
- }
419
- else {
420
- target[prop] = value;
421
- }
422
- }
423
- }
424
- return target;
425
- }
426
- static removeDuplicateCaseInsensitive(obj) {
427
- const summaryCapitalizeObject = {};
428
- const capitalizeObject = {};
429
- const upperCaseCount = [];
430
- for (const property in obj) {
431
- if (obj.hasOwnProperty(property)) {
432
- const upperCaseProperty = property.toUpperCase();
433
- if (!summaryCapitalizeObject.hasOwnProperty(upperCaseProperty)) {
434
- summaryCapitalizeObject[upperCaseProperty] = [
435
- { [property]: obj[property] }
436
- ];
437
- }
438
- else {
439
- summaryCapitalizeObject[upperCaseProperty].push({
440
- [property]: obj[property]
441
- });
442
- }
443
- // counting the number of uppercase lettersMna
444
- upperCaseCount.push({
445
- key: property,
446
- count: property.replace(/[^A-Z]/g, '').length
447
- });
448
- }
449
- }
450
- for (const capitalizedProperty in summaryCapitalizeObject) {
451
- if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {
452
- if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {
453
- const capitalizedPropertyObject = summaryCapitalizeObject[capitalizedProperty];
454
- if (capitalizedPropertyObject.length === 1) {
455
- // for single params (no duplicates)
456
- const singlePossibility = capitalizedPropertyObject[0];
457
- capitalizeObject[capitalizedProperty] =
458
- singlePossibility[Object.keys(singlePossibility)[0]];
459
- }
460
- else if (capitalizedPropertyObject.length > 1) {
461
- // defining the closest to lowercase property
462
- const paramClosestToLowercase = upperCaseCount
463
- .filter(f => f.key.toLowerCase() === capitalizedProperty.toLowerCase())
464
- .reduce((prev, current) => {
465
- return prev.y < current.y ? prev : current;
466
- });
467
- capitalizeObject[paramClosestToLowercase.key.toUpperCase()] =
468
- obj[paramClosestToLowercase.key];
469
- }
470
- }
471
- }
472
- }
473
- for (const property in obj) {
474
- if (obj.hasOwnProperty(property)) {
475
- delete obj[property];
476
- }
477
- }
478
- for (const property in capitalizeObject) {
479
- if (capitalizeObject.hasOwnProperty(property)) {
480
- obj[property] = capitalizeObject[property];
481
- }
482
- }
483
- }
484
- static removeUndefined(obj) {
485
- const output = {};
486
- if (ObjectUtils.isObject(obj)) {
487
- Object.keys(obj)
488
- .filter(key => obj[key] !== undefined)
489
- .forEach(key => {
490
- if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {
491
- output[key] = ObjectUtils.removeUndefined(obj[key]);
492
- }
493
- else {
494
- output[key] = obj[key];
495
- }
496
- });
497
- return output;
498
- }
499
- if (Array.isArray(obj)) {
500
- return obj.map(o => ObjectUtils.removeUndefined(o));
501
- }
502
- return obj;
503
- }
504
- static removeNull(obj) {
505
- const output = {};
506
- if (ObjectUtils.isObject(obj)) {
507
- Object.keys(obj)
508
- .filter(key => obj[key] !== null)
509
- .forEach(key => {
510
- if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {
511
- output[key] = ObjectUtils.removeNull(obj[key]);
512
- }
513
- else {
514
- output[key] = obj[key];
515
- }
516
- });
517
- return output;
518
- }
519
- if (Array.isArray(obj)) {
520
- return obj.map(o => ObjectUtils.removeNull(o));
521
- }
522
- return obj;
523
- }
524
- static naturalCompare(a, b, direction = 'asc', nullsFirst) {
525
- if (direction === 'desc') {
526
- b = [a, (a = b)][0];
527
- }
528
- // nullsFirst = undefined : end if direction = 'asc', first if direction = 'desc'
529
- // nullsFirst = true : always first
530
- // nullsFirst = false : always end
531
- if (a === null ||
532
- a === '' ||
533
- a === undefined ||
534
- b === null ||
535
- b === '' ||
536
- b === undefined) {
537
- const nullScore = a === b
538
- ? 0
539
- : a === undefined
540
- ? 3
541
- : b === undefined
542
- ? -3
543
- : a === null
544
- ? 2
545
- : b === null
546
- ? -2
547
- : a === ''
548
- ? 1
549
- : -1;
550
- if (direction === 'desc') {
551
- return nullsFirst !== false ? nullScore : nullScore * -1;
552
- }
553
- return nullsFirst === true ? nullScore * -1 : nullScore;
554
- }
555
- const ax = [];
556
- const bx = [];
557
- a = '' + a;
558
- b = '' + b;
559
- a.replace(/(\d+)|(\D+)/g, (_, $1, $2) => {
560
- ax.push([$1 || Infinity, $2 || '']);
561
- });
562
- b.replace(/(\d+)|(\D+)/g, (_, $1, $2) => {
563
- bx.push([$1 || Infinity, $2 || '']);
564
- });
565
- while (ax.length && bx.length) {
566
- const an = ax.shift();
567
- const bn = bx.shift();
568
- const nn = an[0] - bn[0] || an[1].localeCompare(bn[1]);
569
- if (nn) {
570
- return nn;
571
- }
572
- }
573
- return ax.length - bx.length;
574
- }
575
- /**
576
- * Return true if two object are equivalent.
577
- * Objects are considered equivalent if they have the same properties and
578
- * if all of their properties (first-level only) share the same value.
579
- * @param obj1 First object
580
- * @param obj2 Second object
581
- * @returns Whether two objects arer equivalent
582
- */
583
- static objectsAreEquivalent(obj1, obj2) {
584
- if (obj1 === obj2) {
585
- return true;
586
- }
587
- const obj1Props = Object.getOwnPropertyNames(obj1);
588
- const obj2Props = Object.getOwnPropertyNames(obj2);
589
- if (obj1Props.length !== obj2Props.length) {
590
- return false;
591
- }
592
- for (const prop of obj1Props) {
593
- if (obj1[prop] !== obj2[prop]) {
594
- return false;
595
- }
596
- }
597
- return true;
598
- }
599
- /**
600
- * Return a new object with an array of keys removed
601
- * @param obj Source object
602
- * @param keys Keys to remove
603
- * @returns A new object
604
- */
605
- static removeKeys(obj, keys) {
606
- const newObj = Object.keys(obj)
607
- .filter(key => keys.indexOf(key) < 0)
608
- .reduce((_obj, key) => {
609
- _obj[key] = obj[key];
610
- return _obj;
611
- }, {});
612
- return newObj;
613
- }
650
+ class NumberUtils {
651
+ static roundToNDecimal(num, decimal = 3) {
652
+ const roundFactor = Math.pow(10, decimal);
653
+ return Math.round(num * roundFactor) / roundFactor;
654
+ }
614
655
  }
615
656
 
616
- class NumberUtils {
617
- static roundToNDecimal(num, decimal = 3) {
618
- const roundFactor = Math.pow(10, decimal);
619
- return Math.round((num) * roundFactor) / roundFactor;
620
- }
657
+ /** Utility function to create a K:V from a list of strings */
658
+ function strEnum(o) {
659
+ return o.reduce((res, key) => {
660
+ res[key] = key;
661
+ return res;
662
+ }, Object.create(null));
621
663
  }
622
664
 
623
- /** Utility function to create a K:V from a list of strings */
624
- function strEnum(o) {
625
- return o.reduce((res, key) => {
626
- res[key] = key;
627
- return res;
628
- }, Object.create(null));
665
+ const PATH_PREBUILT_THEMES = 'assets/igo2/core/theming/prebuilt-themes';
666
+ const LINK_ID = 'theme-styles';
667
+ function loadTheme(doc, themeName, path = PATH_PREBUILT_THEMES) {
668
+ const src = `${path}/${themeName}.css`;
669
+ const head = doc.getElementsByTagName('head')[0];
670
+ let themeLink = doc.getElementById(LINK_ID);
671
+ themeLink ? (themeLink.href = src) : createHtmlLink(doc, src, head);
672
+ }
673
+ function createHtmlLink(doc, src, parent) {
674
+ const element = DomUtils.create(doc, 'link', {
675
+ id: LINK_ID,
676
+ rel: 'stylesheet',
677
+ href: src
678
+ });
679
+ parent.appendChild(element);
629
680
  }
630
681
 
631
- function S4() {
632
- // eslint-disable-next-line no-bitwise
633
- return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
634
- }
635
- function uuid() {
636
- const id = `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
637
- return id.toLowerCase();
682
+ function S4() {
683
+ // eslint-disable-next-line no-bitwise
684
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
685
+ }
686
+ function uuid() {
687
+ const id = `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
688
+ return id.toLowerCase();
638
689
  }
639
690
 
640
- var SubjectStatus;
641
- (function (SubjectStatus) {
642
- SubjectStatus[SubjectStatus["Error"] = 0] = "Error";
643
- SubjectStatus[SubjectStatus["Done"] = 1] = "Done";
644
- SubjectStatus[SubjectStatus["Working"] = 2] = "Working";
645
- SubjectStatus[SubjectStatus["Waiting"] = 3] = "Waiting";
646
- })(SubjectStatus || (SubjectStatus = {}));
647
- class Watcher {
648
- constructor() {
649
- this.status$ = new Subject();
650
- }
651
- get status() {
652
- return this._status;
653
- }
654
- set status(value) {
655
- this._status = value;
656
- this.status$.next(value);
657
- }
658
- // eslint-disable-next-line @typescript-eslint/ban-types
659
- subscribe(callback, scope) {
660
- this.watch();
661
- this.status$$ = this.status$
662
- .pipe(distinctUntilChanged())
663
- .subscribe((status) => {
664
- this.handleStatusChange(status);
665
- callback.call(scope, this);
666
- });
667
- }
668
- unsubscribe() {
669
- this.unwatch();
670
- if (this.status$$ !== undefined) {
671
- this.status$$.unsubscribe();
672
- this.status$$ = undefined;
673
- }
674
- this.status = SubjectStatus.Waiting;
675
- }
676
- handleStatusChange(status) { }
691
+ var SubjectStatus;
692
+ (function (SubjectStatus) {
693
+ SubjectStatus[SubjectStatus["Error"] = 0] = "Error";
694
+ SubjectStatus[SubjectStatus["Done"] = 1] = "Done";
695
+ SubjectStatus[SubjectStatus["Working"] = 2] = "Working";
696
+ SubjectStatus[SubjectStatus["Waiting"] = 3] = "Waiting";
697
+ })(SubjectStatus || (SubjectStatus = {}));
698
+ class Watcher {
699
+ status$ = new Subject();
700
+ status$$;
701
+ get status() {
702
+ return this._status;
703
+ }
704
+ set status(value) {
705
+ this._status = value;
706
+ this.status$.next(value);
707
+ }
708
+ _status;
709
+ subscribe(callback, scope) {
710
+ this.watch();
711
+ this.status$$ = this.status$
712
+ .pipe(distinctUntilChanged())
713
+ .subscribe((status) => {
714
+ this.handleStatusChange(status);
715
+ callback.call(scope, this);
716
+ });
717
+ }
718
+ unsubscribe() {
719
+ this.unwatch();
720
+ if (this.status$$ !== undefined) {
721
+ this.status$$.unsubscribe();
722
+ this.status$$ = undefined;
723
+ }
724
+ this.status = SubjectStatus.Waiting;
725
+ }
726
+ handleStatusChange(status) { }
677
727
  }
678
728
 
679
- /*
680
- * Public API Surface of utils
729
+ /*
730
+ * Public API Surface of utils
681
731
  */
682
732
 
683
- /**
684
- * Generated bundle index. Do not edit.
733
+ /**
734
+ * Generated bundle index. Do not edit.
685
735
  */
686
736
 
687
- export { Base64, ChangeType, ChangeUtils, Clipboard, NumberUtils, ObjectUtils, S4, StringUtils, SubjectStatus, Watcher, downloadContent, downloadFromUri, strEnum, userAgent, uuid };
737
+ export { Base64, ChangeType, ChangeUtils, Clipboard, DomUtils, NumberUtils, ObjectUtils, S4, StringUtils, SubjectStatus, Watcher, customCacheHasher, downloadContent, downloadFromUri, loadTheme, strEnum, userAgent, uuid };
688
738
  //# sourceMappingURL=igo2-utils.mjs.map