@retalia/pos-components 0.0.8 → 0.0.10
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.
- package/README.md +69 -7
- package/fesm2022/retalia-pos-components.mjs +299 -106
- package/fesm2022/retalia-pos-components.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/styles.css +1 -0
- package/styles/tokens.css +21 -15
- package/types/retalia-pos-components.d.ts +113 -23
|
@@ -2,21 +2,37 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { input, output, signal, computed, ChangeDetectionStrategy, Component, viewChild, afterNextRender } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
const DEFAULT_SESSION = { status: 'signedOut' };
|
|
5
|
-
const
|
|
6
|
-
['1', '2', '3'],
|
|
7
|
-
['4', '5', '6'],
|
|
8
|
-
['7', '8', '9'],
|
|
9
|
-
['0', '.', '←'],
|
|
10
|
-
];
|
|
5
|
+
const DIGIT_KEYS = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
11
6
|
class PosLogin {
|
|
12
7
|
errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
13
8
|
session = input(DEFAULT_SESSION, ...(ngDevMode ? [{ debugName: "session" }] : /* istanbul ignore next */ []));
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
heading = input('Clerk sign in', ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
|
|
10
|
+
titleClerkNumber = input('Enter clerk PIN', ...(ngDevMode ? [{ debugName: "titleClerkNumber" }] : /* istanbul ignore next */ []));
|
|
11
|
+
titleClerkPassword = input('Enter clerk password', ...(ngDevMode ? [{ debugName: "titleClerkPassword" }] : /* istanbul ignore next */ []));
|
|
16
12
|
nextLabel = input('Next', ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
|
|
17
13
|
loginLabel = input('Login', ...(ngDevMode ? [{ debugName: "loginLabel" }] : /* istanbul ignore next */ []));
|
|
14
|
+
/** Shop context beside the keypad. Off leaves the keypad on its own. */
|
|
15
|
+
showAside = input(true, ...(ngDevMode ? [{ debugName: "showAside" }] : /* istanbul ignore next */ []));
|
|
16
|
+
/** Draws a frame around the login shell. Off by default. */
|
|
17
|
+
bordered = input(false, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
|
|
18
|
+
/** When false, the brand image is omitted, including the built-in mark. */
|
|
19
|
+
showBrandImage = input(true, ...(ngDevMode ? [{ debugName: "showBrandImage" }] : /* istanbul ignore next */ []));
|
|
20
|
+
/** Partner image URL. Empty, while `showBrandImage` is true, uses the built-in Retalia mark. */
|
|
21
|
+
brandImage = input('', ...(ngDevMode ? [{ debugName: "brandImage" }] : /* istanbul ignore next */ []));
|
|
22
|
+
/** Wordmark after the image. Empty shows no text. */
|
|
23
|
+
brandLabel = input('RETALIA', ...(ngDevMode ? [{ debugName: "brandLabel" }] : /* istanbul ignore next */ []));
|
|
24
|
+
/** First address line under the brand. Empty hides it. */
|
|
25
|
+
locationName = input('Address1', ...(ngDevMode ? [{ debugName: "locationName" }] : /* istanbul ignore next */ []));
|
|
26
|
+
/** Second address line. Empty hides it. */
|
|
27
|
+
terminalLine = input('Address2', ...(ngDevMode ? [{ debugName: "terminalLine" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/** Shop line. Empty hides it. */
|
|
29
|
+
shopName = input('shop 1', ...(ngDevMode ? [{ debugName: "shopName" }] : /* istanbul ignore next */ []));
|
|
30
|
+
dateLabel = input('Date', ...(ngDevMode ? [{ debugName: "dateLabel" }] : /* istanbul ignore next */ []));
|
|
31
|
+
posNumberLabel = input('POS No', ...(ngDevMode ? [{ debugName: "posNumberLabel" }] : /* istanbul ignore next */ []));
|
|
32
|
+
/** Empty hides the POS number tile. */
|
|
33
|
+
posNumber = input('001', ...(ngDevMode ? [{ debugName: "posNumber" }] : /* istanbul ignore next */ []));
|
|
18
34
|
action = output();
|
|
19
|
-
|
|
35
|
+
digitKeys = DIGIT_KEYS;
|
|
20
36
|
inputValue = signal('', ...(ngDevMode ? [{ debugName: "inputValue" }] : /* istanbul ignore next */ []));
|
|
21
37
|
stage = signal('clerkNumber', ...(ngDevMode ? [{ debugName: "stage" }] : /* istanbul ignore next */ []));
|
|
22
38
|
clerkNumber = signal('', ...(ngDevMode ? [{ debugName: "clerkNumber" }] : /* istanbul ignore next */ []));
|
|
@@ -24,13 +40,25 @@ class PosLogin {
|
|
|
24
40
|
? this.titleClerkNumber()
|
|
25
41
|
: this.titleClerkPassword(), ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
26
42
|
maskInput = computed(() => this.stage() === 'password', ...(ngDevMode ? [{ debugName: "maskInput" }] : /* istanbul ignore next */ []));
|
|
43
|
+
hasEntry = computed(() => this.inputValue().length > 0, ...(ngDevMode ? [{ debugName: "hasEntry" }] : /* istanbul ignore next */ []));
|
|
44
|
+
displayText = computed(() => {
|
|
45
|
+
const value = this.inputValue();
|
|
46
|
+
if (!value) {
|
|
47
|
+
return this.title();
|
|
48
|
+
}
|
|
49
|
+
return this.maskInput() ? '•'.repeat(value.length) : value;
|
|
50
|
+
}, ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
|
|
27
51
|
showBack = computed(() => this.stage() === 'password', ...(ngDevMode ? [{ debugName: "showBack" }] : /* istanbul ignore next */ []));
|
|
28
52
|
primaryLabel = computed(() => this.stage() === 'password' ? this.loginLabel() : this.nextLabel(), ...(ngDevMode ? [{ debugName: "primaryLabel" }] : /* istanbul ignore next */ []));
|
|
29
|
-
primaryEnabled = computed(() => this.inputValue().length > 0 && !this.interactionLocked(), ...(ngDevMode ? [{ debugName: "primaryEnabled" }] : /* istanbul ignore next */ []));
|
|
30
53
|
interactionLocked = computed(() => {
|
|
31
54
|
const status = this.session().status;
|
|
32
55
|
return status === 'busy' || status === 'signedIn';
|
|
33
56
|
}, ...(ngDevMode ? [{ debugName: "interactionLocked" }] : /* istanbul ignore next */ []));
|
|
57
|
+
shownDate = computed(() => new Intl.DateTimeFormat('en-GB', {
|
|
58
|
+
weekday: 'long',
|
|
59
|
+
day: 'numeric',
|
|
60
|
+
month: 'long',
|
|
61
|
+
}).format(new Date()), ...(ngDevMode ? [{ debugName: "shownDate" }] : /* istanbul ignore next */ []));
|
|
34
62
|
sessionStatusText = computed(() => {
|
|
35
63
|
const current = this.session();
|
|
36
64
|
if (current.status === 'busy') {
|
|
@@ -88,14 +116,14 @@ class PosLogin {
|
|
|
88
116
|
this.action.emit({ type: 'login.back' });
|
|
89
117
|
}
|
|
90
118
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLogin, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
91
|
-
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 }, 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 } }, outputs: { action: "action" }, host: { classAttribute: "pos-login" }, ngImport: i0, template: "<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <header class=\"pos-login__header\">\r\n <p class=\"pos-login__kicker\">Adaptive POS</p>\r\n <h1 class=\"pos-login__title\">{{ title() }}</h1>\r\n </header>\r\n\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\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-login__body\">\r\n <div class=\"pos-login__display\">\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 placeholder=\"\u00B7 \u00B7 \u00B7 \u00B7\"\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 (row of keypadRows; track $index) {\r\n <div class=\"pos-login__keypad-row\">\r\n @for (key of row; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [class.pos-login__key--action]=\"key === '\u2190' || key === '.'\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-login__actions\">\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 <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=\"M15 6 9 12l6 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>Back</span>\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [class.pos-login__primary--disabled]=\"!primaryEnabled()\"\r\n [disabled]=\"!primaryEnabled()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n {{ primaryLabel() }}\r\n </button>\r\n </div>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;max-width:26rem;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-login__panel{position:relative;display:flex;flex-direction:column;min-height:100%;padding:var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-login__header{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:var(--pos-space-sm);padding-right:var(--pos-space-2xl)}.pos-login__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-login__title{margin:0;max-width:14ch;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em;line-height:1.15}.pos-login__status{min-height:1.5rem;margin:var(--pos-space-md) 0 var(--pos-space-sm);display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:#d6454514;color:var(--pos-color-danger)}.pos-login__key:disabled,.pos-login__back:disabled{cursor:not-allowed;opacity:.55}.pos-login__body{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-xl);width:100%}.pos-login__display{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-display);box-shadow:inset 0 1px #ffffff0f;padding:var(--pos-space-lg) var(--pos-space-xl)}.pos-login__input{display:block;width:100%;margin:0;border:0;background:transparent;color:var(--pos-color-on-display);font-family:var(--pos-font-family-display);font-size:clamp(1.35rem,3vw,1.85rem);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-display);text-align:center;outline:none}.pos-login__input::placeholder{color:#e8edf259;letter-spacing:.45em}.pos-login__keypad{display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-login__keypad-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__key{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-key-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);font-family:inherit;font-size:1.15rem;font-weight:var(--pos-font-weight-bold);cursor:pointer;transition:background .12s ease,color .12s ease,border-color .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-login__key--action{color:var(--pos-color-text-muted);background:var(--pos-color-surface-muted)}.pos-login__key:active{background:var(--pos-color-key-active);border-color:var(--pos-color-key-active);color:var(--pos-color-on-key-active);transform:translateY(1px)}.pos-login__actions{display:flex;align-items:stretch;gap:var(--pos-space-md);margin-top:auto}.pos-login__back{display:inline-flex;flex:0 0 auto;align-items:center;gap:var(--pos-space-xs);min-height:var(--pos-button-min-height);padding:0 var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated);color:var(--pos-color-text);font:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-login__primary{flex:1 1 auto;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-size:1.05rem;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:filter .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-login__primary:not(:disabled):hover{filter:brightness(.97)}.pos-login__primary:not(:disabled):active{transform:translateY(1px)}.pos-login__primary--disabled,.pos-login__primary:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;filter:none;transform:none}@media(min-width:768px){.pos-login__panel{padding:var(--pos-space-2xl)}.pos-login__key{min-height:var(--pos-keypad-size-md)}}@media(min-width:1100px){.pos-login__key{min-height:var(--pos-keypad-size-lg);font-size:1.25rem}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
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 });
|
|
92
120
|
}
|
|
93
121
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosLogin, decorators: [{
|
|
94
122
|
type: Component,
|
|
95
123
|
args: [{ selector: 'pos-login', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
96
124
|
class: 'pos-login',
|
|
97
|
-
}, template: "<section class=\"pos-login__panel\" [attr.aria-busy]=\"session().status === 'busy' ? true : null\">\r\n <header class=\"pos-login__header\">\r\n <p class=\"pos-login__kicker\">Adaptive POS</p>\r\n <h1 class=\"pos-login__title\">{{ title() }}</h1>\r\n </header>\r\n\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\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-login__body\">\r\n <div class=\"pos-login__display\">\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 placeholder=\"\u00B7 \u00B7 \u00B7 \u00B7\"\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 (row of keypadRows; track $index) {\r\n <div class=\"pos-login__keypad-row\">\r\n @for (key of row; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__key\"\r\n [class.pos-login__key--action]=\"key === '\u2190' || key === '.'\"\r\n [disabled]=\"interactionLocked()\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-login__actions\">\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 <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=\"M15 6 9 12l6 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n <span>Back</span>\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-login__primary\"\r\n [class.pos-login__primary--disabled]=\"!primaryEnabled()\"\r\n [disabled]=\"!primaryEnabled()\"\r\n (click)=\"onPrimary()\"\r\n >\r\n {{ primaryLabel() }}\r\n </button>\r\n </div>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;max-width:26rem;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-login__panel{position:relative;display:flex;flex-direction:column;min-height:100%;padding:var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-login__header{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:var(--pos-space-sm);padding-right:var(--pos-space-2xl)}.pos-login__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-login__title{margin:0;max-width:14ch;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em;line-height:1.15}.pos-login__status{min-height:1.5rem;margin:var(--pos-space-md) 0 var(--pos-space-sm);display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-login__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-login__error{padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:#d6454514;color:var(--pos-color-danger)}.pos-login__key:disabled,.pos-login__back:disabled{cursor:not-allowed;opacity:.55}.pos-login__body{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-xl);width:100%}.pos-login__display{border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-display);box-shadow:inset 0 1px #ffffff0f;padding:var(--pos-space-lg) var(--pos-space-xl)}.pos-login__input{display:block;width:100%;margin:0;border:0;background:transparent;color:var(--pos-color-on-display);font-family:var(--pos-font-family-display);font-size:clamp(1.35rem,3vw,1.85rem);font-weight:var(--pos-font-weight-semibold);letter-spacing:var(--pos-letter-spacing-display);text-align:center;outline:none}.pos-login__input::placeholder{color:#e8edf259;letter-spacing:.45em}.pos-login__keypad{display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-login__keypad-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-md)}.pos-login__key{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-key-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);font-family:inherit;font-size:1.15rem;font-weight:var(--pos-font-weight-bold);cursor:pointer;transition:background .12s ease,color .12s ease,border-color .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-login__key--action{color:var(--pos-color-text-muted);background:var(--pos-color-surface-muted)}.pos-login__key:active{background:var(--pos-color-key-active);border-color:var(--pos-color-key-active);color:var(--pos-color-on-key-active);transform:translateY(1px)}.pos-login__actions{display:flex;align-items:stretch;gap:var(--pos-space-md);margin-top:auto}.pos-login__back{display:inline-flex;flex:0 0 auto;align-items:center;gap:var(--pos-space-xs);min-height:var(--pos-button-min-height);padding:0 var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated);color:var(--pos-color-text);font:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer}.pos-login__primary{flex:1 1 auto;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-size:1.05rem;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:filter .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-login__primary:not(:disabled):hover{filter:brightness(.97)}.pos-login__primary:not(:disabled):active{transform:translateY(1px)}.pos-login__primary--disabled,.pos-login__primary:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;filter:none;transform:none}@media(min-width:768px){.pos-login__panel{padding:var(--pos-space-2xl)}.pos-login__key{min-height:var(--pos-keypad-size-md)}}@media(min-width:1100px){.pos-login__key{min-height:var(--pos-keypad-size-lg);font-size:1.25rem}}@media(prefers-reduced-motion:reduce){.pos-login__key,.pos-login__primary{transition:none}}\n"] }]
|
|
98
|
-
}], propDecorators: { errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], session: [{ type: i0.Input, args: [{ isSignal: true, alias: "session", 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 }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
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"] }]
|
|
126
|
+
}], 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"] }] } });
|
|
99
127
|
|
|
100
128
|
const EMPTY_TOTALS$1 = {
|
|
101
129
|
gross: 0,
|
|
@@ -109,12 +137,12 @@ class PosBasket {
|
|
|
109
137
|
lines = input([], ...(ngDevMode ? [{ debugName: "lines" }] : /* istanbul ignore next */ []));
|
|
110
138
|
totals = input(EMPTY_TOTALS$1, ...(ngDevMode ? [{ debugName: "totals" }] : /* istanbul ignore next */ []));
|
|
111
139
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
140
|
+
/** Draws the panel frame. Off by default so the host can sit the basket flush. */
|
|
141
|
+
bordered = input(false, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
|
|
112
142
|
title = input('Basket', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
113
143
|
emptyMessage = input('Basket is empty', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
114
|
-
clearLabel = input('Clear basket', ...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
|
|
115
144
|
action = output();
|
|
116
145
|
hasLines = computed(() => this.lines().length > 0, ...(ngDevMode ? [{ debugName: "hasLines" }] : /* istanbul ignore next */ []));
|
|
117
|
-
canClear = computed(() => this.hasLines() && !this.disabled(), ...(ngDevMode ? [{ debugName: "canClear" }] : /* istanbul ignore next */ []));
|
|
118
146
|
formatMoney(amount) {
|
|
119
147
|
return new Intl.NumberFormat(undefined, {
|
|
120
148
|
style: 'currency',
|
|
@@ -158,29 +186,118 @@ class PosBasket {
|
|
|
158
186
|
}
|
|
159
187
|
this.action.emit({ type: 'basket.voidLine', lineId: line.lineId });
|
|
160
188
|
}
|
|
161
|
-
onClear() {
|
|
162
|
-
if (!this.canClear()) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.action.emit({ type: 'basket.clear' });
|
|
166
|
-
}
|
|
167
189
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosBasket, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
168
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosBasket, isStandalone: true, selector: "pos-basket", inputs: { lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, totals: { classPropertyName: "totals", publicName: "totals", 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 }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-basket" }, ngImport: i0, template: "<section\r\n class=\"pos-basket__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-basket__header\">\r\n <h2 class=\"pos-basket__title\">{{ title() }}</h2>\r\n <p class=\"pos-basket__count\">\r\n {{ lines().length }}\r\n {{ lines().length === 1 ? 'line' : 'lines' }}\r\n </p>\r\n </header>\r\n\r\n <ul class=\"pos-basket__lines\" aria-label=\"Basket lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-basket__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-basket__line\"\r\n [class.pos-basket__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-basket__line-info\">\r\n <h3 class=\"pos-basket__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-basket__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-basket__line-voided\">Voided</p>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-basket__stepper\"\r\n role=\"group\"\r\n [attr.aria-label]=\"'Quantity for ' + line.name\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Decrease quantity\"\r\n [disabled]=\"!canDecrement(line)\"\r\n (click)=\"onDecrement(line)\"\r\n >\r\n \u2212\r\n </button>\r\n <span class=\"pos-basket__qty\" aria-live=\"polite\">{{ line.qty }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Increase quantity\"\r\n [disabled]=\"!canChangeQuantity(line)\"\r\n (click)=\"onIncrement(line)\"\r\n >\r\n +\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-basket__line-prices\">\r\n <p class=\"pos-basket__unit-price\">{{ formatMoney(line.unitPrice) }}</p>\r\n <p class=\"pos-basket__line-total\">{{ formatMoney(line.lineTotal) }}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__void\"\r\n [attr.aria-label]=\"'Void ' + line.name\"\r\n [disabled]=\"!canVoid(line)\"\r\n (click)=\"onVoid(line)\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M6 6l12 12M18 6 6 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <footer class=\"pos-basket__footer\">\r\n <dl class=\"pos-basket__totals\" aria-live=\"polite\">\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row pos-basket__total-row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__clear\"\r\n [disabled]=\"!canClear()\"\r\n (click)=\"onClear()\"\r\n >\r\n {{ clearLabel() }}\r\n </button>\r\n </footer>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-basket__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-basket__header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md);margin-bottom:var(--pos-space-md)}.pos-basket__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em}.pos-basket__count{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-basket__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:0;padding:0;overflow-y:auto;list-style:none}.pos-basket__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-basket__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info void\" \"stepper prices\";align-items:center;gap:var(--pos-space-sm) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-basket__line-info{grid-area:info;min-width:0}.pos-basket__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-basket__line-sku,.pos-basket__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-basket__line-sku{color:var(--pos-color-text-muted)}.pos-basket__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-basket__stepper{grid-area:stepper;display:inline-flex;align-items:center;gap:var(--pos-space-xs);width:fit-content;padding:var(--pos-space-xs);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface)}.pos-basket__qty-btn,.pos-basket__void{display:inline-flex;align-items:center;justify-content:center;margin:0;border:0;background:transparent;color:var(--pos-color-text);font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-basket__qty-btn{min-width:2.75rem;min-height:2.75rem;border-radius:var(--pos-radius-sm);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-basket__qty-btn:not(:disabled):active,.pos-basket__void:not(:disabled):active{background:var(--pos-color-key-active);color:var(--pos-color-on-key-active)}.pos-basket__qty{min-width:1.75rem;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);text-align:center}.pos-basket__line-prices{grid-area:prices;display:flex;flex-direction:column;align-items:flex-end;gap:var(--pos-space-xs)}.pos-basket__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold)}.pos-basket__void{grid-area:void;justify-self:end;min-width:2.75rem;min-height:2.75rem;border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);color:var(--pos-color-text-muted)}.pos-basket__qty-btn:disabled,.pos-basket__void:disabled,.pos-basket__clear:disabled{cursor:not-allowed;opacity:.55}.pos-basket__qty-btn:focus-visible,.pos-basket__void:focus-visible,.pos-basket__clear:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}.pos-basket__line--voided .pos-basket__line-name,.pos-basket__line--voided .pos-basket__line-sku,.pos-basket__line--voided .pos-basket__line-prices{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-basket__footer{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-basket__totals{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-basket__total-row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__total-row dt,.pos-basket__total-row dd{margin:0}.pos-basket__total-row--due{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-basket__clear{min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-danger);color:var(--pos-color-on-danger);font:inherit;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-basket__clear:not(:disabled):active{transform:translateY(1px)}.pos-basket__clear:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);transform:none}@media(min-width:768px){.pos-basket__panel{padding:var(--pos-space-xl)}.pos-basket__line{grid-template-columns:minmax(0,1fr) auto auto auto;grid-template-areas:\"info stepper prices void\";gap:var(--pos-space-md)}}@media(prefers-reduced-motion:reduce){.pos-basket__clear{transform:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
190
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosBasket, isStandalone: true, selector: "pos-basket", inputs: { lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, totals: { classPropertyName: "totals", publicName: "totals", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-basket" }, ngImport: i0, template: "<section\r\n class=\"pos-basket__panel\"\r\n [class.pos-basket__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-basket__header\">\r\n <h2 class=\"pos-basket__title\">{{ title() }}</h2>\r\n <p class=\"pos-basket__count\">\r\n {{ lines().length }}\r\n {{ lines().length === 1 ? 'line' : 'lines' }}\r\n </p>\r\n </header>\r\n\r\n <ul class=\"pos-basket__lines\" aria-label=\"Basket lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-basket__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-basket__line\"\r\n [class.pos-basket__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-basket__line-info\">\r\n <h3 class=\"pos-basket__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-basket__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-basket__line-voided\">Voided</p>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-basket__stepper\"\r\n role=\"group\"\r\n [attr.aria-label]=\"'Quantity for ' + line.name\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Decrease quantity\"\r\n [disabled]=\"!canDecrement(line)\"\r\n (click)=\"onDecrement(line)\"\r\n >\r\n \u2212\r\n </button>\r\n <span class=\"pos-basket__qty\" aria-live=\"polite\">{{ line.qty }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Increase quantity\"\r\n [disabled]=\"!canChangeQuantity(line)\"\r\n (click)=\"onIncrement(line)\"\r\n >\r\n +\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-basket__line-prices\">\r\n <p class=\"pos-basket__unit-price\">{{ formatMoney(line.unitPrice) }}</p>\r\n <p class=\"pos-basket__line-total\">{{ formatMoney(line.lineTotal) }}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__void\"\r\n [attr.aria-label]=\"'Void ' + line.name\"\r\n [disabled]=\"!canVoid(line)\"\r\n (click)=\"onVoid(line)\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M6 6l12 12M18 6 6 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <footer class=\"pos-basket__footer\">\r\n <dl class=\"pos-basket__totals\" aria-live=\"polite\">\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row pos-basket__total-row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n </footer>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-basket__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-basket__panel--bordered{border:1px solid var(--pos-color-border)}.pos-basket__header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md);margin-bottom:var(--pos-space-md)}.pos-basket__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-tight)}.pos-basket__count{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-basket__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:0;padding:0;overflow-y:auto;list-style:none}.pos-basket__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-basket__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info void\" \"stepper prices\";align-items:center;gap:var(--pos-space-sm) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-basket__line-info{grid-area:info;min-width:0}.pos-basket__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-basket__line-sku,.pos-basket__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-basket__line-sku{color:var(--pos-color-text-muted)}.pos-basket__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-basket__stepper{grid-area:stepper;display:inline-flex;align-items:center;gap:var(--pos-space-xs);width:fit-content;padding:var(--pos-space-xs);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface)}.pos-basket__qty-btn,.pos-basket__void{display:inline-flex;align-items:center;justify-content:center;margin:0;border:0;background:transparent;color:var(--pos-color-text);font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-basket__qty-btn{min-width:2.75rem;min-height:2.75rem;border-radius:var(--pos-radius-sm);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-basket__qty-btn:not(:disabled):active,.pos-basket__void:not(:disabled):active{background:var(--pos-color-key-active);color:var(--pos-color-on-key-active)}.pos-basket__qty{min-width:1.75rem;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);text-align:center}.pos-basket__line-prices{grid-area:prices;display:flex;flex-direction:column;align-items:flex-end;gap:var(--pos-space-xs)}.pos-basket__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold)}.pos-basket__void{grid-area:void;justify-self:end;min-width:2.75rem;min-height:2.75rem;border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);color:var(--pos-color-text-muted)}.pos-basket__qty-btn:disabled,.pos-basket__void:disabled{cursor:not-allowed;opacity:.55}.pos-basket__qty-btn:focus-visible,.pos-basket__void:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}.pos-basket__line--voided .pos-basket__line-name,.pos-basket__line--voided .pos-basket__line-sku,.pos-basket__line--voided .pos-basket__line-prices{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-basket__footer{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-basket__totals{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-basket__total-row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__total-row dt,.pos-basket__total-row dd{margin:0}.pos-basket__total-row--due{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}@media(min-width:768px){.pos-basket__panel{padding:var(--pos-space-xl)}.pos-basket__line{grid-template-columns:minmax(0,1fr) auto auto auto;grid-template-areas:\"info stepper prices void\";gap:var(--pos-space-md)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
169
191
|
}
|
|
170
192
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosBasket, decorators: [{
|
|
171
193
|
type: Component,
|
|
172
194
|
args: [{ selector: 'pos-basket', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
173
195
|
class: 'pos-basket',
|
|
174
|
-
}, template: "<section\r\n class=\"pos-basket__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-basket__header\">\r\n <h2 class=\"pos-basket__title\">{{ title() }}</h2>\r\n <p class=\"pos-basket__count\">\r\n {{ lines().length }}\r\n {{ lines().length === 1 ? 'line' : 'lines' }}\r\n </p>\r\n </header>\r\n\r\n <ul class=\"pos-basket__lines\" aria-label=\"Basket lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-basket__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-basket__line\"\r\n [class.pos-basket__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-basket__line-info\">\r\n <h3 class=\"pos-basket__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-basket__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-basket__line-voided\">Voided</p>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-basket__stepper\"\r\n role=\"group\"\r\n [attr.aria-label]=\"'Quantity for ' + line.name\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Decrease quantity\"\r\n [disabled]=\"!canDecrement(line)\"\r\n (click)=\"onDecrement(line)\"\r\n >\r\n \u2212\r\n </button>\r\n <span class=\"pos-basket__qty\" aria-live=\"polite\">{{ line.qty }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Increase quantity\"\r\n [disabled]=\"!canChangeQuantity(line)\"\r\n (click)=\"onIncrement(line)\"\r\n >\r\n +\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-basket__line-prices\">\r\n <p class=\"pos-basket__unit-price\">{{ formatMoney(line.unitPrice) }}</p>\r\n <p class=\"pos-basket__line-total\">{{ formatMoney(line.lineTotal) }}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__void\"\r\n [attr.aria-label]=\"'Void ' + line.name\"\r\n [disabled]=\"!canVoid(line)\"\r\n (click)=\"onVoid(line)\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M6 6l12 12M18 6 6 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <footer class=\"pos-basket__footer\">\r\n <dl class=\"pos-basket__totals\" aria-live=\"polite\">\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row pos-basket__total-row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n
|
|
175
|
-
}], propDecorators: { lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], totals: [{ type: i0.Input, args: [{ isSignal: true, alias: "totals", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }],
|
|
196
|
+
}, template: "<section\r\n class=\"pos-basket__panel\"\r\n [class.pos-basket__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-basket__header\">\r\n <h2 class=\"pos-basket__title\">{{ title() }}</h2>\r\n <p class=\"pos-basket__count\">\r\n {{ lines().length }}\r\n {{ lines().length === 1 ? 'line' : 'lines' }}\r\n </p>\r\n </header>\r\n\r\n <ul class=\"pos-basket__lines\" aria-label=\"Basket lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-basket__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-basket__line\"\r\n [class.pos-basket__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-basket__line-info\">\r\n <h3 class=\"pos-basket__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-basket__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-basket__line-voided\">Voided</p>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-basket__stepper\"\r\n role=\"group\"\r\n [attr.aria-label]=\"'Quantity for ' + line.name\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Decrease quantity\"\r\n [disabled]=\"!canDecrement(line)\"\r\n (click)=\"onDecrement(line)\"\r\n >\r\n \u2212\r\n </button>\r\n <span class=\"pos-basket__qty\" aria-live=\"polite\">{{ line.qty }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__qty-btn\"\r\n aria-label=\"Increase quantity\"\r\n [disabled]=\"!canChangeQuantity(line)\"\r\n (click)=\"onIncrement(line)\"\r\n >\r\n +\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-basket__line-prices\">\r\n <p class=\"pos-basket__unit-price\">{{ formatMoney(line.unitPrice) }}</p>\r\n <p class=\"pos-basket__line-total\">{{ formatMoney(line.lineTotal) }}</p>\r\n </div>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"pos-basket__void\"\r\n [attr.aria-label]=\"'Void ' + line.name\"\r\n [disabled]=\"!canVoid(line)\"\r\n (click)=\"onVoid(line)\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"18\"\r\n height=\"18\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n d=\"M6 6l12 12M18 6 6 18\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <footer class=\"pos-basket__footer\">\r\n <dl class=\"pos-basket__totals\" aria-live=\"polite\">\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-basket__total-row pos-basket__total-row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n </footer>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-basket__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-basket__panel--bordered{border:1px solid var(--pos-color-border)}.pos-basket__header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md);margin-bottom:var(--pos-space-md)}.pos-basket__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-tight)}.pos-basket__count{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-basket__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:0;padding:0;overflow-y:auto;list-style:none}.pos-basket__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-basket__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info void\" \"stepper prices\";align-items:center;gap:var(--pos-space-sm) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-basket__line-info{grid-area:info;min-width:0}.pos-basket__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-basket__line-sku,.pos-basket__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-basket__line-sku{color:var(--pos-color-text-muted)}.pos-basket__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-basket__stepper{grid-area:stepper;display:inline-flex;align-items:center;gap:var(--pos-space-xs);width:fit-content;padding:var(--pos-space-xs);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface)}.pos-basket__qty-btn,.pos-basket__void{display:inline-flex;align-items:center;justify-content:center;margin:0;border:0;background:transparent;color:var(--pos-color-text);font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-basket__qty-btn{min-width:2.75rem;min-height:2.75rem;border-radius:var(--pos-radius-sm);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-basket__qty-btn:not(:disabled):active,.pos-basket__void:not(:disabled):active{background:var(--pos-color-key-active);color:var(--pos-color-on-key-active)}.pos-basket__qty{min-width:1.75rem;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);text-align:center}.pos-basket__line-prices{grid-area:prices;display:flex;flex-direction:column;align-items:flex-end;gap:var(--pos-space-xs)}.pos-basket__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold)}.pos-basket__void{grid-area:void;justify-self:end;min-width:2.75rem;min-height:2.75rem;border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);color:var(--pos-color-text-muted)}.pos-basket__qty-btn:disabled,.pos-basket__void:disabled{cursor:not-allowed;opacity:.55}.pos-basket__qty-btn:focus-visible,.pos-basket__void:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}.pos-basket__line--voided .pos-basket__line-name,.pos-basket__line--voided .pos-basket__line-sku,.pos-basket__line--voided .pos-basket__line-prices{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-basket__footer{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-basket__totals{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-basket__total-row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-basket__total-row dt,.pos-basket__total-row dd{margin:0}.pos-basket__total-row--due{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}@media(min-width:768px){.pos-basket__panel{padding:var(--pos-space-xl)}.pos-basket__line{grid-template-columns:minmax(0,1fr) auto auto auto;grid-template-areas:\"info stepper prices void\";gap:var(--pos-space-md)}}\n"] }]
|
|
197
|
+
}], propDecorators: { lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], totals: [{ type: i0.Input, args: [{ isSignal: true, alias: "totals", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
198
|
+
|
|
199
|
+
class PosHeader {
|
|
200
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
201
|
+
context = input('', ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
202
|
+
/** When false, the brand image is omitted, including the built-in mark. */
|
|
203
|
+
showBrandImage = input(true, ...(ngDevMode ? [{ debugName: "showBrandImage" }] : /* istanbul ignore next */ []));
|
|
204
|
+
/** Partner image URL. Empty, while `showBrandImage` is true, uses the built-in Retalia mark. */
|
|
205
|
+
brandImage = input('', ...(ngDevMode ? [{ debugName: "brandImage" }] : /* istanbul ignore next */ []));
|
|
206
|
+
/** Wordmark after the image. Empty shows no text. */
|
|
207
|
+
brandLabel = input('', ...(ngDevMode ? [{ debugName: "brandLabel" }] : /* istanbul ignore next */ []));
|
|
208
|
+
clerkName = input('', ...(ngDevMode ? [{ debugName: "clerkName" }] : /* istanbul ignore next */ []));
|
|
209
|
+
clerkRole = input('', ...(ngDevMode ? [{ debugName: "clerkRole" }] : /* istanbul ignore next */ []));
|
|
210
|
+
signOutLabel = input('Portal Logout', ...(ngDevMode ? [{ debugName: "signOutLabel" }] : /* istanbul ignore next */ []));
|
|
211
|
+
menuLabel = input('Menu', ...(ngDevMode ? [{ debugName: "menuLabel" }] : /* istanbul ignore next */ []));
|
|
212
|
+
canSignOut = input(true, ...(ngDevMode ? [{ debugName: "canSignOut" }] : /* istanbul ignore next */ []));
|
|
213
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
214
|
+
action = output();
|
|
215
|
+
menuOpen = signal(false, ...(ngDevMode ? [{ debugName: "menuOpen" }] : /* istanbul ignore next */ []));
|
|
216
|
+
initial = computed(() => {
|
|
217
|
+
const name = this.clerkName().trim();
|
|
218
|
+
return name ? name.charAt(0).toUpperCase() : '';
|
|
219
|
+
}, ...(ngDevMode ? [{ debugName: "initial" }] : /* istanbul ignore next */ []));
|
|
220
|
+
toggleMenu() {
|
|
221
|
+
if (this.disabled() || !this.canSignOut()) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
this.menuOpen.update((open) => !open);
|
|
225
|
+
}
|
|
226
|
+
closeMenu() {
|
|
227
|
+
this.menuOpen.set(false);
|
|
228
|
+
}
|
|
229
|
+
onSignOut() {
|
|
230
|
+
if (this.disabled() || !this.canSignOut()) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.menuOpen.set(false);
|
|
234
|
+
this.action.emit({ type: 'header.signOut' });
|
|
235
|
+
}
|
|
236
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
237
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosHeader, isStandalone: true, selector: "pos-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", 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 }, clerkName: { classPropertyName: "clerkName", publicName: "clerkName", isSignal: true, isRequired: false, transformFunction: null }, clerkRole: { classPropertyName: "clerkRole", publicName: "clerkRole", isSignal: true, isRequired: false, transformFunction: null }, signOutLabel: { classPropertyName: "signOutLabel", publicName: "signOutLabel", isSignal: true, isRequired: false, transformFunction: null }, menuLabel: { classPropertyName: "menuLabel", publicName: "menuLabel", isSignal: true, isRequired: false, transformFunction: null }, canSignOut: { classPropertyName: "canSignOut", publicName: "canSignOut", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { attributes: { "role": "banner" }, classAttribute: "pos-header" }, ngImport: i0, template: "<div class=\"pos-header__identity\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-header__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-header__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-header__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-header__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n @if (title()) {\r\n <h1 class=\"pos-header__title\">{{ title() }}</h1>\r\n }\r\n @if (context()) {\r\n <p class=\"pos-header__context\">{{ context() }}</p>\r\n }\r\n</div>\r\n\r\n<div class=\"pos-header__session\">\r\n @if (clerkName()) {\r\n <div class=\"pos-header__clerk\">\r\n @if (canSignOut()) {\r\n <div class=\"pos-header__menu-anchor\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__menu-button\"\r\n [attr.aria-label]=\"menuLabel()\"\r\n [attr.aria-expanded]=\"menuOpen()\"\r\n aria-haspopup=\"menu\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"toggleMenu()\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <circle cx=\"5\" cy=\"12\" r=\"1.6\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1.6\" />\r\n <circle cx=\"19\" cy=\"12\" r=\"1.6\" />\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n <span class=\"pos-header__avatar\" aria-hidden=\"true\">{{ initial() }}</span>\r\n <span class=\"pos-header__clerk-text\">\r\n <span class=\"pos-header__clerk-name\">{{ clerkName() }}</span>\r\n @if (clerkRole()) {\r\n <span class=\"pos-header__clerk-role\">{{ clerkRole() }}</span>\r\n }\r\n </span>\r\n </div>\r\n }\r\n @if (menuOpen()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__backdrop\"\r\n aria-label=\"Close menu\"\r\n (click)=\"closeMenu()\"\r\n ></button>\r\n <div class=\"pos-header__menu\" role=\"menu\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__logout\"\r\n role=\"menuitem\"\r\n (click)=\"onSignOut()\"\r\n >\r\n {{ signOutLabel() }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--pos-space-sm) var(--pos-space-md);box-sizing:border-box;width:100%;min-width:0;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-header__identity,.pos-header__session{display:flex;flex-wrap:wrap;align-items:center;gap:var(--pos-space-sm) var(--pos-space-md);min-width:0}.pos-header__session{position:relative;margin-left:auto}.pos-header__brand{display:flex;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-header__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-header__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-header__title{margin:0;font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold)}.pos-header__context{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-header__clerk{display:flex;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-header__avatar{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);border-radius:var(--pos-radius-pill);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-header__clerk-text{display:flex;flex-direction:column;min-width:0}.pos-header__clerk-name{font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-header__clerk-role{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.2;text-transform:lowercase}.pos-header__menu-anchor{position:relative;flex:0 0 auto}.pos-header__menu-button{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);padding:0;border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-pill);background:var(--pos-color-surface);color:var(--pos-color-text-muted);cursor:pointer}.pos-header__menu-button svg{width:1.25rem;height:1.25rem;fill:currentColor}.pos-header__menu-button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}.pos-header__backdrop{position:fixed;inset:0;z-index:1;border:0;background:transparent;cursor:default}.pos-header__menu{position:absolute;top:calc(100% + var(--pos-space-xs));right:0;z-index:2;box-sizing:border-box;width:16rem;padding:var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay)}.pos-header__logout{display:flex;align-items:center;width:100%;min-height:var(--pos-button-min-height);padding:0 var(--pos-space-md);border:0;border-radius:var(--pos-radius-md);background:transparent;color:var(--pos-color-danger);font:inherit;font-weight:var(--pos-font-weight-semibold);text-align:left;cursor:pointer}.pos-header__logout:hover{background:color-mix(in srgb,var(--pos-color-danger) 12%,var(--pos-color-surface))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
238
|
+
}
|
|
239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosHeader, decorators: [{
|
|
240
|
+
type: Component,
|
|
241
|
+
args: [{ selector: 'pos-header', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
242
|
+
class: 'pos-header',
|
|
243
|
+
role: 'banner',
|
|
244
|
+
}, template: "<div class=\"pos-header__identity\">\r\n @if (showBrandImage() || brandLabel()) {\r\n <div class=\"pos-header__brand\">\r\n @if (showBrandImage()) {\r\n @if (brandImage()) {\r\n <img\r\n class=\"pos-header__brand-image\"\r\n [src]=\"brandImage()\"\r\n [alt]=\"brandLabel() ? '' : 'Brand'\"\r\n />\r\n } @else {\r\n <svg\r\n class=\"pos-header__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-header__brand-label\">{{ brandLabel() }}</span>\r\n }\r\n </div>\r\n }\r\n @if (title()) {\r\n <h1 class=\"pos-header__title\">{{ title() }}</h1>\r\n }\r\n @if (context()) {\r\n <p class=\"pos-header__context\">{{ context() }}</p>\r\n }\r\n</div>\r\n\r\n<div class=\"pos-header__session\">\r\n @if (clerkName()) {\r\n <div class=\"pos-header__clerk\">\r\n @if (canSignOut()) {\r\n <div class=\"pos-header__menu-anchor\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__menu-button\"\r\n [attr.aria-label]=\"menuLabel()\"\r\n [attr.aria-expanded]=\"menuOpen()\"\r\n aria-haspopup=\"menu\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"toggleMenu()\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <circle cx=\"5\" cy=\"12\" r=\"1.6\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"1.6\" />\r\n <circle cx=\"19\" cy=\"12\" r=\"1.6\" />\r\n </svg>\r\n </button>\r\n </div>\r\n }\r\n <span class=\"pos-header__avatar\" aria-hidden=\"true\">{{ initial() }}</span>\r\n <span class=\"pos-header__clerk-text\">\r\n <span class=\"pos-header__clerk-name\">{{ clerkName() }}</span>\r\n @if (clerkRole()) {\r\n <span class=\"pos-header__clerk-role\">{{ clerkRole() }}</span>\r\n }\r\n </span>\r\n </div>\r\n }\r\n @if (menuOpen()) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__backdrop\"\r\n aria-label=\"Close menu\"\r\n (click)=\"closeMenu()\"\r\n ></button>\r\n <div class=\"pos-header__menu\" role=\"menu\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-header__logout\"\r\n role=\"menuitem\"\r\n (click)=\"onSignOut()\"\r\n >\r\n {{ signOutLabel() }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--pos-space-sm) var(--pos-space-md);box-sizing:border-box;width:100%;min-width:0;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-header__identity,.pos-header__session{display:flex;flex-wrap:wrap;align-items:center;gap:var(--pos-space-sm) var(--pos-space-md);min-width:0}.pos-header__session{position:relative;margin-left:auto}.pos-header__brand{display:flex;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-header__brand-image{flex:0 0 auto;width:auto;height:var(--pos-space-xl);color:var(--pos-color-ink)}.pos-header__brand-label{font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-brand)}.pos-header__title{margin:0;font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold)}.pos-header__context{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-header__clerk{display:flex;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-header__avatar{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);border-radius:var(--pos-radius-pill);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-header__clerk-text{display:flex;flex-direction:column;min-width:0}.pos-header__clerk-name{font-weight:var(--pos-font-weight-bold);line-height:1.2}.pos-header__clerk-role{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);line-height:1.2;text-transform:lowercase}.pos-header__menu-anchor{position:relative;flex:0 0 auto}.pos-header__menu-button{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);padding:0;border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-pill);background:var(--pos-color-surface);color:var(--pos-color-text-muted);cursor:pointer}.pos-header__menu-button svg{width:1.25rem;height:1.25rem;fill:currentColor}.pos-header__menu-button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}.pos-header__backdrop{position:fixed;inset:0;z-index:1;border:0;background:transparent;cursor:default}.pos-header__menu{position:absolute;top:calc(100% + var(--pos-space-xs));right:0;z-index:2;box-sizing:border-box;width:16rem;padding:var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-surface);box-shadow:var(--pos-shadow-overlay)}.pos-header__logout{display:flex;align-items:center;width:100%;min-height:var(--pos-button-min-height);padding:0 var(--pos-space-md);border:0;border-radius:var(--pos-radius-md);background:transparent;color:var(--pos-color-danger);font:inherit;font-weight:var(--pos-font-weight-semibold);text-align:left;cursor:pointer}.pos-header__logout:hover{background:color-mix(in srgb,var(--pos-color-danger) 12%,var(--pos-color-surface))}\n"] }]
|
|
245
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", 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 }] }], clerkName: [{ type: i0.Input, args: [{ isSignal: true, alias: "clerkName", required: false }] }], clerkRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "clerkRole", required: false }] }], signOutLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "signOutLabel", required: false }] }], menuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuLabel", required: false }] }], canSignOut: [{ type: i0.Input, args: [{ isSignal: true, alias: "canSignOut", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
246
|
+
|
|
247
|
+
/** Bar buttons, in display order. Other envelope actions belong to other components. */
|
|
248
|
+
const BUTTONS = [
|
|
249
|
+
{
|
|
250
|
+
id: 'clearBasket',
|
|
251
|
+
label: 'Cancel',
|
|
252
|
+
className: 'pos-transaction-action-bar__button--cancel',
|
|
253
|
+
intent: { type: 'actionBar.clearBasket' },
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: 'tender',
|
|
257
|
+
label: 'Cash',
|
|
258
|
+
className: 'pos-transaction-action-bar__button--cash',
|
|
259
|
+
intent: { type: 'actionBar.tender' },
|
|
260
|
+
},
|
|
261
|
+
];
|
|
262
|
+
class PosTransactionActionBar {
|
|
263
|
+
/** Action ids from the envelope. A button is shown only when its id is listed. */
|
|
264
|
+
availableActions = input([], ...(ngDevMode ? [{ debugName: "availableActions" }] : /* istanbul ignore next */ []));
|
|
265
|
+
/** Locks the shown buttons while the host is busy. Does not choose which actions exist. */
|
|
266
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
267
|
+
action = output();
|
|
268
|
+
buttons = computed(() => {
|
|
269
|
+
const offered = new Set(this.availableActions());
|
|
270
|
+
return BUTTONS.filter((button) => offered.has(button.id));
|
|
271
|
+
}, ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
|
|
272
|
+
onPress(button) {
|
|
273
|
+
if (this.disabled()) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.action.emit(button.intent);
|
|
277
|
+
}
|
|
278
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTransactionActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
279
|
+
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 } }, outputs: { action: "action" }, host: { attributes: { "role": "toolbar", "aria-label": "Sale actions" }, classAttribute: "pos-transaction-action-bar" }, ngImport: i0, template: "@for (button of buttons(); track button.id) {\r\n <button\r\n type=\"button\"\r\n [class]=\"'pos-transaction-action-bar__button ' + button.className\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onPress(button)\"\r\n >\r\n {{ button.label }}\r\n </button>\r\n}\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-md);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}:host:empty{display:none}.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-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{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
280
|
+
}
|
|
281
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTransactionActionBar, decorators: [{
|
|
282
|
+
type: Component,
|
|
283
|
+
args: [{ selector: 'pos-transaction-action-bar', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
284
|
+
class: 'pos-transaction-action-bar',
|
|
285
|
+
role: 'toolbar',
|
|
286
|
+
'aria-label': 'Sale actions',
|
|
287
|
+
}, template: "@for (button of buttons(); track button.id) {\r\n <button\r\n type=\"button\"\r\n [class]=\"'pos-transaction-action-bar__button ' + button.className\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onPress(button)\"\r\n >\r\n {{ button.label }}\r\n </button>\r\n}\r\n", styles: [":host{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--pos-space-md);width:100%;box-sizing:border-box;padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}:host:empty{display:none}.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-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{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-transaction-action-bar__button:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:default}\n"] }]
|
|
288
|
+
}], propDecorators: { availableActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableActions", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
176
289
|
|
|
177
290
|
class PosItemEntry {
|
|
178
291
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
292
|
+
/** Draws the panel frame. Off by default so the host can sit the field flush. */
|
|
293
|
+
bordered = input(false, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
|
|
179
294
|
errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
180
295
|
autofocus = input(true, ...(ngDevMode ? [{ debugName: "autofocus" }] : /* istanbul ignore next */ []));
|
|
181
296
|
label = input('Item', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
182
|
-
placeholder = input('Scan
|
|
183
|
-
|
|
297
|
+
placeholder = input('Scan barcode, search products', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
298
|
+
scannerStatus = input('scanner ready', ...(ngDevMode ? [{ debugName: "scannerStatus" }] : /* istanbul ignore next */ []));
|
|
299
|
+
/** Key that moves focus to the field. Empty hides the hint and the shortcut. */
|
|
300
|
+
focusHotkey = input('F2', ...(ngDevMode ? [{ debugName: "focusHotkey" }] : /* istanbul ignore next */ []));
|
|
184
301
|
action = output();
|
|
185
302
|
itemInput = viewChild('itemInput', ...(ngDevMode ? [{ debugName: "itemInput" }] : /* istanbul ignore next */ []));
|
|
186
303
|
reference = signal('', ...(ngDevMode ? [{ debugName: "reference" }] : /* istanbul ignore next */ []));
|
|
@@ -192,6 +309,20 @@ class PosItemEntry {
|
|
|
192
309
|
}
|
|
193
310
|
});
|
|
194
311
|
}
|
|
312
|
+
onDocumentKeydown(event) {
|
|
313
|
+
const hotkey = this.focusHotkey();
|
|
314
|
+
if (!hotkey || event.key !== hotkey || event.repeat) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (this.disabled()) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
event.preventDefault();
|
|
324
|
+
this.focusInput();
|
|
325
|
+
}
|
|
195
326
|
onInput(event) {
|
|
196
327
|
const target = event.target;
|
|
197
328
|
if (!(target instanceof HTMLInputElement)) {
|
|
@@ -201,13 +332,10 @@ class PosItemEntry {
|
|
|
201
332
|
}
|
|
202
333
|
onSubmit(event) {
|
|
203
334
|
event.preventDefault();
|
|
204
|
-
if (this.
|
|
335
|
+
if (!this.canSubmit()) {
|
|
205
336
|
return;
|
|
206
337
|
}
|
|
207
338
|
const reference = this.reference().trim();
|
|
208
|
-
if (!reference) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
339
|
this.action.emit({ type: 'itemEntry.submit', reference });
|
|
212
340
|
this.reference.set('');
|
|
213
341
|
this.focusInput();
|
|
@@ -216,60 +344,23 @@ class PosItemEntry {
|
|
|
216
344
|
this.itemInput()?.nativeElement.focus();
|
|
217
345
|
}
|
|
218
346
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosItemEntry, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
219
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosItemEntry, isStandalone: true, selector: "pos-item-entry", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null },
|
|
347
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosItemEntry, isStandalone: true, selector: "pos-item-entry", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, scannerStatus: { classPropertyName: "scannerStatus", publicName: "scannerStatus", isSignal: true, isRequired: false, transformFunction: null }, focusHotkey: { classPropertyName: "focusHotkey", publicName: "focusHotkey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "document:keydown": "onDocumentKeydown($event)" }, classAttribute: "pos-item-entry" }, viewQueries: [{ propertyName: "itemInput", first: true, predicate: ["itemInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<section\r\n class=\"pos-item-entry__panel\"\r\n [class.pos-item-entry__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <form class=\"pos-item-entry__form\" (submit)=\"onSubmit($event)\">\r\n <div\r\n class=\"pos-item-entry__omnibox\"\r\n [class.pos-item-entry__omnibox--disabled]=\"disabled()\"\r\n >\r\n <label class=\"pos-item-entry__field\">\r\n <span class=\"pos-item-entry__label\">{{ label() }}</span>\r\n <svg\r\n class=\"pos-item-entry__search\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\r\n </svg>\r\n <input\r\n #itemInput\r\n class=\"pos-item-entry__input\"\r\n type=\"text\"\r\n name=\"itemReference\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n [attr.autocorrect]=\"'off'\"\r\n [attr.autocapitalize]=\"'none'\"\r\n enterkeyhint=\"done\"\r\n [placeholder]=\"placeholder()\"\r\n [value]=\"reference()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\r\n [attr.aria-keyshortcuts]=\"focusHotkey() || null\"\r\n (input)=\"onInput($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"pos-item-entry__scanner\">\r\n <svg\r\n class=\"pos-item-entry__scan\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <line x1=\"4\" y1=\"6\" x2=\"4\" y2=\"18\" />\r\n <line x1=\"7\" y1=\"6\" x2=\"7\" y2=\"18\" />\r\n <line x1=\"11\" y1=\"6\" x2=\"11\" y2=\"18\" />\r\n <line x1=\"14\" y1=\"6\" x2=\"14\" y2=\"18\" />\r\n <line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n <line x1=\"21\" y1=\"6\" x2=\"21\" y2=\"18\" />\r\n </svg>\r\n {{ scannerStatus() }}\r\n </span>\r\n\r\n @if (focusHotkey()) {\r\n <kbd class=\"pos-item-entry__hotkey\">{{ focusHotkey() }}</kbd>\r\n }\r\n </div>\r\n </form>\r\n\r\n <div class=\"pos-item-entry__status\" aria-live=\"polite\">\r\n @if (errorMessage()) {\r\n <p class=\"pos-item-entry__error\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-item-entry__panel{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-item-entry__panel--bordered{padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-item-entry__form{min-width:0}.pos-item-entry__omnibox{display:flex;align-items:center;gap:var(--pos-space-sm);box-sizing:border-box;min-height:var(--pos-button-min-height);padding:0 var(--pos-space-md) 0 var(--pos-space-lg);border:1px solid transparent;border-radius:var(--pos-radius-pill);background:var(--pos-color-surface-muted);transition:border-color .12s ease,box-shadow .12s ease,background-color .12s ease}.pos-item-entry__omnibox:focus-within{border-color:var(--pos-color-primary);background:var(--pos-color-surface);box-shadow:0 0 0 3px color-mix(in srgb,var(--pos-color-primary) 35%,transparent)}.pos-item-entry__omnibox:has(.pos-item-entry__input[aria-invalid=true]){border-color:var(--pos-color-danger)}.pos-item-entry__omnibox--disabled{cursor:not-allowed;background:var(--pos-color-disabled)}.pos-item-entry__field{display:flex;flex:1 1 auto;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-item-entry__label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pos-item-entry__search,.pos-item-entry__scan{flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.pos-item-entry__search{width:15px;height:15px;color:var(--pos-color-text-muted)}.pos-item-entry__input{box-sizing:border-box;flex:1 1 auto;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) - 8px);margin:0;padding:0;border:0;background:transparent;color:var(--pos-color-text);font:inherit;outline:none}.pos-item-entry__input::placeholder{color:var(--pos-color-text-muted);opacity:1}.pos-item-entry__input:disabled{cursor:not-allowed;color:var(--pos-color-on-disabled)}.pos-item-entry__scanner{display:inline-flex;flex:0 0 auto;align-items:center;gap:var(--pos-space-xs);padding:2px var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-sm);background:var(--pos-color-surface);color:var(--pos-color-text-muted);font-size:.72em;line-height:1.2;white-space:nowrap}.pos-item-entry__omnibox--disabled .pos-item-entry__scanner{color:var(--pos-color-on-disabled)}.pos-item-entry__scan{width:11px;height:11px}.pos-item-entry__hotkey{flex:0 0 auto;margin:0;padding:0;border:0;background:transparent;color:var(--pos-color-text-muted);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-item-entry__status{min-height:0}.pos-item-entry__error{margin:0;padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:color-mix(in srgb,var(--pos-color-danger) 12%,transparent);color:var(--pos-color-danger);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}@media(max-width:479px){.pos-item-entry__hotkey{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}}@media(min-width:768px){.pos-item-entry__panel--bordered{padding:var(--pos-space-xl)}}@media(prefers-reduced-motion:reduce){.pos-item-entry__omnibox{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
220
348
|
}
|
|
221
349
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosItemEntry, decorators: [{
|
|
222
350
|
type: Component,
|
|
223
351
|
args: [{ selector: 'pos-item-entry', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
224
352
|
class: 'pos-item-entry',
|
|
225
|
-
|
|
226
|
-
|
|
353
|
+
'(document:keydown)': 'onDocumentKeydown($event)',
|
|
354
|
+
}, template: "<section\r\n class=\"pos-item-entry__panel\"\r\n [class.pos-item-entry__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <form class=\"pos-item-entry__form\" (submit)=\"onSubmit($event)\">\r\n <div\r\n class=\"pos-item-entry__omnibox\"\r\n [class.pos-item-entry__omnibox--disabled]=\"disabled()\"\r\n >\r\n <label class=\"pos-item-entry__field\">\r\n <span class=\"pos-item-entry__label\">{{ label() }}</span>\r\n <svg\r\n class=\"pos-item-entry__search\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\r\n </svg>\r\n <input\r\n #itemInput\r\n class=\"pos-item-entry__input\"\r\n type=\"text\"\r\n name=\"itemReference\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n [attr.autocorrect]=\"'off'\"\r\n [attr.autocapitalize]=\"'none'\"\r\n enterkeyhint=\"done\"\r\n [placeholder]=\"placeholder()\"\r\n [value]=\"reference()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\r\n [attr.aria-keyshortcuts]=\"focusHotkey() || null\"\r\n (input)=\"onInput($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"pos-item-entry__scanner\">\r\n <svg\r\n class=\"pos-item-entry__scan\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n aria-hidden=\"true\"\r\n >\r\n <line x1=\"4\" y1=\"6\" x2=\"4\" y2=\"18\" />\r\n <line x1=\"7\" y1=\"6\" x2=\"7\" y2=\"18\" />\r\n <line x1=\"11\" y1=\"6\" x2=\"11\" y2=\"18\" />\r\n <line x1=\"14\" y1=\"6\" x2=\"14\" y2=\"18\" />\r\n <line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n <line x1=\"21\" y1=\"6\" x2=\"21\" y2=\"18\" />\r\n </svg>\r\n {{ scannerStatus() }}\r\n </span>\r\n\r\n @if (focusHotkey()) {\r\n <kbd class=\"pos-item-entry__hotkey\">{{ focusHotkey() }}</kbd>\r\n }\r\n </div>\r\n </form>\r\n\r\n <div class=\"pos-item-entry__status\" aria-live=\"polite\">\r\n @if (errorMessage()) {\r\n <p class=\"pos-item-entry__error\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-item-entry__panel{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-item-entry__panel--bordered{padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-item-entry__form{min-width:0}.pos-item-entry__omnibox{display:flex;align-items:center;gap:var(--pos-space-sm);box-sizing:border-box;min-height:var(--pos-button-min-height);padding:0 var(--pos-space-md) 0 var(--pos-space-lg);border:1px solid transparent;border-radius:var(--pos-radius-pill);background:var(--pos-color-surface-muted);transition:border-color .12s ease,box-shadow .12s ease,background-color .12s ease}.pos-item-entry__omnibox:focus-within{border-color:var(--pos-color-primary);background:var(--pos-color-surface);box-shadow:0 0 0 3px color-mix(in srgb,var(--pos-color-primary) 35%,transparent)}.pos-item-entry__omnibox:has(.pos-item-entry__input[aria-invalid=true]){border-color:var(--pos-color-danger)}.pos-item-entry__omnibox--disabled{cursor:not-allowed;background:var(--pos-color-disabled)}.pos-item-entry__field{display:flex;flex:1 1 auto;align-items:center;gap:var(--pos-space-sm);min-width:0}.pos-item-entry__label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pos-item-entry__search,.pos-item-entry__scan{flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.pos-item-entry__search{width:15px;height:15px;color:var(--pos-color-text-muted)}.pos-item-entry__input{box-sizing:border-box;flex:1 1 auto;width:100%;min-width:0;min-height:calc(var(--pos-button-min-height) - 8px);margin:0;padding:0;border:0;background:transparent;color:var(--pos-color-text);font:inherit;outline:none}.pos-item-entry__input::placeholder{color:var(--pos-color-text-muted);opacity:1}.pos-item-entry__input:disabled{cursor:not-allowed;color:var(--pos-color-on-disabled)}.pos-item-entry__scanner{display:inline-flex;flex:0 0 auto;align-items:center;gap:var(--pos-space-xs);padding:2px var(--pos-space-sm);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-sm);background:var(--pos-color-surface);color:var(--pos-color-text-muted);font-size:.72em;line-height:1.2;white-space:nowrap}.pos-item-entry__omnibox--disabled .pos-item-entry__scanner{color:var(--pos-color-on-disabled)}.pos-item-entry__scan{width:11px;height:11px}.pos-item-entry__hotkey{flex:0 0 auto;margin:0;padding:0;border:0;background:transparent;color:var(--pos-color-text-muted);font-family:inherit;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);line-height:1}.pos-item-entry__status{min-height:0}.pos-item-entry__error{margin:0;padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:color-mix(in srgb,var(--pos-color-danger) 12%,transparent);color:var(--pos-color-danger);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}@media(max-width:479px){.pos-item-entry__hotkey{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}}@media(min-width:768px){.pos-item-entry__panel--bordered{padding:var(--pos-space-xl)}}@media(prefers-reduced-motion:reduce){.pos-item-entry__omnibox{transition:none}}\n"] }]
|
|
355
|
+
}], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], scannerStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "scannerStatus", required: false }] }], focusHotkey: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusHotkey", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], itemInput: [{ type: i0.ViewChild, args: ['itemInput', { isSignal: true }] }] } });
|
|
227
356
|
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
['7', '8', '9'],
|
|
232
|
-
['0', '.', '←'],
|
|
233
|
-
];
|
|
234
|
-
const MAX_WHOLE_DIGITS = 8;
|
|
235
|
-
function parseCashAmount(raw) {
|
|
236
|
-
if (!raw) {
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
const amount = Number(raw);
|
|
240
|
-
if (!Number.isFinite(amount) || amount <= 0) {
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
357
|
+
const COIN_AMOUNTS = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2];
|
|
358
|
+
const NOTE_AMOUNTS = [5, 10, 20, 50];
|
|
359
|
+
function roundMoney(amount) {
|
|
243
360
|
return Math.round(amount * 100) / 100;
|
|
244
361
|
}
|
|
245
|
-
function
|
|
246
|
-
|
|
247
|
-
return current.slice(0, -1);
|
|
248
|
-
}
|
|
249
|
-
if (key === '.') {
|
|
250
|
-
if (current.includes('.')) {
|
|
251
|
-
return current;
|
|
252
|
-
}
|
|
253
|
-
return current === '' ? '0.' : `${current}.`;
|
|
254
|
-
}
|
|
255
|
-
if (!/^\d$/.test(key)) {
|
|
256
|
-
return current;
|
|
257
|
-
}
|
|
258
|
-
if (current === '0') {
|
|
259
|
-
return key;
|
|
260
|
-
}
|
|
261
|
-
const [whole = '', fraction] = current.split('.');
|
|
262
|
-
if (fraction !== undefined) {
|
|
263
|
-
if (fraction.length >= 2) {
|
|
264
|
-
return current;
|
|
265
|
-
}
|
|
266
|
-
return current + key;
|
|
267
|
-
}
|
|
268
|
-
const significant = whole.replace(/^0+/, '');
|
|
269
|
-
if (significant.length >= MAX_WHOLE_DIGITS) {
|
|
270
|
-
return current;
|
|
271
|
-
}
|
|
272
|
-
return current + key;
|
|
362
|
+
function roundUp(amount, step) {
|
|
363
|
+
return roundMoney(Math.ceil(amount / step) * step);
|
|
273
364
|
}
|
|
274
365
|
class PosTender {
|
|
275
366
|
/** Display-only amount due from the host envelope — not calculated here. */
|
|
@@ -279,19 +370,40 @@ class PosTender {
|
|
|
279
370
|
currency = input('EUR', ...(ngDevMode ? [{ debugName: "currency" }] : /* istanbul ignore next */ []));
|
|
280
371
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
281
372
|
errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
282
|
-
title = input('Cash
|
|
283
|
-
amountDueLabel = input('
|
|
284
|
-
tenderedLabel = input('Amount
|
|
373
|
+
title = input('Cash Payment', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
374
|
+
amountDueLabel = input('Remaining', ...(ngDevMode ? [{ debugName: "amountDueLabel" }] : /* istanbul ignore next */ []));
|
|
375
|
+
tenderedLabel = input('Amount given', ...(ngDevMode ? [{ debugName: "tenderedLabel" }] : /* istanbul ignore next */ []));
|
|
285
376
|
changeDueLabel = input('Change due', ...(ngDevMode ? [{ debugName: "changeDueLabel" }] : /* istanbul ignore next */ []));
|
|
286
|
-
tenderLabel = input('
|
|
377
|
+
tenderLabel = input('Pay Now', ...(ngDevMode ? [{ debugName: "tenderLabel" }] : /* istanbul ignore next */ []));
|
|
378
|
+
cancelLabel = input('Cancel', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
|
|
379
|
+
hint = input('tap coins and notes, or use a quick amount.', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
287
380
|
processingLabel = input('Processing tender…', ...(ngDevMode ? [{ debugName: "processingLabel" }] : /* istanbul ignore next */ []));
|
|
288
381
|
action = output();
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
382
|
+
coins = COIN_AMOUNTS;
|
|
383
|
+
notes = NOTE_AMOUNTS;
|
|
384
|
+
given = signal(0, ...(ngDevMode ? [{ debugName: "given" }] : /* istanbul ignore next */ []));
|
|
385
|
+
parsedAmount = computed(() => {
|
|
386
|
+
const amount = this.given();
|
|
387
|
+
return amount > 0 ? amount : null;
|
|
388
|
+
}, ...(ngDevMode ? [{ debugName: "parsedAmount" }] : /* istanbul ignore next */ []));
|
|
292
389
|
canTender = computed(() => this.parsedAmount() !== null && !this.disabled(), ...(ngDevMode ? [{ debugName: "canTender" }] : /* istanbul ignore next */ []));
|
|
293
390
|
hasChangeDue = computed(() => this.changeDue() !== null, ...(ngDevMode ? [{ debugName: "hasChangeDue" }] : /* istanbul ignore next */ []));
|
|
294
|
-
|
|
391
|
+
displayGiven = computed(() => this.given().toFixed(2), ...(ngDevMode ? [{ debugName: "displayGiven" }] : /* istanbul ignore next */ []));
|
|
392
|
+
quickAmounts = computed(() => {
|
|
393
|
+
const remaining = this.amountDue();
|
|
394
|
+
if (!(remaining > 0)) {
|
|
395
|
+
return [];
|
|
396
|
+
}
|
|
397
|
+
const values = [
|
|
398
|
+
remaining,
|
|
399
|
+
roundUp(remaining, 5),
|
|
400
|
+
roundUp(remaining, 10),
|
|
401
|
+
roundUp(remaining, 20),
|
|
402
|
+
].map((value) => roundMoney(value));
|
|
403
|
+
return values
|
|
404
|
+
.filter((value, index) => value >= remaining - 0.001 && values.indexOf(value) === index)
|
|
405
|
+
.slice(0, 4);
|
|
406
|
+
}, ...(ngDevMode ? [{ debugName: "quickAmounts" }] : /* istanbul ignore next */ []));
|
|
295
407
|
statusText = computed(() => {
|
|
296
408
|
if (this.disabled() && !this.hasChangeDue()) {
|
|
297
409
|
return this.processingLabel();
|
|
@@ -306,11 +418,51 @@ class PosTender {
|
|
|
306
418
|
maximumFractionDigits: 2,
|
|
307
419
|
}).format(amount);
|
|
308
420
|
}
|
|
309
|
-
|
|
421
|
+
denominationLabel(amount) {
|
|
422
|
+
const currency = (this.currency() || 'EUR').toUpperCase();
|
|
423
|
+
if (amount >= 1) {
|
|
424
|
+
return new Intl.NumberFormat(undefined, {
|
|
425
|
+
style: 'currency',
|
|
426
|
+
currency,
|
|
427
|
+
minimumFractionDigits: 0,
|
|
428
|
+
maximumFractionDigits: 0,
|
|
429
|
+
}).format(amount);
|
|
430
|
+
}
|
|
431
|
+
const minor = Math.round(amount * 100);
|
|
432
|
+
if (currency === 'GBP') {
|
|
433
|
+
return `${minor}p`;
|
|
434
|
+
}
|
|
435
|
+
if (currency === 'EUR') {
|
|
436
|
+
return `${minor}c`;
|
|
437
|
+
}
|
|
438
|
+
return this.formatMoney(amount);
|
|
439
|
+
}
|
|
440
|
+
quickLabel(amount) {
|
|
441
|
+
const formatted = this.formatMoney(amount);
|
|
442
|
+
return roundMoney(amount) === roundMoney(this.amountDue())
|
|
443
|
+
? `Exact ${formatted}`
|
|
444
|
+
: formatted;
|
|
445
|
+
}
|
|
446
|
+
isExact(amount) {
|
|
447
|
+
return roundMoney(amount) === roundMoney(this.amountDue());
|
|
448
|
+
}
|
|
449
|
+
addAmount(amount) {
|
|
450
|
+
if (this.disabled()) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
this.given.update((current) => roundMoney(current + amount));
|
|
454
|
+
}
|
|
455
|
+
setAmount(amount) {
|
|
310
456
|
if (this.disabled()) {
|
|
311
457
|
return;
|
|
312
458
|
}
|
|
313
|
-
this.
|
|
459
|
+
this.given.set(roundMoney(amount));
|
|
460
|
+
}
|
|
461
|
+
resetAmount() {
|
|
462
|
+
if (this.disabled()) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
this.given.set(0);
|
|
314
466
|
}
|
|
315
467
|
onTender() {
|
|
316
468
|
if (!this.canTender()) {
|
|
@@ -322,15 +474,21 @@ class PosTender {
|
|
|
322
474
|
}
|
|
323
475
|
this.action.emit({ type: 'tender.cash', amount });
|
|
324
476
|
}
|
|
477
|
+
onCancel() {
|
|
478
|
+
if (this.disabled()) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
this.action.emit({ type: 'tender.cancel' });
|
|
482
|
+
}
|
|
325
483
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTender, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
326
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosTender, isStandalone: true, selector: "pos-tender", inputs: { amountDue: { classPropertyName: "amountDue", publicName: "amountDue", isSignal: true, isRequired: false, transformFunction: null }, changeDue: { classPropertyName: "changeDue", publicName: "changeDue", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, amountDueLabel: { classPropertyName: "amountDueLabel", publicName: "amountDueLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderedLabel: { classPropertyName: "tenderedLabel", publicName: "tenderedLabel", isSignal: true, isRequired: false, transformFunction: null }, changeDueLabel: { classPropertyName: "changeDueLabel", publicName: "changeDueLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderLabel: { classPropertyName: "tenderLabel", publicName: "tenderLabel", isSignal: true, isRequired: false, transformFunction: null }, processingLabel: { classPropertyName: "processingLabel", publicName: "processingLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-tender" }, ngImport: i0, template: "<section\r\n class=\"pos-tender__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-tender__header\">\r\n <p class=\"pos-tender__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-tender__title\">{{ title() }}</h2>\r\n </header>\r\n\r\n <div class=\"pos-tender__status\" aria-live=\"polite\">\r\n @if (statusText()) {\r\n <p>{{ statusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-tender__error\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__summary\">\r\n <dl class=\"pos-tender__due\">\r\n <div class=\"pos-tender__row\">\r\n <dt>{{ amountDueLabel() }}</dt>\r\n <dd>{{ formatMoney(amountDue()) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasChangeDue()) {\r\n <div class=\"pos-tender__change\" role=\"status\" aria-live=\"polite\">\r\n <p class=\"pos-tender__change-label\">{{ changeDueLabel() }}</p>\r\n <p class=\"pos-tender__change-value\">\r\n {{ formatMoney(changeDue() ?? 0) }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-tender__display\"\r\n role=\"group\"\r\n [attr.aria-label]=\"tenderedLabel()\"\r\n >\r\n <p class=\"pos-tender__display-label\">{{ tenderedLabel() }}</p>\r\n <p class=\"pos-tender__display-value\" aria-live=\"polite\">\r\n <span class=\"pos-tender__currency\">{{ currency() }}</span>\r\n <span class=\"pos-tender__digits\">{{ displayTendered() }}</span>\r\n </p>\r\n </div>\r\n\r\n <div class=\"pos-tender__keypad\" role=\"group\" aria-label=\"Cash amount keypad\">\r\n @for (row of keypadRows; track $index) {\r\n <div class=\"pos-tender__keypad-row\">\r\n @for (key of row; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__key\"\r\n [class.pos-tender__key--action]=\"key === '\u2190' || key === '.'\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"key === '\u2190' ? 'Backspace' : key === '.' ? 'Decimal point' : key\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__primary\"\r\n [class.pos-tender__primary--disabled]=\"!canTender()\"\r\n [disabled]=\"!canTender()\"\r\n (click)=\"onTender()\"\r\n >\r\n {{ tenderLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;max-width:42rem;min-width:0;container-type:inline-size;container-name:pos-tender;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-tender__panel{min-width:0;display:grid;grid-template-areas:\"header\" \"status\" \"summary\" \"display\" \"keypad\" \"actions\";gap:var(--pos-space-md);padding:var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-tender__header{grid-area:header;display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-tender__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-tender__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em;line-height:1.15}.pos-tender__status{grid-area:status;min-height:1.5rem;display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-tender__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__error{padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:#d6454514;color:var(--pos-color-danger)}.pos-tender__summary{grid-area:summary;display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-tender__due{margin:0}.pos-tender__row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--pos-space-md);margin:0;padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-tender__row dt,.pos-tender__row dd{margin:0}.pos-tender__row dt{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__row dd{font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-tender__display{grid-area:display;min-width:0;padding:var(--pos-space-lg) var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-display);box-shadow:inset 0 1px #ffffff0f}.pos-tender__display-label{margin:0 0 var(--pos-space-sm);color:#e8edf2b3;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:.08em;text-transform:uppercase}.pos-tender__display-value{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-on-display);font-family:var(--pos-font-family-display)}.pos-tender__currency{font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.12em}.pos-tender__digits{min-width:0;overflow-wrap:anywhere;font-size:clamp(1.5rem,4vw,2rem);font-weight:var(--pos-font-weight-semibold);letter-spacing:.04em;font-variant-numeric:tabular-nums}.pos-tender__keypad{grid-area:keypad;display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-tender__keypad-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-md)}.pos-tender__key{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-key-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);font-family:inherit;font-size:1.15rem;font-weight:var(--pos-font-weight-bold);cursor:pointer;transition:background .12s ease,color .12s ease,border-color .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-tender__key--action{color:var(--pos-color-text-muted);background:var(--pos-color-surface-muted)}.pos-tender__key:not(:disabled):active{background:var(--pos-color-key-active);border-color:var(--pos-color-key-active);color:var(--pos-color-on-key-active);transform:translateY(1px)}.pos-tender__key:disabled,.pos-tender__primary:disabled{cursor:not-allowed}.pos-tender__key:disabled{opacity:.55}.pos-tender__key:focus-visible,.pos-tender__primary:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}.pos-tender__change{display:flex;flex-direction:column;gap:var(--pos-space-xs);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-tender__change-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__change-value{margin:0;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-tender__actions{grid-area:actions;display:flex;margin-top:0}.pos-tender__primary{flex:1 1 auto;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-size:1.05rem;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:filter .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-tender__primary:not(:disabled):hover{filter:brightness(.97)}.pos-tender__primary:not(:disabled):active{transform:translateY(1px)}.pos-tender__primary--disabled,.pos-tender__primary:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);filter:none;transform:none}@media(min-width:768px){.pos-tender__key{min-height:var(--pos-keypad-size-md)}}@container pos-tender (min-width: 36rem){.pos-tender__panel{grid-template-columns:minmax(0,1fr) minmax(16rem,1.1fr);grid-template-areas:\"header header\" \"status status\" \"summary keypad\" \"display keypad\" \"actions keypad\";gap:var(--pos-space-lg);padding:var(--pos-space-2xl);align-items:start}.pos-tender__keypad{align-self:start}}@media(min-width:1100px){.pos-tender__key{min-height:var(--pos-keypad-size-lg);font-size:1.25rem}}@media(prefers-reduced-motion:reduce){.pos-tender__key,.pos-tender__primary{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
484
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosTender, isStandalone: true, selector: "pos-tender", inputs: { amountDue: { classPropertyName: "amountDue", publicName: "amountDue", isSignal: true, isRequired: false, transformFunction: null }, changeDue: { classPropertyName: "changeDue", publicName: "changeDue", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, amountDueLabel: { classPropertyName: "amountDueLabel", publicName: "amountDueLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderedLabel: { classPropertyName: "tenderedLabel", publicName: "tenderedLabel", isSignal: true, isRequired: false, transformFunction: null }, changeDueLabel: { classPropertyName: "changeDueLabel", publicName: "changeDueLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderLabel: { classPropertyName: "tenderLabel", publicName: "tenderLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, processingLabel: { classPropertyName: "processingLabel", publicName: "processingLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-tender" }, ngImport: i0, template: "<section class=\"pos-tender__panel\" [attr.aria-busy]=\"disabled() ? true : null\">\r\n <header class=\"pos-tender__header\">\r\n <h2 class=\"pos-tender__title\">{{ title() }}</h2>\r\n <p class=\"pos-tender__hint\">\r\n {{ amountDueLabel() }}:\r\n <span class=\"pos-tender__due\">{{ formatMoney(amountDue()) }}</span>\r\n - {{ hint() }}\r\n </p>\r\n @if (hasChangeDue()) {\r\n <div class=\"pos-tender__change\" role=\"status\" aria-live=\"polite\">\r\n <p class=\"pos-tender__change-label\">{{ changeDueLabel() }}</p>\r\n <p class=\"pos-tender__change-value\">{{ formatMoney(changeDue() ?? 0) }}</p>\r\n </div>\r\n }\r\n </header>\r\n\r\n @if (statusText() || errorMessage()) {\r\n <div class=\"pos-tender__status\" aria-live=\"polite\">\r\n @if (statusText()) {\r\n <p>{{ statusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-tender__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-tender__money\">\r\n <div class=\"pos-tender__coins\" role=\"group\" aria-label=\"Coins\">\r\n @for (amount of coins; track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__coin\"\r\n [attr.data-amount]=\"amount\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"'Add ' + denominationLabel(amount)\"\r\n (click)=\"addAmount(amount)\"\r\n >\r\n {{ denominationLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__notes\" role=\"group\" aria-label=\"Notes\">\r\n @for (amount of notes; track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__note\"\r\n [attr.data-amount]=\"amount\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"'Add ' + denominationLabel(amount)\"\r\n (click)=\"addAmount(amount)\"\r\n >\r\n {{ denominationLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (quickAmounts().length) {\r\n <div class=\"pos-tender__quick\" role=\"group\" aria-label=\"Quick amounts\">\r\n @for (amount of quickAmounts(); track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__pill\"\r\n [class.pos-tender__pill--exact]=\"isExact(amount)\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"setAmount(amount)\"\r\n >\r\n {{ quickLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-tender__given\">\r\n <label class=\"pos-tender__given-label\" for=\"pos-tender-given\">{{ tenderedLabel() }}</label>\r\n <input\r\n id=\"pos-tender-given\"\r\n class=\"pos-tender__digits\"\r\n [value]=\"displayGiven()\"\r\n readonly\r\n tabindex=\"-1\"\r\n aria-label=\"Amount given\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__reset\"\r\n aria-label=\"Reset amount\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"resetAmount()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" 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 d=\"m14 10 4 4m0-4-4 4\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-tender__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__cancel\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onCancel()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M6 6l12 12M18 6 6 18\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n {{ cancelLabel() }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__primary\"\r\n [disabled]=\"!canTender()\"\r\n (click)=\"onTender()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" 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 {{ tenderLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;box-sizing:border-box;width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:var(--pos-color-surface)}*{box-sizing:border-box}.pos-tender__panel{display:flex;flex-direction:column;gap:var(--pos-space-lg);width:100%;padding:var(--pos-space-lg);background:var(--pos-color-surface)}.pos-tender__header{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-tender__title{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-tender__hint,.pos-tender__given-label,.pos-tender__change-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-tender__due{color:var(--pos-color-text);font-weight:var(--pos-font-weight-semibold)}.pos-tender__change{display:flex;align-items:baseline;gap:var(--pos-space-sm)}.pos-tender__change-value{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold)}.pos-tender__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__error{color:var(--pos-color-danger)}.pos-tender__money{display:flex;flex-direction:column;gap:var(--pos-space-lg)}.pos-tender__coins{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--pos-keypad-size),1fr));gap:var(--pos-space-md);width:100%;justify-content:start}.pos-tender__notes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-tender__coin,.pos-tender__note,.pos-tender__pill,.pos-tender__reset,.pos-tender__cancel,.pos-tender__primary{font-family:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-tender__coin,.pos-tender__note,.pos-tender__pill,.pos-tender__reset{border:1px solid var(--pos-color-border);background:var(--pos-color-surface);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key)}.pos-tender__coin{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-keypad-size-lg);height:var(--pos-keypad-size-lg);border-radius:var(--pos-radius-pill)}.pos-tender__note{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-button-min-height);border-radius:var(--pos-radius-md)}.pos-tender__coin:hover:not(:disabled),.pos-tender__note:hover:not(:disabled),.pos-tender__pill:hover:not(:disabled){border-color:var(--pos-color-success)}.pos-tender__quick{display:flex;flex-wrap:wrap;gap:var(--pos-space-sm)}.pos-tender__pill{min-height:var(--pos-button-min-height);padding:0 var(--pos-space-lg);border-radius:var(--pos-radius-pill)}.pos-tender__pill--exact{border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 28%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-tender__given{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--pos-space-md)}.pos-tender__digits{width:min(15rem,100%);min-height:var(--pos-button-min-height);margin:0;padding:0 var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font:inherit;font-size:var(--pos-font-size-lg);text-align:right}.pos-tender__reset{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);border-radius:var(--pos-radius-sm);color:var(--pos-color-danger);box-shadow:none}.pos-tender__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--pos-space-md)}.pos-tender__cancel,.pos-tender__primary{display:inline-flex;flex:1 1 10rem;align-items:center;justify-content:center;gap:var(--pos-space-sm);max-width:14rem;min-height:calc(var(--pos-button-min-height) + var(--pos-space-sm));border:0;border-radius:var(--pos-radius-md)}.pos-tender__cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-tender__primary{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-tender__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-tender__coin:disabled,.pos-tender__note:disabled,.pos-tender__pill:disabled,.pos-tender__reset:disabled,.pos-tender__cancel:disabled,.pos-tender__primary:disabled{border-color:var(--pos-color-disabled);background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);box-shadow:none;cursor:not-allowed;filter:none}.pos-tender__coin:focus-visible,.pos-tender__note:focus-visible,.pos-tender__pill:focus-visible,.pos-tender__reset:focus-visible,.pos-tender__cancel:focus-visible,.pos-tender__primary:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-tender__panel{padding:var(--pos-space-xl)}.pos-tender__money{flex-direction:row;align-items:flex-start}.pos-tender__coins{flex:1 1 auto;width:auto;min-width:0;grid-template-columns:repeat(5,var(--pos-keypad-size-lg))}.pos-tender__notes{display:flex;flex:0 0 auto;flex-direction:column;width:calc(var(--pos-keypad-size-lg) + var(--pos-space-3xl))}.pos-tender__cancel,.pos-tender__primary{flex:0 0 auto;min-width:10rem}}@media(prefers-reduced-motion:reduce){.pos-tender__primary{filter:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
327
485
|
}
|
|
328
486
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTender, decorators: [{
|
|
329
487
|
type: Component,
|
|
330
488
|
args: [{ selector: 'pos-tender', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
331
489
|
class: 'pos-tender',
|
|
332
|
-
}, template: "<section\r\n class=\"pos-tender__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <header class=\"pos-tender__header\">\r\n <p class=\"pos-tender__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-tender__title\">{{ title() }}</h2>\r\n </header>\r\n\r\n <div class=\"pos-tender__status\" aria-live=\"polite\">\r\n @if (statusText()) {\r\n <p>{{ statusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-tender__error\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__summary\">\r\n <dl class=\"pos-tender__due\">\r\n <div class=\"pos-tender__row\">\r\n <dt>{{ amountDueLabel() }}</dt>\r\n <dd>{{ formatMoney(amountDue()) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasChangeDue()) {\r\n <div class=\"pos-tender__change\" role=\"status\" aria-live=\"polite\">\r\n <p class=\"pos-tender__change-label\">{{ changeDueLabel() }}</p>\r\n <p class=\"pos-tender__change-value\">\r\n {{ formatMoney(changeDue() ?? 0) }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"pos-tender__display\"\r\n role=\"group\"\r\n [attr.aria-label]=\"tenderedLabel()\"\r\n >\r\n <p class=\"pos-tender__display-label\">{{ tenderedLabel() }}</p>\r\n <p class=\"pos-tender__display-value\" aria-live=\"polite\">\r\n <span class=\"pos-tender__currency\">{{ currency() }}</span>\r\n <span class=\"pos-tender__digits\">{{ displayTendered() }}</span>\r\n </p>\r\n </div>\r\n\r\n <div class=\"pos-tender__keypad\" role=\"group\" aria-label=\"Cash amount keypad\">\r\n @for (row of keypadRows; track $index) {\r\n <div class=\"pos-tender__keypad-row\">\r\n @for (key of row; track key) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__key\"\r\n [class.pos-tender__key--action]=\"key === '\u2190' || key === '.'\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"key === '\u2190' ? 'Backspace' : key === '.' ? 'Decimal point' : key\"\r\n (click)=\"onKeypad(key)\"\r\n >\r\n {{ key }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__primary\"\r\n [class.pos-tender__primary--disabled]=\"!canTender()\"\r\n [disabled]=\"!canTender()\"\r\n (click)=\"onTender()\"\r\n >\r\n {{ tenderLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;width:100%;max-width:42rem;min-width:0;container-type:inline-size;container-name:pos-tender;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-tender__panel{min-width:0;display:grid;grid-template-areas:\"header\" \"status\" \"summary\" \"display\" \"keypad\" \"actions\";gap:var(--pos-space-md);padding:var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-tender__header{grid-area:header;display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-tender__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-tender__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em;line-height:1.15}.pos-tender__status{grid-area:status;min-height:1.5rem;display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-tender__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__error{padding:var(--pos-space-sm) var(--pos-space-md);border-left:3px solid var(--pos-color-danger);background:#d6454514;color:var(--pos-color-danger)}.pos-tender__summary{grid-area:summary;display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-tender__due{margin:0}.pos-tender__row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--pos-space-md);margin:0;padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-tender__row dt,.pos-tender__row dd{margin:0}.pos-tender__row dt{color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__row dd{font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-tender__display{grid-area:display;min-width:0;padding:var(--pos-space-lg) var(--pos-space-xl);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:var(--pos-color-display);box-shadow:inset 0 1px #ffffff0f}.pos-tender__display-label{margin:0 0 var(--pos-space-sm);color:#e8edf2b3;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:.08em;text-transform:uppercase}.pos-tender__display-value{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-on-display);font-family:var(--pos-font-family-display)}.pos-tender__currency{font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.12em}.pos-tender__digits{min-width:0;overflow-wrap:anywhere;font-size:clamp(1.5rem,4vw,2rem);font-weight:var(--pos-font-weight-semibold);letter-spacing:.04em;font-variant-numeric:tabular-nums}.pos-tender__keypad{grid-area:keypad;display:flex;flex-direction:column;gap:var(--pos-space-md)}.pos-tender__keypad-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--pos-space-md)}.pos-tender__key{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-keypad-size);border:1px solid var(--pos-color-key-border);border-radius:var(--pos-radius-md);background:var(--pos-color-key);color:var(--pos-color-text);font-family:inherit;font-size:1.15rem;font-weight:var(--pos-font-weight-bold);cursor:pointer;transition:background .12s ease,color .12s ease,border-color .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-tender__key--action{color:var(--pos-color-text-muted);background:var(--pos-color-surface-muted)}.pos-tender__key:not(:disabled):active{background:var(--pos-color-key-active);border-color:var(--pos-color-key-active);color:var(--pos-color-on-key-active);transform:translateY(1px)}.pos-tender__key:disabled,.pos-tender__primary:disabled{cursor:not-allowed}.pos-tender__key:disabled{opacity:.55}.pos-tender__key:focus-visible,.pos-tender__primary:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}.pos-tender__change{display:flex;flex-direction:column;gap:var(--pos-space-xs);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-tender__change-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__change-value{margin:0;color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-tender__actions{grid-area:actions;display:flex;margin-top:0}.pos-tender__primary{flex:1 1 auto;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-size:1.05rem;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;transition:filter .12s ease,transform .12s ease;-webkit-tap-highlight-color:transparent}.pos-tender__primary:not(:disabled):hover{filter:brightness(.97)}.pos-tender__primary:not(:disabled):active{transform:translateY(1px)}.pos-tender__primary--disabled,.pos-tender__primary:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);filter:none;transform:none}@media(min-width:768px){.pos-tender__key{min-height:var(--pos-keypad-size-md)}}@container pos-tender (min-width: 36rem){.pos-tender__panel{grid-template-columns:minmax(0,1fr) minmax(16rem,1.1fr);grid-template-areas:\"header header\" \"status status\" \"summary keypad\" \"display keypad\" \"actions keypad\";gap:var(--pos-space-lg);padding:var(--pos-space-2xl);align-items:start}.pos-tender__keypad{align-self:start}}@media(min-width:1100px){.pos-tender__key{min-height:var(--pos-keypad-size-lg);font-size:1.25rem}}@media(prefers-reduced-motion:reduce){.pos-tender__key,.pos-tender__primary{transition:none}}\n"] }]
|
|
333
|
-
}], propDecorators: { amountDue: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountDue", required: false }] }], changeDue: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeDue", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], amountDueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountDueLabel", required: false }] }], tenderedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderedLabel", required: false }] }], changeDueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeDueLabel", required: false }] }], tenderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderLabel", required: false }] }], processingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "processingLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
490
|
+
}, template: "<section class=\"pos-tender__panel\" [attr.aria-busy]=\"disabled() ? true : null\">\r\n <header class=\"pos-tender__header\">\r\n <h2 class=\"pos-tender__title\">{{ title() }}</h2>\r\n <p class=\"pos-tender__hint\">\r\n {{ amountDueLabel() }}:\r\n <span class=\"pos-tender__due\">{{ formatMoney(amountDue()) }}</span>\r\n - {{ hint() }}\r\n </p>\r\n @if (hasChangeDue()) {\r\n <div class=\"pos-tender__change\" role=\"status\" aria-live=\"polite\">\r\n <p class=\"pos-tender__change-label\">{{ changeDueLabel() }}</p>\r\n <p class=\"pos-tender__change-value\">{{ formatMoney(changeDue() ?? 0) }}</p>\r\n </div>\r\n }\r\n </header>\r\n\r\n @if (statusText() || errorMessage()) {\r\n <div class=\"pos-tender__status\" aria-live=\"polite\">\r\n @if (statusText()) {\r\n <p>{{ statusText() }}</p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"pos-tender__error\" role=\"alert\">{{ errorMessage() }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-tender__money\">\r\n <div class=\"pos-tender__coins\" role=\"group\" aria-label=\"Coins\">\r\n @for (amount of coins; track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__coin\"\r\n [attr.data-amount]=\"amount\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"'Add ' + denominationLabel(amount)\"\r\n (click)=\"addAmount(amount)\"\r\n >\r\n {{ denominationLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-tender__notes\" role=\"group\" aria-label=\"Notes\">\r\n @for (amount of notes; track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__note\"\r\n [attr.data-amount]=\"amount\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"'Add ' + denominationLabel(amount)\"\r\n (click)=\"addAmount(amount)\"\r\n >\r\n {{ denominationLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (quickAmounts().length) {\r\n <div class=\"pos-tender__quick\" role=\"group\" aria-label=\"Quick amounts\">\r\n @for (amount of quickAmounts(); track amount) {\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__pill\"\r\n [class.pos-tender__pill--exact]=\"isExact(amount)\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"setAmount(amount)\"\r\n >\r\n {{ quickLabel(amount) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"pos-tender__given\">\r\n <label class=\"pos-tender__given-label\" for=\"pos-tender-given\">{{ tenderedLabel() }}</label>\r\n <input\r\n id=\"pos-tender-given\"\r\n class=\"pos-tender__digits\"\r\n [value]=\"displayGiven()\"\r\n readonly\r\n tabindex=\"-1\"\r\n aria-label=\"Amount given\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__reset\"\r\n aria-label=\"Reset amount\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"resetAmount()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" 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 d=\"m14 10 4 4m0-4-4 4\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"pos-tender__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__cancel\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onCancel()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M6 6l12 12M18 6 6 18\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n {{ cancelLabel() }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tender__primary\"\r\n [disabled]=\"!canTender()\"\r\n (click)=\"onTender()\"\r\n >\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" 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 {{ tenderLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:block;box-sizing:border-box;width:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md);background:var(--pos-color-surface)}*{box-sizing:border-box}.pos-tender__panel{display:flex;flex-direction:column;gap:var(--pos-space-lg);width:100%;padding:var(--pos-space-lg);background:var(--pos-color-surface)}.pos-tender__header{display:flex;flex-direction:column;gap:var(--pos-space-xs)}.pos-tender__title{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-tender__hint,.pos-tender__given-label,.pos-tender__change-label{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-tender__due{color:var(--pos-color-text);font-weight:var(--pos-font-weight-semibold)}.pos-tender__change{display:flex;align-items:baseline;gap:var(--pos-space-sm)}.pos-tender__change-value{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold)}.pos-tender__status p{margin:0;font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-tender__error{color:var(--pos-color-danger)}.pos-tender__money{display:flex;flex-direction:column;gap:var(--pos-space-lg)}.pos-tender__coins{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--pos-keypad-size),1fr));gap:var(--pos-space-md);width:100%;justify-content:start}.pos-tender__notes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pos-space-md)}.pos-tender__coin,.pos-tender__note,.pos-tender__pill,.pos-tender__reset,.pos-tender__cancel,.pos-tender__primary{font-family:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-tender__coin,.pos-tender__note,.pos-tender__pill,.pos-tender__reset{border:1px solid var(--pos-color-border);background:var(--pos-color-surface);color:var(--pos-color-text);box-shadow:var(--pos-shadow-key)}.pos-tender__coin{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-keypad-size-lg);height:var(--pos-keypad-size-lg);border-radius:var(--pos-radius-pill)}.pos-tender__note{display:inline-flex;align-items:center;justify-content:center;min-height:var(--pos-button-min-height);border-radius:var(--pos-radius-md)}.pos-tender__coin:hover:not(:disabled),.pos-tender__note:hover:not(:disabled),.pos-tender__pill:hover:not(:disabled){border-color:var(--pos-color-success)}.pos-tender__quick{display:flex;flex-wrap:wrap;gap:var(--pos-space-sm)}.pos-tender__pill{min-height:var(--pos-button-min-height);padding:0 var(--pos-space-lg);border-radius:var(--pos-radius-pill)}.pos-tender__pill--exact{border-color:var(--pos-color-primary);background:color-mix(in srgb,var(--pos-color-primary) 28%,var(--pos-color-surface));color:var(--pos-color-text)}.pos-tender__given{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--pos-space-md)}.pos-tender__digits{width:min(15rem,100%);min-height:var(--pos-button-min-height);margin:0;padding:0 var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font:inherit;font-size:var(--pos-font-size-lg);text-align:right}.pos-tender__reset{display:inline-flex;align-items:center;justify-content:center;width:var(--pos-button-min-height);height:var(--pos-button-min-height);border-radius:var(--pos-radius-sm);color:var(--pos-color-danger);box-shadow:none}.pos-tender__actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--pos-space-md)}.pos-tender__cancel,.pos-tender__primary{display:inline-flex;flex:1 1 10rem;align-items:center;justify-content:center;gap:var(--pos-space-sm);max-width:14rem;min-height:calc(var(--pos-button-min-height) + var(--pos-space-sm));border:0;border-radius:var(--pos-radius-md)}.pos-tender__cancel{background:var(--pos-color-danger);color:var(--pos-color-on-danger)}.pos-tender__primary{background:var(--pos-color-success);color:var(--pos-color-on-success)}.pos-tender__primary:hover:not(:disabled){filter:brightness(1.06)}.pos-tender__coin:disabled,.pos-tender__note:disabled,.pos-tender__pill:disabled,.pos-tender__reset:disabled,.pos-tender__cancel:disabled,.pos-tender__primary:disabled{border-color:var(--pos-color-disabled);background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);box-shadow:none;cursor:not-allowed;filter:none}.pos-tender__coin:focus-visible,.pos-tender__note:focus-visible,.pos-tender__pill:focus-visible,.pos-tender__reset:focus-visible,.pos-tender__cancel:focus-visible,.pos-tender__primary:focus-visible{outline:3px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-tender__panel{padding:var(--pos-space-xl)}.pos-tender__money{flex-direction:row;align-items:flex-start}.pos-tender__coins{flex:1 1 auto;width:auto;min-width:0;grid-template-columns:repeat(5,var(--pos-keypad-size-lg))}.pos-tender__notes{display:flex;flex:0 0 auto;flex-direction:column;width:calc(var(--pos-keypad-size-lg) + var(--pos-space-3xl))}.pos-tender__cancel,.pos-tender__primary{flex:0 0 auto;min-width:10rem}}@media(prefers-reduced-motion:reduce){.pos-tender__primary{filter:none}}\n"] }]
|
|
491
|
+
}], propDecorators: { amountDue: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountDue", required: false }] }], changeDue: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeDue", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], amountDueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountDueLabel", required: false }] }], tenderedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderedLabel", required: false }] }], changeDueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeDueLabel", required: false }] }], tenderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], processingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "processingLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
334
492
|
|
|
335
493
|
const EMPTY_TOTALS = {
|
|
336
494
|
gross: 0,
|
|
@@ -350,6 +508,8 @@ class PosReceipt {
|
|
|
350
508
|
payments = input([], ...(ngDevMode ? [{ debugName: "payments" }] : /* istanbul ignore next */ []));
|
|
351
509
|
document = input(EMPTY_DOCUMENT, ...(ngDevMode ? [{ debugName: "document" }] : /* istanbul ignore next */ []));
|
|
352
510
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
511
|
+
/** Draws the panel frame. Off by default so the host can sit the receipt flush. */
|
|
512
|
+
bordered = input(false, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
|
|
353
513
|
title = input('Receipt', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
354
514
|
emptyMessage = input('No receipt lines', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
355
515
|
preparingLabel = input('Preparing receipt…', ...(ngDevMode ? [{ debugName: "preparingLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -382,14 +542,14 @@ class PosReceipt {
|
|
|
382
542
|
this.action.emit({ type: 'receipt.newSale' });
|
|
383
543
|
}
|
|
384
544
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosReceipt, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
385
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosReceipt, isStandalone: true, selector: "pos-receipt", inputs: { lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, totals: { classPropertyName: "totals", publicName: "totals", isSignal: true, isRequired: false, transformFunction: null }, payments: { classPropertyName: "payments", publicName: "payments", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", 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 }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, preparingLabel: { classPropertyName: "preparingLabel", publicName: "preparingLabel", isSignal: true, isRequired: false, transformFunction: null }, readyLabel: { classPropertyName: "readyLabel", publicName: "readyLabel", isSignal: true, isRequired: false, transformFunction: null }, newSaleLabel: { classPropertyName: "newSaleLabel", publicName: "newSaleLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderLabel: { classPropertyName: "tenderLabel", publicName: "tenderLabel", isSignal: true, isRequired: false, transformFunction: null }, amountLabel: { classPropertyName: "amountLabel", publicName: "amountLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderedLabel: { classPropertyName: "tenderedLabel", publicName: "tenderedLabel", isSignal: true, isRequired: false, transformFunction: null }, changeLabel: { classPropertyName: "changeLabel", publicName: "changeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-receipt" }, ngImport: i0, template: "<section\r\n class=\"pos-receipt__panel\"\r\n [attr.aria-busy]=\"disabled() || !document().receiptReady ? true : null\"\r\n>\r\n <header class=\"pos-receipt__header\">\r\n <div class=\"pos-receipt__heading\">\r\n <p class=\"pos-receipt__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-receipt__title\">{{ title() }}</h2>\r\n </div>\r\n @if (hasDocumentNumber()) {\r\n <p class=\"pos-receipt__number\" aria-label=\"Document number\">\r\n {{ document().number }}\r\n </p>\r\n }\r\n </header>\r\n\r\n <p class=\"pos-receipt__status\" aria-live=\"polite\">{{ statusText() }}</p>\r\n\r\n <ul class=\"pos-receipt__lines\" aria-label=\"Receipt lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-receipt__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-receipt__line\"\r\n [class.pos-receipt__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-receipt__line-info\">\r\n <h3 class=\"pos-receipt__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-receipt__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-receipt__line-voided\">Voided</p>\r\n }\r\n </div>\r\n <p class=\"pos-receipt__qty\">{{ line.qty }}</p>\r\n <div class=\"pos-receipt__line-prices\">\r\n <p class=\"pos-receipt__unit-price\">\r\n {{ formatMoney(line.unitPrice) }}\r\n </p>\r\n <p class=\"pos-receipt__line-total\">\r\n {{ formatMoney(line.lineTotal) }}\r\n </p>\r\n </div>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <div class=\"pos-receipt__summary\">\r\n <dl class=\"pos-receipt__totals\" aria-live=\"polite\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasPayments()) {\r\n <section class=\"pos-receipt__tender\">\r\n <h3 class=\"pos-receipt__tender-title\">{{ tenderLabel() }}</h3>\r\n <ul class=\"pos-receipt__payments\">\r\n @for (payment of payments(); track $index) {\r\n <li class=\"pos-receipt__payment\">\r\n <header class=\"pos-receipt__payment-header\">\r\n <p class=\"pos-receipt__payment-tender\">{{ payment.tender }}</p>\r\n <p class=\"pos-receipt__payment-state\">{{ payment.state }}</p>\r\n </header>\r\n <dl class=\"pos-receipt__payment-amounts\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ amountLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.amount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ tenderedLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.tendered) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--change\">\r\n <dt>{{ changeLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.change) }}</dd>\r\n </div>\r\n </dl>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-receipt__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-receipt__new-sale\"\r\n [disabled]=\"!canStartNewSale()\"\r\n (click)=\"onNewSale()\"\r\n >\r\n {{ newSaleLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-receipt__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-receipt__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__heading{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-receipt__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-receipt__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em}.pos-receipt__number{margin:0;color:var(--pos-color-text-muted);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere;text-align:right}.pos-receipt__status{margin:var(--pos-space-md) 0 0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:var(--pos-space-md) 0 0;padding:0;overflow-y:auto;list-style:none}.pos-receipt__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-receipt__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info qty\" \"prices prices\";align-items:center;gap:var(--pos-space-xs) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-receipt__line-info{grid-area:info;min-width:0}.pos-receipt__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-receipt__line-sku,.pos-receipt__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-receipt__line-sku{color:var(--pos-color-text-muted)}.pos-receipt__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__qty{grid-area:qty;margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums;text-align:right}.pos-receipt__line-prices{grid-area:prices;display:flex;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-receipt__line--voided .pos-receipt__line-name,.pos-receipt__line--voided .pos-receipt__line-sku,.pos-receipt__line--voided .pos-receipt__line-prices,.pos-receipt__line--voided .pos-receipt__qty{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-receipt__summary{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-receipt__totals,.pos-receipt__payment-amounts{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-receipt__row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__row dt,.pos-receipt__row dd{margin:0}.pos-receipt__row dd{font-variant-numeric:tabular-nums}.pos-receipt__row--due,.pos-receipt__row--change{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-receipt__tender{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-receipt__tender-title{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:.08em;text-transform:uppercase}.pos-receipt__payments{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0;padding:0;list-style:none}.pos-receipt__payment{display:flex;flex-direction:column;gap:var(--pos-space-sm);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-receipt__payment-header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__payment-tender{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-bold)}.pos-receipt__payment-state{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__actions{margin-top:var(--pos-space-md)}.pos-receipt__new-sale{width:100%;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-receipt__new-sale:not(:disabled):active{transform:translateY(1px)}.pos-receipt__new-sale:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;transform:none}.pos-receipt__new-sale:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-receipt__panel{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(16rem,1fr);grid-template-areas:\"header header\" \"status status\" \"lines summary\" \"actions actions\";gap:var(--pos-space-lg);padding:var(--pos-space-xl);align-items:start}.pos-receipt__header{grid-area:header}.pos-receipt__status{grid-area:status;margin:0}.pos-receipt__lines{grid-area:lines;margin:0}.pos-receipt__line{grid-template-columns:minmax(0,1fr) auto auto;grid-template-areas:\"info qty prices\";gap:var(--pos-space-md)}.pos-receipt__line-prices{flex-direction:column;align-items:flex-end;justify-content:center}.pos-receipt__summary{grid-area:summary;margin:0;padding:0;border-top:0}.pos-receipt__actions{grid-area:actions;margin:0}}@media(prefers-reduced-motion:reduce){.pos-receipt__new-sale{transform:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
545
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: PosReceipt, isStandalone: true, selector: "pos-receipt", inputs: { lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, totals: { classPropertyName: "totals", publicName: "totals", isSignal: true, isRequired: false, transformFunction: null }, payments: { classPropertyName: "payments", publicName: "payments", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, preparingLabel: { classPropertyName: "preparingLabel", publicName: "preparingLabel", isSignal: true, isRequired: false, transformFunction: null }, readyLabel: { classPropertyName: "readyLabel", publicName: "readyLabel", isSignal: true, isRequired: false, transformFunction: null }, newSaleLabel: { classPropertyName: "newSaleLabel", publicName: "newSaleLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderLabel: { classPropertyName: "tenderLabel", publicName: "tenderLabel", isSignal: true, isRequired: false, transformFunction: null }, amountLabel: { classPropertyName: "amountLabel", publicName: "amountLabel", isSignal: true, isRequired: false, transformFunction: null }, tenderedLabel: { classPropertyName: "tenderedLabel", publicName: "tenderedLabel", isSignal: true, isRequired: false, transformFunction: null }, changeLabel: { classPropertyName: "changeLabel", publicName: "changeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { classAttribute: "pos-receipt" }, ngImport: i0, template: "<section\r\n class=\"pos-receipt__panel\"\r\n [class.pos-receipt__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() || !document().receiptReady ? true : null\"\r\n>\r\n <header class=\"pos-receipt__header\">\r\n <div class=\"pos-receipt__heading\">\r\n <p class=\"pos-receipt__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-receipt__title\">{{ title() }}</h2>\r\n </div>\r\n @if (hasDocumentNumber()) {\r\n <p class=\"pos-receipt__number\" aria-label=\"Document number\">\r\n {{ document().number }}\r\n </p>\r\n }\r\n </header>\r\n\r\n <p class=\"pos-receipt__status\" aria-live=\"polite\">{{ statusText() }}</p>\r\n\r\n <ul class=\"pos-receipt__lines\" aria-label=\"Receipt lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-receipt__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-receipt__line\"\r\n [class.pos-receipt__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-receipt__line-info\">\r\n <h3 class=\"pos-receipt__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-receipt__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-receipt__line-voided\">Voided</p>\r\n }\r\n </div>\r\n <p class=\"pos-receipt__qty\">{{ line.qty }}</p>\r\n <div class=\"pos-receipt__line-prices\">\r\n <p class=\"pos-receipt__unit-price\">\r\n {{ formatMoney(line.unitPrice) }}\r\n </p>\r\n <p class=\"pos-receipt__line-total\">\r\n {{ formatMoney(line.lineTotal) }}\r\n </p>\r\n </div>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <div class=\"pos-receipt__summary\">\r\n <dl class=\"pos-receipt__totals\" aria-live=\"polite\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasPayments()) {\r\n <section class=\"pos-receipt__tender\">\r\n <h3 class=\"pos-receipt__tender-title\">{{ tenderLabel() }}</h3>\r\n <ul class=\"pos-receipt__payments\">\r\n @for (payment of payments(); track $index) {\r\n <li class=\"pos-receipt__payment\">\r\n <header class=\"pos-receipt__payment-header\">\r\n <p class=\"pos-receipt__payment-tender\">{{ payment.tender }}</p>\r\n <p class=\"pos-receipt__payment-state\">{{ payment.state }}</p>\r\n </header>\r\n <dl class=\"pos-receipt__payment-amounts\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ amountLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.amount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ tenderedLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.tendered) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--change\">\r\n <dt>{{ changeLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.change) }}</dd>\r\n </div>\r\n </dl>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-receipt__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-receipt__new-sale\"\r\n [disabled]=\"!canStartNewSale()\"\r\n (click)=\"onNewSale()\"\r\n >\r\n {{ newSaleLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-receipt__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-receipt__panel--bordered{border:1px solid var(--pos-color-border)}.pos-receipt__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__heading{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-receipt__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-receipt__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-tight)}.pos-receipt__number{margin:0;color:var(--pos-color-text-muted);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere;text-align:right}.pos-receipt__status{margin:var(--pos-space-md) 0 0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:var(--pos-space-md) 0 0;padding:0;overflow-y:auto;list-style:none}.pos-receipt__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-receipt__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info qty\" \"prices prices\";align-items:center;gap:var(--pos-space-xs) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-receipt__line-info{grid-area:info;min-width:0}.pos-receipt__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-receipt__line-sku,.pos-receipt__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-receipt__line-sku{color:var(--pos-color-text-muted)}.pos-receipt__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__qty{grid-area:qty;margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums;text-align:right}.pos-receipt__line-prices{grid-area:prices;display:flex;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-receipt__line--voided .pos-receipt__line-name,.pos-receipt__line--voided .pos-receipt__line-sku,.pos-receipt__line--voided .pos-receipt__line-prices,.pos-receipt__line--voided .pos-receipt__qty{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-receipt__summary{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-receipt__totals,.pos-receipt__payment-amounts{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-receipt__row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__row dt,.pos-receipt__row dd{margin:0}.pos-receipt__row dd{font-variant-numeric:tabular-nums}.pos-receipt__row--due,.pos-receipt__row--change{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-receipt__tender{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-receipt__tender-title{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-receipt__payments{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0;padding:0;list-style:none}.pos-receipt__payment{display:flex;flex-direction:column;gap:var(--pos-space-sm);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-receipt__payment-header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__payment-tender{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-bold)}.pos-receipt__payment-state{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__actions{margin-top:var(--pos-space-md)}.pos-receipt__new-sale{width:100%;min-height:var(--pos-button-min-height);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-receipt__new-sale:not(:disabled):active{transform:translateY(1px)}.pos-receipt__new-sale:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;transform:none}.pos-receipt__new-sale:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-receipt__panel{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(16rem,1fr);grid-template-areas:\"header header\" \"status status\" \"lines summary\" \"actions actions\";gap:var(--pos-space-lg);padding:var(--pos-space-xl);align-items:start}.pos-receipt__header{grid-area:header}.pos-receipt__status{grid-area:status;margin:0}.pos-receipt__lines{grid-area:lines;margin:0}.pos-receipt__line{grid-template-columns:minmax(0,1fr) auto auto;grid-template-areas:\"info qty prices\";gap:var(--pos-space-md)}.pos-receipt__line-prices{flex-direction:column;align-items:flex-end;justify-content:center}.pos-receipt__summary{grid-area:summary;margin:0;padding:0;border-top:0}.pos-receipt__actions{grid-area:actions;margin:0}}@media(prefers-reduced-motion:reduce){.pos-receipt__new-sale{transform:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
386
546
|
}
|
|
387
547
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosReceipt, decorators: [{
|
|
388
548
|
type: Component,
|
|
389
549
|
args: [{ selector: 'pos-receipt', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
390
550
|
class: 'pos-receipt',
|
|
391
|
-
}, template: "<section\r\n class=\"pos-receipt__panel\"\r\n [attr.aria-busy]=\"disabled() || !document().receiptReady ? true : null\"\r\n>\r\n <header class=\"pos-receipt__header\">\r\n <div class=\"pos-receipt__heading\">\r\n <p class=\"pos-receipt__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-receipt__title\">{{ title() }}</h2>\r\n </div>\r\n @if (hasDocumentNumber()) {\r\n <p class=\"pos-receipt__number\" aria-label=\"Document number\">\r\n {{ document().number }}\r\n </p>\r\n }\r\n </header>\r\n\r\n <p class=\"pos-receipt__status\" aria-live=\"polite\">{{ statusText() }}</p>\r\n\r\n <ul class=\"pos-receipt__lines\" aria-label=\"Receipt lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-receipt__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-receipt__line\"\r\n [class.pos-receipt__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-receipt__line-info\">\r\n <h3 class=\"pos-receipt__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-receipt__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-receipt__line-voided\">Voided</p>\r\n }\r\n </div>\r\n <p class=\"pos-receipt__qty\">{{ line.qty }}</p>\r\n <div class=\"pos-receipt__line-prices\">\r\n <p class=\"pos-receipt__unit-price\">\r\n {{ formatMoney(line.unitPrice) }}\r\n </p>\r\n <p class=\"pos-receipt__line-total\">\r\n {{ formatMoney(line.lineTotal) }}\r\n </p>\r\n </div>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <div class=\"pos-receipt__summary\">\r\n <dl class=\"pos-receipt__totals\" aria-live=\"polite\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasPayments()) {\r\n <section class=\"pos-receipt__tender\">\r\n <h3 class=\"pos-receipt__tender-title\">{{ tenderLabel() }}</h3>\r\n <ul class=\"pos-receipt__payments\">\r\n @for (payment of payments(); track $index) {\r\n <li class=\"pos-receipt__payment\">\r\n <header class=\"pos-receipt__payment-header\">\r\n <p class=\"pos-receipt__payment-tender\">{{ payment.tender }}</p>\r\n <p class=\"pos-receipt__payment-state\">{{ payment.state }}</p>\r\n </header>\r\n <dl class=\"pos-receipt__payment-amounts\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ amountLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.amount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ tenderedLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.tendered) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--change\">\r\n <dt>{{ changeLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.change) }}</dd>\r\n </div>\r\n </dl>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-receipt__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-receipt__new-sale\"\r\n [disabled]=\"!canStartNewSale()\"\r\n (click)=\"onNewSale()\"\r\n >\r\n {{ newSaleLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-receipt__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-lg);background:radial-gradient(120% 80% at 100% 0%,rgba(0,194,178,.08),transparent 55%),var(--pos-color-panel)}.pos-receipt__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__heading{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-receipt__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-receipt__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:-.03em}.pos-receipt__number{margin:0;color:var(--pos-color-text-muted);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere;text-align:right}.pos-receipt__status{margin:var(--pos-space-md) 0 0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:var(--pos-space-md) 0 0;padding:0;overflow-y:auto;list-style:none}.pos-receipt__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-receipt__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info qty\" \"prices prices\";align-items:center;gap:var(--pos-space-xs) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-receipt__line-info{grid-area:info;min-width:0}.pos-receipt__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-receipt__line-sku,.pos-receipt__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-receipt__line-sku{color:var(--pos-color-text-muted)}.pos-receipt__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__qty{grid-area:qty;margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums;text-align:right}.pos-receipt__line-prices{grid-area:prices;display:flex;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-receipt__line--voided .pos-receipt__line-name,.pos-receipt__line--voided .pos-receipt__line-sku,.pos-receipt__line--voided .pos-receipt__line-prices,.pos-receipt__line--voided .pos-receipt__qty{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-receipt__summary{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-receipt__totals,.pos-receipt__payment-amounts{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-receipt__row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__row dt,.pos-receipt__row dd{margin:0}.pos-receipt__row dd{font-variant-numeric:tabular-nums}.pos-receipt__row--due,.pos-receipt__row--change{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-receipt__tender{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-receipt__tender-title{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);letter-spacing:.08em;text-transform:uppercase}.pos-receipt__payments{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0;padding:0;list-style:none}.pos-receipt__payment{display:flex;flex-direction:column;gap:var(--pos-space-sm);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-receipt__payment-header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__payment-tender{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-bold)}.pos-receipt__payment-state{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__actions{margin-top:var(--pos-space-md)}.pos-receipt__new-sale{width:100%;min-height:var(--pos-button-min-height);border:0;border-radius:var(--pos-radius-md);background:var(--pos-color-primary);color:var(--pos-color-on-primary);font:inherit;font-weight:var(--pos-font-weight-bold);letter-spacing:.04em;text-transform:uppercase;cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-receipt__new-sale:not(:disabled):active{transform:translateY(1px)}.pos-receipt__new-sale:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;transform:none}.pos-receipt__new-sale:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-receipt__panel{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(16rem,1fr);grid-template-areas:\"header header\" \"status status\" \"lines summary\" \"actions actions\";gap:var(--pos-space-lg);padding:var(--pos-space-xl);align-items:start}.pos-receipt__header{grid-area:header}.pos-receipt__status{grid-area:status;margin:0}.pos-receipt__lines{grid-area:lines;margin:0}.pos-receipt__line{grid-template-columns:minmax(0,1fr) auto auto;grid-template-areas:\"info qty prices\";gap:var(--pos-space-md)}.pos-receipt__line-prices{flex-direction:column;align-items:flex-end;justify-content:center}.pos-receipt__summary{grid-area:summary;margin:0;padding:0;border-top:0}.pos-receipt__actions{grid-area:actions;margin:0}}@media(prefers-reduced-motion:reduce){.pos-receipt__new-sale{transform:none}}\n"] }]
|
|
392
|
-
}], propDecorators: { lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], totals: [{ type: i0.Input, args: [{ isSignal: true, alias: "totals", required: false }] }], payments: [{ type: i0.Input, args: [{ isSignal: true, alias: "payments", required: false }] }], document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], preparingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "preparingLabel", required: false }] }], readyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "readyLabel", required: false }] }], newSaleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "newSaleLabel", required: false }] }], tenderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderLabel", required: false }] }], amountLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountLabel", required: false }] }], tenderedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderedLabel", required: false }] }], changeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
551
|
+
}, template: "<section\r\n class=\"pos-receipt__panel\"\r\n [class.pos-receipt__panel--bordered]=\"bordered()\"\r\n [attr.aria-busy]=\"disabled() || !document().receiptReady ? true : null\"\r\n>\r\n <header class=\"pos-receipt__header\">\r\n <div class=\"pos-receipt__heading\">\r\n <p class=\"pos-receipt__kicker\">Adaptive POS</p>\r\n <h2 class=\"pos-receipt__title\">{{ title() }}</h2>\r\n </div>\r\n @if (hasDocumentNumber()) {\r\n <p class=\"pos-receipt__number\" aria-label=\"Document number\">\r\n {{ document().number }}\r\n </p>\r\n }\r\n </header>\r\n\r\n <p class=\"pos-receipt__status\" aria-live=\"polite\">{{ statusText() }}</p>\r\n\r\n <ul class=\"pos-receipt__lines\" aria-label=\"Receipt lines\">\r\n @if (!hasLines()) {\r\n <li class=\"pos-receipt__empty\">{{ emptyMessage() }}</li>\r\n } @else {\r\n @for (line of lines(); track line.lineId) {\r\n <li>\r\n <article\r\n class=\"pos-receipt__line\"\r\n [class.pos-receipt__line--voided]=\"line.struckThrough\"\r\n >\r\n <div class=\"pos-receipt__line-info\">\r\n <h3 class=\"pos-receipt__line-name\">{{ line.name }}</h3>\r\n <p class=\"pos-receipt__line-sku\">{{ line.sku }}</p>\r\n @if (line.struckThrough) {\r\n <p class=\"pos-receipt__line-voided\">Voided</p>\r\n }\r\n </div>\r\n <p class=\"pos-receipt__qty\">{{ line.qty }}</p>\r\n <div class=\"pos-receipt__line-prices\">\r\n <p class=\"pos-receipt__unit-price\">\r\n {{ formatMoney(line.unitPrice) }}\r\n </p>\r\n <p class=\"pos-receipt__line-total\">\r\n {{ formatMoney(line.lineTotal) }}\r\n </p>\r\n </div>\r\n </article>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n\r\n <div class=\"pos-receipt__summary\">\r\n <dl class=\"pos-receipt__totals\" aria-live=\"polite\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>Gross</dt>\r\n <dd>{{ formatMoney(totals().gross) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Net</dt>\r\n <dd>{{ formatMoney(totals().net) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>VAT</dt>\r\n <dd>{{ formatMoney(totals().vat) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>Discount</dt>\r\n <dd>{{ formatMoney(totals().discount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--due\">\r\n <dt>Due</dt>\r\n <dd>{{ formatMoney(totals().due) }}</dd>\r\n </div>\r\n </dl>\r\n\r\n @if (hasPayments()) {\r\n <section class=\"pos-receipt__tender\">\r\n <h3 class=\"pos-receipt__tender-title\">{{ tenderLabel() }}</h3>\r\n <ul class=\"pos-receipt__payments\">\r\n @for (payment of payments(); track $index) {\r\n <li class=\"pos-receipt__payment\">\r\n <header class=\"pos-receipt__payment-header\">\r\n <p class=\"pos-receipt__payment-tender\">{{ payment.tender }}</p>\r\n <p class=\"pos-receipt__payment-state\">{{ payment.state }}</p>\r\n </header>\r\n <dl class=\"pos-receipt__payment-amounts\">\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ amountLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.amount) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row\">\r\n <dt>{{ tenderedLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.tendered) }}</dd>\r\n </div>\r\n <div class=\"pos-receipt__row pos-receipt__row--change\">\r\n <dt>{{ changeLabel() }}</dt>\r\n <dd>{{ formatMoney(payment.change) }}</dd>\r\n </div>\r\n </dl>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n }\r\n </div>\r\n\r\n <div class=\"pos-receipt__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-receipt__new-sale\"\r\n [disabled]=\"!canStartNewSale()\"\r\n (click)=\"onNewSale()\"\r\n >\r\n {{ newSaleLabel() }}\r\n </button>\r\n </div>\r\n</section>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:0;width:100%;height:100%;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-receipt__panel{display:flex;flex-direction:column;min-height:0;height:100%;padding:var(--pos-space-lg);border-radius:var(--pos-radius-lg);background:var(--pos-color-panel)}.pos-receipt__panel--bordered{border:1px solid var(--pos-color-border)}.pos-receipt__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__heading{display:flex;flex-direction:column;gap:var(--pos-space-sm);min-width:0}.pos-receipt__kicker{margin:0;color:var(--pos-color-primary);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-bold);letter-spacing:.14em;text-transform:uppercase}.pos-receipt__title{margin:0;font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-xl);font-weight:var(--pos-font-weight-bold);letter-spacing:var(--pos-letter-spacing-tight)}.pos-receipt__number{margin:0;color:var(--pos-color-text-muted);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold);overflow-wrap:anywhere;text-align:right}.pos-receipt__status{margin:var(--pos-space-md) 0 0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__lines{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--pos-space-sm);min-height:8rem;margin:var(--pos-space-md) 0 0;padding:0;overflow-y:auto;list-style:none}.pos-receipt__empty{margin:auto 0;padding:var(--pos-space-2xl) var(--pos-space-md);color:var(--pos-color-text-muted);text-align:center}.pos-receipt__line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"info qty\" \"prices prices\";align-items:center;gap:var(--pos-space-xs) var(--pos-space-md);padding:var(--pos-space-md);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-panel-elevated)}.pos-receipt__line-info{grid-area:info;min-width:0}.pos-receipt__line-name{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pos-receipt__line-sku,.pos-receipt__line-voided{margin:var(--pos-space-xs) 0 0;font-size:var(--pos-font-size-sm)}.pos-receipt__line-sku{color:var(--pos-color-text-muted)}.pos-receipt__line-voided{color:var(--pos-color-danger);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__qty{grid-area:qty;margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums;text-align:right}.pos-receipt__line-prices{grid-area:prices;display:flex;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__unit-price{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__line-total{margin:0;font-family:var(--pos-font-family-display);font-weight:var(--pos-font-weight-bold);font-variant-numeric:tabular-nums}.pos-receipt__line--voided .pos-receipt__line-name,.pos-receipt__line--voided .pos-receipt__line-sku,.pos-receipt__line--voided .pos-receipt__line-prices,.pos-receipt__line--voided .pos-receipt__qty{color:var(--pos-color-text-muted);text-decoration:line-through}.pos-receipt__summary{display:flex;flex-direction:column;gap:var(--pos-space-md);margin-top:var(--pos-space-md);padding-top:var(--pos-space-md);border-top:1px solid var(--pos-color-border)}.pos-receipt__totals,.pos-receipt__payment-amounts{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0}.pos-receipt__row{display:flex;justify-content:space-between;gap:var(--pos-space-md);margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm)}.pos-receipt__row dt,.pos-receipt__row dd{margin:0}.pos-receipt__row dd{font-variant-numeric:tabular-nums}.pos-receipt__row--due,.pos-receipt__row--change{padding-top:var(--pos-space-sm);border-top:1px solid var(--pos-color-border);color:var(--pos-color-text);font-family:var(--pos-font-family-display);font-size:var(--pos-font-size-lg);font-weight:var(--pos-font-weight-bold)}.pos-receipt__tender{display:flex;flex-direction:column;gap:var(--pos-space-sm)}.pos-receipt__tender-title{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-receipt__payments{display:flex;flex-direction:column;gap:var(--pos-space-sm);margin:0;padding:0;list-style:none}.pos-receipt__payment{display:flex;flex-direction:column;gap:var(--pos-space-sm);padding:var(--pos-space-md) var(--pos-space-lg);border:1px solid var(--pos-color-success);border-radius:var(--pos-radius-md);background:color-mix(in srgb,var(--pos-color-success) 14%,var(--pos-color-panel-elevated))}.pos-receipt__payment-header{display:flex;align-items:baseline;justify-content:space-between;gap:var(--pos-space-md)}.pos-receipt__payment-tender{margin:0;font-size:var(--pos-font-size-md);font-weight:var(--pos-font-weight-bold)}.pos-receipt__payment-state{margin:0;color:var(--pos-color-text-muted);font-size:var(--pos-font-size-sm);font-weight:var(--pos-font-weight-semibold)}.pos-receipt__actions{margin-top:var(--pos-space-md)}.pos-receipt__new-sale{width:100%;min-height:var(--pos-button-min-height);border:1px solid var(--pos-color-border);border-radius:var(--pos-radius-md);background:var(--pos-color-surface);color:var(--pos-color-text);font:inherit;font-weight:var(--pos-font-weight-semibold);cursor:pointer;-webkit-tap-highlight-color:transparent}.pos-receipt__new-sale:not(:disabled):active{transform:translateY(1px)}.pos-receipt__new-sale:disabled{background:var(--pos-color-disabled);color:var(--pos-color-on-disabled);cursor:not-allowed;transform:none}.pos-receipt__new-sale:focus-visible{outline:2px solid var(--pos-color-primary);outline-offset:2px}@media(min-width:768px){.pos-receipt__panel{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(16rem,1fr);grid-template-areas:\"header header\" \"status status\" \"lines summary\" \"actions actions\";gap:var(--pos-space-lg);padding:var(--pos-space-xl);align-items:start}.pos-receipt__header{grid-area:header}.pos-receipt__status{grid-area:status;margin:0}.pos-receipt__lines{grid-area:lines;margin:0}.pos-receipt__line{grid-template-columns:minmax(0,1fr) auto auto;grid-template-areas:\"info qty prices\";gap:var(--pos-space-md)}.pos-receipt__line-prices{flex-direction:column;align-items:flex-end;justify-content:center}.pos-receipt__summary{grid-area:summary;margin:0;padding:0;border-top:0}.pos-receipt__actions{grid-area:actions;margin:0}}@media(prefers-reduced-motion:reduce){.pos-receipt__new-sale{transform:none}}\n"] }]
|
|
552
|
+
}], propDecorators: { lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], totals: [{ type: i0.Input, args: [{ isSignal: true, alias: "totals", required: false }] }], payments: [{ type: i0.Input, args: [{ isSignal: true, alias: "payments", required: false }] }], document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], preparingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "preparingLabel", required: false }] }], readyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "readyLabel", required: false }] }], newSaleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "newSaleLabel", required: false }] }], tenderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderLabel", required: false }] }], amountLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "amountLabel", required: false }] }], tenderedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenderedLabel", required: false }] }], changeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
393
553
|
|
|
394
554
|
const POS_TOKEN_CATALOG = [
|
|
395
555
|
{
|
|
@@ -462,7 +622,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
462
622
|
kind: 'color',
|
|
463
623
|
group: 'color',
|
|
464
624
|
preview: 'color',
|
|
465
|
-
defaultValue: '#
|
|
625
|
+
defaultValue: '#1a1a1a',
|
|
466
626
|
},
|
|
467
627
|
{
|
|
468
628
|
name: 'Text muted',
|
|
@@ -470,7 +630,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
470
630
|
kind: 'color',
|
|
471
631
|
group: 'color',
|
|
472
632
|
preview: 'color',
|
|
473
|
-
defaultValue: '#
|
|
633
|
+
defaultValue: '#666a70',
|
|
474
634
|
},
|
|
475
635
|
{
|
|
476
636
|
name: 'Surface',
|
|
@@ -486,7 +646,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
486
646
|
kind: 'color',
|
|
487
647
|
group: 'color',
|
|
488
648
|
preview: 'color',
|
|
489
|
-
defaultValue: '#
|
|
649
|
+
defaultValue: '#f5f5f7',
|
|
490
650
|
},
|
|
491
651
|
{
|
|
492
652
|
name: 'Panel',
|
|
@@ -494,7 +654,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
494
654
|
kind: 'color',
|
|
495
655
|
group: 'color',
|
|
496
656
|
preview: 'color',
|
|
497
|
-
defaultValue: '#
|
|
657
|
+
defaultValue: '#ffffff',
|
|
498
658
|
},
|
|
499
659
|
{
|
|
500
660
|
name: 'Panel elevated',
|
|
@@ -510,7 +670,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
510
670
|
kind: 'color',
|
|
511
671
|
group: 'color',
|
|
512
672
|
preview: 'color',
|
|
513
|
-
defaultValue: '#
|
|
673
|
+
defaultValue: '#1a1a1a',
|
|
514
674
|
},
|
|
515
675
|
{
|
|
516
676
|
name: 'Border',
|
|
@@ -518,7 +678,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
518
678
|
kind: 'color',
|
|
519
679
|
group: 'color',
|
|
520
680
|
preview: 'color',
|
|
521
|
-
defaultValue: '#
|
|
681
|
+
defaultValue: '#ececf0',
|
|
522
682
|
},
|
|
523
683
|
{
|
|
524
684
|
name: 'Disabled',
|
|
@@ -542,7 +702,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
542
702
|
kind: 'color',
|
|
543
703
|
group: 'color',
|
|
544
704
|
preview: 'color',
|
|
545
|
-
defaultValue: '#
|
|
705
|
+
defaultValue: '#1a1a1a',
|
|
546
706
|
},
|
|
547
707
|
{
|
|
548
708
|
name: 'On display',
|
|
@@ -566,7 +726,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
566
726
|
kind: 'color',
|
|
567
727
|
group: 'color',
|
|
568
728
|
preview: 'color',
|
|
569
|
-
defaultValue: '#
|
|
729
|
+
defaultValue: '#ececf0',
|
|
570
730
|
},
|
|
571
731
|
{
|
|
572
732
|
name: 'Key active',
|
|
@@ -574,7 +734,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
574
734
|
kind: 'color',
|
|
575
735
|
group: 'color',
|
|
576
736
|
preview: 'color',
|
|
577
|
-
defaultValue: '#
|
|
737
|
+
defaultValue: '#f0e6fd',
|
|
578
738
|
},
|
|
579
739
|
{
|
|
580
740
|
name: 'On key active',
|
|
@@ -582,7 +742,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
582
742
|
kind: 'color',
|
|
583
743
|
group: 'color',
|
|
584
744
|
preview: 'color',
|
|
585
|
-
defaultValue: '#
|
|
745
|
+
defaultValue: '#1a1a1a',
|
|
586
746
|
},
|
|
587
747
|
{
|
|
588
748
|
name: 'Radius sm',
|
|
@@ -678,7 +838,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
678
838
|
kind: 'font-family',
|
|
679
839
|
group: 'type',
|
|
680
840
|
preview: 'font-family',
|
|
681
|
-
defaultValue: "
|
|
841
|
+
defaultValue: "'Chakra Petch', ui-sans-serif, system-ui, sans-serif",
|
|
682
842
|
},
|
|
683
843
|
{
|
|
684
844
|
name: 'Font family display',
|
|
@@ -686,7 +846,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
686
846
|
kind: 'font-family',
|
|
687
847
|
group: 'type',
|
|
688
848
|
preview: 'font-family',
|
|
689
|
-
defaultValue: "
|
|
849
|
+
defaultValue: "'Helvetica Neue', Helvetica, Arial, sans-serif",
|
|
690
850
|
},
|
|
691
851
|
{
|
|
692
852
|
name: 'Font size sm',
|
|
@@ -702,7 +862,7 @@ const POS_TOKEN_CATALOG = [
|
|
|
702
862
|
kind: 'length',
|
|
703
863
|
group: 'type',
|
|
704
864
|
preview: 'font-size',
|
|
705
|
-
defaultValue: '0.
|
|
865
|
+
defaultValue: '0.90625rem',
|
|
706
866
|
},
|
|
707
867
|
{
|
|
708
868
|
name: 'Font size lg',
|
|
@@ -744,6 +904,38 @@ const POS_TOKEN_CATALOG = [
|
|
|
744
904
|
preview: 'letter-spacing',
|
|
745
905
|
defaultValue: '0.28em',
|
|
746
906
|
},
|
|
907
|
+
{
|
|
908
|
+
name: 'Letter spacing brand',
|
|
909
|
+
variable: '--pos-letter-spacing-brand',
|
|
910
|
+
kind: 'length',
|
|
911
|
+
group: 'type',
|
|
912
|
+
preview: 'letter-spacing',
|
|
913
|
+
defaultValue: '0.08em',
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: 'Letter spacing tight',
|
|
917
|
+
variable: '--pos-letter-spacing-tight',
|
|
918
|
+
kind: 'length',
|
|
919
|
+
group: 'type',
|
|
920
|
+
preview: 'letter-spacing',
|
|
921
|
+
defaultValue: '-0.03em',
|
|
922
|
+
},
|
|
923
|
+
{
|
|
924
|
+
name: 'Shadow key',
|
|
925
|
+
variable: '--pos-shadow-key',
|
|
926
|
+
kind: 'other',
|
|
927
|
+
group: 'shadow',
|
|
928
|
+
preview: 'shadow',
|
|
929
|
+
defaultValue: '0 1px 3px color-mix(in srgb, var(--pos-color-ink) 8%, transparent)',
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
name: 'Shadow overlay',
|
|
933
|
+
variable: '--pos-shadow-overlay',
|
|
934
|
+
kind: 'other',
|
|
935
|
+
group: 'shadow',
|
|
936
|
+
preview: 'shadow',
|
|
937
|
+
defaultValue: '0 var(--pos-space-md) var(--pos-space-2xl) color-mix(in srgb, var(--pos-color-ink) 14%, transparent)',
|
|
938
|
+
},
|
|
747
939
|
{
|
|
748
940
|
name: 'Button min height',
|
|
749
941
|
variable: '--pos-button-min-height',
|
|
@@ -944,6 +1136,7 @@ class PosTokens {
|
|
|
944
1136
|
radiusTokens = tokensInGroup('radius');
|
|
945
1137
|
spaceTokens = tokensInGroup('space');
|
|
946
1138
|
typeTokens = tokensInGroup('type');
|
|
1139
|
+
shadowTokens = tokensInGroup('shadow');
|
|
947
1140
|
controlTokens = tokensInGroup('control');
|
|
948
1141
|
overrides = signal({}, ...(ngDevMode ? [{ debugName: "overrides" }] : /* istanbul ignore next */ []));
|
|
949
1142
|
selection = signal(null, ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
@@ -1085,5 +1278,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
|
|
|
1085
1278
|
* Generated bundle index. Do not edit.
|
|
1086
1279
|
*/
|
|
1087
1280
|
|
|
1088
|
-
export { PosBasket, PosItemEntry, PosLogin, PosReceipt, PosTender, PosTokens };
|
|
1281
|
+
export { PosBasket, PosHeader, PosItemEntry, PosLogin, PosReceipt, PosTender, PosTokens, PosTransactionActionBar };
|
|
1089
1282
|
//# sourceMappingURL=retalia-pos-components.mjs.map
|