@retalia/pos-components 0.0.5 → 0.0.7

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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Presentational Adaptive POS Angular components. State in, typed intents out — no service calls.
4
4
 
5
+ Optional HTTP clients live behind a **separate entry point**: `@retalia/pos-components/services`. Components never import that entry. The host calls a service, then passes display state into the UI.
6
+
5
7
  Requires **Angular 21** (`@angular/core` and `@angular/common` `^21.2.0`).
6
8
 
7
9
  ## Install
@@ -10,6 +12,27 @@ Requires **Angular 21** (`@angular/core` and `@angular/common` `^21.2.0`).
10
12
  npm i @retalia/pos-components
11
13
  ```
12
14
 
15
+ ## Services
16
+
17
+ Import from `@retalia/pos-components/services`, never from a `pos-*` component.
18
+
19
+ ```ts
20
+ import {
21
+ ClerkAuthService,
22
+ POS_API_CONFIG,
23
+ PosCommandsClient,
24
+ posApiInterceptor,
25
+ } from '@retalia/pos-components/services';
26
+ ```
27
+
28
+ | | |
29
+ |---|---|
30
+ | `posApiInterceptor` | Reads `portalApiToken` + `contextShopId` cookies and sets `Authorization` / `Shop-Context`. Provide via `provideHttpClient(withInterceptors([posApiInterceptor]))`. |
31
+ | `ClerkAuthService` | `signIn(clerkNumber, password)` — GET `/api/v1.0/clerks/{number}`, password check in the service (stub until ID-647). Call this from the host on `login.submit`. |
32
+ | `PosCommandsClient` | `addItem` / `changeQuantity` / `clearBasket` / `tenderCash` / `newSale` — each returns a `PosStateEnvelope`. |
33
+
34
+ In local Adaptive POS, paste a Portal Bearer into the `portalApiToken` cookie and the shop id into `contextShopId`. Do not send clerk credentials to `POST /token`.
35
+
13
36
  ## Styles
14
37
 
15
38
  Add the package stylesheet once in the host app (e.g. `angular.json` `styles`):
@@ -83,7 +106,7 @@ export class App {
83
106
  if (intent.type !== 'login.submit') {
84
107
  return;
85
108
  }
86
- // Host (or optional package AuthService) calls the API, then:
109
+ // Host (or package ClerkAuthService) calls the API, then:
87
110
  // this.session.set({ status: 'busy' });
88
111
  // this.session.set({ status: 'signedIn', displayName: clerk.name });
89
112
  // this.errorMessage.set('Invalid clerk or password');
@@ -0,0 +1,193 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, Injectable } from '@angular/core';
3
+ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
4
+ import { throwError, switchMap, from, catchError } from 'rxjs';
5
+
6
+ /** Read a document cookie by name. Returns null when missing or not in a browser. */
7
+ function readCookie(name) {
8
+ if (typeof document === 'undefined' || !name) {
9
+ return null;
10
+ }
11
+ const encodedName = encodeURIComponent(name);
12
+ for (const part of document.cookie.split(';')) {
13
+ const trimmed = part.trim();
14
+ const separator = trimmed.indexOf('=');
15
+ if (separator < 0) {
16
+ continue;
17
+ }
18
+ const key = trimmed.slice(0, separator);
19
+ if (key !== name && key !== encodedName) {
20
+ continue;
21
+ }
22
+ return decodeURIComponent(trimmed.slice(separator + 1));
23
+ }
24
+ return null;
25
+ }
26
+
27
+ const DEFAULT_POS_API_CONFIG = {
28
+ apiBaseUrl: '',
29
+ tokenCookieName: 'portalApiToken',
30
+ shopContextCookieName: 'contextShopId',
31
+ };
32
+ const POS_API_CONFIG = new InjectionToken('POS_API_CONFIG', {
33
+ providedIn: 'root',
34
+ factory: () => DEFAULT_POS_API_CONFIG,
35
+ });
36
+ function readAccessToken(config) {
37
+ return config.getAccessToken?.() ?? readCookie(config.tokenCookieName);
38
+ }
39
+ function readShopContext(config) {
40
+ return config.getShopContext?.() ?? readCookie(config.shopContextCookieName);
41
+ }
42
+
43
+ function joinUrl(baseUrl, path) {
44
+ if (!baseUrl || /^https?:\/\//i.test(path)) {
45
+ return path;
46
+ }
47
+ const origin = baseUrl.replace(/\/+$/, '');
48
+ const suffix = path.replace(/^\/+/, '');
49
+ return `${origin}/${suffix}`;
50
+ }
51
+ /** Attaches Bearer + Shop-Context from cookies (or host overrides). */
52
+ const posApiInterceptor = (req, next) => {
53
+ const config = inject(POS_API_CONFIG);
54
+ const token = readAccessToken(config);
55
+ const shopContext = readShopContext(config);
56
+ let headers = req.headers;
57
+ if (token && !headers.has('Authorization')) {
58
+ headers = headers.set('Authorization', `Bearer ${token}`);
59
+ }
60
+ if (shopContext && !headers.has('Shop-Context')) {
61
+ headers = headers.set('Shop-Context', shopContext);
62
+ }
63
+ return next(req.clone({
64
+ url: joinUrl(config.apiBaseUrl, req.url),
65
+ headers,
66
+ }));
67
+ };
68
+
69
+ class ClerkAuthError extends Error {
70
+ name = 'ClerkAuthError';
71
+ constructor(message) {
72
+ super(message);
73
+ }
74
+ }
75
+ const SHA256_HEX = /^[0-9a-f]{64}$/i;
76
+ function displayName(clerk, clerkNumber) {
77
+ const name = `${clerk.firstName ?? ''} ${clerk.lastName ?? ''}`.trim();
78
+ return name || clerk.clerkNumber || clerkNumber;
79
+ }
80
+ /** HeadlessPOS `SvcClerkService.validateClerk`: SHA-256 of UTF-16 `${identifier}.${pin}`. */
81
+ async function hashClerkPin(identifier, pin) {
82
+ const message = `${identifier}.${pin}`;
83
+ const buffer = new ArrayBuffer(message.length * 2);
84
+ const utf16 = new Uint16Array(buffer);
85
+ for (let i = 0; i < message.length; i++) {
86
+ utf16[i] = message.charCodeAt(i);
87
+ }
88
+ const digest = await crypto.subtle.digest('SHA-256', buffer);
89
+ return Array.from(new Uint8Array(digest))
90
+ .map((byte) => byte.toString(16).padStart(2, '0'))
91
+ .join('')
92
+ .toUpperCase();
93
+ }
94
+ async function passwordsMatch(submitted, clerk) {
95
+ const stored = clerk.password ?? '';
96
+ if (SHA256_HEX.test(stored)) {
97
+ const hash = await hashClerkPin(clerk.identifier, submitted);
98
+ return hash === stored.toUpperCase();
99
+ }
100
+ return submitted === stored;
101
+ }
102
+ class ClerkAuthService {
103
+ http = inject(HttpClient);
104
+ /**
105
+ * Looks up the clerk and compares the keypad password in this service.
106
+ * Hashed passwords use the HeadlessPOS SHA-256 check. Not a dedicated
107
+ * sign-in endpoint — replace when ID-647 / PosIdentity lands.
108
+ */
109
+ signIn(clerkNumber, password) {
110
+ const number = clerkNumber.trim();
111
+ if (!number) {
112
+ return throwError(() => new ClerkAuthError('Invalid clerk or password'));
113
+ }
114
+ return this.http.get(`/api/v1.0/clerks/${encodeURIComponent(number)}`).pipe(switchMap((clerk) => from(this.toSession(clerk, number, password))), catchError((error) => {
115
+ if (error instanceof ClerkAuthError) {
116
+ return throwError(() => error);
117
+ }
118
+ if (error instanceof HttpErrorResponse) {
119
+ if (error.status === 401) {
120
+ return throwError(() => new ClerkAuthError('API token missing or expired. Paste portalApiToken into cookies.'));
121
+ }
122
+ if (error.status === 404) {
123
+ return throwError(() => new ClerkAuthError('Invalid clerk or password'));
124
+ }
125
+ }
126
+ return throwError(() => new ClerkAuthError('Unable to sign in'));
127
+ }));
128
+ }
129
+ async toSession(clerk, clerkNumber, password) {
130
+ if (!(await passwordsMatch(password, clerk))) {
131
+ throw new ClerkAuthError('Invalid clerk or password');
132
+ }
133
+ return {
134
+ clerkNumber: clerk.clerkNumber || clerkNumber,
135
+ displayName: displayName(clerk, clerkNumber),
136
+ languageCode: clerk.languageCode || 'en',
137
+ isManager: clerk.isManager === true,
138
+ };
139
+ }
140
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: ClerkAuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
141
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: ClerkAuthService, providedIn: 'root' });
142
+ }
143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: ClerkAuthService, decorators: [{
144
+ type: Injectable,
145
+ args: [{ providedIn: 'root' }]
146
+ }] });
147
+
148
+ function idempotencyKey() {
149
+ return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(16).slice(2)}`;
150
+ }
151
+ /**
152
+ * Thin HTTP client for open-till sale commands (command in → PosStateEnvelope out).
153
+ *
154
+ * Keep as one client while the surface is small. When basket, tender, and sale
155
+ * lifecycle each grow their own handful of methods, split by subdomain, e.g.:
156
+ * - basket: addItem / changeQuantity / clearBasket (+ discounts, modifiers, …)
157
+ * - tender: tenderCash (+ card, void payment, …)
158
+ * - sale: newSale (+ suspend, recall, …)
159
+ * Extract is cheap; avoid splitting early into near-empty clients.
160
+ */
161
+ class PosCommandsClient {
162
+ http = inject(HttpClient);
163
+ addItem(command, key = idempotencyKey()) {
164
+ return this.http.post('/api/v1.0/pos/commands/add-item', command, {
165
+ headers: { 'Idempotency-Key': key },
166
+ });
167
+ }
168
+ changeQuantity(command, key = idempotencyKey()) {
169
+ return this.http.post('/api/v1.0/pos/commands/change-quantity', command, { headers: { 'Idempotency-Key': key } });
170
+ }
171
+ clearBasket(command, key = idempotencyKey()) {
172
+ return this.http.post('/api/v1.0/pos/commands/clear-basket', command, { headers: { 'Idempotency-Key': key } });
173
+ }
174
+ tenderCash(command, key = idempotencyKey()) {
175
+ return this.http.post('/api/v1.0/pos/commands/tender-cash', command, { headers: { 'Idempotency-Key': key } });
176
+ }
177
+ newSale(command, key = idempotencyKey()) {
178
+ return this.http.post('/api/v1.0/pos/commands/new-sale', command, { headers: { 'Idempotency-Key': key } });
179
+ }
180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosCommandsClient, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
181
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosCommandsClient, providedIn: 'root' });
182
+ }
183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosCommandsClient, decorators: [{
184
+ type: Injectable,
185
+ args: [{ providedIn: 'root' }]
186
+ }] });
187
+
188
+ /**
189
+ * Generated bundle index. Do not edit.
190
+ */
191
+
192
+ export { ClerkAuthError, ClerkAuthService, DEFAULT_POS_API_CONFIG, POS_API_CONFIG, PosCommandsClient, posApiInterceptor, readAccessToken, readShopContext };
193
+ //# sourceMappingURL=retalia-pos-components-services.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retalia-pos-components-services.mjs","sources":["../../../projects/pos-components/services/read-cookie.ts","../../../projects/pos-components/services/pos-api-config.ts","../../../projects/pos-components/services/pos-api.interceptor.ts","../../../projects/pos-components/services/clerk-auth.service.ts","../../../projects/pos-components/services/pos-commands.client.ts","../../../projects/pos-components/services/retalia-pos-components-services.ts"],"sourcesContent":["/** Read a document cookie by name. Returns null when missing or not in a browser. */\r\nexport function readCookie(name: string): string | null {\r\n if (typeof document === 'undefined' || !name) {\r\n return null;\r\n }\r\n\r\n const encodedName = encodeURIComponent(name);\r\n for (const part of document.cookie.split(';')) {\r\n const trimmed = part.trim();\r\n const separator = trimmed.indexOf('=');\r\n if (separator < 0) {\r\n continue;\r\n }\r\n\r\n const key = trimmed.slice(0, separator);\r\n if (key !== name && key !== encodedName) {\r\n continue;\r\n }\r\n\r\n return decodeURIComponent(trimmed.slice(separator + 1));\r\n }\r\n\r\n return null;\r\n}\r\n","import { InjectionToken } from '@angular/core';\r\n\r\nimport { readCookie } from './read-cookie';\r\n\r\nexport interface PosApiConfig {\r\n /** Origin for HeadlessAPI. Empty string when the host app proxies `/api`. */\r\n readonly apiBaseUrl: string;\r\n /** Cookie holding the Portal Bearer token (paste in local dev). */\r\n readonly tokenCookieName: string;\r\n /** Cookie holding the shop id sent as `Shop-Context`. */\r\n readonly shopContextCookieName: string;\r\n readonly getAccessToken?: () => string | null;\r\n readonly getShopContext?: () => string | null;\r\n}\r\n\r\nexport const DEFAULT_POS_API_CONFIG: PosApiConfig = {\r\n apiBaseUrl: '',\r\n tokenCookieName: 'portalApiToken',\r\n shopContextCookieName: 'contextShopId',\r\n};\r\n\r\nexport const POS_API_CONFIG = new InjectionToken<PosApiConfig>('POS_API_CONFIG', {\r\n providedIn: 'root',\r\n factory: () => DEFAULT_POS_API_CONFIG,\r\n});\r\n\r\nexport function readAccessToken(config: PosApiConfig): string | null {\r\n return config.getAccessToken?.() ?? readCookie(config.tokenCookieName);\r\n}\r\n\r\nexport function readShopContext(config: PosApiConfig): string | null {\r\n return config.getShopContext?.() ?? readCookie(config.shopContextCookieName);\r\n}\r\n","import { HttpInterceptorFn } from '@angular/common/http';\r\nimport { inject } from '@angular/core';\r\n\r\nimport {\r\n POS_API_CONFIG,\r\n readAccessToken,\r\n readShopContext,\r\n} from './pos-api-config';\r\n\r\nfunction joinUrl(baseUrl: string, path: string): string {\r\n if (!baseUrl || /^https?:\\/\\//i.test(path)) {\r\n return path;\r\n }\r\n\r\n const origin = baseUrl.replace(/\\/+$/, '');\r\n const suffix = path.replace(/^\\/+/, '');\r\n return `${origin}/${suffix}`;\r\n}\r\n\r\n/** Attaches Bearer + Shop-Context from cookies (or host overrides). */\r\nexport const posApiInterceptor: HttpInterceptorFn = (req, next) => {\r\n const config = inject(POS_API_CONFIG);\r\n const token = readAccessToken(config);\r\n const shopContext = readShopContext(config);\r\n\r\n let headers = req.headers;\r\n if (token && !headers.has('Authorization')) {\r\n headers = headers.set('Authorization', `Bearer ${token}`);\r\n }\r\n if (shopContext && !headers.has('Shop-Context')) {\r\n headers = headers.set('Shop-Context', shopContext);\r\n }\r\n\r\n return next(\r\n req.clone({\r\n url: joinUrl(config.apiBaseUrl, req.url),\r\n headers,\r\n }),\r\n );\r\n};\r\n","import { HttpClient, HttpErrorResponse } from '@angular/common/http';\r\nimport { inject, Injectable } from '@angular/core';\r\nimport { catchError, from, Observable, switchMap, throwError } from 'rxjs';\r\n\r\n/** HeadlessAPI clerk payload. Password check is a stub until ID-647. */\r\ninterface ClerkRecord {\r\n identifier?: number;\r\n firstName?: string;\r\n lastName?: string;\r\n password?: string | null;\r\n languageCode?: string;\r\n clerkNumber?: string;\r\n isManager?: boolean;\r\n}\r\n\r\nexport interface ClerkSession {\r\n readonly clerkNumber: string;\r\n readonly displayName: string;\r\n readonly languageCode: string;\r\n readonly isManager: boolean;\r\n}\r\n\r\nexport class ClerkAuthError extends Error {\r\n override readonly name = 'ClerkAuthError';\r\n\r\n constructor(message: string) {\r\n super(message);\r\n }\r\n}\r\n\r\nconst SHA256_HEX = /^[0-9a-f]{64}$/i;\r\n\r\nfunction displayName(clerk: ClerkRecord, clerkNumber: string): string {\r\n const name = `${clerk.firstName ?? ''} ${clerk.lastName ?? ''}`.trim();\r\n return name || clerk.clerkNumber || clerkNumber;\r\n}\r\n\r\n/** HeadlessPOS `SvcClerkService.validateClerk`: SHA-256 of UTF-16 `${identifier}.${pin}`. */\r\nasync function hashClerkPin(identifier: number | undefined, pin: string): Promise<string> {\r\n const message = `${identifier}.${pin}`;\r\n const buffer = new ArrayBuffer(message.length * 2);\r\n const utf16 = new Uint16Array(buffer);\r\n for (let i = 0; i < message.length; i++) {\r\n utf16[i] = message.charCodeAt(i);\r\n }\r\n\r\n const digest = await crypto.subtle.digest('SHA-256', buffer);\r\n return Array.from(new Uint8Array(digest))\r\n .map((byte) => byte.toString(16).padStart(2, '0'))\r\n .join('')\r\n .toUpperCase();\r\n}\r\n\r\nasync function passwordsMatch(submitted: string, clerk: ClerkRecord): Promise<boolean> {\r\n const stored = clerk.password ?? '';\r\n if (SHA256_HEX.test(stored)) {\r\n const hash = await hashClerkPin(clerk.identifier, submitted);\r\n return hash === stored.toUpperCase();\r\n }\r\n\r\n return submitted === stored;\r\n}\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ClerkAuthService {\r\n private readonly http = inject(HttpClient);\r\n\r\n /**\r\n * Looks up the clerk and compares the keypad password in this service.\r\n * Hashed passwords use the HeadlessPOS SHA-256 check. Not a dedicated\r\n * sign-in endpoint — replace when ID-647 / PosIdentity lands.\r\n */\r\n signIn(clerkNumber: string, password: string): Observable<ClerkSession> {\r\n const number = clerkNumber.trim();\r\n if (!number) {\r\n return throwError(() => new ClerkAuthError('Invalid clerk or password'));\r\n }\r\n\r\n return this.http.get<ClerkRecord>(`/api/v1.0/clerks/${encodeURIComponent(number)}`).pipe(\r\n switchMap((clerk) => from(this.toSession(clerk, number, password))),\r\n catchError((error: unknown) => {\r\n if (error instanceof ClerkAuthError) {\r\n return throwError(() => error);\r\n }\r\n\r\n if (error instanceof HttpErrorResponse) {\r\n if (error.status === 401) {\r\n return throwError(\r\n () =>\r\n new ClerkAuthError(\r\n 'API token missing or expired. Paste portalApiToken into cookies.',\r\n ),\r\n );\r\n }\r\n\r\n if (error.status === 404) {\r\n return throwError(() => new ClerkAuthError('Invalid clerk or password'));\r\n }\r\n }\r\n\r\n return throwError(() => new ClerkAuthError('Unable to sign in'));\r\n }),\r\n );\r\n }\r\n\r\n private async toSession(\r\n clerk: ClerkRecord,\r\n clerkNumber: string,\r\n password: string,\r\n ): Promise<ClerkSession> {\r\n if (!(await passwordsMatch(password, clerk))) {\r\n throw new ClerkAuthError('Invalid clerk or password');\r\n }\r\n\r\n return {\r\n clerkNumber: clerk.clerkNumber || clerkNumber,\r\n displayName: displayName(clerk, clerkNumber),\r\n languageCode: clerk.languageCode || 'en',\r\n isManager: clerk.isManager === true,\r\n };\r\n }\r\n}\r\n","import { HttpClient } from '@angular/common/http';\r\nimport { inject, Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { PosStateEnvelope } from './pos-state-envelope';\r\n\r\nexport interface AddItemCommand {\r\n readonly basketId: string;\r\n readonly sku: string;\r\n readonly qty: number;\r\n}\r\n\r\nexport interface ChangeQuantityCommand {\r\n readonly basketId: string;\r\n readonly lineId: number;\r\n readonly qty: number;\r\n}\r\n\r\nexport interface ClearBasketCommand {\r\n readonly basketId: string;\r\n}\r\n\r\nexport interface TenderCashCommand {\r\n readonly basketId: string;\r\n readonly amount: number;\r\n}\r\n\r\nexport interface NewSaleCommand {\r\n readonly basketId: string;\r\n}\r\n\r\nfunction idempotencyKey(): string {\r\n return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(16).slice(2)}`;\r\n}\r\n\r\n/**\r\n * Thin HTTP client for open-till sale commands (command in → PosStateEnvelope out).\r\n *\r\n * Keep as one client while the surface is small. When basket, tender, and sale\r\n * lifecycle each grow their own handful of methods, split by subdomain, e.g.:\r\n * - basket: addItem / changeQuantity / clearBasket (+ discounts, modifiers, …)\r\n * - tender: tenderCash (+ card, void payment, …)\r\n * - sale: newSale (+ suspend, recall, …)\r\n * Extract is cheap; avoid splitting early into near-empty clients.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class PosCommandsClient {\r\n private readonly http = inject(HttpClient);\r\n\r\n addItem(\r\n command: AddItemCommand,\r\n key = idempotencyKey(),\r\n ): Observable<PosStateEnvelope> {\r\n return this.http.post<PosStateEnvelope>('/api/v1.0/pos/commands/add-item', command, {\r\n headers: { 'Idempotency-Key': key },\r\n });\r\n }\r\n\r\n changeQuantity(\r\n command: ChangeQuantityCommand,\r\n key = idempotencyKey(),\r\n ): Observable<PosStateEnvelope> {\r\n return this.http.post<PosStateEnvelope>(\r\n '/api/v1.0/pos/commands/change-quantity',\r\n command,\r\n { headers: { 'Idempotency-Key': key } },\r\n );\r\n }\r\n\r\n clearBasket(\r\n command: ClearBasketCommand,\r\n key = idempotencyKey(),\r\n ): Observable<PosStateEnvelope> {\r\n return this.http.post<PosStateEnvelope>(\r\n '/api/v1.0/pos/commands/clear-basket',\r\n command,\r\n { headers: { 'Idempotency-Key': key } },\r\n );\r\n }\r\n\r\n tenderCash(\r\n command: TenderCashCommand,\r\n key = idempotencyKey(),\r\n ): Observable<PosStateEnvelope> {\r\n return this.http.post<PosStateEnvelope>(\r\n '/api/v1.0/pos/commands/tender-cash',\r\n command,\r\n { headers: { 'Idempotency-Key': key } },\r\n );\r\n }\r\n\r\n newSale(\r\n command: NewSaleCommand,\r\n key = idempotencyKey(),\r\n ): Observable<PosStateEnvelope> {\r\n return this.http.post<PosStateEnvelope>(\r\n '/api/v1.0/pos/commands/new-sale',\r\n command,\r\n { headers: { 'Idempotency-Key': key } },\r\n );\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -323,13 +323,13 @@ class PosTender {
323
323
  this.action.emit({ type: 'tender.cash', amount });
324
324
  }
325
325
  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;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-tender__panel{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;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{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__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__key{min-height:var(--pos-keypad-size-md)}.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 });
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 });
327
327
  }
328
328
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: PosTender, decorators: [{
329
329
  type: Component,
330
330
  args: [{ selector: 'pos-tender', changeDetection: ChangeDetectionStrategy.OnPush, host: {
331
331
  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;color:var(--pos-color-text);font-family:var(--pos-font-family);font-size:var(--pos-font-size-md)}.pos-tender__panel{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;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{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__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__key{min-height:var(--pos-keypad-size-md)}.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"] }]
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
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"] }] } });
334
334
 
335
335
  const EMPTY_TOTALS = {
@@ -851,10 +851,10 @@ function lookupPosTokens(variables) {
851
851
 
852
852
  const TOKEN_DECL = /(--pos-[a-z0-9-]+)\s*:\s*([^;}{]+)/gi;
853
853
  const POS_THEME_CSS_FILENAME = 'pos-theme.css';
854
- const THEME_CSS_HEADER = `/**
855
- * Adaptive POS theme
856
- * Generated by <pos-tokens>. Load after @retalia/pos-components styles.
857
- * Package defaults are unchanged; this file only overrides --pos-* on :root.
854
+ const THEME_CSS_HEADER = `/**
855
+ * Adaptive POS theme
856
+ * Generated by <pos-tokens>. Load after @retalia/pos-components styles.
857
+ * Package defaults are unchanged; this file only overrides --pos-* on :root.
858
858
  */`;
859
859
  function normalizePosTokenValue(kind, value) {
860
860
  const trimmed = value.trim().replace(/\/\*[\s\S]*?\*\//g, '').trim();
@@ -1 +1 @@
1
- {"version":3,"file":"retalia-pos-components.mjs","sources":["../../../projects/pos-components/src/lib/login/pos-login.ts","../../../projects/pos-components/src/lib/login/pos-login.html","../../../projects/pos-components/src/lib/basket/pos-basket.ts","../../../projects/pos-components/src/lib/basket/pos-basket.html","../../../projects/pos-components/src/lib/item-entry/pos-item-entry.ts","../../../projects/pos-components/src/lib/item-entry/pos-item-entry.html","../../../projects/pos-components/src/lib/tender/pos-tender.ts","../../../projects/pos-components/src/lib/tender/pos-tender.html","../../../projects/pos-components/src/lib/receipt/pos-receipt.ts","../../../projects/pos-components/src/lib/receipt/pos-receipt.html","../../../projects/pos-components/src/lib/tokens/pos-token-catalog.ts","../../../projects/pos-components/src/lib/tokens/pos-theme-css.ts","../../../projects/pos-components/src/lib/tokens/pos-tokens.ts","../../../projects/pos-components/src/lib/tokens/pos-tokens.html","../../../projects/pos-components/src/public-api.ts","../../../projects/pos-components/src/retalia-pos-components.ts"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\n\r\nexport type PosLoginIntent =\r\n | { readonly type: 'login.key'; readonly key: string }\r\n | { readonly type: 'login.backspace' }\r\n | { readonly type: 'login.next'; readonly clerkNumber: string }\r\n | { readonly type: 'login.submit'; readonly clerkNumber: string; readonly password: string }\r\n | { readonly type: 'login.back' };\r\n\r\n/** Display-only login/session state from the host envelope — not an API DTO. */\r\nexport type PosLoginSessionStatus = 'signedOut' | 'busy' | 'signedIn';\r\n\r\nexport interface PosLoginSessionState {\r\n readonly status: PosLoginSessionStatus;\r\n readonly displayName?: string;\r\n}\r\n\r\nconst DEFAULT_SESSION: PosLoginSessionState = { status: 'signedOut' };\r\n\r\ntype LoginStage = 'clerkNumber' | 'password';\r\n\r\nconst KEYPAD_ROWS: readonly (readonly string[])[] = [\r\n ['1', '2', '3'],\r\n ['4', '5', '6'],\r\n ['7', '8', '9'],\r\n ['0', '.', '←'],\r\n];\r\n\r\n@Component({\r\n selector: 'pos-login',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-login.html',\r\n styleUrl: './pos-login.scss',\r\n host: {\r\n class: 'pos-login',\r\n },\r\n})\r\nexport class PosLogin {\r\n readonly errorMessage = input('');\r\n readonly session = input<PosLoginSessionState>(DEFAULT_SESSION);\r\n\r\n readonly titleClerkNumber = input('Enter Clerk Number');\r\n readonly titleClerkPassword = input('Enter Clerk Password');\r\n readonly nextLabel = input('Next');\r\n readonly loginLabel = input('Login');\r\n\r\n readonly action = output<PosLoginIntent>();\r\n\r\n protected readonly keypadRows = KEYPAD_ROWS;\r\n protected readonly inputValue = signal('');\r\n protected readonly stage = signal<LoginStage>('clerkNumber');\r\n private readonly clerkNumber = signal('');\r\n\r\n protected readonly title = computed(() =>\r\n this.stage() === 'clerkNumber'\r\n ? this.titleClerkNumber()\r\n : this.titleClerkPassword(),\r\n );\r\n\r\n protected readonly maskInput = computed(() => this.stage() === 'password');\r\n\r\n protected readonly showBack = computed(() => this.stage() === 'password');\r\n\r\n protected readonly primaryLabel = computed(() =>\r\n this.stage() === 'password' ? this.loginLabel() : this.nextLabel(),\r\n );\r\n\r\n protected readonly primaryEnabled = computed(\r\n () => this.inputValue().length > 0 && !this.interactionLocked(),\r\n );\r\n\r\n protected readonly interactionLocked = computed(() => {\r\n const status = this.session().status;\r\n return status === 'busy' || status === 'signedIn';\r\n });\r\n\r\n protected readonly sessionStatusText = computed(() => {\r\n const current = this.session();\r\n if (current.status === 'busy') {\r\n return 'Signing in…';\r\n }\r\n if (current.status === 'signedIn') {\r\n return current.displayName\r\n ? `Signed in as ${current.displayName}`\r\n : 'Signed in';\r\n }\r\n return '';\r\n });\r\n\r\n protected onKeypad(key: string): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n if (key === '←') {\r\n this.inputValue.update((value) => value.slice(0, -1));\r\n this.action.emit({ type: 'login.backspace' });\r\n return;\r\n }\r\n\r\n if (this.inputValue().length >= 12) {\r\n return;\r\n }\r\n\r\n this.inputValue.update((value) => value + key);\r\n this.action.emit({ type: 'login.key', key });\r\n }\r\n\r\n protected onPrimary(): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n const value = this.inputValue();\r\n if (!value) {\r\n return;\r\n }\r\n\r\n if (this.stage() === 'clerkNumber') {\r\n this.clerkNumber.set(value);\r\n this.inputValue.set('');\r\n this.stage.set('password');\r\n this.action.emit({ type: 'login.next', clerkNumber: value });\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'login.submit',\r\n clerkNumber: this.clerkNumber(),\r\n password: value,\r\n });\r\n }\r\n\r\n protected onBack(): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n this.inputValue.set(this.clerkNumber());\r\n this.stage.set('clerkNumber');\r\n this.action.emit({ type: 'login.back' });\r\n }\r\n}\r\n","<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=\"· · · ·\"\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 === '←' || 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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n} from '@angular/core';\r\n\r\nexport type PosBasketIntent =\r\n | {\r\n readonly type: 'basket.changeQuantity';\r\n readonly lineId: number;\r\n readonly qty: number;\r\n }\r\n | { readonly type: 'basket.voidLine'; readonly lineId: number }\r\n | { readonly type: 'basket.clear' };\r\n\r\n/** Display-only VAT from the host envelope — not calculated here. */\r\nexport interface PosBasketVat {\r\n readonly rate: number;\r\n readonly amount: number;\r\n readonly included: boolean;\r\n}\r\n\r\n/** Display-only basket line from the host envelope — not an API DTO. */\r\nexport interface PosBasketLine {\r\n readonly lineId: number;\r\n readonly sku: string;\r\n readonly name: string;\r\n readonly qty: number;\r\n readonly unitPrice: number;\r\n readonly lineTotal: number;\r\n readonly vat: PosBasketVat;\r\n readonly struckThrough: boolean;\r\n}\r\n\r\n/** Display-only totals from the host envelope — not calculated here. */\r\nexport interface PosBasketTotals {\r\n readonly gross: number;\r\n readonly net: number;\r\n readonly vat: number;\r\n readonly discount: number;\r\n readonly due: number;\r\n readonly currency: string;\r\n}\r\n\r\nconst EMPTY_TOTALS: PosBasketTotals = {\r\n gross: 0,\r\n net: 0,\r\n vat: 0,\r\n discount: 0,\r\n due: 0,\r\n currency: 'EUR',\r\n};\r\n\r\n@Component({\r\n selector: 'pos-basket',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-basket.html',\r\n styleUrl: './pos-basket.scss',\r\n host: {\r\n class: 'pos-basket',\r\n },\r\n})\r\nexport class PosBasket {\r\n readonly lines = input<readonly PosBasketLine[]>([]);\r\n readonly totals = input<PosBasketTotals>(EMPTY_TOTALS);\r\n readonly disabled = input(false);\r\n\r\n readonly title = input('Basket');\r\n readonly emptyMessage = input('Basket is empty');\r\n readonly clearLabel = input('Clear basket');\r\n\r\n readonly action = output<PosBasketIntent>();\r\n\r\n protected readonly hasLines = computed(() => this.lines().length > 0);\r\n\r\n protected readonly canClear = computed(\r\n () => this.hasLines() && !this.disabled(),\r\n );\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.totals().currency || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected canChangeQuantity(line: PosBasketLine): boolean {\r\n return !this.disabled() && !line.struckThrough;\r\n }\r\n\r\n protected canDecrement(line: PosBasketLine): boolean {\r\n return this.canChangeQuantity(line) && line.qty > 1;\r\n }\r\n\r\n protected canVoid(line: PosBasketLine): boolean {\r\n return this.canChangeQuantity(line);\r\n }\r\n\r\n protected onIncrement(line: PosBasketLine): void {\r\n if (!this.canChangeQuantity(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'basket.changeQuantity',\r\n lineId: line.lineId,\r\n qty: line.qty + 1,\r\n });\r\n }\r\n\r\n protected onDecrement(line: PosBasketLine): void {\r\n if (!this.canDecrement(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'basket.changeQuantity',\r\n lineId: line.lineId,\r\n qty: line.qty - 1,\r\n });\r\n }\r\n\r\n protected onVoid(line: PosBasketLine): void {\r\n if (!this.canVoid(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'basket.voidLine', lineId: line.lineId });\r\n }\r\n\r\n protected onClear(): void {\r\n if (!this.canClear()) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'basket.clear' });\r\n }\r\n}\r\n","<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 −\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","import {\r\n afterNextRender,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n ElementRef,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n} from '@angular/core';\r\n\r\nexport type PosItemEntryIntent =\r\n | { readonly type: 'itemEntry.submit'; readonly reference: string };\r\n\r\n@Component({\r\n selector: 'pos-item-entry',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-item-entry.html',\r\n styleUrl: './pos-item-entry.scss',\r\n host: {\r\n class: 'pos-item-entry',\r\n },\r\n})\r\nexport class PosItemEntry {\r\n readonly disabled = input(false);\r\n readonly errorMessage = input('');\r\n readonly autofocus = input(true);\r\n\r\n readonly label = input('Item');\r\n readonly placeholder = input('Scan or enter item');\r\n readonly addLabel = input('Add');\r\n\r\n readonly action = output<PosItemEntryIntent>();\r\n\r\n private readonly itemInput = viewChild<ElementRef<HTMLInputElement>>('itemInput');\r\n\r\n protected readonly reference = signal('');\r\n\r\n protected readonly canSubmit = computed(\r\n () => this.reference().trim().length > 0 && !this.disabled(),\r\n );\r\n\r\n constructor() {\r\n afterNextRender(() => {\r\n if (this.autofocus() && !this.disabled()) {\r\n this.focusInput();\r\n }\r\n });\r\n }\r\n\r\n protected onInput(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof HTMLInputElement)) {\r\n return;\r\n }\r\n\r\n this.reference.set(target.value);\r\n }\r\n\r\n protected onSubmit(event: Event): void {\r\n event.preventDefault();\r\n\r\n if (this.disabled()) {\r\n return;\r\n }\r\n\r\n const reference = this.reference().trim();\r\n if (!reference) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'itemEntry.submit', reference });\r\n this.reference.set('');\r\n this.focusInput();\r\n }\r\n\r\n private focusInput(): void {\r\n this.itemInput()?.nativeElement.focus();\r\n }\r\n}\r\n","<section\r\n class=\"pos-item-entry__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <form class=\"pos-item-entry__form\" (submit)=\"onSubmit($event)\">\r\n <label class=\"pos-item-entry__field\">\r\n <span class=\"pos-item-entry__label\">{{ label() }}</span>\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 (input)=\"onInput($event)\"\r\n />\r\n </label>\r\n\r\n <button\r\n type=\"submit\"\r\n class=\"pos-item-entry__add\"\r\n [class.pos-item-entry__add--disabled]=\"!canSubmit()\"\r\n [disabled]=\"!canSubmit()\"\r\n >\r\n {{ addLabel() }}\r\n </button>\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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\n\r\nexport type PosTenderIntent =\r\n | {\r\n readonly type: 'tender.cash';\r\n readonly amount: number;\r\n };\r\n\r\nconst KEYPAD_ROWS: readonly (readonly string[])[] = [\r\n ['1', '2', '3'],\r\n ['4', '5', '6'],\r\n ['7', '8', '9'],\r\n ['0', '.', '←'],\r\n];\r\n\r\nconst MAX_WHOLE_DIGITS = 8;\r\n\r\nfunction parseCashAmount(raw: string): number | null {\r\n if (!raw) {\r\n return null;\r\n }\r\n\r\n const amount = Number(raw);\r\n if (!Number.isFinite(amount) || amount <= 0) {\r\n return null;\r\n }\r\n\r\n return Math.round(amount * 100) / 100;\r\n}\r\n\r\nfunction appendCashKey(current: string, key: string): string {\r\n if (key === '←') {\r\n return current.slice(0, -1);\r\n }\r\n\r\n if (key === '.') {\r\n if (current.includes('.')) {\r\n return current;\r\n }\r\n return current === '' ? '0.' : `${current}.`;\r\n }\r\n\r\n if (!/^\\d$/.test(key)) {\r\n return current;\r\n }\r\n\r\n if (current === '0') {\r\n return key;\r\n }\r\n\r\n const [whole = '', fraction] = current.split('.');\r\n if (fraction !== undefined) {\r\n if (fraction.length >= 2) {\r\n return current;\r\n }\r\n return current + key;\r\n }\r\n\r\n const significant = whole.replace(/^0+/, '');\r\n if (significant.length >= MAX_WHOLE_DIGITS) {\r\n return current;\r\n }\r\n\r\n return current + key;\r\n}\r\n\r\n@Component({\r\n selector: 'pos-tender',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-tender.html',\r\n styleUrl: './pos-tender.scss',\r\n host: {\r\n class: 'pos-tender',\r\n },\r\n})\r\nexport class PosTender {\r\n /** Display-only amount due from the host envelope — not calculated here. */\r\n readonly amountDue = input(0);\r\n /** Display-only change due from the host envelope — not calculated here. */\r\n readonly changeDue = input<number | null>(null);\r\n readonly currency = input('EUR');\r\n readonly disabled = input(false);\r\n readonly errorMessage = input('');\r\n\r\n readonly title = input('Cash tender');\r\n readonly amountDueLabel = input('Amount due');\r\n readonly tenderedLabel = input('Amount tendered');\r\n readonly changeDueLabel = input('Change due');\r\n readonly tenderLabel = input('Tender cash');\r\n readonly processingLabel = input('Processing tender…');\r\n\r\n readonly action = output<PosTenderIntent>();\r\n\r\n protected readonly keypadRows = KEYPAD_ROWS;\r\n protected readonly amountInput = signal('');\r\n\r\n protected readonly parsedAmount = computed(() =>\r\n parseCashAmount(this.amountInput()),\r\n );\r\n\r\n protected readonly canTender = computed(\r\n () => this.parsedAmount() !== null && !this.disabled(),\r\n );\r\n\r\n protected readonly hasChangeDue = computed(() => this.changeDue() !== null);\r\n\r\n protected readonly displayTendered = computed(\r\n () => this.amountInput() || '0',\r\n );\r\n\r\n protected readonly statusText = computed(() => {\r\n if (this.disabled() && !this.hasChangeDue()) {\r\n return this.processingLabel();\r\n }\r\n return '';\r\n });\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.currency() || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected onKeypad(key: string): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n\r\n this.amountInput.update((value) => appendCashKey(value, key));\r\n }\r\n\r\n protected onTender(): void {\r\n if (!this.canTender()) {\r\n return;\r\n }\r\n\r\n const amount = this.parsedAmount();\r\n if (amount === null) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'tender.cash', amount });\r\n }\r\n}\r\n","<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 === '←' || key === '.'\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"key === '←' ? '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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n} from '@angular/core';\r\n\r\nexport interface PosReceiptIntent {\r\n readonly type: 'receipt.newSale';\r\n}\r\n\r\n/** Display-only VAT from the host envelope — not calculated here. */\r\nexport interface PosReceiptVat {\r\n readonly rate: number;\r\n readonly amount: number;\r\n readonly included: boolean;\r\n}\r\n\r\n/** Display-only receipt line from the host envelope — not an API DTO. */\r\nexport interface PosReceiptLine {\r\n readonly lineId: number;\r\n readonly sku: string;\r\n readonly name: string;\r\n readonly qty: number;\r\n readonly unitPrice: number;\r\n readonly lineTotal: number;\r\n readonly vat: PosReceiptVat;\r\n readonly struckThrough: boolean;\r\n}\r\n\r\n/** Display-only totals from the host envelope — not calculated here. */\r\nexport interface PosReceiptTotals {\r\n readonly gross: number;\r\n readonly net: number;\r\n readonly vat: number;\r\n readonly discount: number;\r\n readonly due: number;\r\n readonly currency: string;\r\n}\r\n\r\n/** Display-only tender from the host envelope — not calculated here. */\r\nexport interface PosReceiptPayment {\r\n readonly tender: string;\r\n readonly amount: number;\r\n readonly tendered: number;\r\n readonly change: number;\r\n readonly state: string;\r\n}\r\n\r\n/** Display-only document metadata from the host envelope. */\r\nexport interface PosReceiptDocument {\r\n readonly number: string;\r\n readonly receiptReady: boolean;\r\n}\r\n\r\nconst EMPTY_TOTALS: PosReceiptTotals = {\r\n gross: 0,\r\n net: 0,\r\n vat: 0,\r\n discount: 0,\r\n due: 0,\r\n currency: 'EUR',\r\n};\r\n\r\nconst EMPTY_DOCUMENT: PosReceiptDocument = {\r\n number: '',\r\n receiptReady: false,\r\n};\r\n\r\n@Component({\r\n selector: 'pos-receipt',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-receipt.html',\r\n styleUrl: './pos-receipt.scss',\r\n host: {\r\n class: 'pos-receipt',\r\n },\r\n})\r\nexport class PosReceipt {\r\n readonly lines = input<readonly PosReceiptLine[]>([]);\r\n readonly totals = input<PosReceiptTotals>(EMPTY_TOTALS);\r\n readonly payments = input<readonly PosReceiptPayment[]>([]);\r\n readonly document = input<PosReceiptDocument>(EMPTY_DOCUMENT);\r\n readonly disabled = input(false);\r\n\r\n readonly title = input('Receipt');\r\n readonly emptyMessage = input('No receipt lines');\r\n readonly preparingLabel = input('Preparing receipt…');\r\n readonly readyLabel = input('Receipt ready');\r\n readonly newSaleLabel = input('New sale');\r\n readonly tenderLabel = input('Tender');\r\n readonly amountLabel = input('Amount');\r\n readonly tenderedLabel = input('Tendered');\r\n readonly changeLabel = input('Change');\r\n\r\n readonly action = output<PosReceiptIntent>();\r\n\r\n protected readonly hasLines = computed(() => this.lines().length > 0);\r\n protected readonly hasPayments = computed(() => this.payments().length > 0);\r\n protected readonly hasDocumentNumber = computed(\r\n () => this.document().number.trim().length > 0,\r\n );\r\n\r\n protected readonly statusText = computed(() =>\r\n this.document().receiptReady\r\n ? this.readyLabel()\r\n : this.preparingLabel(),\r\n );\r\n\r\n protected readonly canStartNewSale = computed(() => !this.disabled());\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.totals().currency || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected onNewSale(): void {\r\n if (!this.canStartNewSale()) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'receipt.newSale' });\r\n }\r\n}\r\n","<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","/**\n * Theme-lab catalog. Default values must stay in sync with `styles/tokens.css`.\n * The lab never writes that file; edits are live overrides only.\n */\nexport type PosTokenKind =\n | 'color'\n | 'length'\n | 'font-family'\n | 'font-weight'\n | 'other';\n\nexport type PosTokenGroup = 'color' | 'radius' | 'space' | 'type' | 'control';\n\nexport type PosTokenPreview =\n | 'color'\n | 'radius'\n | 'space'\n | 'font-size'\n | 'font-family'\n | 'font-weight'\n | 'letter-spacing'\n | 'size';\n\nexport interface PosTokenSwatch {\n readonly name: string;\n readonly variable: string;\n}\n\nexport interface PosTokenDefinition extends PosTokenSwatch {\n readonly kind: PosTokenKind;\n readonly group: PosTokenGroup;\n readonly preview: PosTokenPreview;\n readonly defaultValue: string;\n}\n\nexport interface PosTokenSample {\n readonly id: string;\n readonly label: string;\n readonly variables: readonly string[];\n}\n\nexport const POS_TOKEN_CATALOG: readonly PosTokenDefinition[] = [\n {\n name: 'Primary',\n variable: '--pos-color-primary',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#c9b5f0',\n },\n {\n name: 'On primary',\n variable: '--pos-color-on-primary',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'Success',\n variable: '--pos-color-success',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#16dbcc',\n },\n {\n name: 'On success',\n variable: '--pos-color-on-success',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'Danger',\n variable: '--pos-color-danger',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#fe5c73',\n },\n {\n name: 'On danger',\n variable: '--pos-color-on-danger',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#ffffff',\n },\n {\n name: 'Secondary',\n variable: '--pos-color-secondary',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#16dbcc',\n },\n {\n name: 'Warning',\n variable: '--pos-color-warning',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#f0ad4e',\n },\n {\n name: 'Text',\n variable: '--pos-color-text',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'Text muted',\n variable: '--pos-color-text-muted',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#999999',\n },\n {\n name: 'Surface',\n variable: '--pos-color-surface',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#ffffff',\n },\n {\n name: 'Surface muted',\n variable: '--pos-color-surface-muted',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#f5f5f5',\n },\n {\n name: 'Panel',\n variable: '--pos-color-panel',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#f5f5f5',\n },\n {\n name: 'Panel elevated',\n variable: '--pos-color-panel-elevated',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#ffffff',\n },\n {\n name: 'Ink',\n variable: '--pos-color-ink',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'Border',\n variable: '--pos-color-border',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#dddddd',\n },\n {\n name: 'Disabled',\n variable: '--pos-color-disabled',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#dddddd',\n },\n {\n name: 'On disabled',\n variable: '--pos-color-on-disabled',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#999999',\n },\n {\n name: 'Display',\n variable: '--pos-color-display',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'On display',\n variable: '--pos-color-on-display',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#ffffff',\n },\n {\n name: 'Key',\n variable: '--pos-color-key',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#ffffff',\n },\n {\n name: 'Key border',\n variable: '--pos-color-key-border',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#dddddd',\n },\n {\n name: 'Key active',\n variable: '--pos-color-key-active',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#c9b5f0',\n },\n {\n name: 'On key active',\n variable: '--pos-color-on-key-active',\n kind: 'color',\n group: 'color',\n preview: 'color',\n defaultValue: '#333333',\n },\n {\n name: 'Radius sm',\n variable: '--pos-radius-sm',\n kind: 'length',\n group: 'radius',\n preview: 'radius',\n defaultValue: '4px',\n },\n {\n name: 'Radius md',\n variable: '--pos-radius-md',\n kind: 'length',\n group: 'radius',\n preview: 'radius',\n defaultValue: '8px',\n },\n {\n name: 'Radius lg',\n variable: '--pos-radius-lg',\n kind: 'length',\n group: 'radius',\n preview: 'radius',\n defaultValue: '12px',\n },\n {\n name: 'Radius pill',\n variable: '--pos-radius-pill',\n kind: 'length',\n group: 'radius',\n preview: 'radius',\n defaultValue: '9999px',\n },\n {\n name: 'Space xs',\n variable: '--pos-space-xs',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '4px',\n },\n {\n name: 'Space sm',\n variable: '--pos-space-sm',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '8px',\n },\n {\n name: 'Space md',\n variable: '--pos-space-md',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '12px',\n },\n {\n name: 'Space lg',\n variable: '--pos-space-lg',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '16px',\n },\n {\n name: 'Space xl',\n variable: '--pos-space-xl',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '24px',\n },\n {\n name: 'Space 2xl',\n variable: '--pos-space-2xl',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '40px',\n },\n {\n name: 'Space 3xl',\n variable: '--pos-space-3xl',\n kind: 'length',\n group: 'space',\n preview: 'space',\n defaultValue: '56px',\n },\n {\n name: 'Font family',\n variable: '--pos-font-family',\n kind: 'font-family',\n group: 'type',\n preview: 'font-family',\n defaultValue:\n \"Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif\",\n },\n {\n name: 'Font family display',\n variable: '--pos-font-family-display',\n kind: 'font-family',\n group: 'type',\n preview: 'font-family',\n defaultValue:\n \"Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif\",\n },\n {\n name: 'Font size sm',\n variable: '--pos-font-size-sm',\n kind: 'length',\n group: 'type',\n preview: 'font-size',\n defaultValue: '0.8125rem',\n },\n {\n name: 'Font size md',\n variable: '--pos-font-size-md',\n kind: 'length',\n group: 'type',\n preview: 'font-size',\n defaultValue: '0.875rem',\n },\n {\n name: 'Font size lg',\n variable: '--pos-font-size-lg',\n kind: 'length',\n group: 'type',\n preview: 'font-size',\n defaultValue: '1.125rem',\n },\n {\n name: 'Font size xl',\n variable: '--pos-font-size-xl',\n kind: 'length',\n group: 'type',\n preview: 'font-size',\n defaultValue: '1.375rem',\n },\n {\n name: 'Font weight semibold',\n variable: '--pos-font-weight-semibold',\n kind: 'font-weight',\n group: 'type',\n preview: 'font-weight',\n defaultValue: '600',\n },\n {\n name: 'Font weight bold',\n variable: '--pos-font-weight-bold',\n kind: 'font-weight',\n group: 'type',\n preview: 'font-weight',\n defaultValue: '700',\n },\n {\n name: 'Letter spacing display',\n variable: '--pos-letter-spacing-display',\n kind: 'length',\n group: 'type',\n preview: 'letter-spacing',\n defaultValue: '0.28em',\n },\n {\n name: 'Button min height',\n variable: '--pos-button-min-height',\n kind: 'length',\n group: 'control',\n preview: 'size',\n defaultValue: '48px',\n },\n {\n name: 'Keypad size',\n variable: '--pos-keypad-size',\n kind: 'length',\n group: 'control',\n preview: 'size',\n defaultValue: '3.25rem',\n },\n {\n name: 'Keypad size md',\n variable: '--pos-keypad-size-md',\n kind: 'length',\n group: 'control',\n preview: 'size',\n defaultValue: '3.75rem',\n },\n {\n name: 'Keypad size lg',\n variable: '--pos-keypad-size-lg',\n kind: 'length',\n group: 'control',\n preview: 'size',\n defaultValue: '4.25rem',\n },\n];\n\nexport const POS_TOKEN_DEFAULTS: Readonly<Record<string, string>> = Object.freeze(\n Object.fromEntries(\n POS_TOKEN_CATALOG.map((token) => [token.variable, token.defaultValue]),\n ),\n);\n\nexport const POS_TOKEN_BY_VARIABLE: ReadonlyMap<string, PosTokenDefinition> =\n new Map(POS_TOKEN_CATALOG.map((token) => [token.variable, token]));\n\nexport const POS_TOKEN_SAMPLES: readonly PosTokenSample[] = [\n {\n id: 'primary',\n label: 'Primary',\n variables: [\n '--pos-color-primary',\n '--pos-color-on-primary',\n '--pos-radius-md',\n '--pos-button-min-height',\n '--pos-font-weight-bold',\n ],\n },\n {\n id: 'success',\n label: 'Success',\n variables: [\n '--pos-color-success',\n '--pos-color-on-success',\n '--pos-radius-md',\n '--pos-button-min-height',\n '--pos-font-weight-bold',\n ],\n },\n {\n id: 'danger',\n label: 'Danger',\n variables: [\n '--pos-color-danger',\n '--pos-color-on-danger',\n '--pos-radius-md',\n '--pos-button-min-height',\n '--pos-font-weight-bold',\n ],\n },\n {\n id: 'disabled',\n label: 'Disabled',\n variables: [\n '--pos-color-disabled',\n '--pos-color-on-disabled',\n '--pos-radius-md',\n '--pos-button-min-height',\n ],\n },\n {\n id: 'text',\n label: 'Body text',\n variables: [\n '--pos-color-text',\n '--pos-color-text-muted',\n '--pos-font-family',\n '--pos-font-size-md',\n ],\n },\n {\n id: 'error',\n label: 'Danger / error message',\n variables: ['--pos-color-danger', '--pos-font-weight-semibold'],\n },\n];\n\nexport function tokensInGroup(\n group: PosTokenGroup,\n): readonly PosTokenDefinition[] {\n return POS_TOKEN_CATALOG.filter((token) => token.group === group);\n}\n\nexport function lookupPosTokens(\n variables: readonly string[],\n): readonly PosTokenDefinition[] {\n return variables.flatMap((variable) => {\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\n return token ? [token] : [];\n });\n}\n","import {\n POS_TOKEN_BY_VARIABLE,\n POS_TOKEN_CATALOG,\n POS_TOKEN_DEFAULTS,\n type PosTokenKind,\n} from './pos-token-catalog';\n\nconst TOKEN_DECL = /(--pos-[a-z0-9-]+)\\s*:\\s*([^;}{]+)/gi;\n\nexport const POS_THEME_CSS_FILENAME = 'pos-theme.css';\n\nconst THEME_CSS_HEADER = `/**\n * Adaptive POS theme\n * Generated by <pos-tokens>. Load after @retalia/pos-components styles.\n * Package defaults are unchanged; this file only overrides --pos-* on :root.\n */`;\n\nexport function normalizePosTokenValue(\n kind: PosTokenKind,\n value: string,\n): string {\n const trimmed = value.trim().replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim();\n if (!trimmed) {\n return '';\n }\n\n if (kind === 'color') {\n const hex = parseCssHex(trimmed);\n if (hex) {\n return hex;\n }\n }\n\n return trimmed.replace(/\\s*!important$/i, '').trim();\n}\n\nexport function parseCssHex(value: string): string | null {\n const trimmed = value.trim();\n const short = /^#([0-9a-f]{3})$/i.exec(trimmed)?.[1];\n if (short && short.length === 3) {\n const [r, g, b] = short;\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n\n if (/^#[0-9a-f]{6}$/i.test(trimmed)) {\n return trimmed.toLowerCase();\n }\n\n return null;\n}\n\nexport function parsePosThemeCss(css: string): Readonly<Record<string, string>> {\n const result: Record<string, string> = {};\n\n for (const match of css.matchAll(TOKEN_DECL)) {\n const variable = match[1];\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\n if (!token) {\n continue;\n }\n\n const value = normalizePosTokenValue(token.kind, match[2] ?? '');\n if (value) {\n result[variable] = value;\n }\n }\n\n return result;\n}\n\nexport function resolvedPosTheme(\n overrides: Readonly<Record<string, string>>,\n): Readonly<Record<string, string>> {\n const resolved: Record<string, string> = { ...POS_TOKEN_DEFAULTS };\n for (const [variable, value] of Object.entries(overrides)) {\n if (variable in POS_TOKEN_DEFAULTS && value.trim()) {\n resolved[variable] = value;\n }\n }\n return resolved;\n}\n\nexport function overridesFromThemeValues(\n values: Readonly<Record<string, string>>,\n): Record<string, string> {\n const overrides: Record<string, string> = {};\n for (const [variable, value] of Object.entries(values)) {\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\n if (!token) {\n continue;\n }\n\n const normalized = normalizePosTokenValue(token.kind, value);\n if (normalized && normalized !== token.defaultValue) {\n overrides[variable] = normalized;\n }\n }\n return overrides;\n}\n\nexport function serializePosThemeCss(\n values: Readonly<Record<string, string>>,\n): string {\n const lines = POS_TOKEN_CATALOG.map((token) => {\n const value = values[token.variable] ?? token.defaultValue;\n return ` ${token.variable}: ${value};`;\n });\n\n return `${THEME_CSS_HEADER}\\n:root {\\n${lines.join('\\n')}\\n}\\n`;\n}\n\nexport function downloadTextFile(filename: string, contents: string): void {\n const blob = new Blob([contents], { type: 'text/css;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.rel = 'noopener';\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n signal,\r\n} from '@angular/core';\r\n\r\nimport {\r\n POS_TOKEN_BY_VARIABLE,\r\n POS_TOKEN_SAMPLES,\r\n type PosTokenDefinition,\r\n type PosTokenSwatch,\r\n lookupPosTokens,\r\n tokensInGroup,\r\n} from './pos-token-catalog';\r\nimport {\r\n POS_THEME_CSS_FILENAME,\r\n downloadTextFile,\r\n normalizePosTokenValue,\r\n overridesFromThemeValues,\r\n parseCssHex,\r\n parsePosThemeCss,\r\n resolvedPosTheme,\r\n serializePosThemeCss,\r\n} from './pos-theme-css';\r\n\r\nexport type { PosTokenSwatch };\r\n\r\ninterface PosTokenSelection {\r\n readonly id: string;\r\n readonly title: string;\r\n readonly variables: readonly string[];\r\n}\r\n\r\n@Component({\r\n selector: 'pos-tokens',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-tokens.html',\r\n styleUrl: './pos-tokens.scss',\r\n host: {\r\n class: 'pos-tokens',\r\n '[style]': 'themeStyle()',\r\n '(keydown.escape)': 'clearSelection()',\r\n },\r\n})\r\nexport class PosTokens {\r\n protected readonly colorTokens = tokensInGroup('color');\r\n protected readonly radiusTokens = tokensInGroup('radius');\r\n protected readonly spaceTokens = tokensInGroup('space');\r\n protected readonly typeTokens = tokensInGroup('type');\r\n protected readonly controlTokens = tokensInGroup('control');\r\n\r\n private readonly overrides = signal<Record<string, string>>({});\r\n protected readonly selection = signal<PosTokenSelection | null>(null);\r\n protected readonly statusMessage = signal('');\r\n\r\n protected readonly selectedTokens = computed(() => {\r\n const selection = this.selection();\r\n return selection ? lookupPosTokens(selection.variables) : [];\r\n });\r\n\r\n protected readonly hasOverrides = computed(\r\n () => Object.keys(this.overrides()).length > 0,\r\n );\r\n\r\n protected readonly themeStyle = computed(() =>\r\n Object.entries(this.overrides())\r\n .map(([variable, value]) => `${variable}: ${value}`)\r\n .join('; '),\r\n );\r\n\r\n /** Complete :root CSS for the consuming POS. Package defaults are not written. */\r\n themeCss(): string {\r\n return serializePosThemeCss(resolvedPosTheme(this.overrides()));\r\n }\r\n\r\n /** Load a previously exported theme as live overrides. Does not mutate defaults. */\r\n loadThemeCss(css: string): void {\r\n const parsed = parsePosThemeCss(css);\r\n const knownCount = Object.keys(parsed).length;\r\n this.overrides.set(overridesFromThemeValues(parsed));\r\n\r\n if (knownCount === 0) {\r\n this.statusMessage.set('No --pos-* tokens found in that file.');\r\n return;\r\n }\r\n\r\n this.statusMessage.set(\r\n `Imported ${knownCount} tokens as live overrides. Package defaults are unchanged.`,\r\n );\r\n }\r\n\r\n resetTheme(): void {\r\n this.overrides.set({});\r\n this.statusMessage.set('Live overrides cleared. Package defaults restored in this lab.');\r\n }\r\n\r\n protected exportThemeFile(): void {\r\n downloadTextFile(POS_THEME_CSS_FILENAME, this.themeCss());\r\n this.statusMessage.set(\r\n `Downloaded ${POS_THEME_CSS_FILENAME}. Add it after the package stylesheet in the host POS.`,\r\n );\r\n }\r\n\r\n protected async onImportFile(event: Event): Promise<void> {\r\n const input = event.target;\r\n if (!(input instanceof HTMLInputElement) || !input.files?.length) {\r\n return;\r\n }\r\n\r\n const css = await input.files[0].text();\r\n this.loadThemeCss(css);\r\n input.value = '';\r\n }\r\n\r\n protected selectToken(token: PosTokenDefinition): void {\r\n this.selection.set({\r\n id: `token:${token.variable}`,\r\n title: token.name,\r\n variables: [token.variable],\r\n });\r\n }\r\n\r\n protected selectSample(sampleId: string): void {\r\n const sample = POS_TOKEN_SAMPLES.find((item) => item.id === sampleId);\r\n if (!sample) {\r\n return;\r\n }\r\n\r\n this.selection.set({\r\n id: `sample:${sample.id}`,\r\n title: sample.label,\r\n variables: sample.variables,\r\n });\r\n }\r\n\r\n protected clearSelection(): void {\r\n this.selection.set(null);\r\n }\r\n\r\n protected isTokenSelected(variable: string): boolean {\r\n const selection = this.selection();\r\n return selection?.id === `token:${variable}`;\r\n }\r\n\r\n protected isSampleSelected(sampleId: string): boolean {\r\n return this.selection()?.id === `sample:${sampleId}`;\r\n }\r\n\r\n protected isModified(variable: string): boolean {\r\n return variable in this.overrides();\r\n }\r\n\r\n protected currentValue(variable: string): string {\r\n return this.overrides()[variable] ?? POS_TOKEN_BY_VARIABLE.get(variable)?.defaultValue ?? '';\r\n }\r\n\r\n protected defaultValue(variable: string): string {\r\n return POS_TOKEN_BY_VARIABLE.get(variable)?.defaultValue ?? '';\r\n }\r\n\r\n protected colorInputValue(variable: string): string | null {\r\n return parseCssHex(this.currentValue(variable));\r\n }\r\n\r\n protected tokenFieldId(variable: string): string {\r\n return `pos-token-field-${variable.replace(/[^a-z0-9]+/gi, '-')}`;\r\n }\r\n\r\n protected onTokenInput(variable: string, event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof HTMLInputElement)) {\r\n return;\r\n }\r\n\r\n this.setTokenValue(variable, target.value);\r\n }\r\n\r\n protected resetToken(variable: string): void {\r\n this.overrides.update((current) => {\r\n if (!(variable in current)) {\r\n return current;\r\n }\r\n\r\n const next = { ...current };\r\n delete next[variable];\r\n return next;\r\n });\r\n }\r\n\r\n private setTokenValue(variable: string, raw: string): void {\r\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\r\n if (!token) {\r\n return;\r\n }\r\n\r\n const normalized = normalizePosTokenValue(token.kind, raw);\r\n this.overrides.update((current) => {\r\n const next = { ...current };\r\n if (!normalized || normalized === token.defaultValue) {\r\n delete next[variable];\r\n } else {\r\n next[variable] = normalized;\r\n }\r\n return next;\r\n });\r\n }\r\n}\r\n","<article class=\"pos-tokens__page\">\r\n <header class=\"pos-tokens__intro\">\r\n <p class=\"pos-tokens__kicker\">@retalia/pos-components</p>\r\n <h1 class=\"pos-tokens__title\">Design tokens</h1>\r\n <p class=\"pos-tokens__lede\">\r\n Click a sample or token to edit it. Changes are live overrides in this lab only —\r\n package defaults are never overwritten. Export a complete <code>:root</code> CSS\r\n file for the consuming POS, and import that file back later to resume editing.\r\n </p>\r\n <div class=\"pos-tokens__toolbar\">\r\n <input\r\n #importFile\r\n class=\"pos-tokens__file\"\r\n type=\"file\"\r\n accept=\".css,text/css\"\r\n (change)=\"onImportFile($event)\"\r\n />\r\n <button type=\"button\" class=\"pos-tokens__tool pos-tokens__tool--primary\" (click)=\"exportThemeFile()\">\r\n Export CSS\r\n </button>\r\n <button type=\"button\" class=\"pos-tokens__tool\" (click)=\"importFile.click()\">\r\n Import CSS\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__tool\"\r\n [disabled]=\"!hasOverrides()\"\r\n (click)=\"resetTheme()\"\r\n >\r\n Reset overrides\r\n </button>\r\n </div>\r\n <p class=\"pos-tokens__status\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</p>\r\n </header>\r\n\r\n <div class=\"pos-tokens__layout\">\r\n <div class=\"pos-tokens__gallery\">\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-samples\">\r\n <h2 id=\"pos-tokens-samples\" class=\"pos-tokens__heading\">In action</h2>\r\n <p class=\"pos-tokens__hint\">Click a control to edit the tokens it uses.</p>\r\n <div class=\"pos-tokens__samples\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('primary')\"\r\n [attr.aria-pressed]=\"isSampleSelected('primary')\"\r\n (click)=\"selectSample('primary')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--primary\">Primary</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('success')\"\r\n [attr.aria-pressed]=\"isSampleSelected('success')\"\r\n (click)=\"selectSample('success')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--success\">Success</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('danger')\"\r\n [attr.aria-pressed]=\"isSampleSelected('danger')\"\r\n (click)=\"selectSample('danger')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--danger\">Danger</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('disabled')\"\r\n [attr.aria-pressed]=\"isSampleSelected('disabled')\"\r\n (click)=\"selectSample('disabled')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--disabled\">Disabled</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample pos-tokens__sample--text\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('text')\"\r\n [attr.aria-pressed]=\"isSampleSelected('text')\"\r\n (click)=\"selectSample('text')\"\r\n >\r\n <span class=\"pos-tokens__sample-text\">\r\n Body text · <span class=\"pos-tokens__sample-muted\">muted</span>\r\n </span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample pos-tokens__sample--text\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('error')\"\r\n [attr.aria-pressed]=\"isSampleSelected('error')\"\r\n (click)=\"selectSample('error')\"\r\n >\r\n <span class=\"pos-tokens__sample-danger\">Danger / error message</span>\r\n </button>\r\n </div>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-colors\">\r\n <h2 id=\"pos-tokens-colors\" class=\"pos-tokens__heading\">Color</h2>\r\n <ul class=\"pos-tokens__swatch-grid\">\r\n @for (token of colorTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__chip\"\r\n [style.background]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-radius\">\r\n <h2 id=\"pos-tokens-radius\" class=\"pos-tokens__heading\">Radius</h2>\r\n <ul class=\"pos-tokens__radius-row\">\r\n @for (token of radiusTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__radius-box\"\r\n [style.border-radius]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-space\">\r\n <h2 id=\"pos-tokens-space\" class=\"pos-tokens__heading\">Space</h2>\r\n <ul class=\"pos-tokens__space-list\">\r\n @for (token of spaceTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick pos-tokens__pick--row\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__space-bar\"\r\n [style.width]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-type\">\r\n <h2 id=\"pos-tokens-type\" class=\"pos-tokens__heading\">Typography</h2>\r\n <ul class=\"pos-tokens__type-list\">\r\n @for (token of typeTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n @switch (token.preview) {\r\n @case ('font-family') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-family]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('font-size') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-size]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('font-weight') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-weight]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('letter-spacing') {\r\n <span\r\n class=\"pos-tokens__type-preview pos-tokens__type-preview--caps\"\r\n [style.letter-spacing]=\"'var(' + token.variable + ')'\"\r\n >\r\n Display\r\n </span>\r\n }\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-controls\">\r\n <h2 id=\"pos-tokens-controls\" class=\"pos-tokens__heading\">Controls</h2>\r\n <ul class=\"pos-tokens__control-list\">\r\n @for (token of controlTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick pos-tokens__pick--row\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__size-box\"\r\n [style.width]=\"'var(' + token.variable + ')'\"\r\n [style.height]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n </div>\r\n\r\n <aside class=\"pos-tokens__inspector\" aria-labelledby=\"pos-tokens-inspector-title\">\r\n <div class=\"pos-tokens__inspector-header\">\r\n <h2 id=\"pos-tokens-inspector-title\" class=\"pos-tokens__heading\">\r\n {{ selection()?.title ?? 'Theme editor' }}\r\n </h2>\r\n @if (selection()) {\r\n <button type=\"button\" class=\"pos-tokens__tool pos-tokens__tool--quiet\" (click)=\"clearSelection()\">\r\n Close\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (!selection()) {\r\n <p class=\"pos-tokens__hint\">\r\n Select a sample or token to change its values. Export writes a complete CSS\r\n file the host POS can load after the package stylesheet.\r\n </p>\r\n } @else {\r\n <ul class=\"pos-tokens__fields\">\r\n @for (token of selectedTokens(); track token.variable) {\r\n <li class=\"pos-tokens__field\">\r\n <label class=\"pos-tokens__field-label\" [attr.for]=\"tokenFieldId(token.variable)\">\r\n {{ token.name }}\r\n </label>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n <div class=\"pos-tokens__field-controls\">\r\n @if (token.kind === 'color') {\r\n @if (colorInputValue(token.variable); as hex) {\r\n <input\r\n class=\"pos-tokens__color\"\r\n type=\"color\"\r\n [value]=\"hex\"\r\n [attr.aria-label]=\"token.name + ' color'\"\r\n (input)=\"onTokenInput(token.variable, $event)\"\r\n />\r\n }\r\n }\r\n <input\r\n class=\"pos-tokens__value\"\r\n type=\"text\"\r\n [id]=\"tokenFieldId(token.variable)\"\r\n [value]=\"currentValue(token.variable)\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\"\r\n (input)=\"onTokenInput(token.variable, $event)\"\r\n />\r\n </div>\r\n <p class=\"pos-tokens__default\">\r\n Default\r\n <code>{{ defaultValue(token.variable) }}</code>\r\n </p>\r\n @if (isModified(token.variable)) {\r\n <button type=\"button\" class=\"pos-tokens__reset\" (click)=\"resetToken(token.variable)\">\r\n Reset to default\r\n </button>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </aside>\r\n </div>\r\n</article>\r\n","/*\r\n * Public API Surface of @retalia/pos-components\r\n */\r\n\r\nexport { PosLogin } from './lib/login/pos-login';\r\nexport type {\r\n PosLoginIntent,\r\n PosLoginSessionState,\r\n PosLoginSessionStatus,\r\n} from './lib/login/pos-login';\r\n\r\nexport { PosBasket } from './lib/basket/pos-basket';\r\nexport type {\r\n PosBasketIntent,\r\n PosBasketLine,\r\n PosBasketTotals,\r\n PosBasketVat,\r\n} from './lib/basket/pos-basket';\r\n\r\nexport { PosItemEntry } from './lib/item-entry/pos-item-entry';\r\nexport type { PosItemEntryIntent } from './lib/item-entry/pos-item-entry';\r\n\r\nexport { PosTender } from './lib/tender/pos-tender';\r\nexport type { PosTenderIntent } from './lib/tender/pos-tender';\r\n\r\nexport { PosReceipt } from './lib/receipt/pos-receipt';\r\nexport type {\r\n PosReceiptIntent,\r\n PosReceiptLine,\r\n PosReceiptTotals,\r\n PosReceiptVat,\r\n PosReceiptPayment,\r\n PosReceiptDocument,\r\n} from './lib/receipt/pos-receipt';\r\n\r\nexport { PosTokens } from './lib/tokens/pos-tokens';\r\nexport type { PosTokenSwatch } from './lib/tokens/pos-tokens';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["KEYPAD_ROWS","EMPTY_TOTALS"],"mappings":"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"}
1
+ {"version":3,"file":"retalia-pos-components.mjs","sources":["../../../projects/pos-components/src/lib/login/pos-login.ts","../../../projects/pos-components/src/lib/login/pos-login.html","../../../projects/pos-components/src/lib/basket/pos-basket.ts","../../../projects/pos-components/src/lib/basket/pos-basket.html","../../../projects/pos-components/src/lib/item-entry/pos-item-entry.ts","../../../projects/pos-components/src/lib/item-entry/pos-item-entry.html","../../../projects/pos-components/src/lib/tender/pos-tender.ts","../../../projects/pos-components/src/lib/tender/pos-tender.html","../../../projects/pos-components/src/lib/receipt/pos-receipt.ts","../../../projects/pos-components/src/lib/receipt/pos-receipt.html","../../../projects/pos-components/src/lib/tokens/pos-token-catalog.ts","../../../projects/pos-components/src/lib/tokens/pos-theme-css.ts","../../../projects/pos-components/src/lib/tokens/pos-tokens.ts","../../../projects/pos-components/src/lib/tokens/pos-tokens.html","../../../projects/pos-components/src/public-api.ts","../../../projects/pos-components/src/retalia-pos-components.ts"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\n\r\nexport type PosLoginIntent =\r\n | { readonly type: 'login.key'; readonly key: string }\r\n | { readonly type: 'login.backspace' }\r\n | { readonly type: 'login.next'; readonly clerkNumber: string }\r\n | { readonly type: 'login.submit'; readonly clerkNumber: string; readonly password: string }\r\n | { readonly type: 'login.back' };\r\n\r\n/** Display-only login/session state from the host envelope — not an API DTO. */\r\nexport type PosLoginSessionStatus = 'signedOut' | 'busy' | 'signedIn';\r\n\r\nexport interface PosLoginSessionState {\r\n readonly status: PosLoginSessionStatus;\r\n readonly displayName?: string;\r\n}\r\n\r\nconst DEFAULT_SESSION: PosLoginSessionState = { status: 'signedOut' };\r\n\r\ntype LoginStage = 'clerkNumber' | 'password';\r\n\r\nconst KEYPAD_ROWS: readonly (readonly string[])[] = [\r\n ['1', '2', '3'],\r\n ['4', '5', '6'],\r\n ['7', '8', '9'],\r\n ['0', '.', '←'],\r\n];\r\n\r\n@Component({\r\n selector: 'pos-login',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-login.html',\r\n styleUrl: './pos-login.scss',\r\n host: {\r\n class: 'pos-login',\r\n },\r\n})\r\nexport class PosLogin {\r\n readonly errorMessage = input('');\r\n readonly session = input<PosLoginSessionState>(DEFAULT_SESSION);\r\n\r\n readonly titleClerkNumber = input('Enter Clerk Number');\r\n readonly titleClerkPassword = input('Enter Clerk Password');\r\n readonly nextLabel = input('Next');\r\n readonly loginLabel = input('Login');\r\n\r\n readonly action = output<PosLoginIntent>();\r\n\r\n protected readonly keypadRows = KEYPAD_ROWS;\r\n protected readonly inputValue = signal('');\r\n protected readonly stage = signal<LoginStage>('clerkNumber');\r\n private readonly clerkNumber = signal('');\r\n\r\n protected readonly title = computed(() =>\r\n this.stage() === 'clerkNumber'\r\n ? this.titleClerkNumber()\r\n : this.titleClerkPassword(),\r\n );\r\n\r\n protected readonly maskInput = computed(() => this.stage() === 'password');\r\n\r\n protected readonly showBack = computed(() => this.stage() === 'password');\r\n\r\n protected readonly primaryLabel = computed(() =>\r\n this.stage() === 'password' ? this.loginLabel() : this.nextLabel(),\r\n );\r\n\r\n protected readonly primaryEnabled = computed(\r\n () => this.inputValue().length > 0 && !this.interactionLocked(),\r\n );\r\n\r\n protected readonly interactionLocked = computed(() => {\r\n const status = this.session().status;\r\n return status === 'busy' || status === 'signedIn';\r\n });\r\n\r\n protected readonly sessionStatusText = computed(() => {\r\n const current = this.session();\r\n if (current.status === 'busy') {\r\n return 'Signing in…';\r\n }\r\n if (current.status === 'signedIn') {\r\n return current.displayName\r\n ? `Signed in as ${current.displayName}`\r\n : 'Signed in';\r\n }\r\n return '';\r\n });\r\n\r\n protected onKeypad(key: string): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n if (key === '←') {\r\n this.inputValue.update((value) => value.slice(0, -1));\r\n this.action.emit({ type: 'login.backspace' });\r\n return;\r\n }\r\n\r\n if (this.inputValue().length >= 12) {\r\n return;\r\n }\r\n\r\n this.inputValue.update((value) => value + key);\r\n this.action.emit({ type: 'login.key', key });\r\n }\r\n\r\n protected onPrimary(): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n const value = this.inputValue();\r\n if (!value) {\r\n return;\r\n }\r\n\r\n if (this.stage() === 'clerkNumber') {\r\n this.clerkNumber.set(value);\r\n this.inputValue.set('');\r\n this.stage.set('password');\r\n this.action.emit({ type: 'login.next', clerkNumber: value });\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'login.submit',\r\n clerkNumber: this.clerkNumber(),\r\n password: value,\r\n });\r\n }\r\n\r\n protected onBack(): void {\r\n if (this.interactionLocked()) {\r\n return;\r\n }\r\n\r\n this.inputValue.set(this.clerkNumber());\r\n this.stage.set('clerkNumber');\r\n this.action.emit({ type: 'login.back' });\r\n }\r\n}\r\n","<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=\"· · · ·\"\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 === '←' || 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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n} from '@angular/core';\r\n\r\nexport type PosBasketIntent =\r\n | {\r\n readonly type: 'basket.changeQuantity';\r\n readonly lineId: number;\r\n readonly qty: number;\r\n }\r\n | { readonly type: 'basket.voidLine'; readonly lineId: number }\r\n | { readonly type: 'basket.clear' };\r\n\r\n/** Display-only VAT from the host envelope — not calculated here. */\r\nexport interface PosBasketVat {\r\n readonly rate: number;\r\n readonly amount: number;\r\n readonly included: boolean;\r\n}\r\n\r\n/** Display-only basket line from the host envelope — not an API DTO. */\r\nexport interface PosBasketLine {\r\n readonly lineId: number;\r\n readonly sku: string;\r\n readonly name: string;\r\n readonly qty: number;\r\n readonly unitPrice: number;\r\n readonly lineTotal: number;\r\n readonly vat: PosBasketVat;\r\n readonly struckThrough: boolean;\r\n}\r\n\r\n/** Display-only totals from the host envelope — not calculated here. */\r\nexport interface PosBasketTotals {\r\n readonly gross: number;\r\n readonly net: number;\r\n readonly vat: number;\r\n readonly discount: number;\r\n readonly due: number;\r\n readonly currency: string;\r\n}\r\n\r\nconst EMPTY_TOTALS: PosBasketTotals = {\r\n gross: 0,\r\n net: 0,\r\n vat: 0,\r\n discount: 0,\r\n due: 0,\r\n currency: 'EUR',\r\n};\r\n\r\n@Component({\r\n selector: 'pos-basket',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-basket.html',\r\n styleUrl: './pos-basket.scss',\r\n host: {\r\n class: 'pos-basket',\r\n },\r\n})\r\nexport class PosBasket {\r\n readonly lines = input<readonly PosBasketLine[]>([]);\r\n readonly totals = input<PosBasketTotals>(EMPTY_TOTALS);\r\n readonly disabled = input(false);\r\n\r\n readonly title = input('Basket');\r\n readonly emptyMessage = input('Basket is empty');\r\n readonly clearLabel = input('Clear basket');\r\n\r\n readonly action = output<PosBasketIntent>();\r\n\r\n protected readonly hasLines = computed(() => this.lines().length > 0);\r\n\r\n protected readonly canClear = computed(\r\n () => this.hasLines() && !this.disabled(),\r\n );\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.totals().currency || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected canChangeQuantity(line: PosBasketLine): boolean {\r\n return !this.disabled() && !line.struckThrough;\r\n }\r\n\r\n protected canDecrement(line: PosBasketLine): boolean {\r\n return this.canChangeQuantity(line) && line.qty > 1;\r\n }\r\n\r\n protected canVoid(line: PosBasketLine): boolean {\r\n return this.canChangeQuantity(line);\r\n }\r\n\r\n protected onIncrement(line: PosBasketLine): void {\r\n if (!this.canChangeQuantity(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'basket.changeQuantity',\r\n lineId: line.lineId,\r\n qty: line.qty + 1,\r\n });\r\n }\r\n\r\n protected onDecrement(line: PosBasketLine): void {\r\n if (!this.canDecrement(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({\r\n type: 'basket.changeQuantity',\r\n lineId: line.lineId,\r\n qty: line.qty - 1,\r\n });\r\n }\r\n\r\n protected onVoid(line: PosBasketLine): void {\r\n if (!this.canVoid(line)) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'basket.voidLine', lineId: line.lineId });\r\n }\r\n\r\n protected onClear(): void {\r\n if (!this.canClear()) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'basket.clear' });\r\n }\r\n}\r\n","<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 −\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","import {\r\n afterNextRender,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n ElementRef,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n} from '@angular/core';\r\n\r\nexport type PosItemEntryIntent =\r\n | { readonly type: 'itemEntry.submit'; readonly reference: string };\r\n\r\n@Component({\r\n selector: 'pos-item-entry',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-item-entry.html',\r\n styleUrl: './pos-item-entry.scss',\r\n host: {\r\n class: 'pos-item-entry',\r\n },\r\n})\r\nexport class PosItemEntry {\r\n readonly disabled = input(false);\r\n readonly errorMessage = input('');\r\n readonly autofocus = input(true);\r\n\r\n readonly label = input('Item');\r\n readonly placeholder = input('Scan or enter item');\r\n readonly addLabel = input('Add');\r\n\r\n readonly action = output<PosItemEntryIntent>();\r\n\r\n private readonly itemInput = viewChild<ElementRef<HTMLInputElement>>('itemInput');\r\n\r\n protected readonly reference = signal('');\r\n\r\n protected readonly canSubmit = computed(\r\n () => this.reference().trim().length > 0 && !this.disabled(),\r\n );\r\n\r\n constructor() {\r\n afterNextRender(() => {\r\n if (this.autofocus() && !this.disabled()) {\r\n this.focusInput();\r\n }\r\n });\r\n }\r\n\r\n protected onInput(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof HTMLInputElement)) {\r\n return;\r\n }\r\n\r\n this.reference.set(target.value);\r\n }\r\n\r\n protected onSubmit(event: Event): void {\r\n event.preventDefault();\r\n\r\n if (this.disabled()) {\r\n return;\r\n }\r\n\r\n const reference = this.reference().trim();\r\n if (!reference) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'itemEntry.submit', reference });\r\n this.reference.set('');\r\n this.focusInput();\r\n }\r\n\r\n private focusInput(): void {\r\n this.itemInput()?.nativeElement.focus();\r\n }\r\n}\r\n","<section\r\n class=\"pos-item-entry__panel\"\r\n [attr.aria-busy]=\"disabled() ? true : null\"\r\n>\r\n <form class=\"pos-item-entry__form\" (submit)=\"onSubmit($event)\">\r\n <label class=\"pos-item-entry__field\">\r\n <span class=\"pos-item-entry__label\">{{ label() }}</span>\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 (input)=\"onInput($event)\"\r\n />\r\n </label>\r\n\r\n <button\r\n type=\"submit\"\r\n class=\"pos-item-entry__add\"\r\n [class.pos-item-entry__add--disabled]=\"!canSubmit()\"\r\n [disabled]=\"!canSubmit()\"\r\n >\r\n {{ addLabel() }}\r\n </button>\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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\n\r\nexport type PosTenderIntent =\r\n | {\r\n readonly type: 'tender.cash';\r\n readonly amount: number;\r\n };\r\n\r\nconst KEYPAD_ROWS: readonly (readonly string[])[] = [\r\n ['1', '2', '3'],\r\n ['4', '5', '6'],\r\n ['7', '8', '9'],\r\n ['0', '.', '←'],\r\n];\r\n\r\nconst MAX_WHOLE_DIGITS = 8;\r\n\r\nfunction parseCashAmount(raw: string): number | null {\r\n if (!raw) {\r\n return null;\r\n }\r\n\r\n const amount = Number(raw);\r\n if (!Number.isFinite(amount) || amount <= 0) {\r\n return null;\r\n }\r\n\r\n return Math.round(amount * 100) / 100;\r\n}\r\n\r\nfunction appendCashKey(current: string, key: string): string {\r\n if (key === '←') {\r\n return current.slice(0, -1);\r\n }\r\n\r\n if (key === '.') {\r\n if (current.includes('.')) {\r\n return current;\r\n }\r\n return current === '' ? '0.' : `${current}.`;\r\n }\r\n\r\n if (!/^\\d$/.test(key)) {\r\n return current;\r\n }\r\n\r\n if (current === '0') {\r\n return key;\r\n }\r\n\r\n const [whole = '', fraction] = current.split('.');\r\n if (fraction !== undefined) {\r\n if (fraction.length >= 2) {\r\n return current;\r\n }\r\n return current + key;\r\n }\r\n\r\n const significant = whole.replace(/^0+/, '');\r\n if (significant.length >= MAX_WHOLE_DIGITS) {\r\n return current;\r\n }\r\n\r\n return current + key;\r\n}\r\n\r\n@Component({\r\n selector: 'pos-tender',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-tender.html',\r\n styleUrl: './pos-tender.scss',\r\n host: {\r\n class: 'pos-tender',\r\n },\r\n})\r\nexport class PosTender {\r\n /** Display-only amount due from the host envelope — not calculated here. */\r\n readonly amountDue = input(0);\r\n /** Display-only change due from the host envelope — not calculated here. */\r\n readonly changeDue = input<number | null>(null);\r\n readonly currency = input('EUR');\r\n readonly disabled = input(false);\r\n readonly errorMessage = input('');\r\n\r\n readonly title = input('Cash tender');\r\n readonly amountDueLabel = input('Amount due');\r\n readonly tenderedLabel = input('Amount tendered');\r\n readonly changeDueLabel = input('Change due');\r\n readonly tenderLabel = input('Tender cash');\r\n readonly processingLabel = input('Processing tender…');\r\n\r\n readonly action = output<PosTenderIntent>();\r\n\r\n protected readonly keypadRows = KEYPAD_ROWS;\r\n protected readonly amountInput = signal('');\r\n\r\n protected readonly parsedAmount = computed(() =>\r\n parseCashAmount(this.amountInput()),\r\n );\r\n\r\n protected readonly canTender = computed(\r\n () => this.parsedAmount() !== null && !this.disabled(),\r\n );\r\n\r\n protected readonly hasChangeDue = computed(() => this.changeDue() !== null);\r\n\r\n protected readonly displayTendered = computed(\r\n () => this.amountInput() || '0',\r\n );\r\n\r\n protected readonly statusText = computed(() => {\r\n if (this.disabled() && !this.hasChangeDue()) {\r\n return this.processingLabel();\r\n }\r\n return '';\r\n });\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.currency() || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected onKeypad(key: string): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n\r\n this.amountInput.update((value) => appendCashKey(value, key));\r\n }\r\n\r\n protected onTender(): void {\r\n if (!this.canTender()) {\r\n return;\r\n }\r\n\r\n const amount = this.parsedAmount();\r\n if (amount === null) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'tender.cash', amount });\r\n }\r\n}\r\n","<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 === '←' || key === '.'\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"key === '←' ? '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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n input,\r\n output,\r\n} from '@angular/core';\r\n\r\nexport interface PosReceiptIntent {\r\n readonly type: 'receipt.newSale';\r\n}\r\n\r\n/** Display-only VAT from the host envelope — not calculated here. */\r\nexport interface PosReceiptVat {\r\n readonly rate: number;\r\n readonly amount: number;\r\n readonly included: boolean;\r\n}\r\n\r\n/** Display-only receipt line from the host envelope — not an API DTO. */\r\nexport interface PosReceiptLine {\r\n readonly lineId: number;\r\n readonly sku: string;\r\n readonly name: string;\r\n readonly qty: number;\r\n readonly unitPrice: number;\r\n readonly lineTotal: number;\r\n readonly vat: PosReceiptVat;\r\n readonly struckThrough: boolean;\r\n}\r\n\r\n/** Display-only totals from the host envelope — not calculated here. */\r\nexport interface PosReceiptTotals {\r\n readonly gross: number;\r\n readonly net: number;\r\n readonly vat: number;\r\n readonly discount: number;\r\n readonly due: number;\r\n readonly currency: string;\r\n}\r\n\r\n/** Display-only tender from the host envelope — not calculated here. */\r\nexport interface PosReceiptPayment {\r\n readonly tender: string;\r\n readonly amount: number;\r\n readonly tendered: number;\r\n readonly change: number;\r\n readonly state: string;\r\n}\r\n\r\n/** Display-only document metadata from the host envelope. */\r\nexport interface PosReceiptDocument {\r\n readonly number: string;\r\n readonly receiptReady: boolean;\r\n}\r\n\r\nconst EMPTY_TOTALS: PosReceiptTotals = {\r\n gross: 0,\r\n net: 0,\r\n vat: 0,\r\n discount: 0,\r\n due: 0,\r\n currency: 'EUR',\r\n};\r\n\r\nconst EMPTY_DOCUMENT: PosReceiptDocument = {\r\n number: '',\r\n receiptReady: false,\r\n};\r\n\r\n@Component({\r\n selector: 'pos-receipt',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-receipt.html',\r\n styleUrl: './pos-receipt.scss',\r\n host: {\r\n class: 'pos-receipt',\r\n },\r\n})\r\nexport class PosReceipt {\r\n readonly lines = input<readonly PosReceiptLine[]>([]);\r\n readonly totals = input<PosReceiptTotals>(EMPTY_TOTALS);\r\n readonly payments = input<readonly PosReceiptPayment[]>([]);\r\n readonly document = input<PosReceiptDocument>(EMPTY_DOCUMENT);\r\n readonly disabled = input(false);\r\n\r\n readonly title = input('Receipt');\r\n readonly emptyMessage = input('No receipt lines');\r\n readonly preparingLabel = input('Preparing receipt…');\r\n readonly readyLabel = input('Receipt ready');\r\n readonly newSaleLabel = input('New sale');\r\n readonly tenderLabel = input('Tender');\r\n readonly amountLabel = input('Amount');\r\n readonly tenderedLabel = input('Tendered');\r\n readonly changeLabel = input('Change');\r\n\r\n readonly action = output<PosReceiptIntent>();\r\n\r\n protected readonly hasLines = computed(() => this.lines().length > 0);\r\n protected readonly hasPayments = computed(() => this.payments().length > 0);\r\n protected readonly hasDocumentNumber = computed(\r\n () => this.document().number.trim().length > 0,\r\n );\r\n\r\n protected readonly statusText = computed(() =>\r\n this.document().receiptReady\r\n ? this.readyLabel()\r\n : this.preparingLabel(),\r\n );\r\n\r\n protected readonly canStartNewSale = computed(() => !this.disabled());\r\n\r\n protected formatMoney(amount: number): string {\r\n return new Intl.NumberFormat(undefined, {\r\n style: 'currency',\r\n currency: this.totals().currency || 'EUR',\r\n minimumFractionDigits: 2,\r\n maximumFractionDigits: 2,\r\n }).format(amount);\r\n }\r\n\r\n protected onNewSale(): void {\r\n if (!this.canStartNewSale()) {\r\n return;\r\n }\r\n\r\n this.action.emit({ type: 'receipt.newSale' });\r\n }\r\n}\r\n","<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","/**\r\n * Theme-lab catalog. Default values must stay in sync with `styles/tokens.css`.\r\n * The lab never writes that file; edits are live overrides only.\r\n */\r\nexport type PosTokenKind =\r\n | 'color'\r\n | 'length'\r\n | 'font-family'\r\n | 'font-weight'\r\n | 'other';\r\n\r\nexport type PosTokenGroup = 'color' | 'radius' | 'space' | 'type' | 'control';\r\n\r\nexport type PosTokenPreview =\r\n | 'color'\r\n | 'radius'\r\n | 'space'\r\n | 'font-size'\r\n | 'font-family'\r\n | 'font-weight'\r\n | 'letter-spacing'\r\n | 'size';\r\n\r\nexport interface PosTokenSwatch {\r\n readonly name: string;\r\n readonly variable: string;\r\n}\r\n\r\nexport interface PosTokenDefinition extends PosTokenSwatch {\r\n readonly kind: PosTokenKind;\r\n readonly group: PosTokenGroup;\r\n readonly preview: PosTokenPreview;\r\n readonly defaultValue: string;\r\n}\r\n\r\nexport interface PosTokenSample {\r\n readonly id: string;\r\n readonly label: string;\r\n readonly variables: readonly string[];\r\n}\r\n\r\nexport const POS_TOKEN_CATALOG: readonly PosTokenDefinition[] = [\r\n {\r\n name: 'Primary',\r\n variable: '--pos-color-primary',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#c9b5f0',\r\n },\r\n {\r\n name: 'On primary',\r\n variable: '--pos-color-on-primary',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'Success',\r\n variable: '--pos-color-success',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#16dbcc',\r\n },\r\n {\r\n name: 'On success',\r\n variable: '--pos-color-on-success',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'Danger',\r\n variable: '--pos-color-danger',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#fe5c73',\r\n },\r\n {\r\n name: 'On danger',\r\n variable: '--pos-color-on-danger',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#ffffff',\r\n },\r\n {\r\n name: 'Secondary',\r\n variable: '--pos-color-secondary',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#16dbcc',\r\n },\r\n {\r\n name: 'Warning',\r\n variable: '--pos-color-warning',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#f0ad4e',\r\n },\r\n {\r\n name: 'Text',\r\n variable: '--pos-color-text',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'Text muted',\r\n variable: '--pos-color-text-muted',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#999999',\r\n },\r\n {\r\n name: 'Surface',\r\n variable: '--pos-color-surface',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#ffffff',\r\n },\r\n {\r\n name: 'Surface muted',\r\n variable: '--pos-color-surface-muted',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#f5f5f5',\r\n },\r\n {\r\n name: 'Panel',\r\n variable: '--pos-color-panel',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#f5f5f5',\r\n },\r\n {\r\n name: 'Panel elevated',\r\n variable: '--pos-color-panel-elevated',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#ffffff',\r\n },\r\n {\r\n name: 'Ink',\r\n variable: '--pos-color-ink',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'Border',\r\n variable: '--pos-color-border',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#dddddd',\r\n },\r\n {\r\n name: 'Disabled',\r\n variable: '--pos-color-disabled',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#dddddd',\r\n },\r\n {\r\n name: 'On disabled',\r\n variable: '--pos-color-on-disabled',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#999999',\r\n },\r\n {\r\n name: 'Display',\r\n variable: '--pos-color-display',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'On display',\r\n variable: '--pos-color-on-display',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#ffffff',\r\n },\r\n {\r\n name: 'Key',\r\n variable: '--pos-color-key',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#ffffff',\r\n },\r\n {\r\n name: 'Key border',\r\n variable: '--pos-color-key-border',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#dddddd',\r\n },\r\n {\r\n name: 'Key active',\r\n variable: '--pos-color-key-active',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#c9b5f0',\r\n },\r\n {\r\n name: 'On key active',\r\n variable: '--pos-color-on-key-active',\r\n kind: 'color',\r\n group: 'color',\r\n preview: 'color',\r\n defaultValue: '#333333',\r\n },\r\n {\r\n name: 'Radius sm',\r\n variable: '--pos-radius-sm',\r\n kind: 'length',\r\n group: 'radius',\r\n preview: 'radius',\r\n defaultValue: '4px',\r\n },\r\n {\r\n name: 'Radius md',\r\n variable: '--pos-radius-md',\r\n kind: 'length',\r\n group: 'radius',\r\n preview: 'radius',\r\n defaultValue: '8px',\r\n },\r\n {\r\n name: 'Radius lg',\r\n variable: '--pos-radius-lg',\r\n kind: 'length',\r\n group: 'radius',\r\n preview: 'radius',\r\n defaultValue: '12px',\r\n },\r\n {\r\n name: 'Radius pill',\r\n variable: '--pos-radius-pill',\r\n kind: 'length',\r\n group: 'radius',\r\n preview: 'radius',\r\n defaultValue: '9999px',\r\n },\r\n {\r\n name: 'Space xs',\r\n variable: '--pos-space-xs',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '4px',\r\n },\r\n {\r\n name: 'Space sm',\r\n variable: '--pos-space-sm',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '8px',\r\n },\r\n {\r\n name: 'Space md',\r\n variable: '--pos-space-md',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '12px',\r\n },\r\n {\r\n name: 'Space lg',\r\n variable: '--pos-space-lg',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '16px',\r\n },\r\n {\r\n name: 'Space xl',\r\n variable: '--pos-space-xl',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '24px',\r\n },\r\n {\r\n name: 'Space 2xl',\r\n variable: '--pos-space-2xl',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '40px',\r\n },\r\n {\r\n name: 'Space 3xl',\r\n variable: '--pos-space-3xl',\r\n kind: 'length',\r\n group: 'space',\r\n preview: 'space',\r\n defaultValue: '56px',\r\n },\r\n {\r\n name: 'Font family',\r\n variable: '--pos-font-family',\r\n kind: 'font-family',\r\n group: 'type',\r\n preview: 'font-family',\r\n defaultValue:\r\n \"Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif\",\r\n },\r\n {\r\n name: 'Font family display',\r\n variable: '--pos-font-family-display',\r\n kind: 'font-family',\r\n group: 'type',\r\n preview: 'font-family',\r\n defaultValue:\r\n \"Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif\",\r\n },\r\n {\r\n name: 'Font size sm',\r\n variable: '--pos-font-size-sm',\r\n kind: 'length',\r\n group: 'type',\r\n preview: 'font-size',\r\n defaultValue: '0.8125rem',\r\n },\r\n {\r\n name: 'Font size md',\r\n variable: '--pos-font-size-md',\r\n kind: 'length',\r\n group: 'type',\r\n preview: 'font-size',\r\n defaultValue: '0.875rem',\r\n },\r\n {\r\n name: 'Font size lg',\r\n variable: '--pos-font-size-lg',\r\n kind: 'length',\r\n group: 'type',\r\n preview: 'font-size',\r\n defaultValue: '1.125rem',\r\n },\r\n {\r\n name: 'Font size xl',\r\n variable: '--pos-font-size-xl',\r\n kind: 'length',\r\n group: 'type',\r\n preview: 'font-size',\r\n defaultValue: '1.375rem',\r\n },\r\n {\r\n name: 'Font weight semibold',\r\n variable: '--pos-font-weight-semibold',\r\n kind: 'font-weight',\r\n group: 'type',\r\n preview: 'font-weight',\r\n defaultValue: '600',\r\n },\r\n {\r\n name: 'Font weight bold',\r\n variable: '--pos-font-weight-bold',\r\n kind: 'font-weight',\r\n group: 'type',\r\n preview: 'font-weight',\r\n defaultValue: '700',\r\n },\r\n {\r\n name: 'Letter spacing display',\r\n variable: '--pos-letter-spacing-display',\r\n kind: 'length',\r\n group: 'type',\r\n preview: 'letter-spacing',\r\n defaultValue: '0.28em',\r\n },\r\n {\r\n name: 'Button min height',\r\n variable: '--pos-button-min-height',\r\n kind: 'length',\r\n group: 'control',\r\n preview: 'size',\r\n defaultValue: '48px',\r\n },\r\n {\r\n name: 'Keypad size',\r\n variable: '--pos-keypad-size',\r\n kind: 'length',\r\n group: 'control',\r\n preview: 'size',\r\n defaultValue: '3.25rem',\r\n },\r\n {\r\n name: 'Keypad size md',\r\n variable: '--pos-keypad-size-md',\r\n kind: 'length',\r\n group: 'control',\r\n preview: 'size',\r\n defaultValue: '3.75rem',\r\n },\r\n {\r\n name: 'Keypad size lg',\r\n variable: '--pos-keypad-size-lg',\r\n kind: 'length',\r\n group: 'control',\r\n preview: 'size',\r\n defaultValue: '4.25rem',\r\n },\r\n];\r\n\r\nexport const POS_TOKEN_DEFAULTS: Readonly<Record<string, string>> = Object.freeze(\r\n Object.fromEntries(\r\n POS_TOKEN_CATALOG.map((token) => [token.variable, token.defaultValue]),\r\n ),\r\n);\r\n\r\nexport const POS_TOKEN_BY_VARIABLE: ReadonlyMap<string, PosTokenDefinition> =\r\n new Map(POS_TOKEN_CATALOG.map((token) => [token.variable, token]));\r\n\r\nexport const POS_TOKEN_SAMPLES: readonly PosTokenSample[] = [\r\n {\r\n id: 'primary',\r\n label: 'Primary',\r\n variables: [\r\n '--pos-color-primary',\r\n '--pos-color-on-primary',\r\n '--pos-radius-md',\r\n '--pos-button-min-height',\r\n '--pos-font-weight-bold',\r\n ],\r\n },\r\n {\r\n id: 'success',\r\n label: 'Success',\r\n variables: [\r\n '--pos-color-success',\r\n '--pos-color-on-success',\r\n '--pos-radius-md',\r\n '--pos-button-min-height',\r\n '--pos-font-weight-bold',\r\n ],\r\n },\r\n {\r\n id: 'danger',\r\n label: 'Danger',\r\n variables: [\r\n '--pos-color-danger',\r\n '--pos-color-on-danger',\r\n '--pos-radius-md',\r\n '--pos-button-min-height',\r\n '--pos-font-weight-bold',\r\n ],\r\n },\r\n {\r\n id: 'disabled',\r\n label: 'Disabled',\r\n variables: [\r\n '--pos-color-disabled',\r\n '--pos-color-on-disabled',\r\n '--pos-radius-md',\r\n '--pos-button-min-height',\r\n ],\r\n },\r\n {\r\n id: 'text',\r\n label: 'Body text',\r\n variables: [\r\n '--pos-color-text',\r\n '--pos-color-text-muted',\r\n '--pos-font-family',\r\n '--pos-font-size-md',\r\n ],\r\n },\r\n {\r\n id: 'error',\r\n label: 'Danger / error message',\r\n variables: ['--pos-color-danger', '--pos-font-weight-semibold'],\r\n },\r\n];\r\n\r\nexport function tokensInGroup(\r\n group: PosTokenGroup,\r\n): readonly PosTokenDefinition[] {\r\n return POS_TOKEN_CATALOG.filter((token) => token.group === group);\r\n}\r\n\r\nexport function lookupPosTokens(\r\n variables: readonly string[],\r\n): readonly PosTokenDefinition[] {\r\n return variables.flatMap((variable) => {\r\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\r\n return token ? [token] : [];\r\n });\r\n}\r\n","import {\r\n POS_TOKEN_BY_VARIABLE,\r\n POS_TOKEN_CATALOG,\r\n POS_TOKEN_DEFAULTS,\r\n type PosTokenKind,\r\n} from './pos-token-catalog';\r\n\r\nconst TOKEN_DECL = /(--pos-[a-z0-9-]+)\\s*:\\s*([^;}{]+)/gi;\r\n\r\nexport const POS_THEME_CSS_FILENAME = 'pos-theme.css';\r\n\r\nconst THEME_CSS_HEADER = `/**\r\n * Adaptive POS theme\r\n * Generated by <pos-tokens>. Load after @retalia/pos-components styles.\r\n * Package defaults are unchanged; this file only overrides --pos-* on :root.\r\n */`;\r\n\r\nexport function normalizePosTokenValue(\r\n kind: PosTokenKind,\r\n value: string,\r\n): string {\r\n const trimmed = value.trim().replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim();\r\n if (!trimmed) {\r\n return '';\r\n }\r\n\r\n if (kind === 'color') {\r\n const hex = parseCssHex(trimmed);\r\n if (hex) {\r\n return hex;\r\n }\r\n }\r\n\r\n return trimmed.replace(/\\s*!important$/i, '').trim();\r\n}\r\n\r\nexport function parseCssHex(value: string): string | null {\r\n const trimmed = value.trim();\r\n const short = /^#([0-9a-f]{3})$/i.exec(trimmed)?.[1];\r\n if (short && short.length === 3) {\r\n const [r, g, b] = short;\r\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\r\n }\r\n\r\n if (/^#[0-9a-f]{6}$/i.test(trimmed)) {\r\n return trimmed.toLowerCase();\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function parsePosThemeCss(css: string): Readonly<Record<string, string>> {\r\n const result: Record<string, string> = {};\r\n\r\n for (const match of css.matchAll(TOKEN_DECL)) {\r\n const variable = match[1];\r\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\r\n if (!token) {\r\n continue;\r\n }\r\n\r\n const value = normalizePosTokenValue(token.kind, match[2] ?? '');\r\n if (value) {\r\n result[variable] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function resolvedPosTheme(\r\n overrides: Readonly<Record<string, string>>,\r\n): Readonly<Record<string, string>> {\r\n const resolved: Record<string, string> = { ...POS_TOKEN_DEFAULTS };\r\n for (const [variable, value] of Object.entries(overrides)) {\r\n if (variable in POS_TOKEN_DEFAULTS && value.trim()) {\r\n resolved[variable] = value;\r\n }\r\n }\r\n return resolved;\r\n}\r\n\r\nexport function overridesFromThemeValues(\r\n values: Readonly<Record<string, string>>,\r\n): Record<string, string> {\r\n const overrides: Record<string, string> = {};\r\n for (const [variable, value] of Object.entries(values)) {\r\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\r\n if (!token) {\r\n continue;\r\n }\r\n\r\n const normalized = normalizePosTokenValue(token.kind, value);\r\n if (normalized && normalized !== token.defaultValue) {\r\n overrides[variable] = normalized;\r\n }\r\n }\r\n return overrides;\r\n}\r\n\r\nexport function serializePosThemeCss(\r\n values: Readonly<Record<string, string>>,\r\n): string {\r\n const lines = POS_TOKEN_CATALOG.map((token) => {\r\n const value = values[token.variable] ?? token.defaultValue;\r\n return ` ${token.variable}: ${value};`;\r\n });\r\n\r\n return `${THEME_CSS_HEADER}\\n:root {\\n${lines.join('\\n')}\\n}\\n`;\r\n}\r\n\r\nexport function downloadTextFile(filename: string, contents: string): void {\r\n const blob = new Blob([contents], { type: 'text/css;charset=utf-8' });\r\n const url = URL.createObjectURL(blob);\r\n const anchor = document.createElement('a');\r\n anchor.href = url;\r\n anchor.download = filename;\r\n anchor.rel = 'noopener';\r\n document.body.append(anchor);\r\n anchor.click();\r\n anchor.remove();\r\n URL.revokeObjectURL(url);\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n signal,\r\n} from '@angular/core';\r\n\r\nimport {\r\n POS_TOKEN_BY_VARIABLE,\r\n POS_TOKEN_SAMPLES,\r\n type PosTokenDefinition,\r\n type PosTokenSwatch,\r\n lookupPosTokens,\r\n tokensInGroup,\r\n} from './pos-token-catalog';\r\nimport {\r\n POS_THEME_CSS_FILENAME,\r\n downloadTextFile,\r\n normalizePosTokenValue,\r\n overridesFromThemeValues,\r\n parseCssHex,\r\n parsePosThemeCss,\r\n resolvedPosTheme,\r\n serializePosThemeCss,\r\n} from './pos-theme-css';\r\n\r\nexport type { PosTokenSwatch };\r\n\r\ninterface PosTokenSelection {\r\n readonly id: string;\r\n readonly title: string;\r\n readonly variables: readonly string[];\r\n}\r\n\r\n@Component({\r\n selector: 'pos-tokens',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pos-tokens.html',\r\n styleUrl: './pos-tokens.scss',\r\n host: {\r\n class: 'pos-tokens',\r\n '[style]': 'themeStyle()',\r\n '(keydown.escape)': 'clearSelection()',\r\n },\r\n})\r\nexport class PosTokens {\r\n protected readonly colorTokens = tokensInGroup('color');\r\n protected readonly radiusTokens = tokensInGroup('radius');\r\n protected readonly spaceTokens = tokensInGroup('space');\r\n protected readonly typeTokens = tokensInGroup('type');\r\n protected readonly controlTokens = tokensInGroup('control');\r\n\r\n private readonly overrides = signal<Record<string, string>>({});\r\n protected readonly selection = signal<PosTokenSelection | null>(null);\r\n protected readonly statusMessage = signal('');\r\n\r\n protected readonly selectedTokens = computed(() => {\r\n const selection = this.selection();\r\n return selection ? lookupPosTokens(selection.variables) : [];\r\n });\r\n\r\n protected readonly hasOverrides = computed(\r\n () => Object.keys(this.overrides()).length > 0,\r\n );\r\n\r\n protected readonly themeStyle = computed(() =>\r\n Object.entries(this.overrides())\r\n .map(([variable, value]) => `${variable}: ${value}`)\r\n .join('; '),\r\n );\r\n\r\n /** Complete :root CSS for the consuming POS. Package defaults are not written. */\r\n themeCss(): string {\r\n return serializePosThemeCss(resolvedPosTheme(this.overrides()));\r\n }\r\n\r\n /** Load a previously exported theme as live overrides. Does not mutate defaults. */\r\n loadThemeCss(css: string): void {\r\n const parsed = parsePosThemeCss(css);\r\n const knownCount = Object.keys(parsed).length;\r\n this.overrides.set(overridesFromThemeValues(parsed));\r\n\r\n if (knownCount === 0) {\r\n this.statusMessage.set('No --pos-* tokens found in that file.');\r\n return;\r\n }\r\n\r\n this.statusMessage.set(\r\n `Imported ${knownCount} tokens as live overrides. Package defaults are unchanged.`,\r\n );\r\n }\r\n\r\n resetTheme(): void {\r\n this.overrides.set({});\r\n this.statusMessage.set('Live overrides cleared. Package defaults restored in this lab.');\r\n }\r\n\r\n protected exportThemeFile(): void {\r\n downloadTextFile(POS_THEME_CSS_FILENAME, this.themeCss());\r\n this.statusMessage.set(\r\n `Downloaded ${POS_THEME_CSS_FILENAME}. Add it after the package stylesheet in the host POS.`,\r\n );\r\n }\r\n\r\n protected async onImportFile(event: Event): Promise<void> {\r\n const input = event.target;\r\n if (!(input instanceof HTMLInputElement) || !input.files?.length) {\r\n return;\r\n }\r\n\r\n const css = await input.files[0].text();\r\n this.loadThemeCss(css);\r\n input.value = '';\r\n }\r\n\r\n protected selectToken(token: PosTokenDefinition): void {\r\n this.selection.set({\r\n id: `token:${token.variable}`,\r\n title: token.name,\r\n variables: [token.variable],\r\n });\r\n }\r\n\r\n protected selectSample(sampleId: string): void {\r\n const sample = POS_TOKEN_SAMPLES.find((item) => item.id === sampleId);\r\n if (!sample) {\r\n return;\r\n }\r\n\r\n this.selection.set({\r\n id: `sample:${sample.id}`,\r\n title: sample.label,\r\n variables: sample.variables,\r\n });\r\n }\r\n\r\n protected clearSelection(): void {\r\n this.selection.set(null);\r\n }\r\n\r\n protected isTokenSelected(variable: string): boolean {\r\n const selection = this.selection();\r\n return selection?.id === `token:${variable}`;\r\n }\r\n\r\n protected isSampleSelected(sampleId: string): boolean {\r\n return this.selection()?.id === `sample:${sampleId}`;\r\n }\r\n\r\n protected isModified(variable: string): boolean {\r\n return variable in this.overrides();\r\n }\r\n\r\n protected currentValue(variable: string): string {\r\n return this.overrides()[variable] ?? POS_TOKEN_BY_VARIABLE.get(variable)?.defaultValue ?? '';\r\n }\r\n\r\n protected defaultValue(variable: string): string {\r\n return POS_TOKEN_BY_VARIABLE.get(variable)?.defaultValue ?? '';\r\n }\r\n\r\n protected colorInputValue(variable: string): string | null {\r\n return parseCssHex(this.currentValue(variable));\r\n }\r\n\r\n protected tokenFieldId(variable: string): string {\r\n return `pos-token-field-${variable.replace(/[^a-z0-9]+/gi, '-')}`;\r\n }\r\n\r\n protected onTokenInput(variable: string, event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof HTMLInputElement)) {\r\n return;\r\n }\r\n\r\n this.setTokenValue(variable, target.value);\r\n }\r\n\r\n protected resetToken(variable: string): void {\r\n this.overrides.update((current) => {\r\n if (!(variable in current)) {\r\n return current;\r\n }\r\n\r\n const next = { ...current };\r\n delete next[variable];\r\n return next;\r\n });\r\n }\r\n\r\n private setTokenValue(variable: string, raw: string): void {\r\n const token = POS_TOKEN_BY_VARIABLE.get(variable);\r\n if (!token) {\r\n return;\r\n }\r\n\r\n const normalized = normalizePosTokenValue(token.kind, raw);\r\n this.overrides.update((current) => {\r\n const next = { ...current };\r\n if (!normalized || normalized === token.defaultValue) {\r\n delete next[variable];\r\n } else {\r\n next[variable] = normalized;\r\n }\r\n return next;\r\n });\r\n }\r\n}\r\n","<article class=\"pos-tokens__page\">\r\n <header class=\"pos-tokens__intro\">\r\n <p class=\"pos-tokens__kicker\">@retalia/pos-components</p>\r\n <h1 class=\"pos-tokens__title\">Design tokens</h1>\r\n <p class=\"pos-tokens__lede\">\r\n Click a sample or token to edit it. Changes are live overrides in this lab only —\r\n package defaults are never overwritten. Export a complete <code>:root</code> CSS\r\n file for the consuming POS, and import that file back later to resume editing.\r\n </p>\r\n <div class=\"pos-tokens__toolbar\">\r\n <input\r\n #importFile\r\n class=\"pos-tokens__file\"\r\n type=\"file\"\r\n accept=\".css,text/css\"\r\n (change)=\"onImportFile($event)\"\r\n />\r\n <button type=\"button\" class=\"pos-tokens__tool pos-tokens__tool--primary\" (click)=\"exportThemeFile()\">\r\n Export CSS\r\n </button>\r\n <button type=\"button\" class=\"pos-tokens__tool\" (click)=\"importFile.click()\">\r\n Import CSS\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__tool\"\r\n [disabled]=\"!hasOverrides()\"\r\n (click)=\"resetTheme()\"\r\n >\r\n Reset overrides\r\n </button>\r\n </div>\r\n <p class=\"pos-tokens__status\" role=\"status\" aria-live=\"polite\">{{ statusMessage() }}</p>\r\n </header>\r\n\r\n <div class=\"pos-tokens__layout\">\r\n <div class=\"pos-tokens__gallery\">\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-samples\">\r\n <h2 id=\"pos-tokens-samples\" class=\"pos-tokens__heading\">In action</h2>\r\n <p class=\"pos-tokens__hint\">Click a control to edit the tokens it uses.</p>\r\n <div class=\"pos-tokens__samples\">\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('primary')\"\r\n [attr.aria-pressed]=\"isSampleSelected('primary')\"\r\n (click)=\"selectSample('primary')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--primary\">Primary</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('success')\"\r\n [attr.aria-pressed]=\"isSampleSelected('success')\"\r\n (click)=\"selectSample('success')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--success\">Success</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('danger')\"\r\n [attr.aria-pressed]=\"isSampleSelected('danger')\"\r\n (click)=\"selectSample('danger')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--danger\">Danger</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('disabled')\"\r\n [attr.aria-pressed]=\"isSampleSelected('disabled')\"\r\n (click)=\"selectSample('disabled')\"\r\n >\r\n <span class=\"pos-tokens__btn pos-tokens__btn--disabled\">Disabled</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample pos-tokens__sample--text\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('text')\"\r\n [attr.aria-pressed]=\"isSampleSelected('text')\"\r\n (click)=\"selectSample('text')\"\r\n >\r\n <span class=\"pos-tokens__sample-text\">\r\n Body text · <span class=\"pos-tokens__sample-muted\">muted</span>\r\n </span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__sample pos-tokens__sample--text\"\r\n [class.pos-tokens__sample--selected]=\"isSampleSelected('error')\"\r\n [attr.aria-pressed]=\"isSampleSelected('error')\"\r\n (click)=\"selectSample('error')\"\r\n >\r\n <span class=\"pos-tokens__sample-danger\">Danger / error message</span>\r\n </button>\r\n </div>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-colors\">\r\n <h2 id=\"pos-tokens-colors\" class=\"pos-tokens__heading\">Color</h2>\r\n <ul class=\"pos-tokens__swatch-grid\">\r\n @for (token of colorTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__chip\"\r\n [style.background]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-radius\">\r\n <h2 id=\"pos-tokens-radius\" class=\"pos-tokens__heading\">Radius</h2>\r\n <ul class=\"pos-tokens__radius-row\">\r\n @for (token of radiusTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__radius-box\"\r\n [style.border-radius]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-space\">\r\n <h2 id=\"pos-tokens-space\" class=\"pos-tokens__heading\">Space</h2>\r\n <ul class=\"pos-tokens__space-list\">\r\n @for (token of spaceTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick pos-tokens__pick--row\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__space-bar\"\r\n [style.width]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-type\">\r\n <h2 id=\"pos-tokens-type\" class=\"pos-tokens__heading\">Typography</h2>\r\n <ul class=\"pos-tokens__type-list\">\r\n @for (token of typeTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n @switch (token.preview) {\r\n @case ('font-family') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-family]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('font-size') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-size]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('font-weight') {\r\n <span\r\n class=\"pos-tokens__type-preview\"\r\n [style.font-weight]=\"'var(' + token.variable + ')'\"\r\n >\r\n The quick brown fox\r\n </span>\r\n }\r\n @case ('letter-spacing') {\r\n <span\r\n class=\"pos-tokens__type-preview pos-tokens__type-preview--caps\"\r\n [style.letter-spacing]=\"'var(' + token.variable + ')'\"\r\n >\r\n Display\r\n </span>\r\n }\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n\r\n <section class=\"pos-tokens__section\" aria-labelledby=\"pos-tokens-controls\">\r\n <h2 id=\"pos-tokens-controls\" class=\"pos-tokens__heading\">Controls</h2>\r\n <ul class=\"pos-tokens__control-list\">\r\n @for (token of controlTokens; track token.variable) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"pos-tokens__pick pos-tokens__pick--row\"\r\n [class.pos-tokens__pick--selected]=\"isTokenSelected(token.variable)\"\r\n [class.pos-tokens__pick--modified]=\"isModified(token.variable)\"\r\n [attr.aria-pressed]=\"isTokenSelected(token.variable)\"\r\n (click)=\"selectToken(token)\"\r\n >\r\n <span\r\n class=\"pos-tokens__size-box\"\r\n [style.width]=\"'var(' + token.variable + ')'\"\r\n [style.height]=\"'var(' + token.variable + ')'\"\r\n ></span>\r\n <span class=\"pos-tokens__swatch-meta\">\r\n <span class=\"pos-tokens__swatch-name\">\r\n {{ token.name }}\r\n @if (isModified(token.variable)) {\r\n <span class=\"pos-tokens__edited\">Edited</span>\r\n }\r\n </span>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n </span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n </section>\r\n </div>\r\n\r\n <aside class=\"pos-tokens__inspector\" aria-labelledby=\"pos-tokens-inspector-title\">\r\n <div class=\"pos-tokens__inspector-header\">\r\n <h2 id=\"pos-tokens-inspector-title\" class=\"pos-tokens__heading\">\r\n {{ selection()?.title ?? 'Theme editor' }}\r\n </h2>\r\n @if (selection()) {\r\n <button type=\"button\" class=\"pos-tokens__tool pos-tokens__tool--quiet\" (click)=\"clearSelection()\">\r\n Close\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (!selection()) {\r\n <p class=\"pos-tokens__hint\">\r\n Select a sample or token to change its values. Export writes a complete CSS\r\n file the host POS can load after the package stylesheet.\r\n </p>\r\n } @else {\r\n <ul class=\"pos-tokens__fields\">\r\n @for (token of selectedTokens(); track token.variable) {\r\n <li class=\"pos-tokens__field\">\r\n <label class=\"pos-tokens__field-label\" [attr.for]=\"tokenFieldId(token.variable)\">\r\n {{ token.name }}\r\n </label>\r\n <code class=\"pos-tokens__swatch-var\">{{ token.variable }}</code>\r\n <div class=\"pos-tokens__field-controls\">\r\n @if (token.kind === 'color') {\r\n @if (colorInputValue(token.variable); as hex) {\r\n <input\r\n class=\"pos-tokens__color\"\r\n type=\"color\"\r\n [value]=\"hex\"\r\n [attr.aria-label]=\"token.name + ' color'\"\r\n (input)=\"onTokenInput(token.variable, $event)\"\r\n />\r\n }\r\n }\r\n <input\r\n class=\"pos-tokens__value\"\r\n type=\"text\"\r\n [id]=\"tokenFieldId(token.variable)\"\r\n [value]=\"currentValue(token.variable)\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\"\r\n (input)=\"onTokenInput(token.variable, $event)\"\r\n />\r\n </div>\r\n <p class=\"pos-tokens__default\">\r\n Default\r\n <code>{{ defaultValue(token.variable) }}</code>\r\n </p>\r\n @if (isModified(token.variable)) {\r\n <button type=\"button\" class=\"pos-tokens__reset\" (click)=\"resetToken(token.variable)\">\r\n Reset to default\r\n </button>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </aside>\r\n </div>\r\n</article>\r\n","/*\r\n * Public API Surface of @retalia/pos-components\r\n */\r\n\r\nexport { PosLogin } from './lib/login/pos-login';\r\nexport type {\r\n PosLoginIntent,\r\n PosLoginSessionState,\r\n PosLoginSessionStatus,\r\n} from './lib/login/pos-login';\r\n\r\nexport { PosBasket } from './lib/basket/pos-basket';\r\nexport type {\r\n PosBasketIntent,\r\n PosBasketLine,\r\n PosBasketTotals,\r\n PosBasketVat,\r\n} from './lib/basket/pos-basket';\r\n\r\nexport { PosItemEntry } from './lib/item-entry/pos-item-entry';\r\nexport type { PosItemEntryIntent } from './lib/item-entry/pos-item-entry';\r\n\r\nexport { PosTender } from './lib/tender/pos-tender';\r\nexport type { PosTenderIntent } from './lib/tender/pos-tender';\r\n\r\nexport { PosReceipt } from './lib/receipt/pos-receipt';\r\nexport type {\r\n PosReceiptIntent,\r\n PosReceiptLine,\r\n PosReceiptTotals,\r\n PosReceiptVat,\r\n PosReceiptPayment,\r\n PosReceiptDocument,\r\n} from './lib/receipt/pos-receipt';\r\n\r\nexport { PosTokens } from './lib/tokens/pos-tokens';\r\nexport type { PosTokenSwatch } from './lib/tokens/pos-tokens';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["KEYPAD_ROWS","EMPTY_TOTALS"],"mappings":";;;AAwBA,MAAM,eAAe,GAAyB,EAAE,MAAM,EAAE,WAAW,EAAE;AAIrE,MAAMA,aAAW,GAAmC;AAClD,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CAChB;MAWY,QAAQ,CAAA;AACV,IAAA,YAAY,GAAG,KAAK,CAAC,EAAE,mFAAC;AACxB,IAAA,OAAO,GAAG,KAAK,CAAuB,eAAe,8EAAC;AAEtD,IAAA,gBAAgB,GAAG,KAAK,CAAC,oBAAoB,uFAAC;AAC9C,IAAA,kBAAkB,GAAG,KAAK,CAAC,sBAAsB,yFAAC;AAClD,IAAA,SAAS,GAAG,KAAK,CAAC,MAAM,gFAAC;AACzB,IAAA,UAAU,GAAG,KAAK,CAAC,OAAO,iFAAC;IAE3B,MAAM,GAAG,MAAM,EAAkB;IAEvB,UAAU,GAAGA,aAAW;AACxB,IAAA,UAAU,GAAG,MAAM,CAAC,EAAE,iFAAC;AACvB,IAAA,KAAK,GAAG,MAAM,CAAa,aAAa,4EAAC;AAC3C,IAAA,WAAW,GAAG,MAAM,CAAC,EAAE,kFAAC;IAEtB,KAAK,GAAG,QAAQ,CAAC,MAClC,IAAI,CAAC,KAAK,EAAE,KAAK;AACf,UAAE,IAAI,CAAC,gBAAgB;AACvB,UAAE,IAAI,CAAC,kBAAkB,EAAE,4EAC9B;AAEkB,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,UAAU,gFAAC;AAEvD,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,KAAK,UAAU,+EAAC;IAEtD,YAAY,GAAG,QAAQ,CAAC,MACzC,IAAI,CAAC,KAAK,EAAE,KAAK,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,cAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CACnE;IAEkB,cAAc,GAAG,QAAQ,CAC1C,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAChE;AAEkB,IAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAK;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM;AACpC,QAAA,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,UAAU;AACnD,IAAA,CAAC,wFAAC;AAEiB,IAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAK;AACnD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;AAC7B,YAAA,OAAO,aAAa;QACtB;AACA,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE;YACjC,OAAO,OAAO,CAAC;AACb,kBAAE,CAAA,aAAA,EAAgB,OAAO,CAAC,WAAW,CAAA;kBACnC,WAAW;QACjB;AACA,QAAA,OAAO,EAAE;AACX,IAAA,CAAC,wFAAC;AAEQ,IAAA,QAAQ,CAAC,GAAW,EAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE;YAC5B;QACF;AAEA,QAAA,IAAI,GAAG,KAAK,GAAG,EAAE;YACf,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;YAC7C;QACF;QAEA,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,IAAI,EAAE,EAAE;YAClC;QACF;AAEA,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC;AAC9C,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;IAC9C;IAEU,SAAS,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE;YAC5B;QACF;AAEA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;QAC/B,IAAI,CAAC,KAAK,EAAE;YACV;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,aAAa,EAAE;AAClC,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;AAC3B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACvB,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;AAC1B,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;YAC5D;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,cAAc;AACpB,YAAA,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;AAC/B,YAAA,QAAQ,EAAE,KAAK;AAChB,SAAA,CAAC;IACJ;IAEU,MAAM,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE;YAC5B;QACF;QAEA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;AACvC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC1C;wGAxGW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,QAAQ,q+BC5CrB,8qFAkFA,EAAA,MAAA,EAAA,CAAA,mgJAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FDtCa,QAAQ,EAAA,UAAA,EAAA,CAAA;kBATpB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,EAAA,eAAA,EACJ,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,WAAW;AACnB,qBAAA,EAAA,QAAA,EAAA,8qFAAA,EAAA,MAAA,EAAA,CAAA,mgJAAA,CAAA,EAAA;;;AEIH,MAAMC,cAAY,GAAoB;AACpC,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,QAAQ,EAAE,KAAK;CAChB;MAWY,SAAS,CAAA;AACX,IAAA,KAAK,GAAG,KAAK,CAA2B,EAAE,4EAAC;AAC3C,IAAA,MAAM,GAAG,KAAK,CAAkBA,cAAY,6EAAC;AAC7C,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AAEvB,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,4EAAC;AACvB,IAAA,YAAY,GAAG,KAAK,CAAC,iBAAiB,mFAAC;AACvC,IAAA,UAAU,GAAG,KAAK,CAAC,cAAc,iFAAC;IAElC,MAAM,GAAG,MAAM,EAAmB;AAExB,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC,+EAAC;AAElD,IAAA,QAAQ,GAAG,QAAQ,CACpC,MAAM,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,+EAC1C;AAES,IAAA,WAAW,CAAC,MAAc,EAAA;AAClC,QAAA,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE;AACtC,YAAA,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,IAAI,KAAK;AACzC,YAAA,qBAAqB,EAAE,CAAC;AACxB,YAAA,qBAAqB,EAAE,CAAC;AACzB,SAAA,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IACnB;AAEU,IAAA,iBAAiB,CAAC,IAAmB,EAAA;QAC7C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa;IAChD;AAEU,IAAA,YAAY,CAAC,IAAmB,EAAA;AACxC,QAAA,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC;IACrD;AAEU,IAAA,OAAO,CAAC,IAAmB,EAAA;AACnC,QAAA,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrC;AAEU,IAAA,WAAW,CAAC,IAAmB,EAAA;QACvC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;YACjC;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;AACnB,YAAA,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC;AAClB,SAAA,CAAC;IACJ;AAEU,IAAA,WAAW,CAAC,IAAmB,EAAA;QACvC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;YAC5B;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;AACnB,YAAA,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC;AAClB,SAAA,CAAC;IACJ;AAEU,IAAA,MAAM,CAAC,IAAmB,EAAA;QAClC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACvB;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACpE;IAEU,OAAO,GAAA;AACf,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;YACpB;QACF;QAEA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAC5C;wGA5EW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,SAAS,y5BChEtB,iuIA4HA,EAAA,MAAA,EAAA,CAAA,i3KAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FD5Da,SAAS,EAAA,UAAA,EAAA,CAAA;kBATrB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,YAAY,EAAA,eAAA,EACL,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,YAAY;AACpB,qBAAA,EAAA,QAAA,EAAA,iuIAAA,EAAA,MAAA,EAAA,CAAA,i3KAAA,CAAA,EAAA;;;MEtCU,YAAY,CAAA;AACd,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AACvB,IAAA,YAAY,GAAG,KAAK,CAAC,EAAE,mFAAC;AACxB,IAAA,SAAS,GAAG,KAAK,CAAC,IAAI,gFAAC;AAEvB,IAAA,KAAK,GAAG,KAAK,CAAC,MAAM,4EAAC;AACrB,IAAA,WAAW,GAAG,KAAK,CAAC,oBAAoB,kFAAC;AACzC,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;IAEvB,MAAM,GAAG,MAAM,EAAsB;AAE7B,IAAA,SAAS,GAAG,SAAS,CAA+B,WAAW,gFAAC;AAE9D,IAAA,SAAS,GAAG,MAAM,CAAC,EAAE,gFAAC;IAEtB,SAAS,GAAG,QAAQ,CACrC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAC7D;AAED,IAAA,WAAA,GAAA;QACE,eAAe,CAAC,MAAK;YACnB,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;gBACxC,IAAI,CAAC,UAAU,EAAE;YACnB;AACF,QAAA,CAAC,CAAC;IACJ;AAEU,IAAA,OAAO,CAAC,KAAY,EAAA;AAC5B,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAC3B,QAAA,IAAI,EAAE,MAAM,YAAY,gBAAgB,CAAC,EAAE;YACzC;QACF;QAEA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;IAClC;AAEU,IAAA,QAAQ,CAAC,KAAY,EAAA;QAC7B,KAAK,CAAC,cAAc,EAAE;AAEtB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACnB;QACF;QAEA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE;QACzC,IAAI,CAAC,SAAS,EAAE;YACd;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC;AACzD,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,EAAE;IACnB;IAEQ,UAAU,GAAA;QAChB,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE;IACzC;wGAvDW,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,YAAY,8iCCxBzB,kyCAyCA,EAAA,MAAA,EAAA,CAAA,20FAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FDjBa,YAAY,EAAA,UAAA,EAAA,CAAA;kBATxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,eAAA,EACT,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,gBAAgB;AACxB,qBAAA,EAAA,QAAA,EAAA,kyCAAA,EAAA,MAAA,EAAA,CAAA,20FAAA,CAAA,EAAA;4tBAaoE,WAAW,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AEpBlF,MAAM,WAAW,GAAmC;AAClD,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AACf,IAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CAChB;AAED,MAAM,gBAAgB,GAAG,CAAC;AAE1B,SAAS,eAAe,CAAC,GAAW,EAAA;IAClC,IAAI,CAAC,GAAG,EAAE;AACR,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC;AAC1B,IAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE;AAC3C,QAAA,OAAO,IAAI;IACb;IAEA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG;AACvC;AAEA,SAAS,aAAa,CAAC,OAAe,EAAE,GAAW,EAAA;AACjD,IAAA,IAAI,GAAG,KAAK,GAAG,EAAE;QACf,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B;AAEA,IAAA,IAAI,GAAG,KAAK,GAAG,EAAE;AACf,QAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACzB,YAAA,OAAO,OAAO;QAChB;AACA,QAAA,OAAO,OAAO,KAAK,EAAE,GAAG,IAAI,GAAG,CAAA,EAAG,OAAO,GAAG;IAC9C;IAEA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AACrB,QAAA,OAAO,OAAO;IAChB;AAEA,IAAA,IAAI,OAAO,KAAK,GAAG,EAAE;AACnB,QAAA,OAAO,GAAG;IACZ;AAEA,IAAA,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;AACjD,IAAA,IAAI,QAAQ,KAAK,SAAS,EAAE;AAC1B,QAAA,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE;AACxB,YAAA,OAAO,OAAO;QAChB;QACA,OAAO,OAAO,GAAG,GAAG;IACtB;IAEA,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AAC5C,IAAA,IAAI,WAAW,CAAC,MAAM,IAAI,gBAAgB,EAAE;AAC1C,QAAA,OAAO,OAAO;IAChB;IAEA,OAAO,OAAO,GAAG,GAAG;AACtB;MAWa,SAAS,CAAA;;AAEX,IAAA,SAAS,GAAG,KAAK,CAAC,CAAC,gFAAC;;AAEpB,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;AACtC,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AACvB,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AACvB,IAAA,YAAY,GAAG,KAAK,CAAC,EAAE,mFAAC;AAExB,IAAA,KAAK,GAAG,KAAK,CAAC,aAAa,4EAAC;AAC5B,IAAA,cAAc,GAAG,KAAK,CAAC,YAAY,qFAAC;AACpC,IAAA,aAAa,GAAG,KAAK,CAAC,iBAAiB,oFAAC;AACxC,IAAA,cAAc,GAAG,KAAK,CAAC,YAAY,qFAAC;AACpC,IAAA,WAAW,GAAG,KAAK,CAAC,aAAa,kFAAC;AAClC,IAAA,eAAe,GAAG,KAAK,CAAC,oBAAoB,sFAAC;IAE7C,MAAM,GAAG,MAAM,EAAmB;IAExB,UAAU,GAAG,WAAW;AACxB,IAAA,WAAW,GAAG,MAAM,CAAC,EAAE,kFAAC;AAExB,IAAA,YAAY,GAAG,QAAQ,CAAC,MACzC,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,mFACpC;AAEkB,IAAA,SAAS,GAAG,QAAQ,CACrC,MAAM,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gFACvD;AAEkB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,KAAK,IAAI,mFAAC;AAExD,IAAA,eAAe,GAAG,QAAQ,CAC3C,MAAM,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,sFAChC;AAEkB,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;QAC5C,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE;AAC3C,YAAA,OAAO,IAAI,CAAC,eAAe,EAAE;QAC/B;AACA,QAAA,OAAO,EAAE;AACX,IAAA,CAAC,iFAAC;AAEQ,IAAA,WAAW,CAAC,MAAc,EAAA;AAClC,QAAA,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE;AACtC,YAAA,KAAK,EAAE,UAAU;AACjB,YAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK;AAClC,YAAA,qBAAqB,EAAE,CAAC;AACxB,YAAA,qBAAqB,EAAE,CAAC;AACzB,SAAA,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IACnB;AAEU,IAAA,QAAQ,CAAC,GAAW,EAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YACnB;QACF;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D;IAEU,QAAQ,GAAA;AAChB,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACrB;QACF;AAEA,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE;AAClC,QAAA,IAAI,MAAM,KAAK,IAAI,EAAE;YACnB;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;IACnD;wGAtEW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,SAAS,8nDClFtB,siFA+EA,EAAA,MAAA,EAAA,CAAA,8rMAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FDGa,SAAS,EAAA,UAAA,EAAA,CAAA;kBATrB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,YAAY,EAAA,eAAA,EACL,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,YAAY;AACpB,qBAAA,EAAA,QAAA,EAAA,siFAAA,EAAA,MAAA,EAAA,CAAA,8rMAAA,CAAA,EAAA;;;AExBH,MAAM,YAAY,GAAqB;AACrC,IAAA,KAAK,EAAE,CAAC;AACR,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,QAAQ,EAAE,KAAK;CAChB;AAED,MAAM,cAAc,GAAuB;AACzC,IAAA,MAAM,EAAE,EAAE;AACV,IAAA,YAAY,EAAE,KAAK;CACpB;MAWY,UAAU,CAAA;AACZ,IAAA,KAAK,GAAG,KAAK,CAA4B,EAAE,4EAAC;AAC5C,IAAA,MAAM,GAAG,KAAK,CAAmB,YAAY,6EAAC;AAC9C,IAAA,QAAQ,GAAG,KAAK,CAA+B,EAAE,+EAAC;AAClD,IAAA,QAAQ,GAAG,KAAK,CAAqB,cAAc,+EAAC;AACpD,IAAA,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC;AAEvB,IAAA,KAAK,GAAG,KAAK,CAAC,SAAS,4EAAC;AACxB,IAAA,YAAY,GAAG,KAAK,CAAC,kBAAkB,mFAAC;AACxC,IAAA,cAAc,GAAG,KAAK,CAAC,oBAAoB,qFAAC;AAC5C,IAAA,UAAU,GAAG,KAAK,CAAC,eAAe,iFAAC;AACnC,IAAA,YAAY,GAAG,KAAK,CAAC,UAAU,mFAAC;AAChC,IAAA,WAAW,GAAG,KAAK,CAAC,QAAQ,kFAAC;AAC7B,IAAA,WAAW,GAAG,KAAK,CAAC,QAAQ,kFAAC;AAC7B,IAAA,aAAa,GAAG,KAAK,CAAC,UAAU,oFAAC;AACjC,IAAA,WAAW,GAAG,KAAK,CAAC,QAAQ,kFAAC;IAE7B,MAAM,GAAG,MAAM,EAAoB;AAEzB,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC,+EAAC;AAClD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,GAAG,CAAC,kFAAC;IACxD,iBAAiB,GAAG,QAAQ,CAC7C,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,wFAC/C;IAEkB,UAAU,GAAG,QAAQ,CAAC,MACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;AACd,UAAE,IAAI,CAAC,UAAU;AACjB,UAAE,IAAI,CAAC,cAAc,EAAE,iFAC1B;AAEkB,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;AAE3D,IAAA,WAAW,CAAC,MAAc,EAAA;AAClC,QAAA,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE;AACtC,YAAA,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,IAAI,KAAK;AACzC,YAAA,qBAAqB,EAAE,CAAC;AACxB,YAAA,qBAAqB,EAAE,CAAC;AACzB,SAAA,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;IACnB;IAEU,SAAS,GAAA;AACjB,QAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE;YAC3B;QACF;QAEA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC/C;wGAhDW,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,UAAU,2+DC/EvB,ouIAoHA,EAAA,MAAA,EAAA,CAAA,4oNAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FDrCa,UAAU,EAAA,UAAA,EAAA,CAAA;kBATtB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,aAAa,EAAA,eAAA,EACN,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,aAAa;AACrB,qBAAA,EAAA,QAAA,EAAA,ouIAAA,EAAA,MAAA,EAAA,CAAA,4oNAAA,CAAA,EAAA;;;AEpCI,MAAM,iBAAiB,GAAkC;AAC9D,IAAA;AACE,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,QAAQ,EAAE,qBAAqB;AAC/B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,QAAQ,EAAE,qBAAqB;AAC/B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,uBAAuB;AACjC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,uBAAuB;AACjC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,QAAQ,EAAE,qBAAqB;AAC/B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,MAAM;AACZ,QAAA,QAAQ,EAAE,kBAAkB;AAC5B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,QAAQ,EAAE,qBAAqB;AAC/B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,QAAQ,EAAE,2BAA2B;AACrC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,QAAQ,EAAE,mBAAmB;AAC7B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,gBAAgB;AACtB,QAAA,QAAQ,EAAE,4BAA4B;AACtC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,KAAK;AACX,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,QAAQ,EAAE,yBAAyB;AACnC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,QAAQ,EAAE,qBAAqB;AAC/B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,KAAK;AACX,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,eAAe;AACrB,QAAA,QAAQ,EAAE,2BAA2B;AACrC,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,QAAQ,EAAE,mBAAmB;AAC7B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,YAAY,EAAE,QAAQ;AACvB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,gBAAgB;AAC1B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,gBAAgB;AAC1B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,gBAAgB;AAC1B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,gBAAgB;AAC1B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,QAAQ,EAAE,gBAAgB;AAC1B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,QAAQ,EAAE,iBAAiB;AAC3B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,QAAQ,EAAE,mBAAmB;AAC7B,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,aAAa;AACtB,QAAA,YAAY,EACV,sGAAsG;AACzG,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,qBAAqB;AAC3B,QAAA,QAAQ,EAAE,2BAA2B;AACrC,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,aAAa;AACtB,QAAA,YAAY,EACV,sGAAsG;AACzG,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,cAAc;AACpB,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,WAAW;AACpB,QAAA,YAAY,EAAE,WAAW;AAC1B,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,cAAc;AACpB,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,WAAW;AACpB,QAAA,YAAY,EAAE,UAAU;AACzB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,cAAc;AACpB,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,WAAW;AACpB,QAAA,YAAY,EAAE,UAAU;AACzB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,cAAc;AACpB,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,WAAW;AACpB,QAAA,YAAY,EAAE,UAAU;AACzB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,sBAAsB;AAC5B,QAAA,QAAQ,EAAE,4BAA4B;AACtC,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,aAAa;AACtB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,kBAAkB;AACxB,QAAA,QAAQ,EAAE,wBAAwB;AAClC,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,aAAa;AACtB,QAAA,YAAY,EAAE,KAAK;AACpB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,wBAAwB;AAC9B,QAAA,QAAQ,EAAE,8BAA8B;AACxC,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,OAAO,EAAE,gBAAgB;AACzB,QAAA,YAAY,EAAE,QAAQ;AACvB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,mBAAmB;AACzB,QAAA,QAAQ,EAAE,yBAAyB;AACnC,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,aAAa;AACnB,QAAA,QAAQ,EAAE,mBAAmB;AAC7B,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,gBAAgB;AACtB,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;AACD,IAAA;AACE,QAAA,IAAI,EAAE,gBAAgB;AACtB,QAAA,QAAQ,EAAE,sBAAsB;AAChC,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,OAAO,EAAE,MAAM;AACf,QAAA,YAAY,EAAE,SAAS;AACxB,KAAA;CACF;AAEM,MAAM,kBAAkB,GAAqC,MAAM,CAAC,MAAM,CAC/E,MAAM,CAAC,WAAW,CAChB,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CACvE,CACF;AAEM,MAAM,qBAAqB,GAChC,IAAI,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAE7D,MAAM,iBAAiB,GAA8B;AAC1D,IAAA;AACE,QAAA,EAAE,EAAE,SAAS;AACb,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,SAAS,EAAE;YACT,qBAAqB;YACrB,wBAAwB;YACxB,iBAAiB;YACjB,yBAAyB;YACzB,wBAAwB;AACzB,SAAA;AACF,KAAA;AACD,IAAA;AACE,QAAA,EAAE,EAAE,SAAS;AACb,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,SAAS,EAAE;YACT,qBAAqB;YACrB,wBAAwB;YACxB,iBAAiB;YACjB,yBAAyB;YACzB,wBAAwB;AACzB,SAAA;AACF,KAAA;AACD,IAAA;AACE,QAAA,EAAE,EAAE,QAAQ;AACZ,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,SAAS,EAAE;YACT,oBAAoB;YACpB,uBAAuB;YACvB,iBAAiB;YACjB,yBAAyB;YACzB,wBAAwB;AACzB,SAAA;AACF,KAAA;AACD,IAAA;AACE,QAAA,EAAE,EAAE,UAAU;AACd,QAAA,KAAK,EAAE,UAAU;AACjB,QAAA,SAAS,EAAE;YACT,sBAAsB;YACtB,yBAAyB;YACzB,iBAAiB;YACjB,yBAAyB;AAC1B,SAAA;AACF,KAAA;AACD,IAAA;AACE,QAAA,EAAE,EAAE,MAAM;AACV,QAAA,KAAK,EAAE,WAAW;AAClB,QAAA,SAAS,EAAE;YACT,kBAAkB;YAClB,wBAAwB;YACxB,mBAAmB;YACnB,oBAAoB;AACrB,SAAA;AACF,KAAA;AACD,IAAA;AACE,QAAA,EAAE,EAAE,OAAO;AACX,QAAA,KAAK,EAAE,wBAAwB;AAC/B,QAAA,SAAS,EAAE,CAAC,oBAAoB,EAAE,4BAA4B,CAAC;AAChE,KAAA;CACF;AAEK,SAAU,aAAa,CAC3B,KAAoB,EAAA;AAEpB,IAAA,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC;AACnE;AAEM,SAAU,eAAe,CAC7B,SAA4B,EAAA;AAE5B,IAAA,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;QACpC,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjD,OAAO,KAAK,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE;AAC7B,IAAA,CAAC,CAAC;AACJ;;AC1fA,MAAM,UAAU,GAAG,sCAAsC;AAElD,MAAM,sBAAsB,GAAG,eAAe;AAErD,MAAM,gBAAgB,GAAG,CAAA;;;;IAIrB;AAEE,SAAU,sBAAsB,CACpC,IAAkB,EAClB,KAAa,EAAA;AAEb,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;IACpE,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,EAAE;IACX;AAEA,IAAA,IAAI,IAAI,KAAK,OAAO,EAAE;AACpB,QAAA,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC;QAChC,IAAI,GAAG,EAAE;AACP,YAAA,OAAO,GAAG;QACZ;IACF;IAEA,OAAO,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;AACtD;AAEM,SAAU,WAAW,CAAC,KAAa,EAAA;AACvC,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE;AAC5B,IAAA,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QAC/B,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK;AACvB,QAAA,OAAO,IAAI,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC,WAAW,EAAE;IAClD;AAEA,IAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACnC,QAAA,OAAO,OAAO,CAAC,WAAW,EAAE;IAC9B;AAEA,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,gBAAgB,CAAC,GAAW,EAAA;IAC1C,MAAM,MAAM,GAA2B,EAAE;IAEzC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;AAC5C,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE;YACV;QACF;AAEA,QAAA,MAAM,KAAK,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,KAAK,EAAE;AACT,YAAA,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK;QAC1B;IACF;AAEA,IAAA,OAAO,MAAM;AACf;AAEM,SAAU,gBAAgB,CAC9B,SAA2C,EAAA;AAE3C,IAAA,MAAM,QAAQ,GAA2B,EAAE,GAAG,kBAAkB,EAAE;AAClE,IAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QACzD,IAAI,QAAQ,IAAI,kBAAkB,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE;AAClD,YAAA,QAAQ,CAAC,QAAQ,CAAC,GAAG,KAAK;QAC5B;IACF;AACA,IAAA,OAAO,QAAQ;AACjB;AAEM,SAAU,wBAAwB,CACtC,MAAwC,EAAA;IAExC,MAAM,SAAS,GAA2B,EAAE;AAC5C,IAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACtD,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE;YACV;QACF;QAEA,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAC5D,IAAI,UAAU,IAAI,UAAU,KAAK,KAAK,CAAC,YAAY,EAAE;AACnD,YAAA,SAAS,CAAC,QAAQ,CAAC,GAAG,UAAU;QAClC;IACF;AACA,IAAA,OAAO,SAAS;AAClB;AAEM,SAAU,oBAAoB,CAClC,MAAwC,EAAA;IAExC,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;AAC5C,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,YAAY;AAC1D,QAAA,OAAO,KAAK,KAAK,CAAC,QAAQ,CAAA,EAAA,EAAK,KAAK,GAAG;AACzC,IAAA,CAAC,CAAC;IAEF,OAAO,CAAA,EAAG,gBAAgB,CAAA,WAAA,EAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,KAAA,CAAO;AACjE;AAEM,SAAU,gBAAgB,CAAC,QAAgB,EAAE,QAAgB,EAAA;AACjE,IAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACrE,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;AAC1C,IAAA,MAAM,CAAC,IAAI,GAAG,GAAG;AACjB,IAAA,MAAM,CAAC,QAAQ,GAAG,QAAQ;AAC1B,IAAA,MAAM,CAAC,GAAG,GAAG,UAAU;AACvB,IAAA,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,MAAM,CAAC,KAAK,EAAE;IACd,MAAM,CAAC,MAAM,EAAE;AACf,IAAA,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC;AAC1B;;MC7Ea,SAAS,CAAA;AACD,IAAA,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;AACpC,IAAA,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC;AACtC,IAAA,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;AACpC,IAAA,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;AAClC,IAAA,aAAa,GAAG,aAAa,CAAC,SAAS,CAAC;AAE1C,IAAA,SAAS,GAAG,MAAM,CAAyB,EAAE,gFAAC;AAC5C,IAAA,SAAS,GAAG,MAAM,CAA2B,IAAI,gFAAC;AAClD,IAAA,aAAa,GAAG,MAAM,CAAC,EAAE,oFAAC;AAE1B,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AAChD,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE;AAClC,QAAA,OAAO,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE;AAC9D,IAAA,CAAC,qFAAC;IAEiB,YAAY,GAAG,QAAQ,CACxC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,mFAC/C;AAEkB,IAAA,UAAU,GAAG,QAAQ,CAAC,MACvC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE;AAC5B,SAAA,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,KAAK,EAAE;AAClD,SAAA,IAAI,CAAC,IAAI,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,YAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CACd;;IAGD,QAAQ,GAAA;QACN,OAAO,oBAAoB,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACjE;;AAGA,IAAA,YAAY,CAAC,GAAW,EAAA;AACtB,QAAA,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC;QACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM;QAC7C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAEpD,QAAA,IAAI,UAAU,KAAK,CAAC,EAAE;AACpB,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,uCAAuC,CAAC;YAC/D;QACF;QAEA,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,CAAA,SAAA,EAAY,UAAU,CAAA,0DAAA,CAA4D,CACnF;IACH;IAEA,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;AACtB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,gEAAgE,CAAC;IAC1F;IAEU,eAAe,GAAA;QACvB,gBAAgB,CAAC,sBAAsB,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzD,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,CAAA,WAAA,EAAc,sBAAsB,CAAA,sDAAA,CAAwD,CAC7F;IACH;IAEU,MAAM,YAAY,CAAC,KAAY,EAAA;AACvC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM;AAC1B,QAAA,IAAI,EAAE,KAAK,YAAY,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE;YAChE;QACF;AAEA,QAAA,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACvC,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;AACtB,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEU,IAAA,WAAW,CAAC,KAAyB,EAAA;AAC7C,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;AACjB,YAAA,EAAE,EAAE,CAAA,MAAA,EAAS,KAAK,CAAC,QAAQ,CAAA,CAAE;YAC7B,KAAK,EAAE,KAAK,CAAC,IAAI;AACjB,YAAA,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;AAC5B,SAAA,CAAC;IACJ;AAEU,IAAA,YAAY,CAAC,QAAgB,EAAA;AACrC,QAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC;QACrE,IAAI,CAAC,MAAM,EAAE;YACX;QACF;AAEA,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;AACjB,YAAA,EAAE,EAAE,CAAA,OAAA,EAAU,MAAM,CAAC,EAAE,CAAA,CAAE;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,SAAS,EAAE,MAAM,CAAC,SAAS;AAC5B,SAAA,CAAC;IACJ;IAEU,cAAc,GAAA;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1B;AAEU,IAAA,eAAe,CAAC,QAAgB,EAAA;AACxC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE;AAClC,QAAA,OAAO,SAAS,EAAE,EAAE,KAAK,CAAA,MAAA,EAAS,QAAQ,EAAE;IAC9C;AAEU,IAAA,gBAAgB,CAAC,QAAgB,EAAA;QACzC,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,KAAK,CAAA,OAAA,EAAU,QAAQ,CAAA,CAAE;IACtD;AAEU,IAAA,UAAU,CAAC,QAAgB,EAAA;AACnC,QAAA,OAAO,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;IACrC;AAEU,IAAA,YAAY,CAAC,QAAgB,EAAA;AACrC,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,YAAY,IAAI,EAAE;IAC9F;AAEU,IAAA,YAAY,CAAC,QAAgB,EAAA;QACrC,OAAO,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,YAAY,IAAI,EAAE;IAChE;AAEU,IAAA,eAAe,CAAC,QAAgB,EAAA;QACxC,OAAO,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjD;AAEU,IAAA,YAAY,CAAC,QAAgB,EAAA;QACrC,OAAO,CAAA,gBAAA,EAAmB,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA,CAAE;IACnE;IAEU,YAAY,CAAC,QAAgB,EAAE,KAAY,EAAA;AACnD,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAC3B,QAAA,IAAI,EAAE,MAAM,YAAY,gBAAgB,CAAC,EAAE;YACzC;QACF;QAEA,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC;IAC5C;AAEU,IAAA,UAAU,CAAC,QAAgB,EAAA;QACnC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,KAAI;AAChC,YAAA,IAAI,EAAE,QAAQ,IAAI,OAAO,CAAC,EAAE;AAC1B,gBAAA,OAAO,OAAO;YAChB;AAEA,YAAA,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE;AAC3B,YAAA,OAAO,IAAI,CAAC,QAAQ,CAAC;AACrB,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;IACJ;IAEQ,aAAa,CAAC,QAAgB,EAAE,GAAW,EAAA;QACjD,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE;YACV;QACF;QAEA,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC;QAC1D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,KAAI;AAChC,YAAA,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE;YAC3B,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,KAAK,CAAC,YAAY,EAAE;AACpD,gBAAA,OAAO,IAAI,CAAC,QAAQ,CAAC;YACvB;iBAAO;AACL,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,UAAU;YAC7B;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;IACJ;wGAjKW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAT,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,SAAS,4MC7CtB,s5eA+VA,EAAA,MAAA,EAAA,CAAA,qwPAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FDlTa,SAAS,EAAA,UAAA,EAAA,CAAA;kBAXrB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,YAAY,EAAA,eAAA,EACL,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,YAAY;AACnB,wBAAA,SAAS,EAAE,cAAc;AACzB,wBAAA,kBAAkB,EAAE,kBAAkB;AACvC,qBAAA,EAAA,QAAA,EAAA,s5eAAA,EAAA,MAAA,EAAA,CAAA,qwPAAA,CAAA,EAAA;;;AE3CH;;AAEG;;ACFH;;AAEG;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retalia/pos-components",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
@@ -20,6 +20,10 @@
20
20
  ".": {
21
21
  "types": "./types/retalia-pos-components.d.ts",
22
22
  "default": "./fesm2022/retalia-pos-components.mjs"
23
+ },
24
+ "./services": {
25
+ "types": "./types/retalia-pos-components-services.d.ts",
26
+ "default": "./fesm2022/retalia-pos-components-services.mjs"
23
27
  }
24
28
  },
25
29
  "peerDependencies": {
@@ -0,0 +1,170 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken } from '@angular/core';
3
+ import { HttpInterceptorFn } from '@angular/common/http';
4
+ import { Observable } from 'rxjs';
5
+
6
+ interface PosApiConfig {
7
+ /** Origin for HeadlessAPI. Empty string when the host app proxies `/api`. */
8
+ readonly apiBaseUrl: string;
9
+ /** Cookie holding the Portal Bearer token (paste in local dev). */
10
+ readonly tokenCookieName: string;
11
+ /** Cookie holding the shop id sent as `Shop-Context`. */
12
+ readonly shopContextCookieName: string;
13
+ readonly getAccessToken?: () => string | null;
14
+ readonly getShopContext?: () => string | null;
15
+ }
16
+ declare const DEFAULT_POS_API_CONFIG: PosApiConfig;
17
+ declare const POS_API_CONFIG: InjectionToken<PosApiConfig>;
18
+ declare function readAccessToken(config: PosApiConfig): string | null;
19
+ declare function readShopContext(config: PosApiConfig): string | null;
20
+
21
+ /** Attaches Bearer + Shop-Context from cookies (or host overrides). */
22
+ declare const posApiInterceptor: HttpInterceptorFn;
23
+
24
+ interface ClerkSession {
25
+ readonly clerkNumber: string;
26
+ readonly displayName: string;
27
+ readonly languageCode: string;
28
+ readonly isManager: boolean;
29
+ }
30
+ declare class ClerkAuthError extends Error {
31
+ readonly name = "ClerkAuthError";
32
+ constructor(message: string);
33
+ }
34
+ declare class ClerkAuthService {
35
+ private readonly http;
36
+ /**
37
+ * Looks up the clerk and compares the keypad password in this service.
38
+ * Hashed passwords use the HeadlessPOS SHA-256 check. Not a dedicated
39
+ * sign-in endpoint — replace when ID-647 / PosIdentity lands.
40
+ */
41
+ signIn(clerkNumber: string, password: string): Observable<ClerkSession>;
42
+ private toSession;
43
+ static ɵfac: i0.ɵɵFactoryDeclaration<ClerkAuthService, never>;
44
+ static ɵprov: i0.ɵɵInjectableDeclaration<ClerkAuthService>;
45
+ }
46
+
47
+ /** Canonical POS state envelope (PosSharedPackages 0.0.1). Not a display DTO. */
48
+ interface Session {
49
+ tenantId: string;
50
+ storeId: string;
51
+ deviceId: string;
52
+ clerkId: string;
53
+ mode: string;
54
+ locale: string;
55
+ offline: boolean;
56
+ }
57
+ interface Vat {
58
+ rate: number;
59
+ amount: number;
60
+ included: boolean;
61
+ }
62
+ type LineModifier = Record<string, unknown>;
63
+ type LineDiscount = Record<string, unknown>;
64
+ interface BasketLine {
65
+ lineId: number;
66
+ sku: string;
67
+ name: string;
68
+ qty: number;
69
+ unitPrice: number;
70
+ lineTotal: number;
71
+ vat: Vat;
72
+ modifiers: LineModifier[];
73
+ discounts: LineDiscount[];
74
+ struckThrough: boolean;
75
+ }
76
+ interface Basket {
77
+ basketId: string;
78
+ lines: BasketLine[];
79
+ }
80
+ interface Totals {
81
+ gross: number;
82
+ net: number;
83
+ vat: number;
84
+ discount: number;
85
+ due: number;
86
+ currency: string;
87
+ }
88
+ interface Payment {
89
+ tender: string;
90
+ amount: number;
91
+ tendered: number;
92
+ change: number;
93
+ state: string;
94
+ }
95
+ interface Document {
96
+ number: string;
97
+ receiptReady: boolean;
98
+ }
99
+ interface Constraints {
100
+ currency: string;
101
+ offlineCapable: boolean;
102
+ }
103
+ interface ValidationIssue {
104
+ code: string;
105
+ severity: string;
106
+ }
107
+ interface Workflow {
108
+ step: string;
109
+ next: string[];
110
+ }
111
+ type Advisory = Record<string, unknown>;
112
+ interface PosStateEnvelope {
113
+ schemaVersion: string;
114
+ correlationId: string;
115
+ session: Session;
116
+ state: string;
117
+ basket: Basket;
118
+ totals: Totals;
119
+ payments: Payment[];
120
+ document: Document;
121
+ availableActions: string[];
122
+ constraints: Constraints;
123
+ validation: ValidationIssue[];
124
+ workflow: Workflow;
125
+ advisory: Advisory | null;
126
+ }
127
+
128
+ interface AddItemCommand {
129
+ readonly basketId: string;
130
+ readonly sku: string;
131
+ readonly qty: number;
132
+ }
133
+ interface ChangeQuantityCommand {
134
+ readonly basketId: string;
135
+ readonly lineId: number;
136
+ readonly qty: number;
137
+ }
138
+ interface ClearBasketCommand {
139
+ readonly basketId: string;
140
+ }
141
+ interface TenderCashCommand {
142
+ readonly basketId: string;
143
+ readonly amount: number;
144
+ }
145
+ interface NewSaleCommand {
146
+ readonly basketId: string;
147
+ }
148
+ /**
149
+ * Thin HTTP client for open-till sale commands (command in → PosStateEnvelope out).
150
+ *
151
+ * Keep as one client while the surface is small. When basket, tender, and sale
152
+ * lifecycle each grow their own handful of methods, split by subdomain, e.g.:
153
+ * - basket: addItem / changeQuantity / clearBasket (+ discounts, modifiers, …)
154
+ * - tender: tenderCash (+ card, void payment, …)
155
+ * - sale: newSale (+ suspend, recall, …)
156
+ * Extract is cheap; avoid splitting early into near-empty clients.
157
+ */
158
+ declare class PosCommandsClient {
159
+ private readonly http;
160
+ addItem(command: AddItemCommand, key?: string): Observable<PosStateEnvelope>;
161
+ changeQuantity(command: ChangeQuantityCommand, key?: string): Observable<PosStateEnvelope>;
162
+ clearBasket(command: ClearBasketCommand, key?: string): Observable<PosStateEnvelope>;
163
+ tenderCash(command: TenderCashCommand, key?: string): Observable<PosStateEnvelope>;
164
+ newSale(command: NewSaleCommand, key?: string): Observable<PosStateEnvelope>;
165
+ static ɵfac: i0.ɵɵFactoryDeclaration<PosCommandsClient, never>;
166
+ static ɵprov: i0.ɵɵInjectableDeclaration<PosCommandsClient>;
167
+ }
168
+
169
+ export { ClerkAuthError, ClerkAuthService, DEFAULT_POS_API_CONFIG, POS_API_CONFIG, PosCommandsClient, posApiInterceptor, readAccessToken, readShopContext };
170
+ export type { AddItemCommand, Advisory, Basket, BasketLine, ChangeQuantityCommand, ClearBasketCommand, ClerkSession, Constraints, Document, LineDiscount, LineModifier, NewSaleCommand, Payment, PosApiConfig, PosStateEnvelope, Session, TenderCashCommand, Totals, ValidationIssue, Vat, Workflow };