@yomotech/view-toolkit 0.0.93 → 0.0.94

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.
@@ -2930,13 +2930,29 @@ class CustomKeyboardService {
2930
2930
  }
2931
2931
  this.activeSession.set(session);
2932
2932
  document.body.classList.add('vl-custom-keyboard-open');
2933
+ document.addEventListener('pointerdown', this.documentPointerDownHandler, true);
2934
+ target.addEventListener('blur', this.activeTargetBlurHandler);
2933
2935
  try {
2934
2936
  await Keyboard.hide();
2935
2937
  }
2936
2938
  catch {
2937
2939
  // The native keyboard may already be closed.
2938
2940
  }
2941
+ /*
2942
+ * The keyboard may have closed while Keyboard.hide()
2943
+ * was running.
2944
+ */
2945
+ if (this.activeSession() !== session) {
2946
+ return;
2947
+ }
2939
2948
  window.setTimeout(() => {
2949
+ /*
2950
+ * The user may have touched outside during this delay.
2951
+ * Do not focus the old input again.
2952
+ */
2953
+ if (this.activeSession() !== session) {
2954
+ return;
2955
+ }
2940
2956
  target.focus({
2941
2957
  preventScroll: true
2942
2958
  });
@@ -3001,8 +3017,14 @@ class CustomKeyboardService {
3001
3017
  }
3002
3018
  const { target } = session;
3003
3019
  /*
3004
- * change supports controls configured with updateOn blur/change.
3020
+ * Remove listeners before blurring the input.
3021
+ */
3022
+ document.removeEventListener('pointerdown', this.documentPointerDownHandler, true);
3023
+ target.removeEventListener('blur', this.activeTargetBlurHandler);
3024
+ /*
3025
+ * Clear the session before blur events can run.
3005
3026
  */
3027
+ this.activeSession.set(null);
3006
3028
  target.dispatchEvent(new Event('change', {
3007
3029
  bubbles: true
3008
3030
  }));
@@ -3023,7 +3045,6 @@ class CustomKeyboardService {
3023
3045
  target.setAttribute('type', session.originalInputType);
3024
3046
  }
3025
3047
  }
3026
- this.activeSession.set(null);
3027
3048
  document.body.classList.remove('vl-custom-keyboard-open');
3028
3049
  }
3029
3050
  closeIfTargetInside(container) {
@@ -3082,6 +3103,70 @@ class CustomKeyboardService {
3082
3103
  // Ignore inputs without selection support.
3083
3104
  }
3084
3105
  }
3106
+ documentPointerDownHandler = (event) => {
3107
+ this.handleDocumentPointerDown(event);
3108
+ };
3109
+ activeTargetBlurHandler = () => {
3110
+ this.handleActiveTargetBlur();
3111
+ };
3112
+ handleDocumentPointerDown(event) {
3113
+ const session = this.activeSession();
3114
+ if (!session) {
3115
+ return;
3116
+ }
3117
+ const eventTarget = event.target;
3118
+ if (!(eventTarget instanceof Node)) {
3119
+ return;
3120
+ }
3121
+ /*
3122
+ * User clicked the currently active input.
3123
+ */
3124
+ if (eventTarget === session.target ||
3125
+ session.target.contains(eventTarget)) {
3126
+ return;
3127
+ }
3128
+ /*
3129
+ * User clicked a button inside the custom keyboard.
3130
+ * Keep the keyboard open so that the button click can run.
3131
+ */
3132
+ if (eventTarget instanceof Element &&
3133
+ eventTarget.closest('[data-vl-custom-keyboard]')) {
3134
+ return;
3135
+ }
3136
+ /*
3137
+ * User clicked anywhere else.
3138
+ */
3139
+ this.close();
3140
+ }
3141
+ handleActiveTargetBlur() {
3142
+ /*
3143
+ * Wait for the browser to finish changing focus.
3144
+ */
3145
+ window.setTimeout(() => {
3146
+ const session = this.activeSession();
3147
+ if (!session) {
3148
+ return;
3149
+ }
3150
+ const activeElement = document.activeElement;
3151
+ /*
3152
+ * Input still has focus.
3153
+ */
3154
+ if (activeElement === session.target) {
3155
+ return;
3156
+ }
3157
+ const keyboardElement = document.querySelector('[data-vl-custom-keyboard]');
3158
+ /*
3159
+ * Do not close if focus somehow moved to an element
3160
+ * inside the custom keyboard.
3161
+ */
3162
+ if (keyboardElement &&
3163
+ activeElement &&
3164
+ keyboardElement.contains(activeElement)) {
3165
+ return;
3166
+ }
3167
+ this.close();
3168
+ }, 0);
3169
+ }
3085
3170
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: CustomKeyboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3086
3171
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: CustomKeyboardService, providedIn: 'root' });
3087
3172
  }
@@ -5042,11 +5127,11 @@ class CustomKeyboardComponent {
5042
5127
  this.uppercase.update(value => !value);
5043
5128
  }
5044
5129
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: CustomKeyboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5045
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.2", type: CustomKeyboardComponent, isStandalone: true, selector: "vl-custom-keyboard", ngImport: i0, template: "@if (keyboard.activeSession(); as session) {\r\n<section class=\"custom-keyboard\" [class.custom-keyboard--numeric]=\"session.type === 'numeric'\"\r\n [attr.aria-label]=\"session.type + ' keyboard'\" (pointerdown)=\"$event.preventDefault()\">\r\n <div class=\"custom-keyboard__toolbar\">\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.clear()\">\r\n Clear\r\n </button>\r\n\r\n <span class=\"custom-keyboard__type\">\r\n {{ session.type }}\r\n </span>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n\r\n @for (row of rows; track $index) {\r\n <div class=\"custom-keyboard__row\">\r\n @for (key of row; track key) {\r\n <button type=\"button\" class=\"custom-keyboard__key\" (click)=\"enterKey(key)\">\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (\r\n session.type === 'alpha' ||\r\n session.type === 'string'\r\n ) {\r\n <div class=\"custom-keyboard__text-actions\">\r\n <button type=\"button\" class=\"custom-keyboard__shift\" [class.active]=\"uppercase()\" (click)=\"toggleCase()\">\r\n \u21E7 Shift\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__space\" (click)=\"enterSpace()\">\r\n Space\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"custom-keyboard__actions\">\r\n <button type=\"button\" class=\"custom-keyboard__delete\" aria-label=\"Delete previous character\"\r\n (click)=\"keyboard.backspace()\">\r\n <i class=\"pi pi-delete-left\"></i>\r\n Delete\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__done\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n</section>\r\n}", styles: [":host{display:contents}.custom-keyboard{position:fixed;right:0;bottom:0;left:0;z-index:200000;display:block;width:100%;max-height:min(52dvh,390px);padding:8px 6px calc(8px + env(safe-area-inset-bottom,0px));background:#d1d5db;box-shadow:0 -6px 20px #0f172a38;box-sizing:border-box;overflow-y:auto;-webkit-user-select:none;user-select:none;touch-action:manipulation}.custom-keyboard__toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:8px;margin-bottom:8px;padding:0 4px}.custom-keyboard__toolbar-button{padding:6px 10px;color:#126fd1;font-size:14px;font-weight:700;background:transparent;border:0}.custom-keyboard__type{color:#475569;font-size:12px;font-weight:700;text-align:center;text-transform:capitalize}.custom-keyboard__row{display:flex;justify-content:center;gap:4px;margin-bottom:6px}.custom-keyboard__key{flex:1 1 0;max-width:52px;min-width:0;height:42px;padding:0;color:#111827;font-size:16px;font-weight:700;background:#fff;border:0;border-radius:5px;box-shadow:0 1px 2px #0f172a47}.custom-keyboard--numeric .custom-keyboard__key{max-width:92px;height:46px;font-size:18px}.custom-keyboard__key:active,.custom-keyboard__text-actions button:active,.custom-keyboard__actions button:active{transform:scale(.96)}.custom-keyboard__text-actions{display:grid;grid-template-columns:minmax(90px,.4fr) 1fr;gap:6px;margin:2px 4px 6px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:42px;font-size:15px;font-weight:700;border:0;border-radius:5px}.custom-keyboard__shift{color:#172033;background:#aeb6c2}.custom-keyboard__shift.active{color:#fff;background:#64748b}.custom-keyboard__space{color:#172033;background:#fff}.custom-keyboard__actions{display:grid;grid-template-columns:1fr 1.4fr;gap:6px;padding:0 4px}.custom-keyboard__delete{color:#172033;background:#aeb6c2}.custom-keyboard__done{color:#fff;background:#1890ff}@media(max-height:650px){.custom-keyboard{max-height:58dvh}.custom-keyboard__key{height:35px}.custom-keyboard__row{margin-bottom:4px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:36px}}\n"] });
5130
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.2", type: CustomKeyboardComponent, isStandalone: true, selector: "vl-custom-keyboard", ngImport: i0, template: "@if (keyboard.activeSession(); as session) {\r\n<section class=\"custom-keyboard\" data-vl-custom-keyboard [class.custom-keyboard--numeric]=\"session.type === 'numeric'\"\r\n [attr.aria-label]=\"session.type + ' keyboard'\" (pointerdown)=\"$event.preventDefault()\">\r\n <div class=\"custom-keyboard__toolbar\">\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.clear()\">\r\n Clear\r\n </button>\r\n\r\n <span class=\"custom-keyboard__type\">\r\n {{ session.type }}\r\n </span>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n\r\n @for (row of rows; track $index) {\r\n <div class=\"custom-keyboard__row\">\r\n @for (key of row; track key) {\r\n <button type=\"button\" class=\"custom-keyboard__key\" (click)=\"enterKey(key)\">\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (\r\n session.type === 'alpha' ||\r\n session.type === 'string'\r\n ) {\r\n <div class=\"custom-keyboard__text-actions\">\r\n <button type=\"button\" class=\"custom-keyboard__shift\" [class.active]=\"uppercase()\" (click)=\"toggleCase()\">\r\n \u21E7 Shift\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__space\" (click)=\"enterSpace()\">\r\n Space\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"custom-keyboard__actions\">\r\n <button type=\"button\" class=\"custom-keyboard__delete\" aria-label=\"Delete previous character\"\r\n (click)=\"keyboard.backspace()\">\r\n <i class=\"pi pi-delete-left\"></i>\r\n Delete\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__done\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n</section>\r\n}", styles: [":host{display:contents}.custom-keyboard{position:fixed;right:0;bottom:0;left:0;z-index:200000;display:block;width:100%;max-height:min(52dvh,390px);padding:8px 6px calc(8px + env(safe-area-inset-bottom,0px));background:#d1d5db;box-shadow:0 -6px 20px #0f172a38;box-sizing:border-box;overflow-y:auto;-webkit-user-select:none;user-select:none;touch-action:manipulation}.custom-keyboard__toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:8px;margin-bottom:8px;padding:0 4px}.custom-keyboard__toolbar-button{padding:6px 10px;color:#126fd1;font-size:14px;font-weight:700;background:transparent;border:0}.custom-keyboard__type{color:#475569;font-size:12px;font-weight:700;text-align:center;text-transform:capitalize}.custom-keyboard__row{display:flex;justify-content:center;gap:4px;margin-bottom:6px}.custom-keyboard__key{flex:1 1 0;max-width:52px;min-width:0;height:42px;padding:0;color:#111827;font-size:16px;font-weight:700;background:#fff;border:0;border-radius:5px;box-shadow:0 1px 2px #0f172a47}.custom-keyboard--numeric .custom-keyboard__key{max-width:92px;height:46px;font-size:18px}.custom-keyboard__key:active,.custom-keyboard__text-actions button:active,.custom-keyboard__actions button:active{transform:scale(.96)}.custom-keyboard__text-actions{display:grid;grid-template-columns:minmax(90px,.4fr) 1fr;gap:6px;margin:2px 4px 6px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:42px;font-size:15px;font-weight:700;border:0;border-radius:5px}.custom-keyboard__shift{color:#172033;background:#aeb6c2}.custom-keyboard__shift.active{color:#fff;background:#64748b}.custom-keyboard__space{color:#172033;background:#fff}.custom-keyboard__actions{display:grid;grid-template-columns:1fr 1.4fr;gap:6px;padding:0 4px}.custom-keyboard__delete{color:#172033;background:#aeb6c2}.custom-keyboard__done{color:#fff;background:#1890ff}@media(max-height:650px){.custom-keyboard{max-height:58dvh}.custom-keyboard__key{height:35px}.custom-keyboard__row{margin-bottom:4px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:36px}}\n"] });
5046
5131
  }
5047
5132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: CustomKeyboardComponent, decorators: [{
5048
5133
  type: Component,
5049
- args: [{ selector: 'vl-custom-keyboard', standalone: true, template: "@if (keyboard.activeSession(); as session) {\r\n<section class=\"custom-keyboard\" [class.custom-keyboard--numeric]=\"session.type === 'numeric'\"\r\n [attr.aria-label]=\"session.type + ' keyboard'\" (pointerdown)=\"$event.preventDefault()\">\r\n <div class=\"custom-keyboard__toolbar\">\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.clear()\">\r\n Clear\r\n </button>\r\n\r\n <span class=\"custom-keyboard__type\">\r\n {{ session.type }}\r\n </span>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n\r\n @for (row of rows; track $index) {\r\n <div class=\"custom-keyboard__row\">\r\n @for (key of row; track key) {\r\n <button type=\"button\" class=\"custom-keyboard__key\" (click)=\"enterKey(key)\">\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (\r\n session.type === 'alpha' ||\r\n session.type === 'string'\r\n ) {\r\n <div class=\"custom-keyboard__text-actions\">\r\n <button type=\"button\" class=\"custom-keyboard__shift\" [class.active]=\"uppercase()\" (click)=\"toggleCase()\">\r\n \u21E7 Shift\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__space\" (click)=\"enterSpace()\">\r\n Space\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"custom-keyboard__actions\">\r\n <button type=\"button\" class=\"custom-keyboard__delete\" aria-label=\"Delete previous character\"\r\n (click)=\"keyboard.backspace()\">\r\n <i class=\"pi pi-delete-left\"></i>\r\n Delete\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__done\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n</section>\r\n}", styles: [":host{display:contents}.custom-keyboard{position:fixed;right:0;bottom:0;left:0;z-index:200000;display:block;width:100%;max-height:min(52dvh,390px);padding:8px 6px calc(8px + env(safe-area-inset-bottom,0px));background:#d1d5db;box-shadow:0 -6px 20px #0f172a38;box-sizing:border-box;overflow-y:auto;-webkit-user-select:none;user-select:none;touch-action:manipulation}.custom-keyboard__toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:8px;margin-bottom:8px;padding:0 4px}.custom-keyboard__toolbar-button{padding:6px 10px;color:#126fd1;font-size:14px;font-weight:700;background:transparent;border:0}.custom-keyboard__type{color:#475569;font-size:12px;font-weight:700;text-align:center;text-transform:capitalize}.custom-keyboard__row{display:flex;justify-content:center;gap:4px;margin-bottom:6px}.custom-keyboard__key{flex:1 1 0;max-width:52px;min-width:0;height:42px;padding:0;color:#111827;font-size:16px;font-weight:700;background:#fff;border:0;border-radius:5px;box-shadow:0 1px 2px #0f172a47}.custom-keyboard--numeric .custom-keyboard__key{max-width:92px;height:46px;font-size:18px}.custom-keyboard__key:active,.custom-keyboard__text-actions button:active,.custom-keyboard__actions button:active{transform:scale(.96)}.custom-keyboard__text-actions{display:grid;grid-template-columns:minmax(90px,.4fr) 1fr;gap:6px;margin:2px 4px 6px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:42px;font-size:15px;font-weight:700;border:0;border-radius:5px}.custom-keyboard__shift{color:#172033;background:#aeb6c2}.custom-keyboard__shift.active{color:#fff;background:#64748b}.custom-keyboard__space{color:#172033;background:#fff}.custom-keyboard__actions{display:grid;grid-template-columns:1fr 1.4fr;gap:6px;padding:0 4px}.custom-keyboard__delete{color:#172033;background:#aeb6c2}.custom-keyboard__done{color:#fff;background:#1890ff}@media(max-height:650px){.custom-keyboard{max-height:58dvh}.custom-keyboard__key{height:35px}.custom-keyboard__row{margin-bottom:4px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:36px}}\n"] }]
5134
+ args: [{ selector: 'vl-custom-keyboard', standalone: true, template: "@if (keyboard.activeSession(); as session) {\r\n<section class=\"custom-keyboard\" data-vl-custom-keyboard [class.custom-keyboard--numeric]=\"session.type === 'numeric'\"\r\n [attr.aria-label]=\"session.type + ' keyboard'\" (pointerdown)=\"$event.preventDefault()\">\r\n <div class=\"custom-keyboard__toolbar\">\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.clear()\">\r\n Clear\r\n </button>\r\n\r\n <span class=\"custom-keyboard__type\">\r\n {{ session.type }}\r\n </span>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__toolbar-button\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n\r\n @for (row of rows; track $index) {\r\n <div class=\"custom-keyboard__row\">\r\n @for (key of row; track key) {\r\n <button type=\"button\" class=\"custom-keyboard__key\" (click)=\"enterKey(key)\">\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (\r\n session.type === 'alpha' ||\r\n session.type === 'string'\r\n ) {\r\n <div class=\"custom-keyboard__text-actions\">\r\n <button type=\"button\" class=\"custom-keyboard__shift\" [class.active]=\"uppercase()\" (click)=\"toggleCase()\">\r\n \u21E7 Shift\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__space\" (click)=\"enterSpace()\">\r\n Space\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"custom-keyboard__actions\">\r\n <button type=\"button\" class=\"custom-keyboard__delete\" aria-label=\"Delete previous character\"\r\n (click)=\"keyboard.backspace()\">\r\n <i class=\"pi pi-delete-left\"></i>\r\n Delete\r\n </button>\r\n\r\n <button type=\"button\" class=\"custom-keyboard__done\" (click)=\"keyboard.close()\">\r\n Done\r\n </button>\r\n </div>\r\n</section>\r\n}", styles: [":host{display:contents}.custom-keyboard{position:fixed;right:0;bottom:0;left:0;z-index:200000;display:block;width:100%;max-height:min(52dvh,390px);padding:8px 6px calc(8px + env(safe-area-inset-bottom,0px));background:#d1d5db;box-shadow:0 -6px 20px #0f172a38;box-sizing:border-box;overflow-y:auto;-webkit-user-select:none;user-select:none;touch-action:manipulation}.custom-keyboard__toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:8px;margin-bottom:8px;padding:0 4px}.custom-keyboard__toolbar-button{padding:6px 10px;color:#126fd1;font-size:14px;font-weight:700;background:transparent;border:0}.custom-keyboard__type{color:#475569;font-size:12px;font-weight:700;text-align:center;text-transform:capitalize}.custom-keyboard__row{display:flex;justify-content:center;gap:4px;margin-bottom:6px}.custom-keyboard__key{flex:1 1 0;max-width:52px;min-width:0;height:42px;padding:0;color:#111827;font-size:16px;font-weight:700;background:#fff;border:0;border-radius:5px;box-shadow:0 1px 2px #0f172a47}.custom-keyboard--numeric .custom-keyboard__key{max-width:92px;height:46px;font-size:18px}.custom-keyboard__key:active,.custom-keyboard__text-actions button:active,.custom-keyboard__actions button:active{transform:scale(.96)}.custom-keyboard__text-actions{display:grid;grid-template-columns:minmax(90px,.4fr) 1fr;gap:6px;margin:2px 4px 6px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:42px;font-size:15px;font-weight:700;border:0;border-radius:5px}.custom-keyboard__shift{color:#172033;background:#aeb6c2}.custom-keyboard__shift.active{color:#fff;background:#64748b}.custom-keyboard__space{color:#172033;background:#fff}.custom-keyboard__actions{display:grid;grid-template-columns:1fr 1.4fr;gap:6px;padding:0 4px}.custom-keyboard__delete{color:#172033;background:#aeb6c2}.custom-keyboard__done{color:#fff;background:#1890ff}@media(max-height:650px){.custom-keyboard{max-height:58dvh}.custom-keyboard__key{height:35px}.custom-keyboard__row{margin-bottom:4px}.custom-keyboard__text-actions button,.custom-keyboard__actions button{height:36px}}\n"] }]
5050
5135
  }] });
5051
5136
 
5052
5137
  /*