@nexterajs/report-viewer 0.0.1 → 0.1.1
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/NOTICE +16 -16
- package/README.md +98 -96
- package/fesm2022/nexterajs-report-viewer.mjs +1667 -346
- package/fesm2022/nexterajs-report-viewer.mjs.map +1 -1
- package/package.json +2 -2
- package/types/nexterajs-report-viewer.d.ts +226 -68
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nexterajs-report-viewer.mjs","sources":["../../../projects/nextera-report-viewer/src/lib/protocol/nxr-protocol.const.ts","../../../projects/nextera-report-viewer/src/lib/page/nxr-page-html.util.ts","../../../projects/nextera-report-viewer/src/lib/page/nxr-report-page.component.ts","../../../projects/nextera-report-viewer/src/lib/strings/nxr-viewer-strings.const.ts","../../../projects/nextera-report-viewer/src/lib/protocol/nxr-protocol-reader.util.ts","../../../projects/nextera-report-viewer/src/lib/protocol/nxr-viewer-client.service.ts","../../../projects/nextera-report-viewer/src/lib/session/nxr-viewer-session.service.ts","../../../projects/nextera-report-viewer/src/lib/toolbar/nxr-viewer-toolbar.component.ts","../../../projects/nextera-report-viewer/src/lib/viewer/nxr-report-viewer.component.ts","../../../projects/nextera-report-viewer/src/public-api.ts","../../../projects/nextera-report-viewer/src/nexterajs-report-viewer.ts"],"sourcesContent":["/**\n * The version of the viewer protocol this package speaks: the `protocol` member of every\n * `AngularViewerData` answer from `Nextera.Report.AspNetCore`.\n */\nexport const NXR_VIEWER_PROTOCOL = 1;\n","/**\n * Page HTML from the server, made safe to place in the application's document.\n *\n * The report repository's HTML renderer escapes every attribute value and writes links only with\n * http, https, mailto, tel or no scheme, and its chart renderer strips event handlers from chart SVG.\n * This is the second layer: whatever reaches the viewer, a page can neither run script nor load active\n * content, and it cannot style the viewer around it.\n */\n\n/**\n * Elements that run script, load documents, plugins or media, submit, animate other attributes, or\n * carry CSS of their own. The renderer writes none of them into a page.\n */\nconst REMOVED_ELEMENTS = [\n 'script',\n 'noscript',\n 'template',\n 'style',\n 'link',\n 'meta',\n 'base',\n 'iframe',\n 'frame',\n 'frameset',\n 'object',\n 'embed',\n 'applet',\n 'portal',\n 'audio',\n 'video',\n 'source',\n 'track',\n 'picture',\n 'form',\n 'set',\n 'animate',\n].join(',');\n\n/** Attributes holding a URL that a click or a load would follow. */\nconst URL_ATTRIBUTES = new Set([\n 'href',\n 'xlink:href',\n 'src',\n 'action',\n 'formaction',\n 'poster',\n 'background',\n]);\n\n/** Attributes that make requests of their own and have no use in a page. */\nconst REMOVED_ATTRIBUTES = new Set(['srcset', 'ping']);\n\nconst LINK_SCHEMES = new Set(['http', 'https', 'mailto', 'tel']);\n\n/**\n * Whether a URL attribute's value can stay: no scheme (a relative or fragment URL), a link scheme, or,\n * for `src`, an image as a data URL. Browsers ignore spaces and control characters around and inside a\n * scheme, so the check drops them before reading it.\n */\nexport function isSafeUrl(attribute: string, value: string): boolean {\n let compact = '';\n for (const character of value) {\n if (character.charCodeAt(0) > 0x20) compact += character;\n }\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(compact)?.[1]?.toLowerCase();\n if (scheme === undefined || LINK_SCHEMES.has(scheme)) return true;\n return attribute === 'src' && scheme === 'data' && /^data:image\\//i.test(compact);\n}\n\n/**\n * Parses page HTML and returns it without anything active. A template's content is inert while it is\n * examined: its scripts do not run, its images do not load and its handlers do not fire.\n */\nexport function scrubPageHtml(html: string, document: Document): DocumentFragment {\n const template = document.createElement('template');\n template.innerHTML = html;\n const content = template.content;\n for (const element of Array.from(content.querySelectorAll(REMOVED_ELEMENTS))) {\n element.remove();\n }\n for (const element of Array.from(content.querySelectorAll('*'))) {\n for (const attribute of Array.from(element.attributes)) {\n const name = attribute.name.toLowerCase();\n const unsafe =\n name.startsWith('on') ||\n REMOVED_ATTRIBUTES.has(name) ||\n (URL_ATTRIBUTES.has(name) && !isSafeUrl(name, attribute.value));\n if (unsafe) element.removeAttribute(attribute.name);\n }\n }\n return content;\n}\n\n/** A stylesheet, or a rule that holds rules: anything whose rules can be listed and deleted by index. */\ninterface RuleContainer {\n readonly cssRules: CSSRuleList;\n deleteRule(index: number): void;\n}\n\n/**\n * Deletes every style rule whose selector names `:host` or `:host-context()`, also inside grouping rules\n * such as `@media` and inside nested rules. In a shadow root those rules style the shadow host, the\n * viewer's own page element, so a page's CSS could otherwise move or hide it.\n */\nfunction deleteHostRules(container: RuleContainer): void {\n for (let index = container.cssRules.length - 1; index >= 0; index--) {\n const rule = container.cssRules[index];\n if (rule instanceof CSSStyleRule && /:host/i.test(rule.selectorText)) {\n container.deleteRule(index);\n } else if ('cssRules' in rule && !(rule instanceof CSSKeyframesRule)) {\n deleteHostRules(rule as unknown as RuleContainer);\n }\n }\n}\n\nconst sheets = new Map<string, CSSStyleSheet>();\n\n/**\n * One constructed stylesheet per distinct CSS text, shared by every shadow root that adopts it. A\n * report's page CSS is the same for every page, so a long report parses it once. The sheet keeps no rule\n * that could style the shadow host. CSS that a constructed stylesheet refuses gives an empty sheet, so the\n * page shows unstyled instead of not at all.\n */\nexport function adoptedSheet(cssText: string): CSSStyleSheet {\n let sheet = sheets.get(cssText);\n if (!sheet) {\n sheet = new CSSStyleSheet();\n try {\n sheet.replaceSync(cssText);\n deleteHostRules(sheet);\n } catch {\n sheet = new CSSStyleSheet();\n }\n sheets.set(cssText, sheet);\n }\n return sheet;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DOCUMENT,\n ElementRef,\n inject,\n input,\n OnChanges,\n SimpleChanges,\n} from '@angular/core';\nimport type { NxrPageSize } from '../protocol/nxr-protocol.model';\nimport { adoptedSheet, scrubPageHtml } from './nxr-page-html.util';\n\n/** The viewer draws each page's frame and the space between pages, so the page CSS's own are cancelled. */\nconst PAGE_FRAME_CSS = '.nextera-page{margin:0;box-shadow:none;}';\n\n/**\n * One report page, in its own shadow root.\n *\n * The page's size comes from the report's page list, so the page holds its place before its HTML\n * arrives. The HTML is scrubbed by `scrubPageHtml` and placed beside the adopted page stylesheet, so the\n * report's styles and the application's never meet. `contain: paint` keeps even a fixed-position\n * element inside the page's box.\n */\n@Component({\n selector: 'nxr-report-page',\n standalone: true,\n template: '',\n styles: `\n :host {\n display: block;\n position: relative;\n box-sizing: content-box;\n contain: paint;\n background: #fff;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'nxr-report-page',\n '[attr.data-page]': 'page().pageNumber',\n '[style.width.pt]': 'page().widthPoints',\n '[style.height.pt]': 'page().heightPoints',\n },\n})\nexport class NxrReportPageComponent implements OnChanges {\n /** The page's number and size. */\n readonly page = input.required<NxrPageSize>();\n /** The page's HTML from the server, or null while it has not arrived. */\n readonly html = input<string | null>(null);\n /** The stylesheet every page of the report needs. */\n readonly css = input.required<string>();\n\n private readonly document = inject(DOCUMENT);\n private readonly root = (inject(ElementRef).nativeElement as HTMLElement).attachShadow({\n mode: 'open',\n });\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['css']) {\n this.root.adoptedStyleSheets = [adoptedSheet(this.css()), adoptedSheet(PAGE_FRAME_CSS)];\n }\n if (changes['html']) {\n const html = this.html();\n if (html === null) {\n this.root.replaceChildren();\n } else {\n this.root.replaceChildren(scrubPageHtml(html, this.document));\n }\n }\n }\n}\n","/**\n * Every caption and message the viewer shows, in its built-in English. A key in PascalCase is the name\n * Stimulsoft's viewer gives the same text, such as `PageOf`; a key in camelCase names a message only this\n * viewer has. The English is this package's own. A later plan lets a host's translation file replace any\n * of them, so code reads them from an `NxrViewerStrings` value wherever one is at hand.\n */\nexport const NXR_ENGLISH = {\n /** The label before the page-number box. */\n Page: 'Page',\n /** The label between the page-number box and the page count. */\n PageOf: 'of',\n FirstPage: 'First page',\n PrevPage: 'Previous page',\n NextPage: 'Next page',\n LastPage: 'Last page',\n errorUnreachable: 'The report server could not be reached.',\n errorStatus: 'The report server answered with HTTP status {0}.',\n errorTimeout: 'The report server did not answer within {0} seconds.',\n errorMalformed: \"The report server's answer to {0} is not one this viewer can read.\",\n errorProtocol:\n 'The report server speaks viewer protocol {0}, and this viewer speaks protocol {1}.',\n};\n\nexport type NxrViewerStrings = Readonly<Record<keyof typeof NXR_ENGLISH, string>>;\n\n/** Puts each value in place of its numbered placeholder: `{0}` is the first value. */\nexport function formatString(template: string, ...values: (string | number)[]): string {\n return template.replace(/\\{(\\d+)\\}/g, (placeholder, index: string) =>\n Number(index) < values.length ? String(values[Number(index)]) : placeholder,\n );\n}\n","import { HttpErrorResponse } from '@angular/common/http';\nimport { formatString, NXR_ENGLISH, NxrViewerStrings } from '../strings/nxr-viewer-strings.const';\nimport { NXR_VIEWER_PROTOCOL } from './nxr-protocol.const';\nimport type {\n NxrFindAnswer,\n NxrPagesAnswer,\n NxrReportAnswer,\n NxrUpdateCacheAnswer,\n NxrViewerAction,\n NxrViewerDataAnswer,\n NxrViewerFailure,\n} from './nxr-protocol.model';\n\n/**\n * A success answer that is not what the protocol says its action answers: the wrong shape, or an\n * AngularViewerData answer from another version of the protocol.\n */\nexport class NxrMalformedAnswerError extends Error {\n constructor(\n readonly action: NxrViewerAction,\n /** The version an AngularViewerData answer declared, when it declared another one. */\n readonly protocol: number = NXR_VIEWER_PROTOCOL,\n ) {\n super(`The ${action} answer is not what viewer protocol ${NXR_VIEWER_PROTOCOL} answers.`);\n this.name = 'NxrMalformedAnswerError';\n }\n}\n\n/** A request that got no answer within the server options' `requestTimeout`. */\nexport class NxrTimeoutError extends Error {\n constructor(readonly seconds: number) {\n super(`No answer within ${seconds} seconds.`);\n this.name = 'NxrTimeoutError';\n }\n}\n\ntype JsonObject = Record<string, unknown>;\n\nconst OPTION_GROUPS = ['actions', 'appearance', 'toolbar', 'exports', 'server'];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isIndex(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n\nfunction isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isBounds(value: unknown): boolean {\n return (\n isObject(value) &&\n isNumber(value['x']) &&\n isNumber(value['y']) &&\n isNumber(value['width']) &&\n isNumber(value['height'])\n );\n}\n\nfunction isPages(value: unknown): value is NxrPagesAnswer {\n if (!isObject(value)) return false;\n const pages = value['pages'];\n return (\n isIndex(value['startIndex']) &&\n Array.isArray(pages) &&\n pages.every((page) => typeof page === 'string')\n );\n}\n\nfunction isPageSize(value: unknown): boolean {\n return (\n isObject(value) &&\n isIndex(value['pageNumber']) &&\n isNumber(value['widthPoints']) &&\n isNumber(value['heightPoints'])\n );\n}\n\nfunction isLocated(value: unknown, textKey: 'title' | 'text'): boolean {\n return (\n isObject(value) &&\n typeof value[textKey] === 'string' &&\n isIndex(value['pageIndex']) &&\n isBounds(value['bounds'])\n );\n}\n\n/** Reads the answer to AngularViewerData: the token, the viewer options and the host's translation. */\nexport function readViewerData(body: unknown): NxrViewerDataAnswer {\n if (!isObject(body)) throw new NxrMalformedAnswerError('AngularViewerData');\n const { protocol, token, options, localization } = body;\n if (isNumber(protocol) && protocol !== NXR_VIEWER_PROTOCOL) {\n throw new NxrMalformedAnswerError('AngularViewerData', protocol);\n }\n const valid =\n protocol === NXR_VIEWER_PROTOCOL &&\n typeof token === 'string' &&\n token !== '' &&\n isObject(options) &&\n OPTION_GROUPS.every((group) => isObject(options[group])) &&\n (localization === null || isObject(localization));\n if (!valid) throw new NxrMalformedAnswerError('AngularViewerData');\n return body as unknown as NxrViewerDataAnswer;\n}\n\n/** Reads the answer to GetReport: the report's name, page count, page sizes, bookmarks and page stylesheet. */\nexport function readReport(body: unknown): NxrReportAnswer {\n if (!isObject(body)) throw new NxrMalformedAnswerError('GetReport');\n const { reportName, pageCount, pages, bookmarks, pageCss, pagesHtml } = body;\n const valid =\n typeof reportName === 'string' &&\n isIndex(pageCount) &&\n Array.isArray(pages) &&\n pages.length === pageCount &&\n pages.every(isPageSize) &&\n Array.isArray(bookmarks) &&\n bookmarks.every((bookmark) => isLocated(bookmark, 'title')) &&\n typeof pageCss === 'string' &&\n (pagesHtml === undefined || isPages(pagesHtml));\n if (!valid) throw new NxrMalformedAnswerError('GetReport');\n return {\n ...(body as unknown as NxrReportAnswer),\n pagesHtml: (pagesHtml as NxrPagesAnswer | undefined) ?? null,\n };\n}\n\n/** Reads the answer to GetPages. */\nexport function readPages(body: unknown): NxrPagesAnswer {\n if (!isPages(body)) throw new NxrMalformedAnswerError('GetPages');\n return body;\n}\n\n/** Reads the answer to Find. */\nexport function readFind(body: unknown): NxrFindAnswer {\n const hits = isObject(body) ? body['hits'] : undefined;\n if (!Array.isArray(hits) || !hits.every((hit) => isLocated(hit, 'text')))\n throw new NxrMalformedAnswerError('Find');\n return body as unknown as NxrFindAnswer;\n}\n\n/** Reads the answer to UpdateCache. */\nexport function readUpdateCache(body: unknown): NxrUpdateCacheAnswer {\n if (!isObject(body) || typeof body['updated'] !== 'boolean')\n throw new NxrMalformedAnswerError('UpdateCache');\n return body as unknown as NxrUpdateCacheAnswer;\n}\n\nfunction described(status: number, message: string): NxrViewerFailure {\n return { status, type: 'Error', message, retryable: false, traceId: null };\n}\n\n/**\n * What went wrong with a request, from whatever it failed with:\n * - the server's own error answer, kept as it is;\n * - an HTTP error answer without the protocol's shape (a host's, a framework's or a proxy's);\n * - no answer at all;\n * - a timeout;\n * - a success answer the viewer cannot read.\n */\nexport function readFailure(\n failure: unknown,\n action: NxrViewerAction,\n strings: NxrViewerStrings = NXR_ENGLISH,\n): NxrViewerFailure {\n if (failure instanceof HttpErrorResponse) {\n const body: unknown = failure.error;\n if (\n isObject(body) &&\n body['status'] === 'error' &&\n typeof body['type'] === 'string' &&\n typeof body['message'] === 'string' &&\n typeof body['retryable'] === 'boolean'\n ) {\n const traceId = typeof body['traceId'] === 'string' ? body['traceId'] : null;\n return {\n status: failure.status,\n type: body['type'],\n message: body['message'],\n retryable: body['retryable'],\n traceId,\n };\n }\n if (failure.status === 0) return described(0, strings.errorUnreachable);\n if (failure.status >= 200 && failure.status < 300)\n return described(0, formatString(strings.errorMalformed, action));\n return described(failure.status, formatString(strings.errorStatus, failure.status));\n }\n if (failure instanceof NxrTimeoutError) {\n return described(0, formatString(strings.errorTimeout, failure.seconds));\n }\n if (failure instanceof NxrMalformedAnswerError) {\n return failure.protocol !== NXR_VIEWER_PROTOCOL\n ? described(0, formatString(strings.errorProtocol, failure.protocol, NXR_VIEWER_PROTOCOL))\n : described(0, formatString(strings.errorMalformed, failure.action));\n }\n return described(0, failure instanceof Error ? failure.message : String(failure));\n}\n","import { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { inject, Injectable } from '@angular/core';\nimport { catchError, defer, from, map, Observable, switchMap, throwError, timeout } from 'rxjs';\nimport type { NxrViewerStrings } from '../strings/nxr-viewer-strings.const';\nimport type {\n NxrExportAnswer,\n NxrFindAnswer,\n NxrPagesAnswer,\n NxrReportAnswer,\n NxrUpdateCacheAnswer,\n NxrViewerAction,\n NxrViewerDataAnswer,\n} from './nxr-protocol.model';\nimport {\n NxrTimeoutError,\n readFailure,\n readFind,\n readPages,\n readReport,\n readUpdateCache,\n readViewerData,\n} from './nxr-protocol-reader.util';\nimport type { NxrViewerOptions } from './nxr-viewer-options.model';\n\n/** What the component's `postParametersFunction` is called with: the request's action and its parameters. */\nexport interface NxrPostParametersData {\n action: NxrViewerAction;\n [parameter: string]: unknown;\n}\n\n/**\n * The component's `postParametersFunction` input. It runs for every request, the first one included.\n * Each key of an object it returns becomes a form field of the request, replacing a field of the same\n * name; anything else it returns adds nothing.\n */\nexport type NxrPostParametersFunction = (data: NxrPostParametersData) => unknown;\n\n/** What every request is built from. */\nexport interface NxrRequestContext {\n /** The component's `requestUrl`: each request's host action takes the place of `{action}`. */\n requestUrl: string;\n /** The component's `properties`, sent as JSON when truthy. */\n properties: unknown;\n /** The component's `postParametersFunction`. */\n postParametersFunction: NxrPostParametersFunction | null | undefined;\n /** The strings failures are described with. */\n strings: NxrViewerStrings;\n}\n\n/** The server's side of an open viewer: the token it issued and the options it sent. */\nexport interface NxrServerSession {\n token: string;\n options: NxrViewerOptions;\n}\n\n/** Consecutive pages, from a 0-based index. */\nexport interface NxrPageRange {\n startIndex: number;\n count: number;\n}\n\nexport interface NxrFindParameters {\n text: string;\n matchCase?: boolean;\n wholeWord?: boolean;\n}\n\n/**\n * The seconds a request may take when no positive `requestTimeout` applies. That includes the first\n * request, which is sent before the server's options are known. Stimulsoft's viewer uses the same value.\n */\nexport const NXR_UNSET_REQUEST_TIMEOUT_SECONDS = 1000;\n\n/**\n * The URL of a host action. The action's path takes the place of `{action}` in `requestUrl`, and a query\n * string on the action is appended to the URL's own.\n */\nexport function actionUrl(requestUrl: string, action: string): string {\n const queryAt = action.indexOf('?');\n const path = queryAt < 0 ? action : action.slice(0, queryAt);\n const url = requestUrl.replace('{action}', () => path);\n if (queryAt < 0) return url;\n return `${url}${url.includes('?') ? '&' : '?'}${action.slice(queryAt + 1)}`;\n}\n\n/**\n * The host action that answers a viewer action. GetReport goes to `getReport` (or `viewerEvent` when that\n * is empty). The other actions go to `viewerEvent`, or to `getReport` when the server keeps nothing.\n * ExportReport goes to `exportReport` when that is set.\n */\nexport function hostActionFor(options: NxrViewerOptions, action: NxrViewerAction): string {\n const { getReport, viewerEvent, exportReport } = options.actions;\n const reportAction = getReport || viewerEvent;\n const eventAction = options.server.cacheMode === 'None' ? reportAction : viewerEvent;\n if (action === 'GetReport') return reportAction;\n if (action === 'ExportReport') return exportReport || eventAction;\n return eventAction;\n}\n\n/** The file name in a Content-Disposition header, preferring its UTF-8 form. */\nexport function fileNameOf(disposition: string | null): string | null {\n if (!disposition) return null;\n const encoded = /filename\\*\\s*=\\s*UTF-8''([^;]+)/i.exec(disposition);\n if (encoded) {\n try {\n return decodeURIComponent(encoded[1].trim());\n } catch {\n // A malformed escape: the plain file name follows.\n }\n }\n const plain = /filename\\s*=\\s*(?:\"([^\"]*)\"|([^;]+))/i.exec(disposition);\n return plain ? (plain[1] ?? plain[2]).trim() : null;\n}\n\nfunction timeoutOf(session: NxrServerSession | null): number {\n const seconds = session?.options.server.requestTimeout ?? 0;\n return seconds > 0 ? seconds : NXR_UNSET_REQUEST_TIMEOUT_SECONDS;\n}\n\nfunction formOf(\n context: NxrRequestContext,\n action: NxrViewerAction,\n session: NxrServerSession | null,\n parameters: object | null,\n): FormData {\n const form = new FormData();\n form.set('nextera_action', action);\n if (session) {\n const { cacheMode, cacheTimeout, cacheItemPriority } = session.options.server;\n form.set('nextera_token', session.token);\n form.set(\n 'nextera_cache',\n JSON.stringify({ mode: cacheMode, timeout: cacheTimeout, priority: cacheItemPriority }),\n );\n }\n if (parameters) form.set('nextera_parameters', JSON.stringify(parameters));\n if (context.properties) form.set('properties', JSON.stringify(context.properties));\n const added = context.postParametersFunction?.({ ...parameters, action });\n if (typeof added === 'object' && added !== null) {\n for (const [name, value] of Object.entries(added)) {\n form.set(name, value instanceof Blob ? value : String(value));\n }\n }\n return form;\n}\n\n/** An error answer to a blob request carries its body as a blob. Read it, as JSON when it is JSON, so it can be classified. */\nasync function readableFailure(failure: unknown): Promise<unknown> {\n if (!(failure instanceof HttpErrorResponse) || !(failure.error instanceof Blob)) return failure;\n const text = await failure.error.text();\n let body: unknown = text;\n try {\n body = JSON.parse(text);\n } catch {\n // Not JSON: the failure is described by its status.\n }\n return new HttpErrorResponse({\n error: body,\n headers: failure.headers,\n status: failure.status,\n statusText: failure.statusText,\n url: failure.url ?? undefined,\n });\n}\n\n/**\n * Sends one viewer's protocol requests through the application's `HttpClient`, so the application's\n * interceptors apply, and reads each answer. Every observable fails with an `NxrViewerFailure`. A request's\n * form is built when the observable is subscribed.\n */\n@Injectable()\nexport class NxrViewerClientService {\n private readonly http = inject(HttpClient);\n\n /** AngularViewerData, sent to the component's `action`: the token and the options. */\n openViewer(context: NxrRequestContext, action: string): Observable<NxrViewerDataAnswer> {\n return this.post(context, 'AngularViewerData', action, null, null, readViewerData);\n }\n\n /** GetReport: renders the report, with the HTML of the pages in `range` when one is given. */\n getReport(\n context: NxrRequestContext,\n session: NxrServerSession,\n range?: NxrPageRange,\n ): Observable<NxrReportAnswer> {\n const hostAction = hostActionFor(session.options, 'GetReport');\n return this.post(context, 'GetReport', hostAction, session, range ?? null, readReport);\n }\n\n /** GetPages: the HTML of the pages in `range`. */\n getPages(\n context: NxrRequestContext,\n session: NxrServerSession,\n range: NxrPageRange,\n ): Observable<NxrPagesAnswer> {\n return this.post(\n context,\n 'GetPages',\n hostActionFor(session.options, 'GetPages'),\n session,\n range,\n readPages,\n );\n }\n\n /** Find: the text components that match. */\n find(\n context: NxrRequestContext,\n session: NxrServerSession,\n parameters: NxrFindParameters,\n ): Observable<NxrFindAnswer> {\n return this.post(\n context,\n 'Find',\n hostActionFor(session.options, 'Find'),\n session,\n parameters,\n readFind,\n );\n }\n\n /** UpdateCache: keeps the server's copy of the report. */\n updateCache(\n context: NxrRequestContext,\n session: NxrServerSession,\n ): Observable<NxrUpdateCacheAnswer> {\n const hostAction = hostActionFor(session.options, 'UpdateCache');\n return this.post(context, 'UpdateCache', hostAction, session, null, readUpdateCache);\n }\n\n /** ExportReport: the report as a file, in a format such as `Pdf` or `Html`. It never times out. */\n exportReport(\n context: NxrRequestContext,\n session: NxrServerSession,\n format: string,\n ): Observable<NxrExportAnswer> {\n const url = actionUrl(context.requestUrl, hostActionFor(session.options, 'ExportReport'));\n return defer(() =>\n this.http.post(url, formOf(context, 'ExportReport', session, { format }), {\n observe: 'response',\n responseType: 'blob',\n }),\n ).pipe(\n map((response) => ({\n blob: response.body ?? new Blob([]),\n fileName: fileNameOf(response.headers.get('Content-Disposition')) ?? '',\n contentType: response.headers.get('Content-Type') ?? '',\n })),\n catchError((failure: unknown) =>\n from(readableFailure(failure)).pipe(\n switchMap((readable) =>\n throwError(() => readFailure(readable, 'ExportReport', context.strings)),\n ),\n ),\n ),\n );\n }\n\n private post<T>(\n context: NxrRequestContext,\n action: NxrViewerAction,\n hostAction: string,\n session: NxrServerSession | null,\n parameters: object | null,\n read: (body: unknown) => T,\n ): Observable<T> {\n const seconds = timeoutOf(session);\n return defer(() =>\n this.http.post(\n actionUrl(context.requestUrl, hostAction),\n formOf(context, action, session, parameters),\n ),\n ).pipe(\n timeout({\n first: seconds * 1000,\n with: () => throwError(() => new NxrTimeoutError(seconds)),\n }),\n map((body) => read(body)),\n catchError((failure: unknown) =>\n throwError(() => readFailure(failure, action, context.strings)),\n ),\n );\n }\n}\n","import { computed, DestroyRef, inject, Injectable, signal } from '@angular/core';\nimport {\n catchError,\n EMPTY,\n exhaustMap,\n finalize,\n interval,\n Observable,\n Subject,\n Subscription,\n} from 'rxjs';\nimport type {\n NxrPagesAnswer,\n NxrPageSize,\n NxrReportAnswer,\n NxrViewerFailure,\n} from '../protocol/nxr-protocol.model';\nimport {\n NxrRequestContext,\n NxrServerSession,\n NxrViewerClientService,\n} from '../protocol/nxr-viewer-client.service';\nimport type { NxrViewerOptions } from '../protocol/nxr-viewer-options.model';\n\n/** How often an open viewer asks the server to keep its report: every 3 minutes, as Stimulsoft's viewer does. */\nexport const NXR_KEEP_ALIVE_MS = 180_000;\n\n/** The page on screen. */\nexport interface NxrShownPage {\n /** 0-based. */\n index: number;\n size: NxrPageSize;\n /** The page's HTML, or null while it has not arrived: while it is on its way, or after its request failed. */\n html: string | null;\n}\n\nfunction withPages(pages: Map<number, string>, answer: NxrPagesAnswer | null): Map<number, string> {\n answer?.pages.forEach((html, offset) => pages.set(answer.startIndex + offset, html));\n return pages;\n}\n\n/**\n * One viewer's conversation with the report server, and the state the viewer shows.\n *\n * Every signal changes only in this service's methods and in the answers they handle; nothing reacts to\n * a signal changing. Each viewer provides its own session, so viewers on one page never share state.\n */\n@Injectable()\nexport class NxrViewerSessionService {\n private readonly client = inject(NxrViewerClientService);\n\n private readonly optionsState = signal<NxrViewerOptions | null>(null);\n private readonly reportState = signal<NxrReportAnswer | null>(null);\n private readonly htmlState = signal<ReadonlyMap<number, string>>(new Map());\n private readonly pageIndexState = signal(0);\n private readonly pendingState = signal(0);\n private readonly failureState = signal<NxrViewerFailure | null>(null);\n\n /** The options from the last AngularViewerData answer. */\n readonly options = this.optionsState.asReadonly();\n /** The report from the last GetReport answer, or null before one. */\n readonly report = this.reportState.asReadonly();\n /** The 0-based index of the page on screen. */\n readonly pageIndex = this.pageIndexState.asReadonly();\n /** The failure on show, until it is dismissed. */\n readonly failure = this.failureState.asReadonly();\n /** How many pages the report has; 0 before one is loaded. */\n readonly pageCount = computed(() => this.reportState()?.pageCount ?? 0);\n /** Whether a request the user waits for is on its way. Keep-alive requests do not count. */\n readonly busy = computed(() => this.pendingState() > 0);\n /** The page on screen, or null before a report. */\n readonly shownPage = computed<NxrShownPage | null>(() => {\n const report = this.reportState();\n const index = this.pageIndexState();\n if (!report || index >= report.pageCount) return null;\n return { index, size: report.pages[index], html: this.htmlState().get(index) ?? null };\n });\n\n /** Emits after each successful GetReport answer. */\n readonly reportLoaded = new Subject<void>();\n /** Emits each failure put on show. */\n readonly failed = new Subject<NxrViewerFailure>();\n\n private context: NxrRequestContext | null = null;\n private session: NxrServerSession | null = null;\n /** Every request the user waits for. */\n private requests = new Subscription();\n /** The page requests among them, which a new rendering of the report makes obsolete. */\n private pageRequests = new Subscription();\n private keepAlive = Subscription.EMPTY;\n private readonly pagesOnTheWay = new Set<number>();\n /** True from the moment an expired report is sent to be rendered again until that rendering settles. */\n private recovering = false;\n private destroyed = false;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.destroyed = true;\n this.close();\n this.reportLoaded.complete();\n this.failed.complete();\n });\n }\n\n /** Opens the report the host action names, in place of whatever this viewer showed. */\n open(context: NxrRequestContext, action: string): void {\n if (this.destroyed) return;\n this.close();\n this.context = context;\n this.reportState.set(null);\n this.htmlState.set(new Map());\n this.pageIndexState.set(0);\n this.failureState.set(null);\n if (!context.requestUrl) return;\n this.track(this.client.openViewer(context, action), false, (answer) => {\n const session = { token: answer.token, options: answer.options };\n this.session = session;\n this.optionsState.set(answer.options);\n this.startKeepAlive(context, session);\n this.render();\n });\n }\n\n /**\n * Shows the page at a 0-based index; an index outside the report is ignored. Asking for the page already\n * on screen fetches it again when its HTML is missing, as it is after its request failed.\n */\n goToPage(index: number): void {\n const inReport = Number.isInteger(index) && index >= 0 && index < this.pageCount();\n if (this.destroyed || !inReport) return;\n this.pageIndexState.set(index);\n this.loadPage(index);\n }\n\n /** Takes the failure off show. */\n dismissFailure(): void {\n this.failureState.set(null);\n }\n\n /**\n * GetReport, asking for the page on screen, which stays on screen when it is still in the report. The new\n * rendering makes every page request still on its way obsolete. Its settling ends a recovery.\n */\n private render(): void {\n const { context, session } = this.connection();\n const range = { startIndex: this.pageIndexState(), count: 1 };\n const rendering = this.client\n .getReport(context, session, range)\n .pipe(finalize(() => (this.recovering = false)));\n this.track(rendering, false, (report) => {\n this.pageRequests.unsubscribe();\n this.pageRequests = new Subscription();\n this.htmlState.set(withPages(new Map(), report.pagesHtml));\n this.reportState.set(report);\n this.pageIndexState.update((index) => Math.max(0, Math.min(index, report.pageCount - 1)));\n this.reportLoaded.next();\n this.loadPage(this.pageIndexState());\n });\n }\n\n /** GetPages for one page, unless the page is already here or on its way. */\n private loadPage(index: number): void {\n if (index >= this.pageCount() || this.htmlState().has(index) || this.pagesOnTheWay.has(index))\n return;\n const { context, session } = this.connection();\n this.pagesOnTheWay.add(index);\n const request = this.client\n .getPages(context, session, { startIndex: index, count: 1 })\n .pipe(finalize(() => this.pagesOnTheWay.delete(index)));\n this.pageRequests.add(\n this.track(request, true, (answer) =>\n this.htmlState.set(withPages(new Map(this.htmlState()), answer)),\n ),\n );\n }\n\n /**\n * Sends a request the user waits for, and returns its subscription. A `recoverable` request that finds the\n * report gone renders it again; every other failure goes on show.\n */\n private track<T>(\n request: Observable<T>,\n recoverable: boolean,\n next: (value: T) => void,\n ): Subscription {\n this.pendingState.update((count) => count + 1);\n const subscription = request\n .pipe(finalize(() => this.pendingState.update((count) => count - 1)))\n .subscribe({\n next,\n error: (failure: NxrViewerFailure) => this.fail(failure, recoverable),\n });\n this.requests.add(subscription);\n return subscription;\n }\n\n /**\n * An expired report found by a recoverable request is rendered again, unless a rendering is already on its\n * way; every other failure goes on show. Only that rendering settling ends the recovery, so failures in the\n * meantime cannot start a second one.\n */\n private fail(failure: NxrViewerFailure, recoverable: boolean): void {\n if (failure.type === 'CacheExpired' && recoverable) {\n if (!this.recovering) {\n this.recovering = true;\n this.render();\n }\n return;\n }\n this.failureState.set(failure);\n this.failed.next(failure);\n }\n\n /** UpdateCache every three minutes while the server keeps the report. Its failures are not shown. */\n private startKeepAlive(context: NxrRequestContext, session: NxrServerSession): void {\n const { allowAutoUpdateCache, cacheMode } = session.options.server;\n if (!allowAutoUpdateCache || cacheMode === 'None') return;\n this.keepAlive = interval(NXR_KEEP_ALIVE_MS)\n .pipe(\n exhaustMap(() => this.client.updateCache(context, session).pipe(catchError(() => EMPTY))),\n )\n .subscribe();\n }\n\n /** Stops every request and the keep-alive. */\n private close(): void {\n this.requests.unsubscribe();\n this.requests = new Subscription();\n this.pageRequests = new Subscription();\n this.keepAlive.unsubscribe();\n this.session = null;\n this.pagesOnTheWay.clear();\n this.recovering = false;\n }\n\n private connection(): { context: NxrRequestContext; session: NxrServerSession } {\n if (!this.context || !this.session) throw new Error('The viewer has no report open.');\n return { context: this.context, session: this.session };\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\nimport type { NxrViewerOptions } from '../protocol/nxr-viewer-options.model';\nimport { NXR_ENGLISH, type NxrViewerStrings } from '../strings/nxr-viewer-strings.const';\n\n/** The width of the page-number box, as Stimulsoft's page control sizes it. */\nconst PAGE_BOX_WIDTH_PX = 45;\n\n/**\n * The toolbar's page navigation.\n *\n * Stimulsoft's toolbar is a long list of groups; this is the navigation group of it, which is what\n * a report viewer cannot do without: first, previous, the page control, next, last. Each button\n * appears only when its `toolbar.show…Button` option is on, and the group is laid out where\n * `toolbar.alignment` says. The other groups — save, print, find, bookmarks, zoom, view mode —\n * arrive with the tasks that implement them.\n *\n * Navigation is disabled the way Stimulsoft disables it: in `MultiplePages`, and in `Continuous`\n * unless the report panel or the whole viewer scrolls. A button is disabled at the end of the\n * report it would move past, and everything is disabled while a request the user waits for is on\n * its way.\n */\n@Component({\n selector: 'nxr-viewer-toolbar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'nxr-viewer-toolbar',\n role: 'toolbar',\n '[style.background-color]': 'backgroundColor()',\n '[style.border]': 'border()',\n '[style.color]': 'fontColor()',\n '[style.font-family]': 'fontFamily()',\n '[style.justify-content]': 'justifyContent()',\n '[class.nxr-busy]': 'busy()',\n },\n template: `\n @if (showFirstPage()) {\n <button\n type=\"button\"\n class=\"nxr-toolbar-button\"\n [disabled]=\"atStart()\"\n [attr.aria-label]=\"strings().FirstPage\"\n (click)=\"goTo(0)\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M12.5 3v10L6 8zM4.5 3h1.2v10H4.5z\" />\n </svg>\n </button>\n }\n @if (showPreviousPage()) {\n <button\n type=\"button\"\n class=\"nxr-toolbar-button\"\n [disabled]=\"atStart()\"\n [attr.aria-label]=\"strings().PrevPage\"\n (click)=\"goTo(pageIndex() - 1)\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M11 3v10L4.5 8z\" /></svg>\n </button>\n }\n @if (showCurrentPage()) {\n <span class=\"nxr-page-control\">\n <span class=\"nxr-page-label\">{{ strings().Page }}</span>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n class=\"nxr-page-box\"\n [style.width.px]=\"pageBoxWidth\"\n [disabled]=\"pageControlDisabled()\"\n [value]=\"pageIndex() + 1\"\n [attr.aria-label]=\"strings().Page\"\n (keydown.enter)=\"enterPage($event)\"\n />\n <span class=\"nxr-page-label\">{{ strings().PageOf }} {{ pageCount() }}</span>\n </span>\n }\n @if (showNextPage()) {\n <button\n type=\"button\"\n class=\"nxr-toolbar-button\"\n [disabled]=\"atEnd()\"\n [attr.aria-label]=\"strings().NextPage\"\n (click)=\"goTo(pageIndex() + 1)\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5 3v10l6.5-5z\" /></svg>\n </button>\n }\n @if (showLastPage()) {\n <button\n type=\"button\"\n class=\"nxr-toolbar-button\"\n [disabled]=\"atEnd()\"\n [attr.aria-label]=\"strings().LastPage\"\n (click)=\"goTo(pageCount() - 1)\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3.5 3v10L10 8zM10.3 3h1.2v10h-1.2z\" />\n </svg>\n </button>\n }\n `,\n styles: `\n :host {\n display: flex;\n align-items: center;\n gap: 2px;\n box-sizing: border-box;\n padding: 3px 6px;\n min-height: 30px;\n position: relative;\n user-select: none;\n }\n\n /* Stimulsoft covers the toolbar with a disabled panel while a request is in flight. */\n :host(.nxr-busy)::after {\n content: '';\n position: absolute;\n inset: 0;\n cursor: default;\n }\n\n .nxr-toolbar-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n padding: 0;\n border: 0;\n border-radius: 2px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n }\n\n .nxr-toolbar-button:hover:not(:disabled) {\n background: rgb(0 0 0 / 8%);\n }\n\n .nxr-toolbar-button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n\n .nxr-toolbar-button svg {\n width: 16px;\n height: 16px;\n fill: currentColor;\n }\n\n .nxr-page-control {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0 4px;\n white-space: nowrap;\n }\n\n .nxr-page-box {\n height: 21px;\n box-sizing: border-box;\n text-align: center;\n font: inherit;\n color: inherit;\n }\n\n .nxr-page-box:disabled {\n color: transparent;\n }\n `,\n})\nexport class NxrViewerToolbarComponent {\n /** The options from the server, or null before the first answer, when the toolbar shows nothing. */\n readonly options = input<NxrViewerOptions | null>(null);\n /** The 0-based index of the page on screen. */\n readonly pageIndex = input(0);\n /** How many pages the report has. */\n readonly pageCount = input(0);\n /** Whether a request the user waits for is on its way. */\n readonly busy = input(false);\n /** The captions to show. */\n readonly strings = input<NxrViewerStrings>(NXR_ENGLISH);\n\n /** The 0-based page the user asked for. */\n readonly goToPage = output<number>();\n\n protected readonly pageBoxWidth = PAGE_BOX_WIDTH_PX;\n\n private readonly toolbar = computed(() => this.options()?.toolbar ?? null);\n private readonly appearance = computed(() => this.options()?.appearance ?? null);\n\n /**\n * Stimulsoft's rule: navigation is off in `MultiplePages`, and in `Continuous` unless the report\n * panel scrolls or the viewer is full screen — in those cases the page is reached by scrolling.\n */\n private readonly navigationDisabled = computed(() => {\n const toolbar = this.toolbar();\n const appearance = this.appearance();\n if (!toolbar || !appearance) return true;\n if (toolbar.viewMode === 'MultiplePages') return true;\n return (\n toolbar.viewMode === 'Continuous' &&\n !appearance.scrollbarsMode &&\n !appearance.fullScreenMode\n );\n });\n\n protected readonly showFirstPage = computed(() => this.toolbar()?.showFirstPageButton === true);\n protected readonly showPreviousPage = computed(\n () => this.toolbar()?.showPreviousPageButton === true,\n );\n protected readonly showCurrentPage = computed(\n () => this.toolbar()?.showCurrentPageControl === true,\n );\n protected readonly showNextPage = computed(() => this.toolbar()?.showNextPageButton === true);\n protected readonly showLastPage = computed(() => this.toolbar()?.showLastPageButton === true);\n\n protected readonly atStart = computed(\n () => this.busy() || this.navigationDisabled() || this.pageIndex() <= 0,\n );\n protected readonly atEnd = computed(\n () => this.busy() || this.navigationDisabled() || this.pageIndex() >= this.pageCount() - 1,\n );\n protected readonly pageControlDisabled = computed(\n () => this.busy() || this.navigationDisabled() || this.pageCount() <= 1,\n );\n\n protected readonly backgroundColor = computed(() => this.toolbar()?.backgroundColor || null);\n protected readonly fontColor = computed(() => this.toolbar()?.fontColor || null);\n protected readonly fontFamily = computed(() => this.toolbar()?.fontFamily || null);\n\n /** A border only in `Simple`; `Separated` has none, as Stimulsoft's toolbar does. */\n protected readonly border = computed(() => {\n const toolbar = this.toolbar();\n if (!toolbar || toolbar.displayMode === 'Separated' || !toolbar.borderColor) return null;\n return `1px solid ${toolbar.borderColor}`;\n });\n\n protected readonly justifyContent = computed(() => {\n switch (this.toolbar()?.alignment) {\n case 'Center':\n return 'center';\n case 'Right':\n return 'flex-end';\n default:\n return 'flex-start';\n }\n });\n\n /**\n * Enter in the page box goes to the page typed, reading anything that is not a number as page 1\n * and clamping to the report, as Stimulsoft's page control does. Leaving the box does nothing.\n */\n protected enterPage(event: Event): void {\n const box = event.target as HTMLInputElement;\n const typed = Number.parseInt(box.value, 10);\n const page = Math.min(Math.max(Number.isNaN(typed) ? 1 : typed, 1), this.pageCount());\n box.value = String(page);\n this.goTo(page - 1);\n }\n\n protected goTo(index: number): void {\n if (this.busy() || index === this.pageIndex() || index < 0 || index >= this.pageCount()) return;\n this.goToPage.emit(index);\n }\n}\n","import { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n OnChanges,\n output,\n} from '@angular/core';\nimport { NxrReportPageComponent } from '../page/nxr-report-page.component';\nimport type { NxrViewerFailure } from '../protocol/nxr-protocol.model';\nimport {\n NxrViewerClientService,\n type NxrPostParametersFunction,\n type NxrRequestContext,\n} from '../protocol/nxr-viewer-client.service';\nimport { NxrViewerSessionService } from '../session/nxr-viewer-session.service';\nimport { NXR_ENGLISH } from '../strings/nxr-viewer-strings.const';\nimport { NxrViewerToolbarComponent } from '../toolbar/nxr-viewer-toolbar.component';\n\n/**\n * What a host reaches through the component's `api`, with Stimulsoft's names and meanings. The\n * members for zoom, view mode, export, print, email and find arrive with the tasks that implement\n * those; a host that only pages through a report needs these three.\n */\nexport interface NxrViewerApi {\n /** The 0-based page on screen. Setting it shows a page inside the report and ignores anything else. */\n currentPage: number;\n /** How many pages the report has; 0 before one is loaded. */\n readonly pagesCount: number;\n /** Always `Report`, as Stimulsoft's Angular viewer answers when it is not showing a dashboard. */\n readonly reportType: string;\n}\n\n/**\n * A report served by `Nextera.Reports.Angular.NetCore`, shown page by page.\n *\n * The inputs, outputs and `api` are Stimulsoft's `stimulsoft-viewer-angular`, so a host swaps the\n * component and keeps its bindings. As there, a change to any input reloads the report: the\n * component asks for the viewer's options again and opens the report the action names.\n *\n * Each viewer provides its own session, so several on a page never share a report or a token.\n */\n@Component({\n selector: 'nxr-report-viewer',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NxrReportPageComponent, NxrViewerToolbarComponent],\n providers: [NxrViewerClientService, NxrViewerSessionService],\n template: `\n <div\n class=\"nxr-viewer-root\"\n [style]=\"style()\"\n [style.background-color]=\"rootBackgroundColor()\"\n [style.width]=\"rootWidth()\"\n [style.height]=\"rootHeight()\"\n >\n @if (toolbarVisible()) {\n <nxr-viewer-toolbar\n [options]=\"session.options()\"\n [pageIndex]=\"session.pageIndex()\"\n [pageCount]=\"session.pageCount()\"\n [busy]=\"session.busy()\"\n (goToPage)=\"session.goToPage($event)\"\n />\n }\n\n <div\n class=\"nxr-viewer-pages\"\n [style.text-align]=\"pageAlignment()\"\n [style.overflow]=\"pagesOverflow()\"\n >\n @if (session.shownPage(); as page) {\n <nxr-report-page\n class=\"nxr-viewer-page\"\n [class.nxr-viewer-page-shadow]=\"showPageShadow()\"\n [style.border]=\"pageBorder()\"\n [page]=\"page.size\"\n [html]=\"page.html\"\n [css]=\"pageCss()\"\n />\n }\n </div>\n\n @if (session.failure(); as failure) {\n <div class=\"nxr-viewer-failure\" role=\"alert\">\n <span class=\"nxr-viewer-failure-text\">{{ failure.message }}</span>\n <button type=\"button\" class=\"nxr-viewer-failure-close\" (click)=\"session.dismissFailure()\">\n ×\n </button>\n </div>\n }\n </div>\n `,\n styles: `\n :host {\n display: inline-block;\n position: relative;\n }\n\n .nxr-viewer-root {\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n position: relative;\n }\n\n .nxr-viewer-pages {\n flex: 1 1 auto;\n min-height: 0;\n padding: 10px;\n box-sizing: border-box;\n }\n\n .nxr-viewer-page {\n display: inline-block;\n vertical-align: top;\n }\n\n .nxr-viewer-page-shadow {\n box-shadow: 2px 2px 6px rgb(0 0 0 / 30%);\n }\n\n .nxr-viewer-failure {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #fdecea;\n color: #611a15;\n font-size: 13px;\n }\n\n .nxr-viewer-failure-text {\n flex: 1 1 auto;\n }\n\n .nxr-viewer-failure-close {\n border: 0;\n background: transparent;\n color: inherit;\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n }\n `,\n})\nexport class NxrReportViewerComponent implements OnChanges {\n /** Each request's URL, with `{action}` in place of the host action it goes to. */\n readonly requestUrl = input('');\n /** The host action that answers the first request, and so names the report to open. */\n readonly action = input('');\n /** Sent to the host with every request, as JSON, when it is truthy. */\n readonly properties = input<unknown>(null);\n /** The viewer's width; `100%` when it is not given. */\n readonly width = input<string | null>(null);\n /** The viewer's height; 650px when the report panel scrolls, otherwise `100%`. */\n readonly height = input<string | null>(null);\n /** The viewer's background; `White` when it is not given. */\n readonly backgroundColor = input<string | null>('White');\n /** Styles for the viewer's root element. Width, height and background take precedence over it. */\n readonly style = input<string | null>(null);\n /** Called for every request; each key of an object it returns becomes a form field. */\n readonly postParametersFunction = input<NxrPostParametersFunction | null>(null);\n\n /** Emits after each report is loaded. */\n readonly loaded = output<void>();\n /** Emits every failure the viewer puts on show. */\n readonly error = output<NxrViewerFailure>();\n\n protected readonly session = inject(NxrViewerSessionService);\n\n /** Stimulsoft's `api` object: what a host calls to drive the viewer from outside. */\n readonly api: NxrViewerApi = this.buildApi();\n\n private readonly appearance = computed(() => this.session.options()?.appearance ?? null);\n\n protected readonly toolbarVisible = computed(\n () => this.session.options()?.toolbar.visible !== false,\n );\n protected readonly pageCss = computed(() => this.session.report()?.pageCss ?? '');\n protected readonly showPageShadow = computed(() => this.appearance()?.showPageShadow === true);\n protected readonly pageBorder = computed(() => {\n const color = this.appearance()?.pageBorderColor;\n return color ? `1px solid ${color}` : null;\n });\n\n /** Stimulsoft aligns the pages with the report panel's text alignment; `Default` means centred. */\n protected readonly pageAlignment = computed(() => {\n switch (this.appearance()?.pageAlignment) {\n case 'Left':\n return 'left';\n case 'Right':\n return 'right';\n default:\n return 'center';\n }\n });\n\n /** The report panel scrolls inside the viewer only when the server asks for scrollbars. */\n protected readonly pagesOverflow = computed(() =>\n this.appearance()?.scrollbarsMode ? 'auto' : 'hidden',\n );\n\n protected readonly rootWidth = computed(() => this.width() ?? '100%');\n protected readonly rootBackgroundColor = computed(() => this.backgroundColor() ?? 'White');\n protected readonly rootHeight = computed(() => {\n const given = this.height();\n if (given !== null) return given;\n return this.appearance()?.scrollbarsMode ? '650px' : '100%';\n });\n\n constructor() {\n this.session.reportLoaded\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.loaded.emit());\n this.session.failed\n .pipe(takeUntilDestroyed())\n .subscribe((failure) => this.error.emit(failure));\n }\n\n /**\n * A change to any input reloads, as Stimulsoft's viewer does: its `ngOnChanges` never looks at\n * which input changed, so even a width change asks the server for the options and the report\n * again. Matching that keeps a host's reload behaviour the same across the swap.\n */\n ngOnChanges(): void {\n this.session.open(this.context(), this.action());\n }\n\n /**\n * The getters read the session's signals, so a host that asks between renders gets what is on\n * screen now. Built from a captured session rather than `this`, because `this` inside an object\n * literal's accessor is the literal.\n */\n private buildApi(): NxrViewerApi {\n const session = this.session;\n return {\n get currentPage(): number {\n return session.pageIndex();\n },\n set currentPage(value: number) {\n session.goToPage(value);\n },\n get pagesCount(): number {\n return session.pageCount();\n },\n get reportType(): string {\n return 'Report';\n },\n };\n }\n\n private context(): NxrRequestContext {\n return {\n requestUrl: this.requestUrl(),\n properties: this.properties(),\n postParametersFunction: this.postParametersFunction(),\n strings: NXR_ENGLISH,\n };\n }\n}\n","/*\n * Public API Surface of @nexterajs/report-viewer\n */\n\nexport { NXR_VIEWER_PROTOCOL } from './lib/protocol/nxr-protocol.const';\nexport {\n NxrReportViewerComponent,\n type NxrViewerApi,\n} from './lib/viewer/nxr-report-viewer.component';\nexport type { NxrViewerFailure } from './lib/protocol/nxr-protocol.model';\nexport type {\n NxrPostParametersData,\n NxrPostParametersFunction,\n} from './lib/protocol/nxr-viewer-client.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;AAAA;;;AAGG;AACI,MAAM,mBAAmB,GAAG;;ACJnC;;;;;;;AAOG;AAEH;;;AAGG;AACH,MAAM,gBAAgB,GAAG;IACvB,QAAQ;IACR,UAAU;IACV,UAAU;IACV,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,OAAO;IACP,UAAU;IACV,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,SAAS;IACT,MAAM;IACN,KAAK;IACL,SAAS;AACV,CAAA,CAAC,IAAI,CAAC,GAAG,CAAC;AAEX;AACA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,MAAM;IACN,YAAY;IACZ,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,YAAY;AACb,CAAA,CAAC;AAEF;AACA,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEtD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAEhE;;;;AAIG;AACG,SAAU,SAAS,CAAC,SAAiB,EAAE,KAAa,EAAA;IACxD,IAAI,OAAO,GAAG,EAAE;AAChB,IAAA,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE;AAC7B,QAAA,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI;YAAE,OAAO,IAAI,SAAS;IAC1D;AACA,IAAA,MAAM,MAAM,GAAG,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE;IACzE,IAAI,MAAM,KAAK,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;AAAE,QAAA,OAAO,IAAI;AACjE,IAAA,OAAO,SAAS,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;AACnF;AAEA;;;AAGG;AACG,SAAU,aAAa,CAAC,IAAY,EAAE,QAAkB,EAAA;IAC5D,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC;AACnD,IAAA,QAAQ,CAAC,SAAS,GAAG,IAAI;AACzB,IAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO;AAChC,IAAA,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,EAAE;QAC5E,OAAO,CAAC,MAAM,EAAE;IAClB;AACA,IAAA,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE;AAC/D,QAAA,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YACtD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE;AACzC,YAAA,MAAM,MAAM,GACV,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;AACrB,gBAAA,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5B,iBAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;AACjE,YAAA,IAAI,MAAM;AAAE,gBAAA,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,CAAC;QACrD;IACF;AACA,IAAA,OAAO,OAAO;AAChB;AAQA;;;;AAIG;AACH,SAAS,eAAe,CAAC,SAAwB,EAAA;AAC/C,IAAA,KAAK,IAAI,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;QACnE,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;AACtC,QAAA,IAAI,IAAI,YAAY,YAAY,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;AACpE,YAAA,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;QAC7B;aAAO,IAAI,UAAU,IAAI,IAAI,IAAI,EAAE,IAAI,YAAY,gBAAgB,CAAC,EAAE;YACpE,eAAe,CAAC,IAAgC,CAAC;QACnD;IACF;AACF;AAEA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB;AAE/C;;;;;AAKG;AACG,SAAU,YAAY,CAAC,OAAe,EAAA;IAC1C,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,KAAK,GAAG,IAAI,aAAa,EAAE;AAC3B,QAAA,IAAI;AACF,YAAA,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC;YAC1B,eAAe,CAAC,KAAK,CAAC;QACxB;AAAE,QAAA,MAAM;AACN,YAAA,KAAK,GAAG,IAAI,aAAa,EAAE;QAC7B;AACA,QAAA,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC;IAC5B;AACA,IAAA,OAAO,KAAK;AACd;;AC3HA;AACA,MAAM,cAAc,GAAG,0CAA0C;AAEjE;;;;;;;AAOG;MAsBU,sBAAsB,CAAA;;IAExB,IAAI,GAAG,KAAK,CAAC,QAAQ;6EAAe;;IAEpC,IAAI,GAAG,KAAK,CAAgB,IAAI;6EAAC;;IAEjC,GAAG,GAAG,KAAK,CAAC,QAAQ;4EAAU;AAEtB,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,GAAI,MAAM,CAAC,UAAU,CAAC,CAAC,aAA6B,CAAC,YAAY,CAAC;AACrF,QAAA,IAAI,EAAE,MAAM;AACb,KAAA,CAAC;AAEF,IAAA,WAAW,CAAC,OAAsB,EAAA;AAChC,QAAA,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE;AAClB,YAAA,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;QACzF;AACA,QAAA,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE;AACnB,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;AACxB,YAAA,IAAI,IAAI,KAAK,IAAI,EAAE;AACjB,gBAAA,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;YAC7B;iBAAO;AACL,gBAAA,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/D;QACF;IACF;uGAzBW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,sBAAsB,4nBAlBvB,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,+FAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAkBD,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBArBlC,SAAS;+BACE,iBAAiB,EAAA,UAAA,EACf,IAAI,EAAA,QAAA,EACN,EAAE,mBAUK,uBAAuB,CAAC,MAAM,EAAA,IAAA,EACzC;AACJ,wBAAA,KAAK,EAAE,iBAAiB;AACxB,wBAAA,kBAAkB,EAAE,mBAAmB;AACvC,wBAAA,kBAAkB,EAAE,oBAAoB;AACxC,wBAAA,mBAAmB,EAAE,qBAAqB;AAC3C,qBAAA,EAAA,MAAA,EAAA,CAAA,+FAAA,CAAA,EAAA;;;AC3CH;;;;;AAKG;AACI,MAAM,WAAW,GAAG;;AAEzB,IAAA,IAAI,EAAE,MAAM;;AAEZ,IAAA,MAAM,EAAE,IAAI;AACZ,IAAA,SAAS,EAAE,YAAY;AACvB,IAAA,QAAQ,EAAE,eAAe;AACzB,IAAA,QAAQ,EAAE,WAAW;AACrB,IAAA,QAAQ,EAAE,WAAW;AACrB,IAAA,gBAAgB,EAAE,yCAAyC;AAC3D,IAAA,WAAW,EAAE,kDAAkD;AAC/D,IAAA,YAAY,EAAE,sDAAsD;AACpE,IAAA,cAAc,EAAE,oEAAoE;AACpF,IAAA,aAAa,EACX,oFAAoF;CACvF;AAID;SACgB,YAAY,CAAC,QAAgB,EAAE,GAAG,MAA2B,EAAA;AAC3E,IAAA,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE,KAAa,KAC/D,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,CAC5E;AACH;;ACjBA;;;AAGG;AACG,MAAO,uBAAwB,SAAQ,KAAK,CAAA;AAErC,IAAA,MAAA;AAEA,IAAA,QAAA;AAHX,IAAA,WAAA,CACW,MAAuB;;AAEvB,IAAA,QAAA,GAAmB,mBAAmB,EAAA;AAE/C,QAAA,KAAK,CAAC,CAAA,IAAA,EAAO,MAAM,uCAAuC,mBAAmB,CAAA,SAAA,CAAW,CAAC;QAJhF,IAAA,CAAA,MAAM,GAAN,MAAM;QAEN,IAAA,CAAA,QAAQ,GAAR,QAAQ;AAGjB,QAAA,IAAI,CAAC,IAAI,GAAG,yBAAyB;IACvC;AACD;AAED;AACM,MAAO,eAAgB,SAAQ,KAAK,CAAA;AACnB,IAAA,OAAA;AAArB,IAAA,WAAA,CAAqB,OAAe,EAAA;AAClC,QAAA,KAAK,CAAC,CAAA,iBAAA,EAAoB,OAAO,CAAA,SAAA,CAAW,CAAC;QAD1B,IAAA,CAAA,OAAO,GAAP,OAAO;AAE1B,QAAA,IAAI,CAAC,IAAI,GAAG,iBAAiB;IAC/B;AACD;AAID,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;AAE/E,SAAS,QAAQ,CAAC,KAAc,EAAA;AAC9B,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAC7E;AAEA,SAAS,OAAO,CAAC,KAAc,EAAA;AAC7B,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAC3E;AAEA,SAAS,QAAQ,CAAC,KAAc,EAAA;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC5D;AAEA,SAAS,QAAQ,CAAC,KAAc,EAAA;AAC9B,IAAA,QACE,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACpB,QAAA,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACpB,QAAA,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACxB,QAAA,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAE7B;AAEA,SAAS,OAAO,CAAC,KAAc,EAAA;AAC7B,IAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK;AAClC,IAAA,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC;AAC5B,IAAA,QACE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAC5B,QAAA,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AACpB,QAAA,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,QAAQ,CAAC;AAEnD;AAEA,SAAS,UAAU,CAAC,KAAc,EAAA;AAChC,IAAA,QACE,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAC5B,QAAA,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;AAC9B,QAAA,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;AAEnC;AAEA,SAAS,SAAS,CAAC,KAAc,EAAE,OAAyB,EAAA;AAC1D,IAAA,QACE,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,QAAQ;AAClC,QAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAC3B,QAAA,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAE7B;AAEA;AACM,SAAU,cAAc,CAAC,IAAa,EAAA;AAC1C,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AAAE,QAAA,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC;IAC3E,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IACvD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,mBAAmB,EAAE;AAC1D,QAAA,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,EAAE,QAAQ,CAAC;IAClE;AACA,IAAA,MAAM,KAAK,GACT,QAAQ,KAAK,mBAAmB;QAChC,OAAO,KAAK,KAAK,QAAQ;AACzB,QAAA,KAAK,KAAK,EAAE;QACZ,QAAQ,CAAC,OAAO,CAAC;AACjB,QAAA,aAAa,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;SACvD,YAAY,KAAK,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;AACnD,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC;AAClE,IAAA,OAAO,IAAsC;AAC/C;AAEA;AACM,SAAU,UAAU,CAAC,IAAa,EAAA;AACtC,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AAAE,QAAA,MAAM,IAAI,uBAAuB,CAAC,WAAW,CAAC;AACnE,IAAA,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI;AAC5E,IAAA,MAAM,KAAK,GACT,OAAO,UAAU,KAAK,QAAQ;QAC9B,OAAO,CAAC,SAAS,CAAC;AAClB,QAAA,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAK,CAAC,MAAM,KAAK,SAAS;AAC1B,QAAA,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;AACvB,QAAA,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AACxB,QAAA,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,OAAO,KAAK,QAAQ;SAC1B,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;AACjD,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,MAAM,IAAI,uBAAuB,CAAC,WAAW,CAAC;IAC1D,OAAO;AACL,QAAA,GAAI,IAAmC;QACvC,SAAS,EAAG,SAAwC,IAAI,IAAI;KAC7D;AACH;AAEA;AACM,SAAU,SAAS,CAAC,IAAa,EAAA;AACrC,IAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;AAAE,QAAA,MAAM,IAAI,uBAAuB,CAAC,UAAU,CAAC;AACjE,IAAA,OAAO,IAAI;AACb;AAEA;AACM,SAAU,QAAQ,CAAC,IAAa,EAAA;AACpC,IAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS;IACtD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACtE,QAAA,MAAM,IAAI,uBAAuB,CAAC,MAAM,CAAC;AAC3C,IAAA,OAAO,IAAgC;AACzC;AAEA;AACM,SAAU,eAAe,CAAC,IAAa,EAAA;AAC3C,IAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS;AACzD,QAAA,MAAM,IAAI,uBAAuB,CAAC,aAAa,CAAC;AAClD,IAAA,OAAO,IAAuC;AAChD;AAEA,SAAS,SAAS,CAAC,MAAc,EAAE,OAAe,EAAA;AAChD,IAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;AAC5E;AAEA;;;;;;;AAOG;AACG,SAAU,WAAW,CACzB,OAAgB,EAChB,MAAuB,EACvB,UAA4B,WAAW,EAAA;AAEvC,IAAA,IAAI,OAAO,YAAY,iBAAiB,EAAE;AACxC,QAAA,MAAM,IAAI,GAAY,OAAO,CAAC,KAAK;QACnC,IACE,QAAQ,CAAC,IAAI,CAAC;AACd,YAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,OAAO;AAC1B,YAAA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ;AAChC,YAAA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ;AACnC,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,SAAS,EACtC;YACA,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI;YAC5E,OAAO;gBACL,MAAM,EAAE,OAAO,CAAC,MAAM;AACtB,gBAAA,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;AAClB,gBAAA,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;AACxB,gBAAA,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC;gBAC5B,OAAO;aACR;QACH;AACA,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;QACvE,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG;AAC/C,YAAA,OAAO,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AACnE,QAAA,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACrF;AACA,IAAA,IAAI,OAAO,YAAY,eAAe,EAAE;AACtC,QAAA,OAAO,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E;AACA,IAAA,IAAI,OAAO,YAAY,uBAAuB,EAAE;AAC9C,QAAA,OAAO,OAAO,CAAC,QAAQ,KAAK;AAC1B,cAAE,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,QAAQ,EAAE,mBAAmB,CAAC;AACzF,cAAE,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE;IACA,OAAO,SAAS,CAAC,CAAC,EAAE,OAAO,YAAY,KAAK,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AACnF;;ACpIA;;;AAGG;AACI,MAAM,iCAAiC,GAAG,IAAI;AAErD;;;AAGG;AACG,SAAU,SAAS,CAAC,UAAkB,EAAE,MAAc,EAAA;IAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC;AAC5D,IAAA,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IACtD,IAAI,OAAO,GAAG,CAAC;AAAE,QAAA,OAAO,GAAG;IAC3B,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAA,EAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAA,CAAE;AAC7E;AAEA;;;;AAIG;AACG,SAAU,aAAa,CAAC,OAAyB,EAAE,MAAuB,EAAA;IAC9E,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO;AAChE,IAAA,MAAM,YAAY,GAAG,SAAS,IAAI,WAAW;AAC7C,IAAA,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,KAAK,MAAM,GAAG,YAAY,GAAG,WAAW;IACpF,IAAI,MAAM,KAAK,WAAW;AAAE,QAAA,OAAO,YAAY;IAC/C,IAAI,MAAM,KAAK,cAAc;QAAE,OAAO,YAAY,IAAI,WAAW;AACjE,IAAA,OAAO,WAAW;AACpB;AAEA;AACM,SAAU,UAAU,CAAC,WAA0B,EAAA;AACnD,IAAA,IAAI,CAAC,WAAW;AAAE,QAAA,OAAO,IAAI;IAC7B,MAAM,OAAO,GAAG,kCAAkC,CAAC,IAAI,CAAC,WAAW,CAAC;IACpE,IAAI,OAAO,EAAE;AACX,QAAA,IAAI;YACF,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C;AAAE,QAAA,MAAM;;QAER;IACF;IACA,MAAM,KAAK,GAAG,uCAAuC,CAAC,IAAI,CAAC,WAAW,CAAC;IACvE,OAAO,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI;AACrD;AAEA,SAAS,SAAS,CAAC,OAAgC,EAAA;IACjD,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,CAAC;IAC3D,OAAO,OAAO,GAAG,CAAC,GAAG,OAAO,GAAG,iCAAiC;AAClE;AAEA,SAAS,MAAM,CACb,OAA0B,EAC1B,MAAuB,EACvB,OAAgC,EAChC,UAAyB,EAAA;AAEzB,IAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;AAC3B,IAAA,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,IAAI,OAAO,EAAE;AACX,QAAA,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM;QAC7E,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,GAAG,CACN,eAAe,EACf,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC,CACxF;IACH;AACA,IAAA,IAAI,UAAU;AAAE,QAAA,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC1E,IAAI,OAAO,CAAC,UAAU;AAAE,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAClF,IAAA,MAAM,KAAK,GAAG,OAAO,CAAC,sBAAsB,GAAG,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,CAAC;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;AAC/C,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACjD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,YAAY,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D;IACF;AACA,IAAA,OAAO,IAAI;AACb;AAEA;AACA,eAAe,eAAe,CAAC,OAAgB,EAAA;AAC7C,IAAA,IAAI,EAAE,OAAO,YAAY,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,YAAY,IAAI,CAAC;AAAE,QAAA,OAAO,OAAO;IAC/F,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;IACvC,IAAI,IAAI,GAAY,IAAI;AACxB,IAAA,IAAI;AACF,QAAA,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB;AAAE,IAAA,MAAM;;IAER;IACA,OAAO,IAAI,iBAAiB,CAAC;AAC3B,QAAA,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU,EAAE,OAAO,CAAC,UAAU;AAC9B,QAAA,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,SAAS;AAC9B,KAAA,CAAC;AACJ;AAEA;;;;AAIG;MAEU,sBAAsB,CAAA;AAChB,IAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;;IAG1C,UAAU,CAAC,OAA0B,EAAE,MAAc,EAAA;AACnD,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;IACpF;;AAGA,IAAA,SAAS,CACP,OAA0B,EAC1B,OAAyB,EACzB,KAAoB,EAAA;QAEpB,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC;AAC9D,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,UAAU,CAAC;IACxF;;AAGA,IAAA,QAAQ,CACN,OAA0B,EAC1B,OAAyB,EACzB,KAAmB,EAAA;QAEnB,OAAO,IAAI,CAAC,IAAI,CACd,OAAO,EACP,UAAU,EACV,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAC1C,OAAO,EACP,KAAK,EACL,SAAS,CACV;IACH;;AAGA,IAAA,IAAI,CACF,OAA0B,EAC1B,OAAyB,EACzB,UAA6B,EAAA;QAE7B,OAAO,IAAI,CAAC,IAAI,CACd,OAAO,EACP,MAAM,EACN,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,EACtC,OAAO,EACP,UAAU,EACV,QAAQ,CACT;IACH;;IAGA,WAAW,CACT,OAA0B,EAC1B,OAAyB,EAAA;QAEzB,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC;AAChE,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,CAAC;IACtF;;AAGA,IAAA,YAAY,CACV,OAA0B,EAC1B,OAAyB,EACzB,MAAc,EAAA;AAEd,QAAA,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACzF,OAAO,KAAK,CAAC,MACX,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE;AACxE,YAAA,OAAO,EAAE,UAAU;AACnB,YAAA,YAAY,EAAE,MAAM;SACrB,CAAC,CACH,CAAC,IAAI,CACJ,GAAG,CAAC,CAAC,QAAQ,MAAM;YACjB,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;AACnC,YAAA,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE;YACvE,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;SACxD,CAAC,CAAC,EACH,UAAU,CAAC,CAAC,OAAgB,KAC1B,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CACjC,SAAS,CAAC,CAAC,QAAQ,KACjB,UAAU,CAAC,MAAM,WAAW,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CACzE,CACF,CACF,CACF;IACH;IAEQ,IAAI,CACV,OAA0B,EAC1B,MAAuB,EACvB,UAAkB,EAClB,OAAgC,EAChC,UAAyB,EACzB,IAA0B,EAAA;AAE1B,QAAA,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;AAClC,QAAA,OAAO,KAAK,CAAC,MACX,IAAI,CAAC,IAAI,CAAC,IAAI,CACZ,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,EACzC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,CAC7C,CACF,CAAC,IAAI,CACJ,OAAO,CAAC;YACN,KAAK,EAAE,OAAO,GAAG,IAAI;AACrB,YAAA,IAAI,EAAE,MAAM,UAAU,CAAC,MAAM,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;AAC3D,SAAA,CAAC,EACF,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,EACzB,UAAU,CAAC,CAAC,OAAgB,KAC1B,UAAU,CAAC,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAChE,CACF;IACH;uGA/GW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAtB,sBAAsB,EAAA,CAAA;;2FAAtB,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBADlC;;;AClJD;AACO,MAAM,iBAAiB,GAAG,OAAO;AAWxC,SAAS,SAAS,CAAC,KAA0B,EAAE,MAA6B,EAAA;IAC1E,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC;AACpF,IAAA,OAAO,KAAK;AACd;AAEA;;;;;AAKG;MAEU,uBAAuB,CAAA;AACjB,IAAA,MAAM,GAAG,MAAM,CAAC,sBAAsB,CAAC;IAEvC,YAAY,GAAG,MAAM,CAA0B,IAAI;qFAAC;IACpD,WAAW,GAAG,MAAM,CAAyB,IAAI;oFAAC;AAClD,IAAA,SAAS,GAAG,MAAM,CAA8B,IAAI,GAAG,EAAE;kFAAC;IAC1D,cAAc,GAAG,MAAM,CAAC,CAAC;uFAAC;IAC1B,YAAY,GAAG,MAAM,CAAC,CAAC;qFAAC;IACxB,YAAY,GAAG,MAAM,CAA0B,IAAI;qFAAC;;AAG5D,IAAA,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE;;AAExC,IAAA,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE;;AAEtC,IAAA,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;;AAE5C,IAAA,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE;;AAExC,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,IAAI,CAAC;kFAAC;;IAE9D,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC;6EAAC;;AAE9C,IAAA,SAAS,GAAG,QAAQ,CAAsB,MAAK;AACtD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE;AACjC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE;AACnC,QAAA,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,MAAM,CAAC,SAAS;AAAE,YAAA,OAAO,IAAI;QACrD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE;IACxF,CAAC;kFAAC;;AAGO,IAAA,YAAY,GAAG,IAAI,OAAO,EAAQ;;AAElC,IAAA,MAAM,GAAG,IAAI,OAAO,EAAoB;IAEzC,OAAO,GAA6B,IAAI;IACxC,OAAO,GAA4B,IAAI;;AAEvC,IAAA,QAAQ,GAAG,IAAI,YAAY,EAAE;;AAE7B,IAAA,YAAY,GAAG,IAAI,YAAY,EAAE;AACjC,IAAA,SAAS,GAAG,YAAY,CAAC,KAAK;AACrB,IAAA,aAAa,GAAG,IAAI,GAAG,EAAU;;IAE1C,UAAU,GAAG,KAAK;IAClB,SAAS,GAAG,KAAK;AAEzB,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAK;AAChC,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;YACrB,IAAI,CAAC,KAAK,EAAE;AACZ,YAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;AAC5B,YAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;AACxB,QAAA,CAAC,CAAC;IACJ;;IAGA,IAAI,CAAC,OAA0B,EAAE,MAAc,EAAA;QAC7C,IAAI,IAAI,CAAC,SAAS;YAAE;QACpB,IAAI,CAAC,KAAK,EAAE;AACZ,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;AACtB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;AAC7B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1B,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,UAAU;YAAE;AACzB,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,KAAI;AACpE,YAAA,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;AAChE,YAAA,IAAI,CAAC,OAAO,GAAG,OAAO;YACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACrC,YAAA,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC;YACrC,IAAI,CAAC,MAAM,EAAE;AACf,QAAA,CAAC,CAAC;IACJ;AAEA;;;AAGG;AACH,IAAA,QAAQ,CAAC,KAAa,EAAA;AACpB,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAClF,QAAA,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ;YAAE;AACjC,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;AAC9B,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;IACtB;;IAGA,cAAc,GAAA;AACZ,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B;AAEA;;;AAGG;IACK,MAAM,GAAA;QACZ,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;AAC9C,QAAA,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;AAC7D,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC;AACpB,aAAA,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK;AACjC,aAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,MAAM,KAAI;AACtC,YAAA,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;AAC/B,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,EAAE;AACtC,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;AAC1D,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;AAC5B,YAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;AACzF,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;YACxB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AACtC,QAAA,CAAC,CAAC;IACJ;;AAGQ,IAAA,QAAQ,CAAC,KAAa,EAAA;QAC5B,IAAI,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;YAC3F;QACF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;AAC9C,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;AAC7B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC;AAClB,aAAA,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;AAC1D,aAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACzD,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CACnB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,MAAM,KAC/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CACjE,CACF;IACH;AAEA;;;AAGG;AACK,IAAA,KAAK,CACX,OAAsB,EACtB,WAAoB,EACpB,IAAwB,EAAA;AAExB,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG;aAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC;AACnE,aAAA,SAAS,CAAC;YACT,IAAI;AACJ,YAAA,KAAK,EAAE,CAAC,OAAyB,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;AACtE,SAAA,CAAC;AACJ,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC;AAC/B,QAAA,OAAO,YAAY;IACrB;AAEA;;;;AAIG;IACK,IAAI,CAAC,OAAyB,EAAE,WAAoB,EAAA;QAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,IAAI,WAAW,EAAE;AAClD,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;AACpB,gBAAA,IAAI,CAAC,UAAU,GAAG,IAAI;gBACtB,IAAI,CAAC,MAAM,EAAE;YACf;YACA;QACF;AACA,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC;AAC9B,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B;;IAGQ,cAAc,CAAC,OAA0B,EAAE,OAAyB,EAAA;QAC1E,MAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM;AAClE,QAAA,IAAI,CAAC,oBAAoB,IAAI,SAAS,KAAK,MAAM;YAAE;AACnD,QAAA,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,iBAAiB;AACxC,aAAA,IAAI,CACH,UAAU,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;AAE1F,aAAA,SAAS,EAAE;IAChB;;IAGQ,KAAK,GAAA;AACX,QAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;AAC3B,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE;AAClC,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,EAAE;AACtC,QAAA,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;AAC5B,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;AACnB,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;IACzB;IAEQ,UAAU,GAAA;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO;AAAE,YAAA,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC;AACrF,QAAA,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;IACzD;uGA9LW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAvB,uBAAuB,EAAA,CAAA;;2FAAvB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBADnC;;;AC3CD;AACA,MAAM,iBAAiB,GAAG,EAAE;AAE5B;;;;;;;;;;;;;AAaG;MAwJU,yBAAyB,CAAA;;IAE3B,OAAO,GAAG,KAAK,CAA0B,IAAI;gFAAC;;IAE9C,SAAS,GAAG,KAAK,CAAC,CAAC;kFAAC;;IAEpB,SAAS,GAAG,KAAK,CAAC,CAAC;kFAAC;;IAEpB,IAAI,GAAG,KAAK,CAAC,KAAK;6EAAC;;IAEnB,OAAO,GAAG,KAAK,CAAmB,WAAW;gFAAC;;IAG9C,QAAQ,GAAG,MAAM,EAAU;IAEjB,YAAY,GAAG,iBAAiB;AAElC,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,IAAI,IAAI;gFAAC;AACzD,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,IAAI,IAAI;mFAAC;AAEhF;;;AAGG;AACc,IAAA,kBAAkB,GAAG,QAAQ,CAAC,MAAK;AAClD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE;AACpC,QAAA,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU;AAAE,YAAA,OAAO,IAAI;AACxC,QAAA,IAAI,OAAO,CAAC,QAAQ,KAAK,eAAe;AAAE,YAAA,OAAO,IAAI;AACrD,QAAA,QACE,OAAO,CAAC,QAAQ,KAAK,YAAY;YACjC,CAAC,UAAU,CAAC,cAAc;AAC1B,YAAA,CAAC,UAAU,CAAC,cAAc;IAE9B,CAAC;2FAAC;AAEiB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,mBAAmB,KAAK,IAAI;sFAAC;AAC5E,IAAA,gBAAgB,GAAG,QAAQ,CAC5C,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,sBAAsB,KAAK,IAAI;yFACtD;AACkB,IAAA,eAAe,GAAG,QAAQ,CAC3C,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,sBAAsB,KAAK,IAAI;wFACtD;AACkB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,KAAK,IAAI;qFAAC;AAC1E,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,KAAK,IAAI;qFAAC;IAE1E,OAAO,GAAG,QAAQ,CACnC,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;gFACxE;IACkB,KAAK,GAAG,QAAQ,CACjC,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC;8EAC3F;IACkB,mBAAmB,GAAG,QAAQ,CAC/C,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;4FACxE;AAEkB,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,IAAI,IAAI;wFAAC;AACzE,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,IAAI,IAAI;kFAAC;AAC7D,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,IAAI,IAAI;mFAAC;;AAG/D,IAAA,MAAM,GAAG,QAAQ,CAAC,MAAK;AACxC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,IAAI,CAAC,OAAO,CAAC,WAAW;AAAE,YAAA,OAAO,IAAI;AACxF,QAAA,OAAO,CAAA,UAAA,EAAa,OAAO,CAAC,WAAW,EAAE;IAC3C,CAAC;+EAAC;AAEiB,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AAChD,QAAA,QAAQ,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS;AAC/B,YAAA,KAAK,QAAQ;AACX,gBAAA,OAAO,QAAQ;AACjB,YAAA,KAAK,OAAO;AACV,gBAAA,OAAO,UAAU;AACnB,YAAA;AACE,gBAAA,OAAO,YAAY;;IAEzB,CAAC;uFAAC;AAEF;;;AAGG;AACO,IAAA,SAAS,CAAC,KAAY,EAAA;AAC9B,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,MAA0B;AAC5C,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;AAC5C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AACrF,QAAA,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IACrB;AAEU,IAAA,IAAI,CAAC,KAAa,EAAA;QAC1B,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,EAAE,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE;YAAE;AACzF,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;IAC3B;uGA7FW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAzB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,EAAA,wBAAA,EAAA,mBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,aAAA,EAAA,aAAA,EAAA,mBAAA,EAAA,cAAA,EAAA,uBAAA,EAAA,kBAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,EAAA,cAAA,EAAA,oBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAzI1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,81BAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAwEU,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAvJrC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,oBAAoB,cAClB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,IAAA,EACzC;AACJ,wBAAA,KAAK,EAAE,oBAAoB;AAC3B,wBAAA,IAAI,EAAE,SAAS;AACf,wBAAA,0BAA0B,EAAE,mBAAmB;AAC/C,wBAAA,gBAAgB,EAAE,UAAU;AAC5B,wBAAA,eAAe,EAAE,aAAa;AAC9B,wBAAA,qBAAqB,EAAE,cAAc;AACrC,wBAAA,yBAAyB,EAAE,kBAAkB;AAC7C,wBAAA,kBAAkB,EAAE,QAAQ;qBAC7B,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiET,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,81BAAA,CAAA,EAAA;;;ACjEH;;;;;;;;AAQG;MA6GU,wBAAwB,CAAA;;IAE1B,UAAU,GAAG,KAAK,CAAC,EAAE;mFAAC;;IAEtB,MAAM,GAAG,KAAK,CAAC,EAAE;+EAAC;;IAElB,UAAU,GAAG,KAAK,CAAU,IAAI;mFAAC;;IAEjC,KAAK,GAAG,KAAK,CAAgB,IAAI;8EAAC;;IAElC,MAAM,GAAG,KAAK,CAAgB,IAAI;+EAAC;;IAEnC,eAAe,GAAG,KAAK,CAAgB,OAAO;wFAAC;;IAE/C,KAAK,GAAG,KAAK,CAAgB,IAAI;8EAAC;;IAElC,sBAAsB,GAAG,KAAK,CAAmC,IAAI;+FAAC;;IAGtE,MAAM,GAAG,MAAM,EAAQ;;IAEvB,KAAK,GAAG,MAAM,EAAoB;AAExB,IAAA,OAAO,GAAG,MAAM,CAAC,uBAAuB,CAAC;;AAGnD,IAAA,GAAG,GAAiB,IAAI,CAAC,QAAQ,EAAE;AAE3B,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,UAAU,IAAI,IAAI;mFAAC;AAErE,IAAA,cAAc,GAAG,QAAQ,CAC1C,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,KAAK,KAAK;uFACxD;AACkB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,IAAI,EAAE;gFAAC;AAC9D,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,KAAK,IAAI;uFAAC;AAC3E,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,eAAe;QAChD,OAAO,KAAK,GAAG,CAAA,UAAA,EAAa,KAAK,CAAA,CAAE,GAAG,IAAI;IAC5C,CAAC;mFAAC;;AAGiB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAK;AAC/C,QAAA,QAAQ,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa;AACtC,YAAA,KAAK,MAAM;AACT,gBAAA,OAAO,MAAM;AACf,YAAA,KAAK,OAAO;AACV,gBAAA,OAAO,OAAO;AAChB,YAAA;AACE,gBAAA,OAAO,QAAQ;;IAErB,CAAC;sFAAC;;AAGiB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAC1C,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,GAAG,MAAM,GAAG,QAAQ;sFACtD;IAEkB,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,IAAI,MAAM;kFAAC;IAClD,mBAAmB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,IAAI,OAAO;4FAAC;AACvE,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AAC5C,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;QAC3B,IAAI,KAAK,KAAK,IAAI;AAAE,YAAA,OAAO,KAAK;AAChC,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,GAAG,OAAO,GAAG,MAAM;IAC7D,CAAC;mFAAC;AAEF,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,OAAO,CAAC;aACV,IAAI,CAAC,kBAAkB,EAAE;aACzB,SAAS,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,CAAC;aACV,IAAI,CAAC,kBAAkB,EAAE;AACzB,aAAA,SAAS,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD;AAEA;;;;AAIG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAClD;AAEA;;;;AAIG;IACK,QAAQ,GAAA;AACd,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;QAC5B,OAAO;AACL,YAAA,IAAI,WAAW,GAAA;AACb,gBAAA,OAAO,OAAO,CAAC,SAAS,EAAE;YAC5B,CAAC;YACD,IAAI,WAAW,CAAC,KAAa,EAAA;AAC3B,gBAAA,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzB,CAAC;AACD,YAAA,IAAI,UAAU,GAAA;AACZ,gBAAA,OAAO,OAAO,CAAC,SAAS,EAAE;YAC5B,CAAC;AACD,YAAA,IAAI,UAAU,GAAA;AACZ,gBAAA,OAAO,QAAQ;YACjB,CAAC;SACF;IACH;IAEQ,OAAO,GAAA;QACb,OAAO;AACL,YAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;AAC7B,YAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;AAC7B,YAAA,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EAAE;AACrD,YAAA,OAAO,EAAE,WAAW;SACrB;IACH;uGAjHW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,grCAvGxB,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ipBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA9CS,sBAAsB,6FAAE,yBAAyB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,WAAA,EAAA,WAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAwGhD,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBA5GpC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,mBAAmB,cACjB,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,WACtC,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,EAAA,SAAA,EACjD,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,EAAA,QAAA,EAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ipBAAA,CAAA,EAAA;;;AC9FH;;AAEG;;ACFH;;AAEG;;"}
|
|
1
|
+
{"version":3,"file":"nexterajs-report-viewer.mjs","sources":["../../../projects/nextera-report-viewer/src/lib/protocol/nxe-protocol.const.ts","../../../projects/nextera-report-viewer/src/lib/find/nxe-find.util.ts","../../../projects/nextera-report-viewer/src/lib/strings/nxe-viewer-strings.const.ts","../../../projects/nextera-report-viewer/src/lib/find/nxe-viewer-find-panel.component.ts","../../../projects/nextera-report-viewer/src/lib/page/nxe-page-html.util.ts","../../../projects/nextera-report-viewer/src/lib/page/nxe-report-page.component.ts","../../../projects/nextera-report-viewer/src/lib/protocol/nxe-protocol-reader.util.ts","../../../projects/nextera-report-viewer/src/lib/protocol/nxe-viewer-client.service.ts","../../../projects/nextera-report-viewer/src/lib/session/nxe-viewer-session.service.ts","../../../projects/nextera-report-viewer/src/lib/toolbar/nxe-viewer-toolbar.component.ts","../../../projects/nextera-report-viewer/src/lib/viewer/nxe-report-viewer.component.ts","../../../projects/nextera-report-viewer/src/public-api.ts","../../../projects/nextera-report-viewer/src/nexterajs-report-viewer.ts"],"sourcesContent":["/**\r\n * The version of the viewer protocol this package speaks: the `protocol` member of every\r\n * `AngularViewerData` answer from `Nextera.Report.AspNetCore`.\r\n */\r\nexport const NXE_VIEWER_PROTOCOL = 1;\r\n","/**\r\n * Finding text in the pages on screen, as Stimulsoft 2025.1.4's viewer does\r\n * (angular-viewer-panels-chrome.md §1.4-1.7), over each page's shadow root.\r\n *\r\n * A candidate is an element whose only child is a single text node; text split across elements is\r\n * never found. The element's HTML is compared, lower-cased unless the case must match, by a plain\r\n * substring test; a whole word needs no ASCII letter or digit on either side of the first occurrence.\r\n * Each hit gets one label, however often the text occurs in it.\r\n */\r\n\r\n/** The label every hit carries, and how the current one differs from the rest. */\r\nconst LABEL_CLASS = 'nxe-find-label';\r\nconst CURRENT_BORDER = 'red';\r\nconst OTHER_BORDER = 'rgb(138, 138, 138)';\r\n\r\n/** The inline position a hit had before its label made it a positioning box, to put back afterwards. */\r\nconst PREVIOUS_POSITION = 'nxeFindPosition';\r\n\r\nconst WORD_CHARACTER = /[A-Za-z0-9]/;\r\n\r\nexport interface NxeFindMatch {\r\n /** Upper and lower case count as different letters. */\r\n readonly matchCase: boolean;\r\n /** The text must stand as a word of its own. */\r\n readonly wholeWord: boolean;\r\n}\r\n\r\n/** Every element in the roots, in document order, that holds the text. */\r\nexport function findHits(\r\n roots: readonly ParentNode[],\r\n text: string,\r\n match: NxeFindMatch,\r\n): HTMLElement[] {\r\n const needle = match.matchCase ? text : text.toLowerCase();\r\n const hits: HTMLElement[] = [];\r\n if (needle === '') return hits;\r\n for (const root of roots) {\r\n for (const element of Array.from(root.querySelectorAll<HTMLElement>('*'))) {\r\n if (element.childNodes.length !== 1 || element.firstChild?.nodeType !== 3) continue;\r\n const html = match.matchCase ? element.innerHTML : element.innerHTML.toLowerCase();\r\n const at = html.indexOf(needle);\r\n if (at < 0) continue;\r\n if (match.wholeWord && !standsAlone(html, at, needle.length)) continue;\r\n hits.push(element);\r\n }\r\n }\r\n return hits;\r\n}\r\n\r\nfunction standsAlone(html: string, at: number, length: number): boolean {\r\n const before = at > 0 ? html[at - 1] : '';\r\n const after = html[at + length] ?? '';\r\n return !WORD_CHARACTER.test(before) && !WORD_CHARACTER.test(after);\r\n}\r\n\r\n/**\r\n * Labels each hit: a yellow box over the element, 60 % opaque so the text reads through it, with a\r\n * 2 px border that is red on the current hit and grey on the rest, inserted as the element's first\r\n * child and sized to it. The element becomes the label's positioning box; Stimulsoft makes it\r\n * `relative` unless it is positioned already, and it is here unless its computed position is\r\n * `static`, because this engine positions its page elements from the stylesheet.\r\n */\r\nexport function labelHits(hits: readonly HTMLElement[], current: number): void {\r\n hits.forEach((element, index) => {\r\n const label = element.ownerDocument.createElement('div');\r\n label.className = LABEL_CLASS;\r\n Object.assign(label.style, {\r\n position: 'absolute',\r\n left: '0px',\r\n top: '0px',\r\n width: `${Math.max(0, element.offsetWidth - 4)}px`,\r\n height: `${Math.max(0, element.offsetHeight - 4)}px`,\r\n zIndex: '150',\r\n opacity: '0.6',\r\n borderRadius: '3px',\r\n background: 'rgb(255, 255, 0)',\r\n border: `2px solid ${index === current ? CURRENT_BORDER : OTHER_BORDER}`,\r\n pointerEvents: 'none',\r\n } satisfies Partial<CSSStyleDeclaration>);\r\n if (getComputedStyle(element).position === 'static') {\r\n element.dataset[PREVIOUS_POSITION] = element.style.position;\r\n element.style.position = 'relative';\r\n }\r\n element.insertBefore(label, element.firstChild);\r\n });\r\n}\r\n\r\n/** Moves the current mark from one hit to another. */\r\nexport function markCurrent(hits: readonly HTMLElement[], previous: number, current: number): void {\r\n const border = (index: number, color: string): void => {\r\n const label = hits[index]?.querySelector<HTMLElement>(`:scope > .${LABEL_CLASS}`);\r\n if (label) label.style.borderColor = color;\r\n };\r\n border(previous, OTHER_BORDER);\r\n border(current, CURRENT_BORDER);\r\n}\r\n\r\n/** Removes every label from the roots, and gives back the position each hit had before it. */\r\nexport function clearHits(roots: readonly ParentNode[]): void {\r\n for (const root of roots) {\r\n for (const label of Array.from(root.querySelectorAll<HTMLElement>(`.${LABEL_CLASS}`))) {\r\n const element = label.parentElement;\r\n label.remove();\r\n if (element && PREVIOUS_POSITION in element.dataset) {\r\n element.style.position = element.dataset[PREVIOUS_POSITION] ?? '';\r\n delete element.dataset[PREVIOUS_POSITION];\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * Every caption and message the viewer shows, in its built-in English. A key in PascalCase is the name\r\n * Stimulsoft's viewer gives the same text, such as `PageOf`; a key in camelCase names a message only this\r\n * viewer has. The English is this package's own. A later plan lets a host's translation file replace any\r\n * of them, so code reads them from an `NxeViewerStrings` value wherever one is at hand.\r\n */\r\nexport const NXE_ENGLISH = {\r\n /** The label before the page-number box. */\r\n Page: 'Page',\r\n /** The label between the page-number box and the page count. */\r\n PageOf: 'of',\r\n FirstPage: 'First page',\r\n PrevPage: 'Previous page',\r\n NextPage: 'Next page',\r\n LastPage: 'Last page',\r\n /** The save button's caption and tooltip, and its menu items, captioned by the format they write. */\r\n Save: 'Save',\r\n SaveToolTip: 'Save',\r\n formatPdf: 'Adobe PDF',\r\n formatHtml: 'HTML',\r\n /** The resources button's tooltip. */\r\n Resources: 'Resources',\r\n /** The find button's tooltip, and the find panel's captions. */\r\n FindToolTip: 'Find',\r\n FindWhat: 'Find What',\r\n FindPrevious: 'Find Previous',\r\n FindNext: 'Find Next',\r\n MatchCase: 'Match Case',\r\n MatchWholeWord: 'Match Whole Word',\r\n closeFind: 'Close',\r\n /** The view-mode button's tooltip, and its menu items, whose captions are the mode names. */\r\n ViewModeToolTip: 'View mode',\r\n SinglePage: 'Single Page',\r\n Continuous: 'Continuous',\r\n MultiplePages: 'Multiple Pages',\r\n /** The zoom button's tooltip; its caption is the current percentage, so it has no key. */\r\n ZoomToolTip: 'Zoom',\r\n /** Fitting a whole page, which Stimulsoft's menu captions by the page's height. */\r\n ZoomOnePage: 'Page Height',\r\n ZoomPageWidth: 'Page Width',\r\n errorUnreachable: 'The report server could not be reached.',\r\n errorStatus: 'The report server answered with HTTP status {0}.',\r\n errorTimeout: 'The report server did not answer within {0} seconds.',\r\n errorMalformed: \"The report server's answer to {0} is not one this viewer can read.\",\r\n errorProtocol:\r\n 'The report server speaks viewer protocol {0}, and this viewer speaks protocol {1}.',\r\n};\r\n\r\nexport type NxeViewerStrings = Readonly<Record<keyof typeof NXE_ENGLISH, string>>;\r\n\r\n/** Puts each value in place of its numbered placeholder: `{0}` is the first value. */\r\nexport function formatString(template: string, ...values: (string | number)[]): string {\r\n return template.replace(/\\{(\\d+)\\}/g, (placeholder, index: string) =>\r\n Number(index) < values.length ? String(values[Number(index)]) : placeholder,\r\n );\r\n}\r\n","import {\r\n afterNextRender,\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { NXE_ENGLISH, type NxeViewerStrings } from '../strings/nxe-viewer-strings.const';\r\n\r\n/** What the user asked the viewer to find, and which way to go from the current hit. */\r\nexport interface NxeFindRequest {\r\n readonly text: string;\r\n readonly forward: boolean;\r\n readonly matchCase: boolean;\r\n readonly wholeWord: boolean;\r\n}\r\n\r\n/**\r\n * The find panel, as Stimulsoft 2025.1.4 draws and runs it (angular-viewer-panels-chrome.md §1): a\r\n * second bar below the toolbar with Close, the \"Find What\" box, Find Previous, Find Next, and the Match\r\n * Case and Match Whole Word toggles, every item with a 2 px margin.\r\n *\r\n * It searches only on Enter in the box and on the two find buttons, never as the user types, and the\r\n * toggles only change how the next search runs. It opens empty with the box focused, and has no\r\n * tooltips. The viewer does the finding; this panel says what to find.\r\n */\r\n@Component({\r\n selector: 'nxe-viewer-find-panel',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'nxe-viewer-find-panel', role: 'search' },\r\n template: `\r\n <div class=\"nxe-find-bar\">\r\n <button\r\n type=\"button\"\r\n class=\"nxe-find-button\"\r\n [attr.aria-label]=\"strings().closeFind\"\r\n (click)=\"closed.emit()\"\r\n >\r\n <span class=\"nxe-find-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path d=\"M3.5 3.5l9 9m0-9-9 9\" fill=\"none\" stroke=\"#707070\" stroke-width=\"1.2\" />\r\n </svg>\r\n </span>\r\n </button>\r\n <span class=\"nxe-find-label\">{{ strings().FindWhat }}</span>\r\n <input\r\n #box\r\n type=\"text\"\r\n class=\"nxe-find-box\"\r\n [attr.aria-label]=\"strings().FindWhat\"\r\n (keydown.enter)=\"find(box.value, true)\"\r\n />\r\n <button type=\"button\" class=\"nxe-find-button\" (click)=\"find(box.value, false)\">\r\n <span class=\"nxe-find-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 3.5 13 9h-3v3.5H6V9H3z\"\r\n fill=\"#81c1f1\"\r\n stroke=\"#0161b1\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </span>\r\n <span class=\"nxe-find-caption\">{{ strings().FindPrevious }}</span>\r\n </button>\r\n <button type=\"button\" class=\"nxe-find-button\" (click)=\"find(box.value, true)\">\r\n <span class=\"nxe-find-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 12.5 13 7h-3V3.5H6V7H3z\"\r\n fill=\"#81c1f1\"\r\n stroke=\"#0161b1\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </span>\r\n <span class=\"nxe-find-caption\">{{ strings().FindNext }}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nxe-find-button\"\r\n [class.nxe-find-on]=\"matchCase()\"\r\n [attr.aria-pressed]=\"matchCase()\"\r\n (click)=\"matchCase.set(!matchCase())\"\r\n >\r\n <span class=\"nxe-find-caption\">{{ strings().MatchCase }}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"nxe-find-button\"\r\n [class.nxe-find-on]=\"wholeWord()\"\r\n [attr.aria-pressed]=\"wholeWord()\"\r\n (click)=\"wholeWord.set(!wholeWord())\"\r\n >\r\n <span class=\"nxe-find-caption\">{{ strings().MatchWholeWord }}</span>\r\n </button>\r\n </div>\r\n `,\r\n styles: `\r\n /* The bar sits 2 px below the toolbar, as Stimulsoft's panel adds 2 px of top padding. */\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n padding-top: 2px;\r\n user-select: none;\r\n font-family: Arial;\r\n font-size: 12px;\r\n color: #202020;\r\n }\r\n\r\n .nxe-find-bar {\r\n display: flex;\r\n align-items: center;\r\n box-sizing: border-box;\r\n height: 31px;\r\n border: 1px solid #c6c6c6;\r\n border-radius: 3px;\r\n background: #fff;\r\n cursor: default;\r\n }\r\n\r\n .nxe-find-button {\r\n display: inline-flex;\r\n align-items: center;\r\n box-sizing: border-box;\r\n height: 25px;\r\n margin: 2px;\r\n padding: 0;\r\n border: 1px solid transparent;\r\n border-radius: 3px;\r\n background: transparent;\r\n color: inherit;\r\n font: inherit;\r\n white-space: nowrap;\r\n cursor: default;\r\n }\r\n\r\n .nxe-find-button:hover {\r\n background: #dadada;\r\n }\r\n\r\n .nxe-find-button.nxe-find-on {\r\n background: #e5e5e5;\r\n }\r\n\r\n .nxe-find-icon {\r\n display: flex;\r\n flex: none;\r\n box-sizing: border-box;\r\n width: 22px;\r\n padding-left: 3px;\r\n }\r\n\r\n .nxe-find-icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .nxe-find-caption {\r\n padding: 1px 5px 0 0;\r\n }\r\n\r\n .nxe-find-label {\r\n margin: 2px;\r\n padding: 2px 0 0;\r\n white-space: nowrap;\r\n }\r\n\r\n /* 170 px of text, 4 px of padding and two 1 px borders: Stimulsoft's 176 x 23 box. */\r\n .nxe-find-box {\r\n box-sizing: content-box;\r\n width: 170px;\r\n height: 21px;\r\n margin: 2px;\r\n padding: 0 0 0 4px;\r\n border: 1px solid #ababab;\r\n border-radius: 3px;\r\n background: #fff;\r\n color: inherit;\r\n font: inherit;\r\n line-height: 21px;\r\n outline: none;\r\n }\r\n\r\n .nxe-find-box:hover {\r\n border-color: #6b6b6b;\r\n }\r\n `,\r\n})\r\nexport class NxeViewerFindPanelComponent {\r\n /** The captions to show. */\r\n readonly strings = input<NxeViewerStrings>(NXE_ENGLISH);\r\n\r\n /** A search the user asked for. */\r\n readonly search = output<NxeFindRequest>();\r\n /** The user closed the panel. */\r\n readonly closed = output<void>();\r\n\r\n protected readonly matchCase = signal(false);\r\n protected readonly wholeWord = signal(false);\r\n\r\n private readonly box = viewChild.required<ElementRef<HTMLInputElement>>('box');\r\n\r\n constructor() {\r\n // Stimulsoft focuses the box on the next tick after the panel opens.\r\n afterNextRender(() => this.box().nativeElement.focus());\r\n }\r\n\r\n protected find(text: string, forward: boolean): void {\r\n this.search.emit({ text, forward, matchCase: this.matchCase(), wholeWord: this.wholeWord() });\r\n }\r\n}\r\n","/**\r\n * Page HTML from the server, made safe to place in the application's document.\r\n *\r\n * The report repository's HTML renderer escapes every attribute value and writes links only with\r\n * http, https, mailto, tel or no scheme, and its chart renderer strips event handlers from chart SVG.\r\n * This is the second layer: whatever reaches the viewer, a page can neither run script nor load active\r\n * content, and it cannot style the viewer around it.\r\n */\r\n\r\n/**\r\n * Elements that run script, load documents, plugins or media, submit, animate other attributes, or\r\n * carry CSS of their own. The renderer writes none of them into a page.\r\n */\r\nconst REMOVED_ELEMENTS = [\r\n 'script',\r\n 'noscript',\r\n 'template',\r\n 'style',\r\n 'link',\r\n 'meta',\r\n 'base',\r\n 'iframe',\r\n 'frame',\r\n 'frameset',\r\n 'object',\r\n 'embed',\r\n 'applet',\r\n 'portal',\r\n 'audio',\r\n 'video',\r\n 'source',\r\n 'track',\r\n 'picture',\r\n 'form',\r\n 'set',\r\n 'animate',\r\n].join(',');\r\n\r\n/** Attributes holding a URL that a click or a load would follow. */\r\nconst URL_ATTRIBUTES = new Set([\r\n 'href',\r\n 'xlink:href',\r\n 'src',\r\n 'action',\r\n 'formaction',\r\n 'poster',\r\n 'background',\r\n]);\r\n\r\n/** Attributes that make requests of their own and have no use in a page. */\r\nconst REMOVED_ATTRIBUTES = new Set(['srcset', 'ping']);\r\n\r\nconst LINK_SCHEMES = new Set(['http', 'https', 'mailto', 'tel']);\r\n\r\n/**\r\n * Whether a URL attribute's value can stay: no scheme (a relative or fragment URL), a link scheme, or,\r\n * for `src`, an image as a data URL. Browsers ignore spaces and control characters around and inside a\r\n * scheme, so the check drops them before reading it.\r\n */\r\nexport function isSafeUrl(attribute: string, value: string): boolean {\r\n let compact = '';\r\n for (const character of value) {\r\n if (character.charCodeAt(0) > 0x20) compact += character;\r\n }\r\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(compact)?.[1]?.toLowerCase();\r\n if (scheme === undefined || LINK_SCHEMES.has(scheme)) return true;\r\n return attribute === 'src' && scheme === 'data' && /^data:image\\//i.test(compact);\r\n}\r\n\r\n/**\r\n * Parses page HTML and returns it without anything active. A template's content is inert while it is\r\n * examined: its scripts do not run, its images do not load and its handlers do not fire.\r\n */\r\nexport function scrubPageHtml(html: string, document: Document): DocumentFragment {\r\n const template = document.createElement('template');\r\n template.innerHTML = html;\r\n const content = template.content;\r\n for (const element of Array.from(content.querySelectorAll(REMOVED_ELEMENTS))) {\r\n element.remove();\r\n }\r\n for (const element of Array.from(content.querySelectorAll('*'))) {\r\n for (const attribute of Array.from(element.attributes)) {\r\n const name = attribute.name.toLowerCase();\r\n const unsafe =\r\n name.startsWith('on') ||\r\n REMOVED_ATTRIBUTES.has(name) ||\r\n (URL_ATTRIBUTES.has(name) && !isSafeUrl(name, attribute.value));\r\n if (unsafe) element.removeAttribute(attribute.name);\r\n }\r\n }\r\n return content;\r\n}\r\n\r\n/** A stylesheet, or a rule that holds rules: anything whose rules can be listed and deleted by index. */\r\ninterface RuleContainer {\r\n readonly cssRules: CSSRuleList;\r\n deleteRule(index: number): void;\r\n}\r\n\r\n/**\r\n * Deletes every style rule whose selector names `:host` or `:host-context()`, also inside grouping rules\r\n * such as `@media` and inside nested rules. In a shadow root those rules style the shadow host, the\r\n * viewer's own page element, so a page's CSS could otherwise move or hide it.\r\n */\r\nfunction deleteHostRules(container: RuleContainer): void {\r\n for (let index = container.cssRules.length - 1; index >= 0; index--) {\r\n const rule = container.cssRules[index];\r\n if (rule instanceof CSSStyleRule && /:host/i.test(rule.selectorText)) {\r\n container.deleteRule(index);\r\n } else if ('cssRules' in rule && !(rule instanceof CSSKeyframesRule)) {\r\n deleteHostRules(rule as unknown as RuleContainer);\r\n }\r\n }\r\n}\r\n\r\nconst sheets = new Map<string, CSSStyleSheet>();\r\n\r\n/**\r\n * One constructed stylesheet per distinct CSS text, shared by every shadow root that adopts it. A\r\n * report's page CSS is the same for every page, so a long report parses it once. The sheet keeps no rule\r\n * that could style the shadow host. CSS that a constructed stylesheet refuses gives an empty sheet, so the\r\n * page shows unstyled instead of not at all.\r\n */\r\nexport function adoptedSheet(cssText: string): CSSStyleSheet {\r\n let sheet = sheets.get(cssText);\r\n if (!sheet) {\r\n sheet = new CSSStyleSheet();\r\n try {\r\n sheet.replaceSync(cssText);\r\n deleteHostRules(sheet);\r\n } catch {\r\n sheet = new CSSStyleSheet();\r\n }\r\n sheets.set(cssText, sheet);\r\n }\r\n return sheet;\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n DOCUMENT,\r\n ElementRef,\r\n inject,\r\n input,\r\n OnChanges,\r\n SimpleChanges,\r\n} from '@angular/core';\r\nimport type { NxePageSize } from '../protocol/nxe-protocol.model';\r\nimport { adoptedSheet, scrubPageHtml } from './nxe-page-html.util';\r\n\r\n/** CSS pixels per point, and the share of its height Stimulsoft's viewer gives a page. */\r\nconst PX_PER_PT = 96 / 72;\r\nconst VIEWER_HEIGHT = 239 / 240;\r\n\r\n/**\r\n * The viewer draws each page's frame and the space between pages, so the page CSS's own are cancelled.\r\n *\r\n * Zoom scales the page's own box from its top left corner. Stimulsoft re-renders the page on the server\r\n * at the asked-for zoom and never scales on the client; this engine's page HTML is absolutely positioned\r\n * in points, so scaling it here puts the same marks in the same places without a round trip, and the text\r\n * is re-rasterised at the new size rather than resampled. The host element is sized to the scaled box so\r\n * the pages around it lay out against what is on screen.\r\n */\r\nfunction pageFrameCss(zoom: number): string {\r\n const transform = zoom === 1 ? '' : `transform:scale(${zoom});transform-origin:top left;`;\r\n return `.nextera-page{margin:0;box-shadow:none;${transform}}`;\r\n}\r\n\r\n/**\r\n * One report page, in its own shadow root.\r\n *\r\n * The page's size comes from the report's page list, so the page holds its place before its HTML\r\n * arrives. The HTML is scrubbed by `scrubPageHtml` and placed beside the adopted page stylesheet, so the\r\n * report's styles and the application's never meet. `contain: paint` keeps even a fixed-position\r\n * element inside the page's box.\r\n */\r\n@Component({\r\n selector: 'nxe-report-page',\r\n standalone: true,\r\n template: '',\r\n styles: `\r\n :host {\r\n display: block;\r\n position: relative;\r\n box-sizing: content-box;\r\n contain: paint;\r\n background: #fff;\r\n }\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'nxe-report-page',\r\n '[attr.data-page]': 'page().pageNumber',\r\n '[style.width.px]': 'scaledWidth()',\r\n '[style.height.px]': 'scaledHeight()',\r\n },\r\n})\r\nexport class NxeReportPageComponent implements OnChanges {\r\n /** The page's number and size. */\r\n readonly page = input.required<NxePageSize>();\r\n /** The page's HTML from the server, or null while it has not arrived. */\r\n readonly html = input<string | null>(null);\r\n /** The stylesheet every page of the report needs. */\r\n readonly css = input.required<string>();\r\n /** The zoom to draw the page at, as a factor: 1 is 100 %. */\r\n readonly zoom = input(1);\r\n\r\n /**\r\n * The page's box in CSS pixels, as the server's page HTML draws it and Stimulsoft's viewer sizes a\r\n * page: floor(W) wide and floor(H x 239/240) tall, 796 x 1118 for A4 (renderer-html's\r\n * viewer-page.ts). Known from the page's size alone, so the frame holds its place before the HTML\r\n * arrives, and scaled by the zoom.\r\n */\r\n protected readonly scaledWidth = computed(\r\n () => Math.floor(this.page().widthPoints * PX_PER_PT + 1e-9) * this.zoom(),\r\n );\r\n protected readonly scaledHeight = computed(\r\n () => Math.floor(this.page().heightPoints * PX_PER_PT * VIEWER_HEIGHT + 1e-9) * this.zoom(),\r\n );\r\n\r\n private readonly document = inject(DOCUMENT);\r\n private readonly root = (inject(ElementRef).nativeElement as HTMLElement).attachShadow({\r\n mode: 'open',\r\n });\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['css'] || changes['zoom']) {\r\n this.root.adoptedStyleSheets = [adoptedSheet(this.css()), adoptedSheet(pageFrameCss(this.zoom()))];\r\n }\r\n if (changes['html']) {\r\n const html = this.html();\r\n if (html === null) {\r\n this.root.replaceChildren();\r\n } else {\r\n this.root.replaceChildren(scrubPageHtml(html, this.document));\r\n }\r\n }\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { formatString, NXE_ENGLISH, NxeViewerStrings } from '../strings/nxe-viewer-strings.const';\r\nimport { NXE_VIEWER_PROTOCOL } from './nxe-protocol.const';\r\nimport type {\r\n NxeFindAnswer,\r\n NxePagesAnswer,\r\n NxeReportAnswer,\r\n NxeUpdateCacheAnswer,\r\n NxeViewerAction,\r\n NxeViewerDataAnswer,\r\n NxeViewerFailure,\r\n} from './nxe-protocol.model';\r\n\r\n/**\r\n * A success answer that is not what the protocol says its action answers: the wrong shape, or an\r\n * AngularViewerData answer from another version of the protocol.\r\n */\r\nexport class NxeMalformedAnswerError extends Error {\r\n constructor(\r\n readonly action: NxeViewerAction,\r\n /** The version an AngularViewerData answer declared, when it declared another one. */\r\n readonly protocol: number = NXE_VIEWER_PROTOCOL,\r\n ) {\r\n super(`The ${action} answer is not what viewer protocol ${NXE_VIEWER_PROTOCOL} answers.`);\r\n this.name = 'NxeMalformedAnswerError';\r\n }\r\n}\r\n\r\n/** A request that got no answer within the server options' `requestTimeout`. */\r\nexport class NxeTimeoutError extends Error {\r\n constructor(readonly seconds: number) {\r\n super(`No answer within ${seconds} seconds.`);\r\n this.name = 'NxeTimeoutError';\r\n }\r\n}\r\n\r\ntype JsonObject = Record<string, unknown>;\r\n\r\nconst OPTION_GROUPS = ['actions', 'appearance', 'toolbar', 'exports', 'server'];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction isIndex(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\r\n}\r\n\r\nfunction isNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value);\r\n}\r\n\r\nfunction isBounds(value: unknown): boolean {\r\n return (\r\n isObject(value) &&\r\n isNumber(value['x']) &&\r\n isNumber(value['y']) &&\r\n isNumber(value['width']) &&\r\n isNumber(value['height'])\r\n );\r\n}\r\n\r\nfunction isPages(value: unknown): value is NxePagesAnswer {\r\n if (!isObject(value)) return false;\r\n const pages = value['pages'];\r\n return (\r\n isIndex(value['startIndex']) &&\r\n Array.isArray(pages) &&\r\n pages.every((page) => typeof page === 'string')\r\n );\r\n}\r\n\r\nfunction isPageSize(value: unknown): boolean {\r\n return (\r\n isObject(value) &&\r\n isIndex(value['pageNumber']) &&\r\n isNumber(value['widthPoints']) &&\r\n isNumber(value['heightPoints'])\r\n );\r\n}\r\n\r\nfunction isLocated(value: unknown, textKey: 'title' | 'text'): boolean {\r\n return (\r\n isObject(value) &&\r\n typeof value[textKey] === 'string' &&\r\n isIndex(value['pageIndex']) &&\r\n isBounds(value['bounds'])\r\n );\r\n}\r\n\r\n/** Reads the answer to AngularViewerData: the token, the viewer options and the host's translation. */\r\nexport function readViewerData(body: unknown): NxeViewerDataAnswer {\r\n if (!isObject(body)) throw new NxeMalformedAnswerError('AngularViewerData');\r\n const { protocol, token, options, localization } = body;\r\n if (isNumber(protocol) && protocol !== NXE_VIEWER_PROTOCOL) {\r\n throw new NxeMalformedAnswerError('AngularViewerData', protocol);\r\n }\r\n const valid =\r\n protocol === NXE_VIEWER_PROTOCOL &&\r\n typeof token === 'string' &&\r\n token !== '' &&\r\n isObject(options) &&\r\n OPTION_GROUPS.every((group) => isObject(options[group])) &&\r\n (localization === null || isObject(localization));\r\n if (!valid) throw new NxeMalformedAnswerError('AngularViewerData');\r\n return body as unknown as NxeViewerDataAnswer;\r\n}\r\n\r\n/** Reads the answer to GetReport: the report's name, page count, page sizes, bookmarks and page stylesheet. */\r\nexport function readReport(body: unknown): NxeReportAnswer {\r\n if (!isObject(body)) throw new NxeMalformedAnswerError('GetReport');\r\n const { reportName, pageCount, pages, bookmarks, pageCss, pagesHtml } = body;\r\n const valid =\r\n typeof reportName === 'string' &&\r\n isIndex(pageCount) &&\r\n Array.isArray(pages) &&\r\n pages.length === pageCount &&\r\n pages.every(isPageSize) &&\r\n Array.isArray(bookmarks) &&\r\n bookmarks.every((bookmark) => isLocated(bookmark, 'title')) &&\r\n typeof pageCss === 'string' &&\r\n (pagesHtml === undefined || isPages(pagesHtml));\r\n if (!valid) throw new NxeMalformedAnswerError('GetReport');\r\n return {\r\n ...(body as unknown as NxeReportAnswer),\r\n pagesHtml: (pagesHtml as NxePagesAnswer | undefined) ?? null,\r\n };\r\n}\r\n\r\n/** Reads the answer to GetPages. */\r\nexport function readPages(body: unknown): NxePagesAnswer {\r\n if (!isPages(body)) throw new NxeMalformedAnswerError('GetPages');\r\n return body;\r\n}\r\n\r\n/** Reads the answer to Find. */\r\nexport function readFind(body: unknown): NxeFindAnswer {\r\n const hits = isObject(body) ? body['hits'] : undefined;\r\n if (!Array.isArray(hits) || !hits.every((hit) => isLocated(hit, 'text')))\r\n throw new NxeMalformedAnswerError('Find');\r\n return body as unknown as NxeFindAnswer;\r\n}\r\n\r\n/** Reads the answer to UpdateCache. */\r\nexport function readUpdateCache(body: unknown): NxeUpdateCacheAnswer {\r\n if (!isObject(body) || typeof body['updated'] !== 'boolean')\r\n throw new NxeMalformedAnswerError('UpdateCache');\r\n return body as unknown as NxeUpdateCacheAnswer;\r\n}\r\n\r\nfunction described(status: number, message: string): NxeViewerFailure {\r\n return { status, type: 'Error', message, retryable: false, traceId: null };\r\n}\r\n\r\n/**\r\n * What went wrong with a request, from whatever it failed with:\r\n * - the server's own error answer, kept as it is;\r\n * - an HTTP error answer without the protocol's shape (a host's, a framework's or a proxy's);\r\n * - no answer at all;\r\n * - a timeout;\r\n * - a success answer the viewer cannot read.\r\n */\r\nexport function readFailure(\r\n failure: unknown,\r\n action: NxeViewerAction,\r\n strings: NxeViewerStrings = NXE_ENGLISH,\r\n): NxeViewerFailure {\r\n if (failure instanceof HttpErrorResponse) {\r\n const body: unknown = failure.error;\r\n // status and message are all that is asked for. The rest of the protocol's error answer is taken when the server\r\n // sent it and defaulted when it did not, because a host that writes its own error -- bright answers a failed\r\n // GetReport with {status, message} from its controller's catch -- says the one thing the reader cannot work out\r\n // for itself, and demanding type and retryable alongside it threw that sentence away and left the viewer showing\r\n // the status code on its own.\r\n if (isObject(body) && body['status'] === 'error' && typeof body['message'] === 'string') {\r\n return {\r\n status: failure.status,\r\n type: typeof body['type'] === 'string' ? body['type'] : 'Error',\r\n message: body['message'],\r\n retryable: typeof body['retryable'] === 'boolean' ? body['retryable'] : false,\r\n traceId: typeof body['traceId'] === 'string' ? body['traceId'] : null,\r\n };\r\n }\r\n if (failure.status === 0) return described(0, strings.errorUnreachable);\r\n if (failure.status >= 200 && failure.status < 300)\r\n return described(0, formatString(strings.errorMalformed, action));\r\n return described(failure.status, formatString(strings.errorStatus, failure.status));\r\n }\r\n if (failure instanceof NxeTimeoutError) {\r\n return described(0, formatString(strings.errorTimeout, failure.seconds));\r\n }\r\n if (failure instanceof NxeMalformedAnswerError) {\r\n return failure.protocol !== NXE_VIEWER_PROTOCOL\r\n ? described(0, formatString(strings.errorProtocol, failure.protocol, NXE_VIEWER_PROTOCOL))\r\n : described(0, formatString(strings.errorMalformed, failure.action));\r\n }\r\n return described(0, failure instanceof Error ? failure.message : String(failure));\r\n}\r\n","import { HttpClient, HttpErrorResponse } from '@angular/common/http';\r\nimport { inject, Injectable } from '@angular/core';\r\nimport { catchError, defer, from, map, Observable, switchMap, throwError, timeout } from 'rxjs';\r\nimport type { NxeViewerStrings } from '../strings/nxe-viewer-strings.const';\r\nimport type {\r\n NxeExportAnswer,\r\n NxeFindAnswer,\r\n NxePagesAnswer,\r\n NxeReportAnswer,\r\n NxeUpdateCacheAnswer,\r\n NxeViewerAction,\r\n NxeViewerDataAnswer,\r\n} from './nxe-protocol.model';\r\nimport {\r\n NxeTimeoutError,\r\n readFailure,\r\n readFind,\r\n readPages,\r\n readReport,\r\n readUpdateCache,\r\n readViewerData,\r\n} from './nxe-protocol-reader.util';\r\nimport type { NxeViewerOptions } from './nxe-viewer-options.model';\r\n\r\n/** What the component's `postParametersFunction` is called with: the request's action and its parameters. */\r\nexport interface NxePostParametersData {\r\n action: NxeViewerAction;\r\n [parameter: string]: unknown;\r\n}\r\n\r\n/**\r\n * The component's `postParametersFunction` input. It runs for every request, the first one included.\r\n * Each key of an object it returns becomes a form field of the request, replacing a field of the same\r\n * name; anything else it returns adds nothing.\r\n */\r\nexport type NxePostParametersFunction = (data: NxePostParametersData) => unknown;\r\n\r\n/** What every request is built from. */\r\nexport interface NxeRequestContext {\r\n /** The component's `requestUrl`: each request's host action takes the place of `{action}`. */\r\n requestUrl: string;\r\n /** The component's `properties`, sent as JSON when truthy. */\r\n properties: unknown;\r\n /** The component's `postParametersFunction`. */\r\n postParametersFunction: NxePostParametersFunction | null | undefined;\r\n /** The strings failures are described with. */\r\n strings: NxeViewerStrings;\r\n}\r\n\r\n/** The server's side of an open viewer: the token it issued and the options it sent. */\r\nexport interface NxeServerSession {\r\n token: string;\r\n options: NxeViewerOptions;\r\n}\r\n\r\n/** Consecutive pages, from a 0-based index. */\r\nexport interface NxePageRange {\r\n startIndex: number;\r\n count: number;\r\n}\r\n\r\nexport interface NxeFindParameters {\r\n text: string;\r\n matchCase?: boolean;\r\n wholeWord?: boolean;\r\n}\r\n\r\n/**\r\n * The seconds a request may take when no positive `requestTimeout` applies. That includes the first\r\n * request, which is sent before the server's options are known. Stimulsoft's viewer uses the same value.\r\n */\r\nexport const NXE_UNSET_REQUEST_TIMEOUT_SECONDS = 1000;\r\n\r\n/**\r\n * The URL of a host action. The action's path takes the place of `{action}` in `requestUrl`, and a query\r\n * string on the action is appended to the URL's own.\r\n */\r\nexport function actionUrl(requestUrl: string, action: string): string {\r\n const queryAt = action.indexOf('?');\r\n const path = queryAt < 0 ? action : action.slice(0, queryAt);\r\n const url = requestUrl.replace('{action}', () => path);\r\n if (queryAt < 0) return url;\r\n return `${url}${url.includes('?') ? '&' : '?'}${action.slice(queryAt + 1)}`;\r\n}\r\n\r\n/**\r\n * The host action that answers a viewer action. GetReport goes to `getReport` (or `viewerEvent` when that\r\n * is empty). The other actions go to `viewerEvent`, or to `getReport` when the server keeps nothing.\r\n * ExportReport goes to `exportReport` when that is set.\r\n */\r\nexport function hostActionFor(options: NxeViewerOptions, action: NxeViewerAction): string {\r\n const { getReport, viewerEvent, exportReport } = options.actions;\r\n const reportAction = getReport || viewerEvent;\r\n const eventAction = options.server.cacheMode === 'None' ? reportAction : viewerEvent;\r\n if (action === 'GetReport') return reportAction;\r\n if (action === 'ExportReport') return exportReport || eventAction;\r\n return eventAction;\r\n}\r\n\r\n/** The file name in a Content-Disposition header, preferring its UTF-8 form. */\r\nexport function fileNameOf(disposition: string | null): string | null {\r\n if (!disposition) return null;\r\n const encoded = /filename\\*\\s*=\\s*UTF-8''([^;]+)/i.exec(disposition);\r\n if (encoded) {\r\n try {\r\n return decodeURIComponent(encoded[1].trim());\r\n } catch {\r\n // A malformed escape: the plain file name follows.\r\n }\r\n }\r\n const plain = /filename\\s*=\\s*(?:\"([^\"]*)\"|([^;]+))/i.exec(disposition);\r\n return plain ? (plain[1] ?? plain[2]).trim() : null;\r\n}\r\n\r\nfunction timeoutOf(session: NxeServerSession | null): number {\r\n const seconds = session?.options.server.requestTimeout ?? 0;\r\n return seconds > 0 ? seconds : NXE_UNSET_REQUEST_TIMEOUT_SECONDS;\r\n}\r\n\r\nfunction formOf(\r\n context: NxeRequestContext,\r\n action: NxeViewerAction,\r\n session: NxeServerSession | null,\r\n parameters: object | null,\r\n): FormData {\r\n const form = new FormData();\r\n form.set('nextera_action', action);\r\n if (session) {\r\n const { cacheMode, cacheTimeout, cacheItemPriority } = session.options.server;\r\n form.set('nextera_token', session.token);\r\n form.set(\r\n 'nextera_cache',\r\n JSON.stringify({ mode: cacheMode, timeout: cacheTimeout, priority: cacheItemPriority }),\r\n );\r\n }\r\n if (parameters) form.set('nextera_parameters', JSON.stringify(parameters));\r\n if (context.properties) form.set('properties', JSON.stringify(context.properties));\r\n const added = context.postParametersFunction?.({ ...parameters, action });\r\n if (typeof added === 'object' && added !== null) {\r\n for (const [name, value] of Object.entries(added)) {\r\n form.set(name, value instanceof Blob ? value : String(value));\r\n }\r\n }\r\n return form;\r\n}\r\n\r\n/** An error answer to a blob request carries its body as a blob. Read it, as JSON when it is JSON, so it can be classified. */\r\nasync function readableFailure(failure: unknown): Promise<unknown> {\r\n if (!(failure instanceof HttpErrorResponse) || !(failure.error instanceof Blob)) return failure;\r\n const text = await failure.error.text();\r\n let body: unknown = text;\r\n try {\r\n body = JSON.parse(text);\r\n } catch {\r\n // Not JSON: the failure is described by its status.\r\n }\r\n return new HttpErrorResponse({\r\n error: body,\r\n headers: failure.headers,\r\n status: failure.status,\r\n statusText: failure.statusText,\r\n url: failure.url ?? undefined,\r\n });\r\n}\r\n\r\n/**\r\n * Sends one viewer's protocol requests through the application's `HttpClient`, so the application's\r\n * interceptors apply, and reads each answer. Every observable fails with an `NxeViewerFailure`. A request's\r\n * form is built when the observable is subscribed.\r\n */\r\n@Injectable()\r\nexport class NxeViewerClientService {\r\n private readonly http = inject(HttpClient);\r\n\r\n /** AngularViewerData, sent to the component's `action`: the token and the options. */\r\n openViewer(context: NxeRequestContext, action: string): Observable<NxeViewerDataAnswer> {\r\n return this.post(context, 'AngularViewerData', action, null, null, readViewerData);\r\n }\r\n\r\n /** GetReport: renders the report, with the HTML of the pages in `range` when one is given. */\r\n getReport(\r\n context: NxeRequestContext,\r\n session: NxeServerSession,\r\n range?: NxePageRange,\r\n ): Observable<NxeReportAnswer> {\r\n const hostAction = hostActionFor(session.options, 'GetReport');\r\n return this.post(context, 'GetReport', hostAction, session, range ?? null, readReport);\r\n }\r\n\r\n /** GetPages: the HTML of the pages in `range`. */\r\n getPages(\r\n context: NxeRequestContext,\r\n session: NxeServerSession,\r\n range: NxePageRange,\r\n ): Observable<NxePagesAnswer> {\r\n return this.post(\r\n context,\r\n 'GetPages',\r\n hostActionFor(session.options, 'GetPages'),\r\n session,\r\n range,\r\n readPages,\r\n );\r\n }\r\n\r\n /** Find: the text components that match. */\r\n find(\r\n context: NxeRequestContext,\r\n session: NxeServerSession,\r\n parameters: NxeFindParameters,\r\n ): Observable<NxeFindAnswer> {\r\n return this.post(\r\n context,\r\n 'Find',\r\n hostActionFor(session.options, 'Find'),\r\n session,\r\n parameters,\r\n readFind,\r\n );\r\n }\r\n\r\n /** UpdateCache: keeps the server's copy of the report. */\r\n updateCache(\r\n context: NxeRequestContext,\r\n session: NxeServerSession,\r\n ): Observable<NxeUpdateCacheAnswer> {\r\n const hostAction = hostActionFor(session.options, 'UpdateCache');\r\n return this.post(context, 'UpdateCache', hostAction, session, null, readUpdateCache);\r\n }\r\n\r\n /** ExportReport: the report as a file, in a format such as `Pdf` or `Html`. It never times out. */\r\n exportReport(\r\n context: NxeRequestContext,\r\n session: NxeServerSession,\r\n format: string,\r\n ): Observable<NxeExportAnswer> {\r\n const url = actionUrl(context.requestUrl, hostActionFor(session.options, 'ExportReport'));\r\n return defer(() =>\r\n this.http.post(url, formOf(context, 'ExportReport', session, { format }), {\r\n observe: 'response',\r\n responseType: 'blob',\r\n }),\r\n ).pipe(\r\n map((response) => ({\r\n blob: response.body ?? new Blob([]),\r\n fileName: fileNameOf(response.headers.get('Content-Disposition')) ?? '',\r\n contentType: response.headers.get('Content-Type') ?? '',\r\n })),\r\n catchError((failure: unknown) =>\r\n from(readableFailure(failure)).pipe(\r\n switchMap((readable) =>\r\n throwError(() => readFailure(readable, 'ExportReport', context.strings)),\r\n ),\r\n ),\r\n ),\r\n );\r\n }\r\n\r\n private post<T>(\r\n context: NxeRequestContext,\r\n action: NxeViewerAction,\r\n hostAction: string,\r\n session: NxeServerSession | null,\r\n parameters: object | null,\r\n read: (body: unknown) => T,\r\n ): Observable<T> {\r\n const seconds = timeoutOf(session);\r\n return defer(() =>\r\n this.http.post(\r\n actionUrl(context.requestUrl, hostAction),\r\n formOf(context, action, session, parameters),\r\n ),\r\n ).pipe(\r\n timeout({\r\n first: seconds * 1000,\r\n with: () => throwError(() => new NxeTimeoutError(seconds)),\r\n }),\r\n map((body) => read(body)),\r\n catchError((failure: unknown) =>\r\n throwError(() => readFailure(failure, action, context.strings)),\r\n ),\r\n );\r\n }\r\n}\r\n","import { computed, DestroyRef, inject, Injectable, signal } from '@angular/core';\r\nimport {\r\n catchError,\r\n EMPTY,\r\n exhaustMap,\r\n finalize,\r\n interval,\r\n Observable,\r\n Subject,\r\n Subscription,\r\n} from 'rxjs';\r\nimport type {\r\n NxePagesAnswer,\r\n NxePageSize,\r\n NxeReportAnswer,\r\n NxeViewerFailure,\r\n} from '../protocol/nxe-protocol.model';\r\nimport {\r\n NxeRequestContext,\r\n NxeServerSession,\r\n NxeViewerClientService,\r\n} from '../protocol/nxe-viewer-client.service';\r\nimport type { NxeViewerOptions } from '../protocol/nxe-viewer-options.model';\r\n\r\n/** How often an open viewer asks the server to keep its report: every 3 minutes, as Stimulsoft's viewer does. */\r\nexport const NXE_KEEP_ALIVE_MS = 180_000;\r\n\r\n/** The page on screen. */\r\nexport interface NxeShownPage {\r\n /** 0-based. */\r\n index: number;\r\n size: NxePageSize;\r\n /** The page's HTML, or null while it has not arrived: while it is on its way, or after its request failed. */\r\n html: string | null;\r\n}\r\n\r\nfunction withPages(pages: Map<number, string>, answer: NxePagesAnswer | null): Map<number, string> {\r\n answer?.pages.forEach((html, offset) => pages.set(answer.startIndex + offset, html));\r\n return pages;\r\n}\r\n\r\n/**\r\n * Hands a file to the browser to save, under the name the server gave it. A blob URL is used rather\r\n * than a data one because an exported report is far larger than a URL may be, and it is revoked on\r\n * the next turn of the event loop, once the click has been taken.\r\n */\r\nfunction saveBlob(blob: Blob, fileName: string): void {\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = fileName;\r\n link.style.display = 'none';\r\n document.body.append(link);\r\n link.click();\r\n link.remove();\r\n setTimeout(() => URL.revokeObjectURL(url), 0);\r\n}\r\n\r\n/**\r\n * One viewer's conversation with the report server, and the state the viewer shows.\r\n *\r\n * Every signal changes only in this service's methods and in the answers they handle; nothing reacts to\r\n * a signal changing. Each viewer provides its own session, so viewers on one page never share state.\r\n */\r\n@Injectable()\r\nexport class NxeViewerSessionService {\r\n private readonly client = inject(NxeViewerClientService);\r\n\r\n private readonly optionsState = signal<NxeViewerOptions | null>(null);\r\n private readonly reportState = signal<NxeReportAnswer | null>(null);\r\n private readonly htmlState = signal<ReadonlyMap<number, string>>(new Map());\r\n private readonly pageIndexState = signal(0);\r\n private readonly pendingState = signal(0);\r\n private readonly failureState = signal<NxeViewerFailure | null>(null);\r\n\r\n /** The options from the last AngularViewerData answer. */\r\n readonly options = this.optionsState.asReadonly();\r\n /** The report from the last GetReport answer, or null before one. */\r\n readonly report = this.reportState.asReadonly();\r\n /** The 0-based index of the page on screen. */\r\n readonly pageIndex = this.pageIndexState.asReadonly();\r\n /** The failure on show, until it is dismissed. */\r\n readonly failure = this.failureState.asReadonly();\r\n /** How many pages the report has; 0 before one is loaded. */\r\n readonly pageCount = computed(() => this.reportState()?.pageCount ?? 0);\r\n /** Whether a request the user waits for is on its way. Keep-alive requests do not count. */\r\n readonly busy = computed(() => this.pendingState() > 0);\r\n /** The page on screen, or null before a report. */\r\n readonly shownPage = computed<NxeShownPage | null>(() => {\r\n const report = this.reportState();\r\n const index = this.pageIndexState();\r\n if (!report || index >= report.pageCount) return null;\r\n return { index, size: report.pages[index], html: this.htmlState().get(index) ?? null };\r\n });\r\n\r\n /**\r\n * Every page of the report, in order, each with its HTML when it has arrived. The page modes that show\r\n * more than one page at a time lay these out and ask for the ones that come into view; a page holds its\r\n * size, and so its place, before its HTML is here.\r\n */\r\n readonly allPages = computed<readonly NxeShownPage[]>(() => {\r\n const report = this.reportState();\r\n if (!report) return [];\r\n const html = this.htmlState();\r\n return report.pages.map((size, index) => ({ index, size, html: html.get(index) ?? null }));\r\n });\r\n\r\n /** Emits after each successful GetReport answer. */\r\n readonly reportLoaded = new Subject<void>();\r\n /** Emits each failure put on show. */\r\n readonly failed = new Subject<NxeViewerFailure>();\r\n\r\n private context: NxeRequestContext | null = null;\r\n private session: NxeServerSession | null = null;\r\n /** Every request the user waits for. */\r\n private requests = new Subscription();\r\n /** The page requests among them, which a new rendering of the report makes obsolete. */\r\n private pageRequests = new Subscription();\r\n private keepAlive = Subscription.EMPTY;\r\n private readonly pagesOnTheWay = new Set<number>();\r\n /** True from the moment an expired report is sent to be rendered again until that rendering settles. */\r\n private recovering = false;\r\n private destroyed = false;\r\n\r\n constructor() {\r\n inject(DestroyRef).onDestroy(() => {\r\n this.destroyed = true;\r\n this.close();\r\n this.reportLoaded.complete();\r\n this.failed.complete();\r\n });\r\n }\r\n\r\n /** Opens the report the host action names, in place of whatever this viewer showed. */\r\n open(context: NxeRequestContext, action: string): void {\r\n if (this.destroyed) return;\r\n this.close();\r\n this.context = context;\r\n this.reportState.set(null);\r\n this.htmlState.set(new Map());\r\n this.pageIndexState.set(0);\r\n this.failureState.set(null);\r\n if (!context.requestUrl) return;\r\n this.track(this.client.openViewer(context, action), false, (answer) => {\r\n const session = { token: answer.token, options: answer.options };\r\n this.session = session;\r\n this.optionsState.set(answer.options);\r\n this.startKeepAlive(context, session);\r\n this.render();\r\n });\r\n }\r\n\r\n /**\r\n * Shows the page at a 0-based index; an index outside the report is ignored. Asking for the page already\r\n * on screen fetches it again when its HTML is missing, as it is after its request failed.\r\n */\r\n goToPage(index: number): void {\r\n const inReport = Number.isInteger(index) && index >= 0 && index < this.pageCount();\r\n if (this.destroyed || !inReport) return;\r\n this.pageIndexState.set(index);\r\n this.loadPage(index);\r\n }\r\n\r\n /**\r\n * Asks for a page's HTML without moving the page on screen, for the modes that show several pages at\r\n * once and fetch the ones that come into view. A page already here, or already on its way, is left alone.\r\n */\r\n requestPage(index: number): void {\r\n if (this.destroyed || !Number.isInteger(index) || index < 0) return;\r\n this.loadPage(index);\r\n }\r\n\r\n /** Moves the page on screen without asking for it, for scroll tracking, which follows what is drawn. */\r\n markCurrentPage(index: number): void {\r\n if (this.destroyed || !Number.isInteger(index) || index < 0 || index >= this.pageCount()) return;\r\n this.pageIndexState.set(index);\r\n }\r\n\r\n /**\r\n * ExportReport: the report as a file, handed to the browser to save. The export never times out, so\r\n * it is tracked as a request the user waits for and the toolbar stays disabled until the file is here.\r\n */\r\n exportTo(format: string): void {\r\n if (this.destroyed || this.session === null || this.context === null) return;\r\n const { context, session } = this.connection();\r\n this.track(this.client.exportReport(context, session, format), false, (answer) => {\r\n const name = answer.fileName || `${this.reportState()?.reportName ?? 'report'}.${format.toLowerCase()}`;\r\n saveBlob(answer.blob, name);\r\n });\r\n }\r\n\r\n /** Takes the failure off show. */\r\n dismissFailure(): void {\r\n this.failureState.set(null);\r\n }\r\n\r\n /**\r\n * GetReport, asking for the page on screen, which stays on screen when it is still in the report. The new\r\n * rendering makes every page request still on its way obsolete. Its settling ends a recovery.\r\n */\r\n private render(): void {\r\n const { context, session } = this.connection();\r\n const range = { startIndex: this.pageIndexState(), count: 1 };\r\n const rendering = this.client\r\n .getReport(context, session, range)\r\n .pipe(finalize(() => (this.recovering = false)));\r\n this.track(rendering, false, (report) => {\r\n this.pageRequests.unsubscribe();\r\n this.pageRequests = new Subscription();\r\n this.htmlState.set(withPages(new Map(), report.pagesHtml));\r\n this.reportState.set(report);\r\n this.pageIndexState.update((index) => Math.max(0, Math.min(index, report.pageCount - 1)));\r\n this.reportLoaded.next();\r\n this.loadPage(this.pageIndexState());\r\n });\r\n }\r\n\r\n /** GetPages for one page, unless the page is already here or on its way. */\r\n private loadPage(index: number): void {\r\n if (index >= this.pageCount() || this.htmlState().has(index) || this.pagesOnTheWay.has(index))\r\n return;\r\n const { context, session } = this.connection();\r\n this.pagesOnTheWay.add(index);\r\n const request = this.client\r\n .getPages(context, session, { startIndex: index, count: 1 })\r\n .pipe(finalize(() => this.pagesOnTheWay.delete(index)));\r\n this.pageRequests.add(\r\n this.track(request, true, (answer) =>\r\n this.htmlState.set(withPages(new Map(this.htmlState()), answer)),\r\n ),\r\n );\r\n }\r\n\r\n /**\r\n * Sends a request the user waits for, and returns its subscription. A `recoverable` request that finds the\r\n * report gone renders it again; every other failure goes on show.\r\n */\r\n private track<T>(\r\n request: Observable<T>,\r\n recoverable: boolean,\r\n next: (value: T) => void,\r\n ): Subscription {\r\n this.pendingState.update((count) => count + 1);\r\n const subscription = request\r\n .pipe(finalize(() => this.pendingState.update((count) => count - 1)))\r\n .subscribe({\r\n next,\r\n error: (failure: NxeViewerFailure) => this.fail(failure, recoverable),\r\n });\r\n this.requests.add(subscription);\r\n return subscription;\r\n }\r\n\r\n /**\r\n * An expired report found by a recoverable request is rendered again, unless a rendering is already on its\r\n * way; every other failure goes on show. Only that rendering settling ends the recovery, so failures in the\r\n * meantime cannot start a second one.\r\n */\r\n private fail(failure: NxeViewerFailure, recoverable: boolean): void {\r\n if (failure.type === 'CacheExpired' && recoverable) {\r\n if (!this.recovering) {\r\n this.recovering = true;\r\n this.render();\r\n }\r\n return;\r\n }\r\n this.failureState.set(failure);\r\n this.failed.next(failure);\r\n }\r\n\r\n /** UpdateCache every three minutes while the server keeps the report. Its failures are not shown. */\r\n private startKeepAlive(context: NxeRequestContext, session: NxeServerSession): void {\r\n const { allowAutoUpdateCache, cacheMode } = session.options.server;\r\n if (!allowAutoUpdateCache || cacheMode === 'None') return;\r\n this.keepAlive = interval(NXE_KEEP_ALIVE_MS)\r\n .pipe(\r\n exhaustMap(() => this.client.updateCache(context, session).pipe(catchError(() => EMPTY))),\r\n )\r\n .subscribe();\r\n }\r\n\r\n /** Stops every request and the keep-alive. */\r\n private close(): void {\r\n this.requests.unsubscribe();\r\n this.requests = new Subscription();\r\n this.pageRequests = new Subscription();\r\n this.keepAlive.unsubscribe();\r\n this.session = null;\r\n this.pagesOnTheWay.clear();\r\n this.recovering = false;\r\n }\r\n\r\n private connection(): { context: NxeRequestContext; session: NxeServerSession } {\r\n if (!this.context || !this.session) throw new Error('The viewer has no report open.');\r\n return { context: this.context, session: this.session };\r\n }\r\n}\r\n","import { ChangeDetectionStrategy, Component, computed, input, output, signal } from '@angular/core';\r\nimport type { NxeViewerOptions, NxeViewMode } from '../protocol/nxe-viewer-options.model';\r\nimport { NXE_ENGLISH, type NxeViewerStrings } from '../strings/nxe-viewer-strings.const';\r\n\r\n/** The zoom menu's fixed percentages, in Stimulsoft's order, above the two fit items. */\r\nconst ZOOM_PRESETS = [25, 50, 75, 100, 150, 200] as const;\r\n\r\n/** The view-mode menu's items, in Stimulsoft's order. */\r\nconst VIEW_MODES = ['SinglePage', 'Continuous', 'MultiplePages'] as const satisfies readonly NxeViewMode[];\r\n\r\n/**\r\n * The toolbar, as Stimulsoft 2025.1.4 draws it in its default theme, Office2022WhiteBlue.\r\n *\r\n * The items and the rules for each are Stimulsoft's (angular-viewer-toolbar-view.md §1): Save and\r\n * Resources, Find, the page navigation and the page control, then Zoom and View mode, each group\r\n * opened by a separator whose condition is the group's own. Buttons for what this viewer does not do\r\n * yet — Print, Open, Send Email, Bookmarks, Parameters, Editor, Full Screen — are left out; bright and\r\n * orbit turn all of them off.\r\n *\r\n * The look was measured on Stimulsoft's own viewer, side by side with this one: a 31 px bar with a 1 px\r\n * #c6c6c6 border and 3 px corners, 12 px Arial in #202020; 24 x 25 buttons with a transparent 1 px\r\n * border, #dadada under the mouse or while their menu is open, #e5e5e5 while selected, and a half\r\n * transparent icon when disabled; 1 x 21 separators in #d4d4d4; menus with a 1 px #ababab border, a\r\n * 7 px shadow and 24 px items. The icons are this package's own drawings in the same colours.\r\n *\r\n * Navigation is disabled the way Stimulsoft disables it: in `MultiplePages`, and in `Continuous`\r\n * unless the report panel or the whole viewer scrolls. A button is disabled at the end of the report it\r\n * would move past, and everything is disabled while a request the user waits for is on its way.\r\n */\r\n@Component({\r\n selector: 'nxe-viewer-toolbar',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'nxe-viewer-toolbar',\r\n role: 'toolbar',\r\n '[style.color]': 'fontColor()',\r\n '[style.font-family]': 'fontFamily()',\r\n '[class.nxe-busy]': 'busy()',\r\n },\r\n template: `\r\n <div\r\n class=\"nxe-toolbar-bar\"\r\n [style.background-color]=\"backgroundColor()\"\r\n [style.border]=\"border()\"\r\n [style.justify-content]=\"justifyContent()\"\r\n >\r\n @if (showSave()) {\r\n <div class=\"nxe-toolbar-menu\">\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [attr.aria-label]=\"strings().SaveToolTip\"\r\n [attr.aria-expanded]=\"openMenu() === 'save'\"\r\n (click)=\"toggleMenu('save')\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path d=\"M1.5 1.5h13v13h-13z\" fill=\"#d890d8\" stroke=\"#903098\" />\r\n <path d=\"M4.5 1.5h7v4.5h-7z\" fill=\"#fff\" stroke=\"#903098\" />\r\n <path d=\"M3.5 9.5h9v5h-9z\" fill=\"#fff\" stroke=\"#903098\" />\r\n </svg>\r\n </span>\r\n @if (showCaptions()) {\r\n <span class=\"nxe-toolbar-caption\">{{ strings().Save }}</span>\r\n }\r\n <span class=\"nxe-toolbar-arrow\">\r\n <svg viewBox=\"0 0 8 8\" aria-hidden=\"true\">\r\n <path d=\"M1.5 2.5 4 5l2.5-2.5\" fill=\"none\" stroke=\"#787878\" />\r\n </svg>\r\n </span>\r\n </button>\r\n @if (openMenu() === 'save') {\r\n <div class=\"nxe-toolbar-popup\" role=\"menu\">\r\n @for (format of saveFormats(); track format) {\r\n <button type=\"button\" class=\"nxe-toolbar-item\" role=\"menuitem\" (click)=\"save(format)\">\r\n <span class=\"nxe-toolbar-item-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path d=\"M3.5.5h7l3 3v12h-10z\" fill=\"#fff\" stroke=\"#6e6e6e\" />\r\n <path d=\"M10.5.5v3h3\" fill=\"none\" stroke=\"#6e6e6e\" />\r\n @if (format === 'Pdf') {\r\n <path d=\"M.5 6.5h11v5H.5z\" fill=\"#f6d0d0\" stroke=\"#d83b3b\" />\r\n <text x=\"6\" y=\"10.4\" fill=\"#d83b3b\" font-family=\"Arial\" font-size=\"4.2\" font-weight=\"bold\" text-anchor=\"middle\">PDF</text>\r\n } @else {\r\n <path d=\"M.5 6.5h13v5H.5z\" fill=\"#d6e9f8\" stroke=\"#2088d0\" />\r\n <text x=\"7\" y=\"10.4\" fill=\"#2088d0\" font-family=\"Arial\" font-size=\"4\" font-weight=\"bold\" text-anchor=\"middle\">HTML</text>\r\n }\r\n </svg>\r\n </span>\r\n <span class=\"nxe-toolbar-item-text\">{{ formatCaption(format) }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n @if (showPanelsSeparator()) {\r\n <span class=\"nxe-toolbar-separator\"></span>\r\n }\r\n @if (showResources()) {\r\n <!-- A report's resources are not served yet, so there are none to show: Stimulsoft disables the button then. -->\r\n <button type=\"button\" class=\"nxe-toolbar-button\" disabled [attr.aria-label]=\"strings().Resources\">\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\" stroke=\"#313131\">\r\n <path d=\"M6.5 1.5h5l3 3v8h-8z\" fill=\"#fff\" />\r\n <path d=\"M11.5 1.5v3h3\" />\r\n <path d=\"M1.5 4.5h5v10h-5z\" fill=\"#fff\" />\r\n <path d=\"M2.5 7.5h3m-3 2h3m-3 2h3\" stroke=\"#717171\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showFindSeparator()) {\r\n <span class=\"nxe-toolbar-separator\"></span>\r\n }\r\n @if (showFind()) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [class.nxe-toolbar-selected]=\"findOpen()\"\r\n [attr.aria-label]=\"strings().FindToolTip\"\r\n [attr.aria-pressed]=\"findOpen()\"\r\n (click)=\"findToggle.emit()\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\" stroke=\"#383838\">\r\n <circle cx=\"9.5\" cy=\"6.5\" r=\"4.4\" stroke-width=\"1.4\" />\r\n <path d=\"M6.4 9.6 2 14\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showNavigationSeparator()) {\r\n <span class=\"nxe-toolbar-separator\"></span>\r\n }\r\n @if (showFirstPage()) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [disabled]=\"atStart()\"\r\n [attr.aria-label]=\"strings().FirstPage\"\r\n (click)=\"goTo(0)\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"#81c1f1\" stroke=\"#0161b1\" stroke-linejoin=\"round\">\r\n <path d=\"M3.5 2.5h2v11h-2z\" />\r\n <path d=\"M12.5 2.5v11l-6-5.5z\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showPreviousPage()) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [disabled]=\"atStart()\"\r\n [attr.aria-label]=\"strings().PrevPage\"\r\n (click)=\"goTo(pageIndex() - 1)\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"#81c1f1\" stroke=\"#0161b1\" stroke-linejoin=\"round\">\r\n <path d=\"M10.5 2.5v11l-6-5.5z\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showCurrentPage()) {\r\n <span class=\"nxe-page-control\">\r\n <span class=\"nxe-page-label\">{{ strings().Page }}</span>\r\n <span class=\"nxe-page-box-cell\" [class.nxe-page-box-off]=\"pageControlDisabled()\">\r\n <input\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n class=\"nxe-page-box\"\r\n [disabled]=\"pageControlDisabled()\"\r\n [value]=\"pageIndex() + 1\"\r\n [attr.aria-label]=\"strings().Page\"\r\n (keydown.enter)=\"enterPage($event)\"\r\n />\r\n </span>\r\n <span class=\"nxe-page-label\">{{ strings().PageOf }}</span>\r\n <span class=\"nxe-page-label\">{{ pageCount() }}</span>\r\n </span>\r\n }\r\n @if (showNextPage()) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [disabled]=\"atEnd()\"\r\n [attr.aria-label]=\"strings().NextPage\"\r\n (click)=\"goTo(pageIndex() + 1)\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"#81c1f1\" stroke=\"#0161b1\" stroke-linejoin=\"round\">\r\n <path d=\"M5.5 2.5v11l6-5.5z\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showLastPage()) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [disabled]=\"atEnd()\"\r\n [attr.aria-label]=\"strings().LastPage\"\r\n (click)=\"goTo(pageCount() - 1)\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"#81c1f1\" stroke=\"#0161b1\" stroke-linejoin=\"round\">\r\n <path d=\"M3.5 2.5v11l6-5.5z\" />\r\n <path d=\"M10.5 2.5h2v11h-2z\" />\r\n </svg>\r\n </span>\r\n </button>\r\n }\r\n @if (showZoom() || showViewMode()) {\r\n <span class=\"nxe-toolbar-separator\"></span>\r\n }\r\n @if (showZoom()) {\r\n <div class=\"nxe-toolbar-menu\">\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [attr.aria-label]=\"strings().ZoomToolTip\"\r\n [attr.aria-expanded]=\"openMenu() === 'zoom'\"\r\n (click)=\"toggleMenu('zoom')\"\r\n >\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\">\r\n <path d=\"M2.5 1.5h6l3 3v5M8.5 1.5v3h3M2.5 1.5v13h7\" stroke=\"#383838\" />\r\n <circle cx=\"11.5\" cy=\"11.5\" r=\"2\" stroke=\"#2088d0\" />\r\n <path d=\"m13 13 1.8 1.8\" stroke=\"#2088d0\" />\r\n </svg>\r\n </span>\r\n @if (showCaptions()) {\r\n <span class=\"nxe-toolbar-caption\">{{ zoomCaption() }}</span>\r\n }\r\n <span class=\"nxe-toolbar-arrow\">\r\n <svg viewBox=\"0 0 8 8\" aria-hidden=\"true\">\r\n <path d=\"M1.5 2.5 4 5l2.5-2.5\" fill=\"none\" stroke=\"#787878\" />\r\n </svg>\r\n </span>\r\n </button>\r\n @if (openMenu() === 'zoom') {\r\n <div class=\"nxe-toolbar-popup\" role=\"menu\">\r\n @for (percent of zoomPresets; track percent) {\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-item\"\r\n role=\"menuitem\"\r\n [class.nxe-toolbar-item-on]=\"isZoom(percent)\"\r\n (click)=\"chooseZoom(percent)\"\r\n >\r\n <span class=\"nxe-toolbar-item-icon\"></span>\r\n <span class=\"nxe-toolbar-item-text\">{{ percent }}%</span>\r\n </button>\r\n }\r\n <span class=\"nxe-toolbar-item-separator\"></span>\r\n <button type=\"button\" class=\"nxe-toolbar-item\" role=\"menuitem\" (click)=\"fit('page')\">\r\n <span class=\"nxe-toolbar-item-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\">\r\n <path d=\"M3.5 1.5h9v13h-9z\" fill=\"#fff\" stroke=\"#383838\" />\r\n <path d=\"M8 3.5v9M6 5.5l2-2 2 2M6 10.5l2 2 2-2\" stroke=\"#2088d0\" />\r\n </svg>\r\n </span>\r\n <span class=\"nxe-toolbar-item-text\">{{ strings().ZoomOnePage }}</span>\r\n </button>\r\n <button type=\"button\" class=\"nxe-toolbar-item\" role=\"menuitem\" (click)=\"fit('width')\">\r\n <span class=\"nxe-toolbar-item-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\">\r\n <path d=\"M1.5 3.5h13v9h-13z\" fill=\"#fff\" stroke=\"#383838\" />\r\n <path d=\"M3.5 8h9M5.5 6l-2 2 2 2M10.5 6l2 2-2 2\" stroke=\"#2088d0\" />\r\n </svg>\r\n </span>\r\n <span class=\"nxe-toolbar-item-text\">{{ strings().ZoomPageWidth }}</span>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n @if (showViewMode()) {\r\n <div class=\"nxe-toolbar-menu\">\r\n <button\r\n type=\"button\"\r\n class=\"nxe-toolbar-button\"\r\n [attr.aria-label]=\"strings().ViewModeToolTip\"\r\n [attr.aria-expanded]=\"openMenu() === 'viewMode'\"\r\n (click)=\"toggleMenu('viewMode')\"\r\n >\r\n <!-- Stimulsoft's button keeps the single-page icon whatever the mode. -->\r\n <span class=\"nxe-toolbar-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\r\n <path d=\"M2.5 1.5h11v13h-11z\" fill=\"#fff\" stroke=\"#383838\" />\r\n </svg>\r\n </span>\r\n @if (showCaptions()) {\r\n <span class=\"nxe-toolbar-caption\">{{ strings()[viewMode()] }}</span>\r\n }\r\n <span class=\"nxe-toolbar-arrow\">\r\n <svg viewBox=\"0 0 8 8\" aria-hidden=\"true\">\r\n <path d=\"M1.5 2.5 4 5l2.5-2.5\" fill=\"none\" stroke=\"#787878\" />\r\n </svg>\r\n </span>\r\n </button>\r\n @if (openMenu() === 'viewMode') {\r\n <!-- Stimulsoft marks no item here as the current one, unlike the zoom menu. -->\r\n <div class=\"nxe-toolbar-popup\" role=\"menu\">\r\n @for (mode of viewModes; track mode) {\r\n <button type=\"button\" class=\"nxe-toolbar-item\" role=\"menuitem\" (click)=\"chooseViewMode(mode)\">\r\n <span class=\"nxe-toolbar-item-icon\">\r\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"#fff\" stroke=\"#383838\">\r\n @switch (mode) {\r\n @case ('SinglePage') {\r\n <path d=\"M2.5 1.5h11v13h-11z\" />\r\n }\r\n @case ('Continuous') {\r\n <path d=\"M2.5 1.5h11v4h-11zm0 6h11v7h-11z\" />\r\n }\r\n @case ('MultiplePages') {\r\n <path d=\"M2.5 2.5h5v5h-5zm6 0h5v5h-5zm-6 6h5v5h-5zm6 0h5v5h-5z\" />\r\n }\r\n }\r\n </svg>\r\n </span>\r\n <span class=\"nxe-toolbar-item-text\">{{ strings()[mode] }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: `\r\n /* The bar sits 2 px below the top of the toolbar's own box, as Stimulsoft's toolbar table does. */\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n padding-top: 2px;\r\n position: relative;\r\n user-select: none;\r\n font-family: Arial;\r\n font-size: 12px;\r\n color: #202020;\r\n }\r\n\r\n /* Stimulsoft covers the toolbar with a disabled panel while a request is in flight. */\r\n :host(.nxe-busy)::after {\r\n content: '';\r\n position: absolute;\r\n inset: 0;\r\n cursor: default;\r\n }\r\n\r\n .nxe-toolbar-bar {\r\n display: flex;\r\n align-items: center;\r\n box-sizing: border-box;\r\n height: 31px;\r\n padding: 1px;\r\n border: 1px solid #c6c6c6;\r\n border-radius: 3px;\r\n background: #fff;\r\n cursor: default;\r\n }\r\n\r\n /*\r\n * A button is a 22 px icon cell, then its caption and its menu's 18 px arrow cell when it has\r\n * them, inside a transparent 1 px border and a 1 px margin: 24 x 25 for an icon alone.\r\n */\r\n .nxe-toolbar-button {\r\n display: inline-flex;\r\n align-items: center;\r\n box-sizing: border-box;\r\n height: 25px;\r\n margin: 1px;\r\n padding: 0;\r\n border: 1px solid transparent;\r\n border-radius: 3px;\r\n background: transparent;\r\n color: inherit;\r\n font: inherit;\r\n white-space: nowrap;\r\n cursor: default;\r\n }\r\n\r\n .nxe-toolbar-button:hover:not(:disabled),\r\n .nxe-toolbar-button[aria-expanded='true'] {\r\n background: #dadada;\r\n }\r\n\r\n .nxe-toolbar-button.nxe-toolbar-selected {\r\n background: #e5e5e5;\r\n }\r\n\r\n .nxe-toolbar-button:disabled {\r\n color: rgb(214 211 214);\r\n }\r\n\r\n .nxe-toolbar-button:disabled svg {\r\n opacity: 0.5;\r\n }\r\n\r\n .nxe-toolbar-icon {\r\n display: flex;\r\n flex: none;\r\n box-sizing: border-box;\r\n width: 22px;\r\n padding-left: 3px;\r\n }\r\n\r\n .nxe-toolbar-icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .nxe-toolbar-arrow {\r\n display: flex;\r\n flex: none;\r\n justify-content: center;\r\n width: 18px;\r\n }\r\n\r\n .nxe-toolbar-arrow svg {\r\n width: 8px;\r\n height: 8px;\r\n }\r\n\r\n .nxe-toolbar-separator {\r\n flex: none;\r\n width: 1px;\r\n height: 21px;\r\n background: #d4d4d4;\r\n }\r\n\r\n .nxe-page-control {\r\n display: inline-flex;\r\n align-items: center;\r\n height: 23px;\r\n margin: 0 1px;\r\n white-space: nowrap;\r\n }\r\n\r\n .nxe-page-label,\r\n .nxe-page-box-cell {\r\n padding: 0 2px;\r\n }\r\n\r\n .nxe-page-box-cell {\r\n display: flex;\r\n }\r\n\r\n /* Stimulsoft's text box: #ababab, darker under the mouse, and no change or outline on focus. */\r\n .nxe-page-box {\r\n box-sizing: border-box;\r\n width: 51px;\r\n height: 23px;\r\n margin: 0;\r\n padding: 0 0 0 4px;\r\n border: 1px solid #ababab;\r\n border-radius: 3px;\r\n background: #fff;\r\n color: inherit;\r\n font: inherit;\r\n line-height: 21px;\r\n text-align: left;\r\n outline: none;\r\n }\r\n\r\n .nxe-page-box:hover:not(:disabled) {\r\n border-color: #6b6b6b;\r\n }\r\n\r\n /*\r\n * A disabled box keeps its number in the toolbar's colour and is drawn at half opacity, box and all.\r\n * Stimulsoft never disables the input itself: its text-box element around the input is 50 % opaque\r\n * and transparent in colour, while the input keeps toolbar.fontColor -- measured against Stimulsoft\r\n * 2025.1.4 on a one-page report, where the \"1\" reads rgb(32, 32, 32) at half strength. Painting the\r\n * input itself transparent left the viewer showing \"Page [nothing] of 1\".\r\n */\r\n .nxe-page-box:disabled {\r\n border-color: #e1e1e1;\r\n background: #f7f7f7;\r\n color: inherit;\r\n -webkit-text-fill-color: currentColor;\r\n opacity: 1;\r\n }\r\n\r\n .nxe-page-box-off {\r\n opacity: 0.5;\r\n }\r\n\r\n .nxe-toolbar-menu {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n }\r\n\r\n /* A menu opens 1 px below its button and 1 px to its left, inside a 1 px border and padding. */\r\n .nxe-toolbar-popup {\r\n position: absolute;\r\n top: 100%;\r\n left: 0;\r\n z-index: 10;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 1px;\r\n box-sizing: border-box;\r\n padding: 1px;\r\n border: 1px solid #ababab;\r\n border-radius: 3px;\r\n background: #fff;\r\n box-shadow: 0 0 7px rgb(0 0 0 / 30%);\r\n }\r\n\r\n .nxe-toolbar-item {\r\n display: flex;\r\n align-items: center;\r\n flex: none;\r\n box-sizing: border-box;\r\n height: 24px;\r\n margin: 0 1px;\r\n padding: 0;\r\n border: 0;\r\n border-radius: 3px;\r\n background: transparent;\r\n color: #202020;\r\n font: inherit;\r\n text-align: left;\r\n white-space: nowrap;\r\n cursor: default;\r\n }\r\n\r\n .nxe-toolbar-item:first-child {\r\n margin-top: 1px;\r\n }\r\n\r\n .nxe-toolbar-item:last-child {\r\n margin-bottom: 1px;\r\n }\r\n\r\n .nxe-toolbar-item-on {\r\n background: #e5e5e5;\r\n }\r\n\r\n .nxe-toolbar-item:hover {\r\n background: #dadada;\r\n }\r\n\r\n /* Every item lines its caption up past a 22 px icon cell, whether or not it has an icon. */\r\n .nxe-toolbar-item-icon {\r\n display: flex;\r\n flex: none;\r\n box-sizing: border-box;\r\n width: 22px;\r\n padding-left: 3px;\r\n }\r\n\r\n .nxe-toolbar-item-icon svg {\r\n width: 16px;\r\n height: 16px;\r\n }\r\n\r\n .nxe-toolbar-item-text {\r\n padding: 0 20px 0 7px;\r\n }\r\n\r\n .nxe-toolbar-item-separator {\r\n flex: none;\r\n height: 1px;\r\n margin: 0 2px 0 30px;\r\n background: #d4d4d4;\r\n }\r\n `,\r\n})\r\nexport class NxeViewerToolbarComponent {\r\n /** The options from the server, or null before the first answer, when the toolbar shows nothing. */\r\n readonly options = input<NxeViewerOptions | null>(null);\r\n /** The 0-based index of the page on screen. */\r\n readonly pageIndex = input(0);\r\n /** How many pages the report has. */\r\n readonly pageCount = input(0);\r\n /** Whether a request the user waits for is on its way. */\r\n readonly busy = input(false);\r\n /** The captions to show. */\r\n readonly strings = input<NxeViewerStrings>(NXE_ENGLISH);\r\n /** The mode the pages are shown in. */\r\n readonly viewMode = input<NxeViewMode>('SinglePage');\r\n /** The zoom the pages are drawn at, as a factor: 1 is 100 %. */\r\n readonly zoom = input(1);\r\n /** Whether the find panel is open, which Stimulsoft's Find button shows as its selected state. */\r\n readonly findOpen = input(false);\r\n\r\n /** The 0-based page the user asked for. */\r\n readonly goToPage = output<number>();\r\n /** The mode the user chose. */\r\n readonly viewModeChange = output<NxeViewMode>();\r\n /** The zoom the user chose, as a factor. */\r\n readonly zoomChange = output<number>();\r\n /** The user asked to fit a whole page, or the page's width, in the panel. */\r\n readonly fitRequest = output<'page' | 'width'>();\r\n /** The format the user asked the report to be saved as. */\r\n readonly saveRequest = output<string>();\r\n /** The user pressed Find, which opens the find panel or closes it. */\r\n readonly findToggle = output<void>();\r\n\r\n protected readonly zoomPresets = ZOOM_PRESETS;\r\n protected readonly viewModes = VIEW_MODES;\r\n\r\n /** Which menu is open, or null. Stimulsoft opens one at a time and closes it on the next click. */\r\n private readonly openMenuState = signal<'save' | 'zoom' | 'viewMode' | null>(null);\r\n protected readonly openMenu = this.openMenuState.asReadonly();\r\n\r\n /**\r\n * The save menu's formats, in the order Stimulsoft lists them, and only those the server turned on.\r\n * The button itself is left out when no format is on, as Stimulsoft forces it off then.\r\n */\r\n protected readonly saveFormats = computed(() => {\r\n const exports = this.options()?.exports;\r\n if (!exports) return [];\r\n const formats: string[] = [];\r\n if (exports.showExportToPdf) formats.push('Pdf');\r\n if (exports.showExportToHtml) formats.push('Html');\r\n return formats;\r\n });\r\n\r\n protected readonly showSave = computed(\r\n () => this.toolbar()?.showSaveButton === true && this.saveFormats().length > 0,\r\n );\r\n\r\n /** The caption Stimulsoft's save menu gives a format. */\r\n protected formatCaption(format: string): string {\r\n return format === 'Pdf' ? this.strings().formatPdf : this.strings().formatHtml;\r\n }\r\n\r\n protected save(format: string): void {\r\n this.openMenuState.set(null);\r\n this.saveRequest.emit(format);\r\n }\r\n\r\n /**\r\n * The zoom as a rounded percentage, as Stimulsoft captions the button, and empty when the zoom is\r\n * unknown or zero.\r\n */\r\n protected readonly zoomCaption = computed(() => {\r\n const zoom = this.zoom();\r\n return Number.isFinite(zoom) && zoom > 0 ? `${Math.round(zoom * 100)}%` : '';\r\n });\r\n\r\n private readonly toolbar = computed(() => this.options()?.toolbar ?? null);\r\n private readonly appearance = computed(() => this.options()?.appearance ?? null);\r\n\r\n /**\r\n * Stimulsoft's rule: navigation is off in `MultiplePages`, and in `Continuous` unless the report\r\n * panel scrolls or the viewer is full screen — in those cases the page is reached by scrolling.\r\n */\r\n private readonly navigationDisabled = computed(() => {\r\n const toolbar = this.toolbar();\r\n const appearance = this.appearance();\r\n if (!toolbar || !appearance) return true;\r\n if (toolbar.viewMode === 'MultiplePages') return true;\r\n return (\r\n toolbar.viewMode === 'Continuous' &&\r\n !appearance.scrollbarsMode &&\r\n !appearance.fullScreenMode\r\n );\r\n });\r\n\r\n /** Save, Zoom and View mode show their captions unless the server turns captions off. */\r\n protected readonly showCaptions = computed(() => this.toolbar()?.showButtonCaptions !== false);\r\n\r\n protected readonly showResources = computed(() => this.toolbar()?.showResourcesButton === true);\r\n protected readonly showFind = computed(() => this.toolbar()?.showFindButton === true);\r\n protected readonly showFirstPage = computed(() => this.toolbar()?.showFirstPageButton === true);\r\n protected readonly showPreviousPage = computed(\r\n () => this.toolbar()?.showPreviousPageButton === true,\r\n );\r\n protected readonly showCurrentPage = computed(\r\n () => this.toolbar()?.showCurrentPageControl === true,\r\n );\r\n protected readonly showNextPage = computed(() => this.toolbar()?.showNextPageButton === true);\r\n protected readonly showLastPage = computed(() => this.toolbar()?.showLastPageButton === true);\r\n protected readonly showZoom = computed(() => this.toolbar()?.showZoomButton === true);\r\n protected readonly showViewMode = computed(() => this.toolbar()?.showViewModeButton === true);\r\n\r\n /**\r\n * Stimulsoft opens the panels group — Bookmarks, Parameters, Resources — only when Bookmarks or\r\n * Parameters is on; Resources alone follows Save with no separator, as bright and orbit show it.\r\n */\r\n protected readonly showPanelsSeparator = computed(\r\n () =>\r\n this.toolbar()?.showBookmarksButton === true || this.toolbar()?.showParametersButton === true,\r\n );\r\n\r\n /** Stimulsoft opens the Find group whenever Find or Editor is on, whatever comes before it. */\r\n protected readonly showFindSeparator = computed(\r\n () => this.toolbar()?.showFindButton === true || this.toolbar()?.showEditorButton === true,\r\n );\r\n\r\n /** And the navigation group whenever any of its five items is on. */\r\n protected readonly showNavigationSeparator = computed(\r\n () =>\r\n this.showFirstPage() ||\r\n this.showPreviousPage() ||\r\n this.showCurrentPage() ||\r\n this.showNextPage() ||\r\n this.showLastPage(),\r\n );\r\n\r\n /** Whether a preset is the zoom on show, so its menu item reads as chosen. */\r\n protected isZoom(percent: number): boolean {\r\n return Math.round(this.zoom() * 100) === percent;\r\n }\r\n\r\n /** Opens a menu, or closes it when it is the one already open. */\r\n protected toggleMenu(menu: 'save' | 'zoom' | 'viewMode'): void {\r\n this.openMenuState.update((open) => (open === menu ? null : menu));\r\n }\r\n\r\n protected chooseZoom(percent: number): void {\r\n this.openMenuState.set(null);\r\n this.zoomChange.emit(percent / 100);\r\n }\r\n\r\n protected fit(what: 'page' | 'width'): void {\r\n this.openMenuState.set(null);\r\n this.fitRequest.emit(what);\r\n }\r\n\r\n protected chooseViewMode(mode: NxeViewMode): void {\r\n this.openMenuState.set(null);\r\n this.viewModeChange.emit(mode);\r\n }\r\n\r\n protected readonly atStart = computed(\r\n () => this.busy() || this.navigationDisabled() || this.pageIndex() <= 0,\r\n );\r\n protected readonly atEnd = computed(\r\n () => this.busy() || this.navigationDisabled() || this.pageIndex() >= this.pageCount() - 1,\r\n );\r\n protected readonly pageControlDisabled = computed(\r\n () => this.busy() || this.navigationDisabled() || this.pageCount() <= 1,\r\n );\r\n\r\n protected readonly backgroundColor = computed(() => this.toolbar()?.backgroundColor || null);\r\n protected readonly fontColor = computed(() => this.toolbar()?.fontColor || null);\r\n protected readonly fontFamily = computed(() => this.toolbar()?.fontFamily || null);\r\n\r\n /**\r\n * The server's border colour in `Simple`, and none at all in `Separated`, as Stimulsoft's toolbar\r\n * does; without a colour the theme's own border stays.\r\n */\r\n protected readonly border = computed(() => {\r\n const toolbar = this.toolbar();\r\n if (!toolbar) return null;\r\n if (toolbar.displayMode === 'Separated') return '0';\r\n return toolbar.borderColor ? `1px solid ${toolbar.borderColor}` : null;\r\n });\r\n\r\n protected readonly justifyContent = computed(() => {\r\n switch (this.toolbar()?.alignment) {\r\n case 'Center':\r\n return 'center';\r\n case 'Right':\r\n return 'flex-end';\r\n default:\r\n return 'flex-start';\r\n }\r\n });\r\n\r\n /**\r\n * Enter in the page box goes to the page typed, reading anything that is not a number as page 1\r\n * and clamping to the report, as Stimulsoft's page control does. Leaving the box does nothing.\r\n */\r\n protected enterPage(event: Event): void {\r\n const box = event.target as HTMLInputElement;\r\n const typed = Number.parseInt(box.value, 10);\r\n const page = Math.min(Math.max(Number.isNaN(typed) ? 1 : typed, 1), this.pageCount());\r\n box.value = String(page);\r\n this.goTo(page - 1);\r\n }\r\n\r\n protected goTo(index: number): void {\r\n if (this.busy() || index === this.pageIndex() || index < 0 || index >= this.pageCount()) return;\r\n this.goToPage.emit(index);\r\n }\r\n}\r\n","import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n ElementRef,\r\n inject,\r\n input,\r\n linkedSignal,\r\n OnChanges,\r\n output,\r\n signal,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { distinctUntilChanged, skip } from 'rxjs';\r\nimport { clearHits, findHits, labelHits, markCurrent } from '../find/nxe-find.util';\r\nimport {\r\n NxeViewerFindPanelComponent,\r\n type NxeFindRequest,\r\n} from '../find/nxe-viewer-find-panel.component';\r\nimport { NxeReportPageComponent } from '../page/nxe-report-page.component';\r\nimport type { NxeViewerFailure } from '../protocol/nxe-protocol.model';\r\nimport type { NxeViewMode } from '../protocol/nxe-viewer-options.model';\r\n\r\n/** Stimulsoft's scroll tracker waits this long after scrolling stops before it moves the page. */\r\nconst SCROLL_SETTLE_MS = 300;\r\n/** And animates a navigation scroll over this long, in steps of about this many milliseconds. */\r\nconst SCROLL_ANIMATION_MS = 350;\r\nconst SCROLL_STEP_MS = 30;\r\n/** The viewer never measures itself smaller than this, nor closer than this to the window's bottom. */\r\nconst MIN_PANEL_HEIGHT = 200;\r\nconst VIEWER_BOTTOM_GAP = 16;\r\n/** Stimulsoft scrolls a hit to its own height plus this far below the top of the report panel. */\r\nconst FIND_SCROLL_GAP = 50;\r\nimport {\r\n NxeViewerClientService,\r\n type NxePostParametersFunction,\r\n type NxeRequestContext,\r\n} from '../protocol/nxe-viewer-client.service';\r\nimport { NxeViewerSessionService } from '../session/nxe-viewer-session.service';\r\nimport { NXE_ENGLISH } from '../strings/nxe-viewer-strings.const';\r\nimport { NxeViewerToolbarComponent } from '../toolbar/nxe-viewer-toolbar.component';\r\n\r\n/**\r\n * What a host reaches through the component's `api`, with Stimulsoft's names and meanings. The\r\n * members for zoom, view mode, export, print, email and find arrive with the tasks that implement\r\n * those; a host that only pages through a report needs these three.\r\n */\r\nexport interface NxeViewerApi {\r\n /** The 0-based page on screen. Setting it shows a page inside the report and ignores anything else. */\r\n currentPage: number;\r\n /** How many pages the report has; 0 before one is loaded. */\r\n readonly pagesCount: number;\r\n /** Always `Report`, as Stimulsoft's Angular viewer answers when it is not showing a dashboard. */\r\n readonly reportType: string;\r\n}\r\n\r\n/**\r\n * A report served by `Nextera.Reports.Angular.NetCore`, shown page by page.\r\n *\r\n * The inputs, outputs and `api` are Stimulsoft's `stimulsoft-viewer-angular`, so a host swaps the\r\n * component and keeps its bindings. As there, a change to any input reloads the report: the\r\n * component asks for the viewer's options again and opens the report the action names.\r\n *\r\n * Each viewer provides its own session, so several on a page never share a report or a token.\r\n */\r\n@Component({\r\n selector: 'nxe-report-viewer',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n imports: [NxeReportPageComponent, NxeViewerFindPanelComponent, NxeViewerToolbarComponent],\r\n providers: [NxeViewerClientService, NxeViewerSessionService],\r\n host: { '(window:resize)': 'onWindowResize()' },\r\n template: `\r\n <div\r\n #rootBox\r\n class=\"nxe-viewer-root\"\r\n [style]=\"style()\"\r\n [style.background-color]=\"rootBackgroundColor()\"\r\n [style.width]=\"rootWidth()\"\r\n [style.height]=\"rootHeight()\"\r\n >\r\n @if (toolbarVisible()) {\r\n <nxe-viewer-toolbar\r\n [options]=\"session.options()\"\r\n [pageIndex]=\"session.pageIndex()\"\r\n [pageCount]=\"session.pageCount()\"\r\n [busy]=\"session.busy()\"\r\n [viewMode]=\"viewMode()\"\r\n [zoom]=\"zoom()\"\r\n [findOpen]=\"findOpen()\"\r\n (goToPage)=\"navigateTo($event)\"\r\n (viewModeChange)=\"setViewMode($event)\"\r\n (zoomChange)=\"setZoom($event)\"\r\n (fitRequest)=\"fitTo($event)\"\r\n (saveRequest)=\"session.exportTo($event)\"\r\n (findToggle)=\"toggleFind()\"\r\n />\r\n }\r\n @if (findOpen()) {\r\n <nxe-viewer-find-panel (search)=\"find($event)\" (closed)=\"closeFind()\" />\r\n }\r\n\r\n <div class=\"nxe-viewer-body\">\r\n @if (showBookmarksStrip()) {\r\n <div class=\"nxe-viewer-bookmarks\"></div>\r\n }\r\n <div\r\n #pagesBox\r\n class=\"nxe-viewer-pages\"\r\n [class.nxe-viewer-continuous]=\"viewMode() === 'Continuous'\"\r\n [class.nxe-viewer-pages-beside]=\"showBookmarksStrip()\"\r\n [style.text-align]=\"pageAlignment()\"\r\n [style.overflow]=\"pagesOverflow()\"\r\n (scroll)=\"onScroll()\"\r\n >\r\n @for (page of shownPages(); track page.index) {\r\n <nxe-report-page\r\n class=\"nxe-viewer-page\"\r\n [class.nxe-viewer-page-shadow]=\"showPageShadow()\"\r\n [style.border]=\"pageBorder()\"\r\n [page]=\"page.size\"\r\n [html]=\"page.html\"\r\n [css]=\"pageCss()\"\r\n [zoom]=\"zoom()\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (session.failure(); as failure) {\r\n <div class=\"nxe-viewer-failure\" role=\"alert\">\r\n <span class=\"nxe-viewer-failure-text\">{{ failure.message }}</span>\r\n <button type=\"button\" class=\"nxe-viewer-failure-close\" (click)=\"session.dismissFailure()\">\r\n ×\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: `\r\n /*\r\n * The host is an inline box and the viewer an inline block inside it, as Stimulsoft's element and\r\n * its span are: a width or height of 100 % then resolves against the element that holds the\r\n * viewer, not against the viewer's own content, so the viewer fills that element and the pages sit\r\n * in the middle of it.\r\n */\r\n :host {\r\n display: inline;\r\n }\r\n\r\n .nxe-viewer-root {\r\n display: inline-flex;\r\n flex-direction: column;\r\n box-sizing: border-box;\r\n position: relative;\r\n }\r\n\r\n /* The report panel starts 2 px below the toolbar and the find panel. */\r\n .nxe-viewer-body {\r\n position: relative;\r\n display: flex;\r\n flex: 1 1 auto;\r\n min-height: 0;\r\n margin-top: 2px;\r\n }\r\n\r\n /*\r\n * Stimulsoft always has a bookmark, the report itself, so its bookmarks panel opens with every\r\n * report. With bookmarksTreeWidth 0, as bright and orbit set it, all that shows of it is a 5 px\r\n * strip with a border either side down the left edge, and the report panel moves 2 px right.\r\n */\r\n .nxe-viewer-bookmarks {\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n box-sizing: border-box;\r\n width: 5px;\r\n border-left: 1px solid #c6c6c6;\r\n border-right: 1px solid #c6c6c6;\r\n background: #fff;\r\n }\r\n\r\n .nxe-viewer-pages {\r\n position: relative;\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n box-sizing: border-box;\r\n padding: 0 10px;\r\n }\r\n\r\n .nxe-viewer-pages-beside {\r\n margin-left: 2px;\r\n }\r\n\r\n /*\r\n * A page carries its own 10 px margin, as Stimulsoft's page element does, so the panel needs no\r\n * padding: the space around the outermost pages is that margin. In SinglePage and MultiplePages\r\n * the pages are inline-block, flow left to right and wrap into rows, and neighbouring margins do\r\n * not collapse, so the gap between two pages is 20 px; the rows sit where pageAlignment puts them.\r\n */\r\n .nxe-viewer-page {\r\n display: inline-block;\r\n vertical-align: top;\r\n margin: 10px;\r\n }\r\n\r\n /*\r\n * In Continuous the page is block-level with automatic side margins, so there is one page a row,\r\n * centred whatever the alignment says, and the 10 px vertical margins of two neighbours collapse\r\n * to a 10 px gap.\r\n */\r\n .nxe-viewer-continuous .nxe-viewer-page {\r\n display: block;\r\n margin: 10px auto;\r\n }\r\n\r\n .nxe-viewer-page-shadow {\r\n box-shadow: 2px 2px 6px rgb(0 0 0 / 30%);\r\n }\r\n\r\n .nxe-viewer-failure {\r\n position: absolute;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n background: #fdecea;\r\n color: #611a15;\r\n font-size: 13px;\r\n }\r\n\r\n .nxe-viewer-failure-text {\r\n flex: 1 1 auto;\r\n }\r\n\r\n .nxe-viewer-failure-close {\r\n border: 0;\r\n background: transparent;\r\n color: inherit;\r\n font-size: 18px;\r\n line-height: 1;\r\n cursor: pointer;\r\n }\r\n `,\r\n})\r\nexport class NxeReportViewerComponent implements OnChanges {\r\n /** Each request's URL, with `{action}` in place of the host action it goes to. */\r\n readonly requestUrl = input('');\r\n /** The host action that answers the first request, and so names the report to open. */\r\n readonly action = input('');\r\n /** Sent to the host with every request, as JSON, when it is truthy. */\r\n readonly properties = input<unknown>(null);\r\n /** The viewer's width; `100%` when it is not given. */\r\n readonly width = input<string | null>(null);\r\n /** The viewer's height; 650px when the report panel scrolls, otherwise `100%`. */\r\n readonly height = input<string | null>(null);\r\n /** The viewer's background; `White` when it is not given. */\r\n readonly backgroundColor = input<string | null>('White');\r\n /** Styles for the viewer's root element. Width, height and background take precedence over it. */\r\n readonly style = input<string | null>(null);\r\n /** Called for every request; each key of an object it returns becomes a form field. */\r\n readonly postParametersFunction = input<NxePostParametersFunction | null>(null);\r\n\r\n /** Emits after each report is loaded. */\r\n readonly loaded = output<void>();\r\n /** Emits every failure the viewer puts on show. */\r\n readonly error = output<NxeViewerFailure>();\r\n\r\n protected readonly session = inject(NxeViewerSessionService);\r\n\r\n /** Stimulsoft's `api` object: what a host calls to drive the viewer from outside. */\r\n readonly api: NxeViewerApi = this.buildApi();\r\n\r\n private readonly appearance = computed(() => this.session.options()?.appearance ?? null);\r\n\r\n private readonly pagesBox = viewChild<ElementRef<HTMLElement>>('pagesBox');\r\n private readonly rootBox = viewChild<ElementRef<HTMLElement>>('rootBox');\r\n\r\n /**\r\n * The mode the pages are shown in, and the zoom they are drawn at. Both start from the server's\r\n * options and are then the user's, until a new report's options arrive and reset them — which is\r\n * what `linkedSignal` says and an effect would only imply.\r\n */\r\n protected readonly viewMode = linkedSignal<NxeViewMode>(\r\n () => this.session.options()?.toolbar.viewMode ?? 'SinglePage',\r\n );\r\n protected readonly zoom = linkedSignal<number>(() => {\r\n const percent = this.session.options()?.toolbar.zoom ?? 100;\r\n return percent > 0 ? percent / 100 : 1;\r\n });\r\n\r\n /**\r\n * The pages on screen: one in `SinglePage`, the whole report in the modes that scroll through it.\r\n * A page carries its size before its HTML arrives, so the list holds its shape while the pages that\r\n * come into view are fetched.\r\n */\r\n protected readonly shownPages = computed(() => {\r\n if (this.viewMode() === 'SinglePage') {\r\n const page = this.session.shownPage();\r\n return page ? [page] : [];\r\n }\r\n return this.session.allPages();\r\n });\r\n\r\n /** Set while a page-navigation scroll is running, so scroll tracking does not fight it. */\r\n private scrollingToPage = false;\r\n private scrollSettled: ReturnType<typeof setTimeout> | null = null;\r\n\r\n protected readonly toolbarVisible = computed(\r\n () => this.session.options()?.toolbar.visible !== false,\r\n );\r\n\r\n /** See `.nxe-viewer-bookmarks`: the whole of Stimulsoft's bookmarks panel at width 0. */\r\n protected readonly showBookmarksStrip = computed(\r\n () => this.session.report() !== null && this.appearance()?.bookmarksTreeWidth === 0,\r\n );\r\n\r\n /** Whether the find panel is open; Stimulsoft's Find button opens and closes it. */\r\n protected readonly findOpen = signal(false);\r\n\r\n /** The search on show: what was looked for, the elements found, and which one is current. */\r\n private findKey: string | null = null;\r\n private hits: HTMLElement[] = [];\r\n private currentHit = 0;\r\n private lastFind: NxeFindRequest | null = null;\r\n\r\n /**\r\n * The pages whose HTML is on screen, so a search can follow them: in SinglePage the page changes\r\n * under it, and in the scrolling modes pages keep arriving as they are fetched.\r\n */\r\n private readonly renderedPages = computed(() =>\r\n this.shownPages()\r\n .map((page) => `${page.index}:${page.html === null ? 0 : 1}`)\r\n .join(','),\r\n );\r\n protected readonly pageCss = computed(() => this.session.report()?.pageCss ?? '');\r\n protected readonly showPageShadow = computed(() => this.appearance()?.showPageShadow === true);\r\n protected readonly pageBorder = computed(() => {\r\n const color = this.appearance()?.pageBorderColor;\r\n return color ? `1px solid ${color}` : null;\r\n });\r\n\r\n /** Stimulsoft aligns the pages with the report panel's text alignment; `Default` means centred. */\r\n protected readonly pageAlignment = computed(() => {\r\n switch (this.appearance()?.pageAlignment) {\r\n case 'Left':\r\n return 'left';\r\n case 'Right':\r\n return 'right';\r\n default:\r\n return 'center';\r\n }\r\n });\r\n\r\n /** The report panel scrolls inside the viewer only when the server asks for scrollbars. */\r\n protected readonly pagesOverflow = computed(() =>\r\n this.appearance()?.scrollbarsMode ? 'auto' : 'hidden',\r\n );\r\n\r\n protected readonly rootWidth = computed(() => this.width() ?? '100%');\r\n protected readonly rootBackgroundColor = computed(() => this.backgroundColor() ?? 'White');\r\n\r\n /**\r\n * The height the viewer was measured to fill, once it is known.\r\n *\r\n * The report panel is what scrolls, as Stimulsoft's does — its panel measures 836 px against a\r\n * 16 513 px report while the document itself does not scroll at all. That needs the viewer to have a\r\n * definite height, and a host that asks for `100%` inside a container whose own height is automatic\r\n * does not give it one: the viewer would then grow to the whole report, 29 pages of it, and the\r\n * page would scroll instead of the panel. So when the height the host asked for cannot resolve, the\r\n * viewer measures the room between its top and the bottom of the window and takes that.\r\n */\r\n private readonly measuredHeight = signal<string | null>(null);\r\n\r\n protected readonly rootHeight = computed(() => {\r\n const measured = this.measuredHeight();\r\n if (measured !== null) return measured;\r\n const given = this.height();\r\n if (given !== null) return given;\r\n return this.appearance()?.scrollbarsMode ? '650px' : '100%';\r\n });\r\n\r\n constructor() {\r\n this.session.reportLoaded.pipe(takeUntilDestroyed()).subscribe(() => {\r\n // The modes that show the whole report start with every page laid out at its size and none of\r\n // them fetched, so the first screenful has to be asked for here; scrolling asks for the rest.\r\n this.afterPagesSettle();\r\n this.loaded.emit();\r\n });\r\n this.session.failed\r\n .pipe(takeUntilDestroyed())\r\n .subscribe((failure) => this.error.emit(failure));\r\n // While a search is on show, new page HTML on screen means the search runs again over it.\r\n toObservable(this.renderedPages)\r\n .pipe(distinctUntilChanged(), skip(1), takeUntilDestroyed())\r\n .subscribe(() => {\r\n if (this.findOpen() && this.lastFind !== null) {\r\n requestAnimationFrame(() => this.refreshFind());\r\n }\r\n });\r\n }\r\n\r\n /** The Find button opens the panel, or closes it and takes the search's highlights away. */\r\n protected toggleFind(): void {\r\n if (this.findOpen()) {\r\n this.closeFind();\r\n return;\r\n }\r\n this.findOpen.set(true);\r\n this.afterPagesSettle();\r\n }\r\n\r\n protected closeFind(): void {\r\n this.findOpen.set(false);\r\n this.resetFind();\r\n this.afterPagesSettle();\r\n }\r\n\r\n /**\r\n * A search from the find panel, run as Stimulsoft runs it (angular-viewer-panels-chrome.md §1.3,\r\n * §1.6): empty text clears the highlights; new text, or a changed option, finds afresh and makes the\r\n * first hit current; the same search again steps to the next or previous hit, round the ends. Each\r\n * current hit is scrolled into view. Stimulsoft finds only in the pages it has on screen; this viewer\r\n * fetches the pages a scrolling mode has not fetched yet, and finds in them as they arrive.\r\n */\r\n protected find(request: NxeFindRequest): void {\r\n this.lastFind = request;\r\n if (request.text === '') {\r\n this.resetFind();\r\n return;\r\n }\r\n const key = `${request.matchCase ? 1 : 0}${request.wholeWord ? 1 : 0}${request.text}`;\r\n if (key !== this.findKey) {\r\n this.findKey = key;\r\n this.requestAllPages();\r\n this.runFind(request, 0);\r\n this.revealHit(true);\r\n return;\r\n }\r\n if (this.hits.length === 0) return;\r\n const previous = this.currentHit;\r\n const count = this.hits.length;\r\n this.currentHit = request.forward ? (previous + 1) % count : (previous - 1 + count) % count;\r\n markCurrent(this.hits, previous, this.currentHit);\r\n this.revealHit(false);\r\n }\r\n\r\n /** Finds again over the pages now on screen, keeping the current hit when it is still there. */\r\n private refreshFind(): void {\r\n const request = this.lastFind;\r\n if (request === null || request.text === '') return;\r\n const kept = this.hits[this.currentHit];\r\n this.runFind(request, 0);\r\n const index = kept ? this.hits.indexOf(kept) : -1;\r\n if (index > 0) {\r\n markCurrent(this.hits, 0, index);\r\n this.currentHit = index;\r\n }\r\n }\r\n\r\n private runFind(request: NxeFindRequest, current: number): void {\r\n const roots = this.pageRoots();\r\n clearHits(roots);\r\n this.hits = findHits(roots, request.text, request);\r\n this.currentHit = current;\r\n labelHits(this.hits, this.currentHit);\r\n }\r\n\r\n private resetFind(): void {\r\n clearHits(this.pageRoots());\r\n this.hits = [];\r\n this.currentHit = 0;\r\n this.findKey = null;\r\n this.lastFind = null;\r\n }\r\n\r\n /** Each page on screen keeps its HTML in its own shadow root. */\r\n private pageRoots(): ShadowRoot[] {\r\n const box = this.pagesBox()?.nativeElement;\r\n if (!box) return [];\r\n return Array.from(box.querySelectorAll('nxe-report-page'))\r\n .map((page) => page.shadowRoot)\r\n .filter((root): root is ShadowRoot => root !== null);\r\n }\r\n\r\n private requestAllPages(): void {\r\n if (this.viewMode() === 'SinglePage') return;\r\n for (let index = 0; index < this.session.pageCount(); index++) this.session.requestPage(index);\r\n }\r\n\r\n /**\r\n * Scrolls the current hit to its own height plus 50 px below the top of the report panel, over\r\n * 350 ms: always after a fresh search, and after a step only when the hit is out of view. That is\r\n * what Stimulsoft's viewer was seen to do; the exact place it scrolls to also carries offsets of its\r\n * own page markup, which this viewer's pages do not have.\r\n */\r\n private revealHit(always: boolean): void {\r\n const box = this.pagesBox()?.nativeElement;\r\n const hit = this.hits[this.currentHit];\r\n if (!box || !hit) return;\r\n const panel = box.getBoundingClientRect();\r\n const target = hit.getBoundingClientRect();\r\n if (!always && target.top >= panel.top && target.bottom <= panel.bottom) return;\r\n const to = box.scrollTop + target.top - panel.top - (target.height + FIND_SCROLL_GAP);\r\n this.animateScroll(box, Math.max(0, to));\r\n }\r\n\r\n /**\r\n * A change to any input reloads, as Stimulsoft's viewer does: its `ngOnChanges` never looks at\r\n * which input changed, so even a width change asks the server for the options and the report\r\n * again. Matching that keeps a host's reload behaviour the same across the swap.\r\n */\r\n ngOnChanges(): void {\r\n this.session.open(this.context(), this.action());\r\n }\r\n\r\n /**\r\n * Page navigation. In a mode that scrolls through the whole report the page is reached by scrolling\r\n * to it, over 350 ms, which is what Stimulsoft's navigation actions do; in `SinglePage` the page is\r\n * simply the one shown.\r\n */\r\n protected navigateTo(index: number): void {\r\n this.session.goToPage(index);\r\n if (this.viewMode() === 'SinglePage') return;\r\n this.scrollToPage(index);\r\n }\r\n\r\n /** The page number is kept and nothing scrolls, as Stimulsoft's view-mode actions leave it. */\r\n protected setViewMode(mode: NxeViewMode): void {\r\n this.viewMode.set(mode);\r\n this.afterPagesSettle();\r\n }\r\n\r\n /** Nothing preserves the scroll offset across a zoom change, so the visible region shifts. */\r\n protected setZoom(zoom: number): void {\r\n this.zoom.set(zoom);\r\n this.afterPagesSettle();\r\n }\r\n\r\n /**\r\n * Fit a whole page, or a page's width, in the panel. Stimulsoft computes this once from what is on\r\n * screen and stores the number as the zoom; no fit mode is remembered, so a later resize does not\r\n * re-fit. The 40 px it subtracts is the panel's padding and the page's margins.\r\n */\r\n protected fitTo(what: 'page' | 'width'): void {\r\n const box = this.pagesBox()?.nativeElement;\r\n const page = box?.querySelector('nxe-report-page');\r\n if (!box || !(page instanceof HTMLElement)) return;\r\n const available = what === 'width' ? box.clientWidth - 40 : box.clientHeight - 40;\r\n const drawn = what === 'width' ? page.offsetWidth : page.offsetHeight;\r\n if (drawn <= 0 || available <= 0) return;\r\n this.zoom.set((available * this.zoom()) / drawn);\r\n this.afterPagesSettle();\r\n }\r\n\r\n /**\r\n * Scrolling asks for the pages that have come into view, and, once it has stopped for 300 ms, moves\r\n * the page the toolbar reports to the first one still on screen — Stimulsoft's scroll tracking.\r\n */\r\n protected onScroll(): void {\r\n this.requestVisiblePages();\r\n if (this.scrollSettled !== null) clearTimeout(this.scrollSettled);\r\n this.scrollSettled = setTimeout(() => {\r\n this.scrollSettled = null;\r\n if (!this.scrollingToPage) this.trackCurrentPage();\r\n }, SCROLL_SETTLE_MS);\r\n }\r\n\r\n /** The room on screen changed, so the viewer measures itself against it again. */\r\n protected onWindowResize(): void {\r\n this.fitToAvailableRoom();\r\n }\r\n\r\n /** Lets the new layout reach the DOM, then fits the viewer to it and asks for what is on screen. */\r\n private afterPagesSettle(): void {\r\n requestAnimationFrame(() => {\r\n this.fitToAvailableRoom();\r\n this.requestVisiblePages();\r\n });\r\n }\r\n\r\n /**\r\n * Takes the room between the viewer's top and the bottom of the window when the height the host\r\n * asked for did not resolve, so the panel inside scrolls rather than the page. Measured before the\r\n * height is applied, and again only when the window changes, so it never chases its own answer.\r\n */\r\n private fitToAvailableRoom(): void {\r\n const root = this.rootBox()?.nativeElement;\r\n if (!root || !this.appearance()?.scrollbarsMode) return;\r\n const rect = root.getBoundingClientRect();\r\n // A height that resolved is left alone, as Stimulsoft leaves it, even when it ends at the very\r\n // bottom of the window; one that grew past the window's bottom is taken over.\r\n if (this.measuredHeight() === null && rect.bottom <= window.innerHeight + 1) return;\r\n const room = Math.max(MIN_PANEL_HEIGHT, Math.round(window.innerHeight - rect.top - VIEWER_BOTTOM_GAP));\r\n this.measuredHeight.set(`${room}px`);\r\n }\r\n\r\n /** Every page whose box meets the panel, plus one either side, so scrolling stays ahead of the eye. */\r\n private requestVisiblePages(): void {\r\n if (this.viewMode() === 'SinglePage') return;\r\n const box = this.pagesBox()?.nativeElement;\r\n if (!box) return;\r\n const pages = box.querySelectorAll('nxe-report-page');\r\n const top = box.scrollTop - box.clientHeight;\r\n const bottom = box.scrollTop + box.clientHeight * 2;\r\n pages.forEach((element, index) => {\r\n if (!(element instanceof HTMLElement)) return;\r\n const pageTop = element.offsetTop - box.offsetTop;\r\n if (pageTop + element.offsetHeight >= top && pageTop <= bottom) this.session.requestPage(index);\r\n });\r\n }\r\n\r\n /** The first page whose bottom is still below the panel's scroll offset. */\r\n private trackCurrentPage(): void {\r\n const box = this.pagesBox()?.nativeElement;\r\n if (!box) return;\r\n const pages = box.querySelectorAll('nxe-report-page');\r\n for (let index = 0; index < pages.length; index++) {\r\n const element = pages[index];\r\n if (!(element instanceof HTMLElement)) continue;\r\n const pageTop = element.offsetTop - box.offsetTop;\r\n if (pageTop + element.offsetHeight > box.scrollTop) {\r\n this.session.markCurrentPage(index);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n /** Stimulsoft animates the panel to the page's top over 350 ms, in steps of about 30 ms. */\r\n private scrollToPage(index: number): void {\r\n const box = this.pagesBox()?.nativeElement;\r\n const element = box?.querySelectorAll('nxe-report-page')[index];\r\n if (!box || !(element instanceof HTMLElement)) return;\r\n this.animateScroll(box, element.offsetTop - box.offsetTop);\r\n }\r\n\r\n /** Scrolls the report panel over 350 ms in steps of about 30 ms, as Stimulsoft's scrolls all run. */\r\n private animateScroll(box: HTMLElement, to: number): void {\r\n const from = box.scrollTop;\r\n const started = performance.now();\r\n this.scrollingToPage = true;\r\n const step = (): void => {\r\n const done = Math.min(1, (performance.now() - started) / SCROLL_ANIMATION_MS);\r\n box.scrollTop = from + (to - from) * done;\r\n if (done < 1) {\r\n setTimeout(step, SCROLL_STEP_MS);\r\n return;\r\n }\r\n this.scrollingToPage = false;\r\n this.requestVisiblePages();\r\n };\r\n step();\r\n }\r\n\r\n /**\r\n * The getters read the session's signals, so a host that asks between renders gets what is on\r\n * screen now. Built from a captured session rather than `this`, because `this` inside an object\r\n * literal's accessor is the literal.\r\n */\r\n private buildApi(): NxeViewerApi {\r\n const session = this.session;\r\n return {\r\n get currentPage(): number {\r\n return session.pageIndex();\r\n },\r\n set currentPage(value: number) {\r\n session.goToPage(value);\r\n },\r\n get pagesCount(): number {\r\n return session.pageCount();\r\n },\r\n get reportType(): string {\r\n return 'Report';\r\n },\r\n };\r\n }\r\n\r\n private context(): NxeRequestContext {\r\n return {\r\n requestUrl: this.requestUrl(),\r\n properties: this.properties(),\r\n postParametersFunction: this.postParametersFunction(),\r\n strings: NXE_ENGLISH,\r\n };\r\n }\r\n}\r\n","/*\r\n * Public API Surface of @nexterajs/report-viewer\r\n */\r\n\r\nexport { NXE_VIEWER_PROTOCOL } from './lib/protocol/nxe-protocol.const';\r\nexport {\r\n NxeReportViewerComponent,\r\n type NxeViewerApi,\r\n} from './lib/viewer/nxe-report-viewer.component';\r\nexport type { NxeViewerFailure } from './lib/protocol/nxe-protocol.model';\r\nexport type {\r\n NxePostParametersData,\r\n NxePostParametersFunction,\r\n} from './lib/protocol/nxe-viewer-client.service';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|