@lieselthuriot/widget-renderer 0.0.0-stage → 0.2.0

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.
@@ -0,0 +1,1697 @@
1
+ import { a as dutchWidgetRendererLocale, i as defaultWidgetRendererLocale, n as chartAriaLabel, o as frenchWidgetRendererLocale, r as WidgetTooltip, s as germanWidgetRendererLocale, t as chartAccessibilitySummary } from "./lieselthuriot-widget-renderer-chart-accessibility-BzH2alxy.mjs";
2
+ import * as i0 from "@angular/core";
3
+ import { Component, computed, effect, inject, input, output, signal, viewChild } from "@angular/core";
4
+ function normalizeElement(element) {
5
+ return {
6
+ ...element,
7
+ ...element.type === "text" && !element.style.padding ? { style: {
8
+ ...element.style,
9
+ padding: {
10
+ vertical: 0,
11
+ horizontal: 0
12
+ }
13
+ } } : {},
14
+ ...element.type === "button" ? {
15
+ requestRefresh: element.requestRefresh ?? false,
16
+ showOnlyOnHover: element.showOnlyOnHover ?? false
17
+ } : {},
18
+ sensitive: element.type === "divider" ? false : element.sensitive
19
+ };
20
+ }
21
+ function normalizeWidgetInput(widget) {
22
+ return {
23
+ ...widget,
24
+ elements: widget.elements.map(normalizeElement)
25
+ };
26
+ }
27
+ var WidgetValidationError = class extends Error {
28
+ issues;
29
+ constructor(issues) {
30
+ super(issues.map(({ path, message }) => `${path}: ${message}`).join("; "));
31
+ this.issues = issues;
32
+ this.name = "WidgetValidationError";
33
+ }
34
+ };
35
+ const anchors = [
36
+ "top left",
37
+ "top center",
38
+ "top right",
39
+ "center left",
40
+ "center",
41
+ "center right",
42
+ "bottom left",
43
+ "bottom center",
44
+ "bottom right"
45
+ ];
46
+ const elementTypes = [
47
+ "text",
48
+ "image",
49
+ "button",
50
+ "divider",
51
+ "pie",
52
+ "donut",
53
+ "funnel",
54
+ "gauge",
55
+ "bar",
56
+ "line",
57
+ "progress"
58
+ ];
59
+ const gridUnits = [
60
+ "pixel",
61
+ "auto",
62
+ "star"
63
+ ];
64
+ function isRecord(value) {
65
+ return typeof value === "object" && value !== null && !Array.isArray(value);
66
+ }
67
+ function isString(value) {
68
+ return typeof value === "string";
69
+ }
70
+ function isBoolean(value) {
71
+ return typeof value === "boolean";
72
+ }
73
+ function isFiniteNumber(value) {
74
+ return typeof value === "number" && Number.isFinite(value);
75
+ }
76
+ function isOneOf(value, values) {
77
+ return typeof value === "string" && values.includes(value);
78
+ }
79
+ function addIssue(issues, path, message) {
80
+ issues.push({
81
+ path,
82
+ message
83
+ });
84
+ }
85
+ function requiredString(value, path, issues, allowEmpty = false) {
86
+ if (!isString(value) || !allowEmpty && value.length === 0) {
87
+ addIssue(issues, path, allowEmpty ? "must be a string" : "must be a non-empty string");
88
+ return false;
89
+ }
90
+ return true;
91
+ }
92
+ function requiredBoolean(value, path, issues) {
93
+ if (!isBoolean(value)) {
94
+ addIssue(issues, path, "must be a boolean");
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+ function requiredNumber(value, path, issues, minimum = 0) {
100
+ if (!isFiniteNumber(value) || value < minimum) {
101
+ addIssue(issues, path, `must be a finite number greater than or equal to ${minimum}`);
102
+ return false;
103
+ }
104
+ return true;
105
+ }
106
+ function validateTextFont(value, path, issues) {
107
+ if (!isRecord(value)) {
108
+ addIssue(issues, path, "must be an object");
109
+ return;
110
+ }
111
+ requiredNumber(value["size"], `${path}.size`, issues, 1);
112
+ for (const key of [
113
+ "bold",
114
+ "italic",
115
+ "underline",
116
+ "strikethrough"
117
+ ]) if (value[key] !== void 0) requiredBoolean(value[key], `${path}.${key}`, issues);
118
+ }
119
+ function validateChartFont(value, path, issues) {
120
+ if (!isRecord(value)) {
121
+ addIssue(issues, path, "must be an object");
122
+ return;
123
+ }
124
+ requiredNumber(value["size"], `${path}.size`, issues, 1);
125
+ }
126
+ function validateGrid(value, path, issues) {
127
+ if (!isRecord(value)) {
128
+ addIssue(issues, path, "must be an object");
129
+ return;
130
+ }
131
+ requiredNumber(value["row"], `${path}.row`, issues);
132
+ requiredNumber(value["column"], `${path}.column`, issues);
133
+ requiredNumber(value["rowSpan"], `${path}.rowSpan`, issues, 1);
134
+ requiredNumber(value["columnSpan"], `${path}.columnSpan`, issues, 1);
135
+ if (value["anchor"] !== void 0 && !isOneOf(value["anchor"], anchors)) addIssue(issues, `${path}.anchor`, "has an unsupported value");
136
+ }
137
+ function validateStyle(value, path, issues, axisMode = "optional", fontMode = "chart", requiredColors = []) {
138
+ if (!isRecord(value)) {
139
+ addIssue(issues, path, "must be an object");
140
+ return;
141
+ }
142
+ (fontMode === "text" ? validateTextFont : validateChartFont)(value["font"], `${path}.font`, issues);
143
+ const color = value["color"];
144
+ if (isRecord(color)) {
145
+ for (const key of [
146
+ "legend",
147
+ "title",
148
+ "line",
149
+ "fill",
150
+ "track"
151
+ ]) if (requiredColors.includes(key) || color[key] !== void 0) requiredString(color[key], `${path}.color.${key}`, issues, true);
152
+ } else if (requiredColors.length) addIssue(issues, `${path}.color`, "must be an object");
153
+ else requiredString(color, `${path}.color`, issues, true);
154
+ if (axisMode === "required") {
155
+ if (!isRecord(value["axis"])) addIssue(issues, `${path}.axis`, "must be an object");
156
+ else for (const key of [
157
+ "label",
158
+ "line",
159
+ "grid"
160
+ ]) requiredString(value["axis"][key], `${path}.axis.${key}`, issues, true);
161
+ } else if (axisMode === "forbidden" && value["axis"] !== void 0) addIssue(issues, `${path}.axis`, "is not supported for this chart");
162
+ }
163
+ function validateDataPoints(value, path, issues, allowNullColor) {
164
+ if (!Array.isArray(value)) {
165
+ addIssue(issues, path, "must be an array");
166
+ return;
167
+ }
168
+ value.forEach((point, index) => {
169
+ const pointPath = `${path}[${index}]`;
170
+ if (!isRecord(point)) {
171
+ addIssue(issues, pointPath, "must be an object");
172
+ return;
173
+ }
174
+ requiredString(point["label"], `${pointPath}.label`, issues, true);
175
+ requiredNumber(point["value"], `${pointPath}.value`, issues);
176
+ if (point["color"] === void 0) {
177
+ if (!allowNullColor) addIssue(issues, `${pointPath}.color`, "must be a string");
178
+ } else if (point["color"] === null) {
179
+ if (!allowNullColor) addIssue(issues, `${pointPath}.color`, "must be a string");
180
+ } else requiredString(point["color"], `${pointPath}.color`, issues, true);
181
+ });
182
+ }
183
+ function validateProgressData(value, path, issues) {
184
+ if (!isRecord(value)) {
185
+ addIssue(issues, path, "must be an object");
186
+ return;
187
+ }
188
+ requiredNumber(value["min"], `${path}.min`, issues);
189
+ requiredNumber(value["max"], `${path}.max`, issues);
190
+ if (typeof value["min"] === "number" && typeof value["max"] === "number" && value["min"] >= value["max"]) addIssue(issues, `${path}.max`, "must be greater than min");
191
+ const items = value["items"];
192
+ if (!Array.isArray(items)) {
193
+ addIssue(issues, `${path}.items`, "must be an array");
194
+ return;
195
+ }
196
+ let total = 0;
197
+ items.forEach((item, index) => {
198
+ const itemPath = `${path}.items[${index}]`;
199
+ if (!isRecord(item)) {
200
+ addIssue(issues, itemPath, "must be an object");
201
+ return;
202
+ }
203
+ if (!isOneOf(item["kind"], ["segment", "gap"])) {
204
+ addIssue(issues, `${itemPath}.kind`, "has an unsupported value");
205
+ return;
206
+ }
207
+ requiredNumber(item["value"], `${itemPath}.value`, issues);
208
+ if (typeof item["value"] === "number" && Number.isFinite(item["value"])) {
209
+ if (item["value"] < 0) addIssue(issues, `${itemPath}.value`, "must not be negative");
210
+ else total += item["value"];
211
+ }
212
+ if (item["kind"] === "segment") {
213
+ requiredString(item["label"], `${itemPath}.label`, issues);
214
+ requiredString(item["color"], `${itemPath}.color`, issues);
215
+ requiredBoolean(item["active"], `${itemPath}.active`, issues);
216
+ }
217
+ });
218
+ if (typeof value["min"] === "number" && typeof value["max"] === "number" && Number.isFinite(value["min"]) && Number.isFinite(value["max"]) && total > value["max"] - value["min"]) addIssue(issues, `${path}.items`, "total value must not exceed the progress range");
219
+ }
220
+ function validateElement(value, path, issues) {
221
+ if (!isRecord(value)) {
222
+ addIssue(issues, path, "must be an object");
223
+ return;
224
+ }
225
+ const issuePath = path;
226
+ if (!isOneOf(value["type"], elementTypes)) {
227
+ addIssue(issues, `${issuePath}.type`, "has an unsupported value");
228
+ return;
229
+ }
230
+ validateGrid(value["grid"], `${issuePath}.grid`, issues);
231
+ if (value["type"] !== "divider" || value["sensitive"] !== void 0) requiredBoolean(value["sensitive"], `${issuePath}.sensitive`, issues);
232
+ switch (value["type"]) {
233
+ case "text":
234
+ requiredString(value["text"], `${issuePath}.text`, issues, true);
235
+ validateStyle(value["style"], `${issuePath}.style`, issues, "optional", "text");
236
+ if (!isRecord(value["style"])) break;
237
+ requiredString(value["style"]["color"], `${issuePath}.style.color`, issues, true);
238
+ if (value["style"]["background"] !== void 0) requiredString(value["style"]["background"], `${issuePath}.style.background`, issues, true);
239
+ if (value["style"]["padding"] !== void 0) {
240
+ const padding = value["style"]["padding"];
241
+ if (padding !== null && !isRecord(padding)) addIssue(issues, `${issuePath}.style.padding`, "must be an object or null");
242
+ else if (padding !== null) {
243
+ requiredNumber(padding["vertical"], `${issuePath}.style.padding.vertical`, issues);
244
+ requiredNumber(padding["horizontal"], `${issuePath}.style.padding.horizontal`, issues);
245
+ }
246
+ }
247
+ if (value["style"]["radius"] !== void 0) requiredNumber(value["style"]["radius"], `${issuePath}.style.radius`, issues);
248
+ if (!isOneOf(value["style"]["align"], [
249
+ "left",
250
+ "center",
251
+ "right"
252
+ ])) addIssue(issues, `${issuePath}.style.align`, "has an unsupported value");
253
+ requiredBoolean(value["style"]["wrap"], `${issuePath}.style.wrap`, issues);
254
+ break;
255
+ case "image":
256
+ requiredString(value["source"], `${issuePath}.source`, issues);
257
+ requiredString(value["alt"], `${issuePath}.alt`, issues, true);
258
+ if (!isOneOf(value["fit"], [
259
+ "cover",
260
+ "contain",
261
+ "fill"
262
+ ])) addIssue(issues, `${issuePath}.fit`, "has an unsupported value");
263
+ requiredNumber(value["radius"], `${issuePath}.radius`, issues);
264
+ break;
265
+ case "button":
266
+ requiredString(value["label"], `${issuePath}.label`, issues, true);
267
+ if (!isOneOf(value["method"], ["get", "post"])) addIssue(issues, `${issuePath}.method`, "has an unsupported value");
268
+ requiredString(value["url"], `${issuePath}.url`, issues, true);
269
+ if (value["body"] !== void 0 && value["body"] !== null && !isString(value["body"])) addIssue(issues, `${issuePath}.body`, "must be a string or null");
270
+ if (value["method"] === "get" && value["body"] !== void 0 && value["body"] !== null) addIssue(issues, `${issuePath}.body`, "must be empty for GET buttons");
271
+ if (value["requestRefresh"] !== void 0) requiredBoolean(value["requestRefresh"], `${issuePath}.requestRefresh`, issues);
272
+ if (value["showOnlyOnHover"] !== void 0) requiredBoolean(value["showOnlyOnHover"], `${issuePath}.showOnlyOnHover`, issues);
273
+ if (!isOneOf(value["style"], ["solid", "outline"])) addIssue(issues, `${issuePath}.style`, "has an unsupported value");
274
+ break;
275
+ case "divider":
276
+ if (!isOneOf(value["orientation"], ["horizontal", "vertical"])) addIssue(issues, `${issuePath}.orientation`, "has an unsupported value");
277
+ if (!isRecord(value["style"])) addIssue(issues, `${issuePath}.style`, "must be an object");
278
+ else requiredString(value["style"]["color"], `${issuePath}.style.color`, issues);
279
+ break;
280
+ case "gauge":
281
+ if (value["title"] !== void 0) requiredString(value["title"], `${issuePath}.title`, issues, true);
282
+ requiredBoolean(value["showLegend"], `${issuePath}.showLegend`, issues);
283
+ validateRange(value["data"], `${issuePath}.data`, issues, false);
284
+ validateStyle(value["style"], `${issuePath}.style`, issues, "optional", "chart", [
285
+ "legend",
286
+ "title",
287
+ "fill",
288
+ "track"
289
+ ]);
290
+ break;
291
+ case "progress":
292
+ if (value["title"] !== void 0) requiredString(value["title"], `${issuePath}.title`, issues, true);
293
+ validateProgressData(value["data"], `${issuePath}.data`, issues);
294
+ validateStyle(value["style"], `${issuePath}.style`, issues, "optional", "chart", [
295
+ "legend",
296
+ "title",
297
+ "track"
298
+ ]);
299
+ if (isRecord(value["style"])) {
300
+ const radius = value["style"]["radius"];
301
+ if (radius !== void 0 && radius !== null) {
302
+ if (!isRecord(radius)) addIssue(issues, `${issuePath}.style.radius`, "must be an object, null, or undefined");
303
+ else {
304
+ requiredNumber(radius["segment"], `${issuePath}.style.radius.segment`, issues);
305
+ requiredNumber(radius["track"], `${issuePath}.style.radius.track`, issues);
306
+ }
307
+ }
308
+ }
309
+ requiredBoolean(value["showLegend"], `${issuePath}.showLegend`, issues);
310
+ break;
311
+ case "pie":
312
+ case "donut":
313
+ case "funnel":
314
+ case "bar":
315
+ case "line":
316
+ if (value["title"] !== void 0) requiredString(value["title"], `${issuePath}.title`, issues, true);
317
+ requiredBoolean(value["showLegend"], `${issuePath}.showLegend`, issues);
318
+ validateDataPoints(value["data"], `${issuePath}.data`, issues, value["type"] === "line");
319
+ validateStyle(value["style"], `${issuePath}.style`, issues, value["type"] === "pie" || value["type"] === "donut" || value["type"] === "funnel" ? "forbidden" : "required", "chart", value["type"] === "bar" || value["type"] === "line" ? [
320
+ "legend",
321
+ "title",
322
+ "line"
323
+ ] : ["legend", "title"]);
324
+ }
325
+ }
326
+ function validateRange(value, path, issues, hasLabel) {
327
+ if (!isRecord(value)) {
328
+ addIssue(issues, path, "must be an object");
329
+ return;
330
+ }
331
+ if (hasLabel) requiredString(value["label"], `${path}.label`, issues, true);
332
+ if (hasLabel) {
333
+ optionalString(value["separator"], `${path}.separator`, issues);
334
+ optionalString(value["suffix"], `${path}.suffix`, issues);
335
+ }
336
+ requiredNumber(value["value"], `${path}.value`, issues);
337
+ requiredNumber(value["min"], `${path}.min`, issues);
338
+ requiredNumber(value["max"], `${path}.max`, issues);
339
+ if (isFiniteNumber(value["min"]) && isFiniteNumber(value["max"]) && value["min"] >= value["max"]) addIssue(issues, path, "minimum must be less than maximum");
340
+ }
341
+ function optionalString(value, path, issues) {
342
+ if (value !== void 0 && value !== null && !isString(value)) addIssue(issues, path, "must be a string, null, or undefined");
343
+ }
344
+ function validateWidget(value) {
345
+ const issues = [];
346
+ if (!isRecord(value)) return [{
347
+ path: "$",
348
+ message: "must be an object"
349
+ }];
350
+ if (value["version"] !== 2) addIssue(issues, "version", "must be 2");
351
+ requiredString(value["id"], "id", issues, true);
352
+ if (!isOneOf(value["size"], [
353
+ "mini",
354
+ "compact",
355
+ "tall",
356
+ "square",
357
+ "wide",
358
+ "mega",
359
+ "banner",
360
+ "hero"
361
+ ])) addIssue(issues, "size", "must be mini, compact, tall, square, wide, mega, banner, or hero");
362
+ for (const key of ["rows", "columns"]) {
363
+ if (!Array.isArray(value[key]) || value[key].length === 0) {
364
+ addIssue(issues, key, "must be a non-empty array");
365
+ continue;
366
+ }
367
+ value[key].forEach((track, index) => {
368
+ const path = `${key}[${index}]`;
369
+ if (!isRecord(track)) {
370
+ addIssue(issues, path, "must be an object");
371
+ return;
372
+ }
373
+ const unit = track["unit"];
374
+ if (!isOneOf(unit, gridUnits)) addIssue(issues, `${path}.unit`, "has an unsupported value");
375
+ if (unit === "auto") {
376
+ if (track["size"] !== void 0) addIssue(issues, `${path}.size`, "must not be set for auto tracks");
377
+ } else requiredNumber(track["size"], `${path}.size`, issues, 0);
378
+ });
379
+ }
380
+ const background = value["background"];
381
+ if (!isRecord(background)) addIssue(issues, "background", "must be an object");
382
+ else {
383
+ requiredBoolean(background["sensitive"], "background.sensitive", issues);
384
+ requiredBoolean(background["repeat"], "background.repeat", issues);
385
+ if (!isOneOf(background["size"], [
386
+ "cover",
387
+ "contain",
388
+ "auto"
389
+ ])) addIssue(issues, "background.size", "has an unsupported value");
390
+ if (!isOneOf(background["anchor"], anchors)) addIssue(issues, "background.anchor", "has an unsupported value");
391
+ if (background["image"] !== void 0) requiredString(background["image"], "background.image", issues, true);
392
+ }
393
+ const refresh = value["refresh"];
394
+ if (refresh !== void 0 && refresh !== null && !isRecord(refresh)) addIssue(issues, "refresh", "must be an object or null");
395
+ else if (isRecord(refresh)) {
396
+ requiredBoolean(refresh["enabled"], "refresh.enabled", issues);
397
+ requiredString(refresh["label"], "refresh.label", issues, true);
398
+ }
399
+ if (!Array.isArray(value["elements"])) addIssue(issues, "elements", "must be an array");
400
+ else value["elements"].forEach((element, index) => validateElement(element, `elements[${index}]`, issues));
401
+ return issues;
402
+ }
403
+ function runRule(rule, widget) {
404
+ const mode = typeof rule === "function" ? "block" : rule.mode ?? "block";
405
+ try {
406
+ return (typeof rule === "function" ? rule(widget) : rule.validate(widget)).map((issue) => ({
407
+ ...issue,
408
+ severity: mode
409
+ }));
410
+ } catch (error) {
411
+ return [{
412
+ path: "",
413
+ message: `Validation rule failed: ${error instanceof Error ? error.message : String(error)}`,
414
+ severity: mode
415
+ }];
416
+ }
417
+ }
418
+ function safeParseWidgetInput(value, options = {}) {
419
+ const builtInIssues = validateWidget(value);
420
+ if (builtInIssues.length) return {
421
+ success: false,
422
+ issues: builtInIssues
423
+ };
424
+ const data = value;
425
+ const issues = (options.rules ?? []).flatMap((rule) => runRule(rule, data));
426
+ return issues.some((issue) => issue.severity === "block") ? {
427
+ success: false,
428
+ issues
429
+ } : {
430
+ success: true,
431
+ data,
432
+ issues
433
+ };
434
+ }
435
+ function parseWidgetInput(value, options = {}) {
436
+ const result = safeParseWidgetInput(value, options);
437
+ if (!result.success) throw new WidgetValidationError(result.issues);
438
+ return result.data;
439
+ }
440
+ function isWidgetContract(value) {
441
+ return safeParseWidgetInput(value).success;
442
+ }
443
+ function isWidget(value) {
444
+ return safeParseWidgetInput(value).success;
445
+ }
446
+ const WIDGET_FINGERPRINT_VERSION = 1;
447
+ function computeWidgetFingerprint(input) {
448
+ const result = safeParseWidgetInput(input);
449
+ if (!result.success) return null;
450
+ const canonical = canonicalJson(widgetShape(result.data));
451
+ return `wfp:1:${sha256Hex(new TextEncoder().encode(canonical))}`;
452
+ }
453
+ function widgetShape(widget) {
454
+ return {
455
+ version: widget.version,
456
+ size: widget.size,
457
+ rows: widget.rows,
458
+ columns: widget.columns,
459
+ background: widget.background,
460
+ refresh: { enabled: widget.refresh?.enabled ?? false },
461
+ elements: widget.elements.map(elementShape)
462
+ };
463
+ }
464
+ function hasContent(value) {
465
+ return (value ?? "").trim().length > 0;
466
+ }
467
+ function elementShape(element) {
468
+ const base = {
469
+ type: element.type,
470
+ grid: element.grid
471
+ };
472
+ switch (element.type) {
473
+ case "text": return {
474
+ ...base,
475
+ sensitive: element.sensitive,
476
+ hasText: hasContent(element.text),
477
+ style: {
478
+ ...element.style,
479
+ font: {
480
+ size: element.style.font.size,
481
+ bold: element.style.font.bold ?? false,
482
+ italic: element.style.font.italic ?? false,
483
+ underline: element.style.font.underline ?? false,
484
+ strikethrough: element.style.font.strikethrough ?? false
485
+ },
486
+ padding: element.style.padding ?? {
487
+ vertical: 0,
488
+ horizontal: 0
489
+ }
490
+ }
491
+ };
492
+ case "image": return {
493
+ ...base,
494
+ sensitive: element.sensitive,
495
+ source: element.source,
496
+ hasAlt: hasContent(element.alt),
497
+ fit: element.fit,
498
+ overlayColor: element.overlayColor,
499
+ radius: element.radius
500
+ };
501
+ case "button": return {
502
+ ...base,
503
+ sensitive: element.sensitive,
504
+ hasLabel: hasContent(element.label),
505
+ method: element.method,
506
+ requestRefresh: element.requestRefresh ?? false,
507
+ showOnlyOnHover: element.showOnlyOnHover ?? false,
508
+ style: element.style
509
+ };
510
+ case "divider": return {
511
+ ...base,
512
+ orientation: element.orientation,
513
+ style: element.style
514
+ };
515
+ default: return {
516
+ ...base,
517
+ sensitive: element.sensitive,
518
+ hasTitle: hasContent(element.title),
519
+ showLegend: element.showLegend,
520
+ style: element.style
521
+ };
522
+ }
523
+ }
524
+ function canonicalJson(value) {
525
+ if (value === null || value === void 0) return "null";
526
+ if (typeof value === "boolean") return value ? "true" : "false";
527
+ if (typeof value === "number") return canonicalNumber(value);
528
+ if (typeof value === "string") return canonicalString(value);
529
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
530
+ return `{${Object.keys(value).filter((key) => value[key] !== void 0 && value[key] !== null).sort(compareOrdinal).map((key) => `${canonicalString(key)}:${canonicalJson(value[key])}`).join(",")}}`;
531
+ }
532
+ function compareOrdinal(left, right) {
533
+ return left < right ? -1 : left > right ? 1 : 0;
534
+ }
535
+ function canonicalNumber(value) {
536
+ const fixed = value.toFixed(6).replace(/\.?0+$/, "");
537
+ return fixed === "-0" ? "0" : fixed;
538
+ }
539
+ function canonicalString(value) {
540
+ const normalized = value.startsWith("#") ? value.toLowerCase() : value;
541
+ let output = "\"";
542
+ for (const character of normalized) {
543
+ const code = character.charCodeAt(0);
544
+ if (character === "\"" || character === "\\") output += `\\${character}`;
545
+ else if (code < 32) output += `\\u${code.toString(16).padStart(4, "0")}`;
546
+ else output += character;
547
+ }
548
+ return `${output}"`;
549
+ }
550
+ const roundConstants = new Uint32Array([
551
+ 1116352408,
552
+ 1899447441,
553
+ 3049323471,
554
+ 3921009573,
555
+ 961987163,
556
+ 1508970993,
557
+ 2453635748,
558
+ 2870763221,
559
+ 3624381080,
560
+ 310598401,
561
+ 607225278,
562
+ 1426881987,
563
+ 1925078388,
564
+ 2162078206,
565
+ 2614888103,
566
+ 3248222580,
567
+ 3835390401,
568
+ 4022224774,
569
+ 264347078,
570
+ 604807628,
571
+ 770255983,
572
+ 1249150122,
573
+ 1555081692,
574
+ 1996064986,
575
+ 2554220882,
576
+ 2821834349,
577
+ 2952996808,
578
+ 3210313671,
579
+ 3336571891,
580
+ 3584528711,
581
+ 113926993,
582
+ 338241895,
583
+ 666307205,
584
+ 773529912,
585
+ 1294757372,
586
+ 1396182291,
587
+ 1695183700,
588
+ 1986661051,
589
+ 2177026350,
590
+ 2456956037,
591
+ 2730485921,
592
+ 2820302411,
593
+ 3259730800,
594
+ 3345764771,
595
+ 3516065817,
596
+ 3600352804,
597
+ 4094571909,
598
+ 275423344,
599
+ 430227734,
600
+ 506948616,
601
+ 659060556,
602
+ 883997877,
603
+ 958139571,
604
+ 1322822218,
605
+ 1537002063,
606
+ 1747873779,
607
+ 1955562222,
608
+ 2024104815,
609
+ 2227730452,
610
+ 2361852424,
611
+ 2428436474,
612
+ 2756734187,
613
+ 3204031479,
614
+ 3329325298
615
+ ]);
616
+ function sha256Hex(message) {
617
+ const bitLength = message.length * 8;
618
+ const paddedLength = Math.ceil((message.length + 9) / 64) * 64;
619
+ const bytes = new Uint8Array(paddedLength);
620
+ bytes.set(message);
621
+ bytes[message.length] = 128;
622
+ const view = new DataView(bytes.buffer);
623
+ view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296));
624
+ view.setUint32(paddedLength - 4, bitLength >>> 0);
625
+ const hash = new Uint32Array([
626
+ 1779033703,
627
+ 3144134277,
628
+ 1013904242,
629
+ 2773480762,
630
+ 1359893119,
631
+ 2600822924,
632
+ 528734635,
633
+ 1541459225
634
+ ]);
635
+ const words = /* @__PURE__ */ new Uint32Array(64);
636
+ const rotate = (value, bits) => value >>> bits | value << 32 - bits;
637
+ for (let offset = 0; offset < paddedLength; offset += 64) {
638
+ for (let index = 0; index < 16; index++) words[index] = view.getUint32(offset + index * 4);
639
+ for (let index = 16; index < 64; index++) {
640
+ const w15 = words[index - 15];
641
+ const w2 = words[index - 2];
642
+ const s0 = rotate(w15, 7) ^ rotate(w15, 18) ^ w15 >>> 3;
643
+ const s1 = rotate(w2, 17) ^ rotate(w2, 19) ^ w2 >>> 10;
644
+ words[index] = words[index - 16] + s0 + words[index - 7] + s1;
645
+ }
646
+ let [a, b, c, d, e, f, g, h] = hash;
647
+ for (let index = 0; index < 64; index++) {
648
+ const s1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
649
+ const choice = e & f ^ ~e & g;
650
+ const temp1 = h + s1 + choice + roundConstants[index] + words[index] >>> 0;
651
+ const temp2 = (rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
652
+ h = g;
653
+ g = f;
654
+ f = e;
655
+ e = d + temp1 >>> 0;
656
+ d = c;
657
+ c = b;
658
+ b = a;
659
+ a = temp1 + temp2 >>> 0;
660
+ }
661
+ hash[0] += a;
662
+ hash[1] += b;
663
+ hash[2] += c;
664
+ hash[3] += d;
665
+ hash[4] += e;
666
+ hash[5] += f;
667
+ hash[6] += g;
668
+ hash[7] += h;
669
+ }
670
+ return Array.from(hash, (word) => word.toString(16).padStart(8, "0")).join("");
671
+ }
672
+ const WIDGET_HEIGHT = 245;
673
+ const WIDGET_PADDING = 18;
674
+ const WIDGET_GAP = 8;
675
+ const WIDGET_CELL_WIDTH = 133;
676
+ const WIDGET_CELL_HEIGHT = 123;
677
+ const footprintBySize = {
678
+ mini: {
679
+ columns: 1,
680
+ rows: 1
681
+ },
682
+ compact: {
683
+ columns: 2,
684
+ rows: 1
685
+ },
686
+ tall: {
687
+ columns: 1,
688
+ rows: 2
689
+ },
690
+ square: {
691
+ columns: 2,
692
+ rows: 2
693
+ },
694
+ wide: {
695
+ columns: 4,
696
+ rows: 2
697
+ },
698
+ mega: {
699
+ columns: 4,
700
+ rows: 4
701
+ },
702
+ banner: {
703
+ columns: 2,
704
+ rows: 4
705
+ },
706
+ hero: {
707
+ columns: 8,
708
+ rows: 4
709
+ }
710
+ };
711
+ function widgetFootprint(size) {
712
+ return typeof size === "string" && size in footprintBySize ? footprintBySize[size] : footprintBySize.square;
713
+ }
714
+ function gridSpanSize(span, cellSize) {
715
+ return span * cellSize + Math.max(0, span - 1) * 8;
716
+ }
717
+ function widgetWidth(size) {
718
+ return gridSpanSize(widgetFootprint(size).columns, 133);
719
+ }
720
+ function widgetHeight(size) {
721
+ return gridSpanSize(widgetFootprint(size).rows, 123);
722
+ }
723
+ function gridTemplate(tracks) {
724
+ return tracks.map((track) => track.unit === "auto" ? "auto" : `${track.size}${track.unit === "star" ? "fr" : "px"}`).join(" ");
725
+ }
726
+ function elementGridStyle(element) {
727
+ return {
728
+ "grid-row": `${element.grid.row + 1} / span ${element.grid.rowSpan}`,
729
+ "grid-column": `${element.grid.column + 1} / span ${element.grid.columnSpan}`
730
+ };
731
+ }
732
+ var WidgetElementRenderer = class WidgetElementRenderer {
733
+ element = input.required(...ngDevMode ? [{ debugName: "element" }] : /* istanbul ignore next */ []);
734
+ sensitiveVisible = input(false, ...ngDevMode ? [{ debugName: "sensitiveVisible" }] : /* istanbul ignore next */ []);
735
+ locale = input(defaultWidgetRendererLocale, ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
736
+ actionRequested = output();
737
+ failedImage = signal(null, ...ngDevMode ? [{ debugName: "failedImage" }] : /* istanbul ignore next */ []);
738
+ isText(element) {
739
+ return element.type === "text";
740
+ }
741
+ isImage(element) {
742
+ return element.type === "image";
743
+ }
744
+ isButton(element) {
745
+ return element.type === "button";
746
+ }
747
+ isChart(element) {
748
+ return [
749
+ "pie",
750
+ "donut",
751
+ "funnel",
752
+ "gauge",
753
+ "bar",
754
+ "line",
755
+ "progress"
756
+ ].includes(element.type);
757
+ }
758
+ isSensitive(element) {
759
+ return ("sensitive" in element ? element.sensitive : false) && !this.sensitiveVisible();
760
+ }
761
+ sensitiveBlur(element) {
762
+ if (!element.sensitive) return null;
763
+ if (element.type !== "text") return "2px";
764
+ return `${Math.min(Math.max(element.style.font.size * .25, 2), 10)}px`;
765
+ }
766
+ elementAlt(element) {
767
+ return this.isSensitive(element) ? "" : element.alt;
768
+ }
769
+ imageFailed(element) {
770
+ const failedImage = this.failedImage();
771
+ return failedImage?.element === element && failedImage.source === element.source;
772
+ }
773
+ imageLoadFailed(element) {
774
+ this.failedImage.set({
775
+ element,
776
+ source: element.source
777
+ });
778
+ }
779
+ requestAction(element, event) {
780
+ if (this.isSensitive(element)) return;
781
+ this.actionRequested.emit({
782
+ element,
783
+ event
784
+ });
785
+ }
786
+ horizontalAnchor(anchor) {
787
+ return anchor.endsWith("left") ? "flex-start" : anchor.endsWith("right") ? "flex-end" : "center";
788
+ }
789
+ verticalAnchor(anchor) {
790
+ return anchor.startsWith("top") ? "flex-start" : anchor.startsWith("bottom") ? "flex-end" : "center";
791
+ }
792
+ textFontWeight(element) {
793
+ return element.style.font.bold ? 700 : 400;
794
+ }
795
+ textFontStyle(element) {
796
+ return element.style.font.italic ? "italic" : "normal";
797
+ }
798
+ textFontDecoration(element) {
799
+ return [element.style.font.underline && "underline", element.style.font.strikethrough && "line-through"].filter(Boolean).join(" ") || "none";
800
+ }
801
+ elementId(element) {
802
+ return "id" in element ? element.id : null;
803
+ }
804
+ gridRow() {
805
+ return `${this.element().grid.row + 1} / span ${this.element().grid.rowSpan}`;
806
+ }
807
+ gridColumn() {
808
+ return `${this.element().grid.column + 1} / span ${this.element().grid.columnSpan}`;
809
+ }
810
+ static ɵfac = i0.ɵɵngDeclareFactory({
811
+ minVersion: "12.0.0",
812
+ version: "22.2.4",
813
+ ngImport: i0,
814
+ type: WidgetElementRenderer,
815
+ deps: [],
816
+ target: i0.ɵɵFactoryTarget.Component
817
+ });
818
+ static ɵcmp = i0.ɵɵngDeclareComponent({
819
+ minVersion: "17.0.0",
820
+ version: "22.2.4",
821
+ type: WidgetElementRenderer,
822
+ isStandalone: true,
823
+ selector: "widget-element-renderer",
824
+ inputs: {
825
+ element: {
826
+ classPropertyName: "element",
827
+ publicName: "element",
828
+ isSignal: true,
829
+ isRequired: true,
830
+ transformFunction: null
831
+ },
832
+ sensitiveVisible: {
833
+ classPropertyName: "sensitiveVisible",
834
+ publicName: "sensitiveVisible",
835
+ isSignal: true,
836
+ isRequired: false,
837
+ transformFunction: null
838
+ },
839
+ locale: {
840
+ classPropertyName: "locale",
841
+ publicName: "locale",
842
+ isSignal: true,
843
+ isRequired: false,
844
+ transformFunction: null
845
+ }
846
+ },
847
+ outputs: { actionRequested: "actionRequested" },
848
+ host: { properties: {
849
+ "style.grid-row": "gridRow()",
850
+ "style.grid-column": "gridColumn()"
851
+ } },
852
+ ngImport: i0,
853
+ template: "@let item = element();\n<div\n class=\"widget-element\"\n [attr.data-widget-element-id]=\"elementId(item)\"\n [attr.aria-hidden]=\"isSensitive(item) ? 'true' : null\"\n [class.is-sensitive]=\"isSensitive(item)\"\n>\n <div\n class=\"element-content\"\n [class.is-sensitive]=\"isSensitive(item)\"\n [style.--sensitive-blur]=\"sensitiveBlur(item)\"\n [style.justify-content]=\"\n isChart(item) && item.type !== 'progress'\n ? 'stretch'\n : horizontalAnchor(item.grid.anchor ?? 'center')\n \"\n [style.align-items]=\"\n isChart(item) && item.type !== 'progress'\n ? 'stretch'\n : verticalAnchor(item.grid.anchor ?? 'center')\n \"\n >\n @if (isText(item)) {\n @let text = item;\n <span\n class=\"text-element\"\n [style.color]=\"text.style.color\"\n [style.font-size.px]=\"text.style.font.size\"\n [style.font-weight]=\"textFontWeight(text)\"\n [style.font-style]=\"textFontStyle(text)\"\n [style.text-decoration]=\"textFontDecoration(text)\"\n [style.text-align]=\"text.style.align\"\n [style.white-space]=\"text.style.wrap ? 'pre-wrap' : 'pre'\"\n [style.background-color]=\"text.style.background || null\"\n [style.border-radius.px]=\"text.style.radius\"\n [style.padding]=\"\n text.style.padding\n ? text.style.padding.vertical + 'px ' + text.style.padding.horizontal + 'px'\n : null\n \"\n >{{ text.text }}</span\n >\n } @else if (isImage(item)) {\n @let image = item;\n @if (imageFailed(image)) {\n <div\n class=\"image-placeholder\"\n role=\"img\"\n [attr.aria-label]=\"elementAlt(image) || locale().aria.imageUnavailable\"\n [style.border-radius.px]=\"image.radius\"\n >\n <svg aria-hidden=\"true\" viewBox=\"0 0 64 48\" focusable=\"false\">\n <rect x=\"2\" y=\"2\" width=\"60\" height=\"44\" rx=\"5\" />\n <circle cx=\"20\" cy=\"17\" r=\"5\" />\n <path d=\"m8 39 15-14 9 8 7-6 17 12\" />\n </svg>\n </div>\n } @else {\n <img\n [src]=\"image.source\"\n [alt]=\"elementAlt(image)\"\n [style.object-fit]=\"image.fit\"\n [style.object-position]=\"image.grid.anchor ?? 'center'\"\n [style.border-radius.px]=\"image.radius\"\n (error)=\"imageLoadFailed(image)\"\n />\n }\n <span\n class=\"image-overlay\"\n [style.background-color]=\"image.overlayColor || 'transparent'\"\n [style.border-radius.px]=\"image.radius\"\n ></span>\n } @else if (isButton(item)) {\n @let button = item;\n <button\n type=\"button\"\n class=\"action-button\"\n [class.solid]=\"button.style === 'solid'\"\n [class.outline]=\"button.style === 'outline'\"\n [class.show-only-on-hover]=\"button.showOnlyOnHover\"\n [disabled]=\"isSensitive(button)\"\n (click)=\"requestAction(button, $event)\"\n [tabindex]=\"isSensitive(button) ? -1 : 0\"\n >\n {{ button.label }}\n </button>\n } @else if (item.type === 'divider') {\n @let divider = item;\n <div\n class=\"divider-element\"\n [class.is-vertical]=\"divider.orientation === 'vertical'\"\n role=\"separator\"\n [attr.aria-orientation]=\"divider.orientation\"\n [style.background-color]=\"divider.style.color\"\n ></div>\n } @else if (isChart(item)) {\n @let chart = item;\n @defer (on immediate) {\n <widget-chart-element\n [class.is-progress]=\"chart.type === 'progress'\"\n [element]=\"chart\"\n [sensitiveHidden]=\"isSensitive(chart)\"\n [locale]=\"locale()\"\n />\n } @placeholder {\n <div class=\"chart-placeholder\" aria-hidden=\"true\"></div>\n }\n }\n </div>\n</div>\n",
854
+ styles: [":host{position:relative;min-width:0;min-height:0;display:flex;z-index:1}.widget-element{position:relative;min-width:0;min-height:0;display:flex;z-index:1;width:100%;height:100%}.element-content{display:flex;width:100%;height:100%;min-width:0;min-height:0}.element-content:has(widget-chart-element){align-items:stretch}.element-content>widget-chart-element{flex:0 1 auto;width:100%;height:100%;max-width:100%;max-height:100%}.element-content>widget-chart-element.is-progress{height:auto}.chart-placeholder{width:100%;height:100%}.text-element{display:inline-block;overflow:visible;line-height:1.2}img{width:100%;height:100%;display:block}.image-overlay{position:absolute;inset:0;z-index:1;pointer-events:none;border-radius:inherit}.image-placeholder{display:flex;width:100%;height:100%;align-items:center;justify-content:center;overflow:hidden;background:#dfe5ee}.image-placeholder svg{width:min(56px,45%);height:auto;fill:none;stroke:#8c9ab0;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.divider-element{width:100%;height:2px;flex:0 0 auto;border-radius:var(--widget-renderer-pill-radius, 999px)}.divider-element.is-vertical{width:2px;height:100%}.element-content.is-sensitive{filter:blur(var(--sensitive-blur, 2px));-webkit-user-select:none;user-select:none}.action-button{pointer-events:var(--widget-renderer-actions-pointer-events, auto);min-height:30px;border-radius:var(--widget-renderer-radius, 8px);padding:6px 10px;font:600 12px/1.1 inherit;cursor:var(--widget-renderer-action-cursor, pointer)}.action-button.show-only-on-hover{opacity:0;pointer-events:none;transform:translateY(2px);transition:opacity var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease),transform var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}:host-context(.widget-shell:hover) .action-button.show-only-on-hover,:host-context(.widget-shell:focus-within) .action-button.show-only-on-hover{opacity:1;pointer-events:auto;transform:translateY(0)}@media(prefers-reduced-motion:reduce){.action-button.show-only-on-hover{transition:none}}.action-button.solid{border:1px solid var(--widget-renderer-action-background, #151515);background:var(--widget-renderer-action-background, #151515);color:var(--widget-renderer-action-color, #fff)}.action-button.outline{border:1px solid var(--widget-renderer-action-outline-border, #737373);background:var(--widget-renderer-action-outline-background, #fff);color:var(--widget-renderer-action-outline-color, #151515)}\n"],
855
+ deferBlockDependencies: [() => [import("./lieselthuriot-widget-renderer-chart-element-renderer-wVHdIYuJ.mjs").then((m) => m.ChartElementRenderer)]]
856
+ });
857
+ };
858
+ i0.ɵɵngDeclareClassMetadataAsync({
859
+ minVersion: "18.0.0",
860
+ version: "22.2.4",
861
+ ngImport: i0,
862
+ type: WidgetElementRenderer,
863
+ resolveDeferredDeps: () => [import("./lieselthuriot-widget-renderer-chart-element-renderer-wVHdIYuJ.mjs").then((m) => m.ChartElementRenderer)],
864
+ resolveMetadata: (ChartElementRenderer) => ({
865
+ decorators: [{
866
+ type: Component,
867
+ args: [{
868
+ selector: "widget-element-renderer",
869
+ imports: [ChartElementRenderer],
870
+ host: {
871
+ "[style.grid-row]": "gridRow()",
872
+ "[style.grid-column]": "gridColumn()"
873
+ },
874
+ template: "@let item = element();\n<div\n class=\"widget-element\"\n [attr.data-widget-element-id]=\"elementId(item)\"\n [attr.aria-hidden]=\"isSensitive(item) ? 'true' : null\"\n [class.is-sensitive]=\"isSensitive(item)\"\n>\n <div\n class=\"element-content\"\n [class.is-sensitive]=\"isSensitive(item)\"\n [style.--sensitive-blur]=\"sensitiveBlur(item)\"\n [style.justify-content]=\"\n isChart(item) && item.type !== 'progress'\n ? 'stretch'\n : horizontalAnchor(item.grid.anchor ?? 'center')\n \"\n [style.align-items]=\"\n isChart(item) && item.type !== 'progress'\n ? 'stretch'\n : verticalAnchor(item.grid.anchor ?? 'center')\n \"\n >\n @if (isText(item)) {\n @let text = item;\n <span\n class=\"text-element\"\n [style.color]=\"text.style.color\"\n [style.font-size.px]=\"text.style.font.size\"\n [style.font-weight]=\"textFontWeight(text)\"\n [style.font-style]=\"textFontStyle(text)\"\n [style.text-decoration]=\"textFontDecoration(text)\"\n [style.text-align]=\"text.style.align\"\n [style.white-space]=\"text.style.wrap ? 'pre-wrap' : 'pre'\"\n [style.background-color]=\"text.style.background || null\"\n [style.border-radius.px]=\"text.style.radius\"\n [style.padding]=\"\n text.style.padding\n ? text.style.padding.vertical + 'px ' + text.style.padding.horizontal + 'px'\n : null\n \"\n >{{ text.text }}</span\n >\n } @else if (isImage(item)) {\n @let image = item;\n @if (imageFailed(image)) {\n <div\n class=\"image-placeholder\"\n role=\"img\"\n [attr.aria-label]=\"elementAlt(image) || locale().aria.imageUnavailable\"\n [style.border-radius.px]=\"image.radius\"\n >\n <svg aria-hidden=\"true\" viewBox=\"0 0 64 48\" focusable=\"false\">\n <rect x=\"2\" y=\"2\" width=\"60\" height=\"44\" rx=\"5\" />\n <circle cx=\"20\" cy=\"17\" r=\"5\" />\n <path d=\"m8 39 15-14 9 8 7-6 17 12\" />\n </svg>\n </div>\n } @else {\n <img\n [src]=\"image.source\"\n [alt]=\"elementAlt(image)\"\n [style.object-fit]=\"image.fit\"\n [style.object-position]=\"image.grid.anchor ?? 'center'\"\n [style.border-radius.px]=\"image.radius\"\n (error)=\"imageLoadFailed(image)\"\n />\n }\n <span\n class=\"image-overlay\"\n [style.background-color]=\"image.overlayColor || 'transparent'\"\n [style.border-radius.px]=\"image.radius\"\n ></span>\n } @else if (isButton(item)) {\n @let button = item;\n <button\n type=\"button\"\n class=\"action-button\"\n [class.solid]=\"button.style === 'solid'\"\n [class.outline]=\"button.style === 'outline'\"\n [class.show-only-on-hover]=\"button.showOnlyOnHover\"\n [disabled]=\"isSensitive(button)\"\n (click)=\"requestAction(button, $event)\"\n [tabindex]=\"isSensitive(button) ? -1 : 0\"\n >\n {{ button.label }}\n </button>\n } @else if (item.type === 'divider') {\n @let divider = item;\n <div\n class=\"divider-element\"\n [class.is-vertical]=\"divider.orientation === 'vertical'\"\n role=\"separator\"\n [attr.aria-orientation]=\"divider.orientation\"\n [style.background-color]=\"divider.style.color\"\n ></div>\n } @else if (isChart(item)) {\n @let chart = item;\n @defer (on immediate) {\n <widget-chart-element\n [class.is-progress]=\"chart.type === 'progress'\"\n [element]=\"chart\"\n [sensitiveHidden]=\"isSensitive(chart)\"\n [locale]=\"locale()\"\n />\n } @placeholder {\n <div class=\"chart-placeholder\" aria-hidden=\"true\"></div>\n }\n }\n </div>\n</div>\n",
875
+ styles: [":host{position:relative;min-width:0;min-height:0;display:flex;z-index:1}.widget-element{position:relative;min-width:0;min-height:0;display:flex;z-index:1;width:100%;height:100%}.element-content{display:flex;width:100%;height:100%;min-width:0;min-height:0}.element-content:has(widget-chart-element){align-items:stretch}.element-content>widget-chart-element{flex:0 1 auto;width:100%;height:100%;max-width:100%;max-height:100%}.element-content>widget-chart-element.is-progress{height:auto}.chart-placeholder{width:100%;height:100%}.text-element{display:inline-block;overflow:visible;line-height:1.2}img{width:100%;height:100%;display:block}.image-overlay{position:absolute;inset:0;z-index:1;pointer-events:none;border-radius:inherit}.image-placeholder{display:flex;width:100%;height:100%;align-items:center;justify-content:center;overflow:hidden;background:#dfe5ee}.image-placeholder svg{width:min(56px,45%);height:auto;fill:none;stroke:#8c9ab0;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.divider-element{width:100%;height:2px;flex:0 0 auto;border-radius:var(--widget-renderer-pill-radius, 999px)}.divider-element.is-vertical{width:2px;height:100%}.element-content.is-sensitive{filter:blur(var(--sensitive-blur, 2px));-webkit-user-select:none;user-select:none}.action-button{pointer-events:var(--widget-renderer-actions-pointer-events, auto);min-height:30px;border-radius:var(--widget-renderer-radius, 8px);padding:6px 10px;font:600 12px/1.1 inherit;cursor:var(--widget-renderer-action-cursor, pointer)}.action-button.show-only-on-hover{opacity:0;pointer-events:none;transform:translateY(2px);transition:opacity var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease),transform var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}:host-context(.widget-shell:hover) .action-button.show-only-on-hover,:host-context(.widget-shell:focus-within) .action-button.show-only-on-hover{opacity:1;pointer-events:auto;transform:translateY(0)}@media(prefers-reduced-motion:reduce){.action-button.show-only-on-hover{transition:none}}.action-button.solid{border:1px solid var(--widget-renderer-action-background, #151515);background:var(--widget-renderer-action-background, #151515);color:var(--widget-renderer-action-color, #fff)}.action-button.outline{border:1px solid var(--widget-renderer-action-outline-border, #737373);background:var(--widget-renderer-action-outline-background, #fff);color:var(--widget-renderer-action-outline-color, #151515)}\n"]
876
+ }]
877
+ }],
878
+ ctorParameters: null,
879
+ propDecorators: {
880
+ element: [{
881
+ type: i0.Input,
882
+ args: [{
883
+ isSignal: true,
884
+ alias: "element",
885
+ required: true
886
+ }]
887
+ }],
888
+ sensitiveVisible: [{
889
+ type: i0.Input,
890
+ args: [{
891
+ isSignal: true,
892
+ alias: "sensitiveVisible",
893
+ required: false
894
+ }]
895
+ }],
896
+ locale: [{
897
+ type: i0.Input,
898
+ args: [{
899
+ isSignal: true,
900
+ alias: "locale",
901
+ required: false
902
+ }]
903
+ }],
904
+ actionRequested: [{
905
+ type: i0.Output,
906
+ args: ["actionRequested"]
907
+ }]
908
+ }
909
+ })
910
+ });
911
+ var WidgetSkeleton = class WidgetSkeleton {
912
+ size = input.required(...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
913
+ darkMode = input(false, ...ngDevMode ? [{ debugName: "darkMode" }] : /* istanbul ignore next */ []);
914
+ locale = input(defaultWidgetRendererLocale, ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
915
+ static ɵfac = i0.ɵɵngDeclareFactory({
916
+ minVersion: "12.0.0",
917
+ version: "22.2.4",
918
+ ngImport: i0,
919
+ type: WidgetSkeleton,
920
+ deps: [],
921
+ target: i0.ɵɵFactoryTarget.Component
922
+ });
923
+ static ɵcmp = i0.ɵɵngDeclareComponent({
924
+ minVersion: "17.1.0",
925
+ version: "22.2.4",
926
+ type: WidgetSkeleton,
927
+ isStandalone: true,
928
+ selector: "widget-skeleton",
929
+ inputs: {
930
+ size: {
931
+ classPropertyName: "size",
932
+ publicName: "size",
933
+ isSignal: true,
934
+ isRequired: true,
935
+ transformFunction: null
936
+ },
937
+ darkMode: {
938
+ classPropertyName: "darkMode",
939
+ publicName: "darkMode",
940
+ isSignal: true,
941
+ isRequired: false,
942
+ transformFunction: null
943
+ },
944
+ locale: {
945
+ classPropertyName: "locale",
946
+ publicName: "locale",
947
+ isSignal: true,
948
+ isRequired: false,
949
+ transformFunction: null
950
+ }
951
+ },
952
+ ngImport: i0,
953
+ template: "<div\n class=\"widget-skeleton\"\n [class.is-mini]=\"size() === 'mini'\"\n [class.is-compact]=\"size() === 'compact'\"\n [class.is-tall]=\"size() === 'tall'\"\n [class.is-wide]=\"size() === 'wide'\"\n [class.is-mega]=\"size() === 'mega'\"\n [class.is-banner]=\"size() === 'banner'\"\n [class.is-hero]=\"size() === 'hero'\"\n [class.is-dark]=\"darkMode()\"\n role=\"status\"\n [attr.aria-label]=\"locale().aria.loading\"\n>\n <div class=\"skeleton-toolbar\"></div>\n <div class=\"skeleton-content\">\n <span class=\"skeleton-line skeleton-line-small\"></span>\n <span class=\"skeleton-line skeleton-line-title\"></span>\n <span class=\"skeleton-line skeleton-line-copy\"></span>\n <span class=\"skeleton-chart\"></span>\n <span class=\"skeleton-button\"></span>\n </div>\n</div>\n",
954
+ styles: [":host{display:block}.widget-skeleton{position:relative;width:274px;max-width:100%;height:254px;box-sizing:border-box;overflow:hidden;border-radius:var(--widget-renderer-radius);background:#dfe5ee;box-shadow:var(--widget-renderer-shadow)}.widget-skeleton.is-wide{width:556px}.widget-skeleton.is-mini{width:133px;height:123px}.widget-skeleton.is-compact{width:274px;height:123px}.widget-skeleton.is-tall{width:133px;height:254px}.widget-skeleton.is-mega{width:556px;height:516px}.widget-skeleton.is-banner{width:274px;height:516px}.widget-skeleton.is-hero{width:1120px;height:516px}.widget-skeleton.is-mini .skeleton-toolbar{top:8px;right:8px;width:22px;height:22px}.widget-skeleton.is-mini .skeleton-content{box-sizing:border-box;height:100%;gap:3px;padding:24px 12px 8px}.widget-skeleton.is-mini .skeleton-line{height:6px}.widget-skeleton.is-mini .skeleton-line-title{height:10px}.widget-skeleton.is-mini .skeleton-chart{flex:1 1 auto;min-height:20px;margin-top:0}.widget-skeleton.is-mini .skeleton-button{width:42px;height:18px}.widget-skeleton:is(.is-compact,.is-tall) .skeleton-content{box-sizing:border-box;height:100%;gap:5px;padding:30px 12px 10px}.widget-skeleton.is-compact .skeleton-chart{min-height:28px;margin-top:0}.widget-skeleton.is-tall .skeleton-chart{flex:1 1 auto;min-height:45px;margin-top:0}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-content{box-sizing:border-box;height:100%}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-chart{flex:1 1 auto;min-height:180px}.widget-skeleton.is-dark{background:#182236}.skeleton-line,.skeleton-chart,.skeleton-button{background:linear-gradient(100deg,#dfe5ee 20%,#f2f5f9,#dfe5ee 70%);background-size:200% 100%;animation:skeleton-shimmer 1.8s linear infinite}.widget-skeleton.is-dark .skeleton-line,.widget-skeleton.is-dark .skeleton-chart,.widget-skeleton.is-dark .skeleton-button{background:linear-gradient(100deg,#182236 20%,#2b3b59,#182236 70%);background-size:200% 100%}.skeleton-toolbar{position:absolute;top:12px;right:12px;width:var(--widget-renderer-control-size);height:var(--widget-renderer-control-size);border-radius:var(--widget-renderer-radius);background:#c4cedd}.widget-skeleton.is-dark .skeleton-toolbar{background:#2b3b59}.skeleton-content{display:flex;flex-direction:column;gap:10px;padding:44px var(--widget-renderer-content-padding) 16px}.skeleton-line{display:block;height:10px;border-radius:var(--widget-renderer-pill-radius)}.skeleton-line-small{width:28%}.skeleton-line-title{width:72%;height:20px}.skeleton-line-copy{width:58%}.skeleton-chart{width:100%;height:64px;margin-top:2px;border-radius:var(--widget-renderer-radius)}.skeleton-button{align-self:flex-end;width:58px;height:30px;border-radius:var(--widget-renderer-radius)}@keyframes skeleton-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.skeleton-line,.skeleton-chart,.skeleton-button{animation:none}}\n"]
955
+ });
956
+ };
957
+ i0.ɵɵngDeclareClassMetadata({
958
+ minVersion: "12.0.0",
959
+ version: "22.2.4",
960
+ ngImport: i0,
961
+ type: WidgetSkeleton,
962
+ decorators: [{
963
+ type: Component,
964
+ args: [{
965
+ selector: "widget-skeleton",
966
+ template: "<div\n class=\"widget-skeleton\"\n [class.is-mini]=\"size() === 'mini'\"\n [class.is-compact]=\"size() === 'compact'\"\n [class.is-tall]=\"size() === 'tall'\"\n [class.is-wide]=\"size() === 'wide'\"\n [class.is-mega]=\"size() === 'mega'\"\n [class.is-banner]=\"size() === 'banner'\"\n [class.is-hero]=\"size() === 'hero'\"\n [class.is-dark]=\"darkMode()\"\n role=\"status\"\n [attr.aria-label]=\"locale().aria.loading\"\n>\n <div class=\"skeleton-toolbar\"></div>\n <div class=\"skeleton-content\">\n <span class=\"skeleton-line skeleton-line-small\"></span>\n <span class=\"skeleton-line skeleton-line-title\"></span>\n <span class=\"skeleton-line skeleton-line-copy\"></span>\n <span class=\"skeleton-chart\"></span>\n <span class=\"skeleton-button\"></span>\n </div>\n</div>\n",
967
+ styles: [":host{display:block}.widget-skeleton{position:relative;width:274px;max-width:100%;height:254px;box-sizing:border-box;overflow:hidden;border-radius:var(--widget-renderer-radius);background:#dfe5ee;box-shadow:var(--widget-renderer-shadow)}.widget-skeleton.is-wide{width:556px}.widget-skeleton.is-mini{width:133px;height:123px}.widget-skeleton.is-compact{width:274px;height:123px}.widget-skeleton.is-tall{width:133px;height:254px}.widget-skeleton.is-mega{width:556px;height:516px}.widget-skeleton.is-banner{width:274px;height:516px}.widget-skeleton.is-hero{width:1120px;height:516px}.widget-skeleton.is-mini .skeleton-toolbar{top:8px;right:8px;width:22px;height:22px}.widget-skeleton.is-mini .skeleton-content{box-sizing:border-box;height:100%;gap:3px;padding:24px 12px 8px}.widget-skeleton.is-mini .skeleton-line{height:6px}.widget-skeleton.is-mini .skeleton-line-title{height:10px}.widget-skeleton.is-mini .skeleton-chart{flex:1 1 auto;min-height:20px;margin-top:0}.widget-skeleton.is-mini .skeleton-button{width:42px;height:18px}.widget-skeleton:is(.is-compact,.is-tall) .skeleton-content{box-sizing:border-box;height:100%;gap:5px;padding:30px 12px 10px}.widget-skeleton.is-compact .skeleton-chart{min-height:28px;margin-top:0}.widget-skeleton.is-tall .skeleton-chart{flex:1 1 auto;min-height:45px;margin-top:0}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-content{box-sizing:border-box;height:100%}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-chart{flex:1 1 auto;min-height:180px}.widget-skeleton.is-dark{background:#182236}.skeleton-line,.skeleton-chart,.skeleton-button{background:linear-gradient(100deg,#dfe5ee 20%,#f2f5f9,#dfe5ee 70%);background-size:200% 100%;animation:skeleton-shimmer 1.8s linear infinite}.widget-skeleton.is-dark .skeleton-line,.widget-skeleton.is-dark .skeleton-chart,.widget-skeleton.is-dark .skeleton-button{background:linear-gradient(100deg,#182236 20%,#2b3b59,#182236 70%);background-size:200% 100%}.skeleton-toolbar{position:absolute;top:12px;right:12px;width:var(--widget-renderer-control-size);height:var(--widget-renderer-control-size);border-radius:var(--widget-renderer-radius);background:#c4cedd}.widget-skeleton.is-dark .skeleton-toolbar{background:#2b3b59}.skeleton-content{display:flex;flex-direction:column;gap:10px;padding:44px var(--widget-renderer-content-padding) 16px}.skeleton-line{display:block;height:10px;border-radius:var(--widget-renderer-pill-radius)}.skeleton-line-small{width:28%}.skeleton-line-title{width:72%;height:20px}.skeleton-line-copy{width:58%}.skeleton-chart{width:100%;height:64px;margin-top:2px;border-radius:var(--widget-renderer-radius)}.skeleton-button{align-self:flex-end;width:58px;height:30px;border-radius:var(--widget-renderer-radius)}@keyframes skeleton-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.skeleton-line,.skeleton-chart,.skeleton-button{animation:none}}\n"]
968
+ }]
969
+ }],
970
+ propDecorators: {
971
+ size: [{
972
+ type: i0.Input,
973
+ args: [{
974
+ isSignal: true,
975
+ alias: "size",
976
+ required: true
977
+ }]
978
+ }],
979
+ darkMode: [{
980
+ type: i0.Input,
981
+ args: [{
982
+ isSignal: true,
983
+ alias: "darkMode",
984
+ required: false
985
+ }]
986
+ }],
987
+ locale: [{
988
+ type: i0.Input,
989
+ args: [{
990
+ isSignal: true,
991
+ alias: "locale",
992
+ required: false
993
+ }]
994
+ }]
995
+ }
996
+ });
997
+ var WidgetBackground = class WidgetBackground {
998
+ background = input.required(...ngDevMode ? [{ debugName: "background" }] : /* istanbul ignore next */ []);
999
+ sensitive = input(false, ...ngDevMode ? [{ debugName: "sensitive" }] : /* istanbul ignore next */ []);
1000
+ image = input("none", ...ngDevMode ? [{ debugName: "image" }] : /* istanbul ignore next */ []);
1001
+ static ɵfac = i0.ɵɵngDeclareFactory({
1002
+ minVersion: "12.0.0",
1003
+ version: "22.2.4",
1004
+ ngImport: i0,
1005
+ type: WidgetBackground,
1006
+ deps: [],
1007
+ target: i0.ɵɵFactoryTarget.Component
1008
+ });
1009
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1010
+ minVersion: "17.1.0",
1011
+ version: "22.2.4",
1012
+ type: WidgetBackground,
1013
+ isStandalone: true,
1014
+ selector: "widget-background",
1015
+ inputs: {
1016
+ background: {
1017
+ classPropertyName: "background",
1018
+ publicName: "background",
1019
+ isSignal: true,
1020
+ isRequired: true,
1021
+ transformFunction: null
1022
+ },
1023
+ sensitive: {
1024
+ classPropertyName: "sensitive",
1025
+ publicName: "sensitive",
1026
+ isSignal: true,
1027
+ isRequired: false,
1028
+ transformFunction: null
1029
+ },
1030
+ image: {
1031
+ classPropertyName: "image",
1032
+ publicName: "image",
1033
+ isSignal: true,
1034
+ isRequired: false,
1035
+ transformFunction: null
1036
+ }
1037
+ },
1038
+ ngImport: i0,
1039
+ template: `<div
1040
+ class="widget-background"
1041
+ [class.is-sensitive]="sensitive()"
1042
+ style="background-image: none"
1043
+ >
1044
+ <div
1045
+ class="widget-background-image"
1046
+ [class.is-sensitive]="sensitive()"
1047
+ [style.background-image]="image()"
1048
+ [style.background-size]="background().size"
1049
+ [style.background-position]="background().anchor"
1050
+ [style.background-repeat]="background().repeat ? 'repeat' : 'no-repeat'"
1051
+ ></div>
1052
+ </div>
1053
+ <div
1054
+ class="widget-overlay"
1055
+ [style.background-color]="background().overlayColor || 'transparent'"
1056
+ ></div>`,
1057
+ isInline: true,
1058
+ styles: [":host{position:absolute;inset:0}.widget-background{position:absolute;inset:0}.widget-background-image{position:absolute;inset:0;background-position:center;background-repeat:no-repeat;background-size:cover;transition:filter var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}.widget-background-image.is-sensitive{inset:-18px;filter:blur(18px);transform:scale(1.04)}.widget-overlay{position:absolute;inset:0;pointer-events:none;z-index:0}\n"]
1059
+ });
1060
+ };
1061
+ i0.ɵɵngDeclareClassMetadata({
1062
+ minVersion: "12.0.0",
1063
+ version: "22.2.4",
1064
+ ngImport: i0,
1065
+ type: WidgetBackground,
1066
+ decorators: [{
1067
+ type: Component,
1068
+ args: [{
1069
+ selector: "widget-background",
1070
+ template: `<div
1071
+ class="widget-background"
1072
+ [class.is-sensitive]="sensitive()"
1073
+ style="background-image: none"
1074
+ >
1075
+ <div
1076
+ class="widget-background-image"
1077
+ [class.is-sensitive]="sensitive()"
1078
+ [style.background-image]="image()"
1079
+ [style.background-size]="background().size"
1080
+ [style.background-position]="background().anchor"
1081
+ [style.background-repeat]="background().repeat ? 'repeat' : 'no-repeat'"
1082
+ ></div>
1083
+ </div>
1084
+ <div
1085
+ class="widget-overlay"
1086
+ [style.background-color]="background().overlayColor || 'transparent'"
1087
+ ></div>`,
1088
+ styles: [":host{position:absolute;inset:0}.widget-background{position:absolute;inset:0}.widget-background-image{position:absolute;inset:0;background-position:center;background-repeat:no-repeat;background-size:cover;transition:filter var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}.widget-background-image.is-sensitive{inset:-18px;filter:blur(18px);transform:scale(1.04)}.widget-overlay{position:absolute;inset:0;pointer-events:none;z-index:0}\n"]
1089
+ }]
1090
+ }],
1091
+ propDecorators: {
1092
+ background: [{
1093
+ type: i0.Input,
1094
+ args: [{
1095
+ isSignal: true,
1096
+ alias: "background",
1097
+ required: true
1098
+ }]
1099
+ }],
1100
+ sensitive: [{
1101
+ type: i0.Input,
1102
+ args: [{
1103
+ isSignal: true,
1104
+ alias: "sensitive",
1105
+ required: false
1106
+ }]
1107
+ }],
1108
+ image: [{
1109
+ type: i0.Input,
1110
+ args: [{
1111
+ isSignal: true,
1112
+ alias: "image",
1113
+ required: false
1114
+ }]
1115
+ }]
1116
+ }
1117
+ });
1118
+ var WidgetToolbar = class WidgetToolbar {
1119
+ refresh = input(null, ...ngDevMode ? [{ debugName: "refresh" }] : /* istanbul ignore next */ []);
1120
+ hasSensitiveElements = input(false, ...ngDevMode ? [{ debugName: "hasSensitiveElements" }] : /* istanbul ignore next */ []);
1121
+ sensitiveVisible = input(false, ...ngDevMode ? [{ debugName: "sensitiveVisible" }] : /* istanbul ignore next */ []);
1122
+ locale = input(defaultWidgetRendererLocale, ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
1123
+ refreshRequested = output();
1124
+ sensitiveToggled = output();
1125
+ static ɵfac = i0.ɵɵngDeclareFactory({
1126
+ minVersion: "12.0.0",
1127
+ version: "22.2.4",
1128
+ ngImport: i0,
1129
+ type: WidgetToolbar,
1130
+ deps: [],
1131
+ target: i0.ɵɵFactoryTarget.Component
1132
+ });
1133
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1134
+ minVersion: "17.0.0",
1135
+ version: "22.2.4",
1136
+ type: WidgetToolbar,
1137
+ isStandalone: true,
1138
+ selector: "widget-toolbar",
1139
+ inputs: {
1140
+ refresh: {
1141
+ classPropertyName: "refresh",
1142
+ publicName: "refresh",
1143
+ isSignal: true,
1144
+ isRequired: false,
1145
+ transformFunction: null
1146
+ },
1147
+ hasSensitiveElements: {
1148
+ classPropertyName: "hasSensitiveElements",
1149
+ publicName: "hasSensitiveElements",
1150
+ isSignal: true,
1151
+ isRequired: false,
1152
+ transformFunction: null
1153
+ },
1154
+ sensitiveVisible: {
1155
+ classPropertyName: "sensitiveVisible",
1156
+ publicName: "sensitiveVisible",
1157
+ isSignal: true,
1158
+ isRequired: false,
1159
+ transformFunction: null
1160
+ },
1161
+ locale: {
1162
+ classPropertyName: "locale",
1163
+ publicName: "locale",
1164
+ isSignal: true,
1165
+ isRequired: false,
1166
+ transformFunction: null
1167
+ }
1168
+ },
1169
+ outputs: {
1170
+ refreshRequested: "refreshRequested",
1171
+ sensitiveToggled: "sensitiveToggled"
1172
+ },
1173
+ ngImport: i0,
1174
+ template: `<div class="widget-toolbar" [attr.aria-label]="locale().aria.toolbarActions">
1175
+ @if (refresh()?.enabled) {
1176
+ <button
1177
+ type="button"
1178
+ class="icon-button"
1179
+ [attr.aria-label]="refresh()?.label"
1180
+ [title]="refresh()?.label"
1181
+ (click)="refreshRequested.emit()"
1182
+ >
1183
+ ↻
1184
+ </button>
1185
+ }
1186
+ @if (hasSensitiveElements()) {
1187
+ <button
1188
+ type="button"
1189
+ class="icon-button"
1190
+ [attr.aria-label]="
1191
+ sensitiveVisible() ? locale().aria.hideSensitiveData : locale().aria.showSensitiveData
1192
+ "
1193
+ [title]="
1194
+ sensitiveVisible() ? locale().aria.hideSensitiveData : locale().aria.showSensitiveData
1195
+ "
1196
+ (click)="sensitiveToggled.emit()"
1197
+ >
1198
+ @if (sensitiveVisible()) {
1199
+ <svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
1200
+ <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12Z" />
1201
+ <circle cx="12" cy="12" r="2.5" />
1202
+ </svg>
1203
+ } @else {
1204
+ <svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
1205
+ <path
1206
+ d="m3 3 18 18M10.6 5.3A10.7 10.7 0 0 1 12 5c6.5 0 10 7 10 7a18.4 18.4 0 0 1-3.1 3.8M6.2 6.2C3.5 8 2 12 2 12s3.5 7 10 7a10.7 10.7 0 0 1-3.4-.6"
1207
+ />
1208
+ </svg>
1209
+ }
1210
+ </button>
1211
+ }
1212
+ </div>`,
1213
+ isInline: true,
1214
+ styles: [":host{position:absolute;top:8px;right:8px;z-index:3}.widget-toolbar{display:flex;gap:4px;opacity:0;transform:translateY(-4px);transition:opacity var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease),transform var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}:host-context(.widget-shell:hover) .widget-toolbar,:host-context(.widget-shell:focus-within) .widget-toolbar{opacity:1;transform:translateY(0)}.icon-button{display:inline-flex;align-items:center;justify-content:center;pointer-events:var(--widget-renderer-actions-pointer-events, auto);width:var(--widget-renderer-control-size, 28px);height:var(--widget-renderer-control-size, 28px);border:1px solid var(--widget-renderer-control-border, #ffffff38);border-radius:var(--widget-renderer-radius, 8px);background:var(--widget-renderer-control-background, #10182ccc);color:var(--widget-renderer-action-color, #fff);cursor:pointer}.icon-button svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.icon-button:hover,.icon-button:focus-visible{border-color:var(--widget-renderer-control-hover-border, #17233c);background:var(--widget-renderer-control-hover-background, #fff);color:var(--widget-renderer-control-hover-color, #17233c)}\n"]
1215
+ });
1216
+ };
1217
+ i0.ɵɵngDeclareClassMetadata({
1218
+ minVersion: "12.0.0",
1219
+ version: "22.2.4",
1220
+ ngImport: i0,
1221
+ type: WidgetToolbar,
1222
+ decorators: [{
1223
+ type: Component,
1224
+ args: [{
1225
+ selector: "widget-toolbar",
1226
+ template: `<div class="widget-toolbar" [attr.aria-label]="locale().aria.toolbarActions">
1227
+ @if (refresh()?.enabled) {
1228
+ <button
1229
+ type="button"
1230
+ class="icon-button"
1231
+ [attr.aria-label]="refresh()?.label"
1232
+ [title]="refresh()?.label"
1233
+ (click)="refreshRequested.emit()"
1234
+ >
1235
+ ↻
1236
+ </button>
1237
+ }
1238
+ @if (hasSensitiveElements()) {
1239
+ <button
1240
+ type="button"
1241
+ class="icon-button"
1242
+ [attr.aria-label]="
1243
+ sensitiveVisible() ? locale().aria.hideSensitiveData : locale().aria.showSensitiveData
1244
+ "
1245
+ [title]="
1246
+ sensitiveVisible() ? locale().aria.hideSensitiveData : locale().aria.showSensitiveData
1247
+ "
1248
+ (click)="sensitiveToggled.emit()"
1249
+ >
1250
+ @if (sensitiveVisible()) {
1251
+ <svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
1252
+ <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12Z" />
1253
+ <circle cx="12" cy="12" r="2.5" />
1254
+ </svg>
1255
+ } @else {
1256
+ <svg aria-hidden="true" viewBox="0 0 24 24" focusable="false">
1257
+ <path
1258
+ d="m3 3 18 18M10.6 5.3A10.7 10.7 0 0 1 12 5c6.5 0 10 7 10 7a18.4 18.4 0 0 1-3.1 3.8M6.2 6.2C3.5 8 2 12 2 12s3.5 7 10 7a10.7 10.7 0 0 1-3.4-.6"
1259
+ />
1260
+ </svg>
1261
+ }
1262
+ </button>
1263
+ }
1264
+ </div>`,
1265
+ styles: [":host{position:absolute;top:8px;right:8px;z-index:3}.widget-toolbar{display:flex;gap:4px;opacity:0;transform:translateY(-4px);transition:opacity var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease),transform var(--widget-renderer-transition-duration, .16s) var(--widget-renderer-transition-easing, ease)}:host-context(.widget-shell:hover) .widget-toolbar,:host-context(.widget-shell:focus-within) .widget-toolbar{opacity:1;transform:translateY(0)}.icon-button{display:inline-flex;align-items:center;justify-content:center;pointer-events:var(--widget-renderer-actions-pointer-events, auto);width:var(--widget-renderer-control-size, 28px);height:var(--widget-renderer-control-size, 28px);border:1px solid var(--widget-renderer-control-border, #ffffff38);border-radius:var(--widget-renderer-radius, 8px);background:var(--widget-renderer-control-background, #10182ccc);color:var(--widget-renderer-action-color, #fff);cursor:pointer}.icon-button svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.icon-button:hover,.icon-button:focus-visible{border-color:var(--widget-renderer-control-hover-border, #17233c);background:var(--widget-renderer-control-hover-background, #fff);color:var(--widget-renderer-control-hover-color, #17233c)}\n"]
1266
+ }]
1267
+ }],
1268
+ propDecorators: {
1269
+ refresh: [{
1270
+ type: i0.Input,
1271
+ args: [{
1272
+ isSignal: true,
1273
+ alias: "refresh",
1274
+ required: false
1275
+ }]
1276
+ }],
1277
+ hasSensitiveElements: [{
1278
+ type: i0.Input,
1279
+ args: [{
1280
+ isSignal: true,
1281
+ alias: "hasSensitiveElements",
1282
+ required: false
1283
+ }]
1284
+ }],
1285
+ sensitiveVisible: [{
1286
+ type: i0.Input,
1287
+ args: [{
1288
+ isSignal: true,
1289
+ alias: "sensitiveVisible",
1290
+ required: false
1291
+ }]
1292
+ }],
1293
+ locale: [{
1294
+ type: i0.Input,
1295
+ args: [{
1296
+ isSignal: true,
1297
+ alias: "locale",
1298
+ required: false
1299
+ }]
1300
+ }],
1301
+ refreshRequested: [{
1302
+ type: i0.Output,
1303
+ args: ["refreshRequested"]
1304
+ }],
1305
+ sensitiveToggled: [{
1306
+ type: i0.Output,
1307
+ args: ["sensitiveToggled"]
1308
+ }]
1309
+ }
1310
+ });
1311
+ var WidgetValidationOverlay = class WidgetValidationOverlay {
1312
+ issues = input.required(...ngDevMode ? [{ debugName: "issues" }] : /* istanbul ignore next */ []);
1313
+ static ɵfac = i0.ɵɵngDeclareFactory({
1314
+ minVersion: "12.0.0",
1315
+ version: "22.2.4",
1316
+ ngImport: i0,
1317
+ type: WidgetValidationOverlay,
1318
+ deps: [],
1319
+ target: i0.ɵɵFactoryTarget.Component
1320
+ });
1321
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1322
+ minVersion: "17.0.0",
1323
+ version: "22.2.4",
1324
+ type: WidgetValidationOverlay,
1325
+ isStandalone: true,
1326
+ selector: "widget-validation-overlay",
1327
+ inputs: { issues: {
1328
+ classPropertyName: "issues",
1329
+ publicName: "issues",
1330
+ isSignal: true,
1331
+ isRequired: true,
1332
+ transformFunction: null
1333
+ } },
1334
+ ngImport: i0,
1335
+ template: `<div class="widget-validation-overlay" role="alert" aria-live="polite">
1336
+ <strong class="widget-validation-title">Widget validation failed</strong>
1337
+ <ul class="widget-validation-issues">
1338
+ @for (issue of issues(); track $index) {
1339
+ <li>
1340
+ <code>{{ issue.path }}</code
1341
+ >: {{ issue.message }}
1342
+ </li>
1343
+ }
1344
+ </ul>
1345
+ </div>`,
1346
+ isInline: true,
1347
+ styles: [":host{position:absolute;inset:0;z-index:2}.widget-validation-overlay{height:100%;display:flex;flex-direction:column;gap:8px;box-sizing:border-box;overflow:auto;padding:var(--widget-renderer-content-padding, 18px);border:1px solid #e06a6a;background:#fff4f4ef;color:#7f1d1d;pointer-events:auto}.widget-validation-title{font-size:13px}.widget-validation-issues{display:grid;gap:4px;margin:0;padding-inline-start:18px;font:12px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace}.widget-validation-issues code{font:inherit;font-weight:700}:host-context(html[data-theme=\"dark\"]) .widget-validation-overlay{border-color:#f08a8a;background:#3b1717ef;color:#ffd6d6}\n"]
1348
+ });
1349
+ };
1350
+ i0.ɵɵngDeclareClassMetadata({
1351
+ minVersion: "12.0.0",
1352
+ version: "22.2.4",
1353
+ ngImport: i0,
1354
+ type: WidgetValidationOverlay,
1355
+ decorators: [{
1356
+ type: Component,
1357
+ args: [{
1358
+ selector: "widget-validation-overlay",
1359
+ template: `<div class="widget-validation-overlay" role="alert" aria-live="polite">
1360
+ <strong class="widget-validation-title">Widget validation failed</strong>
1361
+ <ul class="widget-validation-issues">
1362
+ @for (issue of issues(); track $index) {
1363
+ <li>
1364
+ <code>{{ issue.path }}</code
1365
+ >: {{ issue.message }}
1366
+ </li>
1367
+ }
1368
+ </ul>
1369
+ </div>`,
1370
+ styles: [":host{position:absolute;inset:0;z-index:2}.widget-validation-overlay{height:100%;display:flex;flex-direction:column;gap:8px;box-sizing:border-box;overflow:auto;padding:var(--widget-renderer-content-padding, 18px);border:1px solid #e06a6a;background:#fff4f4ef;color:#7f1d1d;pointer-events:auto}.widget-validation-title{font-size:13px}.widget-validation-issues{display:grid;gap:4px;margin:0;padding-inline-start:18px;font:12px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace}.widget-validation-issues code{font:inherit;font-weight:700}:host-context(html[data-theme=\"dark\"]) .widget-validation-overlay{border-color:#f08a8a;background:#3b1717ef;color:#ffd6d6}\n"]
1371
+ }]
1372
+ }],
1373
+ propDecorators: { issues: [{
1374
+ type: i0.Input,
1375
+ args: [{
1376
+ isSignal: true,
1377
+ alias: "issues",
1378
+ required: true
1379
+ }]
1380
+ }] }
1381
+ });
1382
+ var WidgetRenderer = class WidgetRenderer {
1383
+ widget = input(null, ...ngDevMode ? [{ debugName: "widget" }] : /* istanbul ignore next */ []);
1384
+ loading = input(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
1385
+ darkMode = input(false, ...ngDevMode ? [{ debugName: "darkMode" }] : /* istanbul ignore next */ []);
1386
+ locale = input({}, ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
1387
+ validationRules = input([], ...ngDevMode ? [{ debugName: "validationRules" }] : /* istanbul ignore next */ []);
1388
+ refreshRequested = output();
1389
+ actionRequested = output();
1390
+ sensitiveVisible = signal(false, ...ngDevMode ? [{ debugName: "sensitiveVisible" }] : /* istanbul ignore next */ []);
1391
+ tooltip = inject(WidgetTooltip);
1392
+ tooltipLayer = viewChild("tooltipLayer", ...ngDevMode ? [{ debugName: "tooltipLayer" }] : /* istanbul ignore next */ []);
1393
+ parsedWidget = computed(() => {
1394
+ const widget = this.widget();
1395
+ return widget === null ? {
1396
+ success: false,
1397
+ issues: []
1398
+ } : safeParseWidgetInput(widget, { rules: this.validationRules() });
1399
+ }, ...ngDevMode ? [{ debugName: "parsedWidget" }] : /* istanbul ignore next */ []);
1400
+ isLoading = computed(() => this.loading() !== false, ...ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []);
1401
+ resolvedLocale = computed(() => ({
1402
+ ...defaultWidgetRendererLocale,
1403
+ aria: {
1404
+ ...defaultWidgetRendererLocale.aria,
1405
+ ...this.locale().aria,
1406
+ chart: {
1407
+ ...defaultWidgetRendererLocale.aria.chart,
1408
+ ...this.locale().aria?.chart
1409
+ }
1410
+ }
1411
+ }), ...ngDevMode ? [{ debugName: "resolvedLocale" }] : /* istanbul ignore next */ []);
1412
+ loadingSize = computed(() => {
1413
+ const loading = this.loading();
1414
+ return typeof loading === "string" ? loading : "square";
1415
+ }, ...ngDevMode ? [{ debugName: "loadingSize" }] : /* istanbul ignore next */ []);
1416
+ validationIssues = computed(() => this.parsedWidget().issues, ...ngDevMode ? [{ debugName: "validationIssues" }] : /* istanbul ignore next */ []);
1417
+ blockingIssues = computed(() => this.validationIssues().filter((issue) => issue.severity !== "report"), ...ngDevMode ? [{ debugName: "blockingIssues" }] : /* istanbul ignore next */ []);
1418
+ renderWidget = computed(() => {
1419
+ const result = this.parsedWidget();
1420
+ if (!result.success) return {
1421
+ ...emptyWidget,
1422
+ size: widgetSizeOrSquare(this.widget()?.size)
1423
+ };
1424
+ return {
1425
+ ...normalizeWidgetInput(result.data),
1426
+ refresh: result.data.refresh ?? emptyWidget.refresh
1427
+ };
1428
+ }, ...ngDevMode ? [{ debugName: "renderWidget" }] : /* istanbul ignore next */ []);
1429
+ hasSensitiveElements = computed(() => {
1430
+ const widget = this.renderWidget();
1431
+ return widget.background.sensitive || widget.elements.some((element) => "sensitive" in element && element.sensitive);
1432
+ }, ...ngDevMode ? [{ debugName: "hasSensitiveElements" }] : /* istanbul ignore next */ []);
1433
+ backgroundSensitive = computed(() => {
1434
+ return this.renderWidget().background.sensitive && !this.sensitiveVisible();
1435
+ }, ...ngDevMode ? [{ debugName: "backgroundSensitive" }] : /* istanbul ignore next */ []);
1436
+ gridRows = computed(() => gridTemplate(this.renderWidget().rows), ...ngDevMode ? [{ debugName: "gridRows" }] : /* istanbul ignore next */ []);
1437
+ gridColumns = computed(() => gridTemplate(this.renderWidget().columns), ...ngDevMode ? [{ debugName: "gridColumns" }] : /* istanbul ignore next */ []);
1438
+ widgetWidth = computed(() => widgetWidth(this.renderWidget().size), ...ngDevMode ? [{ debugName: "widgetWidth" }] : /* istanbul ignore next */ []);
1439
+ widgetHeight = computed(() => widgetHeight(this.renderWidget().size), ...ngDevMode ? [{ debugName: "widgetHeight" }] : /* istanbul ignore next */ []);
1440
+ backgroundImage = computed(() => {
1441
+ const image = this.renderWidget().background.image;
1442
+ return image ? `url("${image}")` : "none";
1443
+ }, ...ngDevMode ? [{ debugName: "backgroundImage" }] : /* istanbul ignore next */ []);
1444
+ constructor() {
1445
+ effect(() => {
1446
+ this.widget();
1447
+ this.sensitiveVisible.set(false);
1448
+ });
1449
+ effect(() => {
1450
+ if (this.loading() !== false) this.sensitiveVisible.set(false);
1451
+ });
1452
+ effect(() => {
1453
+ const layer = this.tooltipLayer()?.nativeElement;
1454
+ if (layer) this.tooltip.setOverlay(layer);
1455
+ });
1456
+ }
1457
+ ngOnDestroy() {
1458
+ this.tooltip.clear();
1459
+ }
1460
+ toggleSensitive() {
1461
+ this.sensitiveVisible.update((visible) => !visible);
1462
+ }
1463
+ static ɵfac = i0.ɵɵngDeclareFactory({
1464
+ minVersion: "12.0.0",
1465
+ version: "22.2.4",
1466
+ ngImport: i0,
1467
+ type: WidgetRenderer,
1468
+ deps: [],
1469
+ target: i0.ɵɵFactoryTarget.Component
1470
+ });
1471
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1472
+ minVersion: "17.0.0",
1473
+ version: "22.2.4",
1474
+ type: WidgetRenderer,
1475
+ isStandalone: true,
1476
+ selector: "widget-renderer",
1477
+ inputs: {
1478
+ widget: {
1479
+ classPropertyName: "widget",
1480
+ publicName: "widget",
1481
+ isSignal: true,
1482
+ isRequired: false,
1483
+ transformFunction: null
1484
+ },
1485
+ loading: {
1486
+ classPropertyName: "loading",
1487
+ publicName: "loading",
1488
+ isSignal: true,
1489
+ isRequired: false,
1490
+ transformFunction: null
1491
+ },
1492
+ darkMode: {
1493
+ classPropertyName: "darkMode",
1494
+ publicName: "darkMode",
1495
+ isSignal: true,
1496
+ isRequired: false,
1497
+ transformFunction: null
1498
+ },
1499
+ locale: {
1500
+ classPropertyName: "locale",
1501
+ publicName: "locale",
1502
+ isSignal: true,
1503
+ isRequired: false,
1504
+ transformFunction: null
1505
+ },
1506
+ validationRules: {
1507
+ classPropertyName: "validationRules",
1508
+ publicName: "validationRules",
1509
+ isSignal: true,
1510
+ isRequired: false,
1511
+ transformFunction: null
1512
+ }
1513
+ },
1514
+ outputs: {
1515
+ refreshRequested: "refreshRequested",
1516
+ actionRequested: "actionRequested"
1517
+ },
1518
+ providers: [WidgetTooltip],
1519
+ viewQueries: [{
1520
+ propertyName: "tooltipLayer",
1521
+ first: true,
1522
+ predicate: ["tooltipLayer"],
1523
+ descendants: true,
1524
+ isSignal: true
1525
+ }],
1526
+ ngImport: i0,
1527
+ template: "@if (isLoading()) {\n <widget-skeleton [size]=\"loadingSize()\" [darkMode]=\"darkMode()\" [locale]=\"resolvedLocale()\" />\n} @else {\n @let widget = renderWidget();\n <section class=\"widget-shell\" [style.width.px]=\"widgetWidth()\" [style.height.px]=\"widgetHeight()\">\n <div\n class=\"widget-viewport\"\n [style.background-color]=\"widget.background.color || 'transparent'\"\n >\n <widget-background\n [background]=\"widget.background\"\n [sensitive]=\"backgroundSensitive()\"\n [image]=\"backgroundImage()\"\n />\n @if (blockingIssues().length > 0) {\n <widget-validation-overlay [issues]=\"blockingIssues()\" />\n }\n <widget-toolbar\n [refresh]=\"widget.refresh\"\n [hasSensitiveElements]=\"hasSensitiveElements()\"\n [sensitiveVisible]=\"sensitiveVisible()\"\n [locale]=\"resolvedLocale()\"\n (refreshRequested)=\"refreshRequested.emit()\"\n (sensitiveToggled)=\"toggleSensitive()\"\n />\n <div\n class=\"widget-grid\"\n [style.grid-template-rows]=\"gridRows()\"\n [style.grid-template-columns]=\"gridColumns()\"\n >\n @for (element of widget.elements; track $index) {\n <widget-element-renderer\n [element]=\"element\"\n [sensitiveVisible]=\"sensitiveVisible()\"\n [locale]=\"resolvedLocale()\"\n (actionRequested)=\"actionRequested.emit($event)\"\n />\n }\n </div>\n </div>\n <div #tooltipLayer class=\"widget-tooltip-layer\">\n @if (tooltip.state(); as tip) {\n <span\n class=\"chart-tooltip\"\n role=\"tooltip\"\n [style.--tooltip-x.px]=\"tip.x\"\n [style.--tooltip-y.px]=\"tip.y\"\n [style.--tooltip-border]=\"tip.color || 'rgb(0 0 0 / 0.12)'\"\n ><span class=\"tooltip-marker\" [style.background]=\"tip.color\"></span\n ><span>{{ tip.label }}</span\n ><strong>{{ tip.value }}</strong></span\n >\n }\n </div>\n </section>\n}\n",
1528
+ styles: [":host{display:block;--widget-renderer-radius: 8px;--widget-renderer-pill-radius: 999px;--widget-renderer-control-size: 28px;--widget-renderer-content-padding: 18px;--widget-renderer-shadow: 0 18px 40px #10182c38;--widget-renderer-transition-duration: .16s;--widget-renderer-transition-easing: ease;--widget-renderer-control-background: #10182ccc;--widget-renderer-control-border: #ffffff38;--widget-renderer-control-hover-border: #17233c;--widget-renderer-control-hover-background: #fff;--widget-renderer-control-hover-color: #17233c;--widget-renderer-action-background: #151515;--widget-renderer-action-color: #fff;--widget-renderer-action-outline-border: #737373;--widget-renderer-action-outline-background: #fff;--widget-renderer-action-outline-color: #151515}.widget-skeleton{position:relative;width:274px;max-width:100%;height:254px;box-sizing:border-box;overflow:hidden;border-radius:var(--widget-renderer-radius);background:#dfe5ee;box-shadow:var(--widget-renderer-shadow)}.widget-skeleton.is-wide{width:556px}.widget-skeleton.is-mini{width:133px;height:123px}.widget-skeleton.is-compact{width:274px;height:123px}.widget-skeleton.is-tall{width:133px;height:254px}.widget-skeleton.is-mega{width:556px;height:516px}.widget-skeleton.is-banner{width:274px;height:516px}.widget-skeleton.is-hero{width:1120px;height:516px}.widget-skeleton.is-mini .skeleton-toolbar{top:8px;right:8px;width:22px;height:22px}.widget-skeleton.is-mini .skeleton-content{box-sizing:border-box;height:100%;gap:3px;padding:24px 12px 8px}.widget-skeleton.is-mini .skeleton-line{height:6px}.widget-skeleton.is-mini .skeleton-line-title{height:10px}.widget-skeleton.is-mini .skeleton-chart{flex:1 1 auto;min-height:20px;margin-top:0}.widget-skeleton.is-mini .skeleton-button{width:42px;height:18px}.widget-skeleton:is(.is-compact,.is-tall) .skeleton-content{box-sizing:border-box;height:100%;gap:5px;padding:30px 12px 10px}.widget-skeleton.is-compact .skeleton-chart{min-height:28px;margin-top:0}.widget-skeleton.is-tall .skeleton-chart{flex:1 1 auto;min-height:45px;margin-top:0}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-content{box-sizing:border-box;height:100%}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-chart{flex:1 1 auto;min-height:180px}.widget-skeleton.is-dark{background:#182236}.skeleton-line,.skeleton-chart,.skeleton-button{background:linear-gradient(100deg,#dfe5ee 20%,#f2f5f9,#dfe5ee 70%);background-size:200% 100%;animation:skeleton-shimmer 1.8s linear infinite}.widget-skeleton.is-dark .skeleton-line,.widget-skeleton.is-dark .skeleton-chart,.widget-skeleton.is-dark .skeleton-button{background:linear-gradient(100deg,#182236 20%,#2b3b59,#182236 70%);background-size:200% 100%}.skeleton-toolbar{position:absolute;top:12px;right:12px;width:var(--widget-renderer-control-size);height:var(--widget-renderer-control-size);border-radius:var(--widget-renderer-radius);background:#c4cedd}.widget-skeleton.is-dark .skeleton-toolbar{background:#2b3b59}.skeleton-content{display:flex;flex-direction:column;gap:10px;padding:44px var(--widget-renderer-content-padding) 16px}.skeleton-line{display:block;height:10px;border-radius:var(--widget-renderer-pill-radius)}.skeleton-line-small{width:28%}.skeleton-line-title{width:72%;height:20px}.skeleton-line-copy{width:58%}.skeleton-chart{width:100%;height:64px;margin-top:2px;border-radius:var(--widget-renderer-radius)}.skeleton-button{align-self:flex-end;width:58px;height:30px;border-radius:var(--widget-renderer-radius)}@keyframes skeleton-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.skeleton-line,.skeleton-chart,.skeleton-button{animation:none}}.widget-shell{position:relative;overflow:visible;box-sizing:border-box;color:#f6f7fb}.widget-viewport{position:absolute;inset:0;overflow:hidden;border-radius:var(--widget-renderer-radius);box-shadow:var(--widget-renderer-shadow)}.widget-viewport:after{position:absolute;inset:0;z-index:5;box-sizing:border-box;border:1px solid #10182c26;border-radius:inherit;content:\"\";pointer-events:none}.widget-tooltip-layer{position:absolute;inset:0;z-index:6;overflow:visible;pointer-events:none}.chart-tooltip{--tooltip-border: rgb(0 0 0 / .12);position:absolute;z-index:4;top:var(--tooltip-y);left:var(--tooltip-x);display:flex;min-width:104px;align-items:center;gap:7px;padding:10px;transform:translate(-50%,calc(-100% - 10px));border:1px solid var(--tooltip-border);border-radius:var(--widget-renderer-radius, 4px);background:var(--widget-renderer-control-hover-background, #fff);box-shadow:1px 2px 10px #0003;color:#6e7079;font-size:14px;font-weight:400;line-height:1;white-space:nowrap}.chart-tooltip strong{margin-inline-start:auto;color:#464646;font-size:14px;font-weight:900}.tooltip-marker{width:9px;height:9px;flex:0 0 auto;border-radius:50%}.widget-grid{position:absolute;inset:0;display:grid;gap:8px;padding:18px}.chart-placeholder{width:100%;height:100%}.element-content{display:flex;width:100%;height:100%;min-width:0;min-height:0}.element-content:has(widget-chart-element){align-items:stretch}.element-content>widget-chart-element{flex:0 1 auto;width:100%;height:100%;max-width:100%;max-height:100%}.element-content>widget-chart-element.is-progress{height:auto}.divider-element{width:100%;height:2px;flex:0 0 auto;border-radius:var(--widget-renderer-pill-radius)}.divider-element.is-vertical{width:2px;height:100%}.element-content.is-sensitive{filter:blur(var(--sensitive-blur, 2px));-webkit-user-select:none;user-select:none}.text-element{display:inline-block;overflow:visible;line-height:1.2}img{width:100%;height:100%;display:block}.image-overlay{position:absolute;inset:0;z-index:1;pointer-events:none;border-radius:inherit}.image-placeholder{display:flex;width:100%;height:100%;align-items:center;justify-content:center;overflow:hidden;background:#dfe5ee}.image-placeholder svg{width:min(56px,45%);height:auto;fill:none;stroke:#8c9ab0;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.action-button{min-height:30px;border-radius:var(--widget-renderer-radius);padding:6px 10px;font:600 12px/1.1 inherit;cursor:var(--widget-renderer-action-cursor, pointer)}.action-button.show-only-on-hover{opacity:0;pointer-events:none;transform:translateY(2px);transition:opacity var(--widget-renderer-transition-duration) var(--widget-renderer-transition-easing),transform var(--widget-renderer-transition-duration) var(--widget-renderer-transition-easing)}.widget-shell:hover .action-button.show-only-on-hover,.widget-shell:focus-within .action-button.show-only-on-hover{opacity:1;pointer-events:auto;transform:translateY(0)}.action-button.solid{border:1px solid #151515;background:#151515;color:#fff}.action-button.outline{border:1px solid #737373;background:#fff;color:#151515}\n"],
1529
+ dependencies: [
1530
+ {
1531
+ kind: "component",
1532
+ type: WidgetElementRenderer,
1533
+ selector: "widget-element-renderer",
1534
+ inputs: [
1535
+ "element",
1536
+ "sensitiveVisible",
1537
+ "locale"
1538
+ ],
1539
+ outputs: ["actionRequested"]
1540
+ },
1541
+ {
1542
+ kind: "component",
1543
+ type: WidgetSkeleton,
1544
+ selector: "widget-skeleton",
1545
+ inputs: [
1546
+ "size",
1547
+ "darkMode",
1548
+ "locale"
1549
+ ]
1550
+ },
1551
+ {
1552
+ kind: "component",
1553
+ type: WidgetBackground,
1554
+ selector: "widget-background",
1555
+ inputs: [
1556
+ "background",
1557
+ "sensitive",
1558
+ "image"
1559
+ ]
1560
+ },
1561
+ {
1562
+ kind: "component",
1563
+ type: WidgetToolbar,
1564
+ selector: "widget-toolbar",
1565
+ inputs: [
1566
+ "refresh",
1567
+ "hasSensitiveElements",
1568
+ "sensitiveVisible",
1569
+ "locale"
1570
+ ],
1571
+ outputs: ["refreshRequested", "sensitiveToggled"]
1572
+ },
1573
+ {
1574
+ kind: "component",
1575
+ type: WidgetValidationOverlay,
1576
+ selector: "widget-validation-overlay",
1577
+ inputs: ["issues"]
1578
+ }
1579
+ ]
1580
+ });
1581
+ };
1582
+ i0.ɵɵngDeclareClassMetadata({
1583
+ minVersion: "12.0.0",
1584
+ version: "22.2.4",
1585
+ ngImport: i0,
1586
+ type: WidgetRenderer,
1587
+ decorators: [{
1588
+ type: Component,
1589
+ args: [{
1590
+ selector: "widget-renderer",
1591
+ providers: [WidgetTooltip],
1592
+ imports: [
1593
+ WidgetElementRenderer,
1594
+ WidgetSkeleton,
1595
+ WidgetBackground,
1596
+ WidgetToolbar,
1597
+ WidgetValidationOverlay
1598
+ ],
1599
+ template: "@if (isLoading()) {\n <widget-skeleton [size]=\"loadingSize()\" [darkMode]=\"darkMode()\" [locale]=\"resolvedLocale()\" />\n} @else {\n @let widget = renderWidget();\n <section class=\"widget-shell\" [style.width.px]=\"widgetWidth()\" [style.height.px]=\"widgetHeight()\">\n <div\n class=\"widget-viewport\"\n [style.background-color]=\"widget.background.color || 'transparent'\"\n >\n <widget-background\n [background]=\"widget.background\"\n [sensitive]=\"backgroundSensitive()\"\n [image]=\"backgroundImage()\"\n />\n @if (blockingIssues().length > 0) {\n <widget-validation-overlay [issues]=\"blockingIssues()\" />\n }\n <widget-toolbar\n [refresh]=\"widget.refresh\"\n [hasSensitiveElements]=\"hasSensitiveElements()\"\n [sensitiveVisible]=\"sensitiveVisible()\"\n [locale]=\"resolvedLocale()\"\n (refreshRequested)=\"refreshRequested.emit()\"\n (sensitiveToggled)=\"toggleSensitive()\"\n />\n <div\n class=\"widget-grid\"\n [style.grid-template-rows]=\"gridRows()\"\n [style.grid-template-columns]=\"gridColumns()\"\n >\n @for (element of widget.elements; track $index) {\n <widget-element-renderer\n [element]=\"element\"\n [sensitiveVisible]=\"sensitiveVisible()\"\n [locale]=\"resolvedLocale()\"\n (actionRequested)=\"actionRequested.emit($event)\"\n />\n }\n </div>\n </div>\n <div #tooltipLayer class=\"widget-tooltip-layer\">\n @if (tooltip.state(); as tip) {\n <span\n class=\"chart-tooltip\"\n role=\"tooltip\"\n [style.--tooltip-x.px]=\"tip.x\"\n [style.--tooltip-y.px]=\"tip.y\"\n [style.--tooltip-border]=\"tip.color || 'rgb(0 0 0 / 0.12)'\"\n ><span class=\"tooltip-marker\" [style.background]=\"tip.color\"></span\n ><span>{{ tip.label }}</span\n ><strong>{{ tip.value }}</strong></span\n >\n }\n </div>\n </section>\n}\n",
1600
+ styles: [":host{display:block;--widget-renderer-radius: 8px;--widget-renderer-pill-radius: 999px;--widget-renderer-control-size: 28px;--widget-renderer-content-padding: 18px;--widget-renderer-shadow: 0 18px 40px #10182c38;--widget-renderer-transition-duration: .16s;--widget-renderer-transition-easing: ease;--widget-renderer-control-background: #10182ccc;--widget-renderer-control-border: #ffffff38;--widget-renderer-control-hover-border: #17233c;--widget-renderer-control-hover-background: #fff;--widget-renderer-control-hover-color: #17233c;--widget-renderer-action-background: #151515;--widget-renderer-action-color: #fff;--widget-renderer-action-outline-border: #737373;--widget-renderer-action-outline-background: #fff;--widget-renderer-action-outline-color: #151515}.widget-skeleton{position:relative;width:274px;max-width:100%;height:254px;box-sizing:border-box;overflow:hidden;border-radius:var(--widget-renderer-radius);background:#dfe5ee;box-shadow:var(--widget-renderer-shadow)}.widget-skeleton.is-wide{width:556px}.widget-skeleton.is-mini{width:133px;height:123px}.widget-skeleton.is-compact{width:274px;height:123px}.widget-skeleton.is-tall{width:133px;height:254px}.widget-skeleton.is-mega{width:556px;height:516px}.widget-skeleton.is-banner{width:274px;height:516px}.widget-skeleton.is-hero{width:1120px;height:516px}.widget-skeleton.is-mini .skeleton-toolbar{top:8px;right:8px;width:22px;height:22px}.widget-skeleton.is-mini .skeleton-content{box-sizing:border-box;height:100%;gap:3px;padding:24px 12px 8px}.widget-skeleton.is-mini .skeleton-line{height:6px}.widget-skeleton.is-mini .skeleton-line-title{height:10px}.widget-skeleton.is-mini .skeleton-chart{flex:1 1 auto;min-height:20px;margin-top:0}.widget-skeleton.is-mini .skeleton-button{width:42px;height:18px}.widget-skeleton:is(.is-compact,.is-tall) .skeleton-content{box-sizing:border-box;height:100%;gap:5px;padding:30px 12px 10px}.widget-skeleton.is-compact .skeleton-chart{min-height:28px;margin-top:0}.widget-skeleton.is-tall .skeleton-chart{flex:1 1 auto;min-height:45px;margin-top:0}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-content{box-sizing:border-box;height:100%}.widget-skeleton:is(.is-mega,.is-banner,.is-hero) .skeleton-chart{flex:1 1 auto;min-height:180px}.widget-skeleton.is-dark{background:#182236}.skeleton-line,.skeleton-chart,.skeleton-button{background:linear-gradient(100deg,#dfe5ee 20%,#f2f5f9,#dfe5ee 70%);background-size:200% 100%;animation:skeleton-shimmer 1.8s linear infinite}.widget-skeleton.is-dark .skeleton-line,.widget-skeleton.is-dark .skeleton-chart,.widget-skeleton.is-dark .skeleton-button{background:linear-gradient(100deg,#182236 20%,#2b3b59,#182236 70%);background-size:200% 100%}.skeleton-toolbar{position:absolute;top:12px;right:12px;width:var(--widget-renderer-control-size);height:var(--widget-renderer-control-size);border-radius:var(--widget-renderer-radius);background:#c4cedd}.widget-skeleton.is-dark .skeleton-toolbar{background:#2b3b59}.skeleton-content{display:flex;flex-direction:column;gap:10px;padding:44px var(--widget-renderer-content-padding) 16px}.skeleton-line{display:block;height:10px;border-radius:var(--widget-renderer-pill-radius)}.skeleton-line-small{width:28%}.skeleton-line-title{width:72%;height:20px}.skeleton-line-copy{width:58%}.skeleton-chart{width:100%;height:64px;margin-top:2px;border-radius:var(--widget-renderer-radius)}.skeleton-button{align-self:flex-end;width:58px;height:30px;border-radius:var(--widget-renderer-radius)}@keyframes skeleton-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.skeleton-line,.skeleton-chart,.skeleton-button{animation:none}}.widget-shell{position:relative;overflow:visible;box-sizing:border-box;color:#f6f7fb}.widget-viewport{position:absolute;inset:0;overflow:hidden;border-radius:var(--widget-renderer-radius);box-shadow:var(--widget-renderer-shadow)}.widget-viewport:after{position:absolute;inset:0;z-index:5;box-sizing:border-box;border:1px solid #10182c26;border-radius:inherit;content:\"\";pointer-events:none}.widget-tooltip-layer{position:absolute;inset:0;z-index:6;overflow:visible;pointer-events:none}.chart-tooltip{--tooltip-border: rgb(0 0 0 / .12);position:absolute;z-index:4;top:var(--tooltip-y);left:var(--tooltip-x);display:flex;min-width:104px;align-items:center;gap:7px;padding:10px;transform:translate(-50%,calc(-100% - 10px));border:1px solid var(--tooltip-border);border-radius:var(--widget-renderer-radius, 4px);background:var(--widget-renderer-control-hover-background, #fff);box-shadow:1px 2px 10px #0003;color:#6e7079;font-size:14px;font-weight:400;line-height:1;white-space:nowrap}.chart-tooltip strong{margin-inline-start:auto;color:#464646;font-size:14px;font-weight:900}.tooltip-marker{width:9px;height:9px;flex:0 0 auto;border-radius:50%}.widget-grid{position:absolute;inset:0;display:grid;gap:8px;padding:18px}.chart-placeholder{width:100%;height:100%}.element-content{display:flex;width:100%;height:100%;min-width:0;min-height:0}.element-content:has(widget-chart-element){align-items:stretch}.element-content>widget-chart-element{flex:0 1 auto;width:100%;height:100%;max-width:100%;max-height:100%}.element-content>widget-chart-element.is-progress{height:auto}.divider-element{width:100%;height:2px;flex:0 0 auto;border-radius:var(--widget-renderer-pill-radius)}.divider-element.is-vertical{width:2px;height:100%}.element-content.is-sensitive{filter:blur(var(--sensitive-blur, 2px));-webkit-user-select:none;user-select:none}.text-element{display:inline-block;overflow:visible;line-height:1.2}img{width:100%;height:100%;display:block}.image-overlay{position:absolute;inset:0;z-index:1;pointer-events:none;border-radius:inherit}.image-placeholder{display:flex;width:100%;height:100%;align-items:center;justify-content:center;overflow:hidden;background:#dfe5ee}.image-placeholder svg{width:min(56px,45%);height:auto;fill:none;stroke:#8c9ab0;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.action-button{min-height:30px;border-radius:var(--widget-renderer-radius);padding:6px 10px;font:600 12px/1.1 inherit;cursor:var(--widget-renderer-action-cursor, pointer)}.action-button.show-only-on-hover{opacity:0;pointer-events:none;transform:translateY(2px);transition:opacity var(--widget-renderer-transition-duration) var(--widget-renderer-transition-easing),transform var(--widget-renderer-transition-duration) var(--widget-renderer-transition-easing)}.widget-shell:hover .action-button.show-only-on-hover,.widget-shell:focus-within .action-button.show-only-on-hover{opacity:1;pointer-events:auto;transform:translateY(0)}.action-button.solid{border:1px solid #151515;background:#151515;color:#fff}.action-button.outline{border:1px solid #737373;background:#fff;color:#151515}\n"]
1601
+ }]
1602
+ }],
1603
+ ctorParameters: () => [],
1604
+ propDecorators: {
1605
+ widget: [{
1606
+ type: i0.Input,
1607
+ args: [{
1608
+ isSignal: true,
1609
+ alias: "widget",
1610
+ required: false
1611
+ }]
1612
+ }],
1613
+ loading: [{
1614
+ type: i0.Input,
1615
+ args: [{
1616
+ isSignal: true,
1617
+ alias: "loading",
1618
+ required: false
1619
+ }]
1620
+ }],
1621
+ darkMode: [{
1622
+ type: i0.Input,
1623
+ args: [{
1624
+ isSignal: true,
1625
+ alias: "darkMode",
1626
+ required: false
1627
+ }]
1628
+ }],
1629
+ locale: [{
1630
+ type: i0.Input,
1631
+ args: [{
1632
+ isSignal: true,
1633
+ alias: "locale",
1634
+ required: false
1635
+ }]
1636
+ }],
1637
+ validationRules: [{
1638
+ type: i0.Input,
1639
+ args: [{
1640
+ isSignal: true,
1641
+ alias: "validationRules",
1642
+ required: false
1643
+ }]
1644
+ }],
1645
+ refreshRequested: [{
1646
+ type: i0.Output,
1647
+ args: ["refreshRequested"]
1648
+ }],
1649
+ actionRequested: [{
1650
+ type: i0.Output,
1651
+ args: ["actionRequested"]
1652
+ }],
1653
+ tooltipLayer: [{
1654
+ type: i0.ViewChild,
1655
+ args: ["tooltipLayer", { isSignal: true }]
1656
+ }]
1657
+ }
1658
+ });
1659
+ const emptyWidget = {
1660
+ version: 2,
1661
+ id: "empty-widget",
1662
+ size: "square",
1663
+ rows: [{
1664
+ size: 1,
1665
+ unit: "star"
1666
+ }],
1667
+ columns: [{
1668
+ size: 1,
1669
+ unit: "star"
1670
+ }],
1671
+ background: {
1672
+ sensitive: false,
1673
+ repeat: false,
1674
+ size: "auto",
1675
+ anchor: "center"
1676
+ },
1677
+ refresh: {
1678
+ enabled: false,
1679
+ label: "Refresh widget"
1680
+ },
1681
+ elements: []
1682
+ };
1683
+ function widgetSizeOrSquare(value) {
1684
+ return [
1685
+ "mini",
1686
+ "compact",
1687
+ "tall",
1688
+ "square",
1689
+ "wide",
1690
+ "mega",
1691
+ "banner",
1692
+ "hero"
1693
+ ].includes(value) ? value : "square";
1694
+ }
1695
+ export { WIDGET_CELL_HEIGHT, WIDGET_CELL_WIDTH, WIDGET_FINGERPRINT_VERSION, WIDGET_GAP, WIDGET_HEIGHT, WIDGET_PADDING, WidgetRenderer, WidgetValidationError, chartAccessibilitySummary, chartAriaLabel, computeWidgetFingerprint, defaultWidgetRendererLocale, dutchWidgetRendererLocale, elementGridStyle, frenchWidgetRendererLocale, germanWidgetRendererLocale, gridSpanSize, gridTemplate, isWidget, isWidgetContract, normalizeWidgetInput, parseWidgetInput, safeParseWidgetInput, widgetFootprint, widgetHeight, widgetWidth };
1696
+
1697
+ //# sourceMappingURL=lieselthuriot-widget-renderer.mjs.map