glib-web 2.6.0 → 2.6.2

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 (48) hide show
  1. package/LICENSE +0 -0
  2. package/action.js +6 -4
  3. package/actions/auth/restart.js +0 -0
  4. package/actions/dialogs/oauth.js +0 -0
  5. package/actions/dialogs/options.js +0 -0
  6. package/actions/forms/submit.js +6 -3
  7. package/actions/panels/scrollTo.js +4 -2
  8. package/actions/tours/start.js +10 -1
  9. package/actions/tours/stop.js +7 -0
  10. package/components/_message.vue +0 -0
  11. package/components/datetime.vue +0 -0
  12. package/components/fab.vue +0 -0
  13. package/components/fields/check.vue +1 -5
  14. package/components/fields/checkGroup.vue +14 -11
  15. package/components/fields/country/countries.js +0 -0
  16. package/components/fields/country/field.vue +0 -0
  17. package/components/fields/country/regions.js +0 -0
  18. package/components/fields/datetime.vue +0 -0
  19. package/components/fields/dynamicSelect.vue +0 -0
  20. package/components/fields/file.vue +31 -8
  21. package/components/fields/otpField.vue +58 -17
  22. package/components/fields/radioGroup.vue +1 -5
  23. package/components/fields/richText.vue +11 -17
  24. package/components/fields/text.vue +2 -16
  25. package/components/fields/textarea.vue +7 -1
  26. package/components/fields/timeZone.vue +0 -0
  27. package/components/hr.vue +0 -0
  28. package/components/html.vue +0 -0
  29. package/components/mixins/longClick.js +0 -0
  30. package/components/mixins/scrolling.js +0 -0
  31. package/components/mixins/table/export.js +0 -0
  32. package/components/mixins/table/import.js +0 -0
  33. package/components/p.vue +0 -0
  34. package/keys.js +0 -0
  35. package/nav/dialog.vue +78 -15
  36. package/nav/drawerButton.vue +0 -0
  37. package/package.json +2 -2
  38. package/settings.json.example +0 -0
  39. package/styles/test.sass +0 -0
  40. package/styles/test.scss +0 -0
  41. package/templates/unsupported.vue +0 -0
  42. package/utils/dom.js +0 -0
  43. package/utils/launch.js +8 -0
  44. package/utils/public.js +4 -0
  45. package/utils/queue.js +0 -0
  46. package/utils/settings.js +7 -0
  47. package/utils/storage.js +0 -0
  48. package/utils/url.js +0 -0
package/LICENSE CHANGED
File without changes
package/action.js CHANGED
@@ -53,6 +53,7 @@ import ActionCommandsCustom from "./actions/commands/custom";
53
53
  import ActionCommandsEnqueue from "./actions/commands/enqueue";
54
54
 
55
55
  import ActionToursStart from "./actions/tours/start";
56
+ import ActionToursStop from "./actions/tours/stop";
56
57
 
57
58
  import ActionComponentsUpdate from "./actions/components/update";
58
59
 
@@ -110,6 +111,7 @@ const actions = {
110
111
  "commands/enqueue": ActionCommandsEnqueue,
111
112
 
112
113
  "tours/start": ActionToursStart,
114
+ "tours/stop": ActionToursStop,
113
115
  "components/update": ActionComponentsUpdate
114
116
  };
115
117
 
@@ -170,10 +172,10 @@ export default class Action {
170
172
  }
171
173
  action.execute(spec, component, params);
172
174
  } catch (e) {
173
- console.error(
174
- "Failed executing command",
175
- actionName,
176
- `Error: '${e.message}'`
175
+ GLib.settings.errorHandler(
176
+ new Error(
177
+ `Failed executing command "${actionName}". Error: ${e.message}`
178
+ )
177
179
  );
178
180
  }
179
181
  }
File without changes
File without changes
File without changes
@@ -1,7 +1,10 @@
1
1
  export default class {
2
2
  execute(properties, component) {
3
- component.$dispatchEvent("forms/directSubmit", {
4
- url: properties.overrideUrl
5
- });
3
+ setTimeout(() => {
4
+ component.$dispatchEvent("forms/directSubmit", {
5
+ url: properties.overrideUrl
6
+ });
7
+ }, 500)
8
+
6
9
  }
7
10
  }
@@ -1,7 +1,9 @@
1
1
  // Scroll the main body of the current window
2
2
  export default class {
3
- execute(properties) {
4
- const pageBody = Utils.history._pageBody;
3
+ execute(properties, component) {
4
+ const pageBody =
5
+ Utils.launch.dialog.closestBody(component) || Utils.history._pageBody;
6
+
5
7
  const selector = `#${properties.viewId}`;
6
8
  console.log("Scrolling to", selector);
7
9
  const element = pageBody.querySelector(selector);
@@ -1,9 +1,11 @@
1
1
  import Driver from "driver.js";
2
2
  import "driver.js/dist/driver.min.css";
3
3
 
4
+ let driver = null;
5
+
4
6
  export default class {
5
7
  execute(spec, component) {
6
- let driver = new Driver(spec.options || {});
8
+ driver = new Driver(spec.options || {});
7
9
  let steps = spec.steps;
8
10
  steps
9
11
  .filter(value => value.customBehavior)
@@ -14,4 +16,11 @@ export default class {
14
16
  driver.defineSteps(steps);
15
17
  driver.start(spec.startFrom || 0);
16
18
  }
19
+
20
+ static stopTour() {
21
+ if (driver) {
22
+ driver.reset();
23
+ driver = null;
24
+ }
25
+ }
17
26
  }
@@ -0,0 +1,7 @@
1
+ import tour from "./start.js";
2
+
3
+ export default class {
4
+ execute(spec, component) {
5
+ tour.stopTour();
6
+ }
7
+ }
File without changes
File without changes
File without changes
@@ -58,11 +58,7 @@ export default {
58
58
  );
59
59
  }, 100);
60
60
 
61
- Utils.type.ifObject(this.spec.onChange, onChange => {
62
- this.$nextTick(() => {
63
- GLib.action.execute(onChange, this);
64
- });
65
- });
61
+ this.$executeOnChange();
66
62
  },
67
63
  $internalizeValue(val) {
68
64
  if (val == this.spec.checkValue) {
@@ -29,17 +29,17 @@ export default {
29
29
  // "fields-hidden": HiddenField
30
30
  // },
31
31
  props: {
32
- spec: { type: Object, required: true }
32
+ spec: { type: Object, required: true },
33
33
  },
34
34
  data() {
35
35
  return {
36
36
  anyChecked: false,
37
37
  errorMessage: null,
38
38
  rules: [
39
- _v => {
39
+ (_v) => {
40
40
  return this.anyChecked || this.errorMessage || true;
41
- }
42
- ]
41
+ },
42
+ ],
43
43
  };
44
44
  },
45
45
  // computed: {
@@ -51,7 +51,7 @@ export default {
51
51
  $ready() {
52
52
  const validation = this.spec.validation || {};
53
53
 
54
- Utils.type.ifObject(validation.required, required => {
54
+ Utils.type.ifObject(validation.required, (required) => {
55
55
  this.errorMessage = required.message;
56
56
  });
57
57
 
@@ -59,7 +59,7 @@ export default {
59
59
  const vm = this;
60
60
  this.$el.addEventListener(
61
61
  "change",
62
- function(e) {
62
+ function (e) {
63
63
  vm.detectChecked();
64
64
  },
65
65
  false
@@ -70,7 +70,7 @@ export default {
70
70
  const vm = this;
71
71
  this.$el
72
72
  .querySelectorAll("input[type=checkbox]")
73
- .forEach(function(checkbox) {
73
+ .forEach(function (checkbox) {
74
74
  if (checkbox.checked) {
75
75
  vm.anyChecked = true;
76
76
  return;
@@ -79,12 +79,15 @@ export default {
79
79
  },
80
80
  childSpec(item) {
81
81
  if (this.spec.readOnly) {
82
- return Object.assign(item, { readOnly: this.spec.readOnly });
82
+ return Object.assign(item, {
83
+ readOnly: this.spec.readOnly,
84
+ onChange: this.spec.onChange,
85
+ });
83
86
  }
84
87
 
85
- return item;
86
- }
87
- }
88
+ return Object.assign(item, { onChange: this.spec.onChange });
89
+ },
90
+ },
88
91
  };
89
92
  </script>
90
93
 
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,14 +2,28 @@
2
2
  <div ref="fileUploadContainer" class="mb-3" :style="$styles()">
3
3
  <label class="v-label v-label--active">{{ spec.label }}</label>
4
4
  <div class="preview-container">
5
- <v-avatar v-if="placeholder.type == 'avatar'" :style="genericStyles(placeholder)" class="mr-4">
5
+ <v-avatar
6
+ v-if="placeholder.type == 'avatar'"
7
+ :style="genericStyles(placeholder)"
8
+ class="mr-4"
9
+ >
6
10
  <img :src="fileImage || placeholder.url" />
7
11
  </v-avatar>
8
- <img v-else-if="placeholder.type == 'image'" class="square-image mr-4" :style="genericStyles(placeholder)"
9
- :src="fileImage || placeholder.url" />
10
-
11
- <v-text-field v-else-if="placeholder.type == 'input'" :value="fileTitle" outlined prominent
12
- placholder="Upload your file" disabled />
12
+ <img
13
+ v-else-if="placeholder.type == 'image'"
14
+ class="square-image mr-4"
15
+ :style="genericStyles(placeholder)"
16
+ :src="fileImage || placeholder.url"
17
+ />
18
+
19
+ <v-text-field
20
+ v-else-if="placeholder.type == 'input'"
21
+ :value="fileTitle"
22
+ outlined
23
+ prominent
24
+ placholder="Upload your file"
25
+ disabled
26
+ />
13
27
 
14
28
  <span v-else class="mr-4">{{ fileTitle }}</span>
15
29
 
@@ -33,7 +47,12 @@
33
47
  </v-btn>
34
48
  </span>
35
49
  </div>
36
- <input ref="directUploadFile" style="display: none;" type="file" @change="uploadFiles" />
50
+ <input
51
+ ref="directUploadFile"
52
+ style="display: none;"
53
+ type="file"
54
+ @change="uploadFiles"
55
+ />
37
56
 
38
57
  <!-- <input type="file" :name="spec.name" ref='directUploadFile' @change='uploadFiles' v-show='!uploaded'/> -->
39
58
  <v-progress-linear v-if="showProgress" v-model="progress.value" />
@@ -73,7 +92,7 @@ export default {
73
92
  };
74
93
  },
75
94
  computed: {
76
- showProgress: function () {
95
+ showProgress: function() {
77
96
  return this.progress.value >= 0;
78
97
  }
79
98
  },
@@ -129,6 +148,10 @@ export default {
129
148
  this.uploaded = true;
130
149
  this.progress.value = -1;
131
150
  this.displayImagePreview(file, blob);
151
+
152
+ // This only works for single uploads. For multi-uploads, we'll need to make sure
153
+ // that all uploads have finished successfully.
154
+ this.$executeOnChange();
132
155
  }
133
156
 
134
157
  input.disabled = false;
@@ -1,18 +1,40 @@
1
1
  <template>
2
2
  <div>
3
- <input
4
- v-for="(digit, index) in digits"
5
- ref="input"
6
- :key="index"
7
- v-model="otp[index]"
8
- maxlength="1"
9
- class="otp-input"
10
- @input="handleInput($event, index)"
11
- @keydown="handleKeydown($event, index)"
12
- @paste="handlePaste($event, index)"
13
- @focus="handleFocus($event, index)"
14
- @blur="handleBlur($event, index)"
15
- />
3
+ <div v-if="spec.type === 'text'">
4
+ <input
5
+ v-for="(digit, index) in digits"
6
+ ref="input"
7
+ :key="index"
8
+ v-model="otp[index]"
9
+ type="text"
10
+ maxlength="1"
11
+ class="otp-input"
12
+ @input="handleInput($event, index)"
13
+ @keydown="handleKeydown($event, index)"
14
+ @paste="handlePaste($event, index)"
15
+ @focus="handleFocus($event, index)"
16
+ @blur="handleBlur($event, index)"
17
+ @click="handleClick($event)"
18
+ />
19
+ </div>
20
+ <div v-else>
21
+ <input
22
+ v-for="(digit, index) in digits"
23
+ ref="input"
24
+ :key="index"
25
+ v-model="otp[index]"
26
+ type="number"
27
+ oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);"
28
+ maxlength="1"
29
+ class="otp-input"
30
+ @input="handleInput($event, index)"
31
+ @keydown="handleKeydown($event, index)"
32
+ @paste="handlePaste($event, index)"
33
+ @focus="handleFocus($event, index)"
34
+ @blur="handleBlur($event, index)"
35
+ @click="handleClick($event)"
36
+ />
37
+ </div>
16
38
  <input type="hidden" :name="spec.name" :value="otpValue" />
17
39
  </div>
18
40
  </template>
@@ -37,8 +59,8 @@ export default {
37
59
  },
38
60
  methods: {
39
61
  $ready() {
40
- this.digits = this.spec.lengths;
41
- this.otp = Array(this.spec.lengths).fill("");
62
+ this.digits = this.spec.length;
63
+ this.otp = Array(this.spec.length).fill("");
42
64
  },
43
65
  handleInput(event, index) {
44
66
  if (event.target.value.length === 1) {
@@ -48,8 +70,12 @@ export default {
48
70
  handleKeydown(event, index) {
49
71
  if (event.key === "Backspace") {
50
72
  event.preventDefault();
51
- this.focusPrevious(index);
52
- this.$set(this.otp, index, "");
73
+ if (this.otp[index] !== "") {
74
+ this.$set(this.otp, index, "");
75
+ } else {
76
+ this.focusPrevious(index);
77
+ this.$set(this.otp, index - 1, "");
78
+ }
53
79
  }
54
80
  },
55
81
  handlePaste(event, index) {
@@ -81,6 +107,9 @@ export default {
81
107
  if (index > 0) {
82
108
  this.$refs.input[index - 1].focus();
83
109
  }
110
+ },
111
+ handleClick(event) {
112
+ event.target.select();
84
113
  }
85
114
  }
86
115
  };
@@ -95,4 +124,16 @@ export default {
95
124
  font-size: 24px;
96
125
  margin: 8px;
97
126
  }
127
+
128
+ /* Chrome, Safari, Edge, Opera */
129
+ input::-webkit-outer-spin-button,
130
+ input::-webkit-inner-spin-button {
131
+ -webkit-appearance: none;
132
+ margin: 0;
133
+ }
134
+
135
+ /* Firefox */
136
+ input[type="number"] {
137
+ -moz-appearance: textfield;
138
+ }
98
139
  </style>
@@ -34,11 +34,7 @@ export default {
34
34
  },
35
35
  methods: {
36
36
  onChange() {
37
- Utils.type.ifObject(this.spec.onChange, onChange => {
38
- this.$nextTick(() => {
39
- GLib.action.execute(onChange, this);
40
- });
41
- });
37
+ this.$executeOnChange();
42
38
  },
43
39
  updateValue(variable) {
44
40
  if (variable.value) {
@@ -14,9 +14,9 @@
14
14
  v-model="richEditorValue"
15
15
  :editor-toolbar="customToolbar"
16
16
  use-custom-image-handler
17
+ :editor-options="editorSettings"
17
18
  @text-change="onRichTextEditorChanged"
18
19
  @image-added="uploadImage"
19
- :editorOptions="editorSettings"
20
20
  />
21
21
  <!-- Hide these fields but don't remove them because these are the values that will get submitted. -->
22
22
  <div :style="{ display: rawMode ? 'block' : 'none' }">
@@ -124,6 +124,10 @@ class TextEditor {
124
124
 
125
125
  // replace {{image1}} to real image1 url
126
126
  replaceWithRealImage(html) {
127
+ if (!html) {
128
+ return "";
129
+ }
130
+
127
131
  const vm = this.context;
128
132
  return html.replace(/\{\{image([0-9]+)\}\}/g, function (_, index) {
129
133
  const image = vm.spec.images[index - 1];
@@ -143,6 +147,10 @@ class TextEditor {
143
147
 
144
148
  // replace image1 url with {{image1}}
145
149
  replaceWithFakeImage(html) {
150
+ if (!html) {
151
+ return "";
152
+ }
153
+
146
154
  const vm = this.context;
147
155
  let index = 0;
148
156
  vm.imageKeys.clear();
@@ -281,7 +289,7 @@ export default {
281
289
  this.produce
282
290
  );
283
291
 
284
- this.onChange(this.producedValue);
292
+ this.$executeOnChange(this.producedValue);
285
293
  }),
286
294
  onRawTextEditorChanged: eventFiltering.debounce(function () {
287
295
  this.producedValue = this.textEditor.producedValue(
@@ -290,22 +298,8 @@ export default {
290
298
  this.produce
291
299
  );
292
300
 
293
- this.onChange(this.producedValue);
301
+ this.$executeOnChange(this.producedValue);
294
302
  }),
295
- onChange(producedValue) {
296
- Utils.type.ifObject(this.spec.onChange, (onChange) => {
297
- this.$nextTick(() => {
298
- const params = {
299
- [this.spec.paramNameForFormData || "formData"]: {
300
- [this.fieldName]: producedValue,
301
- },
302
- };
303
-
304
- const data = Object.assign({}, onChange, params);
305
- GLib.action.execute(data, this);
306
- });
307
- });
308
- },
309
303
  insertImage: function (file, Editor, cursorLocation, blob) {
310
304
  let vm = this;
311
305
  var reader = new FileReader();
@@ -137,22 +137,8 @@ export default {
137
137
  return this.$classes().concat("g-text-field--hintless");
138
138
  },
139
139
  onChange: eventFiltering.debounce(function() {
140
- this.executeActionWithParams();
141
- }, 300),
142
- executeActionWithParams() {
143
- Utils.type.ifObject(this.spec.onChange, onChange => {
144
- this.$nextTick(() => {
145
- const params = {
146
- [this.spec.paramNameForFormData || "formData"]: {
147
- [this.fieldName]: this.fieldModel
148
- }
149
- };
150
-
151
- const data = Object.assign({}, onChange, params);
152
- GLib.action.execute(data, this);
153
- });
154
- });
155
- }
140
+ this.$executeOnChange();
141
+ }, 300)
156
142
  }
157
143
  };
158
144
  </script>
@@ -16,6 +16,7 @@
16
16
  :no-resize="$classes().includes('no-resize')"
17
17
  validate-on-blur
18
18
  @keyup="$onTyping"
19
+ @input="onChange"
19
20
  ></v-textarea>
20
21
  <input
21
22
  v-if="spec.readOnly"
@@ -27,6 +28,8 @@
27
28
  </template>
28
29
 
29
30
  <script>
31
+ import eventFiltering from "../../utils/eventFiltering";
32
+
30
33
  export default {
31
34
  props: {
32
35
  spec: { type: Object, required: true }
@@ -45,7 +48,10 @@ export default {
45
48
  },
46
49
  classes() {
47
50
  return this.$classes().concat("g-text-field--hintless");
48
- }
51
+ },
52
+ onChange: eventFiltering.debounce(function() {
53
+ this.$executeOnChange();
54
+ }, 300)
49
55
  }
50
56
  };
51
57
  </script>
File without changes
package/components/hr.vue CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/components/p.vue CHANGED
File without changes
package/keys.js CHANGED
File without changes
package/nav/dialog.vue CHANGED
@@ -7,24 +7,34 @@
7
7
  :sm-and-down="false"
8
8
  :persistent="true"
9
9
  >
10
- <v-card>
11
- <v-card-title v-if="title || showClose" class="text-h5" primary-title>
12
- {{ title }}
10
+ <v-card :style="hamburgerStyles" class="hamburger">
11
+ <!-- <v-card-title v-if="title || showClose" class="text-h5" primary-title> -->
12
+ <div>
13
+ <panels-responsive v-if="header" :spec="header" />
14
+ <div v-if="title" class="dialogs-title theme--light v-subheader">
15
+ {{ title }}
16
+ </div>
17
+
13
18
  <v-btn v-if="showClose" text icon class="dialog-close" @click="close">
14
19
  <v-icon>close</v-icon>
15
20
  </v-btn>
16
- </v-card-title>
21
+ </div>
22
+ <!-- </v-card-title> -->
17
23
 
18
- <component :is="containerComponent" :spec="formSpec">
19
- <div v-if="message" class="dialog-message">
20
- <common-message :spec="{ message: message }" />
21
- </div>
22
- <panels-responsive v-if="body" :spec="body" />
23
- </component>
24
+ <div class="dialogs-body">
25
+ <component :is="containerComponent" :spec="formSpec">
26
+ <div v-if="message" class="dialog-message">
27
+ <common-message :spec="{ message: message }" />
28
+ </div>
29
+ <panels-responsive v-if="body" :spec="body" />
30
+ </component>
31
+ </div>
24
32
 
25
- <v-divider></v-divider>
33
+ <panels-responsive v-if="footer" :spec="footer" />
26
34
 
27
35
  <v-card-actions v-if="spec.buttons">
36
+ <v-divider></v-divider>
37
+
28
38
  <v-spacer></v-spacer>
29
39
 
30
40
  <v-btn
@@ -36,8 +46,6 @@
36
46
  >
37
47
  {{ button.text }}
38
48
  </v-btn>
39
-
40
- <panels-responsive v-if="footer" :spec="footer" />
41
49
  </v-card-actions>
42
50
  </v-card>
43
51
  </v-dialog>
@@ -59,9 +67,11 @@ export default {
59
67
  },
60
68
  data: function() {
61
69
  return {
70
+ mainHeight: 0,
62
71
  title: null,
63
72
  message: null,
64
73
  body: null,
74
+ header: null,
65
75
  footer: null,
66
76
  model: null,
67
77
  url: null,
@@ -88,6 +98,12 @@ export default {
88
98
  } else {
89
99
  return false;
90
100
  }
101
+ },
102
+ hamburgerStyles() {
103
+ if (this.spec.height == "matchParent") {
104
+ return `height: ${this.mainHeight}px;`;
105
+ }
106
+ return null;
91
107
  }
92
108
  },
93
109
  watch: {
@@ -98,11 +114,24 @@ export default {
98
114
  }
99
115
  },
100
116
  methods: {
117
+ $mounted() {
118
+ window.addEventListener(
119
+ "resize",
120
+ event => {
121
+ this.updateMainHeight();
122
+ },
123
+ true
124
+ );
125
+ },
101
126
  $ready() {
102
127
  this.$root.vueApp = this.vueApp;
103
128
  this.onResize();
104
129
  this.show(false);
105
130
  this.stack.push(this);
131
+
132
+ this.$nextTick(() => {
133
+ this.updateMainHeight();
134
+ });
106
135
  },
107
136
  $tearDown() {
108
137
  console.log("Dialog destroyed");
@@ -128,7 +157,6 @@ export default {
128
157
  onResize() {
129
158
  this.isMobile = window.innerWidth < 600;
130
159
  },
131
-
132
160
  show(reload) {
133
161
  const spec = this.spec;
134
162
  this.url = spec.url;
@@ -146,6 +174,7 @@ export default {
146
174
  this.title = response.title;
147
175
  this.message = "";
148
176
  this.formSpec = response.fullPageForm;
177
+ this.header = response.header;
149
178
  this.body = response.body;
150
179
  this.footer = response.footer;
151
180
  this.showClose = this.spec.showClose || false;
@@ -161,12 +190,19 @@ export default {
161
190
  }
162
191
 
163
192
  this.model = true;
193
+ },
194
+ updateMainHeight() {
195
+ console.debug("Setting body height");
196
+ this.mainHeight = window.innerHeight - 140;
164
197
  }
165
198
  }
166
199
  };
167
200
  </script>
168
201
 
169
- <style scoped>
202
+ <style lang="scss" scoped>
203
+ .dialogs-title {
204
+ padding: 16px 16px 0px 16px;
205
+ }
170
206
  .dialog-message {
171
207
  padding: 16px 16px 20px 16px;
172
208
  /* white-space: pre-wrap; */
@@ -179,4 +215,31 @@ export default {
179
215
  .v-card__text {
180
216
  padding: 0 !important;
181
217
  }
218
+ .hamburger {
219
+ display: flex;
220
+ flex-direction: column;
221
+ justify-content: space-between;
222
+ height: 100%;
223
+ padding: 0;
224
+ }
225
+ .dialogs-body {
226
+ // height: 100%;
227
+ // overflow-y: overlay;
228
+ overflow-y: auto;
229
+ }
230
+ </style>
231
+
232
+ <style lang="scss">
233
+ .v-dialog {
234
+ // Hide superfluous scrollbar (Edge)
235
+ -ms-overflow-style: none;
236
+ * {
237
+ -ms-overflow-style: initial;
238
+ }
239
+
240
+ // Hide superfluous scrollbar (Webkit)
241
+ &::-webkit-scrollbar {
242
+ display: none;
243
+ }
244
+ }
182
245
  </style>
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glib-web",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -47,4 +47,4 @@
47
47
  "prettier": "^1.18.2",
48
48
  "typescript": "^4.9.5"
49
49
  }
50
- }
50
+ }
File without changes
package/styles/test.sass CHANGED
File without changes
package/styles/test.scss CHANGED
File without changes
File without changes
package/utils/dom.js CHANGED
File without changes
package/utils/launch.js CHANGED
@@ -19,6 +19,14 @@ export default class {
19
19
  }
20
20
 
21
21
  class LaunchDialog {
22
+ static closestBody(component) {
23
+ const dialog = component.$el.closest(".v-dialog");
24
+ if (dialog) {
25
+ return dialog.querySelector(".dialogs-body");
26
+ }
27
+ return null;
28
+ }
29
+
22
30
  static _initStack() {
23
31
  if (!this.stack) {
24
32
  this.stack = [];
package/utils/public.js CHANGED
@@ -6,6 +6,7 @@ import Form from "./form";
6
6
  import Component from "./component";
7
7
  import Hash from "./hash";
8
8
  import Queue from "./queue";
9
+ import Settings from "./settings";
9
10
 
10
11
  const _queue = new Queue();
11
12
 
@@ -31,6 +32,9 @@ export default class {
31
32
  static get Hash() {
32
33
  return Hash;
33
34
  }
35
+ static get settings() {
36
+ return Settings;
37
+ }
34
38
  static get queue() {
35
39
  return _queue;
36
40
  }
package/utils/queue.js CHANGED
File without changes
package/utils/settings.js CHANGED
@@ -3,6 +3,9 @@ class MutableSettings {
3
3
  this.reactive = true;
4
4
  this.themes = {};
5
5
  this.gtagId = null;
6
+ this.errorHandler = err => {
7
+ console.error(err.message);
8
+ };
6
9
  }
7
10
  }
8
11
  const settings = new MutableSettings();
@@ -17,6 +20,10 @@ export default class ImmutableSettings {
17
20
  return settings.themes;
18
21
  }
19
22
 
23
+ static get errorHandler() {
24
+ return settings.errorHandler;
25
+ }
26
+
20
27
  static get env() {
21
28
  return process.env.NODE_ENV;
22
29
  }
package/utils/storage.js CHANGED
File without changes
package/utils/url.js CHANGED
File without changes