@retalia/pos-components 0.0.16 → 0.0.18

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.
@@ -1,6 +1,28 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, signal, computed, ChangeDetectionStrategy, Component, viewChild, inject, DestroyRef, afterNextRender, InjectionToken, booleanAttribute, ElementRef, contentChildren, linkedSignal, effect, untracked, forwardRef } from '@angular/core';
2
+ import { Directive, input, output, signal, computed, ChangeDetectionStrategy, Component, viewChild, linkedSignal, afterRenderEffect, inject, DestroyRef, afterNextRender, InjectionToken, booleanAttribute, ElementRef, contentChildren, effect, untracked, forwardRef } from '@angular/core';
3
3
 
4
+ /** Projects partner content into the login shop column, after the date and POS number. */
5
+ class PosLoginAside {
6
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLoginAside, deps: [], target: i0.ɵɵFactoryTarget.Directive });
7
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.22", type: PosLoginAside, isStandalone: true, selector: "[posLoginAside]", ngImport: i0 });
8
+ }
9
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLoginAside, decorators: [{
10
+ type: Directive,
11
+ args: [{
12
+ selector: '[posLoginAside]',
13
+ }]
14
+ }] });
15
+ /** Projects partner content under the login keypad. */
16
+ class PosLoginPanel {
17
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLoginPanel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
18
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.22", type: PosLoginPanel, isStandalone: true, selector: "[posLoginPanel]", ngImport: i0 });
19
+ }
20
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLoginPanel, decorators: [{
21
+ type: Directive,
22
+ args: [{
23
+ selector: '[posLoginPanel]',
24
+ }]
25
+ }] });
4
26
  const DEFAULT_SESSION = { status: 'signedOut' };
5
27
  const DIGIT_KEYS = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
6
28
  class PosLogin {
@@ -116,15 +138,264 @@ class PosLogin {
116
138
  this.action.emit({ type: 'login.back' });
117
139
  }
118
140
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLogin, deps: [], target: i0.ɵɵFactoryTarget.Component });
119
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosLogin, isStandalone: true, selector: "pos-login", inputs: { errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, session: { classPropertyName: "session", publicName: "session", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, titleClerkNumber: { classPropertyName: "titleClerkNumber", publicName: "titleClerkNumber", isSignal: true, isRequired: false, transformFunction: null }, titleClerkPassword: { classPropertyName: "titleClerkPassword", publicName: "titleClerkPassword", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, loginLabel: { classPropertyName: "loginLabel", publicName: "loginLabel", isSignal: true, isRequired: false, transformFunction: null }, showAside: { classPropertyName: "showAside", publicName: "showAside", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, showBrandImage: { classPropertyName: "showBrandImage", publicName: "showBrandImage", isSignal: true, isRequired: false, transformFunction: null }, brandImage: { classPropertyName: "brandImage", publicName: "brandImage", isSignal: true, isRequired: false, transformFunction: null }, brandLabel: { classPropertyName: "brandLabel", publicName: "brandLabel", isSignal: true, isRequired: false, transformFunction: null }, locationName: { classPropertyName: "locationName", publicName: "locationName", isSignal: true, isRequired: false, transformFunction: null }, terminalLine: { classPropertyName: "terminalLine", publicName: "terminalLine", isSignal: true, isRequired: false, transformFunction: null }, shopName: { classPropertyName: "shopName", publicName: "shopName", isSignal: true, isRequired: false, transformFunction: null }, dateLabel: { classPropertyName: "dateLabel", publicName: "dateLabel", isSignal: true, isRequired: false, transformFunction: null }, posNumberLabel: { classPropertyName: "posNumberLabel", publicName: "posNumberLabel", isSignal: true, isRequired: false, transformFunction: null }, posNumber: { classPropertyName: "posNumber", publicName: "posNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-login" }, ngImport: i0, template: "<div\r\n class=\"pos-login__shell\"\r\n [class.pos-login__shell--aside]=\"showAside()\"\r\n [class.pos-login__shell--bordered]=\"bordered()\"\r\n>\r\n @if (showAside()) {\r\n <aside class=\"pos-login__aside\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-login__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-login__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-login__brand-image\"\r\n viewBox=\"492.40 241.70 51.34 54.94\"\r\n [attr.aria-hidden]=\"brandLabel() ? true : null\"\r\n [attr.aria-label]=\"brandLabel() ? null : 'Retalia'\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 522.628906 291.910156 C 522.636719 293.0625 523.441406 293.511719 524.425781 292.914062 L 540.464844 283.207031 C 541.449219 282.613281 542.246094 281.195312 542.246094 280.046875 L 542.246094 261.132812 C 542.246094 259.980469 541.441406 259.523438 540.453125 260.113281 L 524.292969 269.691406 C 523.300781 270.277344 522.503906 271.683594 522.511719 272.835938 Z M 522.628906 291.910156\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 539.097656 253.351562 L 517.101562 243.664062 C 516.066406 243.203125 514.417969 243.265625 513.421875 243.804688 L 495.835938 253.308594 C 494.839844 253.847656 494.027344 255.214844 494.023438 256.367188 L 493.910156 280.140625 C 493.902344 281.292969 494.699219 282.679688 495.683594 283.234375 L 501.734375 286.640625 C 502.71875 287.199219 503.503906 286.71875 503.480469 285.566406 L 503.214844 271.488281 C 503.207031 271.082031 503.492188 270.894531 503.855469 271.066406 L 506.128906 272.148438 C 507.152344 272.636719 507.980469 273.960938 507.980469 275.113281 L 507.980469 287.839844 C 507.980469 288.992188 508.773438 290.394531 509.746094 290.972656 L 515.777344 294.5625 C 516.753906 295.140625 517.554688 294.679688 517.566406 293.527344 L 517.800781 273.300781 C 517.808594 272.488281 517.539062 271.238281 517.195312 270.503906 L 515.460938 266.789062 C 515.292969 266.421875 515.476562 266.109375 515.871094 266.089844 L 518.925781 265.941406 C 520.050781 265.886719 521.761719 265.378906 522.738281 264.808594 L 539.195312 255.21875 C 540.175781 254.648438 540.132812 253.8125 539.097656 253.351562 M 520.609375 255.050781 L 518.019531 256.585938 C 516.914062 257.125 515.734375 257.289062 514.710938 256.804688 L 511.078125 255.101562 C 510.054688 254.621094 510.023438 253.773438 511.003906 253.210938 L 513.835938 251.597656 C 514.53125 251.203125 515.691406 251.132812 516.425781 251.445312 L 520.449219 253.128906 C 521.488281 253.570312 521.5625 254.429688 520.609375 255.050781\"\r\n />\r\n </svg>\r\n }\r\n }\r\n @if (brandLabel()) {\r\n <span class=\"pos-login__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (locationName() || terminalLine()) {\r\n <div class=\"pos-login__place\">\r\n @if (locationName()) {\r\n <p class=\"pos-login__location\">{{ locationName() }}</p>\r\n }\r\n @if (terminalLine()) {\r\n <p class=\"pos-login__terminal\">{{ terminalLine() }}</p>\r\n }\r\n @if (shopName()) {\r\n <p class=\"pos-login__terminal\">{{ shopName() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-login__facts\">\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ dateLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ shownDate() }}</p>\r\n </div>\r\n @if (posNumber()) {\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ posNumberLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ posNumber() }}</p>\r\n </div>\r\n }\r\n </div>\r\n </aside>\r\n }\r\n\r\n<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <div class=\"pos-login__main\">\r\n <header class=\"pos-login__header\">\r\n <h1 class=\"pos-login__heading\">{{ heading() }}</h1>\r\n @if (showBack()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__back\"\r\n aria-label=\"Back\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onBack()\"\r\n >\r\n Back\r\n </button>\r\n }\r\n </header>\r\n\r\n <div class=\"pos-login__display\">\r\n <p class=\"pos-login__title\" [class.pos-login__title--entry]=\"hasEntry()\">{{ displayText() }}</p>\r\n <input\r\n class=\"pos-login__input\"\r\n [attr.type]=\"maskInput() ? 'password' : 'text'\"\r\n [value]=\"inputValue()\"\r\n maxlength=\"12\"\r\n readonly\r\n tabindex=\"-1\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-label=\"Login code\"\r\n />\r\n </div>\r\n\r\n <div class=\"pos-login__keypad\" role=\"group\" aria-label=\"Keypad\">\r\n @for (key of digitKeys; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key pos-login__key--delete\"\r\n aria-label=\"Delete\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('\u2190')\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 5h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-5-7 5-7Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"m14 10 4 4m0-4-4 4\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('0')\"\r\n >\r\n 0\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [attr.aria-label]=\"primaryLabel()\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M5 12.5 9.5 17 19 7.5\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2.2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n @if (sessionStatusText() || errorMessage()) {\r\n <div class=\"pos-login__status\" aria-live=\"polite\">\r\n @if (sessionStatusText()) {\r\n <p>{{ sessionStatusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-login__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</section>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;min-height:100vh;align-items:center;justify-content:center;padding:var(--pos-space-lg);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:transparent}*{box-sizing:border-box}.pos-login__shell{display:flex;flex-direction:column;width:min(22rem,100%);min-width:0}.pos-login__shell--aside{width:min(56rem,100%);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay);overflow:hidden}.pos-login__shell--bordered{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__aside{display:flex;flex-direction:column;gap:var(--pos-space-xl);min-width:0;padding:var(--pos-space-xl);border-bottom:1px solid var(--pos-color-border)}.pos-login__brand{display:flex;align-items:center;gap:var(--pos-space-sm)}.pos-login__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-login__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-login__place{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-login__location{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__terminal{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-login__facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__fact{min-width:0;padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__fact-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-login__fact-value{margin:var(--pos-space-xs) 0 0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-login__panel{display:flex;flex:1 1 auto;align-items:flex-start;justify-content:center;width:100%;min-width:0;padding:var(--pos-space-xl)}.pos-login__shell:not(.pos-login__shell--aside) .pos-login__panel{padding:0}.pos-login__main{display:flex;flex-direction:column;gap:var(--pos-space-md);width:min(22rem,100%)}.pos-login__header{display:flex;align-items:center;justify-content:space-between;gap:var(--pos-space-sm);min-height:var(--pos-space-xl)}.pos-login__heading{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__display{position:relative;display:flex;align-items:center;justify-content:center;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) + var(--pos-space-lg));padding:var(--pos-space-md) var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-login__title{margin:0;max-width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:calc(var(--pos-font-size-xl) * 1.3);font-weight:var(--pos-font-weight-bold);line-height:1.2;text-align:center;overflow-wrap:anywhere}.pos-login__title--entry{letter-spacing:var(--pos-letter-spacing-display)}.pos-login__input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.pos-login__keypad{display:grid;width:100%;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-sm)}.pos-login__key,.pos-login__primary,.pos-login__back{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-login__key,.pos-login__primary{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-semibold);transition:background .12s ease,border-color .12s ease,color .12s ease,transform 80ms ease,filter .12s ease}.pos-login__key--delete{color:var(--pos-color-text-muted)}.pos-login__key:hover:not(:disabled){border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 22%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-login__key:active:not(:disabled),.pos-login__primary:active:not(:disabled),.pos-login__back:active:not(:disabled){transform:scale(.985)}.pos-login__key:disabled,.pos-login__back:disabled,.pos-login__primary:disabled{cursor:not-allowed;opacity:.45;transform:none;filter:none}.pos-login__key:focus-visible,.pos-login__primary:focus-visible,.pos-login__back:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-login__primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-login__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-login__back{border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__back:hover:not(:disabled){color:var(--pos-color-text)}.pos-login__status{display:flex;flex-direction:column;gap:var(--pos-space-xs);text-align:center}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{color:var(--pos-color-danger)}@media(min-width:768px){.pos-login__shell--aside{flex-direction:row;align-items:stretch}.pos-login__aside,.pos-login__panel{flex:1 1 50%}.pos-login__aside{border-bottom:0;border-right:1px solid var(--pos-color-border);padding:var(--pos-space-2xl)}.pos-login__key,.pos-login__primary{min-height:var(--pos-keypad-size-md)}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary,.pos-login__back{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
141
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosLogin, isStandalone: true, selector: "pos-login", inputs: { errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, session: { classPropertyName: "session", publicName: "session", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, titleClerkNumber: { classPropertyName: "titleClerkNumber", publicName: "titleClerkNumber", isSignal: true, isRequired: false, transformFunction: null }, titleClerkPassword: { classPropertyName: "titleClerkPassword", publicName: "titleClerkPassword", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, loginLabel: { classPropertyName: "loginLabel", publicName: "loginLabel", isSignal: true, isRequired: false, transformFunction: null }, showAside: { classPropertyName: "showAside", publicName: "showAside", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, showBrandImage: { classPropertyName: "showBrandImage", publicName: "showBrandImage", isSignal: true, isRequired: false, transformFunction: null }, brandImage: { classPropertyName: "brandImage", publicName: "brandImage", isSignal: true, isRequired: false, transformFunction: null }, brandLabel: { classPropertyName: "brandLabel", publicName: "brandLabel", isSignal: true, isRequired: false, transformFunction: null }, locationName: { classPropertyName: "locationName", publicName: "locationName", isSignal: true, isRequired: false, transformFunction: null }, terminalLine: { classPropertyName: "terminalLine", publicName: "terminalLine", isSignal: true, isRequired: false, transformFunction: null }, shopName: { classPropertyName: "shopName", publicName: "shopName", isSignal: true, isRequired: false, transformFunction: null }, dateLabel: { classPropertyName: "dateLabel", publicName: "dateLabel", isSignal: true, isRequired: false, transformFunction: null }, posNumberLabel: { classPropertyName: "posNumberLabel", publicName: "posNumberLabel", isSignal: true, isRequired: false, transformFunction: null }, posNumber: { classPropertyName: "posNumber", publicName: "posNumber", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-login" }, ngImport: i0, template: "<div\r\n class=\"pos-login__shell\"\r\n [class.pos-login__shell--aside]=\"showAside()\"\r\n [class.pos-login__shell--bordered]=\"bordered()\"\r\n>\r\n @if (showAside()) {\r\n <aside class=\"pos-login__aside\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-login__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-login__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-login__brand-image\"\r\n viewBox=\"492.40 241.70 51.34 54.94\"\r\n [attr.aria-hidden]=\"brandLabel() ? true : null\"\r\n [attr.aria-label]=\"brandLabel() ? null : 'Retalia'\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 522.628906 291.910156 C 522.636719 293.0625 523.441406 293.511719 524.425781 292.914062 L 540.464844 283.207031 C 541.449219 282.613281 542.246094 281.195312 542.246094 280.046875 L 542.246094 261.132812 C 542.246094 259.980469 541.441406 259.523438 540.453125 260.113281 L 524.292969 269.691406 C 523.300781 270.277344 522.503906 271.683594 522.511719 272.835938 Z M 522.628906 291.910156\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 539.097656 253.351562 L 517.101562 243.664062 C 516.066406 243.203125 514.417969 243.265625 513.421875 243.804688 L 495.835938 253.308594 C 494.839844 253.847656 494.027344 255.214844 494.023438 256.367188 L 493.910156 280.140625 C 493.902344 281.292969 494.699219 282.679688 495.683594 283.234375 L 501.734375 286.640625 C 502.71875 287.199219 503.503906 286.71875 503.480469 285.566406 L 503.214844 271.488281 C 503.207031 271.082031 503.492188 270.894531 503.855469 271.066406 L 506.128906 272.148438 C 507.152344 272.636719 507.980469 273.960938 507.980469 275.113281 L 507.980469 287.839844 C 507.980469 288.992188 508.773438 290.394531 509.746094 290.972656 L 515.777344 294.5625 C 516.753906 295.140625 517.554688 294.679688 517.566406 293.527344 L 517.800781 273.300781 C 517.808594 272.488281 517.539062 271.238281 517.195312 270.503906 L 515.460938 266.789062 C 515.292969 266.421875 515.476562 266.109375 515.871094 266.089844 L 518.925781 265.941406 C 520.050781 265.886719 521.761719 265.378906 522.738281 264.808594 L 539.195312 255.21875 C 540.175781 254.648438 540.132812 253.8125 539.097656 253.351562 M 520.609375 255.050781 L 518.019531 256.585938 C 516.914062 257.125 515.734375 257.289062 514.710938 256.804688 L 511.078125 255.101562 C 510.054688 254.621094 510.023438 253.773438 511.003906 253.210938 L 513.835938 251.597656 C 514.53125 251.203125 515.691406 251.132812 516.425781 251.445312 L 520.449219 253.128906 C 521.488281 253.570312 521.5625 254.429688 520.609375 255.050781\"\r\n />\r\n </svg>\r\n }\r\n }\r\n @if (brandLabel()) {\r\n <span class=\"pos-login__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (locationName() || terminalLine()) {\r\n <div class=\"pos-login__place\">\r\n @if (locationName()) {\r\n <p class=\"pos-login__location\">{{ locationName() }}</p>\r\n }\r\n @if (terminalLine()) {\r\n <p class=\"pos-login__terminal\">{{ terminalLine() }}</p>\r\n }\r\n @if (shopName()) {\r\n <p class=\"pos-login__terminal\">{{ shopName() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-login__facts\">\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ dateLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ shownDate() }}</p>\r\n </div>\r\n @if (posNumber()) {\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ posNumberLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ posNumber() }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Custom content slot -->\r\n <div class=\"pos-login__slot\">\r\n <ng-content select=\"[posLoginAside]\" />\r\n </div>\r\n </aside>\r\n }\r\n\r\n<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <div class=\"pos-login__main\">\r\n <header class=\"pos-login__header\">\r\n <h1 class=\"pos-login__heading\">{{ heading() }}</h1>\r\n @if (showBack()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__back\"\r\n aria-label=\"Back\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onBack()\"\r\n >\r\n Back\r\n </button>\r\n }\r\n </header>\r\n\r\n <div class=\"pos-login__display\">\r\n <p class=\"pos-login__title\" [class.pos-login__title--entry]=\"hasEntry()\">{{ displayText() }}</p>\r\n <input\r\n class=\"pos-login__input\"\r\n [attr.type]=\"maskInput() ? 'password' : 'text'\"\r\n [value]=\"inputValue()\"\r\n maxlength=\"12\"\r\n readonly\r\n tabindex=\"-1\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-label=\"Login code\"\r\n />\r\n </div>\r\n\r\n <div class=\"pos-login__keypad\" role=\"group\" aria-label=\"Keypad\">\r\n @for (key of digitKeys; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key pos-login__key--delete\"\r\n aria-label=\"Delete\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('\u2190')\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 5h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-5-7 5-7Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"m14 10 4 4m0-4-4 4\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('0')\"\r\n >\r\n 0\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [attr.aria-label]=\"primaryLabel()\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M5 12.5 9.5 17 19 7.5\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2.2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n @if (sessionStatusText() || errorMessage()) {\r\n <div class=\"pos-login__status\" aria-live=\"polite\">\r\n @if (sessionStatusText()) {\r\n <p>{{ sessionStatusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-login__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- // Custom content slot -->\r\n <div class=\"pos-login__slot\">\r\n <ng-content select=\"[posLoginPanel]\" />\r\n </div>\r\n </div>\r\n</section>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;min-height:100vh;align-items:center;justify-content:center;padding:var(--pos-space-lg);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:transparent}*{box-sizing:border-box}.pos-login__shell{display:flex;flex-direction:column;width:min(22rem,100%);min-width:0}.pos-login__shell--aside{width:min(56rem,100%);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay);overflow:hidden}.pos-login__shell--bordered{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__aside{display:flex;flex-direction:column;gap:var(--pos-space-xl);min-width:0;padding:var(--pos-space-xl);border-bottom:1px solid var(--pos-color-border)}.pos-login__brand{display:flex;align-items:center;gap:var(--pos-space-sm)}.pos-login__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-login__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-login__place{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-login__location{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__terminal{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-login__facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__fact{min-width:0;padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__fact-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-login__fact-value{margin:var(--pos-space-xs) 0 0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-login__slot{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-login__slot:not(:has(*)){display:none}.pos-login__panel{display:flex;flex:1 1 auto;align-items:flex-start;justify-content:center;width:100%;min-width:0;padding:var(--pos-space-xl)}.pos-login__shell:not(.pos-login__shell--aside) .pos-login__panel{padding:0}.pos-login__main{display:flex;flex-direction:column;gap:var(--pos-space-md);width:min(22rem,100%)}.pos-login__header{display:flex;align-items:center;justify-content:space-between;gap:var(--pos-space-sm);min-height:var(--pos-space-xl)}.pos-login__heading{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__display{position:relative;display:flex;align-items:center;justify-content:center;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) + var(--pos-space-lg));padding:var(--pos-space-md) var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-login__title{margin:0;max-width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:calc(var(--pos-font-size-xl) * 1.3);font-weight:var(--pos-font-weight-bold);line-height:1.2;text-align:center;overflow-wrap:anywhere}.pos-login__title--entry{letter-spacing:var(--pos-letter-spacing-display)}.pos-login__input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.pos-login__keypad{display:grid;width:100%;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-sm)}.pos-login__key,.pos-login__primary,.pos-login__back{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-login__key,.pos-login__primary{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-semibold);transition:background .12s ease,border-color .12s ease,color .12s ease,transform 80ms ease,filter .12s ease}.pos-login__key--delete{color:var(--pos-color-text-muted)}.pos-login__key:hover:not(:disabled){border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 22%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-login__key:active:not(:disabled),.pos-login__primary:active:not(:disabled),.pos-login__back:active:not(:disabled){transform:scale(.985)}.pos-login__key:disabled,.pos-login__back:disabled,.pos-login__primary:disabled{cursor:not-allowed;opacity:.45;transform:none;filter:none}.pos-login__key:focus-visible,.pos-login__primary:focus-visible,.pos-login__back:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-login__primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-login__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-login__back{border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__back:hover:not(:disabled){color:var(--pos-color-text)}.pos-login__status{display:flex;flex-direction:column;gap:var(--pos-space-xs);text-align:center}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{color:var(--pos-color-danger)}@media(min-width:768px){.pos-login__shell--aside{flex-direction:row;align-items:stretch}.pos-login__aside,.pos-login__panel{flex:1 1 50%}.pos-login__aside{border-bottom:0;border-right:1px solid var(--pos-color-border);padding:var(--pos-space-2xl)}.pos-login__key,.pos-login__primary{min-height:var(--pos-keypad-size-md)}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary,.pos-login__back{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
120
142
  }
121
143
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLogin, decorators: [{
122
144
  type: Component,
123
145
  args: [{ selector: 'pos-login', changeDetection: ChangeDetectionStrategy.OnPush, host: {
124
146
  class: 'pos-login',
125
- }, template: "<div\r\n class=\"pos-login__shell\"\r\n [class.pos-login__shell--aside]=\"showAside()\"\r\n [class.pos-login__shell--bordered]=\"bordered()\"\r\n>\r\n @if (showAside()) {\r\n <aside class=\"pos-login__aside\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-login__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-login__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-login__brand-image\"\r\n viewBox=\"492.40 241.70 51.34 54.94\"\r\n [attr.aria-hidden]=\"brandLabel() ? true : null\"\r\n [attr.aria-label]=\"brandLabel() ? null : 'Retalia'\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 522.628906 291.910156 C 522.636719 293.0625 523.441406 293.511719 524.425781 292.914062 L 540.464844 283.207031 C 541.449219 282.613281 542.246094 281.195312 542.246094 280.046875 L 542.246094 261.132812 C 542.246094 259.980469 541.441406 259.523438 540.453125 260.113281 L 524.292969 269.691406 C 523.300781 270.277344 522.503906 271.683594 522.511719 272.835938 Z M 522.628906 291.910156\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 539.097656 253.351562 L 517.101562 243.664062 C 516.066406 243.203125 514.417969 243.265625 513.421875 243.804688 L 495.835938 253.308594 C 494.839844 253.847656 494.027344 255.214844 494.023438 256.367188 L 493.910156 280.140625 C 493.902344 281.292969 494.699219 282.679688 495.683594 283.234375 L 501.734375 286.640625 C 502.71875 287.199219 503.503906 286.71875 503.480469 285.566406 L 503.214844 271.488281 C 503.207031 271.082031 503.492188 270.894531 503.855469 271.066406 L 506.128906 272.148438 C 507.152344 272.636719 507.980469 273.960938 507.980469 275.113281 L 507.980469 287.839844 C 507.980469 288.992188 508.773438 290.394531 509.746094 290.972656 L 515.777344 294.5625 C 516.753906 295.140625 517.554688 294.679688 517.566406 293.527344 L 517.800781 273.300781 C 517.808594 272.488281 517.539062 271.238281 517.195312 270.503906 L 515.460938 266.789062 C 515.292969 266.421875 515.476562 266.109375 515.871094 266.089844 L 518.925781 265.941406 C 520.050781 265.886719 521.761719 265.378906 522.738281 264.808594 L 539.195312 255.21875 C 540.175781 254.648438 540.132812 253.8125 539.097656 253.351562 M 520.609375 255.050781 L 518.019531 256.585938 C 516.914062 257.125 515.734375 257.289062 514.710938 256.804688 L 511.078125 255.101562 C 510.054688 254.621094 510.023438 253.773438 511.003906 253.210938 L 513.835938 251.597656 C 514.53125 251.203125 515.691406 251.132812 516.425781 251.445312 L 520.449219 253.128906 C 521.488281 253.570312 521.5625 254.429688 520.609375 255.050781\"\r\n />\r\n </svg>\r\n }\r\n }\r\n @if (brandLabel()) {\r\n <span class=\"pos-login__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (locationName() || terminalLine()) {\r\n <div class=\"pos-login__place\">\r\n @if (locationName()) {\r\n <p class=\"pos-login__location\">{{ locationName() }}</p>\r\n }\r\n @if (terminalLine()) {\r\n <p class=\"pos-login__terminal\">{{ terminalLine() }}</p>\r\n }\r\n @if (shopName()) {\r\n <p class=\"pos-login__terminal\">{{ shopName() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-login__facts\">\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ dateLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ shownDate() }}</p>\r\n </div>\r\n @if (posNumber()) {\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ posNumberLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ posNumber() }}</p>\r\n </div>\r\n }\r\n </div>\r\n </aside>\r\n }\r\n\r\n<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <div class=\"pos-login__main\">\r\n <header class=\"pos-login__header\">\r\n <h1 class=\"pos-login__heading\">{{ heading() }}</h1>\r\n @if (showBack()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__back\"\r\n aria-label=\"Back\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onBack()\"\r\n >\r\n Back\r\n </button>\r\n }\r\n </header>\r\n\r\n <div class=\"pos-login__display\">\r\n <p class=\"pos-login__title\" [class.pos-login__title--entry]=\"hasEntry()\">{{ displayText() }}</p>\r\n <input\r\n class=\"pos-login__input\"\r\n [attr.type]=\"maskInput() ? 'password' : 'text'\"\r\n [value]=\"inputValue()\"\r\n maxlength=\"12\"\r\n readonly\r\n tabindex=\"-1\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-label=\"Login code\"\r\n />\r\n </div>\r\n\r\n <div class=\"pos-login__keypad\" role=\"group\" aria-label=\"Keypad\">\r\n @for (key of digitKeys; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key pos-login__key--delete\"\r\n aria-label=\"Delete\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('\u2190')\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 5h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-5-7 5-7Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"m14 10 4 4m0-4-4 4\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('0')\"\r\n >\r\n 0\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [attr.aria-label]=\"primaryLabel()\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M5 12.5 9.5 17 19 7.5\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2.2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n @if (sessionStatusText() || errorMessage()) {\r\n <div class=\"pos-login__status\" aria-live=\"polite\">\r\n @if (sessionStatusText()) {\r\n <p>{{ sessionStatusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-login__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</section>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;min-height:100vh;align-items:center;justify-content:center;padding:var(--pos-space-lg);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:transparent}*{box-sizing:border-box}.pos-login__shell{display:flex;flex-direction:column;width:min(22rem,100%);min-width:0}.pos-login__shell--aside{width:min(56rem,100%);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay);overflow:hidden}.pos-login__shell--bordered{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__aside{display:flex;flex-direction:column;gap:var(--pos-space-xl);min-width:0;padding:var(--pos-space-xl);border-bottom:1px solid var(--pos-color-border)}.pos-login__brand{display:flex;align-items:center;gap:var(--pos-space-sm)}.pos-login__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-login__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-login__place{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-login__location{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__terminal{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-login__facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__fact{min-width:0;padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__fact-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-login__fact-value{margin:var(--pos-space-xs) 0 0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-login__panel{display:flex;flex:1 1 auto;align-items:flex-start;justify-content:center;width:100%;min-width:0;padding:var(--pos-space-xl)}.pos-login__shell:not(.pos-login__shell--aside) .pos-login__panel{padding:0}.pos-login__main{display:flex;flex-direction:column;gap:var(--pos-space-md);width:min(22rem,100%)}.pos-login__header{display:flex;align-items:center;justify-content:space-between;gap:var(--pos-space-sm);min-height:var(--pos-space-xl)}.pos-login__heading{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__display{position:relative;display:flex;align-items:center;justify-content:center;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) + var(--pos-space-lg));padding:var(--pos-space-md) var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-login__title{margin:0;max-width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:calc(var(--pos-font-size-xl) * 1.3);font-weight:var(--pos-font-weight-bold);line-height:1.2;text-align:center;overflow-wrap:anywhere}.pos-login__title--entry{letter-spacing:var(--pos-letter-spacing-display)}.pos-login__input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.pos-login__keypad{display:grid;width:100%;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-sm)}.pos-login__key,.pos-login__primary,.pos-login__back{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-login__key,.pos-login__primary{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-semibold);transition:background .12s ease,border-color .12s ease,color .12s ease,transform 80ms ease,filter .12s ease}.pos-login__key--delete{color:var(--pos-color-text-muted)}.pos-login__key:hover:not(:disabled){border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 22%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-login__key:active:not(:disabled),.pos-login__primary:active:not(:disabled),.pos-login__back:active:not(:disabled){transform:scale(.985)}.pos-login__key:disabled,.pos-login__back:disabled,.pos-login__primary:disabled{cursor:not-allowed;opacity:.45;transform:none;filter:none}.pos-login__key:focus-visible,.pos-login__primary:focus-visible,.pos-login__back:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-login__primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-login__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-login__back{border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__back:hover:not(:disabled){color:var(--pos-color-text)}.pos-login__status{display:flex;flex-direction:column;gap:var(--pos-space-xs);text-align:center}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{color:var(--pos-color-danger)}@media(min-width:768px){.pos-login__shell--aside{flex-direction:row;align-items:stretch}.pos-login__aside,.pos-login__panel{flex:1 1 50%}.pos-login__aside{border-bottom:0;border-right:1px solid var(--pos-color-border);padding:var(--pos-space-2xl)}.pos-login__key,.pos-login__primary{min-height:var(--pos-keypad-size-md)}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary,.pos-login__back{transition:none}}\n"] }]
147
+ }, template: "<div\r\n class=\"pos-login__shell\"\r\n [class.pos-login__shell--aside]=\"showAside()\"\r\n [class.pos-login__shell--bordered]=\"bordered()\"\r\n>\r\n @if (showAside()) {\r\n <aside class=\"pos-login__aside\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-login__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-login__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-login__brand-image\"\r\n viewBox=\"492.40 241.70 51.34 54.94\"\r\n [attr.aria-hidden]=\"brandLabel() ? true : null\"\r\n [attr.aria-label]=\"brandLabel() ? null : 'Retalia'\"\r\n >\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 522.628906 291.910156 C 522.636719 293.0625 523.441406 293.511719 524.425781 292.914062 L 540.464844 283.207031 C 541.449219 282.613281 542.246094 281.195312 542.246094 280.046875 L 542.246094 261.132812 C 542.246094 259.980469 541.441406 259.523438 540.453125 260.113281 L 524.292969 269.691406 C 523.300781 270.277344 522.503906 271.683594 522.511719 272.835938 Z M 522.628906 291.910156\"\r\n />\r\n <path\r\n fill=\"currentColor\"\r\n d=\"M 539.097656 253.351562 L 517.101562 243.664062 C 516.066406 243.203125 514.417969 243.265625 513.421875 243.804688 L 495.835938 253.308594 C 494.839844 253.847656 494.027344 255.214844 494.023438 256.367188 L 493.910156 280.140625 C 493.902344 281.292969 494.699219 282.679688 495.683594 283.234375 L 501.734375 286.640625 C 502.71875 287.199219 503.503906 286.71875 503.480469 285.566406 L 503.214844 271.488281 C 503.207031 271.082031 503.492188 270.894531 503.855469 271.066406 L 506.128906 272.148438 C 507.152344 272.636719 507.980469 273.960938 507.980469 275.113281 L 507.980469 287.839844 C 507.980469 288.992188 508.773438 290.394531 509.746094 290.972656 L 515.777344 294.5625 C 516.753906 295.140625 517.554688 294.679688 517.566406 293.527344 L 517.800781 273.300781 C 517.808594 272.488281 517.539062 271.238281 517.195312 270.503906 L 515.460938 266.789062 C 515.292969 266.421875 515.476562 266.109375 515.871094 266.089844 L 518.925781 265.941406 C 520.050781 265.886719 521.761719 265.378906 522.738281 264.808594 L 539.195312 255.21875 C 540.175781 254.648438 540.132812 253.8125 539.097656 253.351562 M 520.609375 255.050781 L 518.019531 256.585938 C 516.914062 257.125 515.734375 257.289062 514.710938 256.804688 L 511.078125 255.101562 C 510.054688 254.621094 510.023438 253.773438 511.003906 253.210938 L 513.835938 251.597656 C 514.53125 251.203125 515.691406 251.132812 516.425781 251.445312 L 520.449219 253.128906 C 521.488281 253.570312 521.5625 254.429688 520.609375 255.050781\"\r\n />\r\n </svg>\r\n }\r\n }\r\n @if (brandLabel()) {\r\n <span class=\"pos-login__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (locationName() || terminalLine()) {\r\n <div class=\"pos-login__place\">\r\n @if (locationName()) {\r\n <p class=\"pos-login__location\">{{ locationName() }}</p>\r\n }\r\n @if (terminalLine()) {\r\n <p class=\"pos-login__terminal\">{{ terminalLine() }}</p>\r\n }\r\n @if (shopName()) {\r\n <p class=\"pos-login__terminal\">{{ shopName() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-login__facts\">\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ dateLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ shownDate() }}</p>\r\n </div>\r\n @if (posNumber()) {\r\n <div class=\"pos-login__fact\">\r\n <p class=\"pos-login__fact-label\">{{ posNumberLabel() }}</p>\r\n <p class=\"pos-login__fact-value\">{{ posNumber() }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Custom content slot -->\r\n <div class=\"pos-login__slot\">\r\n <ng-content select=\"[posLoginAside]\" />\r\n </div>\r\n </aside>\r\n }\r\n\r\n<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <div class=\"pos-login__main\">\r\n <header class=\"pos-login__header\">\r\n <h1 class=\"pos-login__heading\">{{ heading() }}</h1>\r\n @if (showBack()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__back\"\r\n aria-label=\"Back\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onBack()\"\r\n >\r\n Back\r\n </button>\r\n }\r\n </header>\r\n\r\n <div class=\"pos-login__display\">\r\n <p class=\"pos-login__title\" [class.pos-login__title--entry]=\"hasEntry()\">{{ displayText() }}</p>\r\n <input\r\n class=\"pos-login__input\"\r\n [attr.type]=\"maskInput() ? 'password' : 'text'\"\r\n [value]=\"inputValue()\"\r\n maxlength=\"12\"\r\n readonly\r\n tabindex=\"-1\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-label=\"Login code\"\r\n />\r\n </div>\r\n\r\n <div class=\"pos-login__keypad\" role=\"group\" aria-label=\"Keypad\">\r\n @for (key of digitKeys; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key pos-login__key--delete\"\r\n aria-label=\"Delete\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('\u2190')\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 5h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-5-7 5-7Z\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"m14 10 4 4m0-4-4 4\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad('0')\"\r\n >\r\n 0\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [attr.aria-label]=\"primaryLabel()\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M5 12.5 9.5 17 19 7.5\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2.2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n @if (sessionStatusText() || errorMessage()) {\r\n <div class=\"pos-login__status\" aria-live=\"polite\">\r\n @if (sessionStatusText()) {\r\n <p>{{ sessionStatusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-login__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- // Custom content slot -->\r\n <div class=\"pos-login__slot\">\r\n <ng-content select=\"[posLoginPanel]\" />\r\n </div>\r\n </div>\r\n</section>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;box-sizing:border-box;width:100%;height:100%;min-height:100vh;align-items:center;justify-content:center;padding:var(--pos-space-lg);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:transparent}*{box-sizing:border-box}.pos-login__shell{display:flex;flex-direction:column;width:min(22rem,100%);min-width:0}.pos-login__shell--aside{width:min(56rem,100%);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay);overflow:hidden}.pos-login__shell--bordered{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__aside{display:flex;flex-direction:column;gap:var(--pos-space-xl);min-width:0;padding:var(--pos-space-xl);border-bottom:1px solid var(--pos-color-border)}.pos-login__brand{display:flex;align-items:center;gap:var(--pos-space-sm)}.pos-login__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-login__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-login__place{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-login__location{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__terminal{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-login__facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__fact{min-width:0;padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg)}.pos-login__fact-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-login__fact-value{margin:var(--pos-space-xs) 0 0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-login__slot{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-login__slot:not(:has(*)){display:none}.pos-login__panel{display:flex;flex:1 1 auto;align-items:flex-start;justify-content:center;width:100%;min-width:0;padding:var(--pos-space-xl)}.pos-login__shell:not(.pos-login__shell--aside) .pos-login__panel{padding:0}.pos-login__main{display:flex;flex-direction:column;gap:var(--pos-space-md);width:min(22rem,100%)}.pos-login__header{display:flex;align-items:center;justify-content:space-between;gap:var(--pos-space-sm);min-height:var(--pos-space-xl)}.pos-login__heading{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-login__display{position:relative;display:flex;align-items:center;justify-content:center;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) + var(--pos-space-lg));padding:var(--pos-space-md) var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-login__title{margin:0;max-width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:calc(var(--pos-font-size-xl) * 1.3);font-weight:var(--pos-font-weight-bold);line-height:1.2;text-align:center;overflow-wrap:anywhere}.pos-login__title--entry{letter-spacing:var(--pos-letter-spacing-display)}.pos-login__input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.pos-login__keypad{display:grid;width:100%;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-sm)}.pos-login__key,.pos-login__primary,.pos-login__back{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-login__key,.pos-login__primary{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-semibold);transition:background .12s ease,border-color .12s ease,color .12s ease,transform 80ms ease,filter .12s ease}.pos-login__key--delete{color:var(--pos-color-text-muted)}.pos-login__key:hover:not(:disabled){border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 22%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-login__key:active:not(:disabled),.pos-login__primary:active:not(:disabled),.pos-login__back:active:not(:disabled){transform:scale(.985)}.pos-login__key:disabled,.pos-login__back:disabled,.pos-login__primary:disabled{cursor:not-allowed;opacity:.45;transform:none;filter:none}.pos-login__key:focus-visible,.pos-login__primary:focus-visible,.pos-login__back:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-login__primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-login__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-login__back{border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__back:hover:not(:disabled){color:var(--pos-color-text)}.pos-login__status{display:flex;flex-direction:column;gap:var(--pos-space-xs);text-align:center}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{color:var(--pos-color-danger)}@media(min-width:768px){.pos-login__shell--aside{flex-direction:row;align-items:stretch}.pos-login__aside,.pos-login__panel{flex:1 1 50%}.pos-login__aside{border-bottom:0;border-right:1px solid var(--pos-color-border);padding:var(--pos-space-2xl)}.pos-login__key,.pos-login__primary{min-height:var(--pos-keypad-size-md)}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary,.pos-login__back{transition:none}}\n"] }]
126
148
  }], propDecorators: { errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], session: [{ type: i0.Input, args: [{ isSignal: true, alias: "session", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], titleClerkNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleClerkNumber", required: false }] }], titleClerkPassword: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleClerkPassword", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], loginLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "loginLabel", required: false }] }], showAside: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAside", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], showBrandImage: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBrandImage", required: false }] }], brandImage: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandImage", required: false }] }], brandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandLabel", required: false }] }], locationName: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationName", required: false }] }], terminalLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "terminalLine", required: false }] }], shopName: [{ type: i0.Input, args: [{ isSignal: true, alias: "shopName", required: false }] }], dateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateLabel", required: false }] }], posNumberLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "posNumberLabel", required: false }] }], posNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "posNumber", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
127
149
 
150
+ /** Id the host stores and passes back as `selectedId`. */
151
+ function posTillDeviceKey(device) {
152
+ const deviceId = device.deviceId?.trim();
153
+ return deviceId ? deviceId : String(device.id);
154
+ }
155
+ let domIdSequence = 0;
156
+ function nextDomId(prefix) {
157
+ domIdSequence += 1;
158
+ return `${prefix}-${domIdSequence}`;
159
+ }
160
+ function deviceKind(device) {
161
+ if (device.kind) {
162
+ return device.kind;
163
+ }
164
+ return device.isVirtual ? 'virtual' : 'hardware';
165
+ }
166
+ class PosTillDevices {
167
+ devices = input([], ...(ngDevMode ? [{ debugName: "devices" }] : /* istanbul ignore next */ []));
168
+ /** `deviceId` when the config has one, otherwise `String(id)`. */
169
+ selectedId = input('', ...(ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []));
170
+ /** `dialog` is the connector popup. `summary` and `link` open that popup. */
171
+ variant = input('dialog', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
172
+ /** `plug` draws the till-devices button. `none` keeps the text link. */
173
+ icon = input('none', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
174
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
175
+ title = input('Till devices', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
176
+ description = input('Choose the connector this till uses.', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
177
+ listLabel = input('Connectors', ...(ngDevMode ? [{ debugName: "listLabel" }] : /* istanbul ignore next */ []));
178
+ cancelLabel = input('Cancel', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
179
+ confirmLabel = input('Use this connector', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
180
+ emptyLabel = input('No connectors are set up for this till.', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
181
+ selectLabel = input('Select connector', ...(ngDevMode ? [{ debugName: "selectLabel" }] : /* istanbul ignore next */ []));
182
+ changeLabel = input('Till devices', ...(ngDevMode ? [{ debugName: "changeLabel" }] : /* istanbul ignore next */ []));
183
+ setupLabel = input('Set up till devices', ...(ngDevMode ? [{ debugName: "setupLabel" }] : /* istanbul ignore next */ []));
184
+ connectorLabel = input('Connector', ...(ngDevMode ? [{ debugName: "connectorLabel" }] : /* istanbul ignore next */ []));
185
+ printerCaption = input('Printer', ...(ngDevMode ? [{ debugName: "printerCaption" }] : /* istanbul ignore next */ []));
186
+ paymentCaption = input('Payment', ...(ngDevMode ? [{ debugName: "paymentCaption" }] : /* istanbul ignore next */ []));
187
+ noPaymentLabel = input('No payment device', ...(ngDevMode ? [{ debugName: "noPaymentLabel" }] : /* istanbul ignore next */ []));
188
+ paymentFallbackLabel = input('Payment device', ...(ngDevMode ? [{ debugName: "paymentFallbackLabel" }] : /* istanbul ignore next */ []));
189
+ hardwareLabel = input('Hardware', ...(ngDevMode ? [{ debugName: "hardwareLabel" }] : /* istanbul ignore next */ []));
190
+ softwareLabel = input('Software', ...(ngDevMode ? [{ debugName: "softwareLabel" }] : /* istanbul ignore next */ []));
191
+ virtualLabel = input('Virtual', ...(ngDevMode ? [{ debugName: "virtualLabel" }] : /* istanbul ignore next */ []));
192
+ offlineLabel = input('Offline', ...(ngDevMode ? [{ debugName: "offlineLabel" }] : /* istanbul ignore next */ []));
193
+ nothingToInstallLabel = input('Nothing to install', ...(ngDevMode ? [{ debugName: "nothingToInstallLabel" }] : /* istanbul ignore next */ []));
194
+ action = output();
195
+ dialogRef = viewChild('dialog', ...(ngDevMode ? [{ debugName: "dialogRef" }] : /* istanbul ignore next */ []));
196
+ dialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "dialogOpen" }] : /* istanbul ignore next */ []));
197
+ pickedId = linkedSignal(() => this.selectedId(), ...(ngDevMode ? [{ debugName: "pickedId" }] : /* istanbul ignore next */ []));
198
+ restoreFocus = null;
199
+ titleId = nextDomId('pos-till-devices-title');
200
+ descriptionId = nextDomId('pos-till-devices-description');
201
+ showDialog = computed(() => this.variant() === 'dialog' || this.dialogOpen(), ...(ngDevMode ? [{ debugName: "showDialog" }] : /* istanbul ignore next */ []));
202
+ cards = computed(() => this.devices().map((device, index) => this.toCard(device, index)), ...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
203
+ selectedCard = computed(() => {
204
+ const id = this.selectedId();
205
+ if (!id) {
206
+ return null;
207
+ }
208
+ return this.cards().find((card) => card.key === id) ?? null;
209
+ }, ...(ngDevMode ? [{ debugName: "selectedCard" }] : /* istanbul ignore next */ []));
210
+ linkText = computed(() => this.selectedCard() ? this.changeLabel() : this.selectLabel(), ...(ngDevMode ? [{ debugName: "linkText" }] : /* istanbul ignore next */ []));
211
+ canConfirm = computed(() => {
212
+ if (this.disabled()) {
213
+ return false;
214
+ }
215
+ const picked = this.cards().find((card) => card.selected);
216
+ return picked != null && !picked.offline;
217
+ }, ...(ngDevMode ? [{ debugName: "canConfirm" }] : /* istanbul ignore next */ []));
218
+ constructor() {
219
+ afterRenderEffect(() => {
220
+ const open = this.showDialog();
221
+ const dialog = this.dialogRef()?.nativeElement;
222
+ if (!open || !dialog || dialog.contains(document.activeElement)) {
223
+ return;
224
+ }
225
+ const preferred = dialog.querySelector('.pos-till-devices__card--selected:not(:disabled)');
226
+ const fallback = dialog.querySelector('.pos-till-devices__card:not(:disabled), .pos-till-devices__button');
227
+ (preferred ?? fallback)?.focus();
228
+ });
229
+ }
230
+ openDialog() {
231
+ if (this.disabled() || this.variant() === 'dialog') {
232
+ return;
233
+ }
234
+ const active = document.activeElement;
235
+ this.restoreFocus = active instanceof HTMLElement ? active : null;
236
+ this.pickedId.set(this.selectedId());
237
+ this.dialogOpen.set(true);
238
+ this.action.emit({ type: 'tillDevices.open' });
239
+ }
240
+ pick(card) {
241
+ if (this.disabled() || card.offline) {
242
+ return;
243
+ }
244
+ this.pickedId.set(card.key);
245
+ this.action.emit({ type: 'tillDevices.select', deviceId: card.key });
246
+ }
247
+ moveSelection(index, step, event) {
248
+ const cards = this.cards();
249
+ if (cards.length === 0) {
250
+ return;
251
+ }
252
+ event.preventDefault();
253
+ let next = index;
254
+ for (let attempt = 0; attempt < cards.length; attempt += 1) {
255
+ next = (next + step + cards.length) % cards.length;
256
+ const card = cards[next];
257
+ if (!card.offline && !this.disabled()) {
258
+ this.pick(card);
259
+ queueMicrotask(() => {
260
+ this.dialogRef()?.nativeElement
261
+ .querySelector(`[data-card-index="${next}"]`)
262
+ ?.focus();
263
+ });
264
+ return;
265
+ }
266
+ }
267
+ }
268
+ confirm() {
269
+ const picked = this.cards().find((card) => card.selected);
270
+ if (!picked || picked.offline || this.disabled()) {
271
+ return;
272
+ }
273
+ if (this.variant() !== 'dialog') {
274
+ this.dialogOpen.set(false);
275
+ }
276
+ this.action.emit({ type: 'tillDevices.confirm', deviceId: picked.key });
277
+ this.returnFocus();
278
+ }
279
+ dismiss() {
280
+ if (this.variant() !== 'dialog') {
281
+ this.dialogOpen.set(false);
282
+ }
283
+ this.pickedId.set(this.selectedId());
284
+ this.action.emit({ type: 'tillDevices.dismiss' });
285
+ this.returnFocus();
286
+ }
287
+ onDialogKeydown(event) {
288
+ if (event.key === 'Escape') {
289
+ event.preventDefault();
290
+ this.dismiss();
291
+ return;
292
+ }
293
+ if (event.key !== 'Tab') {
294
+ return;
295
+ }
296
+ const dialog = this.dialogRef()?.nativeElement;
297
+ if (!dialog) {
298
+ return;
299
+ }
300
+ const items = Array.from(dialog.querySelectorAll('button:not(:disabled)'));
301
+ if (items.length === 0) {
302
+ event.preventDefault();
303
+ return;
304
+ }
305
+ const first = items[0];
306
+ const last = items[items.length - 1];
307
+ const active = document.activeElement;
308
+ if (event.shiftKey && (active === first || !dialog.contains(active))) {
309
+ event.preventDefault();
310
+ last.focus();
311
+ return;
312
+ }
313
+ if (!event.shiftKey && active === last) {
314
+ event.preventDefault();
315
+ first.focus();
316
+ }
317
+ }
318
+ returnFocus() {
319
+ const restore = this.restoreFocus;
320
+ this.restoreFocus = null;
321
+ restore?.focus();
322
+ }
323
+ toCard(device, index) {
324
+ const kind = deviceKind(device);
325
+ const key = posTillDeviceKey(device);
326
+ const offline = device.online === false;
327
+ return {
328
+ index,
329
+ key,
330
+ device,
331
+ kind,
332
+ kindText: device.kindLabel?.trim() || this.kindText(kind),
333
+ payment: this.paymentText(device),
334
+ printer: device.printerLabel?.trim() ?? '',
335
+ detail: this.detailText(device, kind),
336
+ offline,
337
+ selected: key === this.pickedId(),
338
+ presence: this.presence(device, kind, offline),
339
+ };
340
+ }
341
+ presence(device, kind, offline) {
342
+ if (offline) {
343
+ return 'offline';
344
+ }
345
+ if (device.online === true || kind === 'virtual') {
346
+ return 'online';
347
+ }
348
+ return 'unknown';
349
+ }
350
+ kindText(kind) {
351
+ if (kind === 'virtual') {
352
+ return this.virtualLabel();
353
+ }
354
+ if (kind === 'software') {
355
+ return this.softwareLabel();
356
+ }
357
+ return this.hardwareLabel();
358
+ }
359
+ paymentText(device) {
360
+ const label = device.paymentLabel?.trim();
361
+ if (label) {
362
+ return label;
363
+ }
364
+ if (device.terminalType == null) {
365
+ return '';
366
+ }
367
+ return device.terminalType === 0
368
+ ? this.noPaymentLabel()
369
+ : this.paymentFallbackLabel();
370
+ }
371
+ detailText(device, kind) {
372
+ const custom = device.detail?.trim();
373
+ if (custom) {
374
+ return custom;
375
+ }
376
+ const host = device.host?.trim() ?? '';
377
+ const identity = device.mac?.trim() || device.deviceId?.trim() || '';
378
+ if (device.online === false) {
379
+ return [this.offlineLabel(), host, identity].filter(Boolean).join(' · ');
380
+ }
381
+ if (kind === 'virtual') {
382
+ return [this.nothingToInstallLabel(), identity].filter(Boolean).join(' · ');
383
+ }
384
+ return [host, identity].filter(Boolean).join(' · ');
385
+ }
386
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTillDevices, deps: [], target: i0.ɵɵFactoryTarget.Component });
387
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosTillDevices, isStandalone: true, selector: "pos-till-devices", inputs: { devices: { classPropertyName: "devices", publicName: "devices", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, listLabel: { classPropertyName: "listLabel", publicName: "listLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null }, selectLabel: { classPropertyName: "selectLabel", publicName: "selectLabel", isSignal: true, isRequired: false, transformFunction: null }, changeLabel: { classPropertyName: "changeLabel", publicName: "changeLabel", isSignal: true, isRequired: false, transformFunction: null }, setupLabel: { classPropertyName: "setupLabel", publicName: "setupLabel", isSignal: true, isRequired: false, transformFunction: null }, connectorLabel: { classPropertyName: "connectorLabel", publicName: "connectorLabel", isSignal: true, isRequired: false, transformFunction: null }, printerCaption: { classPropertyName: "printerCaption", publicName: "printerCaption", isSignal: true, isRequired: false, transformFunction: null }, paymentCaption: { classPropertyName: "paymentCaption", publicName: "paymentCaption", isSignal: true, isRequired: false, transformFunction: null }, noPaymentLabel: { classPropertyName: "noPaymentLabel", publicName: "noPaymentLabel", isSignal: true, isRequired: false, transformFunction: null }, paymentFallbackLabel: { classPropertyName: "paymentFallbackLabel", publicName: "paymentFallbackLabel", isSignal: true, isRequired: false, transformFunction: null }, hardwareLabel: { classPropertyName: "hardwareLabel", publicName: "hardwareLabel", isSignal: true, isRequired: false, transformFunction: null }, softwareLabel: { classPropertyName: "softwareLabel", publicName: "softwareLabel", isSignal: true, isRequired: false, transformFunction: null }, virtualLabel: { classPropertyName: "virtualLabel", publicName: "virtualLabel", isSignal: true, isRequired: false, transformFunction: null }, offlineLabel: { classPropertyName: "offlineLabel", publicName: "offlineLabel", isSignal: true, isRequired: false, transformFunction: null }, nothingToInstallLabel: { classPropertyName: "nothingToInstallLabel", publicName: "nothingToInstallLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { properties: { "class.pos-till-devices--dialog": "variant() === \"dialog\"", "class.pos-till-devices--summary": "variant() === \"summary\"", "class.pos-till-devices--link": "variant() === \"link\"" }, classAttribute: "pos-till-devices" }, viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dialog"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (variant() === 'summary') {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__summary\"\r\n [class.pos-till-devices__summary--attention]=\"!selectedCard()\"\r\n [disabled]=\"disabled()\"\r\n aria-haspopup=\"dialog\"\r\n (click)=\"openDialog()\"\r\n >\r\n <span class=\"pos-till-devices__eyebrow\">\r\n {{ connectorLabel() }}\r\n @if (selectedCard(); as card) {\r\n <span> \u00B7 {{ card.kindText }}</span>\r\n }\r\n </span>\r\n <span\r\n class=\"pos-till-devices__summary-title\"\r\n [class.pos-till-devices__summary-title--attention]=\"!selectedCard()\"\r\n >\r\n @if (selectedCard(); as card) {\r\n {{ card.device.name }}\r\n } @else {\r\n {{ setupLabel() }}\r\n <span aria-hidden=\"true\"> \u203A</span>\r\n }\r\n </span>\r\n @if (selectedCard(); as card) {\r\n @if (card.printer || card.payment) {\r\n <span class=\"pos-till-devices__summary-meta\">\r\n @if (card.printer) {\r\n <span>{{ printerCaption() }}: {{ card.printer }}</span>\r\n }\r\n @if (card.printer && card.payment) {\r\n <span aria-hidden=\"true\"> \u00B7 </span>\r\n }\r\n @if (card.payment) {\r\n <span>{{ paymentCaption() }}: {{ card.payment }}</span>\r\n }\r\n </span>\r\n }\r\n }\r\n </button>\r\n}\r\n\r\n@if (variant() === 'link') {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__link\"\r\n [class.pos-till-devices__link--attention]=\"icon() === 'none' && !selectedCard()\"\r\n [class.pos-till-devices__link--button]=\"icon() === 'plug'\"\r\n [disabled]=\"disabled()\"\r\n aria-haspopup=\"dialog\"\r\n (click)=\"openDialog()\"\r\n >\r\n @if (icon() === 'plug') {\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 8V4M16 8V4M7 8h10v5a5 5 0 0 1-10 0V8Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M12 18v2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n }\r\n {{ linkText() }}\r\n @if (icon() === 'none') {\r\n <span aria-hidden=\"true\"> \u203A</span>\r\n }\r\n </button>\r\n}\r\n\r\n@if (showDialog()) {\r\n <div class=\"pos-till-devices__overlay\" (click)=\"dismiss()\">\r\n <div\r\n #dialog\r\n class=\"pos-till-devices__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-labelledby]=\"titleId\"\r\n [attr.aria-describedby]=\"description() ? descriptionId : null\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"onDialogKeydown($event)\"\r\n >\r\n <header class=\"pos-till-devices__header\">\r\n <h2 [id]=\"titleId\" class=\"pos-till-devices__title\">{{ title() }}</h2>\r\n @if (description()) {\r\n <p [id]=\"descriptionId\" class=\"pos-till-devices__description\">{{ description() }}</p>\r\n }\r\n </header>\r\n\r\n @if (cards().length === 0) {\r\n <p class=\"pos-till-devices__empty\">{{ emptyLabel() }}</p>\r\n } @else {\r\n <div class=\"pos-till-devices__grid\" role=\"radiogroup\" [attr.aria-label]=\"listLabel()\">\r\n @for (card of cards(); track card.key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__card\"\r\n [class.pos-till-devices__card--selected]=\"card.selected\"\r\n [class.pos-till-devices__card--offline]=\"card.offline\"\r\n role=\"radio\"\r\n [attr.data-card-index]=\"card.index\"\r\n [attr.aria-checked]=\"card.selected\"\r\n [disabled]=\"disabled() || card.offline\"\r\n (click)=\"pick(card)\"\r\n (keydown.arrowRight)=\"moveSelection(card.index, 1, $event)\"\r\n (keydown.arrowDown)=\"moveSelection(card.index, 1, $event)\"\r\n (keydown.arrowLeft)=\"moveSelection(card.index, -1, $event)\"\r\n (keydown.arrowUp)=\"moveSelection(card.index, -1, $event)\"\r\n >\r\n <span class=\"pos-till-devices__card-head\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n @if (card.kind === 'virtual') {\r\n <path\r\n d=\"M13 2 4 14h7l-1 8 10-14h-7l0-6Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n } @else {\r\n <path\r\n d=\"M8 8V4M16 8V4M7 8h10v5a5 5 0 0 1-10 0V8Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M12 18v2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n }\r\n </svg>\r\n <span class=\"pos-till-devices__name\">{{ card.device.name }}</span>\r\n <span\r\n class=\"pos-till-devices__badge\"\r\n [class.pos-till-devices__badge--virtual]=\"card.kind === 'virtual'\"\r\n [class.pos-till-devices__badge--software]=\"card.kind === 'software'\"\r\n >\r\n {{ card.kindText }}\r\n </span>\r\n </span>\r\n\r\n @if (card.printer) {\r\n <span class=\"pos-till-devices__row\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n d=\"M7 8V4h10v4M7 17H5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M7 14h10v6H7z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>\r\n <span class=\"pos-till-devices__row-label\">{{ printerCaption() }}: </span>\r\n <span class=\"pos-till-devices__row-value\">{{ card.printer }}</span>\r\n </span>\r\n </span>\r\n }\r\n\r\n @if (card.payment) {\r\n <span class=\"pos-till-devices__row\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <rect\r\n x=\"3\"\r\n y=\"6\"\r\n width=\"18\"\r\n height=\"12\"\r\n rx=\"2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n />\r\n <path d=\"M3 10h18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" />\r\n </svg>\r\n <span>\r\n <span class=\"pos-till-devices__row-label\">{{ paymentCaption() }}: </span>\r\n <span class=\"pos-till-devices__row-value\">{{ card.payment }}</span>\r\n </span>\r\n </span>\r\n }\r\n\r\n @if (card.detail) {\r\n <span\r\n class=\"pos-till-devices__presence\"\r\n [class.pos-till-devices__presence--online]=\"card.presence === 'online'\"\r\n [class.pos-till-devices__presence--offline]=\"card.presence === 'offline'\"\r\n >\r\n <span class=\"pos-till-devices__dot\" aria-hidden=\"true\"></span>\r\n <span>{{ card.detail }}</span>\r\n </span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-till-devices__actions\">\r\n <button type=\"button\" class=\"pos-till-devices__button\" (click)=\"dismiss()\">\r\n {{ cancelLabel() }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__button pos-till-devices__button--primary\"\r\n [disabled]=\"!canConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabel() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block;box-sizing:border-box;min-width:0;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}:host(.pos-till-devices--link){display:flex;justify-content:center}*{box-sizing:border-box}.pos-till-devices__summary,.pos-till-devices__link,.pos-till-devices__card,.pos-till-devices__button{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-till-devices__summary{display:flex;flex-direction:column;align-items:flex-start;gap:var(--pos-space-xs);width:100%;min-height:var(--pos-button-min-height);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);color:var(--pos-color-text);text-align:left}.pos-till-devices__summary--attention{border-style:dashed;border-color:var(--pos-color-danger)}.pos-till-devices__eyebrow{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-till-devices__summary-title{font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-till-devices__summary-title--attention{color:var(--pos-color-danger)}.pos-till-devices__summary-meta{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__link{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-button-min-height);padding:var(--pos-space-sm) var(--pos-space-md);border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-till-devices__link--attention{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-bold)}.pos-till-devices__link--button{width:100%;gap:var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font-size:var(--pos-font-size-md);box-shadow:var(--pos-shadow-key)}.pos-till-devices__link--button .pos-till-devices__icon{width:1.15rem;height:1.15rem;margin-top:0;color:var(--pos-color-text)}.pos-till-devices__summary:hover:not(:disabled),.pos-till-devices__link:hover:not(:disabled),.pos-till-devices__card:hover:not(:disabled){border-color:var(--pos-color-primary)}.pos-till-devices__link:hover:not(:disabled){text-decoration:underline}.pos-till-devices__link--button:hover:not(:disabled){text-decoration:none}.pos-till-devices__summary:focus-visible,.pos-till-devices__link:focus-visible,.pos-till-devices__card:focus-visible,.pos-till-devices__button:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-till-devices__summary:disabled,.pos-till-devices__link:disabled,.pos-till-devices__card:disabled,.pos-till-devices__button:disabled{cursor:not-allowed;opacity:.45}.pos-till-devices__overlay{position:fixed;inset:0;z-index:40;display:flex;align-items:flex-start;justify-content:center;padding:var(--pos-space-lg);overflow:auto;background:color-mix(in srgb,var(--pos-color-ink) 45%,transparent)}.pos-till-devices__dialog{display:flex;flex-direction:column;gap:var(--pos-space-lg);width:min(64rem,100%);max-height:calc(100vh - var(--pos-space-lg) * 2);margin-block:auto;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay)}.pos-till-devices__header{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-till-devices__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-till-devices__description,.pos-till-devices__empty{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__empty{padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-till-devices__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--pos-space-md);min-height:0;margin:0;padding:0;overflow:auto}.pos-till-devices__card{display:flex;flex-direction:column;align-items:stretch;gap:var(--pos-space-sm);width:100%;min-height:var(--pos-button-min-height);padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);text-align:left}.pos-till-devices__card--selected{border-color:var(--pos-color-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--pos-color-primary) 55%,transparent)}.pos-till-devices__card-head{display:flex;align-items:flex-start;gap:var(--pos-space-sm);min-width:0}.pos-till-devices__icon{flex:0 0 auto;width:1.15rem;height:1.15rem;margin-top:.1rem;color:var(--pos-color-text-muted)}.pos-till-devices__name{flex:1 1 auto;min-width:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);line-height:1.3;overflow-wrap:anywhere}.pos-till-devices__badge{flex:0 0 auto;padding:var(--pos-space-xs) var(--pos-space-sm);border-radius:var(--pos-radius-pill);background:var(--pos-color-surface-muted);color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1.2}.pos-till-devices__badge--virtual{background:color-mix(in srgb,var(--pos-color-primary) 45%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-till-devices__badge--software{background:color-mix(in srgb,var(--pos-color-warning) 40%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-till-devices__row,.pos-till-devices__presence{display:flex;align-items:flex-start;gap:var(--pos-space-sm);min-width:0;font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__row-label{color:var(--pos-color-text-muted)}.pos-till-devices__row-value{font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere}.pos-till-devices__presence{align-items:center;color:var(--pos-color-text-muted)}.pos-till-devices__presence--online{color:color-mix(in srgb,var(--pos-color-success) 28%,var(--pos-color-text))}.pos-till-devices__presence--offline{color:var(--pos-color-danger)}.pos-till-devices__dot{flex:0 0 auto;width:var(--pos-space-sm);height:var(--pos-space-sm);margin-top:.15rem;border-radius:var(--pos-radius-pill);background:currentColor}.pos-till-devices__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--pos-space-sm)}.pos-till-devices__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);padding:var(--pos-space-sm) var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold)}.pos-till-devices__button--primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-till-devices__button--primary:hover:not(:disabled){filter:brightness(1.06)}@media(min-width:768px){.pos-till-devices__dialog{padding:var(--pos-space-xl)}.pos-till-devices__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pos-till-devices__button{flex:0 1 auto;min-width:8rem}}@media(min-width:1024px){.pos-till-devices__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(prefers-reduced-motion:reduce){.pos-till-devices__button--primary{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
388
+ }
389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTillDevices, decorators: [{
390
+ type: Component,
391
+ args: [{ selector: 'pos-till-devices', changeDetection: ChangeDetectionStrategy.OnPush, host: {
392
+ class: 'pos-till-devices',
393
+ '[class.pos-till-devices--dialog]': 'variant() === "dialog"',
394
+ '[class.pos-till-devices--summary]': 'variant() === "summary"',
395
+ '[class.pos-till-devices--link]': 'variant() === "link"',
396
+ }, template: "@if (variant() === 'summary') {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__summary\"\r\n [class.pos-till-devices__summary--attention]=\"!selectedCard()\"\r\n [disabled]=\"disabled()\"\r\n aria-haspopup=\"dialog\"\r\n (click)=\"openDialog()\"\r\n >\r\n <span class=\"pos-till-devices__eyebrow\">\r\n {{ connectorLabel() }}\r\n @if (selectedCard(); as card) {\r\n <span> \u00B7 {{ card.kindText }}</span>\r\n }\r\n </span>\r\n <span\r\n class=\"pos-till-devices__summary-title\"\r\n [class.pos-till-devices__summary-title--attention]=\"!selectedCard()\"\r\n >\r\n @if (selectedCard(); as card) {\r\n {{ card.device.name }}\r\n } @else {\r\n {{ setupLabel() }}\r\n <span aria-hidden=\"true\"> \u203A</span>\r\n }\r\n </span>\r\n @if (selectedCard(); as card) {\r\n @if (card.printer || card.payment) {\r\n <span class=\"pos-till-devices__summary-meta\">\r\n @if (card.printer) {\r\n <span>{{ printerCaption() }}: {{ card.printer }}</span>\r\n }\r\n @if (card.printer && card.payment) {\r\n <span aria-hidden=\"true\"> \u00B7 </span>\r\n }\r\n @if (card.payment) {\r\n <span>{{ paymentCaption() }}: {{ card.payment }}</span>\r\n }\r\n </span>\r\n }\r\n }\r\n </button>\r\n}\r\n\r\n@if (variant() === 'link') {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__link\"\r\n [class.pos-till-devices__link--attention]=\"icon() === 'none' && !selectedCard()\"\r\n [class.pos-till-devices__link--button]=\"icon() === 'plug'\"\r\n [disabled]=\"disabled()\"\r\n aria-haspopup=\"dialog\"\r\n (click)=\"openDialog()\"\r\n >\r\n @if (icon() === 'plug') {\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 8V4M16 8V4M7 8h10v5a5 5 0 0 1-10 0V8Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M12 18v2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n }\r\n {{ linkText() }}\r\n @if (icon() === 'none') {\r\n <span aria-hidden=\"true\"> \u203A</span>\r\n }\r\n </button>\r\n}\r\n\r\n@if (showDialog()) {\r\n <div class=\"pos-till-devices__overlay\" (click)=\"dismiss()\">\r\n <div\r\n #dialog\r\n class=\"pos-till-devices__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-labelledby]=\"titleId\"\r\n [attr.aria-describedby]=\"description() ? descriptionId : null\"\r\n (click)=\"$event.stopPropagation()\"\r\n (keydown)=\"onDialogKeydown($event)\"\r\n >\r\n <header class=\"pos-till-devices__header\">\r\n <h2 [id]=\"titleId\" class=\"pos-till-devices__title\">{{ title() }}</h2>\r\n @if (description()) {\r\n <p [id]=\"descriptionId\" class=\"pos-till-devices__description\">{{ description() }}</p>\r\n }\r\n </header>\r\n\r\n @if (cards().length === 0) {\r\n <p class=\"pos-till-devices__empty\">{{ emptyLabel() }}</p>\r\n } @else {\r\n <div class=\"pos-till-devices__grid\" role=\"radiogroup\" [attr.aria-label]=\"listLabel()\">\r\n @for (card of cards(); track card.key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__card\"\r\n [class.pos-till-devices__card--selected]=\"card.selected\"\r\n [class.pos-till-devices__card--offline]=\"card.offline\"\r\n role=\"radio\"\r\n [attr.data-card-index]=\"card.index\"\r\n [attr.aria-checked]=\"card.selected\"\r\n [disabled]=\"disabled() || card.offline\"\r\n (click)=\"pick(card)\"\r\n (keydown.arrowRight)=\"moveSelection(card.index, 1, $event)\"\r\n (keydown.arrowDown)=\"moveSelection(card.index, 1, $event)\"\r\n (keydown.arrowLeft)=\"moveSelection(card.index, -1, $event)\"\r\n (keydown.arrowUp)=\"moveSelection(card.index, -1, $event)\"\r\n >\r\n <span class=\"pos-till-devices__card-head\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n @if (card.kind === 'virtual') {\r\n <path\r\n d=\"M13 2 4 14h7l-1 8 10-14h-7l0-6Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n } @else {\r\n <path\r\n d=\"M8 8V4M16 8V4M7 8h10v5a5 5 0 0 1-10 0V8Z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M12 18v2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linecap=\"round\"\r\n />\r\n }\r\n </svg>\r\n <span class=\"pos-till-devices__name\">{{ card.device.name }}</span>\r\n <span\r\n class=\"pos-till-devices__badge\"\r\n [class.pos-till-devices__badge--virtual]=\"card.kind === 'virtual'\"\r\n [class.pos-till-devices__badge--software]=\"card.kind === 'software'\"\r\n >\r\n {{ card.kindText }}\r\n </span>\r\n </span>\r\n\r\n @if (card.printer) {\r\n <span class=\"pos-till-devices__row\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n d=\"M7 8V4h10v4M7 17H5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M7 14h10v6H7z\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>\r\n <span class=\"pos-till-devices__row-label\">{{ printerCaption() }}: </span>\r\n <span class=\"pos-till-devices__row-value\">{{ card.printer }}</span>\r\n </span>\r\n </span>\r\n }\r\n\r\n @if (card.payment) {\r\n <span class=\"pos-till-devices__row\">\r\n <svg class=\"pos-till-devices__icon\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <rect\r\n x=\"3\"\r\n y=\"6\"\r\n width=\"18\"\r\n height=\"12\"\r\n rx=\"2\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.7\"\r\n />\r\n <path d=\"M3 10h18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" />\r\n </svg>\r\n <span>\r\n <span class=\"pos-till-devices__row-label\">{{ paymentCaption() }}: </span>\r\n <span class=\"pos-till-devices__row-value\">{{ card.payment }}</span>\r\n </span>\r\n </span>\r\n }\r\n\r\n @if (card.detail) {\r\n <span\r\n class=\"pos-till-devices__presence\"\r\n [class.pos-till-devices__presence--online]=\"card.presence === 'online'\"\r\n [class.pos-till-devices__presence--offline]=\"card.presence === 'offline'\"\r\n >\r\n <span class=\"pos-till-devices__dot\" aria-hidden=\"true\"></span>\r\n <span>{{ card.detail }}</span>\r\n </span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-till-devices__actions\">\r\n <button type=\"button\" class=\"pos-till-devices__button\" (click)=\"dismiss()\">\r\n {{ cancelLabel() }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-till-devices__button pos-till-devices__button--primary\"\r\n [disabled]=\"!canConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabel() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block;box-sizing:border-box;min-width:0;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}:host(.pos-till-devices--link){display:flex;justify-content:center}*{box-sizing:border-box}.pos-till-devices__summary,.pos-till-devices__link,.pos-till-devices__card,.pos-till-devices__button{font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-till-devices__summary{display:flex;flex-direction:column;align-items:flex-start;gap:var(--pos-space-xs);width:100%;min-height:var(--pos-button-min-height);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);color:var(--pos-color-text);text-align:left}.pos-till-devices__summary--attention{border-style:dashed;border-color:var(--pos-color-danger)}.pos-till-devices__eyebrow{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-brand);text-transform:uppercase}.pos-till-devices__summary-title{font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold);line-height:1.25}.pos-till-devices__summary-title--attention{color:var(--pos-color-danger)}.pos-till-devices__summary-meta{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__link{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-button-min-height);padding:var(--pos-space-sm) var(--pos-space-md);border:0;background:transparent;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-till-devices__link--attention{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-bold)}.pos-till-devices__link--button{width:100%;gap:var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font-size:var(--pos-font-size-md);box-shadow:var(--pos-shadow-key)}.pos-till-devices__link--button .pos-till-devices__icon{width:1.15rem;height:1.15rem;margin-top:0;color:var(--pos-color-text)}.pos-till-devices__summary:hover:not(:disabled),.pos-till-devices__link:hover:not(:disabled),.pos-till-devices__card:hover:not(:disabled){border-color:var(--pos-color-primary)}.pos-till-devices__link:hover:not(:disabled){text-decoration:underline}.pos-till-devices__link--button:hover:not(:disabled){text-decoration:none}.pos-till-devices__summary:focus-visible,.pos-till-devices__link:focus-visible,.pos-till-devices__card:focus-visible,.pos-till-devices__button:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}.pos-till-devices__summary:disabled,.pos-till-devices__link:disabled,.pos-till-devices__card:disabled,.pos-till-devices__button:disabled{cursor:not-allowed;opacity:.45}.pos-till-devices__overlay{position:fixed;inset:0;z-index:40;display:flex;align-items:flex-start;justify-content:center;padding:var(--pos-space-lg);overflow:auto;background:color-mix(in srgb,var(--pos-color-ink) 45%,transparent)}.pos-till-devices__dialog{display:flex;flex-direction:column;gap:var(--pos-space-lg);width:min(64rem,100%);max-height:calc(100vh - var(--pos-space-lg) * 2);margin-block:auto;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay)}.pos-till-devices__header{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-till-devices__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-till-devices__description,.pos-till-devices__empty{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__empty{padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface-muted)}.pos-till-devices__grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--pos-space-md);min-height:0;margin:0;padding:0;overflow:auto}.pos-till-devices__card{display:flex;flex-direction:column;align-items:stretch;gap:var(--pos-space-sm);width:100%;min-height:var(--pos-button-min-height);padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key);text-align:left}.pos-till-devices__card--selected{border-color:var(--pos-color-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--pos-color-primary) 55%,transparent)}.pos-till-devices__card-head{display:flex;align-items:flex-start;gap:var(--pos-space-sm);min-width:0}.pos-till-devices__icon{flex:0 0 auto;width:1.15rem;height:1.15rem;margin-top:.1rem;color:var(--pos-color-text-muted)}.pos-till-devices__name{flex:1 1 auto;min-width:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);line-height:1.3;overflow-wrap:anywhere}.pos-till-devices__badge{flex:0 0 auto;padding:var(--pos-space-xs) var(--pos-space-sm);border-radius:var(--pos-radius-pill);background:var(--pos-color-surface-muted);color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1.2}.pos-till-devices__badge--virtual{background:color-mix(in srgb,var(--pos-color-primary) 45%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-till-devices__badge--software{background:color-mix(in srgb,var(--pos-color-warning) 40%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-till-devices__row,.pos-till-devices__presence{display:flex;align-items:flex-start;gap:var(--pos-space-sm);min-width:0;font-size:var(--pos-font-size-sm);line-height:1.4}.pos-till-devices__row-label{color:var(--pos-color-text-muted)}.pos-till-devices__row-value{font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere}.pos-till-devices__presence{align-items:center;color:var(--pos-color-text-muted)}.pos-till-devices__presence--online{color:color-mix(in srgb,var(--pos-color-success) 28%,var(--pos-color-text))}.pos-till-devices__presence--offline{color:var(--pos-color-danger)}.pos-till-devices__dot{flex:0 0 auto;width:var(--pos-space-sm);height:var(--pos-space-sm);margin-top:.15rem;border-radius:var(--pos-radius-pill);background:currentColor}.pos-till-devices__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--pos-space-sm)}.pos-till-devices__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);padding:var(--pos-space-sm) var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold)}.pos-till-devices__button--primary{border-color:var(--pos-color-primary);background:var(--pos-color-primary);color:var(--pos-color-on-primary)}.pos-till-devices__button--primary:hover:not(:disabled){filter:brightness(1.06)}@media(min-width:768px){.pos-till-devices__dialog{padding:var(--pos-space-xl)}.pos-till-devices__grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pos-till-devices__button{flex:0 1 auto;min-width:8rem}}@media(min-width:1024px){.pos-till-devices__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(prefers-reduced-motion:reduce){.pos-till-devices__button--primary{transition:none}}\n"] }]
397
+ }], ctorParameters: () => [], propDecorators: { devices: [{ type: i0.Input, args: [{ isSignal: true, alias: "devices", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], listLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "listLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }], selectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabel", required: false }] }], changeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeLabel", required: false }] }], setupLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "setupLabel", required: false }] }], connectorLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectorLabel", required: false }] }], printerCaption: [{ type: i0.Input, args: [{ isSignal: true, alias: "printerCaption", required: false }] }], paymentCaption: [{ type: i0.Input, args: [{ isSignal: true, alias: "paymentCaption", required: false }] }], noPaymentLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noPaymentLabel", required: false }] }], paymentFallbackLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paymentFallbackLabel", required: false }] }], hardwareLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hardwareLabel", required: false }] }], softwareLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "softwareLabel", required: false }] }], virtualLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualLabel", required: false }] }], offlineLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "offlineLabel", required: false }] }], nothingToInstallLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nothingToInstallLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], dialogRef: [{ type: i0.ViewChild, args: ['dialog', { isSignal: true }] }] } });
398
+
128
399
  const EMPTY_TOTALS$1 = {
129
400
  gross: 0,
130
401
  net: 0,
@@ -280,26 +551,34 @@ class PosTransactionActionBar {
280
551
  /** Envelope action names. `clearBasket` shows Cancel. `tender` shows Cash and Card. */
281
552
  availableActions = input([], ...(ngDevMode ? [{ debugName: "availableActions" }] : /* istanbul ignore next */ []));
282
553
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
554
+ /** Key that clicks Cash. Empty hides the hint and the shortcut. */
555
+ cashHotkey = input('F11', ...(ngDevMode ? [{ debugName: "cashHotkey" }] : /* istanbul ignore next */ []));
283
556
  /** Key that clicks Card. Empty hides the hint and the shortcut. */
284
557
  cardHotkey = input('F12', ...(ngDevMode ? [{ debugName: "cardHotkey" }] : /* istanbul ignore next */ []));
285
558
  action = output();
559
+ cashButton = viewChild('cashButton', ...(ngDevMode ? [{ debugName: "cashButton" }] : /* istanbul ignore next */ []));
286
560
  cardButton = viewChild('cardButton', ...(ngDevMode ? [{ debugName: "cardButton" }] : /* istanbul ignore next */ []));
287
- // Clicks the real button, so a hidden (no tender) or disabled Card ignores the key.
561
+ // Clicks the real button, so a hidden (no tender) or disabled button ignores the key.
288
562
  onDocumentKeydown(event) {
289
- const hotkey = this.cardHotkey();
290
- if (!hotkey || event.key !== hotkey || event.repeat) {
563
+ if (event.repeat || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
291
564
  return;
292
565
  }
293
- if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
294
- return;
295
- }
296
- const button = this.cardButton()?.nativeElement;
566
+ const button = this.buttonForHotkey(event.key);
297
567
  if (!button || button.disabled) {
298
568
  return;
299
569
  }
300
570
  event.preventDefault();
301
571
  button.click();
302
572
  }
573
+ buttonForHotkey(key) {
574
+ if (this.cashHotkey() && key === this.cashHotkey()) {
575
+ return this.cashButton()?.nativeElement;
576
+ }
577
+ if (this.cardHotkey() && key === this.cardHotkey()) {
578
+ return this.cardButton()?.nativeElement;
579
+ }
580
+ return undefined;
581
+ }
303
582
  onClear() {
304
583
  this.action.emit({ type: 'actionBar.clearBasket' });
305
584
  }
@@ -310,15 +589,15 @@ class PosTransactionActionBar {
310
589
  this.action.emit({ type: 'actionBar.tenderCard' });
311
590
  }
312
591
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTransactionActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
313
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosTransactionActionBar, isStandalone: true, selector: "pos-transaction-action-bar", inputs: { availableActions: { classPropertyName: "availableActions", publicName: "availableActions", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, cardHotkey: { classPropertyName: "cardHotkey", publicName: "cardHotkey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "document:keydown": "onDocumentKeydown($event)" }, classAttribute: "pos-transaction-action-bar" }, viewQueries: [{ propertyName: "cardButton", first: true, predicate: ["cardButton"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (availableActions().includes('clearBasket')) {\n <button\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cancel\"\n [disabled]=\"disabled()\"\n (click)=\"onClear()\"\n >\n Cancel\n </button>\n}\n@if (availableActions().includes('tender')) {\n <button\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cash\"\n [disabled]=\"disabled()\"\n (click)=\"onCash()\"\n >\n Cash\n </button>\n <button\n #cardButton\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--card\"\n [disabled]=\"disabled()\"\n [attr.aria-keyshortcuts]=\"cardHotkey() || null\"\n (click)=\"onCard()\"\n >\n Card\n @if (cardHotkey()) {\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cardHotkey() }}</kbd>\n }\n </button>\n}\n<ng-content />\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-sm);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-transaction-action-bar__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);border:1px solid transparent;border-radius:var(--pos-radius-md);font:inherit;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-transaction-action-bar__button--cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-transaction-action-bar__button--cash,.pos-transaction-action-bar__button--card{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button--card{color:var(--pos-color-on-display)}.pos-transaction-action-bar__hotkey{margin:0 0 0 var(--pos-space-sm);padding:0;border:0;background:transparent;color:var(--pos-color-on-disabled);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
592
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosTransactionActionBar, isStandalone: true, selector: "pos-transaction-action-bar", inputs: { availableActions: { classPropertyName: "availableActions", publicName: "availableActions", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, cashHotkey: { classPropertyName: "cashHotkey", publicName: "cashHotkey", isSignal: true, isRequired: false, transformFunction: null }, cardHotkey: { classPropertyName: "cardHotkey", publicName: "cardHotkey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "document:keydown": "onDocumentKeydown($event)" }, classAttribute: "pos-transaction-action-bar" }, viewQueries: [{ propertyName: "cashButton", first: true, predicate: ["cashButton"], descendants: true, isSignal: true }, { propertyName: "cardButton", first: true, predicate: ["cardButton"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (availableActions().includes('clearBasket')) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cancel\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onClear()\"\r\n >\r\n Cancel\r\n </button>\r\n}\r\n@if (availableActions().includes('tender')) {\r\n <button\r\n #cashButton\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cash\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-keyshortcuts]=\"cashHotkey() || null\"\r\n (click)=\"onCash()\"\r\n >\r\n Cash\r\n @if (cashHotkey()) {\r\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cashHotkey() }}</kbd>\r\n }\r\n </button>\r\n <button\r\n #cardButton\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--card\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-keyshortcuts]=\"cardHotkey() || null\"\r\n (click)=\"onCard()\"\r\n >\r\n Card\r\n @if (cardHotkey()) {\r\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cardHotkey() }}</kbd>\r\n }\r\n </button>\r\n}\r\n<ng-content />\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-sm);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-transaction-action-bar__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);border:1px solid transparent;border-radius:var(--pos-radius-md);font:inherit;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-transaction-action-bar__button--cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-transaction-action-bar__button--cash,.pos-transaction-action-bar__button--card{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button--card{color:var(--pos-color-on-display)}.pos-transaction-action-bar__hotkey{margin:0 0 0 var(--pos-space-sm);padding:0;border:0;background:transparent;color:var(--pos-color-on-disabled);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
314
593
  }
315
594
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTransactionActionBar, decorators: [{
316
595
  type: Component,
317
596
  args: [{ selector: 'pos-transaction-action-bar', changeDetection: ChangeDetectionStrategy.OnPush, host: {
318
597
  class: 'pos-transaction-action-bar',
319
598
  '(document:keydown)': 'onDocumentKeydown($event)',
320
- }, template: "@if (availableActions().includes('clearBasket')) {\n <button\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cancel\"\n [disabled]=\"disabled()\"\n (click)=\"onClear()\"\n >\n Cancel\n </button>\n}\n@if (availableActions().includes('tender')) {\n <button\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cash\"\n [disabled]=\"disabled()\"\n (click)=\"onCash()\"\n >\n Cash\n </button>\n <button\n #cardButton\n type=\"button\"\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--card\"\n [disabled]=\"disabled()\"\n [attr.aria-keyshortcuts]=\"cardHotkey() || null\"\n (click)=\"onCard()\"\n >\n Card\n @if (cardHotkey()) {\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cardHotkey() }}</kbd>\n }\n </button>\n}\n<ng-content />\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-sm);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-transaction-action-bar__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);border:1px solid transparent;border-radius:var(--pos-radius-md);font:inherit;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-transaction-action-bar__button--cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-transaction-action-bar__button--cash,.pos-transaction-action-bar__button--card{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button--card{color:var(--pos-color-on-display)}.pos-transaction-action-bar__hotkey{margin:0 0 0 var(--pos-space-sm);padding:0;border:0;background:transparent;color:var(--pos-color-on-disabled);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"] }]
321
- }], propDecorators: { availableActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableActions", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cardHotkey: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardHotkey", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], cardButton: [{ type: i0.ViewChild, args: ['cardButton', { isSignal: true }] }] } });
599
+ }, template: "@if (availableActions().includes('clearBasket')) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cancel\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onClear()\"\r\n >\r\n Cancel\r\n </button>\r\n}\r\n@if (availableActions().includes('tender')) {\r\n <button\r\n #cashButton\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--cash\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-keyshortcuts]=\"cashHotkey() || null\"\r\n (click)=\"onCash()\"\r\n >\r\n Cash\r\n @if (cashHotkey()) {\r\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cashHotkey() }}</kbd>\r\n }\r\n </button>\r\n <button\r\n #cardButton\r\n type=\"button\"\r\n class=\"pos-transaction-action-bar__button pos-transaction-action-bar__button--card\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-keyshortcuts]=\"cardHotkey() || null\"\r\n (click)=\"onCard()\"\r\n >\r\n Card\r\n @if (cardHotkey()) {\r\n <kbd class=\"pos-transaction-action-bar__hotkey\" aria-hidden=\"true\">{{ cardHotkey() }}</kbd>\r\n }\r\n </button>\r\n}\r\n<ng-content />\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-sm);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-transaction-action-bar__button{flex:1 1 8rem;min-height:var(--pos-button-min-height);border:1px solid transparent;border-radius:var(--pos-radius-md);font:inherit;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-transaction-action-bar__button--cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-transaction-action-bar__button--cash,.pos-transaction-action-bar__button--card{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button--card{color:var(--pos-color-on-display)}.pos-transaction-action-bar__hotkey{margin:0 0 0 var(--pos-space-sm);padding:0;border:0;background:transparent;color:var(--pos-color-on-disabled);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"] }]
600
+ }], propDecorators: { availableActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableActions", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cashHotkey: [{ type: i0.Input, args: [{ isSignal: true, alias: "cashHotkey", required: false }] }], cardHotkey: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardHotkey", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], cashButton: [{ type: i0.ViewChild, args: ['cashButton', { isSignal: true }] }], cardButton: [{ type: i0.ViewChild, args: ['cardButton', { isSignal: true }] }] } });
322
601
 
323
602
  class PosItemEntry {
324
603
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
@@ -3055,5 +3334,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3055
3334
  * Generated bundle index. Do not edit.
3056
3335
  */
3057
3336
 
3058
- export { POS_WORKSPACE_BASKET_RIGHT_LAYOUT, POS_WORKSPACE_DEFAULT_LAYOUT, POS_WORKSPACE_EMPTY_LAYOUT, POS_WORKSPACE_HEADER_SPAN_LAYOUT, PosBasket, PosHeader, PosItemEntry, PosLogin, PosReceipt, PosTender, PosTokens, PosTransactionActionBar, PosWorkspace, PosWorkspacePane, parseWorkspaceLayout, workspaceLayoutJson };
3337
+ export { POS_WORKSPACE_BASKET_RIGHT_LAYOUT, POS_WORKSPACE_DEFAULT_LAYOUT, POS_WORKSPACE_EMPTY_LAYOUT, POS_WORKSPACE_HEADER_SPAN_LAYOUT, PosBasket, PosHeader, PosItemEntry, PosLogin, PosLoginAside, PosLoginPanel, PosReceipt, PosTender, PosTillDevices, PosTokens, PosTransactionActionBar, PosWorkspace, PosWorkspacePane, parseWorkspaceLayout, posTillDeviceKey, workspaceLayoutJson };
3059
3338
  //# sourceMappingURL=retalia-pos-components.mjs.map