inviton-powerduck 0.0.72 → 0.0.74

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 (72) hide show
  1. package/common/base-component.tsx +288 -288
  2. package/common/keyboard-open-tracker.ts +44 -0
  3. package/components/app/dynamic-component-container.tsx +1 -1
  4. package/components/app/root-dynamic-component-container.tsx +1 -1
  5. package/components/button/button.tsx +1 -1
  6. package/components/button/excel-upload-button.tsx +1 -1
  7. package/components/button/ladda-button.tsx +1 -1
  8. package/components/button/text-button.tsx +1 -1
  9. package/components/button/upload-button.tsx +1 -1
  10. package/components/card/card-body.tsx +1 -1
  11. package/components/card/card-header-with-options.tsx +1 -1
  12. package/components/card/card-header.tsx +1 -1
  13. package/components/card/card.tsx +1 -1
  14. package/components/collapse/index.tsx +1 -1
  15. package/components/contenteditable/index.tsx +1 -1
  16. package/components/context-menu/context-menu.tsx +1 -1
  17. package/components/counter/fetchdata.tsx +1 -1
  18. package/components/counter/index.tsx +1 -1
  19. package/components/datatable/col-vis-modal.tsx +1 -1
  20. package/components/datatable/export-excel-modal.tsx +1 -1
  21. package/components/datatable/filter-modal.tsx +1 -1
  22. package/components/dropdown/currency-code-picker.tsx +1 -1
  23. package/components/dropdown/image-dropdown.tsx +1 -1
  24. package/components/dropdown/language-picker.tsx +1 -1
  25. package/components/dropdown/timezone-picker.tsx +1 -1
  26. package/components/dropdown-button/dropdown-button-element.tsx +1 -1
  27. package/components/dropdown-button/dropdown-button-heading.tsx +1 -1
  28. package/components/dropdown-button/dropdown-button-item.tsx +1 -1
  29. package/components/dropdown-button/dropdown-button-separator.tsx +1 -1
  30. package/components/dropdown-button/language-dropdown-button.tsx +1 -1
  31. package/components/file-downloader/index.tsx +1 -1
  32. package/components/form/footer-buttons.tsx +1 -1
  33. package/components/form/form.tsx +1 -1
  34. package/components/form/separator.tsx +1 -1
  35. package/components/form/validation-result-displayer.tsx +1 -1
  36. package/components/fullcalendar/fullcalendar-draggable-event.tsx +1 -1
  37. package/components/fullcalendar/timegrid-calendar.tsx +1 -1
  38. package/components/google/maps.tsx +1 -1
  39. package/components/highlight-js/index.tsx +1 -1
  40. package/components/home/index.tsx +1 -1
  41. package/components/html-literal/html-literal.tsx +1 -1
  42. package/components/image-crop/image-cropping-modal.tsx +1 -1
  43. package/components/image-crop/upload-and-crop.tsx +1 -1
  44. package/components/input/checkbox-without-label.tsx +1 -1
  45. package/components/input/geo-json.tsx +1 -1
  46. package/components/loading-indicator/index.tsx +1 -1
  47. package/components/modal/animation-error.tsx +1 -1
  48. package/components/modal/animation-success.tsx +1 -1
  49. package/components/modal/icon-question.tsx +1 -1
  50. package/components/modal/icon-warning.tsx +1 -1
  51. package/components/modal/modal-body.tsx +1 -1
  52. package/components/modal/modal-footer.tsx +1 -1
  53. package/components/modal-wrap/modal-section-wrapper.tsx +1 -1
  54. package/components/modal-wrap/modal-subtitle.tsx +1 -1
  55. package/components/progress-bar/index.tsx +1 -1
  56. package/components/rating/rating-displayer.tsx +1 -1
  57. package/components/rating/rating-picker.tsx +1 -1
  58. package/components/share/share-modal.tsx +1 -1
  59. package/components/share/share.tsx +1 -1
  60. package/components/sortable/sortable-container.tsx +1 -1
  61. package/components/sortable/sortable-item.tsx +1 -1
  62. package/components/spreadsheet/spreadsheet.tsx +1 -1
  63. package/components/summary-stats/summary-stats.tsx +1 -1
  64. package/components/swiper/swiper-gallery.tsx +1 -1
  65. package/components/swiper/swiper-slide.tsx +1 -1
  66. package/components/swiper/swiper.tsx +1 -1
  67. package/components/table-wrapper/table-wrapper.tsx +1 -1
  68. package/components/tilebox/tilebox.tsx +1 -1
  69. package/components/tooltip/index.tsx +1 -1
  70. package/components/transition/index.tsx +1 -1
  71. package/components/wizard/wizard-subtitle.tsx +1 -1
  72. package/package.json +1 -1
@@ -13,303 +13,303 @@ import { IValidation, ValidationState } from './static-wrappers/interfaces/valid
13
13
  import ScrollUtils from "./scroll-utils";
14
14
 
15
15
  export abstract class PowerduckViewModelBase extends Vue {
16
- blockRoot: boolean = true;
17
- authorized: boolean = true;
18
- v$: Validation;
19
-
20
- constructor(optionBuilder: OptionBuilder, vueInstance: any) {
21
- super(optionBuilder, vueInstance);
22
- this.v$ = useVuelidate({
23
- $scope: vueInstance
24
- }) as any as Validation;
25
- }
26
-
27
- /**
28
- * Current interface language
29
- */
30
- get appLanguage(): Language {
31
- return PowerduckState.getCurrentLanguage();
32
- }
33
-
34
- /**
35
- * Try GET data from Inviton API enpoint
36
- */
37
- public async tryGetDataByArgs<TData, TArgs = {}>(args: TryCallApiArgs<TData, TArgs>): Promise<TData> {
38
- return this.tryCallApiByArgs(args, false);
39
- }
40
-
41
- /**
42
- * Try POST data to Inviton API endpoint
43
- */
44
- public async tryPostDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TryPostApiResponse<TData>> {
45
- var retVal = await this.tryCallApiByArgs(args, true);
46
- if (retVal != null && retVal["ajaxErr"] != null) {
47
- return {
48
- data: null as any,
49
- error: retVal["ajaxErr"],
50
- result: TryCallApiResult.Error,
51
- };
52
- } else {
53
- return {
54
- data: retVal,
55
- error: null as any,
56
- result: TryCallApiResult.Success,
57
- };
58
- }
59
- }
60
-
61
- /**
62
- * Try PATCH data to Inviton API endpoint
63
- * just decorator
64
- */
65
- public async tryPatchDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TryPatchApiResponse<TData>> {
66
- return await this.tryPostDataByArgs(args);
67
- }
68
-
69
- public async tryDeleteDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TData> {
70
- return this.tryCallApiByArgs(args, false);
71
- }
72
-
73
- private async tryCallApiByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>, includeError: boolean): Promise<TData> {
74
- var retVal: TData;
75
- let handle: any = null;
76
-
77
- if (args.blockRoot != false) {
78
- handle = setTimeout(() => {
79
- this.blockRoot = true;
80
- }, 850);
81
- }
82
-
83
- var apiMethod = args.apiMethod as any;
84
- var promise = apiMethod(args.requestArgs, args.timeout);
85
-
86
- try {
87
- retVal = await promise;
88
- } catch (e: any) {
89
- let err: AjaxError = e;
90
-
91
- if (args.blockRoot != false) {
92
- this.blockRoot = false;
93
- }
94
-
95
- if (e == "not authorized, token expired") {
96
- err = {
97
- authorized: false,
98
- responseText: PowerduckState.getResourceValue('loginExpired'),
99
- } as any;
100
- }
101
-
102
- if (err.authorized == false || e == "not authorized, token expired") {
103
- (window as any).loginModalRootInstance.show();
104
- }
105
-
106
- if (!err.authorized && args.toggleAuthorization) {
107
- this.authorized = err.authorized;
108
- }
109
-
110
- if (args.showError != false) {
111
- let parsedMsg = PowerduckState.parseErrorMessage(err.responseText);
112
- if (!isNullOrEmpty(parsedMsg)) {
113
- this.showErrorMessage(parsedMsg);
114
- } else if (err.responseText) {
115
- this.showErrorMessage(err.responseText);
116
- } else if ((err as any).message) {
117
- this.showErrorMessage((err as any).message);
118
- }
119
- }
120
-
121
- if (includeError) {
122
- retVal = {
123
- ajaxErr: err,
124
- } as any;
125
- } else {
126
- retVal = null as any;
127
- }
128
- }
129
-
130
- if (args.blockRoot != false) {
131
- try {
132
- clearTimeout(handle);
133
- } catch (error) { }
134
-
135
- if (this.blockRoot == true) {
136
- this.blockRoot = false;
137
- }
138
- }
139
-
140
- return retVal;
141
- }
142
-
143
- /**
144
- * Get children components of given type
145
- *
146
- * @param typeName Name of the type
147
- */
148
- getChildrenByType<T>(typeName: string): Array<T> {
149
- return PortalUtils.getChildrenByType(this, typeName);
150
- }
151
-
152
- /**
153
- * Displays unobtrusive error message
154
- * @param errMsg Error message
155
- */
156
- showErrorMessage(errMsg: string): void {
157
- NotificationProvider.showErrorMessage(errMsg);
158
- }
159
-
160
- /**
161
- * Displays unobtrusive success message
162
- * @param successMsg Success message
163
- */
164
- showSuccessMessage(successMsg: string): void {
165
- NotificationProvider.showSuccessMessage(successMsg);
166
- }
167
-
168
- /**
169
- * Parse variable into number
170
- * @param val
171
- * @param defaultValue
172
- */
173
- getNumericValue(val: any, defaultValue?: number) {
174
- if (val != null) {
175
- try {
176
- val = Number(val);
177
- if (isNaN(val)) {
178
- val = defaultValue;
179
- }
180
- } catch (e) {
181
- val = defaultValue;
182
- }
183
- } else {
184
- val = defaultValue;
185
- }
186
-
187
- return val;
188
- }
189
-
190
- /**
191
- * Validates current viewModel state based on given valdiation ruleset
192
- */
193
- async validate(showErrorMessage?: boolean, silent?: boolean): Promise<boolean> {
194
- if (localStorage.getItem("disableValidation") == "1") {
195
- return true;
196
- }
197
-
198
- if (this.v$ == null) {
199
- throw "Validation rules not specified, has to be specified in @Component declaration!";
200
- }
201
-
202
- var isInvalid = !(await this.v$.$validate());
203
- if (isInvalid) {
204
- if (showErrorMessage != false) {
205
- this.showValidationErrorMessage();
206
- }
207
-
208
- if (silent != true) {
209
- this.validationIncludeDirty = true;
210
- this.$nextTick(() => {
211
- this.scrollToFirstPossibleError($(this.unwrapRootElement()));
212
- });
213
- }
214
- }
215
-
216
- return !isInvalid;
217
- }
218
-
219
- unwrapRootElement(): HTMLElement {
220
- if ((this.$el as any).$getChildSlots != null) {
221
- return (((this.$el as any).$getChildSlots() || [])[0]?.el || this.$el) as any;
222
- }
223
-
224
- return this.$el as any;
225
- }
226
-
227
- showValidationErrorMessage() {
228
- this.showErrorMessage(PowerduckState.getResourceValue('errorsOnForm'));
229
- }
230
-
231
- scrollToFirstPossibleError(context: JQuery) {
232
- ScrollUtils.scrollToFirstPossibleError(context);
233
- }
234
-
235
- /**
236
- * Scrolls to element
237
- * @param elem
238
- */
239
- scrollToElem(elem: typeof Vue | Element | typeof Vue[] | Element[], mobileOffset?: boolean | number, mobileOffsetSmoothing?: boolean, animated?: boolean, instant?: boolean): void {
240
- ScrollUtils.scrollToElem(elem, mobileOffset, mobileOffsetSmoothing, animated, instant);
241
- }
242
-
243
- /**
244
- * Scrolls to position
245
- * @param elem
246
- */
247
- scrollToPos(position: number, context?: JQuery, animated?: boolean, instant?: boolean): void {
248
- ScrollUtils.scrollToPos(position, context, animated, instant);
249
- }
250
-
251
- /**
252
- * Determines if DIRTY should be included in validation
253
- */
254
- validationIncludeDirty: boolean = false;
255
-
256
- /**
257
- * Obtains validation state of given property
258
- * @param valProp Validation property
259
- */
260
- validationStateOf(valProp: IValidation | IValidation[], customMessage?: string): ValidationState {
261
- let retVal: ValidationState = null as any;
262
- if (!PortalUtils.isArray(valProp)) {
263
- retVal = ValidationHelper.getValidationDisplayState(valProp as any, this.validationIncludeDirty);
264
- } else {
265
- let validationResult: ValidationState;
266
- for (let i = 0, len = (valProp as IValidation[]).length; i < len; i++) {
267
- validationResult = ValidationHelper.getValidationDisplayState(valProp[i], this.validationIncludeDirty);
268
- if (!validationResult.valid) {
269
- retVal = validationResult;
270
- break;
271
- }
272
- }
273
- }
274
-
275
- if (retVal?.valid == false) {
276
- if (!isNullOrEmpty(customMessage as any)) {
277
- retVal = retVal || {} as any;
278
- retVal.errorMessage = customMessage as string;
279
- }
280
- }
281
-
282
- return retVal;
283
- }
284
-
285
- /**
286
- * Resets validation state of the viewModel
287
- */
288
- resetValidation() {
289
- ValidationHelper.resetValidation(this);
290
- this.validationIncludeDirty = false;
291
- }
16
+ blockRoot: boolean = true;
17
+ authorized: boolean = true;
18
+ v$: Validation;
19
+
20
+ constructor(optionBuilder: OptionBuilder, vueInstance: any) {
21
+ super(optionBuilder, vueInstance);
22
+ this.v$ = useVuelidate({
23
+ $scope: vueInstance
24
+ }) as any as Validation;
25
+ }
26
+
27
+ /**
28
+ * Current interface language
29
+ */
30
+ get appLanguage(): Language {
31
+ return PowerduckState.getCurrentLanguage();
32
+ }
33
+
34
+ /**
35
+ * Try GET data from Inviton API enpoint
36
+ */
37
+ public async tryGetDataByArgs<TData, TArgs = {}>(args: TryCallApiArgs<TData, TArgs>): Promise<TData> {
38
+ return this.tryCallApiByArgs(args, false);
39
+ }
40
+
41
+ /**
42
+ * Try POST data to Inviton API endpoint
43
+ */
44
+ public async tryPostDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TryPostApiResponse<TData>> {
45
+ var retVal = await this.tryCallApiByArgs(args, true);
46
+ if (retVal != null && retVal["ajaxErr"] != null) {
47
+ return {
48
+ data: null as any,
49
+ error: retVal["ajaxErr"],
50
+ result: TryCallApiResult.Error,
51
+ };
52
+ } else {
53
+ return {
54
+ data: retVal,
55
+ error: null as any,
56
+ result: TryCallApiResult.Success,
57
+ };
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Try PATCH data to Inviton API endpoint
63
+ * just decorator
64
+ */
65
+ public async tryPatchDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TryPatchApiResponse<TData>> {
66
+ return await this.tryPostDataByArgs(args);
67
+ }
68
+
69
+ public async tryDeleteDataByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>): Promise<TData> {
70
+ return this.tryCallApiByArgs(args, false);
71
+ }
72
+
73
+ private async tryCallApiByArgs<TData, TArgs>(args: TryCallApiArgs<TData, TArgs>, includeError: boolean): Promise<TData> {
74
+ var retVal: TData;
75
+ let handle: any = null;
76
+
77
+ if (args.blockRoot != false) {
78
+ handle = setTimeout(() => {
79
+ this.blockRoot = true;
80
+ }, 850);
81
+ }
82
+
83
+ var apiMethod = args.apiMethod as any;
84
+ var promise = apiMethod(args.requestArgs, args.timeout);
85
+
86
+ try {
87
+ retVal = await promise;
88
+ } catch (e: any) {
89
+ let err: AjaxError = e;
90
+
91
+ if (args.blockRoot != false) {
92
+ this.blockRoot = false;
93
+ }
94
+
95
+ if (e == "not authorized, token expired") {
96
+ err = {
97
+ authorized: false,
98
+ responseText: PowerduckState.getResourceValue('loginExpired'),
99
+ } as any;
100
+ }
101
+
102
+ if (err.authorized == false || e == "not authorized, token expired") {
103
+ (window as any).loginModalRootInstance.show();
104
+ }
105
+
106
+ if (!err.authorized && args.toggleAuthorization) {
107
+ this.authorized = err.authorized;
108
+ }
109
+
110
+ if (args.showError != false) {
111
+ let parsedMsg = PowerduckState.parseErrorMessage(err.responseText);
112
+ if (!isNullOrEmpty(parsedMsg)) {
113
+ this.showErrorMessage(parsedMsg);
114
+ } else if (err.responseText) {
115
+ this.showErrorMessage(err.responseText);
116
+ } else if ((err as any).message) {
117
+ this.showErrorMessage((err as any).message);
118
+ }
119
+ }
120
+
121
+ if (includeError) {
122
+ retVal = {
123
+ ajaxErr: err,
124
+ } as any;
125
+ } else {
126
+ retVal = null as any;
127
+ }
128
+ }
129
+
130
+ if (args.blockRoot != false) {
131
+ try {
132
+ clearTimeout(handle);
133
+ } catch (error) { }
134
+
135
+ if (this.blockRoot == true) {
136
+ this.blockRoot = false;
137
+ }
138
+ }
139
+
140
+ return retVal;
141
+ }
142
+
143
+ /**
144
+ * Get children components of given type
145
+ *
146
+ * @param typeName Name of the type
147
+ */
148
+ getChildrenByType<T>(typeName: string): Array<T> {
149
+ return PortalUtils.getChildrenByType(this, typeName);
150
+ }
151
+
152
+ /**
153
+ * Displays unobtrusive error message
154
+ * @param errMsg Error message
155
+ */
156
+ showErrorMessage(errMsg: string): void {
157
+ NotificationProvider.showErrorMessage(errMsg);
158
+ }
159
+
160
+ /**
161
+ * Displays unobtrusive success message
162
+ * @param successMsg Success message
163
+ */
164
+ showSuccessMessage(successMsg: string): void {
165
+ NotificationProvider.showSuccessMessage(successMsg);
166
+ }
167
+
168
+ /**
169
+ * Parse variable into number
170
+ * @param val
171
+ * @param defaultValue
172
+ */
173
+ getNumericValue(val: any, defaultValue?: number) {
174
+ if (val != null) {
175
+ try {
176
+ val = Number(val);
177
+ if (isNaN(val)) {
178
+ val = defaultValue;
179
+ }
180
+ } catch (e) {
181
+ val = defaultValue;
182
+ }
183
+ } else {
184
+ val = defaultValue;
185
+ }
186
+
187
+ return val;
188
+ }
189
+
190
+ /**
191
+ * Validates current viewModel state based on given valdiation ruleset
192
+ */
193
+ async validate(showErrorMessage?: boolean, silent?: boolean): Promise<boolean> {
194
+ if (localStorage.getItem("disableValidation") == "1") {
195
+ return true;
196
+ }
197
+
198
+ if (this.v$ == null) {
199
+ throw "Validation rules not specified, has to be specified in @Component declaration!";
200
+ }
201
+
202
+ var isInvalid = !(await this.v$.$validate());
203
+ if (isInvalid) {
204
+ if (showErrorMessage != false) {
205
+ this.showValidationErrorMessage();
206
+ }
207
+
208
+ if (silent != true) {
209
+ this.validationIncludeDirty = true;
210
+ this.$nextTick(() => {
211
+ this.scrollToFirstPossibleError($(this.unwrapRootElement()));
212
+ });
213
+ }
214
+ }
215
+
216
+ return !isInvalid;
217
+ }
218
+
219
+ unwrapRootElement(): HTMLElement {
220
+ if ((this.$el as any).$getChildSlots != null) {
221
+ return (((this.$el as any).$getChildSlots() || [])[0]?.el || this.$el) as any;
222
+ }
223
+
224
+ return this.$el as any;
225
+ }
226
+
227
+ showValidationErrorMessage() {
228
+ this.showErrorMessage(PowerduckState.getResourceValue('errorsOnForm'));
229
+ }
230
+
231
+ scrollToFirstPossibleError(context: JQuery) {
232
+ ScrollUtils.scrollToFirstPossibleError(context);
233
+ }
234
+
235
+ /**
236
+ * Scrolls to element
237
+ * @param elem
238
+ */
239
+ scrollToElem(elem: typeof Vue | Element | typeof Vue[] | Element[], mobileOffset?: boolean | number, mobileOffsetSmoothing?: boolean, animated?: boolean, instant?: boolean): void {
240
+ ScrollUtils.scrollToElem(elem, mobileOffset, mobileOffsetSmoothing, animated, instant);
241
+ }
242
+
243
+ /**
244
+ * Scrolls to position
245
+ * @param elem
246
+ */
247
+ scrollToPos(position: number, context?: JQuery, animated?: boolean, instant?: boolean): void {
248
+ ScrollUtils.scrollToPos(position, context, animated, instant);
249
+ }
250
+
251
+ /**
252
+ * Determines if DIRTY should be included in validation
253
+ */
254
+ validationIncludeDirty: boolean = false;
255
+
256
+ /**
257
+ * Obtains validation state of given property
258
+ * @param valProp Validation property
259
+ */
260
+ validationStateOf(valProp: IValidation | IValidation[], customMessage?: string): ValidationState {
261
+ let retVal: ValidationState = null as any;
262
+ if (!PortalUtils.isArray(valProp)) {
263
+ retVal = ValidationHelper.getValidationDisplayState(valProp as any, this.validationIncludeDirty);
264
+ } else {
265
+ let validationResult: ValidationState;
266
+ for (let i = 0, len = (valProp as IValidation[]).length; i < len; i++) {
267
+ validationResult = ValidationHelper.getValidationDisplayState(valProp[i], this.validationIncludeDirty);
268
+ if (!validationResult.valid) {
269
+ retVal = validationResult;
270
+ break;
271
+ }
272
+ }
273
+ }
274
+
275
+ if (retVal?.valid == false) {
276
+ if (!isNullOrEmpty(customMessage as any)) {
277
+ retVal = retVal || {} as any;
278
+ retVal.errorMessage = customMessage as string;
279
+ }
280
+ }
281
+
282
+ return retVal;
283
+ }
284
+
285
+ /**
286
+ * Resets validation state of the viewModel
287
+ */
288
+ resetValidation() {
289
+ ValidationHelper.resetValidation(this);
290
+ this.validationIncludeDirty = false;
291
+ }
292
292
  }
293
293
 
294
294
  interface TryCallApiArgs<TData, TArgs> {
295
- apiMethod: (data?: TArgs) => Promise<TData>;
296
- timeout?: number;
297
- requestArgs?: TArgs;
298
- showError?: boolean;
299
- blockRoot?: boolean;
300
- toggleAuthorization?: boolean;
301
- toggleAuthorizationOnNullUser?: boolean;
295
+ apiMethod: (data?: TArgs) => Promise<TData>;
296
+ timeout?: number;
297
+ requestArgs?: TArgs;
298
+ showError?: boolean;
299
+ blockRoot?: boolean;
300
+ toggleAuthorization?: boolean;
301
+ toggleAuthorizationOnNullUser?: boolean;
302
302
  }
303
303
 
304
304
  export interface TryPostApiResponse<TData> {
305
- data: TData;
306
- result: TryCallApiResult;
307
- error: AjaxError;
305
+ data: TData;
306
+ result: TryCallApiResult;
307
+ error: AjaxError;
308
308
  }
309
309
 
310
310
  export interface TryPatchApiResponse<TData> extends TryPostApiResponse<TData> { }
311
311
 
312
312
  interface PortalActionMessage {
313
- action: string;
314
- data: any;
313
+ action: string;
314
+ data: any;
315
315
  }
@@ -0,0 +1,44 @@
1
+ export default class KeyboardOpenTracker {
2
+ static bind() {
3
+ if ((window as any)._keyboardOpenTrackerBound == true) {
4
+ return;
5
+ }
6
+
7
+ (window as any)._keyboardOpenTrackerBound = true;
8
+
9
+ const getOrientation = () => {
10
+ return window.matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
11
+ }
12
+
13
+ const getScreenHeight = () => {
14
+ return window.screen.height; // Constant physical screen height
15
+ }
16
+
17
+ let lastOrientation = getOrientation();
18
+ const handleResize = () => {
19
+ const currentOrientation = getOrientation();
20
+ const currentInnerHeight = window.visualViewport?.height ?? window.innerHeight;
21
+ const screenHeight = getScreenHeight();
22
+
23
+ // Different thresholds for portrait/landscape
24
+ const THRESHOLD_PORTRAIT = 150;
25
+ const THRESHOLD_LANDSCAPE = 100;
26
+
27
+ const isPortrait = currentOrientation === 'portrait';
28
+ const threshold = isPortrait ? THRESHOLD_PORTRAIT : THRESHOLD_LANDSCAPE;
29
+
30
+ // Reset baseline when orientation changes
31
+ if (currentOrientation !== lastOrientation) {
32
+ lastOrientation = currentOrientation;
33
+ return;
34
+ }
35
+
36
+ const heightDiff = screenHeight - currentInnerHeight;
37
+ const isKeyboardOpen = heightDiff > threshold;
38
+ document.body.classList.toggle('powerduck-keyboard-open', isKeyboardOpen);
39
+ }
40
+
41
+ window.addEventListener('resize', handleResize);
42
+ handleResize(); // Run initially
43
+ }
44
+ }
@@ -85,5 +85,5 @@ class DynamicComponentContainerComponent extends Vue implements IDynamicComponen
85
85
  }
86
86
  }
87
87
 
88
- const DynamicComponentContainer = toNative(DynamicComponentContainerComponent)
88
+ const DynamicComponentContainer = toNative(DynamicComponentContainerComponent)
89
89
  export default DynamicComponentContainer
@@ -30,5 +30,5 @@ class RootDynamicComponentContainerComponent extends Vue implements IDynamicComp
30
30
  }
31
31
  }
32
32
 
33
- const RootDynamicComponentContainer = toNative(RootDynamicComponentContainerComponent)
33
+ const RootDynamicComponentContainer = toNative(RootDynamicComponentContainerComponent)
34
34
  export default RootDynamicComponentContainer
@@ -122,5 +122,5 @@ class ButtonComponent extends TsxComponent<ButtonArgs> implements ButtonArgs {
122
122
  }
123
123
  }
124
124
 
125
- const Button = toNative(ButtonComponent)
125
+ const Button = toNative(ButtonComponent)
126
126
  export default Button
@@ -55,5 +55,5 @@ class ExcelUploadButtonComponent extends TsxComponent<ExcelUploadButtonArgs> imp
55
55
  }
56
56
  }
57
57
 
58
- const ExcelUploadButton = toNative(ExcelUploadButtonComponent)
58
+ const ExcelUploadButton = toNative(ExcelUploadButtonComponent)
59
59
  export default ExcelUploadButton