neo.mjs 6.7.8 → 6.8.1

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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.7.8'
23
+ * @member {String} version='6.8.1'
24
24
  */
25
- version: '6.7.8'
25
+ version: '6.8.1'
26
26
  }
27
27
 
28
28
  /**
@@ -19,7 +19,7 @@ class Page2 extends FormPageContainer {
19
19
  module : DateField,
20
20
  labelText: 'Birthday',
21
21
  name : 'birthday',
22
- style : {marginBottom: '800px', marginTop: '800px'}
22
+ style : {marginBottom: '2000px', marginTop: '800px'}
23
23
  }]
24
24
  }
25
25
  }
@@ -3,7 +3,6 @@ import path from 'path';
3
3
  import webpack from 'webpack';
4
4
 
5
5
  const cwd = process.cwd(),
6
- configPath = path.resolve(cwd, 'buildScripts/myApps.json'),
7
6
  requireJson = path => JSON.parse(fs.readFileSync((path))),
8
7
  packageJson = requireJson(path.resolve(cwd, 'package.json')),
9
8
  neoPath = packageJson.name === 'neo.mjs' ? './' : './node_modules/neo.mjs/',
@@ -13,26 +12,16 @@ const cwd = process.cwd(),
13
12
  regexIndexNodeModules = /node_modules/g,
14
13
  regexTopLevel = /\.\.\//g;
15
14
 
16
- let config, examplesPath;
17
-
18
- if (fs.existsSync(configPath)) {
19
- config = requireJson(configPath);
20
- } else {
21
- const myAppsPath = path.resolve(neoPath, 'buildScripts/webpack/json/myApps.json');
22
-
23
- if (fs.existsSync(myAppsPath)) {
24
- config = requireJson(myAppsPath);
25
- } else {
26
- config = requireJson(path.resolve(neoPath, 'buildScripts/webpack/json/myApps.template.json'));
27
- }
28
- }
15
+ let contextAdjusted = false,
16
+ examplesPath;
29
17
 
30
18
  if (!buildTarget.folder) {
31
19
  buildTarget.folder = 'dist/development';
32
20
  }
33
21
 
34
22
  export default env => {
35
- let examples = [],
23
+ let apps = [],
24
+ examples = [],
36
25
  insideNeo = env.insideNeo == 'true',
37
26
  content, inputPath, outputPath;
38
27
 
@@ -88,7 +77,7 @@ export default env => {
88
77
 
89
78
  const isFile = fileName => fs.lstatSync(fileName).isFile();
90
79
 
91
- const parseFolder = (folderPath, index, relativePath) => {
80
+ const parseFolder = (apps, folderPath, index, relativePath) => {
92
81
  let itemPath;
93
82
 
94
83
  fs.readdirSync(folderPath).forEach(itemName => {
@@ -96,22 +85,26 @@ export default env => {
96
85
 
97
86
  if (isFile(itemPath)) {
98
87
  if (itemName === 'app.mjs') {
99
- examples.push(relativePath);
88
+ apps.push(relativePath);
100
89
  }
101
90
  } else {
102
- parseFolder(itemPath, index + 1, relativePath + `/${itemName}`);
91
+ parseFolder(apps, itemPath, index + 1, relativePath + `/${itemName}`);
103
92
  }
104
93
  });
105
94
  };
106
95
 
107
- config.apps?.forEach(key => {
108
- createStartingPoint(key, key === 'Docs' ? '' : 'apps');
96
+ parseFolder(apps, path.join(cwd, 'apps'), 0, '');
97
+
98
+ apps.forEach(key => {
99
+ createStartingPoint(key.substr(1), 'apps');
109
100
  });
110
101
 
102
+ createStartingPoint('Docs', '');
103
+
111
104
  examplesPath = path.join(cwd, 'examples');
112
105
 
113
106
  if (fs.existsSync(examplesPath)) {
114
- parseFolder(examplesPath, 0, '');
107
+ parseFolder(examples, examplesPath, 0, '');
115
108
 
116
109
  examples.forEach(key => {
117
110
  createStartingPoint(key.substr(1), 'examples');
@@ -130,8 +123,11 @@ export default env => {
130
123
 
131
124
  plugins: [
132
125
  new webpack.ContextReplacementPlugin(/.*/, context => {
133
- if (!insideNeo && context.context.includes('/src/worker')) {
134
- context.request = '../../' + context.request;
126
+ let con = context.context;
127
+
128
+ if (!insideNeo && !contextAdjusted && (con.includes('/src/worker') || con.includes('\\src\\worker'))) {
129
+ context.request = path.join('../../', context.request);
130
+ contextAdjusted = true;
135
131
  }
136
132
  }),
137
133
  ...plugins
@@ -7,12 +7,7 @@
7
7
  "RealWorld",
8
8
  "RealWorld2",
9
9
  "SharedCovid",
10
- "SharedCovidChart",
11
- "SharedCovidGallery",
12
- "SharedCovidHelix",
13
- "SharedCovidMap",
14
10
  "SharedDialog",
15
- "SharedDialog2",
16
11
  "Website"
17
12
  ]
18
13
  }
@@ -3,7 +3,6 @@ import path from 'path';
3
3
  import webpack from 'webpack';
4
4
 
5
5
  const cwd = process.cwd(),
6
- configPath = path.resolve(cwd, 'buildScripts/myApps.json'),
7
6
  requireJson = path => JSON.parse(fs.readFileSync((path))),
8
7
  packageJson = requireJson(path.resolve(cwd, 'package.json')),
9
8
  neoPath = packageJson.name === 'neo.mjs' ? './' : './node_modules/neo.mjs/',
@@ -17,26 +16,15 @@ const cwd = process.cwd(),
17
16
  regexTrimStart = /^\s+/gm;
18
17
 
19
18
  let contextAdjusted = false,
20
- config, examplesPath;
21
-
22
- if (fs.existsSync(configPath)) {
23
- config = requireJson(configPath);
24
- } else {
25
- const myAppsPath = path.resolve(neoPath, 'buildScripts/webpack/json/myApps.json');
26
-
27
- if (fs.existsSync(myAppsPath)) {
28
- config = requireJson(myAppsPath);
29
- } else {
30
- config = requireJson(path.resolve(neoPath, 'buildScripts/webpack/json/myApps.template.json'));
31
- }
32
- }
19
+ examplesPath;
33
20
 
34
21
  if (!buildTarget.folder) {
35
22
  buildTarget.folder = 'dist/production';
36
23
  }
37
24
 
38
25
  export default env => {
39
- let examples = [],
26
+ let apps = [],
27
+ examples = [],
40
28
  insideNeo = env.insideNeo == 'true',
41
29
  content, inputPath, outputPath;
42
30
 
@@ -98,7 +86,7 @@ export default env => {
98
86
 
99
87
  const isFile = fileName => fs.lstatSync(fileName).isFile();
100
88
 
101
- const parseFolder = (folderPath, index, relativePath) => {
89
+ const parseFolder = (apps, folderPath, index, relativePath) => {
102
90
  let itemPath;
103
91
 
104
92
  fs.readdirSync(folderPath).forEach(itemName => {
@@ -106,22 +94,26 @@ export default env => {
106
94
 
107
95
  if (isFile(itemPath)) {
108
96
  if (itemName === 'app.mjs') {
109
- examples.push(relativePath);
97
+ apps.push(relativePath);
110
98
  }
111
99
  } else {
112
- parseFolder(itemPath, index + 1, relativePath + `/${itemName}`);
100
+ parseFolder(apps, itemPath, index + 1, relativePath + `/${itemName}`);
113
101
  }
114
102
  });
115
103
  };
116
104
 
117
- config.apps?.forEach(key => {
118
- createStartingPoint(key, key === 'Docs' ? '' : 'apps');
105
+ parseFolder(apps, path.join(cwd, 'apps'), 0, '');
106
+
107
+ apps.forEach(key => {
108
+ createStartingPoint(key.substr(1), 'apps');
119
109
  });
120
110
 
111
+ createStartingPoint('Docs', '');
112
+
121
113
  examplesPath = path.join(cwd, 'examples');
122
114
 
123
115
  if (fs.existsSync(examplesPath)) {
124
- parseFolder(examplesPath, 0, '');
116
+ parseFolder(examples, examplesPath, 0, '');
125
117
 
126
118
  examples.forEach(key => {
127
119
  createStartingPoint(key.substr(1), 'examples');
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='6.7.8'
23
+ * @member {String} version='6.8.1'
24
24
  */
25
- version: '6.7.8'
25
+ version: '6.8.1'
26
26
  }
27
27
 
28
28
  /**
@@ -132,6 +132,7 @@ class DemoDialog extends Dialog {
132
132
  index : nextIndex,
133
133
  listeners : {close: me.onWindowClose, scope: me},
134
134
  modal : me.app.mainView.down({valueLabelText: 'Modal'}).checked,
135
+ trapFocus : true,
135
136
  optionalAnimateTargetId: button.id,
136
137
  style : {left: me.getOffset(), top: me.getOffset()},
137
138
  title : 'Dialog ' + nextIndex
@@ -90,6 +90,7 @@ class MainContainer extends Viewport {
90
90
  boundaryContainerId : me.boundaryContainerId,
91
91
  listeners : {close: me.onWindowClose, scope: me},
92
92
  modal : me.down({valueLabelText: 'Modal'}).checked,
93
+ trapFocus : true,
93
94
  optionalAnimateTargetId: data.component.id,
94
95
  title : 'Dialog 1'
95
96
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "6.7.8",
3
+ "version": "6.8.1",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -14,7 +14,6 @@
14
14
  "add-config": "node ./buildScripts/addConfig.mjs",
15
15
  "build-all": "node ./buildScripts/buildAll.mjs -f -n",
16
16
  "build-all-questions": "node ./buildScripts/buildAll.mjs -f",
17
- "build-my-apps": "node ./buildScripts/webpack/buildMyApps.mjs -f",
18
17
  "build-themes": "node ./buildScripts/buildThemes.mjs -f",
19
18
  "build-threads": "node ./buildScripts/webpack/buildThreads.mjs -f",
20
19
  "create-app": "node ./buildScripts/createApp.mjs",
@@ -61,6 +61,12 @@
61
61
  }
62
62
  }
63
63
 
64
+ &.neo-centered {
65
+ left : 50%;
66
+ top : 50%;
67
+ transform : translate(-50%, -50%);
68
+ }
69
+
64
70
  &.neo-panel {
65
71
  .neo-footer-toolbar {
66
72
  border : none;
@@ -103,3 +109,9 @@
103
109
  }
104
110
  }
105
111
  }
112
+
113
+ // A focusable, but zero-sized element used to grab and redirect focus in focus-trapped modals
114
+ .neo-focus-trap {
115
+ position : absolute;
116
+ clip : rect(0, 0, 0, 0);
117
+ }
@@ -1,6 +1,6 @@
1
1
  .neo-switchfield {
2
2
  .neo-switchfield-input {
3
- background-color: var(--switchfield-color-off-idle);
3
+ background-color: var(--switchfield-color-off);
4
4
  border-radius : 999px;
5
5
  height : var(--switchfield-height);
6
6
  margin : 0;
@@ -20,32 +20,33 @@
20
20
  background-color: var(--switchfield-color-knob);
21
21
  border-radius : 50%;
22
22
  height : var(--switchfield-knobsize);
23
- left : 0;
24
- top : 1.5px;
23
+ left : 2px;
24
+ top : 2px;
25
25
  transition : transform 150ms ease-out;
26
26
  width : var(--switchfield-knobsize);
27
27
  }
28
28
 
29
29
  &:after {
30
- border : 1px solid var(--switchfield-color-knob);
30
+ border : 1px solid var(--switchfield-color-icon-off);
31
31
  border-radius: 50%;
32
- bottom : 7px;
33
- height : 8px;
34
- right : 7px;
35
- width : 8px;
32
+ bottom : 8px;
33
+ height : 6px;
34
+ right : 5px;
35
+ width : 6px;
36
36
  }
37
37
 
38
38
  &:checked {
39
- background-color: var(--switchfield-color-on-idle);
39
+ background-color: var(--switchfield-color-on);
40
40
 
41
41
  &:before {
42
- transform: translateX(100%);
42
+ transform: translateX(80%);
43
43
  }
44
44
 
45
45
  &:after {
46
- background-color: var(--switchfield-color-knob);
46
+ background-color: var(--switchfield-color-icon-on);
47
47
  border : 0;
48
- bottom : 8px;
48
+ border-radius : 0;
49
+ height : 8px;
49
50
  left : 9px;
50
51
  right : auto;
51
52
  width : 1px;
@@ -2,12 +2,14 @@
2
2
  --switchfield-bordercolor-focused: #57B2EF;
3
3
  --switchfield-borderwidth-focused: 4px;
4
4
  --switchfield-color-knob : #fff;
5
+ --switchfield-color-icon-on : #fff;
6
+ --switchfield-color-icon-off : #767676;
7
+ --switchfield-color-off : #BDBDBD;
5
8
  --switchfield-color-off-disabled : #BDBDBD;
6
9
  --switchfield-color-off-hovered : #9E9E9E;
7
- --switchfield-color-off-idle : #BDBDBD;
10
+ --switchfield-color-on : #005A96;
8
11
  --switchfield-color-on-disabled : #005A96;
9
12
  --switchfield-color-on-hovered : #004C7E;
10
- --switchfield-color-on-idle : #005A96;
11
13
  --switchfield-height : 24px;
12
14
  --switchfield-knobsize : 20px;
13
15
  --switchfield-opacity-disabled : .5;
@@ -2,12 +2,14 @@
2
2
  --switchfield-bordercolor-focused: #57B2EF;
3
3
  --switchfield-borderwidth-focused: 4px;
4
4
  --switchfield-color-knob : #fff;
5
+ --switchfield-color-icon-on : #fff;
6
+ --switchfield-color-icon-off : #767676;
7
+ --switchfield-color-off : #BDBDBD;
5
8
  --switchfield-color-off-disabled : #BDBDBD;
6
9
  --switchfield-color-off-hovered : #9E9E9E;
7
- --switchfield-color-off-idle : #BDBDBD;
10
+ --switchfield-color-on : #005A96;
8
11
  --switchfield-color-on-disabled : #005A96;
9
12
  --switchfield-color-on-hovered : #004C7E;
10
- --switchfield-color-on-idle : #005A96;
11
13
  --switchfield-height : 24px;
12
14
  --switchfield-knobsize : 20px;
13
15
  --switchfield-opacity-disabled : .5;
@@ -236,12 +236,12 @@ const DefaultConfig = {
236
236
  useVdomWorker: true,
237
237
  /**
238
238
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '6.7.8'
239
+ * @default '6.8.1'
240
240
  * @memberOf! module:Neo
241
241
  * @name config.version
242
242
  * @type String
243
243
  */
244
- version: '6.7.8'
244
+ version: '6.8.1'
245
245
  };
246
246
 
247
247
  Object.assign(DefaultConfig, {
@@ -610,13 +610,16 @@ class Base extends CoreBase {
610
610
  * @protected
611
611
  */
612
612
  afterSetHidden(value, oldValue) {
613
- let me = this;
613
+ let me = this,
614
+ state = value ? 'hide' : 'show';
614
615
 
615
616
  if (value && oldValue === undefined && me.hideMode === 'removeDom') {
616
617
  me.vdom.removeDom = true
617
618
  } else if (value || oldValue !== undefined) {
618
- me[value ? 'hide' : 'show']()
619
+ me[state]()
619
620
  }
621
+
622
+ me.fire(state, {id: me.id})
620
623
  }
621
624
 
622
625
  /**
@@ -127,7 +127,20 @@ class Base extends Panel {
127
127
  /**
128
128
  * @member {String|null} title_=null
129
129
  */
130
- title_: null
130
+ title_: null,
131
+ /**
132
+ * Set to `true` to have tabbing wrap within this Dialog.
133
+ *
134
+ * Should be used with `modal`.
135
+ * @member {Boolean} trapFocus_=false
136
+ */
137
+ trapFocus_: false,
138
+ /**
139
+ * Set to `true` to have this Dialog centered in the viewport.
140
+ *
141
+ * @member {Boolean} centered_=false
142
+ */
143
+ centered_: false
131
144
  }
132
145
 
133
146
  /**
@@ -141,7 +154,7 @@ class Base extends Panel {
141
154
 
142
155
  me.createHeader();
143
156
 
144
- if (!me.animateTargetId) {
157
+ if (!me.animateTargetId && !me.centered) {
145
158
  Neo.assignDefaults(style, {
146
159
  left : '50%',
147
160
  top : '50%',
@@ -185,6 +198,17 @@ class Base extends Panel {
185
198
  super.afterSetAppName(value, oldValue)
186
199
  }
187
200
 
201
+ /**
202
+ * Triggered after the centered config got changed
203
+ * @param {Boolean} value
204
+ * @param {Boolean} oldValue
205
+ * @protected
206
+ */
207
+ afterSetCentered(value, oldValue) {
208
+ NeoArray.toggle(this.vdom.cls, 'neo-centered', value);
209
+ this.update();
210
+ }
211
+
188
212
  /**
189
213
  * Triggered after the draggable config got changed
190
214
  * @param {Boolean} value
@@ -252,6 +276,19 @@ class Base extends Panel {
252
276
  me.rendered && me.syncModalMask()
253
277
  }
254
278
 
279
+ /**
280
+ * Triggered after the mounted config got changed
281
+ * @param {Boolean} value
282
+ * @param {Boolean} oldValue
283
+ * @protected
284
+ */
285
+ afterSetMounted(value, oldValue) {
286
+ super.afterSetMounted(value, oldValue);
287
+
288
+ // Ensure focus trapping is up-to-date, enabled or disabled.
289
+ this.syncTrapFocus()
290
+ }
291
+
255
292
  /**
256
293
  * Triggered after the resizable config got changed
257
294
  * @param {Boolean} value
@@ -289,6 +326,16 @@ class Base extends Panel {
289
326
  }
290
327
  }
291
328
 
329
+ /**
330
+ * Triggered after the trapFocus config got changed
331
+ * @param {Boolean} value
332
+ * @param {Boolean} oldValue
333
+ * @protected
334
+ */
335
+ afterSetTrapFocus(value, oldValue) {
336
+ this.syncTrapFocus()
337
+ }
338
+
292
339
  /**
293
340
  *
294
341
  */
@@ -676,6 +723,15 @@ class Base extends Panel {
676
723
  // This should sync the visibility and position of the modal mask element.
677
724
  Neo.main.DomAccess.syncModalMask({ id, modal: this.modal })
678
725
  }
726
+
727
+ /**
728
+ *
729
+ */
730
+ syncTrapFocus() {
731
+ if (this.mounted) {
732
+ Neo.main.DomAccess.trapFocus({ id: this.id, trap: this.trapFocus })
733
+ }
734
+ }
679
735
  }
680
736
 
681
737
  Neo.applyClassConfig(Base);
@@ -11,35 +11,34 @@ class Toolbar extends Base {
11
11
  * @protected
12
12
  */
13
13
  className: 'Neo.dialog.header.Toolbar',
14
+ /**
15
+ * @member {Object} actionMap
16
+ */
17
+ actionMap: {
18
+ close : () => ({action: 'close', iconCls: 'far fa-window-close'}),
19
+ maximize: () => ({action: 'maximize', iconCls: 'far fa-window-maximize'})
20
+ },
21
+ /**
22
+ * You can define the action order and directly add custom actions.
23
+ * @example
24
+ * {
25
+ * actions: [
26
+ * 'close',
27
+ * 'maximize',
28
+ * {action: 'help', iconCls: 'far fa-circle-question'}
29
+ * ]
30
+ * }
31
+ *
32
+ * You can also extend the actionMap if needed.
33
+ * @member {Object[]|String[]|null} actions=['maximize','close']
34
+ */
35
+ actions: ['maximize', 'close'],
14
36
  /**
15
37
  * @member {String|null} title=null
16
38
  */
17
39
  title_: null
18
40
  }
19
41
 
20
- /**
21
- * @member {Object} actionMap
22
- */
23
- actionMap = {
24
- close : () => ({action: 'close', iconCls: 'far fa-window-close'}),
25
- maximize: () => ({action: 'maximize', iconCls: 'far fa-window-maximize'})
26
- }
27
- /**
28
- * You can define the action order and directly add custom actions.
29
- * @example
30
- * {
31
- * actions: [
32
- * 'close',
33
- * 'maximize',
34
- * {action: 'help', iconCls: 'far fa-circle-question'}
35
- * ]
36
- * }
37
- *
38
- * You can also extend the actionMap if needed.
39
- * @member {Object[]|String[]|null} actions=['maximize','close']
40
- */
41
- actions = ['maximize', 'close']
42
-
43
42
  /**
44
43
  * Triggered after the title config got changed
45
44
  * @param {String} value
@@ -83,7 +82,7 @@ class Toolbar extends Base {
83
82
 
84
83
  me.items = items;
85
84
 
86
- super.createItems();
85
+ super.createItems()
87
86
  }
88
87
 
89
88
  /**
@@ -109,7 +109,7 @@ class DateField extends Picker {
109
109
  me.dateSelector.on({
110
110
  change: me.onDatePickerChange,
111
111
  scope : me
112
- });
112
+ })
113
113
  }
114
114
 
115
115
  /**
@@ -162,7 +162,7 @@ class DateField extends Picker {
162
162
  * @returns {Neo.component.DateSelector}
163
163
  */
164
164
  createPickerComponent() {
165
- return this.dateSelector;
165
+ return this.dateSelector
166
166
  }
167
167
 
168
168
  /**
@@ -193,7 +193,7 @@ class DateField extends Picker {
193
193
  let me = this;
194
194
 
195
195
  me.hidePicker();
196
- me.focus(me.getInputElId());
196
+ me.focus(me.getInputElId())
197
197
  }
198
198
 
199
199
  /**
@@ -204,15 +204,15 @@ class DateField extends Picker {
204
204
  vdom = me.vdom;
205
205
 
206
206
  me.clean = false;
207
-
207
+
208
208
  if (me.hidePickerOnSelect) {
209
209
  VDomUtil.removeVdomChild(vdom, me.getPickerId());
210
210
 
211
211
  me.promiseUpdate().then(data => {
212
- me.value = opts.value;
213
- });
212
+ me.value = opts.value
213
+ })
214
214
  } else {
215
- me.value = opts.value;
215
+ me.value = opts.value
216
216
  }
217
217
  }
218
218
 
@@ -239,9 +239,9 @@ class DateField extends Picker {
239
239
 
240
240
  if (me.pickerIsMounted) {
241
241
  me.dateSelector.focusCurrentItem();
242
- super.onKeyDownEnter(data);
242
+ super.onKeyDownEnter(data)
243
243
  } else {
244
- super.onKeyDownEnter(data, me.dateSelector.focusCurrentItem, me.dateSelector);
244
+ super.onKeyDownEnter(data, me.dateSelector.focusCurrentItem, me.dateSelector)
245
245
  }
246
246
  }
247
247
 
@@ -2,12 +2,16 @@ import Base from '../../form/field/Base.mjs';
2
2
  import NeoArray from '../../util/Array.mjs';
3
3
 
4
4
  const
5
- sizeRE = /^(\d+)(kb|mb|gb)?$/i,
6
- sizeMultiplier = {
5
+ sizeRE = /^(\d+)(kb|mb|gb)?$/i,
6
+ sizeMultiplier = {
7
7
  unit : 1,
8
8
  kb : 1000,
9
9
  mb : 1000000,
10
10
  gb : 1000000000
11
+ },
12
+ httpSuccessCodes = {
13
+ 2 : 1,
14
+ 4 : 1
11
15
  };
12
16
 
13
17
  /**
@@ -509,7 +513,7 @@ class FileUpload extends Base {
509
513
 
510
514
  // Successful network request.
511
515
  // Check the resulting JSON packet for details and any error.
512
- if (String(xhr.status).startsWith('2')) {
516
+ if (httpSuccessCodes[String(xhr.status)[0]]) {
513
517
  if (loaded !== 0) {
514
518
  const response = JSON.parse(xhr.response);
515
519
 
@@ -600,7 +604,7 @@ class FileUpload extends Base {
600
604
  });
601
605
 
602
606
  // Success
603
- if (String(statusResponse.status).slice(0, 1) === '2') {
607
+ if (httpSuccessCodes[String(statusResponse.status)[0]]) {
604
608
  me.clear();
605
609
  me.state = 'ready';
606
610
  }
@@ -624,7 +628,7 @@ class FileUpload extends Base {
624
628
  });
625
629
 
626
630
  // Success
627
- if (String(statusResponse.status).slice(0, 1) === '2') {
631
+ if (httpSuccessCodes[String(statusResponse.status)[0]]) {
628
632
  const
629
633
  serverJson = await statusResponse.json(),
630
634
  serverStatus = serverJson.status,