@mintplayer/ng-spark 22.32.0 → 22.34.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.
- package/README.md +101 -1
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-account.mjs +18 -18
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs +16 -8
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-core.mjs +6 -6
- package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +24 -24
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-contributions.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-dashboards.mjs +726 -0
- package/fesm2022/mintplayer-ng-spark-dashboards.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +220 -49
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-icon.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs +6 -6
- package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-models.mjs +44 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +21 -21
- package/fesm2022/mintplayer-ng-spark-notifications.mjs +687 -0
- package/fesm2022/mintplayer-ng-spark-notifications.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-organizations-accept.mjs +179 -0
- package/fesm2022/mintplayer-ng-spark-organizations-accept.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-organizations.mjs +202 -0
- package/fesm2022/mintplayer-ng-spark-organizations.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +9 -1
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +125 -85
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +95 -29
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +84 -12
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-pwa.mjs +74 -6
- package/fesm2022/mintplayer-ng-spark-pwa.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +10 -109
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-score-renderers.mjs +801 -0
- package/fesm2022/mintplayer-ng-spark-score-renderers.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-services.mjs +424 -72
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-share-page.mjs +334 -0
- package/fesm2022/mintplayer-ng-spark-share-page.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-share.mjs +10 -0
- package/fesm2022/mintplayer-ng-spark-share.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-shell.mjs +38 -36
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +9 -9
- package/package.json +29 -1
- package/types/mintplayer-ng-spark-dashboards.d.ts +226 -0
- package/types/mintplayer-ng-spark-grid.d.ts +77 -26
- package/types/mintplayer-ng-spark-models.d.ts +150 -17
- package/types/mintplayer-ng-spark-notifications.d.ts +188 -0
- package/types/mintplayer-ng-spark-organizations-accept.d.ts +40 -0
- package/types/mintplayer-ng-spark-organizations.d.ts +72 -0
- package/types/mintplayer-ng-spark-panels.d.ts +16 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +10 -0
- package/types/mintplayer-ng-spark-po-detail.d.ts +29 -0
- package/types/mintplayer-ng-spark-po-edit.d.ts +37 -0
- package/types/mintplayer-ng-spark-pwa.d.ts +48 -2
- package/types/mintplayer-ng-spark-query-list.d.ts +8 -23
- package/types/mintplayer-ng-spark-score-renderers.d.ts +340 -0
- package/types/mintplayer-ng-spark-services.d.ts +146 -6
- package/types/mintplayer-ng-spark-share-page.d.ts +67 -0
- package/types/mintplayer-ng-spark-share.d.ts +26 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-dashboards.mjs","names":[],"sources":["../../dashboards/src/dashboard-format.ts","../../dashboards/src/spark-stat.component.ts","../../dashboards/src/spark-meter.component.ts","../../dashboards/src/spark-dashboard-table.component.ts","../../dashboards/src/spark-dashboard.component.ts","../../dashboards/src/provide-spark-dashboards.ts"],"sourcesContent":["import { formatNumber } from '@angular/common';\n\n/** How a dashboard value is written: a plain number, bytes (binary units), a percentage, a date, or as is. */\nexport type SparkDashboardFormat = 'number' | 'bytes' | 'percent' | 'date' | 'datetime' | 'text';\n\n/** A finite number from a wire value (a number or a numeric string), else null. */\nexport function toSparkNumber(value: unknown): number | null {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value === 'string' && value.trim() !== '') {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : null;\n }\n return null;\n}\n\n/** 1536 → \"1.5 KB\": binary units, one decimal from KB up; \"—\" for no value. */\nexport function formatSparkBytes(bytes: number | null | undefined, locale = 'en'): string {\n if (bytes == null || !Number.isFinite(bytes)) return '—';\n const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n let value = bytes;\n let unit = 0;\n while (Math.abs(value) >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit++;\n }\n return unit === 0 ? `${formatNumber(value, locale, '1.0-0')} B` : `${formatNumber(value, locale, '1.1-1')} ${units[unit]}`;\n}\n\n/**\n * A value as a dashboard writes it: \"—\" for none; numbers by `format` (`decimals` places for `number`/`percent`,\n * default 0); dates in the viewer's locale; anything else as text.\n */\nexport function formatSparkDashboardValue(value: unknown, format: SparkDashboardFormat | undefined, locale = 'en', decimals?: number): string {\n if (value === null || value === undefined || value === '') return '—';\n switch (format) {\n case 'bytes':\n return formatSparkBytes(toSparkNumber(value), locale);\n case 'percent': {\n const n = toSparkNumber(value);\n const d = decimals ?? 1;\n return n === null ? '—' : `${formatNumber(n, locale, `1.${d}-${d}`)}%`;\n }\n case 'date':\n case 'datetime': {\n const date = new Date(String(value));\n if (Number.isNaN(date.getTime())) return String(value);\n return format === 'date' ? date.toLocaleDateString(locale) : date.toLocaleString(locale);\n }\n case 'text':\n return String(value);\n case 'number':\n default: {\n const n = typeof value === 'boolean' ? null : toSparkNumber(value);\n if (n === null) return String(value);\n const d = decimals ?? 0;\n return formatNumber(n, locale, `1.${d}-${d}`);\n }\n }\n}\n\n/** The colour a threshold gives a value: `danger` at or past `danger`, `warning` at or past `warning`, else none. */\nexport function sparkThresholdColor(\n value: number | null,\n thresholds: { warning?: number; danger?: number; direction?: 'above' | 'below' },\n): 'warning' | 'danger' | null {\n if (value === null) return null;\n const past = (limit: number | undefined) =>\n typeof limit === 'number' && (thresholds.direction === 'below' ? value <= limit : value >= limit);\n if (past(thresholds.danger)) return 'danger';\n if (past(thresholds.warning)) return 'warning';\n return null;\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, LOCALE_ID } from '@angular/core';\nimport type { SparkAttributeColumnRenderer, SparkAttributeDetailRenderer } from '@mintplayer/ng-spark/renderers';\nimport { formatSparkDashboardValue, SparkDashboardFormat, sparkThresholdColor, toSparkNumber } from './dashboard-format';\n\n/** `rendererOptions` of the `spark-stat` renderer. Every member is optional. */\nexport interface SparkStatOptions {\n /** How the value is written. Default `'number'`. */\n format?: SparkDashboardFormat;\n /** Decimals for `number` (default 0) and `percent` (default 1). */\n decimals?: number;\n /** Text after the value, e.g. `' sites'`. Default none. */\n suffix?: string;\n /** The value turns amber at or past this. */\n warning?: number;\n /** The value turns red at or past this. */\n danger?: number;\n /** `'above'` (default): high is bad, as for disk use. `'below'`: low is bad, as for free space. */\n direction?: 'above' | 'below';\n}\n\n/**\n * The `spark-stat` renderer: one figure, large on a detail page (a dashboard tile) and plain in a grid cell,\n * coloured amber or red once it passes the model's `warning` / `danger` threshold. No value draws a muted dash.\n */\n@Component({\n selector: 'spark-stat',\n template: `\n <span class=\"spark-stat\" [class.text-warning-emphasis]=\"color() === 'warning'\" [class.text-danger]=\"color() === 'danger'\"\n [class.text-body-secondary]=\"text() === '—'\" [attr.data-threshold]=\"color()\">{{ text() }}</span>\n `,\n styles: [`\n :host { display: inline-block; }\n .spark-stat { font-size: var(--spark-stat-font-size, 1.75rem); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkStatComponent implements SparkAttributeColumnRenderer, SparkAttributeDetailRenderer {\n private readonly locale = inject(LOCALE_ID);\n\n readonly value = input<any>();\n readonly options = input<Record<string, any> | undefined>();\n\n private readonly settings = computed(() => (this.options() ?? {}) as SparkStatOptions);\n\n protected readonly text = computed(() => {\n const s = this.settings();\n const text = formatSparkDashboardValue(this.value(), s.format, this.locale, typeof s.decimals === 'number' ? s.decimals : undefined);\n return text === '—' || typeof s.suffix !== 'string' ? text : text + s.suffix;\n });\n\n protected readonly color = computed(() => sparkThresholdColor(toSparkNumber(this.value()), this.settings()));\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, LOCALE_ID } from '@angular/core';\nimport { formatNumber } from '@angular/common';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsProgressBarComponent, BsProgressComponent } from '@mintplayer/ng-bootstrap/progress-bar';\nimport type { SparkAttributeColumnRenderer, SparkAttributeDetailRenderer } from '@mintplayer/ng-spark/renderers';\nimport { formatSparkDashboardValue, SparkDashboardFormat, sparkThresholdColor, toSparkNumber } from './dashboard-format';\n\n/** `rendererOptions` of the `spark-meter` renderer. Every member is optional. */\nexport interface SparkMeterOptions {\n /** The ceiling when the value is a plain number (a value `{ value, max }` brings its own). Default 100. */\n max?: number;\n /** How the value and the ceiling are written. Default `'number'`. */\n format?: SparkDashboardFormat;\n /** Amber from this share of the ceiling, in percent. Default 75. */\n warning?: number;\n /** Red from this share of the ceiling, in percent. Default 90. */\n danger?: number;\n /** The meter's accessible name. Default `'Usage'`. */\n label?: string;\n}\n\ninterface MeterView {\n value: number;\n max: number;\n /** The share of the ceiling, in percent (0–100), one decimal. */\n share: number;\n color: Color;\n text: string;\n}\n\n/**\n * The `spark-meter` renderer: how much of something is used, as a bar coloured by its share (green, amber from 75 %,\n * red from 90 % by default) with \"used of total (share)\" next to it. The value is a number against the `max` option, or\n * `{ value, max }` from the server (the dashboards package's `DashboardValues.Meter`), e.g. disk bytes used of the total.\n * No value, or no ceiling, draws a muted dash.\n */\n@Component({\n selector: 'spark-meter',\n imports: [BsProgressComponent, BsProgressBarComponent],\n template: `\n @if (view(); as v) {\n <div class=\"d-flex flex-column gap-1 spark-meter\">\n <bs-progress [style.height]=\"'.75rem'\">\n <bs-progress-bar [value]=\"v.share\" [minimum]=\"0\" [maximum]=\"100\" [color]=\"v.color\"\n [ariaLabel]=\"label()\" [valueText]=\"v.text\" />\n </bs-progress>\n <span class=\"small text-nowrap\" data-meter-text>{{ v.text }}</span>\n </div>\n } @else {\n <span class=\"text-muted small\">—</span>\n }\n `,\n styles: [`:host { display: block; min-width: 8rem; }`],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkMeterComponent implements SparkAttributeColumnRenderer, SparkAttributeDetailRenderer {\n private readonly locale = inject(LOCALE_ID);\n\n readonly value = input<any>();\n readonly options = input<Record<string, any> | undefined>();\n\n private readonly settings = computed(() => (this.options() ?? {}) as SparkMeterOptions);\n protected readonly label = computed(() => (typeof this.settings().label === 'string' ? this.settings().label! : 'Usage'));\n\n protected readonly view = computed<MeterView | null>(() => {\n const raw = this.value();\n const s = this.settings();\n const isPair = raw !== null && typeof raw === 'object' && 'value' in raw;\n const value = toSparkNumber(isPair ? raw.value : raw);\n const max = toSparkNumber(isPair ? raw.max : undefined) ?? toSparkNumber(s.max) ?? (isPair ? null : 100);\n if (value === null || max === null || max <= 0) return null;\n\n const share = Math.round(Math.min(100, Math.max(0, (value / max) * 100)) * 10) / 10;\n const threshold = sparkThresholdColor(share, {\n warning: typeof s.warning === 'number' ? s.warning : 75,\n danger: typeof s.danger === 'number' ? s.danger : 90,\n });\n const format = s.format ?? 'number';\n return {\n value,\n max,\n share,\n color: threshold === 'danger' ? Color.danger : threshold === 'warning' ? Color.warning : Color.success,\n text: `${formatSparkDashboardValue(value, format, this.locale)} / ${formatSparkDashboardValue(max, format, this.locale)} (${formatNumber(share, this.locale, '1.0-1')}%)`,\n };\n });\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, LOCALE_ID } from '@angular/core';\nimport { BsTableComponent } from '@mintplayer/ng-bootstrap/table';\nimport { SparkIconComponent } from '@mintplayer/ng-spark/icon';\nimport type { SparkAttributeDetailRenderer } from '@mintplayer/ng-spark/renderers';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { formatSparkDashboardValue, SparkDashboardFormat } from './dashboard-format';\n\n/** One column of a `spark-dashboard-table`. */\nexport interface SparkDashboardTableColumn {\n /** The row field. For a value that is a dictionary, its rows are `{ key, value }`. */\n key: string;\n /** A translation key for the header (`translations.json`), shown as is when it has no translation. Default `key`. */\n label?: string;\n /** How the cells are written. Numbers and bytes are right-aligned. Default: as is. */\n format?: SparkDashboardFormat | 'boolean';\n /** Translate each cell as `{translate}{value}` (e.g. `'seoUi.runStatus.'`), falling back to the value. */\n translate?: string;\n}\n\n/** `rendererOptions` of the `spark-dashboard-table` renderer. */\nexport interface SparkDashboardTableOptions {\n /** The columns, in order. Default: the first row's fields. */\n columns?: SparkDashboardTableColumn[];\n /** A translation key shown when there are no rows. Default `'dashboards.empty'`. */\n empty?: string;\n}\n\ninterface TableCell {\n text: string;\n check: boolean;\n}\n\n/**\n * The `spark-dashboard-table` renderer (detail pages): a dashboard value that is a list of rows, such as the\n * RavenDB statistics' collections (D12: tables are JSON attributes). A dictionary (`{ \"Completed\": 3 }`) reads as\n * rows `{ key, value }`.\n */\n@Component({\n selector: 'spark-dashboard-table',\n imports: [BsTableComponent, SparkIconComponent],\n template: `\n @if (rows().length > 0) {\n <bs-table [isResponsive]=\"true\" class=\"d-block mb-0\">\n <thead>\n <tr>\n @for (column of columns(); track column.key) {\n <th [class.text-end]=\"isNumeric(column)\">{{ header(column) }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of cells(); track $index) {\n <tr>\n @for (cell of row; track $index; let i = $index) {\n <td [class.text-end]=\"isNumeric(columns()[i])\" [class.text-break]=\"!isNumeric(columns()[i])\">\n @if (cell.check) { <spark-icon name=\"check-lg\" class=\"text-success\" aria-hidden=\"true\" /><span class=\"visually-hidden\">{{ cell.text }}</span> } @else { {{ cell.text }} }\n </td>\n }\n </tr>\n }\n </tbody>\n </bs-table>\n } @else {\n <span class=\"text-body-secondary small\" data-empty>{{ lang.t(settings().empty ?? 'dashboards.empty', '—') }}</span>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkDashboardTableComponent implements SparkAttributeDetailRenderer {\n private readonly locale = inject(LOCALE_ID);\n protected readonly lang = inject(SparkLanguageService);\n\n readonly value = input<any>();\n readonly options = input<Record<string, any> | undefined>();\n\n protected readonly settings = computed(() => (this.options() ?? {}) as SparkDashboardTableOptions);\n\n protected readonly rows = computed<Record<string, unknown>[]>(() => toSparkTableRows(this.value()));\n\n protected readonly columns = computed<SparkDashboardTableColumn[]>(() => {\n const declared = this.settings().columns;\n if (Array.isArray(declared) && declared.length > 0) return declared.filter(c => typeof c?.key === 'string');\n const first = this.rows()[0];\n return first ? Object.keys(first).map(key => ({ key })) : [];\n });\n\n protected readonly cells = computed<TableCell[][]>(() => {\n const columns = this.columns();\n return this.rows().map(row => columns.map(column => this.cell(row[column.key], column)));\n });\n\n protected header(column: SparkDashboardTableColumn): string {\n return column.label ? this.lang.t(column.label, column.label) : column.key;\n }\n\n protected isNumeric(column: SparkDashboardTableColumn | undefined): boolean {\n return column?.format === 'number' || column?.format === 'bytes' || column?.format === 'percent';\n }\n\n private cell(value: unknown, column: SparkDashboardTableColumn): TableCell {\n if (column.format === 'boolean')\n return { text: value === true ? this.lang.t('dashboards.yes', 'yes') : '', check: value === true };\n if (column.translate && value !== null && value !== undefined && value !== '')\n return { text: this.lang.t(column.translate + String(value), String(value)), check: false };\n return { text: formatSparkDashboardValue(value, column.format, this.locale), check: false };\n }\n}\n\n/** The rows of a table value: a list of objects as is, a dictionary as `{ key, value }` rows, anything else none. */\nexport function toSparkTableRows(value: unknown): Record<string, unknown>[] {\n if (Array.isArray(value)) return value.filter((r): r is Record<string, unknown> => r !== null && typeof r === 'object' && !Array.isArray(r));\n if (value !== null && typeof value === 'object') return Object.entries(value).map(([key, v]) => ({ key, value: v }));\n if (typeof value === 'string' && value.trim().startsWith('[')) {\n try {\n return toSparkTableRows(JSON.parse(value));\n } catch {\n return [];\n }\n }\n return [];\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, LOCALE_ID, Type } from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { BsCardBodyComponent, BsCardComponent } from '@mintplayer/ng-bootstrap/card';\nimport { EntityAttributeDefinition, hasShowedOnFlag, PersistentObject, ShowedOn, TranslatedString } from '@mintplayer/ng-spark/models';\nimport type { SparkDetailContext } from '@mintplayer/ng-spark/panels';\nimport { ResolveTranslationPipe, TranslateKeyPipe } from '@mintplayer/ng-spark/pipes';\nimport { rendererValue, SPARK_ATTRIBUTE_RENDERERS, withDeclaredInputs } from '@mintplayer/ng-spark/renderers';\nimport { formatSparkDashboardValue } from './dashboard-format';\n\n/** The `metadata` key a dashboard carries (the dashboards package's `SparkDashboardActions.MetadataKey`). */\nexport const SPARK_DASHBOARD_METADATA_KEY = 'dashboard';\n\n/** Whether `item` is a dashboard: the server marks one with `metadata.dashboard`. */\nexport function isSparkDashboard(item: PersistentObject | null | undefined): boolean {\n const marker = item?.metadata?.[SPARK_DASHBOARD_METADATA_KEY];\n return marker !== null && typeof marker === 'object';\n}\n\ninterface DashboardTile {\n attribute: EntityAttributeDefinition;\n /** Columns spanned: 1, 2, or the whole row. */\n span: 1 | 2 | 'row';\n component: Type<any> | null;\n inputs: Record<string, any>;\n /** The value as text, for an attribute without a detail renderer. */\n text: string;\n}\n\ninterface DashboardSection {\n id: string;\n name: string | null;\n label?: TranslatedString;\n tiles: DashboardTile[];\n}\n\n/**\n * The dashboard tile layout (D12): replaces a dashboard's attribute cards on the routed detail page\n * (`SPARK_DETAIL_LAYOUTS`, registered by `provideSparkDashboards()`). Each group of the model is a section, each\n * attribute a tile: its label above its detail renderer (`spark-stat`, `spark-meter`, `spark-trend`,\n * `spark-dashboard-table`, …) or its plain value. `columnSpan` 2 takes two columns, 3 and more (and a table without one) the\n * whole row. An attribute the caller may not read is not on the object and has no tile. The page follows the object\n * over `/spark/live` like any live type, so the tiles change in place.\n */\n@Component({\n selector: 'spark-dashboard',\n imports: [NgComponentOutlet, BsCardComponent, BsCardBodyComponent, ResolveTranslationPipe, TranslateKeyPipe],\n template: `\n <div class=\"spark-dashboard mx-3 my-2\">\n @for (section of sections(); track section.id) {\n <section class=\"mb-3\" [attr.data-section]=\"section.name\">\n @if (section.name) {\n <h3 class=\"h6 text-body-secondary mb-2\">{{ section.label | resolveTranslation:section.name }}</h3>\n }\n <div class=\"spark-dashboard-tiles\">\n @for (tile of section.tiles; track tile.attribute.id) {\n <bs-card class=\"d-block h-100\" [class.spark-dashboard-span-2]=\"tile.span === 2\"\n [class.spark-dashboard-span-row]=\"tile.span === 'row'\" [attr.data-tile]=\"tile.attribute.name\">\n <bs-card-body>\n <div class=\"small text-body-secondary mb-1\">{{ tile.attribute.label | resolveTranslation:tile.attribute.name }}</div>\n @if (tile.component) {\n <ng-container *ngComponentOutlet=\"tile.component; inputs: tile.inputs\" />\n } @else {\n <div class=\"fs-4 fw-semibold text-break\">{{ tile.text }}</div>\n }\n </bs-card-body>\n </bs-card>\n }\n </div>\n </section>\n }\n @if (generatedAt(); as at) {\n <p class=\"small text-body-secondary mb-0\" data-generated>{{ 'dashboards.updated' | t }} {{ at }}</p>\n }\n </div>\n `,\n styles: [`\n .spark-dashboard-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(12rem, 100%), 1fr)); gap: .75rem; }\n .spark-dashboard-tiles > * { min-width: 0; }\n .spark-dashboard-span-row { grid-column: 1 / -1; }\n /* Two columns only where two fit: on a phone the grid has one, and span 2 would widen the page. */\n @media (min-width: 576px) { .spark-dashboard-span-2 { grid-column: span 2; } }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkDashboardComponent {\n private readonly locale = inject(LOCALE_ID);\n private readonly renderers = inject(SPARK_ATTRIBUTE_RENDERERS);\n\n readonly context = input.required<SparkDetailContext>();\n\n protected readonly sections = computed<DashboardSection[]>(() => {\n const { item, entityType } = this.context();\n const loaded = new Map(item.attributes.map(a => [a.name, a] as const));\n const formData: Record<string, any> = {};\n for (const a of item.attributes) formData[a.name] = rendererValue(a);\n\n const tiles = (entityType.attributes ?? [])\n .filter(a => loaded.has(a.name) && hasShowedOnFlag(loaded.get(a.name)?.showedOn ?? a.showedOn, ShowedOn.PersistentObject))\n .sort((a, b) => a.order - b.order)\n .map(attribute => this.tile(attribute, item, formData));\n\n const groups = [...(entityType.groups ?? [])].sort((a, b) => a.order - b.order);\n const groupIds = new Set(groups.map(g => g.id));\n const sections: DashboardSection[] = [];\n const ungrouped = tiles.filter(t => !t.attribute.group || !groupIds.has(t.attribute.group));\n if (ungrouped.length > 0) sections.push({ id: '__ungrouped__', name: null, tiles: ungrouped });\n for (const group of groups) {\n const grouped = tiles.filter(t => t.attribute.group === group.id);\n if (grouped.length > 0) sections.push({ id: group.id, name: group.name, label: group.label, tiles: grouped });\n }\n return sections;\n });\n\n /** When the server read the values, in the viewer's locale. */\n protected readonly generatedAt = computed(() => {\n const marker = this.context().item.metadata?.[SPARK_DASHBOARD_METADATA_KEY];\n const at = marker && typeof marker === 'object' ? (marker as Record<string, unknown>)['generatedAtUtc'] : null;\n if (typeof at !== 'string') return null;\n const date = new Date(at);\n return Number.isNaN(date.getTime()) ? null : date.toLocaleTimeString(this.locale);\n });\n\n private tile(attribute: EntityAttributeDefinition, item: PersistentObject, formData: Record<string, any>): DashboardTile {\n const value = rendererValue(item.attributes.find(a => a.name === attribute.name));\n const registration = attribute.renderer ? this.renderers.find(r => r.name === attribute.renderer) : undefined;\n const component = registration?.detailComponent ?? null;\n // A table without a columnSpan takes the row; a columnSpan of 3 or more is the row, 2 is two columns.\n const columnSpan = attribute.columnSpan ?? (attribute.renderer === 'spark-dashboard-table' ? 3 : 1);\n const span = columnSpan >= 3 ? 'row' : columnSpan === 2 ? 2 : 1;\n return {\n attribute,\n span,\n component,\n inputs: component\n ? withDeclaredInputs(component, { value, attribute, options: attribute.rendererOptions, formData, item })\n : {},\n text: formatSparkDashboardValue(value, undefined, this.locale),\n };\n }\n}\n","import { Provider } from '@angular/core';\nimport { provideSparkDetailLayouts } from '@mintplayer/ng-spark/panels';\nimport type { SparkAttributeRendererRegistration } from '@mintplayer/ng-spark/renderers';\nimport { isSparkDashboard, SparkDashboardComponent } from './spark-dashboard.component';\nimport { SparkDashboardTableComponent } from './spark-dashboard-table.component';\nimport { SparkMeterComponent } from './spark-meter.component';\nimport { SparkStatComponent } from './spark-stat.component';\n\n/**\n * The dashboard renderers under their model names. Renderers are one list, so add these to the app's own in its\n * single `provideSparkAttributeRenderers` (or `provideSparkScoreRenderers`, which `spark-trend` comes from) call:\n *\n * @example\n * provideSparkScoreRenderers([...appRenderers, ...sparkDashboardRenderers]),\n * provideSparkDashboards(),\n */\nexport const sparkDashboardRenderers: readonly SparkAttributeRendererRegistration[] = [\n { name: 'spark-stat', columnComponent: SparkStatComponent, detailComponent: SparkStatComponent },\n { name: 'spark-meter', columnComponent: SparkMeterComponent, detailComponent: SparkMeterComponent },\n { name: 'spark-dashboard-table', detailComponent: SparkDashboardTableComponent },\n];\n\n/**\n * Draws every dashboard (an object the server marks with `metadata.dashboard`, the dashboards package's live virtual\n * types) with the tile layout instead of the attribute cards, on the routed detail page. The renderers are registered\n * separately: see {@link sparkDashboardRenderers}.\n */\nexport function provideSparkDashboards(): Provider[] {\n return provideSparkDetailLayouts({\n id: 'spark-dashboard',\n component: SparkDashboardComponent,\n matches: item => isSparkDashboard(item),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAMA,SAAgB,cAAc,OAAc;CAC1C,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;CACvE,IAAI,OAAO,UAAU,YAAY,MAAM,KAAI,MAAO,IAAI;EACpD,MAAM,SAAS,OAAO,KAAK;EAC3B,OAAO,OAAO,SAAS,MAAM,IAAI,SAAS;CAC5C;CACA,OAAO;AACT;AAGA,SAAgB,iBAAiB,OAAkC,SAAS,MAAI;CAC9E,IAAI,SAAS,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO;CACrD,MAAM,QAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;EAAM;CAAI;CAChD,IAAI,QAAQ;CACZ,IAAI,OAAO;CACX,OAAO,KAAK,IAAI,KAAK,KAAK,QAAQ,OAAO,MAAM,SAAS,GAAG;EACzD,SAAS;EACT;CACF;CACA,OAAO,SAAS,IAAI,GAAG,aAAa,OAAO,QAAQ,OAAO,EAAC,MAAO,GAAG,aAAa,OAAO,QAAQ,OAAO,EAAC,GAAI,MAAM;AACrH;AAMA,SAAgB,0BAA0B,OAAgB,QAA0C,SAAS,MAAM,UAAiB;CAClI,IAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,IAAI,OAAO;CAClE,QAAQ,QAAR;EACE,KAAK,SACH,OAAO,iBAAiB,cAAc,KAAK,GAAG,MAAM;EACtD,KAAK,WAAW;GACd,MAAM,IAAI,cAAc,KAAK;GAC7B,MAAM,IAAI,YAAY;GACtB,OAAO,MAAM,OAAO,MAAM,GAAG,aAAa,GAAG,QAAQ,KAAK,EAAC,GAAI,GAAG,EAAC;EACrE;EACA,KAAK;EACL,KAAK,YAAY;GACf,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,CAAC;GACnC,IAAI,OAAO,MAAM,KAAK,QAAO,CAAE,GAAG,OAAO,OAAO,KAAK;GACrD,OAAO,WAAW,SAAS,KAAK,mBAAmB,MAAM,IAAI,KAAK,eAAe,MAAM;EACzF;EACA,KAAK,QACH,OAAO,OAAO,KAAK;EAErB,SAAS;GACP,MAAM,IAAI,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK;GACjE,IAAI,MAAM,MAAM,OAAO,OAAO,KAAK;GACnC,MAAM,IAAI,YAAY;GACtB,OAAO,aAAa,GAAG,QAAQ,KAAK,EAAC,GAAI,GAAG;EAC9C;CACF;AACF;AAGA,SAAgB,oBACd,OACA,YAAgF;CAEhF,IAAI,UAAU,MAAM,OAAO;CAC3B,MAAM,QAAQ,UACZ,OAAO,UAAU,aAAa,WAAW,cAAc,UAAU,SAAS,QAAQ,SAAS;CAC7F,IAAI,KAAK,WAAW,MAAM,GAAG,OAAO;CACpC,IAAI,KAAK,WAAW,OAAO,GAAG,OAAO;CACrC,OAAO;AACT;ACnCA,IAAa,qBAAb,MAAa,mBAAkB;CACZ,SAAS,OAAO,SAAS;CAEjC,QAAQ,MAAY,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACpB,UAAU,MAAwC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAE1C,WAAW,eAAgB,KAAK,QAAO,KAAM,CAAA,GAAwB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAEnE,OAAO,eAAc;EACtC,MAAM,IAAI,KAAK,SAAQ;EACvB,MAAM,OAAO,0BAA0B,KAAK,MAAK,GAAI,EAAE,QAAQ,KAAK,QAAQ,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW,MAAS;EACnI,OAAO,SAAS,OAAO,OAAO,EAAE,WAAW,WAAW,OAAO,OAAO,EAAE;CACxE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,QAAQ,eAAe,oBAAoB,cAAc,KAAK,MAAK,CAAE,GAAG,KAAK,SAAQ,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAdjG,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAkB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAlB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAkB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UAVnB;;;;EAGT,UAAA;EAAA,QAAA,CAAA,4JAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAOU,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkB,YAAA,CAAA;EAZ9B,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAY,UACZ;;;;GAGT,iBAKgB,wBAAwB;GAAM,QAAA,CAAA,4JAAA;EAAA,CAAA;;;;;;;;;;;;;;;;;;;;;ACqBjD,IAAa,sBAAb,MAAa,oBAAmB;CACb,SAAS,OAAO,SAAS;CAEjC,QAAQ,MAAY,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACpB,UAAU,MAAwC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAE1C,WAAW,eAAgB,KAAK,QAAO,KAAM,CAAA,GAAyB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACpE,QAAQ,eAAgB,OAAO,KAAK,SAAQ,CAAE,CAAC,UAAU,WAAW,KAAK,SAAQ,CAAE,CAAC,QAAS,SAAS,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEtG,OAAO,eAAgC;EACxD,MAAM,MAAM,KAAK,MAAK;EACtB,MAAM,IAAI,KAAK,SAAQ;EACvB,MAAM,SAAS,QAAQ,QAAQ,OAAO,QAAQ,YAAY,WAAW;EACrE,MAAM,QAAQ,cAAc,SAAS,IAAI,QAAQ,GAAG;EACpD,MAAM,MAAM,cAAc,SAAS,IAAI,MAAM,MAAS,KAAK,cAAc,EAAE,GAAG,MAAM,SAAS,OAAO;EACpG,IAAI,UAAU,QAAQ,QAAQ,QAAQ,OAAO,GAAG,OAAO;EAEvD,MAAM,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAI,QAAQ,MAAO,GAAG,CAAC,IAAI,EAAE,IAAI;EACjF,MAAM,YAAY,oBAAoB,OAAO;GAC3C,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;GACrD,QAAQ,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;EACnD,CAAA;EACD,MAAM,SAAS,EAAE,UAAU;EAC3B,OAAO;GACL;GACA;GACA;GACA,OAAO,cAAc,WAAW,MAAM,SAAS,cAAc,YAAY,MAAM,UAAU,MAAM;GAC/F,MAAM,GAAG,0BAA0B,OAAO,QAAQ,KAAK,MAAM,EAAC,KAAM,0BAA0B,KAAK,QAAQ,KAAK,MAAM,EAAC,IAAK,aAAa,OAAO,KAAK,QAAQ,OAAO,EAAC;EACtK;CACH,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CA9BS,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAmB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAnB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAmB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UAhBpB;;;;;;;;;;;;;EAYT,UAAA;EAAA,QAAA,CAAA,uCAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAbS;GAAmB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAsB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAiB1C,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmB,YAAA,CAAA;EAnB/B,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAa,SACd,CAAC,qBAAqB,sBAAsB;GAAC,UAC5C;;;;;;;;;;;;;GAYT,iBAEgB,wBAAwB;GAAM,QAAA,CAAA,uCAAA;EAAA,CAAA;;;;;;;;;;;;;;;;;;;;;ACejD,IAAa,+BAAb,MAAa,6BAA4B;CACtB,SAAS,OAAO,SAAS;CACvB,OAAO,OAAO,oBAAoB;CAE5C,QAAQ,MAAY,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACpB,UAAU,MAAwC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAExC,WAAW,eAAgB,KAAK,QAAO,KAAM,CAAA,GAAkC,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAE/E,OAAO,eAA0C,iBAAiB,KAAK,MAAK,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEhF,UAAU,eAA2C;EACtE,MAAM,WAAW,KAAK,SAAQ,CAAE,CAAC;EACjC,IAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG,OAAO,SAAS,QAAO,MAAK,OAAO,GAAG,QAAQ,QAAQ;EAC1G,MAAM,QAAQ,KAAK,KAAI,CAAE,CAAC;EAC1B,OAAO,QAAQ,OAAO,KAAK,KAAK,CAAC,CAAC,KAAI,SAAQ,EAAE,IAAG,EAAG,IAAI,CAAA;CAC5D,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,QAAQ,eAA6B;EACtD,MAAM,UAAU,KAAK,QAAO;EAC5B,OAAO,KAAK,KAAI,CAAE,CAAC,KAAI,QAAO,QAAQ,KAAI,WAAU,KAAK,KAAK,IAAI,OAAO,MAAM,MAAM,CAAC,CAAC;CACzF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,OAAO,QAAiC;EAChD,OAAO,OAAO,QAAQ,KAAK,KAAK,EAAE,OAAO,OAAO,OAAO,KAAK,IAAI,OAAO;CACzE;CAEU,UAAU,QAA6C;EAC/D,OAAO,QAAQ,WAAW,YAAY,QAAQ,WAAW,WAAW,QAAQ,WAAW;CACzF;CAEQ,KAAK,OAAgB,QAAiC;EAC5D,IAAI,OAAO,WAAW,WACpB,OAAO;GAAE,MAAM,UAAU,OAAO,KAAK,KAAK,EAAE,kBAAkB,KAAK,IAAI;GAAI,OAAO,UAAU;EAAI;EAClG,IAAI,OAAO,aAAa,UAAU,QAAQ,UAAU,UAAa,UAAU,IACzE,OAAO;GAAE,MAAM,KAAK,KAAK,EAAE,OAAO,YAAY,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC;GAAG,OAAO;EAAK;EAC3F,OAAO;GAAE,MAAM,0BAA0B,OAAO,OAAO,QAAQ,KAAK,MAAM;GAAG,OAAO;EAAK;CAC3F;CArCW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA4B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA5B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA4B,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UA5B7B;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBT,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MA1BS;GAAgB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAkB,UAAA;GAAA,QAAA,CAAA,MAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA6BnC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA4B,YAAA,CAAA;EA/BxC,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,kBAAkB,kBAAkB;GAC9C,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BV,iBAAiB,wBAAwB;EAC1C,CAAA;;;;;;;;;;;;;;;;;;;;;AA0CD,SAAgB,iBAAiB,OAAc;CAC7C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,QAAQ,MAAoC,MAAM,QAAQ,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC,CAAC;CAC3I,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,QAAQ;EAAE;EAAK,OAAO;CAAC,EAAG;CACnH,IAAI,OAAO,UAAU,YAAY,MAAM,KAAI,CAAE,CAAC,WAAW,GAAG,GAC1D,IAAI;EACF,OAAO,iBAAiB,KAAK,MAAM,KAAK,CAAC;CAC3C,QAAQ;EACN,OAAO,CAAA;CACT;CAEF,OAAO,CAAA;AACT;AC9GA,MAAa,+BAA+B;AAG5C,SAAgB,iBAAiB,MAAyC;CACxE,MAAM,SAAS,MAAM,WAAW;CAChC,OAAO,WAAW,QAAQ,OAAO,WAAW;AAC9C;AAoEA,IAAa,0BAAb,MAAa,wBAAuB;CACjB,SAAS,OAAO,SAAS;CACzB,YAAY,OAAO,yBAAyB;CAEpD,UAAU,MAAM,SAA8B,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEpC,WAAW,eAAkC;EAC9D,MAAM,EAAE,MAAM,eAAe,KAAK,QAAO;EACzC,MAAM,SAAS,IAAI,IAAI,KAAK,WAAW,KAAI,MAAK,CAAC,EAAE,MAAM,CAAC,CAAU,CAAC;EACrE,MAAM,WAAgC,CAAA;EACtC,KAAK,MAAM,KAAK,KAAK,YAAY,SAAS,EAAE,QAAQ,cAAc,CAAC;EAEnE,MAAM,SAAS,WAAW,cAAc,CAAA,EAAA,CACrC,QAAO,MAAK,OAAO,IAAI,EAAE,IAAI,KAAK,gBAAgB,OAAO,IAAI,EAAE,IAAI,CAAC,EAAE,YAAY,EAAE,UAAU,SAAS,gBAAgB,CAAC,CAAC,CACzH,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CACjC,KAAI,cAAa,KAAK,KAAK,WAAW,MAAM,QAAQ,CAAC;EAExD,MAAM,SAAS,CAAC,GAAI,WAAW,UAAU,CAAA,CAAG,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;EAC9E,MAAM,WAAW,IAAI,IAAI,OAAO,KAAI,MAAK,EAAE,EAAE,CAAC;EAC9C,MAAM,WAA+B,CAAA;EACrC,MAAM,YAAY,MAAM,QAAO,MAAK,CAAC,EAAE,UAAU,SAAS,CAAC,SAAS,IAAI,EAAE,UAAU,KAAK,CAAC;EAC1F,IAAI,UAAU,SAAS,GAAG,SAAS,KAAK;GAAE,IAAI;GAAiB,MAAM;GAAM,OAAO;EAAS,CAAE;EAC7F,KAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,UAAU,MAAM,QAAO,MAAK,EAAE,UAAU,UAAU,MAAM,EAAE;GAChE,IAAI,QAAQ,SAAS,GAAG,SAAS,KAAK;IAAE,IAAI,MAAM;IAAI,MAAM,MAAM;IAAM,OAAO,MAAM;IAAO,OAAO;GAAO,CAAE;EAC9G;EACA,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAGiB,cAAc,eAAc;EAC7C,MAAM,SAAS,KAAK,QAAO,CAAE,CAAC,KAAK,WAAW;EAC9C,MAAM,KAAK,UAAU,OAAO,WAAW,WAAY,OAAmC,oBAAoB;EAC1G,IAAI,OAAO,OAAO,UAAU,OAAO;EACnC,MAAM,OAAO,IAAI,KAAK,EAAE;EACxB,OAAO,OAAO,MAAM,KAAK,QAAO,CAAE,IAAI,OAAO,KAAK,mBAAmB,KAAK,MAAM;CAClF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEM,KAAK,WAAsC,MAAwB,UAA6B;EACtG,MAAM,QAAQ,cAAc,KAAK,WAAW,MAAK,MAAK,EAAE,SAAS,UAAU,IAAI,CAAC;EAEhF,MAAM,aADe,UAAU,WAAW,KAAK,UAAU,MAAK,MAAK,EAAE,SAAS,UAAU,QAAQ,IAAI,OAClF,EAAc,mBAAmB;EAEnD,MAAM,aAAa,UAAU,eAAe,UAAU,aAAa,0BAA0B,IAAI;EAEjG,OAAO;GACL;GACA,MAHW,cAAc,IAAI,QAAQ,eAAe,IAAI,IAAI;GAI5D;GACA,QAAQ,YACJ,mBAAmB,WAAW;IAAE;IAAO;IAAW,SAAS,UAAU;IAAiB;IAAU;GAAI,CAAE,IACtG,CAAA;GACJ,MAAM,0BAA0B,OAAO,QAAW,KAAK,MAAM;EAC9D;CACH;CAtDW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAuB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAvB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAuB,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,SAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UAtCxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BT,UAAA;EAAA,QAAA,CAAA,6QAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MA7BS;IAAiB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,UAAA,CAAA,mBAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAe,UAAA;IAAA,QAAA,CAAA,SAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAmB,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAsB,MAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAgB,MAAA;GAAA;EAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAuChG,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAuB,YAAA,CAAA;EAzCnC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAiB,SAClB;IAAC;IAAmB;IAAiB;IAAqB;IAAwB;GAAgB;GAAC,UAClG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BT,iBAQgB,wBAAwB;GAAM,QAAA,CAAA,6QAAA;EAAA,CAAA;;;;;;;;;;;AClEjD,MAAa,0BAAyE;CACpF;EAAE,MAAM;EAAc,iBAAiB;EAAoB,iBAAiB;CAAkB;CAC9F;EAAE,MAAM;EAAe,iBAAiB;EAAqB,iBAAiB;CAAmB;CACjG;EAAE,MAAM;EAAyB,iBAAiB;CAA4B;AAC/E;AAOD,SAAgB,yBAAsB;CACpC,OAAO,0BAA0B;EAC/B,IAAI;EACJ,WAAW;EACX,UAAS,SAAQ,iBAAiB,IAAI;CACvC,CAAA;AACH"}
|